Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Problem bei FFT (https://www.delphipraxis.net/85240-problem-bei-fft.html)

3_of_8 27. Jan 2007 22:36


Problem bei FFT
 
Morgen.

Ich versuche gerade, eine FFT zu implementieren, aber irgendwie kriege ich das nicht so ganz hin...

Delphi-Quellcode:
unit complex;

interface

uses Math;

type
  TComplex=record
    re, im: Single; //Real- und Imaginärteil
  end;

  TComplexArray=array of TComplex;

function AddC(a, b: TComplex): TComplex; overload;
function AddC(a: TComplex; b: Single): TComplex; overload;
function SubC(a, b: TComplex): TComplex; overload;
function SubC(a: TComplex; b: Single): TComplex; overload;
function MulC(a, b: TComplex): TComplex; overload;
function MulC(a: TComplex; b: Single): TComplex; overload;

function MakeC(re, im: Single): TComplex;

procedure FFT(var a: TComplexArray); overload;
procedure FFT(var a: array of Single); overload;
procedure FFT(var a: array of Integer); overload;

implementation

function AddC(a, b: TComplex): TComplex;
begin
  Result.re:=a.re+b.re;
  Result.im:=a.im+b.im;
end;

function AddC(a: TComplex; b: Single): TComplex;
begin
  Result.re:=a.re+b;
  Result.im:=a.im;
end;

function SubC(a, b: TComplex): TComplex;
begin
  Result.re:=a.re-b.re;
  Result.im:=a.im-b.im;
end;

function SubC(a: TComplex; b: Single): TComplex;
begin
  Result.re:=a.re-b;
  Result.im:=a.im;
end;

function MulC(a, b: TComplex): TComplex;
begin
  Result.re:=a.re*b.re-a.im*b.im;
  Result.im:=a.re*b.im+a.im*b.re;
end;

function MulC(a: TComplex; b: Single): TComplex;
begin
  Result.re:=a.re*b;
  Result.im:=a.im*b;
end;

function MakeC(re, im: Single): TComplex;
begin
  Result.re:=re;
  Result.im:=im;
end;

procedure shuffle(var a: TComplexArray; n, lo: Integer); //Mischt die Elemente des Arrays
var I, m: Integer;
    b: TComplexArray;
begin
  m:=n shr 1;
  setlength(b, m);
  for I:=0 to m-1 do
    b[i]:=a[lo+i];
  for I:=0 to m-1 do
    a[lo+i+i+1]:=a[lo+i+m];
  for I:=0 to m-1 do
    a[lo+i+i]:=b[i];
end;

procedure DoFFT(var a: TComplexArray; n, lo: Integer; w: TComplex); //Führt die FFT rekursiv aus
var I, m: Integer;
    z, v, h: TComplex;
begin
    //Hier ist w möglicherweise falsch
    z:=MulC(w, MulC(w, MulC(w, MulC(w, MulC(w, MulC(w, w))))));
    if n>1 then
    begin
        m:=n shr 1; //Teilt die Arraylänge auf
        z:=MakeC(1, 0); //Soviel wie z:=1, nur eben als komplexe Zahl
        for I:=lo to lo+m-1 do
        begin
            h:=SubC(a[i], a[i+m]);
            a[i]:=AddC(a[i],a[i+m]);
            a[i+m]:=MulC(h,z);
            z:=MulC(z,w);
        end;
        v:=MulC(w,w);
        DoFFT(a, m, lo, v);
        DoFFT(a, m, lo+m, v);
        shuffle(a, n, lo);
    end;
end;

//In den folgenden Prozeduren ist exp(2*Pi/length(a)) jeweils e^2*Pi*n,
//die primitive Einheitswurzel

procedure FFT(var a: TComplexArray);
begin
  DoFFT(a, length(a), 0, MakeC(cos(DegToRad(2*Pi/length(a))), sin(DegToRad(2*Pi/length(a)))));
end;

procedure FFT(var a: array of Single);
var I: Integer;
    b: TComplexArray;
begin
  setlength(b, length(a));
  for I:=0 to high(a) do b[I]:=MakeC(a[I], 0);
  DoFFT(b, length(a), 0, MakeC(cos(DegToRad(2*Pi/length(a))), sin(DegToRad(2*Pi/length(a)))));
  for I:=0 to high(a) do a[I]:=b[I].re;
end;

procedure FFT(var a: array of Integer);
var I: Integer;
    b: TComplexArray;
begin
  setlength(b, length(a));
  for I:=0 to high(a) do b[I]:=MakeC(a[I], 0);
  DoFFT(b, length(a), 0, MakeC(cos(DegToRad(2*Pi/length(a))), sin(DegToRad(2*Pi/length(a)))));
  for I:=0 to high(a) do a[I]:=trunc(b[I].re);
end;

end.
EDIT: Soo, das sieht jetzt schon *etwas* besser aus.
Der Algorithmus kompiliert, läuft und terminiert ohne Exceptions und die Ergebnisse für w sind auch schon fast in Ordnung.

Wo ich mir aber nicht ganz sicher bin, das ist die Berechnung von w.
Wenn ich das richtig sehe, dann ist w=e^(2*Pi*i/n) und e^(i*x)=cos(x)+sin(x)*i. Dadurch lässt sich das ganze auflösen in w=cos(2*Pi/n)+sin(2*Pi/n)*i, was ich oben auch habe. Nur hätte ich eigentlich angenommen, dass mit sin und cos die Sinus- und Kosinusfunktionen im Bogenmaß gemeint sind, aber einigermaßen passende Ergebnisse bekomme ich nur mit Gradangaben, also vorher ein DegToRad...

3_of_8 28. Jan 2007 23:17

Re: Problem bei FFT
 
*push*

dino 28. Jan 2007 23:34

Re: Problem bei FFT
 
da du ja schon selber am pushen bist, kann ich vielleicht mal sagen, dass ich mich mal mit fft beschäftigt habe und es auch mal programmieren wollte, aber schnell demotiviert wurde :(

und tatsächlich: es ist kompliziert(wenn ich dein code mal so sehe)

aber ich möchte auch, dass jemand, der mehr erfahrung hat dir sagt, was du wissen willst, also: wenn jemand die antwort kennt, so soll er dies alles hier ignorieren

sirius 29. Jan 2007 07:29

Re: Problem bei FFT
 
Zitat:

Zitat von 3_of_8
Wo ich mir aber nicht ganz sicher bin, das ist die Berechnung von w.
Wenn ich das richtig sehe, dann ist w=e^(2*Pi*i/n) und e^(i*x)=cos(x)+sin(x)*i. Dadurch lässt sich das ganze auflösen in w=cos(2*Pi/n)+sin(2*Pi/n)*i, was ich oben auch habe. Nur hätte ich eigentlich angenommen, dass mit sin und cos die Sinus- und Kosinusfunktionen im Bogenmaß gemeint sind, aber einigermaßen passende Ergebnisse bekomme ich nur mit Gradangaben, also vorher ein DegToRad...

Ich habe bisher nur einfache DFT-Algos auf eine spezielle Anzahl von Abtastwerten bzw. Samplingraten "optimiert"/angepasst. Deswegen kann ich nicht genau sagen, was an deiner FFT flasch, oder fehlerhaft ist. Was komisch aussieht, hast du ja selber bemängelt:
Das DEGtoRad muss falsch sein.
Und was ist dieses w^7, was du am Anfang der Funktion machst.

Und nebenbei: Ist dir klar, was du am Ende einer DFT/FFT für Ergebnisse bekommst? Sagt dir Aliasing/Antialiasing etwas?


PS:
Warum denn gleich FFT? Reicht nicht erstmal eine einfache DFT? Da versteht man noch eher was passiert.


Edit: Wenn ich von der DFT ausgehe, müsstest du für w am Anfang die konjugiert Komplexe nehmen.
du tust die dir anscheinend mit deinem w^7 irgendwie zurechtzubasteln. Das dürfte aber nur bei einer bestimmten Zahl an Abtastwerten klappen.

IngoD7 29. Jan 2007 08:31

Re: Problem bei FFT
 
Zitat:

Zitat von sirius
Zitat:

Zitat von 3_of_8
Nur hätte ich eigentlich angenommen, dass mit sin und cos die Sinus- und Kosinusfunktionen im Bogenmaß gemeint sind, aber einigermaßen passende Ergebnisse bekomme ich nur mit Gradangaben, also vorher ein DegToRad...

Was komisch aussieht, hast du ja selber bemängelt:
Das DEGtoRad muss falsch sein.

Ich habe keine Ahnung, was FFT und dergleichen ist, aaaaber:

Die Winkelangaben dieser Funktionen müssen in Delphi im Bogenmaß angegeben werden. Daher muss in Delphi eine Winkelangabe von z.B. 30° zuvor mit DegToRad umgewandelt werden, damit der Sinus von 30° auch wirklich 0,5 ergibt.

Wenn also in cos(DegToRad(2*Pi/length(a))) das 2*Pi/length(a) schon Bogenmaß ist, dann ist DegToRad falsch und deine Ergebnisse wohl nur zufällig "einigermaßen passend". ;-) Wenn das 2*Pi/length(a) eine Grad-Angabe ist, dass ist das DegToRad korrekt, um in Delphi auf den korrekten Cos-Wert zu kommen.


Kann aber natürlich auch sein, dass ich euch überhaupt nicht verstanden habe ... :drunken:

EWeiss 29. Jan 2007 08:52

Re: Problem bei FFT
 
Einen eigenen FFT Algo zu programmieren setzt ein fundiertes wissen an Mathematik vorraus.
Wenn du nicht darüber verfügst dann lass es lieber und benutze vorhandene algos.

Irgendwo macht das auch keinen sinn etwas zu erfinden was schon vorhanden ist.
Es sein denn !!!
Du könntest ihn optimieren, damit haben sich aber schon einige Professoren beschäftigt
und viele sind gescheitert.

Information darüber was FFT (fast Fourier transform) bedeutet bitte hier ein link.

http://de.wikipedia.org/wiki/Schnell...Transformation

gruß

sirius 29. Jan 2007 09:45

Re: Problem bei FFT
 
Zitat:

Zitat von EWeiss
Information darüber was FFT (fast Fourier transform) bedeutet bitte hier ein link.
http://de.wikipedia.org/wiki/Schnell...Transformation
gruß

Ich glaube, den Link und den weiterfürhenden Link hat er schon selber gefunden.

Ich bin zwar der Meinung, dass man durch Abschreiben (und gleichzeitiges darüber Nachdenken) auch ein Menge lernen kann. Aber bei so komplexen Sachen...
Hut ab, vor dem, der es schafft.

3_of_8 29. Jan 2007 12:29

Re: Problem bei FFT
 
Mein Wissen über Mathematik ist immerhin etwa auf Erstsemesterniveau, die Gleichungen der FFT verstehe ich größtenteils.

Zitat:

Und was ist dieses w^7, was du am Anfang der Funktion machst.
Das hätte eigentlich schon längst draußen sein sollen, das habe ich nur gemacht, um zu testen, ob w^n=1.

@Dino: Du wurdest nicht demotiviert, dir wurde nur gesagt, dass eine FFT garantiert nicht das tut, was du tun willst, weil das, was du tun wolltest, nicht möglich ist.

sirius 29. Jan 2007 12:46

Re: Problem bei FFT
 
Was gibst du den zum Testen für eine Zeitreihe ein, und was für Ergebnisse bekommst du?

3_of_8 29. Jan 2007 13:12

Re: Problem bei FFT
 
Ich weiß nicht so genau, was ich erwarte. :lol:

Deswegen probier ichs einfach mal aus mit einem array[0..127] of Single, die die Werte einer Sinuskurve enthalten.

EDIT: Ich schätze mal, das ganze würde funktionieren, wenn ich wenigstens w ausrechnen könnte.

Also, ich habe w^n=1

w=e^(2*Pi*i/n)

1. Eulersche Formel:
e^(Phi*i)=cos(Phi)+sin(Phi)*i

Also Umformung:
w=cos(2*Pi/n)+sin(2*Pi/n)

Nur erhalte ich dann Ergebnisse, bei denen wenn w die 7. primitive Einheitswurzel ist, Re(w^7) bei ~1 liegt, aber Im(w^7) bei 0.1.

sirius 29. Jan 2007 13:19

Re: Problem bei FFT
 
Ein sinus ist für den Anfang genau Richtig, später macht man dann einfach mal die Addition von Schwingungen unterschiedlicher Frequenz.
Aber welche Frequenz hat dein Sinus.
Du musst zum Testen dir das auch alles genau festlegen (128 Werte sin etwas wenig).
Versuche mal mindestens 5 Perioden (10 ist besser) bei einer Abtastfrequenz von mindestens dem 3-fachen hineinzubekommen.
Dazu musst du dir auch genau festlegen, welche Zeitwerte du hast und kannst damit dann die diskreten Frequenzwerte nach der FFt ausrechnen und dann gilt eigentlich (egal welcher FFT-Algo oder eben nur DFT):
-Das erste Element ist der Gleichanteil
-Und alles ab dem zweiten Element ist der entsprechende Frequenzanteil; allerdings nur die Hälfte, da die andere Hälfte im hinteren Teil des Spektrums ist, gespiegelt an Fs/2 (<<-Aliasing); Der Winkel ist konjugiert Komplex.

3_of_8 29. Jan 2007 13:22

Re: Problem bei FFT
 
Erklär mir mal, wie ich meine FFT mit Parameter eines Arrays aufrufen muss und wie ich die Werte interpretieren muss, Beispieldaten wähl bitte du, weil ich grad keine Ahnung mehr hab.

Übrigens hab ich oben geeditet.

sirius 29. Jan 2007 13:54

Re: Problem bei FFT
 
Ich vermute immernoch, dass dein w=e^(-2*i*pi/n) ist. Bedenke, dass die n-te Wurzel aus x immer n Lösungen hat. Deine ist auch eine, aber für den Fall wahrscheinlich nicht die "Richtige".


Ok, Eingangsdaten:

Nimm mal ein array von 1024 Werten:
Delphi-Quellcode:
for n:=0 to 1023 do a[n]:=5*sin(2*pi*10*n/1000);
Das entspricht A*sin(w*t)
A..Amplitude
w..omega/Kreisfrequenz=2*pi*f=2*pi*10
t..entspricht n/1000;wobei 1000 die Abtastfrequenz ist

Du bekommst also eine Sinuskurve mit 10 Hz, wo aller 1ms ein fiktiver Messpunkt ist; also 100 Mespunkte pro Periode -->für 1024 Werte etwa 10 Perioden.

Nach der FFT entsprechen die Absolutwerte der Elemente folgenden Frequenzen: n*1000/1024 (n=0..1023); also an 11. Stelle liegen etwa unsere 10Hz und dort sollte eine Spitze im Spektrum auftauchen, wie auch etwa bei Stelle 1013 (Aliasing).

Die Winkel kannst du natürlich bei einer Schwingung vergessen, da ja keine Referenz existiert.

3_of_8 29. Jan 2007 14:04

Re: Problem bei FFT
 
Zitat:

Ich vermute immernoch, dass dein w=e^(-2*i*pi/n) ist. Bedenke, dass die n-te Wurzel aus x immer n Lösungen hat. Deine ist auch eine, aber für den Fall wahrscheinlich nicht die "Richtige".
Eben gerade nicht.

Mein w ist keine Lösung von w^n=1, denn w^n=1+0.1i.

Seltsamerweise ist bei mir folgendes:

w:=cos(2*Pi/n)+sin(2*Pi/n)

Für n=1 ist w^1=1
Für n=2 ist w^2=1
Für n=3 ist w^2=~(-0.96-1.21i)

sirius 29. Jan 2007 14:32

Re: Problem bei FFT
 
Liste der Anhänge anzeigen (Anzahl: 1)
Für welches w? Ich verstehe nicht ganz, was du rechnest.

Dir fehlt anscheinend noch ein bisschen Wissen zu komplexen Zahlen. Das kann ich dir aber hier und mal eben nebenbei nicht erklären.

Im Anhang findest du wie es die DFT macht, für n=8 Abtastwerte
(Der Rote Pfeil ist w)
Da der Betrag der Zahl immer 1 ist, werden beim potenzieren nur die Winkel verändert (und zwar werden die addiert)
Dasselbe Ergebnis kommt bei w=e^( +2*pi*i/8 ) heraus.

3_of_8 29. Jan 2007 14:42

Re: Problem bei FFT
 
Ich weiß meiner Meinung nach genug über komplexe Zahlen.

Mein Algorithmus für die FFT erwartet ein w, das die n-te primitive Einheitswurzel ist, wobei n die Länge des Arrays ist.

Die n-te primitive Einheitswurzel lässt sich berechnen durch e^(2*Pi*i/n).

e^(x*i) ist nach der 1. Eulerschen Formel gleich cos(x)+sin(x)*i.

Daher schließe ich w=e^(2*Pi*i/n)=cos(2*Pi/n)+sin(2*Pi/n)*i. Mit dieser Formel berechne ich w, allerdings stimmen die Werte seltsamerweise nicht.

EDIT: Meine Formeln sind ein eindeutiger Schluss aus deinem Kreis.

EDIT2: :wall: Mein Wert für w war die ganze Zeit richtig, das Problem war meine Testroutine, die einfach falsch potenziert hat. Und das DegToRad() muss ich, wie ich gleich vermutet hatte, weglassen.

sirius 29. Jan 2007 15:13

Re: Problem bei FFT
 
So, jetzt habe ich mal ein wenig geanuer reingeschaut

Ich bin über die Variante (array of single) reingegangen
sieht jetzt so aus:
Delphi-Quellcode:
procedure FFT(var a: array of Single);
var I: Integer;
    b: TComplexArray;
begin
  setlength(b, length(a));
  for I:=0 to high(a) do b[I]:=MakeC(a[I], 0);
  DoFFT(b, length(a), 0, MakeC(cos((2*Pi/length(a))), -sin((2*Pi/length(a))))); //das Minus ist erstmal egal
  for I:=0 to high(a) do a[I]:=sqrt(sqr(b[I].re)+sqr(b[i].im))/length(a);
end;
Das Minus ist egal, da wir nur den Betrag auswerten.
Dein Fehler ist, dass du nur den Realteil auswertest.

Getestet mit Tchart:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var l:Tlineseries;
    a:array[0..1023] of single;
    i:integer;
begin
  for i:=0 to 1023 do a[i]:=5*sin(2*pi*10*i/1000);
  for i:=0 to chart1.SeriesCount-1 do chart1.Series[0].free;
  l:=tlineseries.create(chart1);
  chart1.AddSeries(l);

  fft(a);
  for i:=0 to 1023 do l.AddXY(i*1000/1024,a[i]);
end;
Wenn du aus den beiden 1000 auch eine 1024 machst, bekommst du ein "scharfes" Ergebnis.

3_of_8 29. Jan 2007 15:25

Re: Problem bei FFT
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich habe keine Chart gefunden und hab mir daher mit einem Image beholfen:

EDIT: Wie oben schon beschrieben, habe ich ja das Problem gefunden. ;)

