2016-09-21 9 views
-4

Ich bin derzeit in einem Praktikum beschäftigt und mein Chef möchte, dass ich eine FFT bis Ende der Woche in Java programmiert habe.Die FFT-Ausgabe verstehen

Jetzt habe ich schon einen Code für die FFT von der Princeton University: http://introcs.cs.princeton.edu/java/97data/FFT.java

ich diesen Code in meinem Projekt umgesetzt und erweitert, mit dem ich jetzt bin in der Lage zu sein, zuerst die binäre Eingabe eines Signals las, dann Verarbeiten Sie die FFT für diese Beispielwerte und geben Sie dann die Größe an.

Jetzt komme ich zu meinem Problem. Ich habe die folgenden Werte eingegeben, die ich mit final double d = Math.sin(i); generiert und 8 Mal geloopt habe (das ist nur für Testzwecke, nächste Woche muss ich echte Werte eingeben).

0.0 
0.8414709848078965 
0.9092974268256817 
0.1411200080598672 
-0.7568024953079282 
-0.9589242746631385 
-0.27941549819892586 
0.6569865987187891 

so kommen diese Werte von einer reinen Sinus (ich weiß nicht, das richtige englische Wort, sondern mit reinem Sinus meine ich eine Sinus mit genau einer Frequenz von beispielsweise 50 Hz).

Der Ausgang ist jetzt

0.553732750242242 
2.3946469565385193 - 2.0970118573701813i 
-1.386684423934684 + 0.9155598966338983i 
-0.8810419659226628 + 0.28041399267903344i 
-0.8075738836045867 
-0.8810419659226628 - 0.28041399267903366i 
-1.386684423934684 - 0.9155598966338983i 
2.394646956538519 + 2.0970118573701817i 

Und die Größen der Ausgangs

0.553732750242242 
3.183047718211326 
1.6616689248786416 
0.9245901540720989 
0.8075738836045867 
0.924590154072099 
1.6616689248786416 
3.183047718211326 

Jetzt habe ich erwartet, dass tatsächlich die Ausgangswerte 0 bei jeder Frequenz Probe zeigen, bis ich die Frequenz der Reichweite reiner Sinus wird dominiert, wobei der Ausgang> 0 sein soll (zB bei 50 Hz). Das hat zumindest mein Chef erwartet, als er mir diese Aufgabe gab.

Zusammenfassung: Also das ist, was ich mit kämpfen. Ich habe einen anderen Thread gelesen, der nach einem ähnlichen Problem fragt, aber es gibt immer noch unbeantwortete Fragen für mich. Was soll ich mit den gegebenen Ausgabedaten machen? Wie finde ich die am häufigsten auftretende Frequenz?

Ich könnte wirklich Hilfe oder Erklärung brauchen, wo mein Denken falsch ist.

Danke fürs Zuhören ...

Antwort

1

Computing ein 512-Punkt-Fourier-Transformation nach einer einfachen Fensterfunktion Anwendung:

w(i)= ((float)i-(float)(n-1f)/2f) 

es gibt bei i peak = 25 (max Größe auf Ergebnis-Array).

Eingabe wurde auch mit mehr Informationen, wie beispielsweise Frequenz des Sinuswellengenerators (50 Hz) und Abtastrate (1kHz oder 0,001 Sekunden pro Probe) und das Hinzufügen von 2PI Konstante hinzugefügt:

Initialisierung sieht nun wie folgt aus (als sin (2xPIxFxi) Notation):

for (int i = 0; i < n; i++) 
{ 
     v1[i] = ((float)i-(float)(n-1f)/2f)* 
      (float)Math.Sin(0.001f* 50f*2f*Math.PI*(float)i); 
          ^ ^^    ^
           |  | |     | 
           |  F |     | 
          sampling  2xPi constant sample bin 
          rate(simulation) 
} 

und Ergebnis Spitzen wie folgt aussieht:

v2[22] 2145,21852033773 
v2[23] 3283,36245333956 
v2[24] 6368,06249969329 
v2[25] 28160,6579468591 <-- peak 
v2[26] 23231,0481898687 
v2[27] 1503,8455705291 
v2[28] 1708,68502071037 

so haben wir

25 

Jetzt sind diese Schritte im Frequenzraum und der Eingang wurde bei 1 kHz Frequenz, so dass Sie ein Maximum von 500 Hz harmonisches Signal (die Hälfte der Abtastrate) wahrnehmen können.

25*500 = 12500 

auch resultieren Bereich von 0 bis N/2 mit anderer Hälfte verspiegelt und wahrnehmbaren Frequenzbereich Dividieren (500) zur Ergebnisbereich (256 für N = 512) ergibt

48.83 Hz 

große Portion der Fehler muss die zu Beginn verwendete Fensterfunktion sein, aber v2 [26] hat einen höheren Wert als v2 [24], also liegt der tatsächliche Pick irgendwo näher an v2 [26] und der geglättete Graph dieser Punkte sollte 50 Hz zeigen.

Ignorieren Sie das erste Element des Ergebnisarrays, da es sich um konstanten Signalpegel oder unendliche Wellenlänge oder Nullfrequenz handelt.

Hier sind dft-Computing-Codes nur um sicher zu sein, wenn fft richtigen Ergebnisse zurückgibt:

//a---->b Fourier Transformation brute-force 
__kernel void dft(__global float *aRe, 
        __global float *aIm, 
        __global float *bRe, 
        __global float *bIm) 
{ 
    int id=get_global_id(0); // thread id 
    int s=get_global_size(0); // total threads = 512 
    double cRe=0.0f; 
    double cIm=0.0f; 
    double fid=(double)id; 
    double fmpi2n=(-2.0*M_PI)*fid/(double)s; 
    for(int i=0;i<s;i++) 
    { 
      double fi=(float)i; 
      double re=cos(fmpi2n*fi); 
      double im=sin(fmpi2n*fi); 

      cRe+=aRe[i]*re-aIm[i]*im; 
      cIm+=aRe[i]*im+aIm[i]*re; 
    } 

    bRe[id]=cRe; 
    bIm[id]=cIm; 
} 

und sicher sein, Testergebnis gegen inverse Transformation zu überprüfen, ob ursprüngliche Eingangssignal wieder erreicht wird:

Ich weiß, es ist schlecht, langsamen Code auf schnellen Maschinen zu laufen, aber das sieht so viel einfacher zu versuchen und ist skalierbar für viele Kerne (2,4ms für eine 320core-GPU einschließlich Array-Kopien).

+0

Hallo Huseyin, vielen Dank, das war sehr hilfreich! – Winterwurst

+0

@Winterwurst auch wenn Peak nicht dort ist, wo Sie es vorhersehen, können Sie intrapolieren versuchen, die Peak-Bin zwischen zwei ganzen Zahlen fein abzustimmen. –