Frage

Ich bin verblüfft von den Ergebnissen, die ich von FFT bekomme und würde jede Hilfe schätzen.

Ich verwende FFTW 3.2.2, habe aber mit anderen FFT -Implementierungen (in Java) ähnliche Ergebnisse erzielt. Wenn ich die FFT einer Sinuswelle nehme, hängt die Skalierung des Ergebnisses von der Frequenz (Hz) der Welle ab-speziell, unabhängig davon, ob es nahe an einer ganzen Zahl liegt oder nicht. Die resultierenden Werte sind sehr klein skaliert, wenn die Frequenz nahe einer ganzen Zahl liegt, und sie sind Größenordnungen größer, wenn sich die Frequenz zwischen den ganzen Zahlen befindet. Diese Grafik Zeigt die Größe des Spike im FFT -Ergebnis an, das der Frequenz der Welle für verschiedene Frequenzen entspricht. Ist das richtig??

Ich habe überprüft, ob die inverse FFT des FFT den ursprünglichen Sinuswellenzeiten der Anzahl der Proben entspricht und es ist. Die Form der FFT scheint auch korrekt zu sein.

Es wäre nicht so schlimm, wenn ich einzelne Sinuswellen analysieren würde, weil ich unabhängig von seiner Größe nur nach dem Spike im FFT suchen könnte. Das Problem ist, dass ich Summen von Sinuswellen analysieren möchte. Wenn ich eine Summe von Sinuswellen bei beispielsweise 440 Hz und 523,25 Hz analysiere, taucht nur der Spike für die bei 523,25 Hz auf. Der Spike für den anderen ist so winzig, dass es einfach wie Geräusch aussieht. Es muss eine Möglichkeit geben, diese Arbeit zu machen, da es in MATLAB funktioniert-ich bekomme ähnliche Spikes bei beiden Frequenzen. Wie kann ich den folgenden Code ändern, um die Skalierung für verschiedene Frequenzen auszugleichen?

#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); 
 }
}
War es hilfreich?

Lösung

Die resultierenden Werte sind sehr klein skaliert, wenn die Frequenz nahe einer ganzen Zahl liegt, und sie sind Größenordnungen größer, wenn sich die Frequenz zwischen den ganzen Zahlen befindet.

Das liegt daran, dass eine schnelle Fourier -Transformation annimmt, dass die Eingabe periodisch ist und unendlich wiederholt wird. Wenn Sie eine nicht integrale Anzahl von Sinuswellen haben und diese Wellenform wiederholen, ist sie keine perfekte Sinuswelle. Dies führt zu einem FFT -Ergebnis, das darunter leidet "Spektralleckage"

Einblick in Fensterfunktionen. Diese dämpfen die Eingabe am Anfang und am Ende, so dass die spektrale Leckage verringert wird.

PS: Wenn Sie genaue Frequenzinhalte um die grundlegenden Wellenzyklen erhalten möchten und nicht zu viele Punkte pro Zyklus erfassen müssen (32 oder 64 Punkte pro Zyklus sind wahrscheinlich reichlich). Wenn Sie bei höheren Harmonischen einen genauen Frequenzgehalt erhalten möchten, erfassen Sie eine geringere Anzahl von Zyklen und mehr Punkte pro Zyklus.

Andere Tipps

Ich kann nur empfehlen, sich den GNU -Radiocode anzusehen. Die Datei, die für Sie von besonderem Interesse sein könnte, ist usrp_fft.py.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top