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

Я экранирован результатами, которые я получаю от FFT и ценил бы любую справку.

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

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

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

#include 
#include 
#include  
#include 
#include 
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); 
 }
}

6
задан Nils Pipenbrinck 24 December 2009 в 23:21
поделиться

2 ответа

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

Это потому, что Fast Преобразование Фурье предполагает, что ввод является периодическим и повторяется бесконечно. Если у вас нецелое количество синусоидальных волн и вы повторяете эту форму волны, это не идеальная синусоида. Это приводит к результату БПФ, который страдает от «спектральной утечки»

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

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

10
ответ дан 10 December 2019 в 00:39
поделиться

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

0
ответ дан 10 December 2019 в 00:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: