How can i calculate the peak using kissFFT?

时光毁灭记忆、已成空白 提交于 2019-12-10 11:44:59

问题


I want to apply FFT on the real audio device and calculate the peak from it

here is my code..

    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;

    }

Now i calculate the pick using code. But everytime it returns 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;

    }

}

Here i always get peak=0. Please help

Here is my spectrum output for the first 25 FFT samples:

 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

回答1:


I suspect that you are (a) failing to apply a suitable window function prior to the FFT and/or (b) you have a large DC component. This will result in a large, possibly smeared (due to spectral leakage) peak at 0 Hz. You can verify this by printing/plotting your spectrum array.

To remedy this:

  • apply a suitable window function (e.g. Hann) prior to the FFT

  • change your peak finding loop so that it starts somewhere above bin 0, e.g.

    const int PEAK_MIN = BUFFER_SIZE / 1024;

    for (int i = PEAK_MIN; i < BUFFER_SIZE / 2 + 1; i++) { ...




回答2:


There is a fairly simple but computationally intensive way to do pitch detection of a voice using the autocorrelation method. I can't see why it wouldn't apply to a guitar as well! It will, however, struggle when there are more than one fundamental frequency. I'm not aware of an algorithm that handles that, however.

You need to take enough samples to cover at least 3 pitch periods. You then autocorrelate the signal (The Autocorrelation can be efficiently performed with an FFT).

One you have your autocorrelated signal you will find the largest peak at lag 0. The second highest peak ought to be your pitch.

You get better results by windowing the input signal using something like a hamming window before autocorrelation.

Further still Paul Boersma of Praat fame came up with a far more accurate method of pitch detection.

Basically using his scheme. You take the autocorrelation of the window function then store for later use. Next you window the input signal. Autocorrelate that signal. Now divide by the autocorrelation of the window function. Finally, select the highest peak and the offset from lag 0 is the number of samples to your pitch detection.

Its worth noting that you really need to interpolate the autocorrelation peaks to get the best results. I, personally, have used parabolic interpolation and the accuracy improvement I gained was huge. Parabolic interpolation is very easy:

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);
}

Where kB is the autocorrelation peak you've identified and kA is the auto correlation sample before it and kC the sample after.

Edit: If you don't need the kind of accuracy the above method provides there is another REALLY simple method of calculating fundamental frequency called the Harmonic Product Spectrum (Check the start of this presentation). Basically you start with your FFT. You convert it to the magnitude spectrum. Finally you downsample it 2x, 3x and 4x. Then you multiply the samples together. The largest peak will by your fundamental frequency. However this is severely limited by your FFT resolution.

Hope that helps!



来源:https://stackoverflow.com/questions/16934097/how-can-i-calculate-the-peak-using-kissfft

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!