web-dev-qa-db-fra.com

Comment obtenir la fréquence du résultat fft?

J'ai enregistré un tableau [1024] de données de mon micro sur mon Android, je l'ai transmis via une DFT vers l'avant 1D des données réelles (en définissant 1024 bits supplémentaires sur 0). J'ai enregistré le tableau dans un fichier texte, et répété cela 8 fois.

J'ai récupéré 16384 résultats. J'ai ouvert le fichier texte dans Excel et fait un graphique pour voir à quoi il ressemblait (x = index du tableau, y = taille du nombre renvoyé). Il y a des pointes massives (à la fois positives et négatives) de magnitude autour de 110, 232, et de petites pointes se poursuivant de cette façon jusqu'en 1817 et 1941 où les pointes redeviennent grandes, puis retombent.

Mon problème est que partout où je cherche de l'aide sur le sujet, il mentionne l'obtention des nombres réels et imaginaires, je n'ai qu'un tableau 1D, que j'ai récupéré de la méthode que j'ai utilisée de la classe de Piotr Wendykier:

DoubleFFT_1D.realForwardFull(audioDataArray); // from the library JTransforms.

Ma question est: que dois-je faire de ces données pour renvoyer une fréquence? Le son enregistré me faisait jouer un "A" sur la corde inférieure (5e frette) de ma guitare (à environ 440 Hz).

29
Ben Taliadoros

Les données complexes sont entrelacées, avec des composants réels aux indices pairs et des composants imaginaires aux indices impairs, c'est-à-dire que les composants réels sont à l'indice 2*i, les composants imaginaires sont à l'index 2*i+1.

Pour obtenir la magnitude du spectre à l'indice i, vous voulez:

re = fft[2*i];
im = fft[2*i+1];
magnitude[i] = sqrt(re*re+im*im);

Ensuite, vous pouvez tracer la magnitude [i] pour i = 0 à N/2 pour obtenir le spectre de puissance. Selon la nature de votre entrée audio, vous devriez voir un ou plusieurs pics dans le spectre.

Pour obtenir la fréquence approximative d'un pic donné, vous pouvez convertir l'index du pic comme suit:

freq = i * Fs / N;

où:

freq = frequency in Hz
i = index of peak
Fs = sample rate (e.g. 44100 Hz or whatever you are using)
N = size of FFT (e.g. 1024 in your case)

Remarque: si vous n'avez pas précédemment appliqué un fonction de fenêtre aux données d'entrée du domaine temporel, vous obtiendrez une certaine quantité de fuite spectrale et le spectre de puissance ressemblera plutôt "barbouillé".


Pour développer cela, voici un pseudo-code pour un exemple complet où nous prenons des données audio et identifions la fréquence du plus grand pic:

N = 1024          // size of FFT and sample window
Fs = 44100        // sample rate = 44.1 kHz
data[N]           // input PCM data buffer
fft[N * 2]        // FFT complex buffer (interleaved real/imag)
magnitude[N / 2]  // power spectrum

capture audio in data[] buffer
apply window function to data[]

// copy real input data to complex FFT buffer
for i = 0 to N - 1
  fft[2*i] = data[i]
  fft[2*i+1] = 0

perform in-place complex-to-complex FFT on fft[] buffer

// calculate power spectrum (magnitude) values from fft[]
for i = 0 to N / 2 - 1
  re = fft[2*i]
  im = fft[2*i+1]
  magnitude[i] = sqrt(re*re+im*im)

// find largest peak in power spectrum
max_magnitude = -INF
max_index = -1
for i = 0 to N / 2 - 1
  if magnitude[i] > max_magnitude
    max_magnitude = magnitude[i]
    max_index = i

// convert index of largest peak to frequency
freq = max_index * Fs / N
47
Paul R