Der FFT scheint zu funktionieren, jetzt die Frage, warum der Ausschlag so ist, wie er ist.

EDIT2: Ich weiß, warum er bei 10/11 so ist, aber warum ist er hinten auch so? Du hast vorher was von (Anti-)Aliasing gesagt, was meinst du damit? Und ist es normal, dass einige Werte nach dem FFT negativ sind?

sirius 29. Jan 2007 18:15

Re: Problem bei FFT
 
Liste der Anhänge anzeigen (Anzahl: 2)
Ich hab erstmal mein Ergebnis angefügt.

Hab übersehen, dass du den Fehler gefunden hast. Nimm aber bitte trotzdem statt dem Realteil den Absolutwert, ansonsten bekommst du bei komplexeren Signalen Probleme. Ausserdem werden dann alle deine Werte positiv, so wie es sein soll.
Und ob w=w1=e^(-2*pi*i/n) oder w=w2=(+2*pi*i/n) entscheidet am Ende das Vorzeichen der Winkel der einzelnen Frequenzanteile und ist somit schon wichtig. Und wie ich schon sagte, w1^n=w2^n=1.

Wenn dein (Ton-)signal mein beschriebenes 10Hz Signal ist, verstehe ich nicht, wo in deinem Bild die Frequenzanteile unter 10 Hz sind, die müssten wieder Richtung 0 gehen.

