2013-03-16 21 views
9

Sto cercando un modo per ottenere i dati di alti e bassi da una canzone per un certo incremento di tempo (ad esempio 0,1 secondi) e nell'intervallo da 0,0 a 1,0. Ho cercato su Google, ma non sono stato in grado di trovare nulla di lontanamente vicino a quello che sto cercando. In definitiva, voglio essere in grado di rappresentare il livello degli alti e dei bassi mentre la canzone è in riproduzione.Estrai acuti e bassi da audio in iOS

Grazie!

+0

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 –

+0

ok questo spiega la procedura, ma non come eseguire quella procedura su iOS - o almeno da dove iniziare. –

+0

iOS ha filtri passa basso e passa alto integrati nel framework dell'unità audio. –

risposta

10

È 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.

  1. Un tono di acuto è definito come superiore a 2000Hz.
  2. Un tono basso è inferiore a 300 Hz (se la memoria mi serve correttamente).
  3. 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; 
} 
5

Sembra che stiate cercando il codice di esempio Fast Fourier Transform.

È un argomento abbastanza ampio da coprire in una risposta.

Gli strumenti necessari sono già costruire in iOS: VDSP API

Questo dovrebbe aiutare a: vDSP Programming Guide

E c'è anche un FFT Sample Code disponibili

Si potrebbe anche voler controllare iPhoneFFT . Anche se quel codice è leggermente aggiornato, , può aiutarti a capire i processi "sotto il cofano".

3

Suggerire per esempio da auriotouch2 di Apple - ha tutto dall'analisi della frequenza alla rappresentazione dell'interfaccia utente di ciò che si desidera.