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

Pan*_*ian 6 java audio signal-processing fft

我的错频率,我不明白为什么我得到错误的值.因为我按照指令计算后跟stackoverflow.我使用了来自http://introcs.cs.princeton.edu/java/97data/FFT.java.html的 FFT和 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+"---");
            }
        });
Run Code Online (Sandbox Code Playgroud)

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

Har*_*ger 2

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

对于任何实值输入信号(您拥有的),Fs/2 和 Fs(=采样频率)之间的频谱是 0 和 Fs/2 之间频谱的精确镜像(我发现了这个很好的背景解释)。因此,对于每个频率,都存在两个幅度几乎相同的峰值。我写“几乎”是因为由于机器精度有限,它们不一定完全相同。因此,您可以在包含低于奈奎斯特频率 (=Fs/2) 的频率的频谱前半部分或包含高于奈奎斯特频率的频率的频谱后半部分中随机找到峰值。

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

只需更换

for(int j=0;j<bufferSize;j++){
Run Code Online (Sandbox Code Playgroud)

for(int j=0;j<=bufferSize/2;j++){
Run Code Online (Sandbox Code Playgroud)

在您提供的源代码中。

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