Und für das Aliasing müsste ich eigentlich ziemlich weit ausholen, und mir fehlt die Zeit dazu.

Also kurz (und damit alle Angaben ohne Gewähr):
Aliasing entsteht durch die Digitalisierung. Nehmen wir an du hast ein 10Hz-signal analog und tastest es Digital mit 50Hz ab, also aller 20ms ein Wert.
Und jetzt stehst du mit deinem abgetastetem Signal da, aller 20ms ein Wert und überlegst, wie das Ursprungssignal aussah. du kannst es mal ausprobieren, in dein abgetastetes Singnal passen folgende Frequenzen einzeln hervorragend rein:
10Hz
40Hz
60Hz
90Hz
110Hz
140Hz
160Hz
.
.
.
also alle 50Hz*k-10Hz und 50Hz*k+10Hz (k..ganze Zahl)

Nun musst du dich für eine Frequenz entscheiden.
Das geht am einfachsten, wenn du weist, was im Ursprungssignal überhaupt drinn war.
Wenn du z.B. wüsstest, dass im Ursprungssignal nur Werte zwischen 0<=f<25Hz waren, ist das Ergebnis klar. entsprechend kannst du das Fenster um 25Hz immer weiter verschieben.

Deswegen gibt es Antialiasingfilter, die machen nix weiter als das analoge Eingangsignal in einen Bandpass (oder Tiefpass) zu quetschen, damit beim A/D-wandeln nur signale (in unserem eispiel) zwischen 0 und 25 Hz auftauchen (oder eben ein anderes Frequenz-Band).
Man muss also immer mit der doppelten Frequenz abtasten, wie das Frequenzband breit ist (am besten mehr).

