Question

Je suis déconcerté par les résultats que je reçois de FFT et apprécierait toute aide.

J'utilise FFTW 3.2.2, mais ont obtenu des résultats similaires avec d'autres implémentations FFT (en Java). Quand je prends la FFT d'une onde sinusoïdale, la mise à l'échelle du résultat dépend de la fréquence (Hz) de l'onde - en particulier, que ce soit près d'un nombre entier ou non. Les valeurs obtenues sont mises à l'échelle très faible lorsque la fréquence est proche d'un nombre entier, et ils sont des ordres de grandeur plus grande lorsque la fréquence est entre des nombres entiers. Ce graphique montre l'ampleur de la pointe dans le résultat FFT correspondant à la fréquence, pour différentes fréquences de l'onde. Est-ce correct??

I vérifié que la FFT inverse de la FFT est égale au temps d'onde sinusoïdale d'origine le nombre d'échantillons, et il est. La forme de la FFT semble aussi être correct.

Il ne serait pas si mal si j'analyse des ondes sinusoïdales individuelles, parce que je pouvais chercher la pointe de la FFT quelle que soit sa hauteur. Le problème est que je veux analyser sommes d'ondes sinusoïdales. Si j'analyse une somme d'ondes sinusoïdales à, disons, 440 Hz et 523,25 Hz, alors que la pointe de l'une à 523,25 Hz apparaît. Le pic de l'autre est si petit qu'il ressemble le bruit. Il doit y avoir un moyen de faire ce travail parce que dans Matlab il ne work-- je reçois des pointes de taille similaire aux deux fréquences. Comment puis-je modifier le code ci-dessous pour égaliser la mise à l'échelle des fréquences différentes?

#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); 
 }
}
Était-ce utile?

La solution

  

Les valeurs obtenues sont mises à l'échelle très faible lorsque la fréquence est proche d'un nombre entier, et ils sont des ordres de grandeur plus grande lorsque la fréquence est entre des nombres entiers.

En effet, une transformée de Fourier rapide suppose l'entrée est périodique et est répétée à l'infini. Si vous avez un nombre non d'ondes sinusoïdales et vous répétez cette forme d'onde, ce n'est pas une onde sinusoïdale parfaite. Cela provoque un résultat FFT qui souffre de

Rechercher dans les fonctions de la fenêtre de . Ceux-ci atténuent l'entrée au début et à la fin, de sorte que la fuite spectrale est diminuée.

p.s .: si vous voulez obtenir le contenu de fréquence précise autour de la base, la capture beaucoup de cycles d'ondes et vous n'avez pas besoin de capturer trop de points par cycle (32 ou 64 points par cycle est probablement beaucoup). Si vous souhaitez obtenir le contenu de fréquence précise à des harmoniques plus élevées, capturer un plus petit nombre de cycles, et plus de points par cycle.

Autres conseils

Je ne peux que vous recommander regardez le code GNU Radio. Le fichier qui pourrait être d'un intérêt particulier pour vous est usrp_fft.py.

scroll top