3

私が使用している fft (高速フーリエ変換) ルーチンを理解しようとしている (盗む) (リサイクルする)

入力は、サンプル波形である 512 個のデータ ポイントの配列です。テスト データはこの配列に生成されます。fft は、この配列を周波数領域に変換します。周波数、周期、サンプルレート、および fft 配列内の位置の関係を理解し​​ようとしています。例を挙げて説明します:

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

サンプルレートは 1000 サンプル/秒です。10Hz で一連のサンプルを生成します。

入力配列のピーク値は arr(28)、arr(128)、arr(228) ... 周期 = 100 サンプル ポイント

fft 配列のピーク値はインデックス 6 にあります (0 の巨大な値を除く)

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

サンプルレートは 8000 サンプル/秒です 440Hz でサンプルのセットを生成します

入力配列のピーク値には、arr(7)、arr(25)、arr(43)、arr(61) ... 期間 = 18 サンプル ポイントが含まれます

fft 配列のピーク値はインデックス 29 にあります (0 の巨大な値を除く)

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

fft 配列のピークのインデックスを周波数に関連付けるにはどうすればよいですか?

4

8 に答える 8

2

サンプル データセットを提供していただけると助かります。

私の推測では、サンプリング アーティファクトと呼ばれるものがあると思います。DC (周波数 0 ) での強い信号は、これが事実であることを示唆しています。

入力データの平均値がゼロであることを常に確認する必要があります。fft を呼び出す前に、平均を見つけて各サンプル ポイントから減算することをお勧めします。

同様に、サンプリング ウィンドウのアーティファクトにも注意する必要があります。最初と最後のデータ ポイントがゼロに近いことが重要です。そうしないと、サンプリング ウィンドウの外側から内側への「ステップ」によって、さまざまな周波数で大量のエネルギーが注入される効果があるからです。

要するに、fft 分析を行うには、どこかで見つかった fft ルーチンを単純に再利用するよりも注意が必要です。

質問で説明されている 10Hz 信号の最初の 100 サンプル ポイントを次に示します。サンプリング アーティファクトを回避するためにマッサージされています。