Nun zurück zu unserr FFT. Wir setzen ja beim bereits abgetasten Signal an und versuchen die Ursprungsfrequenzanteile vom analogen Signal zu bekommen.

In dem von mir angegebenen Beispiel haben wir ein mit 1000Hz abgetastetes 10Hz Signal. Damit gilt die Bedingung -> Unser Frequenzband ist 0 bis 10Hz =10Hz und wir tasten mit (deutlich) mehr als 2*10Hz=20Hz ab.
Wenn wir mit 1000Hz abtasten spiegeln sich, wie oben beschrieben, alle anderen (Aliasing)-Frequenzen um 1000Hz, also
10Hz
990Hz
1010Hz
1990Hz
.
.
.
Die FFt rechnet aber nur bis 1000Hz und teilt die Anteile gerecht und fair, gleichmäßig auf beide Anteile auf. Demnach haben wir bei einer Ursprungsamplitude von 5 bei 10Hz, nachher einen Frequenzanteil von 2,5 bei 10Hz und 2,5 bei 990Hz.

Soweit, was mir dazu einfällt.
Kannst das Alising mal damit testen, dass du statt den 10Hz, die anderen frequenzen testest. Es sollte das gleiche Ergebnis liefern. du kannst also nur bis Abtastrate/2 (=500Hz) die Ergebnisse verwenden.

Edit+Edit2: Aliasing-Bild angefügt

3_of_8 29. Jan 2007 21:36

Re: Problem bei FFT
 
Folgendes Problem:

Ich habe eine WAV-Datei geparst.

Sie enthält einen Ton der länge t ms, die Abtastfrequenz ist a Hz. Damit ist die Anzahl der Abtastungen n=t*a/1000.
Die WAV-Datei enthält einen Sinuston von f Hz.

1. Problem: Eine FFT kann nur mit 2^m (0<=m<unendlich) Abtastungen arbeiten. Meine Lösung: Anhängen von Nullen, bis die Zahl der Abtastungen eine Zweierpotenz ist.
2. Problem: Erhalten einer Spitze. Ich nehme hierfür einfach den Maximalwert aus dem Array.
3. Problem: Umrechnen des Wertes in eine Frequenz.

Hier habe ich jetzt das Problem, dass ich nicht weiß, wie ich das umrechnen soll. Meine erste Lösung wäre gewesen Arrayindex*a/length(Array). Das funktioniert erwartungsgemäß überhaupt nicht und ich erhalte unsinnige Werte, die sich außerdem verändern, je nachdem, wie lange der Abschnitt des Sinustons ist, den ich analysiere.

Wo liegen meine Fehler?

EDIT: Heureka, es funktioniert. Ich geb euch allen ne Runde an der DP-Bar aus.

sirius 30. Jan 2007 07:53

Re: Problem bei FFT
 
Zitat:

EDIT: Heureka, es funktioniert. Ich geb euch allen ne Runde an der DP-Bar aus.
Ich nehme an, dass ich nicht mehr direkt antworten brauche.

Trotzdem noch ein paar Bemerkungen zur FFT/DFT: Da du sie anscheinend das erste Mal verwendest.

Zitat:

1. Problem: Eine FFT kann nur mit 2^m (0<=m<unendlich) Abtastungen arbeiten. Meine Lösung: Anhängen von Nullen, bis die Zahl der Abtastungen eine Zweierpotenz ist.
Mit dem Anhängen von Nullen verfälschst du das Ergebnis. Besonders der Knick an der Stelle, wo die Nullen anfangen, bringt dir Frequenzen ins Spektrum, die du so nicht hättest. Teste das mal an dem einfachen 10Hz-Sinus.
Dem kannst du mit einer DFT aus dem Weg gehen. Die ist ein bisschen einfacher zu programmieren. Und in Zeiten von 3GHz-Prozessoren dürfte der Zeitunterschied sehr gering sein.

Zitat:

2. Problem: Erhalten einer Spitze. Ich nehme hierfür einfach den Maximalwert aus dem Array.
Da weis ich nicht, warum und wofür.

Zitat:

3. Problem: Umrechnen des Wertes in eine Frequenz.
Hast du anscheinend hinbekommen. Ansonsten stehts ein paar Beiträge weiter oben.


Zitat:

Sie enthält einen Ton der länge t ms, die Abtastfrequenz ist a Hz. Damit ist die Anzahl der Abtastungen n=t*a/1000.
Die WAV-Datei enthält einen Sinuston von f Hz.
Ok, Anwendung der FFT/DFT:
Du hast einen bestimmten Zeitabschnitt eines Signals und willst wissen, welche Frequenzanteile mit welcher Amplitude und welcher Phasenlage in dem Signal sind. Erweiterung für unser obiges Bsp:
Delphi-Quellcode:
for n:=0 to 1023 do a[n]:=1+5*sin(2*pi*10*n/1000)+8*sin(2*pi*80/1000);
So jetzt hast du neben den 10Hz auch noch einmal 80Hz mit Amplitude 8 und 0Hz (also Gleichanteil) von 1.
Das sollte nach der FFT auch wieder herauskommen.
In dieser Form kann man quasi jedes Signal aus seinen einzelnen Schwingungen zusammensetzen. Das kann auch ein Rechtecksignal sein, oder ein Dreieck, oder eine e-Funktion. Kannst ja mal alles testen, welches Spektrum da so herauskommt.
Zu dem Beispiel kann man noch ein Phasenlage hinzubringen (also den Sinus etwas verschieben):
Delphi-Quellcode:
for n:=0 to 1023 do a[n]:=1+5*sin(2*pi*10*n/1000+pi/2)+8*sin(2*pi*80/1000);
Ich hab die 10Hz mal um 90° verschoben. Das bekommst du aus der FFT heraus, wenn du die Differenz der Werte von arctan(Im/Re) auswertest.

