Pregunta

Estoy desconcertado por los resultados que estoy obteniendo de FFT y agradecería cualquier ayuda.

Estoy usando FFTW 3.2.2, pero han conseguido resultados similares con otras implementaciones FFT (en Java). Cuando tomo la FFT de una onda sinusoidal, la escala del resultado depende de la frecuencia (Hz) de la onda - en concreto, si está cerca de un número entero o no. Los valores resultantes se ajustan a escala muy pequeña cuando la frecuencia está cerca de un número entero, y son órdenes de magnitud mayor cuando la frecuencia es de entre números enteros. Este gráfico muestra la magnitud de la espiga en el resultado FFT correspondiente a la frecuencia de la onda, para diferentes frecuencias. ¿¿Es esto correcto??

I comprobado que la FFT inversa de la FFT es igual a los tiempos de onda senoidal originales el número de muestras, y lo es. La forma de la FFT también parece ser correcta.

No sería tan malo si estuviera analizando ondas sinusoidales individuales, porque yo sólo podía mirar por la subida de la FFT, independientemente de su altura. El problema es que quiero analizar sumas de ondas sinusoidales. Si estoy analizando una suma de ondas sinusoidales en, por ejemplo, 440 Hz y 523,25 Hz, entonces sólo el pico de la de 523,25 Hz aparece. El pico para el otro es tan pequeña que sólo se ve como el ruido. Tiene que haber alguna manera de hacer este trabajo porque en Matlab que hace trabajo-- consigo picos de tamaño similar en ambas frecuencias. ¿Cómo puedo cambiar el código de abajo para igualar la escala para diferentes frecuencias?

#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); 
 }
}
¿Fue útil?

Solución

  

Los valores resultantes se ajustan a escala muy pequeña cuando la frecuencia está cerca de un número entero, y son órdenes de magnitud mayor cuando la frecuencia es de entre números enteros.

Esto se debe a una transformación rápida de Fourier supone la entrada es periódica y se repite infinitamente. Si usted tiene un número no entero de ondas sinusoidales, y se repite esta forma de onda, no es una onda sinusoidal perfecta. Esto provoca un resultado de FFT que sufre de "fuga espectral"

Mira en funciones de la ventana . Estos atenúan la entrada al principio y al final, por lo que se ve disminuida que la fuga espectral.

p.s .: si desea obtener el contenido de frecuencia precisa en torno a la fundamental, la captura de una gran cantidad de ciclos de onda y que no es necesario para capturar demasiados puntos por ciclo (32 o 64 puntos por ciclo es probablemente un montón). Si desea obtener el contenido de frecuencia precisa en armónicos más altos, la captura de un menor número de ciclos, y más puntos por ciclo.

Otros consejos

Sólo puedo recomendar que nos fijamos en el código GNU Radio. El archivo que podría ser de particular interés para usted es usrp_fft.py.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top