Величина результата FFT зависит от частоты волны?

я озадачен результатами, которые я получаю от FFT, и был бы признателен за любую помощь.

Я использую FFTW 3.2.2, но получил аналогичные результаты с другими реализациями FFT (в Java). Когда я БПФ синусоидальной волны, масштабирование результата зависит от частоты (Гц) волны-в частности, близко ли это к целому числу или нет. Полученные значения масштабируются очень мало, когда частота близка к целому числу, и они на порядки больше когда частота находится между целыми числами. этот график показывает величину всплеска в результате БПФ, соответствующую частоте волны, для разных частот. Это правда??

Я проверил, что обратный БПФ БПФ равен исходной синусоидальной волне, умноженной на количество выборок, и это так. Форма БПФ также кажется правильной.

было бы не так плохо, если бы я анализировал отдельные синусоидальные волны, потому что я мог бы просто посмотреть для шипа в БПФ независимо от его высоты. Проблема в том, что я хочу проанализировать суммы синусоидальных волн. Если я анализирую сумму синусоидальных волн, скажем, 440 Гц и 523,25 Гц, то появляется только всплеск для одного из 523,25 Гц. Спайк для другого настолько крошечный, что он просто выглядит как шум. Должен быть какой-то способ сделать эту работу, потому что в Matlab она работает-я получаю спайки одинакового размера на обеих частотах. Как я могу изменить код ниже, чтобы выровнять масштабирование для разных частоты?

#include <cstdlib>
#include <cstring>
#include <cmath> 
#include <fftw3.h>
#include <cstdio>
using namespace std; 

const double PI = 3.141592;

/* Samples from 1-second sine wave with given frequency (Hz) */
void sineWave(double a[], double frequency, int samplesPerSecond, double ampFactor); 

int main(int argc, char** argv) {

 /* Args: frequency (Hz), samplesPerSecond, ampFactor */
 if (argc != 4)  return -1; 
 double frequency  = atof(argv[1]); 
 int samplesPerSecond = atoi(argv[2]); 
 double ampFactor  = atof(argv[3]); 

 /* Init FFT input and output arrays. */
 double * wave = new double[samplesPerSecond]; 
 sineWave(wave, frequency, samplesPerSecond, ampFactor); 
 double * fftHalfComplex = new double[samplesPerSecond]; 
 int fftLen = samplesPerSecond/2 + 1; 
 double * fft = new double[fftLen]; 
 double * ifft = new double[samplesPerSecond]; 

 /* Do the FFT. */
 fftw_plan plan = fftw_plan_r2r_1d(samplesPerSecond, wave, fftHalfComplex, FFTW_R2HC, FFTW_ESTIMATE);
 fftw_execute(plan); 
 memcpy(fft, fftHalfComplex, sizeof(double) * fftLen); 
 fftw_destroy_plan(plan);

 /* Do the IFFT. */
 fftw_plan iplan = fftw_plan_r2r_1d(samplesPerSecond, fftHalfComplex, ifft, FFTW_HC2R, FFTW_ESTIMATE); 
 fftw_execute(iplan); 
 fftw_destroy_plan(iplan);

 printf("%s,%s,%s", argv[1], argv[2], argv[3]); 
 for (int i = 0; i < samplesPerSecond; i++) {
  printf("t%.6f", wave[i]); 
 }
 printf("n"); 
 printf("%s,%s,%s", argv[1], argv[2], argv[3]); 
 for (int i = 0; i < fftLen; i++) {
  printf("t%.9f", fft[i]); 
 }
 printf("n"); 
 printf("n"); 
 printf("%s,%s,%s", argv[1], argv[2], argv[3]); 
 for (int i = 0; i < samplesPerSecond; i++) {
  printf("t%.6f (%.6f)", ifft[i], samplesPerSecond * wave[i]);  // actual and expected result
 }

 delete[] wave; 
 delete[] fftHalfComplex; 
 delete[] fft; 
 delete[] ifft; 
}

void sineWave(double a[], double frequency, int samplesPerSecond, double ampFactor) {
 for (int i = 0; i < samplesPerSecond; i++) {
  double time = i / (double) samplesPerSecond; 
  a[i] = ampFactor * sin(2 * PI * frequency * time); 
 }
}

2 ответов


результирующие значения масштабируются очень мало, когда частота близка к целому числу, и они на порядки больше, когда частота находится между целыми числами.

это потому, что быстрое преобразование Фурье предполагает, что вход является периодическим и повторяется бесконечно. Если у вас есть нецелое число синусоид, и вы повторите этот сигнал, это не идеальная синусоида. Это вызывает результат FFT, который страдает от "спектральный утечка"

посмотреть в окне функции. Они ослабляют вход в начале и конце, так что спектральная утечка уменьшается.

p.С.: если вы хотите получить точное частотное содержание вокруг фундаментального, захватите много волновых циклов, и вам не нужно захватывать слишком много точек за цикл (32 или 64 точки за цикл, вероятно, много). Если вы хотите получить точное частотное содержание на высших гармониках, захватите меньшее количество циклов, и больше очков за цикл.


Я могу только рекомендовать вам посмотреть код GNU Radio. Файл, который может представлять для вас особый интерес, usrp_fft.py - ...