7

ho implementato il progetto di Demetri Pitch Detector per l'iPhone e che colpiscono contro due problemi. 1) qualsiasi tipo di rumore di fondo invia le banane di lettura della frequenza e 2) i suoni di frequenza inferiore non vengono inseriti correttamente. Ho cercato di accordare la mia chitarra e mentre le corde più alte hanno lavorato - il sintonizzatore non riuscivo a scorgere correttamente il basso E.FFT su iPhone di ignorare il rumore di fondo e trovare piazzole inferiori

codice

Il Pitch Detection si trova in RIOInterface.mm e va qualcosa di simile ...

// get the data 
AudioUnitRender(...); 

// convert int16 to float 
Convert(...); 

// divide the signal into even-odd configuration 
vDSP_ctoz((COMPLEX*)outputBuffer, 2, &A, 1, nOver2); 

// apply the fft 
vDSP_fft_zrip(fftSetup, &A, stride, log2n, FFT_FORWARD); 

// convert split real form to split vector 
vDSP_ztoc(&A, 1, (COMPLEX *)outputBuffer, 2, nOver2); 

Demetri passa poi a determinare la frequenza 'dominante' come segue:

float dominantFrequency = 0; 
int bin = -1; 
for (int i=0; i<n; i+=2) { 
    float curFreq = MagnitudeSquared(outputBuffer[i], outputBuffer[i+1]); 
    if (curFreq > dominantFrequency) { 
     dominantFrequency = curFreq; 
     bin = (i+1)/2; 
    } 
} 
memset(outputBuffer, 0, n*sizeof(SInt16)); 

// Update the UI with our newly acquired frequency value. 
[THIS->listener frequencyChangedWithValue:bin*(THIS->sampleRate/bufferCapacity)]; 

per cominciare, credo che ho bisogno di applicare un filtro passa-basso ... ma io non sono un esperto e non FFT sicuro esattamente dove o come farlo rispetto ai dati restituiti dalla funzione vDSP S. Inoltre, non sono sicuro di come migliorare la precisione del codice nelle frequenze più basse. Sembra che ci siano altri algoritmi per determinare la frequenza dominante, ma ancora una volta, cercando un calcio nella giusta direzione quando si utilizzano i dati restituiti dal framework Accelerate di Apple.

UPDATE:

Il accelerare quadro in realtà ha alcune funzioni a finestre. ha installato una finestra di base come questa

windowSize = maxFrames; 
transferBuffer = (float*)malloc(sizeof(float)*windowSize); 
window = (float*)malloc(sizeof(float)*windowSize); 
memset(window, 0, sizeof(float)*windowSize); 
vDSP_hann_window(window, windowSize, vDSP_HANN_NORM); 

che poi applico inserendo

vDSP_vmul(outputBuffer, 1, window, 1, transferBuffer, 1, windowSize); 

prima della funzione vDSP_ctoz. Poi cambio il resto del codice per usare "transferBuffer" invece di outputBuffer ... ma finora non ho notato alcun cambiamento drammatico nell'ipotesi finale.

+0

due cose che ricordo di aver giocato con questa roba qualche anno fa: è possibile impostare un livello di squelch per il suono di sottofondo semplicemente sottraendo i dati di input non elaborati da una quantità predeterminata (che si può immaginare per ora, finché non si calcola un buon algoritmo), impostando qualsiasi cosa che va sotto 0 a 0. e frequenze più basse, per qualche motivo non ricordo, non si registra tanto forte quanto più alto, quindi è necessario aumentare i volumi a bassa frequenza in modo esponenziale prima di confrontare a una frequenza dominante più alta. –

+0

Sembra che non si stia applicando una funzione finestra adeguata prima della FFT, quindi ci saranno molti artefatti nello spettro di potenza che probabilmente rovinerebbero qualsiasi tipo di tentativo di rilevamento del pitch. –

+2

Ecco una domanda quasi duplicata con una risposta simile: http://stackoverflow.com/questions/4227420/matlab-missing-fundamental-from-an-fft – hotpaw2

risposta

7

Pitch non è lo stesso di bin frequenza di picco magnitudo (che è ciò che la FFT nel quadro Accelerate potrebbe dare direttamente). Quindi qualsiasi rilevatore di frequenza di picco non sarà affidabile per la stima del passo. Un filtro passa-basso non è d'aiuto quando la nota ha un fondamentale mancante o molto debole (comune in alcuni suoni di voce, piano e chitarra) e/o un sacco di forti sfumature nel suo spettro.

Guardate uno spettro a larga banda o spettrografo dei vostri suoni musicali e vedrete il problema.

In genere sono necessari altri metodi per una stima più affidabile del pitch musicale. Alcuni di questi includono metodi di autocorrelazione (AMDF, ASDF), analisi Cepstrum/Cepstral, spettro di prodotti armonici, vocoder di fase e/o algoritmi compositi come RAPT (Robust Algorithm for Pitch Tracking) e YAAPT. Una FFT è utile solo come una parte secondaria di alcuni dei metodi precedenti.

+0

