FFT 的基频
Posted
技术标签:
【中文标题】FFT 的基频【英文标题】:Fundamental frequency from FFT 【发布时间】:2014-05-23 12:22:15 【问题描述】:我正在做一个从录音机返回基频的 android 项目。 我用 FFT 类计算频率:
http://introcs.cs.princeton.edu/java/97data/FFT.java
和复杂数组来自:
http://introcs.cs.princeton.edu/java/97data/Complex.java.html.
这是我计算频率的代码:
public double calculateFFT(byte[] signal)
final int mNumberOfFFTPoints =1024;
double mMaxFFTSample;
double temp;
Complex[] y;
Complex[] complexSignal = new Complex[mNumberOfFFTPoints];
double[] absSignal = new double[mNumberOfFFTPoints/2];
for(int i = 0; i < mNumberOfFFTPoints; i++)
temp = (double)((signal[2*i] & 0xFF) | (signal[2*i+1] << 8)) / 32768.0F;
complexSignal[i] = new Complex(temp,0.0);
y = FFT.fft(complexSignal);
mMaxFFTSample = 0.0;
int mPeakPos = 0;
for(int i = 0; i < (mNumberOfFFTPoints/2); i++)
absSignal[i] = Math.sqrt(Math.pow(y[i].re(), 2) + Math.pow(y[i].im(), 2));
if(absSignal[i] > mMaxFFTSample)
mMaxFFTSample = absSignal[i];
mPeakPos = i;
return ((1.0 * sampleRate) / (1.0 * mNumberOfFFTPoints)) * mPeakPos;
其中 sampleRate=44100 和 mNumberOfFFTPoints=1024。从这段代码中我读到了很多值,但我 只想得到基频,所以只有值。你能帮我理解这个算法吗?
【问题讨论】:
这个问题比你想象的要复杂得多,只能通过主观决定你感兴趣的信号类型来回答。一个可能对你有用也可能不适合你的简单解决方案是采取最强的成分,或频率低且强的成分。 一定要试试人声的基频,不知道要不要像这个基频的值一样考虑最大值 【参考方案1】:一般来说,音乐或语音的基频检测非常重要。话虽如此,根据您的来源,您也许可以简化问题。
例如,如果您的音源是一个唱单个音符的人,录音中没有音乐或其他背景声音,则修改后的峰值检测器可能会提供合理的结果。
下图显示了一位女高音持有降 B-3 (Bb3) 音符的频谱。 Bb3 的基频是 233 Hz,但女高音实际上唱的是 236 Hz 基频(最左边和最高峰)。
下图显示了一位女高音手握 F4 音符的频谱。 F4 的基频是 349 Hz,但女高音实际上唱的是 360 Hz 基频(最左边的峰值)。
但是,上图也显示了基频检测的挑战之一。在这种情况下,最高峰不是基波,而是 714 Hz 的一次谐波。您修改后的峰值检测器将不得不应对这些情况。
其他可能性是倒谱分析和自相关。 请参阅这些参考资料: Fundamental frequency detection /// Speech Signal Analysis
来自Sooeet.com FFT calculator的FFT、图表和音频数据
【讨论】:
以上是关于FFT 的基频的主要内容,如果未能解决你的问题,请参考以下文章