使用FFT计算频率时的值错误

时间:2014-02-18 11:57:54

标签: java audio signal-processing fft

我的频率错误,我不明白为什么我得到了错误的值。因为我按照指令计算后跟stackoverflow。 我用的是FFT http://introcs.cs.princeton.edu/java/97data/FFT.java.html 和复杂的 http://introcs.cs.princeton.edu/java/97data/Complex.java.html

audioRec.startRecording();
audioRec.read(bufferByte, 0,bufferSize);
for(int i=0;i<bufferSize;i++){
    bufferDouble[i]=(double)bufferByte[i];    
    }
Complex[] fftArray = new Complex[bufferSize];
    for(int i=0;i<bufferSize;i++){
    fftArray[i]=new Complex(bufferDouble[i],0);
    }
    FFT.fft(fftArray);
double[] magnitude=new double[bufferSize];
for(int i=0;i<bufferSize;i++){
      magnitude[i] = Math.sqrt((fftArray[i].re()*fftArray[i].re()) + (fftArray[i].im()*fftArray[i].im()));
    }
double max = 0.0;
int index = -1;
for(int j=0;j<bufferSize;j++){
    if(max < magnitude[j]){
            max = magnitude[j];
        index = j;
        }
    }
    final int peak=index * sampleRate/bufferSize;
    Log.v(TAG2, "Peak Frequency = " + index * sampleRate/bufferSize);
    handler.post(new Runnable() {
            public void run() {
                textView.append("---"+peak+"---");
            }
        });

我得到的价值如21000,18976,40222,30283等...... 请帮我..... 谢谢..

1 个答案:

答案 0 :(得分:2)

您的源代码几乎没问题。唯一的问题是你在整个频谱中搜索峰值,即从0到Fs / 2到Fs。

对于任何实值输入信号(你有),Fs / 2和Fs之间的频谱(=采样频率)是0和Fs / 2之间频谱的精确镜像(我发现this nice background explanation) 。因此,对于每个频率,存在两个具有 几乎 相同幅度的峰值。我写'差不多'是因为由于机器精度有限,它们不一定 完全 相同。因此,您可以随机找到频谱上半部分的峰值,其中包含低于奈奎斯特频率(= Fs / 2)的频率,或频谱高于奈奎斯特频率的频谱的后半部分。

如果您想自己纠正错误,请在此处阅读。否则继续:

只需替换

for(int j=0;j<bufferSize;j++){

for(int j=0;j<=bufferSize/2;j++){

在您提供的源代码中。

P.S。:通常情况下,最好将窗口函数应用于分析缓冲区(例如汉明窗口),但对于峰值拾取的应用,它不会对结果产生太大影响。