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,
You don't actually show the code where you calculate the frequency of the peak, but my guess is that the problem is here:
This should most likely be:
See this answer and/or this answer for an explanation of how to determine frequency from FFT output. (TL;DR:
f = Fs * i / n
)