Dementsprechend kannst du deinen Auswertezeitraum so festlegen, dass er von der Länge her einer Zweierpotenz entspricht(z.B. 1024 Werte). Wenn da dein Sinuston mit f Hz drinn ist, solltest du den auch im Sprektrum sehen, neben vielen anderen Tönen.
Jetzt hast du zwei Möglichkeiten
-gleitende FFT: Du verschiebst dein FFT-Fenster nicht um 1024 Werte weiter für die nächste Auswertung, sondern nur um 1, 10 oder 100
-nicht gleitend: Du verschiebst es halt um 1024 Werte



Jetzt etwas Grundsätzliches:
Eine Fourieranalyse ist etwas ganz Tolles. Aber sie ist nicht der Weisheit letzter Schluss. Sie ist eigentlich nur der Einstieg in die Signalanalyse. Folgende Probleme bei der FFT fallen mir spontan ein:
1. Die FFT ist natürlich diskret (deswegen haben wir nur für bestimmte Frequenzen den richtigen Wert, alle anderen Frequenzen verteilen sich mit auf die Umliegenden (wie wir bei 10Hz und 1024 Abtastwerten ja gesehen haben)
Lösung: Du machst für Frequenzen, die du exakt haben möchtest eine eigene DFT, wo die Anzahl der Abtastwerte ein Vielfaches der zu untersuchenden Frequenz ist. (Geht natürlich nur, wenn du auf bestimmte Frequenzen testen willst/kannst.)
2. Wenn du dir aus deinem Signal die 1024 Werte nimmst, bekommst du nur gute Ergebnisse, wenn du dieses Fenster quasi x-mal aneinander hängst und danach keine Sprünge im Signal sind (an den Fenstergrenzen).
Lösung:Fensterfunktionen
3. Du wirst es nie schaffen, alle Frequenzen exakt aus dem Signal herauszubekommen (ausser es ist so sauber, wie in unserem Beispiel), dass muss dir bewusst sein. Es befassen sich x Bücher und dahinter Wissenschaftler mit diesem Thema der Signalanalyse. Die FFT ist ein Werkzeug, aber kein Perfektes. Prony-Methode ist z.B. ein anderes. die Methode geht dann über Differentialgleichungen. Und hat natürlich auch wieder Nachteile.


Edit:
-Grobe Rechtschreibfehler korrigiert
-Für die Analyse von Musik um bunte Bildchen darzustellen, à la Visualisierung in diversen Media-Playern reicht die FFT(DFT) aus.

Edit2: Hier ist auch noch ein schöner Link, um bildhaft zu zeigen, was Knicke im Signal bedeuten (deine Nullen oder falsche Fensterung)

negaH 30. Jan 2007 13:48

Re: Problem bei FFT
 
Du möchtest nur wenige und vorher bekannnten Frequenzen aus deinem Signal auswerten ?

Dann gibt es noch andere Möglichkeiten effektiver zum Ziel zu kommmen.

- IIR, FIR Filter können Banpässe,High/Lowpass, Notch und andere Filter sein. Sie dämpfen oder verstärken quasi ein definierbares Frequenzband
- Digitale Lock-In-Amplifier. Das sind sogenannte PSD->Phase Sensitive Devices oder auch Synchrone Gleichrichter genannt. Es gibt viele Namen für diese Methode. Sie können aber eine exakte Frequenz/Codesequenz/Spreadspektrum herausfiltern bzw. den Gleichstromanteil und Phasenlage dieser gesuchten Frequenz im vorhandenen Signalgemisch ausrechnen. Damit kann man zb. aus so stark verrauschten/gestörten Signalen die Nutzdaten/Frequenzen noch rausfinden selbst wenn sie nur noch Bruchteile in der Amplitude betragen. Fast jede neuere Funktechnik basiert auf solchen Methoden, zb. Bluetooth, ZigBee, GSM, GPS, Radar wären ohne nicht möglich.

Hier im Forum habe ich schon mal erklärt wie man in Software einen solchen Lookin Amplifier baut, suche mal danach. Ich selber habe damit DTMF Tonsequenzen (töne beim Wählen am Telefon) dekoriert, in Echtzeit. Der Vorteil ist dabei das diese Methode präziser und performanter als eine FFT ist. Eine FFT als Spekrumanalyse ist immer ein Breitbandgeschoss.

Die Frage ist also ob du wirklich das komplette Spektrum benötigst oder nur ganz spezielle Frequenzen. Je nach Antwort dann FFT oder Signalprozessing mit Filtern.


Gruß Hagen

sirius 30. Jan 2007 17:13

Re: Problem bei FFT
 
Hallo Hagen,

Der Lookin-Verstärker macht doch nix anderes als DFT auf einer Frequenz.
Du multiplizierst dein Eingangssignal mit einem Referenzsignal bekannter Frequenz. Genau dasselbe macht die DFT. Die macht es allerdings iterativ für alle Frequnezen die in das Zeitfenster passen.

Damit ist natürlich, der zeitliche Aufwand erheblich kürzer gegenüber einer DFT. Außerdem, und das ist das Wichtigste, lässt sich ein Look-In-Verstärker recht einfach hardwareseitig zusammenbauen (im Vergleich zu einer FFT) und ist, wie auch die Softwarevariante, sehr fix.

negaH 31. Jan 2007 11:03

Re: Problem bei FFT
 
Hi Sirius,

ich habe nicht das Gegenteil behauptet ;) Auch die IIR/FIR Filter lassen sich auf die Theorien der Fourier Transformation zurückführen.

Entscheidend ist aber was anderes: Wie versteht ein Laie/Mensch am schnellsten eine Technologie ? Und da muß ich sagen das mir persönlich die Theorien der Lookin-Amplifiers, PSDs, FIR, IIR viel leichter nachvollziehbar waren als die der FFT. Obwohl ich erst mit der FFT angefangen habe.

Es gibt aber auch wesentliche Unterschiede. Ein Lookin-Amplifier kann zb. mit jeder dynamischen Frequenzform arbeiten. Dh. statt einer Sinusfrequenz mit fester Frequenz im Zeitspektrum kann ein Lookin Amlifier/PSD mit einer beliebigen Signalform, zb. ein Code basierend auf einem Bakercode, arbeiten. Das benutzt zb. die Radartechnoogie oder das Speadspektrum im WLAN. Sowas per FFT machen zu wollen dürfte sehr schwierig sein, ich wüsste jetzt nicht wie das machbar ist.

Gruß Hagen

3_of_8 31. Jan 2007 11:59

Re: Problem bei FFT
 
Ich möchte eine große Anzahl von Frequenzen auf einem Spektrum von ~5000-8000 Hz überprüfen. Also ist das wohl eher ungeeignet.

sirius 31. Jan 2007 12:02

Re: Problem bei FFT
 
Zitat:

Zitat von negaH
ich habe nicht das Gegenteil behauptet ;)

Ich weis.

Zitat:

Zitat von negaH
Auch die IIR/FIR Filter lassen sich auf die Theorien der Fourier Transformation zurückführen.

Wenn man es so nimmt, lässt sich auch Prony darauf zurückführen (ich habs selber noch nicht ausprobiert, wurde mir aber gesagt)
Allerdings ist ein (Dual-) Look-In-Verstärker exakt DFT. Ob man nun mit 2 sinussen (Was ist eigentlich die Mehrzahl von sinus?) mit einer Phasen-Verschiebung von 90° multipliziert oder mit einer Komplexen Zahl, die sich mit derselben Frequenz auf dem Einheitskreis dreht... Es ist wirklich haargenau dasselbe. Nur die DFT macht es als hintereinanderweg für alle Frequenzen.

Zitat:

Zitat von negaH
Entscheidend ist aber was anderes: Wie versteht ein Laie/Mensch am schnellsten eine Technologie ? Und da muß ich sagen das mir persönlich die Theorien der Lookin-Amplifiers, PSDs, FIR, IIR viel leichter nachvollziehbar waren als die der FFT. Obwohl ich erst mit der FFT angefangen habe.

Und genau deswegen hab ich es nochmal ergänzt, dass der LookIn-Verstärker eben die DFT für eine Frequenz ist. Weiter oben hab ich ja auch geschrieben, dass zum Verständnis des ganzen, eine Implementierung einer DFT besser ist, als gleich eine FFT zu nehmen. (Was ja in einem anderen Beitrag/Thread auch beherzigt wurde)


Zitat:

Zitat von negaH
Es gibt aber auch wesentliche Unterschiede. Ein Lookin-Amplifier kann zb. mit jeder dynamischen Frequenzform arbeiten. Dh. statt einer Sinusfrequenz mit fester Frequenz im Zeitspektrum kann ein Lookin Amlifier/PSD mit einer beliebigen Signalform, zb. ein Code basierend auf einem Bakercode, arbeiten. Das benutzt zb. die Radartechnoogie oder das Speadspektrum im WLAN. Sowas per FFT machen zu wollen dürfte sehr schwierig sein, ich wüsste jetzt nicht wie das machbar ist.

Natürlich kann ich auch eine komplexe Funktion erstellen, die im Zeitberaich jedes beliebige Signal nachbildet und das durch eine (dann Pseudo)-DFT schicken. Und wenn das Signal nicht ganz chaotisch ist, ergeben sich auch wieder Dopplungen, sodass man (à la FFT) abkürzen kann. Aber hier ist, wie du auch schon sagtest, der Unterschied, ob ich ein Spektrum haben will, oder nur eine Frequenz/Frequenzfolge. Und dann brauch ich auch keine (Pseudo-)FFT entwickeln. Und wahrscheinlich gibts sowas schon, nur unter einem ganz anderen Namen.... :wink:

3_of_8 31. Jan 2007 14:26

Re: Problem bei FFT
 
Das ist meine momentan (funktionierende) Implementation einer DFT. Wenn möglich wird eine FFT angewandt. Ich empfehle, das ganze nicht mit mehr als 2000 Werten aufzurufen, es sei denn, die Anzahl der Werte ist eine Zweierpotenz oder lässt sich sehr oft durch 2 teilen.

Aufgerufen wird das einfach mit DFT(a), wobei a ein Array of Integer, Single oder ein TComplexArray ist.

Nach dem Aufruf enthält das Array die Amplitudenwerte der einzelnen Frequenzen, in Index 1 steht der Wert der Frequenz (Samplingrate/Abtastwerte) Hz, in Index 2 2*(Samplingrate/Abtastwerte) Hz und in Index I steht der Wert für I*(Samplingrate/Abtastwerte) Hz. Man sollte nur Werte bis zum Index (Abtastwerte/2), also bis (Samplingrate/2) Hz, der sogenannten Nyquist-Frequenz abfragen, da einem ansonsten der Alias-Effekt auftritt.

(Vielleicht wäre das was für die CL?)

Delphi-Quellcode:
unit complex;

interface

uses Math;

type
  TComplex=record
    re, im: Extended;
  end;

  TComplexArray=array of TComplex;

function AddC(a, b: TComplex): TComplex; overload;
function AddC(a: TComplex; b: Single): TComplex; overload;
function SubC(a, b: TComplex): TComplex; overload;
function SubC(a: TComplex; b: Single): TComplex; overload;
function MulC(a, b: TComplex): TComplex; overload;
function MulC(a: TComplex; b: Single): TComplex; overload;
function MakeC(re, im: Single): TComplex;

procedure DFT(var a: TComplexArray); overload;
procedure DFT(var a: array of Single); overload;
procedure DFT(var a: array of Integer); overload;

implementation

function AddC(a, b: TComplex): TComplex;
begin
  Result.re:=a.re+b.re;
  Result.im:=a.im+b.im;
end;

function AddC(a: TComplex; b: Single): TComplex;
begin
  Result.re:=a.re+b;
  Result.im:=a.im;
end;

function SubC(a, b: TComplex): TComplex;
begin
  Result.re:=a.re-b.re;
  Result.im:=a.im-b.im;
end;

function SubC(a: TComplex; b: Single): TComplex;
begin
  Result.re:=a.re-b;
  Result.im:=a.im;
end;

function MulC(a, b: TComplex): TComplex;
begin
  Result.re:=a.re*b.re-a.im*b.im;
  Result.im:=a.re*b.im+a.im*b.re;
end;

function MulC(a: TComplex; b: Single): TComplex;
begin
  Result.re:=a.re*b;
  Result.im:=a.im*b;
end;

function MakeC(re, im: Single): TComplex;
begin
  Result.re:=re;
  Result.im:=im;
end;


procedure shuffle(var a: TComplexArray; n, lo: Integer);
var I, m: Integer;
    b: TComplexArray;
begin
  m:=n shr 1;
  setlength(b, m);
  for I:=0 to m-1 do
    b[i]:=a[lo+i];
  for I:=0 to m-1 do
    a[lo+i+i+1]:=a[lo+i+m];
  for I:=0 to m-1 do
    a[lo+i+i]:=b[i];
end;

procedure DoDFT(var a: TComplexArray; n, lo: Integer; w: TComplex);
var b, f: array of TComplex;
    I, J, index: Integer;
begin
  setlength(b, n);
  for I:=0 to n-1 do
  begin
    b[I]:=a[I+lo];
    a[I+lo]:=MakeC(0, 0);
  end;
  setlength(f, n);
  f[0]:=MakeC(1, 0);
  f[1]:=w;
  for I:=2 to n-1 do
    f[I]:=MulC(f[I-1], w);
  for I:=0 to n-1 do
  begin
    index:=0;
    for J:=0 to n-1 do
    begin
      a[I+lo]:=AddC(a[I+lo], MulC(b[J], f[index]));
      inc(index, I);
      if index>n then dec(index, n);
    end;
  end;
end;

procedure DoFFT(var a: TComplexArray; n, lo: Integer; w: TComplex);
var I, m: Integer;
    z, v, h: TComplex;
