一个具有自相关信号的信号会在滞后0处找到最大的峰值.第二个最高的峰值应该是您的音高.通过在自相关之前使用汉明窗之类的窗口对输入信号进行窗口化处理,可以获得更好的结果.还有 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分辨率.希望有帮助!I want to apply FFT on the real audio device and calculate the peak from ithere 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 0float 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 helpHere 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.03653006-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[1]: 0.01156806-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[2]: 0.01208606-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[3]: 0.01156806-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[4]: 0.04039706-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[5]: 0.01156806-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[6]: 0.01208606-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[7]: 0.01156806-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[8]: 0.04412106-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[9]: 0.01156806-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[10]: 0.01208606-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[11]: 0.01156806-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[12]: 0.04039606-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[13]: 0.01156806-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[14]: 0.01208606-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[15]: 0.01156806-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[16]: 0.11646406-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[17]: 0.01156806-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[18]: 0.01208606-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[19]: 0.01156806-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[20]: 0.04039706-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[21]: 0.01156806-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[22]: 0.01208606-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[23]: 0.01156806-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[24]: 0.04412106-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(267) > peak 2223.00000006-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(270) > FREQUENCY 4342.77343806-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(281) > octave 8 解决方案 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! 这篇关于我如何使用KissFFT计算峰值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
08-20 01:06