Domanda

Sto cercando di capire una routine fft (Fast Fourier Transform) che sto usando (rubando) (riciclando)

L'input è un array di 512 punti dati che sono una forma d'onda di esempio. I dati di test vengono generati in questo array. fft trasforma questo array in dominio di frequenza. Cercare di comprendere la relazione tra frequenza, periodo, frequenza di campionamento e posizione nell'array fft. Illustrerò con esempi:

========================================

La frequenza di campionamento è di 1000 campioni / s. Genera una serie di campioni a 10Hz.

L'array di input ha valori di picco su arr (28), arr (128), arr (228) ... periodo = 100 punti campione

il valore di picco nell'array fft è all'indice 6 (escluso un valore enorme a 0)

========================================

La frequenza di campionamento è di 8000 campioni / s Genera serie di campioni a 440Hz

I valori di picco dell'array di input includono arr (7), arr (25), arr (43), arr (61) ... periodo = 18 punti campione

il valore di picco nell'array fft è all'indice 29 (escluso un valore enorme a 0)

========================================

Come posso mettere in relazione l'indice del picco nell'array fft con la frequenza?

È stato utile?

Soluzione

Se si ignora la parte immaginaria, la distribuzione della frequenza è lineare tra i bin:

Frequenza @ i = (frequenza di campionamento / 2) * (i / Nbins).

Quindi, per il tuo primo esempio, supponendo che tu avessi 256 bin, il bidone più grande corrisponde ad una frequenza di 1000/2 * 6/256 = 11,7 Hz. Dato che il tuo input era 10Hz, immagino che anche il bin 5 (9,7Hz) avesse un grande componente. Per ottenere una maggiore precisione, è necessario prelevare più campioni, per ottenere contenitori più piccoli.

Il tuo secondo esempio fornisce 8000/2 * 29/256 = 453Hz. Ancora una volta, vicino, ma hai bisogno di più cassonetti. La tua risoluzione qui è solo 4000/256 = 15.6Hz.

Altri suggerimenti

Sarebbe utile se dovessi fornire il tuo set di dati di esempio.

La mia ipotesi sarebbe che tu abbia quelli che sono chiamati artefatti di campionamento. Il segnale forte a DC (frequenza 0) suggerisce che questo è il caso.

Devi sempre assicurarti che il valore medio nei tuoi dati di input sia zero: trova la media e sottrala da ciascun punto di campionamento prima di invocare la fft è una buona pratica.

Sulla stessa linea, devi stare attento al manufatto della finestra di campionamento. È importante che il primo e l'ultimo punto dati siano vicini allo zero perché altrimenti il ??"passaggio" dall'esterno all'interno della finestra di campionamento ha l'effetto di iniettare molta energia a frequenze diverse.

La linea di fondo è che fare un'analisi fft richiede più cura che semplicemente riciclare una routine fft trovata da qualche parte.

Ecco i primi 100 punti di campionamento di un segnale a 10Hz come descritto nella domanda, massaggiati per evitare artefatti di campionamento

