web-dev-qa-db-ja.com

FFT結果から周波数を取得する方法は?

マイクからのデータの配列[1024]をAndroid電話、実際のデータの1D転送DFTに渡しました(さらに1024ビットを0に設定)で記録しました)。配列をテキストファイルに変換し、これを8回繰り返します。

16384件の結果が返されました。 Excelでテキストファイルを開き、グラフを作成して、どのように見えるかを確認しました(x =配列のインデックス、y =返される数値のサイズ)。大きさが110、232前後の大きなスパイク(正と負の両方)があり、小さなスパイクは1817年と1941年頃まで続き、スパイクは再び大きくなり、その後再び低下します。

私の問題は、実数と虚数の取得について言及しているトピックに関するヘルプを探す場合、Piotr Wendykierのクラスから使用したメソッドから取得した1D配列しかないということです。

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

私の質問は次のとおりです。周波数を返すために、このデータに対して何をする必要がありますか?録音された音は、ギターの下弦(5フレット)で(約440Hz)Aを演奏したものです。

29
Ben Taliadoros

複素数データはインターリーブされ、偶数インデックスに実数成分があり、奇数インデックスに虚数成分があります。つまり、実数成分はインデックス2*iにあり、虚数成分はインデックス2*i+1にあります。

インデックスiのスペクトルの大きさを取得するには、次のようにします。

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

次に、パワースペクトルを取得するために、i = 0からN/2の大きさ[i]をプロットできます。オーディオ入力の性質に応じて、スペクトルに1つ以上のピークが表示されます。

特定のピークのおおよその頻度を取得するには、次のようにピークのインデックスを変換できます。

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
47
Paul R