【问题标题】:fftw slight peak inaccuracy/driftingfftw 轻微的峰值不准确/漂移
【发布时间】:2015-08-28 14:37:32
【问题描述】:

我正在使用 fftw 获取音频信号的频谱。我获得了 float32 格式的音频样本,并且还尝试了使用 PortAudio 的其他格式。然后我使用 fftw 处理它。在所有格式中,我的频率峰值与实际频率略有漂移。我的设置是。

  • 信号发生器提供正弦信号。
  • 44.1KHz 的采样率。

直到 10KHz,我都得到了正确/相对准确的读数。然而,随着我逐渐增加发生器的频率,我开始得到偏移。例如在 10KHz 以上,会发生这种情况。

Actual frequency         Peak on Spectrum
10KHz                    10.5KHz
12KHz                    12.9KHz
14KHz                    15.5KHz
16KHz                    18.2KHz

fft代码是这样的。

//Take Samples and do Windowing

 for( i=0; i<framesPerBuffer; i++ )
     {          
         samples[i] = in[i];
         fft->fftIn[i] = (0.54-(0.46*cos(scale_fact*i))) * samples[i];
     }

//Zero Padding

  for(i=framesPerBuffer; i<fftSize; i++)
  {
    fft->fftIn[i] = 0.0;
  }

//FFTW Code

{  fftSize = fftSize;
  this->fftSize = fftSize;
    cout << "Plan start " <<  endl;

  outArraySize = fftSize/2+1;
  cout << "fft Processor start \n";
  fftIn = ((double*) fftw_malloc(sizeof(double) * fftSize));
  fftOut = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * outArraySize );
  fftOutAbs = (double*) fftw_malloc(sizeof(double) * outArraySize );

   fftwPlan = fftw_plan_dft_r2c_1d(fftSize, fftIn, fftOut, FFTW_ESTIMATE);


  //  fftwPlan = fftw_plan_dft_r2c_1d(fftSize, fftIn, fftOut, FFTW_MEASURE);
}

//Absolute response

  int n=fftSize/2+1;
  for(int i=0; i < n; i++)
  {
    fftOutAbs[i] = sqrt(fftOut[i][0]*fftOut[i][0] + fftOut[i][1]*fftOut[i][1]);

  }

  for(unsigned int i=0; i < n; i++)
  {   
     mainCureYData[i] = 20.0 * log10(one_over_n * fft->fftOutAbs[i]);
  }

我需要一些关于这个问题可能在哪里/为什么会出现的提示?

硬件设置看起来不错,因为峰值在 sndpeek 应用程序上显示正确。

谢谢,

【问题讨论】:

    标签: c++ signal-processing fft fftw portaudio


    【解决方案1】:

    您实际上并没有显示计算峰值频率的代码,但我的猜测是问题出在这里:

    int n=fftSize/2+1;
    

    这很可能是:

    int n=fftSize/2;
    

    请参阅this answer 和/或this answer,了解如何根据 FFT 输出确定频率。 (TL;DR:f = Fs * i / n

    【讨论】:

    • 为此,下面的代码生成了 bin,然后用 FFT 数据绘制了这个数组以获得图形。最高幅度的 bin 应该是信号的频率。在我的情况下,这就是“漂移”的原因。 code for(int i=0; i &lt; DEFAULT_FFT_SIZE/2+1; i++) { mainCureXData[i] = ((double) i) / (DEFAULT_FFT_SIZE/2+1) * ap-&gt;getSampleRate()/2; `
    • 再次看起来像是对事物加 1 的过度喜爱。 ;-) DEFAULT_FFT_SIZE/2+1 很可能是 DEFAULT_FFT_SIZE/2。请参阅上面我的答案中的链接答案,以更好地解释 bin 索引如何映射到频率。另请注意,您可能不想查看 Nyquist bin。
    • FFT 点的数量是fftSize,所以我希望f = Fs * i / fftSize。 OP 的变量n=fftSize/2+1 正确用于处理下半部分频谱。它只是不应该用于频率计算部分。
    • @SlethEye:确实-我只是在猜测,因为没有显示相关代码。它看起来像一个不同的“off by one”错误 - 请参阅上面的评论。
    • 好的。尝试过mainCureXData[i] = (((double) i) * 44100.0) / 8192 ;,其中 44.1K 是 fs,8192 是 fftSize,但问题仍然存在。直观地说,+1 会导致这种行为吗?
    猜你喜欢
    • 1970-01-01
    • 2013-10-17
    • 1970-01-01
    • 2014-10-23
    • 1970-01-01
    • 1970-01-01
    • 2021-11-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多