> sinx[1:100]
  [1]  0.000000e+00  6.279052e-02  1.253332e-01  1.873813e-01  2.486899e-01  3.090170e-01  3.681246e-01  4.257793e-01  4.817537e-01  5.358268e-01
 [11]  5.877853e-01  6.374240e-01  6.845471e-01  7.289686e-01  7.705132e-01  8.090170e-01  8.443279e-01  8.763067e-01  9.048271e-01  9.297765e-01
 [21]  9.510565e-01  9.685832e-01  9.822873e-01  9.921147e-01  9.980267e-01  1.000000e+00  9.980267e-01  9.921147e-01  9.822873e-01  9.685832e-01
 [31]  9.510565e-01  9.297765e-01  9.048271e-01  8.763067e-01  8.443279e-01  8.090170e-01  7.705132e-01  7.289686e-01  6.845471e-01  6.374240e-01
 [41]  5.877853e-01  5.358268e-01  4.817537e-01  4.257793e-01  3.681246e-01  3.090170e-01  2.486899e-01  1.873813e-01  1.253332e-01  6.279052e-02
 [51] -2.542075e-15 -6.279052e-02 -1.253332e-01 -1.873813e-01 -2.486899e-01 -3.090170e-01 -3.681246e-01 -4.257793e-01 -4.817537e-01 -5.358268e-01
 [61] -5.877853e-01 -6.374240e-01 -6.845471e-01 -7.289686e-01 -7.705132e-01 -8.090170e-01 -8.443279e-01 -8.763067e-01 -9.048271e-01 -9.297765e-01
 [71] -9.510565e-01 -9.685832e-01 -9.822873e-01 -9.921147e-01 -9.980267e-01 -1.000000e+00 -9.980267e-01 -9.921147e-01 -9.822873e-01 -9.685832e-01
 [81] -9.510565e-01 -9.297765e-01 -9.048271e-01 -8.763067e-01 -8.443279e-01 -8.090170e-01 -7.705132e-01 -7.289686e-01 -6.845471e-01 -6.374240e-01
 [91] -5.877853e-01 -5.358268e-01 -4.817537e-01 -4.257793e-01 -3.681246e-01 -3.090170e-01 -2.486899e-01 -1.873813e-01 -1.253332e-01 -6.279052e-02

Ed ecco i valori assoluti risultanti del dominio della frequenza fft

 [1] 7.160038e-13 1.008741e-01 2.080408e-01 3.291725e-01 4.753899e-01 6.653660e-01 9.352601e-01 1.368212e+00 2.211653e+00 4.691243e+00 5.001674e+02
[12] 5.293086e+00 2.742218e+00 1.891330e+00 1.462830e+00 1.203175e+00 1.028079e+00 9.014559e-01 8.052577e-01 7.294489e-01

Sono un po 'arrugginito anche in matematica e elaborazione del segnale ma con le informazioni aggiuntive posso dare una possibilità.

Se si desidera conoscere l'energia del segnale per contenitore, è necessario l'entità dell'uscita complessa. Quindi, solo guardare l'output reale non è abbastanza. Anche quando l'ingresso è solo numeri reali. Per ogni cestino la grandezza dell'output è sqrt (real ^ 2 + imag ^ 2), proprio come pitagora :-)

I

bin da 0 a 449 sono frequenze positive da 0 Hz a 500 Hz. i bin da 500 a 1000 sono frequenze negative e dovrebbero essere uguali a quelli positivi per un segnale reale. Se elaborate un buffer ogni secondo le frequenze e gli indici di array si allineano correttamente. Quindi il picco all'indice 6 corrisponde a 6Hz, quindi è un po 'strano. Ciò potrebbe essere dovuto al fatto che stai solo guardando i dati di output reali e i dati reali e immaginari si combinano per dare un picco atteso all'indice 10. Le frequenze dovrebbero essere mappate linearmente ai bin.

I picchi su 0 indicano un offset DC.

È da un po 'di tempo che non faccio FFT ma ecco cosa ricordo

FFT di solito accetta numeri complessi come input e output. Quindi non sono davvero sicuro di come la parte reale e immaginaria dell'input e dell'output sia mappata sugli array.

Non capisco davvero cosa stai facendo. Nel primo esempio dici di elaborare buffer di campionamento a 10Hz per una frequenza di campionamento di 1000 Hz? Quindi dovresti avere 10 buffer al secondo con 100 campioni ciascuno. Non capisco come il tuo array di input può essere lungo almeno 228 campioni.

Di solito la prima metà del buffer di output sono bin di frequenza da 0 frequenza (= offset cc) a 1/2 frequenza di campionamento. e la seconda metà sono frequenze negative. se il tuo input è solo dati reali con 0 per il segnale immaginario, le frequenze positive e negative sono uguali. La relazione del segnale reale / immaginario sull'uscita contiene informazioni sulla fase dal segnale di ingresso.

La frequenza per bin i è i * (samplerate / n), dove n è il numero di campioni nella finestra di input della FFT.