> 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.3582
 [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.297
 [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 3 9.6818
 [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 40e-144
 [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 5.279
 [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 -56.358 e-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-07 -95.297 e-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.6858 e-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.3744 e-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.2530332e-01 -6.2799 e-02

そして、これが 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.6+012 4.6+0912
[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
于 2008-10-02T02:07:28.190 に答える
2

虚数部を無視すると、度数分布はビン間で線形になります。

Frequency@i = (サンプリング レート/2)*(i/Nbins)。

したがって、最初の例では、256 個のビンがあると仮定すると、最大のビンは 1000/2 * 6/256 = 11.7 Hz の周波数に対応します。あなたの入力は 10Hz だったので、ビン 5 (9.7Hz) にも大きな成分があったと思います。精度を高めるには、より多くのサンプルを取得して、より小さなビンを取得する必要があります。

2 番目の例では、8000/2*29/256 = 453Hz が得られます。繰り返しますが、もっとビンが必要です。ここでの解像度はわずか 4000/256 = 15.6Hz です。

于 2008-10-01T20:19:34.687 に答える
1

もう1つの方法は、探している各音の中心周波数のGoertzelのアルゴリズムを作成することです。

アルゴリズムの1つの実装が機能するようになったら、中心周波数を設定するためにパラメーターを使用するように設定できます。これにより、88個、またはコレクションで必要なものを簡単に実行して、ピーク値をスキャンできます。

Goertzelアルゴリズムは、基本的にシングルビンFFTです。この方法を使用すると、音符が自然に進むように、ビンを対数的に配置できます。

ウィキペディアからのいくつかの擬似コード:

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;

前の2つのサンプルを表す2つの変数は、次の反復のために維持されます。これは、ストリーミングアプリケーションで使用できます。おそらく、電力計算もループ内にあるべきだと思います。(ただし、Wikiの記事ではそのように描かれていません。)

トーン検出の場合、88の異なる係数、88ペアの前のサンプルがあり、88の電力出力サンプルがその周波数ビンの相対レベルを示します。

于 2009-01-04T17:30:03.160 に答える
1

FFTをやってからしばらく経ちましたが、覚えていることは次のとおりです

FFT は通常、入力と出力として複素数を取ります。そのため、入力と出力の実数部と虚数部が配列にどのようにマップされるかはよくわかりません。

あなたが何をしているのかよくわかりません。最初の例では、1000 Hz のサンプル レートに対して 10 Hz でサンプル バッファーを処理すると言いますか? したがって、それぞれ 100 サンプルの 1 秒あたり 10 バッファが必要です。入力配列が少なくとも 228 サンプルの長さになる方法がわかりません。

通常、出力バッファの前半は、0 周波数 (=DC オフセット) から 1/2 サンプル レートまでの周波数ビンです。後半は負の周波数です。入力が実数データのみで、虚数信号の正と負の周波数が 0 の場合は同じです。出力の実数/虚数信号の関係には、入力信号からの位相情報が含まれています。

于 2008-09-26T11:16:55.387 に答える
1

他の人が言ったように、サンプルは周波数領域で等間隔です(対数ではありません)。

例 1 の場合、次のようになります。

代替テキスト http://home.comcast.net/~kootsoop/images/SINE1.jpg

他の例については、取得する必要があります

代替テキスト http://home.comcast.net/~kootsoop/images/SINE2.jpg

したがって、ピークの位置に関しては、両方の答えが正しいようです。

私が得ていないのは、大きなDC成分です。入力として正弦波を生成していますか? 入力は負になりますか?正弦波の場合、十分なサイクルが得られれば、DC はゼロに近くなるはずです。

于 2008-10-02T02:59:59.763 に答える
1

ビン i の周波数は i * (サンプルレート / n) です。ここで、n は FFT の入力ウィンドウ内のサンプル数です。

オーディオを扱っている場合、ピッチは周波数の対数に比例するため、ビンのピッチ解像度は周波数が高くなるにつれて増加します。低周波信号を正確に解決することは困難です。そのためには、より大きな FFT ウィンドウを使用する必要があり、時間分解能が低下します。特定のサンプル レートの時間分解能に対する周波数のトレードオフがあります。

あなたは0で大きな値を持つビンに言及しています - これは周波数0のビン、つまりDC成分です。これが大きい場合、おそらく値は一般的に正です。ビン n/2 (この場合は 256) はナイキスト周波数で、サンプル レートの半分です。これは、このレートでサンプリングされた信号で解決できる最高周波数です。

信号が実数の場合、ビン n/2+1 から n-1 には、それぞれビン n/2-1 から 1 の複素共役が含まれます。DC 値は 1 回だけ表示されます。

于 2008-10-01T20:47:37.007 に答える
1

私も数学と信号処理に少し慣れていませんが、追加情報があれば試してみることができます。

ビンごとの信号エネルギーを知りたい場合は、複素数出力の大きさが必要です。したがって、実際の出力を見るだけでは十分ではありません。入力が実数のみの場合でも。すべてのビンの出力の大きさは、ピタゴラスのように sqrt(real^2 + imag^2) です :-)

ビン 0 ~ 449 は、0 Hz ~ 500 Hz の正の周波数です。ビン 500 から 1000 は負の周波数であり、実際の信号の正と同じである必要があります。1 秒ごとに 1 つのバッファを処理すると、周波数と配列のインデックスが適切に整列します。したがって、インデックス 6 のピークは 6Hz に対応するため、少し奇妙です。これは、実数の出力データのみを見ており、実数と虚数のデータを組み合わせて、インデックス 10 で予想されるピークを示していることが原因である可能性があります。周波数は、ビンに線形にマッピングする必要があります。

0 のピークは DC オフセットを示します。

于 2008-09-26T11:45:22.780 に答える