Ottenere i picchi di FFT dai dati

Sto sviluppando un sistema di riconoscimento vocale da zero utilizzando Octave. Sto cercando di rilevare i fonemi rilevando le differenze di frequenza. Attualmente ho letto in un file wav, organizzato i valori in blocchi e applicato fft ai dati globali. Dopo, ho tracciato i nuovi dati con la plot(abs(real(fft(q)))) che crea questo grafico: grafico di fft

Come posso ottenere i valori di frequenza (i picchi del grafico)?

Se non hai accesso a findpeaks , la premessa di base su come funziona è che per ogni punto del segnale, cerca una finestra di tre elementi centrata in questo punto e controlla se il centro di questa finestra è più grande rispetto all’elemento sinistro e destro di questa finestra. Vuoi essere in grado di trovare picchi sia positivi che negativi, quindi dovresti controllare il valore assoluto.

In questo modo, ciò che puoi fare è creare due segnali aggiuntivi che spostano il segnale verso sinistra di 1 e verso destra di 1. Quando eseguiremo questo, controlleremo effettivamente i picchi a partire dal secondo elemento del segnale, in per fare spazio a guardare a sinistra. Continuiamo a controllare fino al penultimo elemento , per fare spazio a guardare a destra. Pertanto, controlleremo effettivamente i picchi su una versione N - 2 del segnale dove N è la lunghezza del segnale. Pertanto, quando creiamo il segnale spostato a sinistra, estraiamo il primo elemento del segnale fino al terzo elemento finale . Quando creiamo il giusto segnale spostato, estraiamo dal terzo elemento fino all’ultimo elemento. Il segnale originale avrà semplicemente il suo primo e ultimo elemento rimosso.

Pertanto, controllando i picchi in questo modo, perderemo il primo e l’ultimo punto dei dati, ma ciò dovrebbe essere adatto in quanto molto probabilmente non ci saranno picchi all’inizio e alla fine. Dopo aver creato tutti questi segnali, utilizzare semplicemente l’indicizzazione logica per vedere se i valori corrispondenti nel segnale originale (senza il primo e l’ultimo elemento) sono maggiori degli altri due segnali nelle rispettive posizioni corrispondenti.

Pertanto, supponendo che il segnale sia stato memorizzato in f , procedere come segue:

 f1 = abs(f(2:end-1)); %// Original signal f2 = abs(f(1:end-2)); %// Left shift f3 = abs(f(3:end)); %// Right shift idx = find(f1 > f2 & f1 > f3) + 1; %// Get the locations of where we find our peaks 

idx conterrà le posizioni dell’indice di dove si verificano i picchi. Tieni presente che abbiamo iniziato a cercare i picchi nella seconda posizione, quindi devi aggiungere 1 per tenere conto di questo spostamento. Se si desidera trovare i valori di tempo effettivo (o frequenza nel proprio caso), si utilizzerà semplicemente idx per indicizzare l’array di tempo (o frequenza) utilizzato per generare il segnale e individuarli. Come tale, usiamo un caso artificiale in cui io generi una sinusoide da 0 a 3 secondi con una frequenza di 1 Hz. Perciò:

 t = 0 : 0.01 : 3; f = sin(2*pi*t); 

Ora, se eseguissimo il codice sopra con questo segnale, troveremmo la posizione delle nostre vette. Possiamo quindi utilizzare queste posizioni per indicizzare in t e f e tracciare il segnale, nonché dove abbiamo rilevato i nostri picchi. Perciò:

 plot(t, f, t(idx), f(idx), 'r.') 

Questo è quello che ottengo:

inserisci la descrizione dell'immagine qui

Tieni presente che questo è un modo molto semplice per rilevare i picchi, ma questo è ciò che viene essenzialmente fatto in findpeaks . Se hai usato il codice sopra, fondamentalmente troverai tutti i picchi . In quanto tale, il codice troverà dozzine di picchi nel grafico sopra, perché ci sono massimi locali su tutto il tuo spettro. Probabilmente vuoi determinare dove si trovano i picchi forti . Quello che le persone di solito fanno è usare una soglia per indicare quanto dovrebbe essere grande il picco prima di decidere se si tratta di un picco valido. In quanto tale, puoi applicare una soglia e fare qualcosa del genere:

 thresh = ... ; %// Define threshold here idx = find(f1 > f2 & f1 > f3 & f1 > thresh) + 1; %// Get the locations of where we find our peaks 

Nel tuo caso per il tuo grafico, potresti voler impostare questo in modo da trovare eventuali picchi la cui magnitudine sia maggiore di 10 forse.


Ci sono molte altre cose che fa findpeaks , come filtrare picchi rumorosi e altre misure robuste. Se si desidera utilizzare findpeaks , è necessario assicurarsi di installare il pacchetto di segnali. Puoi semplicemente usare pkg install dal Prompt dei comandi di Octave e installare il pacchetto di signal . In particolare, prova questo:

 pkg install -forge signal 

Una volta installato il pacchetto di signal , è ansible caricarlo nell’ambiente Octave facendo:

 pkg load signal 

Se devi installare le dipendenze, ti dirà quando proverai a installare il pacchetto del signal . Dai un’occhiata a questo link per maggiori dettagli: https://www.gnu.org/software/octave/doc/interpreter/Installing-and-Removing-Packages.html

mkoctfile è mkoctfile di creazione / compilazione di un file Octave. Se non hai mkoctfile , assicurati di avere la versione più recente di Octave installata. Quello che ti consiglio di fare per semplificare le cose è installare Homebrew o MacPorts e ottenere Octave in questo modo. Una volta installato, dovresti riuscire a far funzionare mkoctfile . Tuttavia, se ancora non è ansible, potrebbe essere necessario installare un compilatore compatibile. L’approccio semplice consiste nell’installare gli strumenti di sviluppo della riga di comando da Xcode. Vai a questo link quindi vai a Strumenti aggiuntivi.

In bocca al lupo!

Puoi utilizzare la funzione findpeaks dal pacchetto del segnale di ottava:

http://octave.sourceforge.net/signal/function/findpeaks.html