fftw slight peak inaccuracy/drifting

258 Views Asked by At

I am using fftw to get spectrum of an Audio Signal. I get Audio Samples in float32 and have also tried other formats using PortAudio. Then I take fft of it using fftw. In all the formats, I have slight drift of frequency peak from actual frequency. My setup is.

  • Signal Generator to supply sinusoidal signal.
  • Sampling rate of 44.1KHz.

I am getting correct/relatively accurate readings till 10KHz. However as I gradually increase the frequency of Generator, I start getting offset. For example above 10KHz, this is what happens.

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

The fft Code is as like this.

//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]);
  }

I need some hints as to where/why this problem could be ?

The Hardware setup look fine as the peak shows correct on sndpeek application.

Thanks,

1

There are 1 best solutions below

6
On

You don't actually show the code where you calculate the frequency of the peak, but my guess is that the problem is here:

int n=fftSize/2+1;

This should most likely be:

int n=fftSize/2;

See this answer and/or this answer for an explanation of how to determine frequency from FFT output. (TL;DR: f = Fs * i / n)