Autor Beitrag
DJ Raptor
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 24

Win XP
D2005
BeitragVerfasst: Do 15.09.05 23:11 
Hallöchen,

da ich die Suche jetzt seit Tagen schon quäle und überwiegend unspezifische, veraltete oder nicht funktinierende Lösungen gefunden habe stelle ich nochmal diese Frage. Das die Analyse des Signals FFT Berechnung benötigt ist mir klar, leider übersteigt allerdings die Erstellung einer komplett eigenen Lösung meine mathematischen Kenntnisse und vor allem meine zur Verfügung stehende Zeit. Von daher die ganz konkrete Frage: Hat jemand sowas schon mal funktional in die Praxis umgesetzt und wenn ja wie (Eigenerstellung, basierend auf bass.dll oder fmod etc.) ?? Oder kennt vielleicht jemand sogar eine Open Source oder Freeware Komponente die genau das ohne Umwege ermöglicht? Die Lösung sollte für oder auf Delphi 2005 übertragbar sein. Ich freue mich über jeden Hinweis oder Unterstützung.

Greetz Raptor =)
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Do 15.09.05 23:45 
Ich glaub es gibt DLLs die das Power-Spektrum berechnen. Ich kenn die aber nicht so gut. Ich könnte dir aber erklären, wie man das mit FFT rechnet.
DJ Raptor Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 24

Win XP
D2005
BeitragVerfasst: Fr 16.09.05 12:48 
hm der begriff power spektrum sagt mir jetzt nichts, ich muss eben anhand des gesamtsignals wissen welche frequenz in Hz vorliegt. Natürlich mit einer gewissen Toleranz, da die Frequenz ja nie ganz genau exakt anliegen wird. eine erklärung für FFT wär aber natürlich auch hilfreich wobei ich dann natürlich zur Theorie auch noch einen Vorschlag zur praktischen Umsetzung bräuchte.
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Fr 16.09.05 13:32 
user profile iconDJ Raptor hat folgendes geschrieben:
hm der begriff power spektrum sagt mir jetzt nichts, ich muss eben anhand des gesamtsignals wissen welche frequenz in Hz vorliegt. Natürlich mit einer gewissen Toleranz, da die Frequenz ja nie ganz genau exakt anliegen wird. eine erklärung für FFT wär aber natürlich auch hilfreich wobei ich dann natürlich zur Theorie auch noch einen Vorschlag zur praktischen Umsetzung bräuchte.

So genau kannst du die Frequenzen sowieso nicht rausfinden. Es gibt eine mathematisch bedingte Unschärfe (welche übrigens dieselbe ist wie bei der Unschärfe bei der Quantenmechanik ;)).
Wie dem auch sei. Zunächst brauchst du eine FFT Routine. Die FFT-Funktion nimmt ein kurzes Mono-Signal (z.B. ein array of double) und transformiert ihn in den Fourier-Raum. Der Fourier-Raum ist im allgemeinen komplex und deswegen kriegst du auch ein array of complex aus der FFT-Routine raus. In den komplexen Zahlen des Arrays sind die Stärke und die Phasenverschiebung der einzelnen Frequenzanteile gespeichert. Um nun das Energie-Spektrum zu erhalten, rechnest du den Betrag der komplexen Zahlen (= Pythagoras) und quadrierst sie. Das ist eigentlich schon alles.
Die Frequenzen in der komplexen Array sind folgendermassen geordnet:
1. Eintrag = Nullverschiebung.
2. Eintrag = Grundfrequenz = 1/Signaldauer. Wenn das Mono-Signal also 0.5s lang ist, ist die Grundfrequenz 2 Hz.
3. Eintrag = 2xGrundfrequenz
4. Eintrag = 3xGrundfrequenz
etc.
Die höchste Frequenz (die sog. Nyquist-Frequenz) ist gerade die Hälfte der Abtastfrequenz (bei einem 44KHz Signal ist die höchstmögliche Frequenz 22KHz).

Praktische Umsetzung:
- Du nimmst die Wave-Daten und schneidest sie in kleine Stücke. Am besten nimmst du für die Länge eine feste Zweierpotenz. Z.B. 2048 Samples. Für jedes kleine Stück führst du dann eine Frequenzanalyse durch.
- Du nimmst so ein Stückchen und konvertierst die Daten (bei 16-bit Sound in SmallInt gegeben) in Floats (z.B. in Double)
- Du normierst die Floats (durch 32768 teilen)
- Danach multiplizierst du ein Hamming-Window drüber. Das ist wichtig, sonst kriegst du Phantomfrequenzen, weil die Wave-Form links und rechts nicht stetig ineinander übergehen.
Die Hamming-Funktion sieht folgendermassen aus:
ausblenden Delphi-Quelltext
1:
2:
for i := 0 to n-1 do
 CorrectedWavePiece[i] := OldWavePiece[i] * ((0.42 - 0.5 * cos(2.0 * pi * i / n) + 0.08 * cos(4.0 * pi * i / n)));

