È ragionevolmente facile. È necessario eseguire una FFT e quindi riassumere i contenitori che ti interessano. Molto del modo in cui sceglierai dipenderà dalla frequenza di campionamento del tuo audio.
È quindi necessario scegliere un ordine FFT appropriato per ottenere una buona informazione nei bin di frequenza restituiti.
Quindi, se si esegue un ordine 8 FFT, sono necessari 256 campioni. Questo ti restituirà 128 coppie complesse.
Quindi è necessario convertirli in grandezza. Questo è in realtà abbastanza semplice. se stai usando std :: complex puoi semplicemente eseguire uno std :: abs sul numero complesso e avrai la sua grandezza (sqrt (r^2 + i^2)).
È interessante notare che a questo punto c'è qualcosa chiamato Parseval's theorem. Questo teorema afferma che dopo aver eseguito una trasformazione di Fourier la somma dei bin restituiti è uguale alla somma dei quadrati medi del segnale di ingresso.
Ciò significa che per ottenere l'ampiezza di un set specifico di contenitori è sufficiente aggiungerli insieme dividere per il numero di essi e quindi sqrt per ottenere il valore di ampiezza RMS di tali bin.
Quindi, dove ti lascia?
Bene da qui è necessario capire quali bin si stanno sommando.
- Un tono di acuto è definito come superiore a 2000Hz.
- Un tono basso è inferiore a 300 Hz (se la memoria mi serve correttamente).
- I medi sono compresi tra 300Hz e 2kHz.
Supponiamo ora che la frequenza di campionamento sia 8 kHz. Il Nyquist rate dice che la frequenza più alta che puoi rappresentare nel campionamento a 8kHz è 4kHz. Ogni bin rappresenta quindi 4000/128 o 31.25Hz.
Quindi, se i primi 10 scomparti (fino a 312,5 Hz) vengono utilizzati per le frequenze dei bassi. Il contenitore da 10 a il contenitore 63 rappresentano i medi. Infine bin da 64 a 127 sono le alte.
È quindi possibile calcolare il valore RMS come descritto sopra e si dispone dei valori RMS.
I valori RMS possono essere convertiti in valori dBFS eseguendo 20.0f * log10f(rmsVal);
. Questo ti restituirà un valore da 0 dB (ampiezza massima) fino a -infinity dB (ampiezza minima). Essere consapevoli ampiezze non vanno da -1 a 1.
Per aiutarvi a lungo, ecco un po 'della mia C++ basato classe FFT per iPhone (che utilizza VDSP sotto il cofano):
MacOSFFT::MacOSFFT(unsigned int fftOrder) :
BaseFFT(fftOrder)
{
mFFTSetup = (void*)vDSP_create_fftsetup(mFFTOrder, 0);
mImagBuffer.resize(1 << mFFTOrder);
mRealBufferOut.resize(1 << mFFTOrder);
mImagBufferOut.resize(1 << mFFTOrder);
}
MacOSFFT::~MacOSFFT()
{
vDSP_destroy_fftsetup((FFTSetup)mFFTSetup);
}
bool MacOSFFT::ForwardFFT(std::vector< std::complex<float> >& outVec, const std::vector<float>& inVec)
{
return ForwardFFT(&outVec.front(), &inVec.front(), inVec.size());
}
bool MacOSFFT::ForwardFFT(std::complex<float>* pOut, const float* pIn, unsigned int num)
{
// Bring in a pre-allocated imaginary buffer that is initialised to 0.
DSPSplitComplex dspscIn;
dspscIn.realp = (float*)pIn;
dspscIn.imagp = &mImagBuffer.front();
DSPSplitComplex dspscOut;
dspscOut.realp = &mRealBufferOut.front();
dspscOut.imagp = &mImagBufferOut.front();
vDSP_fft_zop((FFTSetup)mFFTSetup, &dspscIn, 1, &dspscOut, 1, mFFTOrder, kFFTDirection_Forward);
vDSP_ztoc(&dspscOut, 1, (DSPComplex*)pOut, 1, num);
return true;
}
Vedere la risposta accettata a questa domanda: http://stackoverflow.com/questions/1794010/how-to-use-numpy-with-portaudio-to-extract-bass-mid-treble?rq=1 –
ok questo spiega la procedura, ma non come eseguire quella procedura su iOS - o almeno da dove iniziare. –
iOS ha filtri passa basso e passa alto integrati nel framework dell'unità audio. –