Se stai gestendo l'audio, poiché l'intonazione è proporzionale al registro della frequenza, la risoluzione dell'intonazione dei bin aumenta al pari della frequenza: è difficile risolvere con precisione i segnali a bassa frequenza. Per fare ciò è necessario utilizzare finestre FFT più grandi, che riducono la risoluzione temporale. Esiste un compromesso di frequenza con la risoluzione temporale per una determinata frequenza di campionamento.

Menzionate un bidone con un valore grande a 0 - questo è il bidone con frequenza 0, cioè il componente DC. Se questo è grande, presumibilmente i tuoi valori sono generalmente positivi. Bin n / 2 (nel tuo caso 256) è la frequenza di Nyquist, metà della frequenza di campionamento, che è la frequenza più alta che può essere risolta nel segnale campionato a questa frequenza.

Se il segnale è reale, i bin da n / 2 + 1 a n-1 conterranno rispettivamente i coniugati complessi dei bin da n / 2-1 a 1. Il valore DC appare solo una volta.

I campioni sono, come altri hanno già detto, equidistanti nel dominio della frequenza (non logaritmico).

Ad esempio 1, dovresti ottenere questo:

alt text http://home.comcast.net/~kootsoop/images /SINE1.jpg

Per l'altro esempio dovresti ottenere

alt text http://home.comcast.net/~kootsoop/images /SINE2.jpg

Quindi le tue risposte sembrano entrambe corrette riguardo alla posizione di picco.

Quello che non sto ottenendo è il grande componente DC. Sei sicuro di generare un'onda sinusoidale come input? L'ingresso diventa negativo? Per un'onda sinusoidale, la DC dovrebbe essere vicina allo zero a condizione che tu abbia abbastanza cicli.

Un'altra strada è creare un Algoritmo di Goertzel di ogni frequenza del centro note che stai cercando .

Una volta che un'implementazione dell'algoritmo funziona, puoi renderla tale che siano necessari parametri per impostare la frequenza centrale. Con ciò potresti facilmente eseguirne 88 o qualsiasi cosa ti serva in una raccolta e scansionare per il valore di picco.

L'algoritmo di Goertzel è fondamentalmente un singolo bin FFT. Usando questo metodo puoi posizionare i tuoi contenitori logaritmicamente come vanno naturalmente le note musicali.

Alcuni pseudo codici da Wikipedia:

s_prev = 0
s_prev2 = 0
coeff = 2*cos(2*PI*normalized_frequency);
for each sample, x[n],
  s = x[n] + coeff*s_prev - s_prev2;
  s_prev2 = s_prev;
  s_prev = s;
end
power = s_prev2*s_prev2 + s_prev*s_prev - coeff*s_prev2*s_prev;

Le due variabili che rappresentano i due campioni precedenti vengono mantenute per la successiva iterazione. Questo può essere quindi utilizzato in un'applicazione di streaming. Penso che forse anche il calcolo della potenza dovrebbe essere all'interno del loop. (Tuttavia non è raffigurato come tale nell'articolo Wiki.)

Nel caso del rilevamento del tono ci sarebbero 88 diversi coefficienti, 88 coppie di campioni precedenti e risulterebbe in 88 campioni di potenza in uscita che indicano il livello relativo in quel bin di frequenza.

WaveyDavey dice che sta catturando il suono da un microfono, attraverso l'hardware audio del suo computer, MA che i suoi risultati non sono centrati sullo zero. Sembra un problema con l'hardware. DOVREBBE ESSERE centrato sullo zero.

Quando la stanza è silenziosa, il flusso di valori proveniente dall'API del suono dovrebbe essere molto vicino all'ampiezza 0, con lievi + - variazioni per il rumore ambientale. Se nella stanza è presente un suono vibratorio (ad esempio un piano, un flauto, una voce), il flusso di dati dovrebbe mostrare un'onda fondamentalmente sinusoidale che va sia positiva che negativa e che si avvicina alla media vicino allo zero. In caso contrario, il sistema ha qualche funk in corso!

-Rick

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top