Wobei n = length(OldWavePiece) ist. Diese Korrekturfunktion die man drübermultipliziert bewirkt zudem eine Faltung im Frequenzraum und verschmiert so die Frequenzen ein bisschen.
- Auf dieses korrigierte Array führst du eine FFT durch und erhältst ein neues Array mit komplexen Zahlen. Das komplexe Output-Array ist halb so lang wie das reelle Input-Array. Es geht jedoch keine Information verloren, da eine komplexe Zahl ja aus zwei reellen besteht.
- Für jede komplexe Zahl berechnest du den Betrag und quadrierst diesen (Energie = Imaginärteil^2+Realteil^2).
Dann hast du für jedes Vielfache der Grundfrequenz die Energie..

Ich weiss nicht, wie einfach oder schwer es ist, das umzusetzen, wenn man noch nie mit solchen Sachen gearbeitet hat.
DJ Raptor Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 24

Win XP
D2005
BeitragVerfasst: Fr 16.09.05 14:41 
waaaaaah :roll: ok das das ganze mit höherer mathematik zu tun hat, war mir klar. aber das?? hab zwar prinzipiell annähernd verstanden wie das in der theorie funktioniert, aber für mich unmöglich das in die praxis umzusetzen. es muss doch für sowas fertige units geben oder die möglichkeit das über einfache komponenten zu lösen?? ich bin ja sicher nicht der einzige der eine solche funktion benötigt? zudem muss das ganze ja zumindest annähernd in echtzeit passieren.
GTA-Place
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: Fr 16.09.05 14:50 
Beim MusicInfoFinder hab ich das mit der Bass.dll gelößt.

_________________
"Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
DJ Raptor Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 24

Win XP
D2005
BeitragVerfasst: Fr 16.09.05 15:43 
hi, kannst du denn bitte mal genau erläutern wie du da vorgegangen bist?? Oder darf man den Sourcecode vielleicht sehen als Anhaltspunkt?? Hatte auch schon mit der bass.dll rumgespielt, aber es nicht hinbekommen das frequenzband exakt anzuzeigen. In der Demo wird ja ein sehr breites Spektrum angezeigt und das auch nur sehr ungenau. Ich muss halt nur in einem bestimmten Bereich messen und muss bis auf einen Halbton exakt unterscheiden.
GTA-Place
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: Fr 16.09.05 15:53 
Im ganzen sieht das so etwa aus:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
var
  Channel: DWord; 
begin
  Channel := BASS_StreamCreateFile(FALSE, PChar(Dateien[0].Name), 00, BASS_STREAM_DECODE);
  BASS_ChannelPlay(Channel1, False);

  GetFreqTimer.Enabled := True;
end;

ausblenden OnTimer
1:
2:
3:
4:
5:
6:
7:
8:
9:
var
  FFTData: TFFTData;
  FreqSch: Integer; 
begin
  BASS_ChannelGetData(Channel1, @FFTData, BASS_DATA_FFT1024);

  for FreqSch := 0 to X do          // X beliebige Zahl, je nach benötigter Menge der Frequenzen
    TempFreq := TempFreq + FloatToStr(FFTData[FreqSch]);
end;

Muss halt mal ein bisschen testen.

_________________
"Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
DJ Raptor Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 24

Win XP
D2005
BeitragVerfasst: Fr 16.09.05 16:25 
hmmm ok, aber die OnTimer routine versteh ich nicht ganz. Wenn ich das richtig sehe bekomme ich hier doch nur einen String aller X FFTData Array Einträge?? Dann weiß ich aber doch immer noch nicht welcher Frequenz jeder Array Eintrag von FFTData entspricht? Und welche Werte stehen überhaupt in diesem Array?
GTA-Place
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: Fr 16.09.05 16:43 
In FFTData stehen alle Frequenzen, der jetzigen Position des Audiofiles.
ausblenden Delphi-Quelltext
1:
BASS_ChannelGetData(Channel1, @FFTData, BASS_DATA_FFT1024);					

_________________
"Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
DJ Raptor Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 24

Win XP
D2005
BeitragVerfasst: Sa 17.09.05 18:02 
hmm ok, aber wo stehen die dazugehörigen Werte dieser Frequenzen. Somit hätte ich zwar eine Übersicht über alle Frequenzen der momentanen Position aber nicht wie die entsprechende Verteilung der Pegel ist.