begin
  if n and (n-1)=0 then
  begin
    if n>1 then
    begin
        m:=n shr 1;
        z:=MakeC(1, 0);
        for I:=lo to lo+m-1 do
        begin
            h:=SubC(a[i], a[i+m]);
            a[i]:=AddC(a[i],a[i+m]);
            a[i+m]:=MulC(h,z);
            z:=MulC(z,w);
        end;
        v:=MulC(w,w);
        DoFFT(a, m, lo, v);
        DoFFT(a, m, lo+m, v);
        shuffle(a, n, lo);
    end;
  end else if n>1 then
  begin
    DoDFT(a, n, lo, w);
  end;
end;

procedure DFT(var a: TComplexArray);
begin
    DoFFT(a, length(a), 0, MakeC(cos(2*Pi/length(a)),
        sin(2*Pi/length(a))))
end;

procedure DFT(var a: array of Single);
var I, index: Integer;
    b: TComplexArray;
begin
  setlength(b, length(a));
  for I:=0 to high(a) do b[I]:=MakeC(a[I], 0);
    DoFFT(b, length(b), 0, MakeC(cos(2*Pi/length(b)),
        sin(2*Pi/length(b))));
  for I:=0 to high(b) do a[I]:=sqrt(sqr(b[I].re)+sqr(b[I].im));
end;

procedure DFT(var a: array of Integer);
var I: Integer;
    b: TComplexArray;
begin
  setlength(b, length(a));
  for I:=0 to high(a) do b[I]:=MakeC(a[I], 0);
    DoFFT(b, length(b), 0, MakeC(cos(2*Pi/length(b)),
        sin(2*Pi/length(b))));
  for I:=0 to high(b) do a[I]:=trunc(sqrt(sqr(b[I].re)+sqr(b[I].im)));
end;

end.
EDIT: Hier noch eine Funktion zum Analysieren der vorherrschenden Frequenz in einem Tonabschnitt.
Delphi-Quellcode:
function GetFrequency(Data: array of Single; SampleRate, SampleIndex,
    Samples: Integer): Integer;
var I, n, max: Integer;
    a: array of Single;
begin
  max:=0;
  if length(Data)-SampleIndex<Samples then
    raise EAccessViolation.Create('Sound index or length out of bounds.');
  setlength(a, Samples);
  for I:=0 to Samples-1 do
    a[I]:=Data[SampleIndex+I];
  dft(a);
  for I:=0 to (n shr 1)-1 do if a[I]>a[max] then
  begin
    max:=I;
  end;
  Result:=trunc(SampleRate/Samples*max);
end;

sirius 31. Jan 2007 14:59

Re: Problem bei FFT
 
Klappt das? Die DFT so in die Rekursion der FFT zu basteln?

Edit: Ja, müsste :stupid: Edit2: Man könnte es natürlich auch vor der Rekursion überprüfen.

Edit2: zu GetFrequency
Und immer daran denken, dass der absolute Fehler (durch digitalisierung) bei SampleRate/Samples/2 liegt :!:
Von anderen Fehlern habe ich schon genug gesprochen, dürften aber für diese (weniger kritische) Analyse nicht interessant sein.

SunBlack 19. Mär 2008 08:06

Re: Problem bei FFT
 
Hallo 3_of_8,

ich hab mir gerade deinen Code angeguckt um zu verstehen, wie die DFt genau funktioniert (mit Wiki werde ich da nicht schlau :( ). Allerdings habe ich da ein Problem. Wie soll man den real- und Imaginaryteil verstehen? Also kann man die Daten irgendwie weiter gebrauchen, oder bringt einem immer nur der Pythagoras da etwas?

Gruß
SunBlack

sirius 19. Mär 2008 08:31

Re: Problem bei FFT
 
Es ist schon wichtig, dass es eine komplexe Zahl ist (kommt ja auch aus dem algorithmus).
Eine komplexe Zahl besteht immer aus Betrag und Phasenwinkel. Den Betrag bekommst du ja hier aus dem Pythagoras. Den Winkel aus dem Tangens (Arcustangens).
Letztenendes bringt die ja die DFT den Anteil des Sinus für jeden Frequenzanteil. Und der kann ja auch verschoben sein, dass ist dann der Winkel.

Jedes beliebige Signal f setzt sich ja aus der Summe:
Code:
f(t) = A_1 * sin (w_1*t + phi_1)
     + A_2 * sin (w_2*t + phi_2)
     + A_3 * sin (w_3*t + phi_3)
     + ...
zusammen. dabei sind die w_x deine Frequenzen, A_x die dazugehörigen Amplituden (aus Pythagoras) und phi_x der Phasenwinkel (=arctan(Imag/Real))

Edit: Achtung: Den winkel musst du auch noch wie den Betrag bezüglich des Aliasing korrigieren.

SunBlack 19. Mär 2008 08:54

Re: Problem bei FFT
 
Zitat:

Zitat von sirius
Eine komplexe Zahl besteht immer aus Betrag und Phasenwinkel. Den Betrag bekommst du ja hier aus dem Pythagoras. Den Winkel aus dem Tangens (Arcustangens).

Das drt Betrag die Amplitude ist, habe ich hier schon rausgelesen ;). Mir gehts eher um etwas anderes. Und zwar zeichnet man ja komplexe Zahlen eigentlich immer ro, dass der reele Teil die x-Achse ist und der imaginäre die y-Achse. Wie könnte man die beiden Ahcsen beschriften jetzt inhaltlich beschriften?


Aber sagt mal, bin ich blind oder ist da nicht nen Fehler im Algo drin?

Delphi-Quellcode:
function GetFrequency(Data: array of Single; SampleRate, SampleIndex,
    Samples: Integer): Integer;
