Как получить частоту от результата FFT? - PullRequest
29 голосов
/ 06 октября 2011

Я записал массив [1024] данных с моего микрофона на свой телефон Android, пропустил его через 1D прямую ДПФ реальных данных (установив еще 1024 бита в 0).Я сохранил массив в текстовый файл и повторил это 8 раз.

Я получил 16384 результатов.Я открыл текстовый файл в Excel и сделал график, чтобы увидеть, как он выглядит (x = индекс массива, y = размер возвращаемого числа).Есть некоторые массивные пики (как положительные, так и отрицательные) величиной около 110, 232, и небольшие пики, продолжающиеся таким образом до 1817 и 1941 года, когда пики снова увеличиваются, а затем снова падают.

Моя проблема в том,что, где бы я ни искал помощи по теме, в которой упоминается получение действительных и мнимых чисел, у меня есть только одномерный массив, который я получал от метода, который использовал из класса Петра Вендикера:

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

Мой вопросявляется: Что мне нужно сделать с этими данными, чтобы вернуть частоту?Записанный звук - это то, что я играл «А» на нижней струне (5-й лад) моей гитары (примерно 440 Гц).

1 Ответ

47 голосов
/ 06 октября 2011

Сложные данные чередуются с реальными компонентами с четными индексами и мнимыми компонентами с нечетными индексами, т. Е. Реальные компоненты имеют индекс 2*i, мнимые компоненты имеют индекс 2*i+1.

Чтобы получить величину спектра по индексу i, вы хотите:

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

Затем вы можете построить величину [i] для i = 0 до N / 2, чтобы получить спектр мощности. В зависимости от характера вашего аудиовхода вы должны увидеть один или несколько пиков в спектре.

Чтобы получить приблизительную частоту любого данного пика, вы можете преобразовать индекс пика следующим образом:

freq = i * Fs / N;

где:

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)

Примечание: если вы ранее не применили подходящую оконную функцию к входным данным во временной области, то вы получите определенную величину спектральной утечки , и спектр мощности будет выглядеть скорее "размазанный".


Для более подробного описания приведем псевдокод для полного примера, в котором мы берем аудиоданные и определяем частоту самого большого пика:

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