1

実機にFFTをかけ、そこからピークを算出したい

ここに私のコードがあります..

    N=8192
    kiss_fft_cpx out[N/2 +1];

    int len = fft->N / 2 + 1;

    kiss_fft_scalar* samples = &samples2[0]; //inputs from the mic

    kiss_fftr(fft->config, samples, out);

    for (int i = 0; i < len; i++) {

        float re = scale(out[i].r) * N;
        float im = scale(out[i].i) * N;

        if (i > 0)
            spectrum[i] = sqrtf(re * re + im * im) / (N / 2);
        else
            spectrum[i] = sqrtf(re * re + im * im) / N;

    }

ここで、コードを使用してピックを計算します。しかし、毎回0を返します

float peak = 0;
float maxEnergy = 0;
for (int i = 0; i < BUFFER_SIZE / 2 + 1; i++) {

    float binEnergy = spectrum.at(i);

    if (binEnergy > maxEnergy) {

        maxEnergy = binEnergy;
        peak = i;

    }

}

ここでは常にpeak=0になります。助けてください

最初の 25 個の FFT サンプルのスペクトル出力は次のとおりです。

 06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[0]: 0.036530
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[1]: 0.011568
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[2]: 0.012086
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[3]: 0.011568
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[4]: 0.040397
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[5]: 0.011568
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[6]: 0.012086
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[7]: 0.011568
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[8]: 0.044121
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[9]: 0.011568
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[10]: 0.012086
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[11]: 0.011568
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[12]: 0.040396
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[13]: 0.011568
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[14]: 0.012086
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[15]: 0.011568
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[16]: 0.116464
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[17]: 0.011568
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[18]: 0.012086
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[19]: 0.011568
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[20]: 0.040397
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[21]: 0.011568
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[22]: 0.012086
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[23]: 0.011568
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[24]: 0.044121
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(267) > peak   2223.000000
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(270) > FREQUENCY   4342.773438
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(281) > octave 8
4

2 に答える 2

2

自己相関法を使用して音声のピッチ検出を行う、かなり単純ですが計算集約的な方法があります。ギターにも当てはまらない理由がわかりません!ただし、基本周波数が複数ある場合は苦労します。ただし、それを処理するアルゴリズムは知りません。

少なくとも 3 つのピッチ周期をカバーするのに十分なサンプルを取得する必要があります。次に、信号を自己相関します (自己相関はFFTで効率的に実行できます)。

自己相関信号を取得すると、ラグ 0 で最大のピークが見つかります。2 番目に高いピークがピッチになります。

自己相関の前にハミング ウィンドウなどを使用して入力信号をウィンドウ処理することで、より良い結果が得られます。

さらに、Praatで有名な Paul Boersma は、はるかに正確なピッチ検出方法を考案しました。

基本的に彼のスキームを使用しています。ウィンドウ関数の自己相関を取り、後で使用するために保存します。次に、入力信号にウィンドウを適用します。その信号を自己相関させます。次に、ウィンドウ関数の自己相関で割ります。最後に、最高のピークを選択します。ラグ 0 からのオフセットは、ピッチ検出のサンプル数です。

最良の結果を得るには、自己相関ピークを補間する必要があることに注意してください。私は個人的に放物線補間を使用しており、得られた精度の向上は非常に大きかった. 放物線補間は非常に簡単です。

void ParabolicInterpolation( const float kA, const float kB, const float kC, float& p, float& m )
{
    p   = 0.5f * ((kA - kC) / (kA - (2.0f * kB) + kC));
    m   = (0.25f * (kA - kC) * p);
}

ここで、kB は特定した自己相関ピーク、kA はその前の自己相関サンプル、kC は後のサンプルです。

編集:上記の方法が提供するような精度が必要ない場合は、高調波積スペクトルと呼ばれる基本周波数を計算する別の非常に簡単な方法があります(このプレゼンテーションの冒頭を確認してください)。基本的に、FFT から始めます。それをマグニチュード スペクトルに変換します。最後に、2 倍、3 倍、4 倍にダウンサンプリングします。次に、サンプルを乗算します。最大のピークは基本周波数になります。ただし、これは FFT 解像度によって大きく制限されます。

それが役立つことを願っています!

于 2013-06-06T10:12:36.660 に答える