Grazie a @ hotpaw2. Dovrò approfondire alcune delle tecniche che elencherai qui. Grazie per i suggerimenti. –

+0

I riferimenti alle descrizioni di alcuni degli altri metodi di stima del passo sono sul mio blog: http://www.nicholson.com/rhn/dsp.html#1 – hotpaw2

3

Per lo meno è necessario applicare un window function ai dati nel dominio del tempo, prima di calcolare la FFT. Senza questo passo lo spettro di potenza conterrà artefatti (vedi: spectral leakage) che interferiranno con i tuoi tentativi di estrarre informazioni sul pitch.

Una semplice Hann (alias Hanning) dovrebbe essere sufficiente.

+2

Buona risposta e bella immagine avatar: D – jarryd

+0

Non posso davvero essere d'accordo con questo commento. È necessario applicare un filtro finestra _prima_ si campiona il segnale analogico. Una volta campionato (cioè, una volta registrato attraverso il microfono o come un modulo WAV), non è necessario filtrare nulla - a meno che non stia cercando un altro effetto –

+0

@ZeJibe: Penso che forse ti stai confondendo tra l'applicazione di un [ funzione finestra] (https://en.wikipedia.org/wiki/Window_function) e utilizzando un [filtro anti-aliasing] (https://en.wikipedia.org/wiki/Anti-aliasing_filter)? –

1

Qual è la frequenza e il blocco del campione? La bassa E è intorno agli 80 Hz, quindi è necessario assicurarsi che il blocco di acquisizione sia sufficientemente lungo da acquisire molti cicli a questa frequenza. Questo perché la Trasformata di Fourier divide lo spettro di frequenza in contenitori, ciascuno di diversi Hz di larghezza. Se si campiona a 44.1 kHz e un campione del dominio del tempo a 1024 punti, ad esempio, ciascun bin sarà 44100/1024 = 43,07 Hz di larghezza. Quindi una E bassa sarebbe nel secondo bidone. Per una serie di motivi (relativi alla dispersione spettrale e alla natura dei blocchi di tempo finiti), in pratica si dovrebbero considerare i primi 3 o 4 bin di dati in un risultato FFT con estremo sospetto.

Se si rilascia la frequenza di campionamento su 8 kHz, lo stesso blocco offre bin che sono 7.8125 Hz di larghezza. Ora la bassa E sarà nel 10 ° o 11 ° bin, che è molto meglio. Puoi anche usare un blocco più lungo.

E come Paul R points out, è necessario utilizzare una finestra per ridurre la perdita spettrale.

+0

Ho provato sia il 22050 che il 44100. Ho anche provato i blocchi di 1024, 2048 e 4096 in una sorta di buffer circolare che salva i dati di ogni callback fino a quando non ho una quantità "bloccata". Capisco l'idea che, dato un blocco fisso, una frequenza di campionamento più bassa mi darà bidoni leggermente più larghi e renderà leggermente più facile sentire il basso E.Sfortunatamente, quello che noto è che quando arriverò a circa 295 Hz, il sintonizzatore inizierà a leggere numeri come 883 e 901. Molto vicino ai multipli di 2 e 3 del tono reale. –

+0

Sto generando toni su un altro iPhone in cui mi sono seduto. Ho notato che mentre lo alzo ', e il mio seno dal suono puro inizia a suonare spigoloso, il sintonizzatore perde il valore corretto che stava visualizzando e inizia a vagare in altre frequenze --- non necessariamente multipli di 2 o 3 di il tono fondamentale che sto cercando. –

+0

Una dimensione di blocco più lunga è un buon inizio per uno qualsiasi degli stimatori di altezza, ma un picco di magnitudine FFT non funzionerà per nessun suono con una frequenza fondamentale mancante o debole (anche se con il rolloff del microfono). – hotpaw2

1

La funzione di risposta in frequenza di iPhone scende al di sotto di 100 - 200 Hz (vedere http://blog.faberacoustical.com/2009/ios/iphone/iphone-microphone-frequency-response-comparison/ per un esempio).

Se si sta tentando di rilevare la modalità fondamentale di una stringa di chitarra bassa, il microfono potrebbe agire come filtro e sopprimere la frequenza a cui si è interessati. Esistono un paio di opzioni se si è interessati all'utilizzo dei dati di fft puoi ottenere - puoi nascondere i dati nel dominio della frequenza attorno alla nota che stai cercando di rilevare in modo che tutto ciò che puoi vedere sia la prima modalità anche se è di magnitudine inferiore rispetto alle modalità più alte (cioè avere un interruttore per sintonizzare la prima stringa e metterlo in questa modalità).

Oppure puoi filtrare i dati del suono passa-basso - puoi farlo nel dominio del tempo o anche più facilmente dato che hai già dati sul dominio della frequenza, nel dominio della frequenza. Un filtro passa-basso nel dominio del tempo molto semplice consiste nel fare un filtro medio che si muove nel tempo. Un filtro passa-basso per un dominio di frequenza molto semplice consiste nel moltiplicare la grandezza del proprio fft di un vettore con 1 nella gamma delle basse frequenze e una rampa lineare (o addirittura una fase) nelle frequenze più alte.