var I, [color=#ff007f]n[/color], max: Integer;
    a: array of Single;
begin
  max:=0;
  if length(Data)-SampleIndex<Samples then
    raise EAccessViolation.Create('Sound index or length out of bounds.');
  setlength(a, Samples);
  for I:=0 to Samples-1 do
    a[I]:=Data[SampleIndex+I];
  dft(a);
  for I:=0 to ([color=#ff007f]n[/color] shr 1)-1 do if a[I]>a[max] then
  begin
    max:=I;
  end;
  Result:=trunc(SampleRate/Samples*max);
end;
Aber n wird nirgens gesetzt.

3_of_8 19. Mär 2008 09:01

Re: Problem bei FFT
 
Das ist jetzt mal ne gute Frage... Könnte ein C&P-Fehler sein, der Original-Source ist noch etwas komplexer, da ich für meine Anwendung noch mehr brauche, da hab ich diesen Beispielcode rauskopiert.

Ersetze n einfach durch Samples und hau es aus der Variablendeklaration raus.

Achja, und, die Achsen in der Gaußschen Ebene markiert man mit Re und Im, nach den Funktionen Re(z) und Im(z). Und die Amplitude ist nicht der Betrag, wie kommst du darauf?

Der Betrag eines Elements I des Ergebnisvektors entspricht dem Anteil der Frequenz 2*I*SampleRate/Samples.

SunBlack 19. Mär 2008 09:13

Re: Problem bei FFT
 
Ich meine den Pythagoras ;).

Gibts eigentlich eine einfache Variante um aus dem Ergebnis einer DFT wieder den Ursprung herzustellen (z.B. mit gefilterten Frequenzen)? Denn soweit ich mich entsinne, gibt es ja noch eine inverse FFT.

sirius 19. Mär 2008 10:13

Re: Problem bei FFT
 
Ein komplese Zahl kannst du darstellen als:
Code:
 x + y * i                   | mit x=Realteil und y=Imaginärteil
 r * e ^(i * phi)            | mit r=Betrag und phi=Phase
 r* (cos(phi) + i * sin(phi)) |     -"-
Bei der FFT interessiert dich nicht Real- oder Imaginärteil sondern Betrag und Phase

Und wie du es rückwärts rechnest, habe ich schon oben beschrieben. Du musst dir anscheinend mal über die Bedeutung der Fourierttransformation klar werden. Denn was man allgemein als Rücktransformation nennt, ist eigentlich der Ausgangspunkt.
Die Ausgangslage ist ja, dass man jedes Signal aus unendlich vielen Sinussignalen unterschiedlicher Frequenz zusammensetzen kann.
Zitat:

Code:
f(t) = A_1 * sin (w_1*t + phi_1)
     + A_2 * sin (w_2*t + phi_2)
     + A_3 * sin (w_3*t + phi_3)
     + ...

Und die daraus resultierende Frage ist eben, kann man aus dem fertigen Signal wieder zurück auf die Ausgangsschwingungen rechnen. Und das ist die Fouriertransformation (und für konkrete Messwerte dann die DFT/FFT)

SunBlack 19. Mär 2008 10:49

Re: Problem bei FFT
 
Mir ist die Fourier-Transformation eugentlich nur Fourier-Analyse, also zur Bestimmung des Frequenzspektrum bekannt. Von daher habe ich an der Stelle ein Problem, den Ursprung wiederherzustellen, denn man weiß ja nicht, wann eine Frequenz vorkam, und wie rum.
Wenn man z.B. eine beliebige Musikdatei analysiert erhält man ja ein Spektrum. Aber wie willst du aus diesem Spektrum wieder den Ursprung herstellen? Denn wann welche Frequenz auftritt, wird ja imho nicht gespeichert.

Das nächste Problem, welches ich dabei habe: Nehmen wir mal an, man hat eine ganze Datei lang nur eine einfache Sinusschwingung. Kann man anhand der ermittelten Frequenz im nachhinein noch sagen, ob die Kurve zuerst ins negative ging oder zuerst ins positive?

Medium 19. Mär 2008 11:08

Re: Problem bei FFT
 
Dafür ist die Phase doch gerade da. Und es muss keine zeitlichen Informationen geben, da sich die klanglichen Unterschiede über die Zeit durch die Überlagerung der Sinuswellen ergeben.

SunBlack 19. Mär 2008 11:17

Re: Problem bei FFT
 
Ich glaube, ich habe gerade nen Denkfehler :cry: .

Wenn ich z.B. eine Datei habe, in der die ganze Zeit 60Hz schwingen. Und am Anfang und am Ende, aber nicht in der Mitte, werden noch 45 Hz überlagert. Woher bekomme ich dann die Informationen über die beiden 45 Hz-Startpositionen? Und wenn die die erste mit 45° anfängt und die zweite mit 290°, wo kann ich die verschiedenen Phasen ablesen? (Ich steh gerade wahrscheinlich aufm Schlauch ;) )

sirius 19. Mär 2008 12:17

Re: Problem bei FFT
 
Liste der Anhänge anzeigen (Anzahl: 2)
Zum allgemeinen Verständnis.

Schau dir mal Bild 1 (sin1.png) an! In dem ersten Plot ist ein 50Hz-Sinus und in dem zweiten Plot ein 150Hz Sinus, wobei die Amplitude bei den 150Hz etwas geringer ist. Die Phase beider Schwingungen ist identisch. Sie fangen beide am Anfang mit 0 an und laufen in positive Richtung los. Im dritten Plot ist die Summe beider Funktionen gezeichnet. Wichtig dabei ist, dass die Summe aus reinen Sinus-Funktionen erstellt wurde.
Die Aufgabe der FFT besteht darin, wenn man nur den unteren Signalverlauf hat, die beiden Ausgangsfunktionen wiederherzustellen bzw. die Parameter der Sinus-Funktionen zu bekommen. Und eine Sinus-Funktion braucht eine Amplitude und einen Phasenwinkel. Also genau das, was die komplexe Zahl aussagt. Und das bekommst du aus der FFT (für diskrete Abtastwerte) heraus.

In dem zweiten Bild sin2.png habe ich noch dargestellt, was eben die Phase bedeutet. Hier ist die 150Hz-Schwingung um pi/4 verschoben.


So, nun habe ich nur 2 Schwingungen addiert (also zwei unterschiedliche Frequenzen). Es gibt neben 50Hz und 150Hz natürlich noch unendlich viele weitere Frequenzen. Und du kannst jedes (periodische) Signal in genau solche Frequenzanteile, also in solche Sinus-Funktionen, zerlegen. Im Allgemeinen sind es mehr als nur zwei Anteile.


Edit: Ein Wort geändert

Medium 19. Mär 2008 12:28

Re: Problem bei FFT
 
Die FA liefert überhaupt keine Information über ein wann. Es ist ja gerade die Aufgabe, ein Signal von einer Zeit/Amplituden Darstellung in eine Frequenz/Phasen/Ausprägung Darstellung zu überführen.
Wenn du ein Sample nimmst, in dem die Hälfte der Zeit 50Hz brummen, die andere hälfte 70Hz, dann bekommst du nicht einfach nur 50 und 70Hz Peaks im Spektrum, sondern nahezu jede weitere Frequenz ist auch mit von der Partie, und zwar so, dass wenn man sie überlagert, wieder deine 50 und 70Hz herauskommen.

sirius 19. Mär 2008 12:33

Re: Problem bei FFT
 
Zitat:

Zitat von SunBlack
Wenn ich z.B. eine Datei habe, in der die ganze Zeit 60Hz schwingen. Und am Anfang und am Ende, aber nicht in der Mitte, werden noch 45 Hz überlagert. Woher bekomme ich dann die Informationen über die beiden 45 Hz-Startpositionen? Und wenn die die erste mit 45° anfängt und die zweite mit 290°, wo kann ich die verschiedenen Phasen ablesen? (Ich steh gerade wahrscheinlich aufm Schlauch ;) )

Du darfst sowieso nicht das gesamte Signal auf einmal durch die FFT schieben, sondern immer nur ein Zeitfenster von ..sagen wir.. 20ms (je nach Abtastrate, gewünschter Genauigkeit), dann bekommst du einen Zeitverlauf (Ein Punkt aller 20ms) für die 45Hz und einen für die 60Hz. Und dann kannst du schauen, wann welche Frequenz zu hören/sehen/.. ist.


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:15 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz