Forum: Digitale Signalverarbeitung / DSP / Machine Learning FFT für Anfänger


von Sera (Gast)


Lesenswert?

Hallo zusammen,

Ich möchte auch eine FFT in c++ programmieren. Hierbei kommt es mir erst
mal nicht auf die Geschwindigkeit an. Ich habe versucht soviel wie
möglich zu lesen, jedoch beschreiben die Meisten das ganze immer so
kompliziert, das es keiner verstehen kann, daher versuche ich es über
diesen Weg.

Ich möchte für den Anfang ein FFT mit 150 Punkten erstellen.ich habe 
schöne  die Funktionswerte  in einem Array geschrieben.

Kann mir vielleicht jemand anhand dieses kleinen Beispiels vorrechnen 
oder mal erklären
wie ich die FFT  in c++ implementieren oder kennt man ein Classe ,das 
mir  weiterhilft.

bin für  jede Tipps  sehr Dankbar.


Grüsse

Sera

von Achim W. (Gast)


Lesenswert?

Hallo,
die FFT ist die schnelle Variante der DFT. Das Ergebnis ist (so glaube 
ich) das gleiche.

DFT:
Du hast Deine Werte in einem Array.
Erzeuge jetzt einfach ein 2. Array und fülle das mit einem Sinus mit zum 
Beispiel 1kHz.

Jetzt gehst Du mit einer Schleife über alle Werte und multiplizierst 
alle Werte aus dem 1. Array mit denen aus dem 2. und bildest die Summe.

Also a[0]*b[0] + a[1]*b[1] + ... + a[150]*b[150]
Das Ergebnis (/150) ist der 1kHz Frequenzanteil.

Allerdings nur der, der in Phase mit dem Sinus ist. Damit die Phase 
keine Rolle spielt, machst Du das gleiche noch mit dem Cosinus und 
bildest den quadratischen Mittelwert aus dem 1kHz Sinusergebnis und dem 
1kHz Cosinusergebnis, also wurzel(s*s + c*c)

Und jetzt das alles wiederholen bei der nächsten Frequenz, zum Beispiel 
1.1kHz ..

von Niklas (Gast)


Lesenswert?

Hallo

die FFT ist eine schnelle Berechnung der DFT. Vor allem wenn die Anzahl 
der FFT eine Potenz von 2 ist also N = 2^r.
Bevor du dich an die FFT gibst solltest du daher zuerst die DFT komplett 
verstehen und dich dann an Sachen wie Butterfly, Twiddlefaktoren und 
Bitumkehrung geben. Ansonsten wird das nix mit der FFT

von Aris (Gast)


Lesenswert?

Damit hätte man dann die SFT - die slow fourrier analysis.

von FlorenZ (Gast)


Lesenswert?

@Achim:
Auch wenn ich die Frage nicht gestellt habe,
vielen Dank für die Antwort.

Ich habe noch nirgends eine verständlichere Erklärung der DFT gelesen.
Die hätte in der Wikipedia durchaus ihre Berechtigung...

Gruß, FlorenZ

von Martin K. (mkmannheim) Benutzerseite


Lesenswert?

Das ist auf Wiki aber sehr gut erklärt, finde ich. Auch im Netz findet 
man genug Erklärungen.

von Sera (Gast)


Lesenswert?

Danke Sehr Achim für dein Erklärung, sorry ich hat Internetproblem.
 Nach deiner Erklärung hab ich mit DFT noch mal beschäftigt und habe die 
Implementierung von DFT wie folgenden vorangegangen:
[c]

for( i=0;i<N;i++){   // N = 1024 : Anzahl der Punkte
  x[i]=f(x);          //  in Array schreibe ich die Funktionswerte
}
for(i=0; i<N;i++){
    a=0;
    b=0;
   for(i=0; i<N;i++){
     a=x[j]*cos((2*pi/N)*i*j);
     b=x[j]*sin((2*pi/N)*i*j);
    a+=a;
    b+=b;
  }
X[i]= sqrt(a*a+b*b);   // DFT Amplitudenwerte von Funktion
}

Kann man mir sagen ob es  richtig und  wie  kann ich  es verbessern 
falls da fehler ist.

PS:

> Das Ergebnis (/150) ist der 1kHz Frequenzanteil.
> Und jetzt das alles wiederholen bei der nächsten Frequenz, zum Beispiel
> 1.1kHz ..
Achim was meinst du hier das habe ich  nicht  verstanden , was du mit 
wiederhlen bei der nächsten Frequenzen meint.


Gruß
Sera

von Achim W. (Gast)


Lesenswert?

Ja, fast. Die innere Schleife muss natürlich j sein, nicht i.
Und die Aufsummierung muss anders erfolgen, sonst wird die Summe immer 
wieder zurückgesetzt.
1
for( i=0;i<N;i++){   // N = 1024 : Anzahl der Punkte
2
  x[i]=f(x);          //  in Array schreibe ich die Funktionswerte
3
}
4
5
for(i=0; i<N;i++){
6
    a=0;
7
    b=0;
8
    for(j=0; j<N;j ++){ 
9
        a+=x[j]*cos((2*pi/N)*i*j);
10
        b+=x[j]*sin((2*pi/N)*i*j);
11
    }
12
    X[i]= sqrt(a*a+b*b);   // DFT Amplitudenwerte von Funktion
13
}

>was du mit wiederhlen bei der nächsten Frequenzen meint.
Damit habe ich genau die äußere Schleife gemeint. Also die zweite der 
drei for-Schleifen mit Index i.

von Mori (Gast)


Lesenswert?

ah ok Danke  sehr ;

was  soll ich  da  änderen damit, ich die statt DFT nun FFT 
implementieren.
und  noch eine frage  entspricht  X[0]  das gleiche Anteil von dem 
Signal?

Gruß
Sera

von Achim W. (Gast)


Lesenswert?

>und  noch eine frage  entspricht  X[0]  das gleiche Anteil von dem Signal?
genau.

>was  soll ich  da  änderen damit, ich die statt DFT nun FFT implementieren.
Soweit ich das in Erinnerung habe, ist die FFT eine Variante der DFT, 
bei der N immer ein zweier-Potenz ist.
Dadurch kann man den Algorithmus deutlich in der Geschwindigkeit 
optimieren und es sind nicht mehr i*j Schleifendurchgänge notwendig, 
sondern deutlich weniger.

von Mori (Gast)


Lesenswert?

ja es muss der anzahl der punkte 2^n sein und da brauchst man nur bis 
2^n/2 werte zu brechnen. aber da  werde ich einfach weiter 
recherchieren.

ist X[0] hier das gleichanteil von den Signal?

von Mori (Gast)


Lesenswert?

ah danke habe deine Anwort übersehen

von Balu (Gast)


Lesenswert?

Ein Frage: Wenn man über eine komplette Welle drübersummiert, ist das 
Ergebnis doch Null. Oder wird der Effekt genutzt, dass die Wellen 
interferieren? Ich denke mir, dass das Ergennis einfach immer positiv 
sein wird, wenn man eine Welle gleicher Frequenz draufmultipliziert, 
richtig?

Ausserdem: Wieviele Wellen Sinus und Cosinus sind in dem array jeweils 
enthalten?  Es kann ja nur für eine ganzzahlig aufgehen. Ist es eine 
komplette Welle für die höchste Frequenz oder eine für die niedrigste?

Ich denke mir, dass die anderen entsprechend ihrer Frequenz angepasst 
werden und damit viele nicht genau in das Array-Raster passen, was 
wieder leakage erzteugen dürfte, oder?

Wird dieser Effekt durch die Fensterfunktion auf die Eingangsdate 
komplett beseitigt? Oder müssen die Koeefizienten im Sinus Cosinus Array 
auch nochmal gefenstert werden, wie man das bei anderen FIR-Filtern 
macht? Oder wird das dann doppelt gemoppelt?

Dann weiter; Wie stellt man die Stelheit der Frequenzen ein? Macht es 
Sinn, für die längste Welle (die anderen sind ja gemäss Frequenz kürzer) 
nicht nur eine Welle in das Array zu nehmen, sondern mehr als eine? ich 
habe ein wenig herumprobiert und festgestellt, dass die Frequenzen 
selektiver werden und regelrechte Durchsacker entstehen, wenn man die 
Frequenzen durchfährt. ???

Danke für eure Antworten.

von J. S. (engineer) Benutzerseite


Lesenswert?

Balu schrieb:
> Ausserdem: Wieviele Wellen Sinus und Cosinus sind in dem array jeweils
> enthalten?
Eine, die Grundwelle. Für die anderen Ordnungszahlen die entsprechenden 
Oberwellen.

> Ich denke mir, dass die anderen entsprechend ihrer Frequenz angepasst
> werden und damit viele nicht genau in das Array-Raster passen,
Ja

> was wieder leakage erzteugen dürfte, oder?
Du meinst, weil die Wellen nicht vollständig abschließen? Das ist 
zumindeste bei typischen Auflösungen der FFT unerheblich, weil der 
Beitrag des Restschwanzes minimal ist.

> Wird dieser Effekt durch die Fensterfunktion auf die Eingangsdate
> komplett beseitigt?
Ich würde sagen, das kommt auf die Fensterfunktion an. Je nachdem, wie 
die zum Rand ausläuft, hast Du sicher ein etwas anderes Verhalten.

>regelrechte Durchsacker entstehen
das sollte der oben beschriebene Randeffekt sein.

Welche FFT hast Du verwendet?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.