fftw небольшая погрешность пиков / дрейф

Я использую fftw, чтобы получить спектр аудиосигнала. Я получаю образцы аудио в float32, а также пробовал другие форматы с помощью PortAudio. Затем я использую fftw. Во всех форматах у меня есть небольшое отклонение пика частоты от фактической частоты. Моя установка.

  • Генератор сигналов для подачи синусоидального сигнала.
  • Частота дискретизации 44,1 кГц.

Я получаю правильные / относительно точные показания до 10 кГц. Однако по мере того, как я постепенно увеличиваю частоту генератора, я начинаю получать компенсацию. Например, выше 10 кГц, вот что происходит.

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.

Спасибо,


person jav321    schedule 12.06.2015    source источник


Ответы (1)


На самом деле вы не показываете код, в котором вычисляете частоту пика, но я предполагаю, что проблема здесь:

int n=fftSize/2+1;

Скорее всего, это должно быть:

int n=fftSize/2;

См. этот ответ и / или этот ответ для объяснение того, как определить частоту на выходе БПФ. (TL; DR: f = Fs * i / n)

person Paul R    schedule 12.06.2015
comment
Для этого приведенный ниже код генерирует ячейки, а затем этот массив наносится на график с данными БПФ, чтобы получить график. Бин наивысшего значения должен быть частотой сигнала. Это то, что ускользает от меня в моем случае. code for(int i=0; i < DEFAULT_FFT_SIZE/2+1; i++) { mainCureXData[i] = ((double) i) / (DEFAULT_FFT_SIZE/2+1) * ap->getSampleRate()/2; ` - person jav321; 12.06.2015
comment
Опять же, это выглядит как чрезмерная привязанность к добавлению единицы к вещам. ;-) DEFAULT_FFT_SIZE/2+1 скорее всего должно быть DEFAULT_FFT_SIZE/2. См. Связанные ответы в моем ответе выше, чтобы лучше понять, как индекс корзины сопоставляется с частотой. Также обратите внимание, что вы, вероятно, не захотите смотреть на корзину Найквиста. - person Paul R; 12.06.2015
comment
количество точек БПФ fftSize, поэтому я ожидал f = Fs * i / fftSize. Переменная n=fftSize/2+1 OP правильно используется для обработки нижней половины спектра. Его просто не следует использовать для вычисления частоты. - person SleuthEye; 12.06.2015
comment
@SlethEye: действительно - я просто догадывался, потому что соответствующий код не был показан. Похоже, что на одну ошибку отличается - см. Комментарий выше. - person Paul R; 12.06.2015
comment
В порядке . Пробовали mainCureXData[i] = (((double) i) * 44100.0) / 8192 ;, где 44,1K - это fs, а 8192 - fftSize, но проблема не устранена. Интуитивно, может ли +1 вызвать такое поведение? - person jav321; 12.06.2015
comment
@ jav321 с fftSize=8192, +1 вызывает ошибку ~ 0,02% в оценке частоты, а не ошибку 5-14%, которую показывают ваши результаты. Вероятно, есть и другие источники ошибок или искажений. - person SleuthEye; 12.06.2015