Entwickler-Ecke

Algorithmen, Optimierung und Assembler - Frequenzanalyse


GTA-Place - Di 28.02.06 12:42
Titel: Frequenzanalyse
Hallo.

Ich brauche für den MIF (MusicInfoFinder) einen gescheiten Algorithmus. Bis jetzt arbeite ich mit der Bass.dll und habe das ganze so gemacht:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
function TMainForm.AnalyzeSong(Song: PChar): Extended;
var
  FFTData: TFFTData;
  FreqSch: Integer;
  Round:   Integer;
  Teiler:  Integer;
  SChan:   DWord;
begin
  SChan := BASS_StreamCreateFile(False, Song, 00,
             BASS_STREAM_DECODE AND BASS_STREAM_AUTOFREE);

  BASS_SetConfig(BASS_CONFIG_BUFFER, 5000);

  try
    Result := 0;
    Round  := 0;
    Teiler := 0;

    while (Result = 0OR (Round < 10000do
    begin
      BASS_ChannelGetData(SChan, @FFTData, BASS_DATA_FFT2048);

      for FreqSch := 0 to 1023 do
        Result := Result + (FFTData[FreqSch] * 44100 / 1024);

      if not (Result = 0then
      begin
        inc(Round);
        inc(Teiler, 1024);
      end;
    end;

    Result := Result / Teiler;
  except
    Result := 0;
  end;

  BASS_SetConfig(BASS_CONFIG_BUFFER, 500);

  BASS_ChannelStop(SChan);
  BASS_StreamFree(SChan);
end;

(FFTData = Array of DWORD)

Aber jede Analyse vom selben Song, gibt mir einen anderen Wert aus. Woran liegt das? Ich müsste es erstmal hinbekommen, dass jedesmal der selbe Wert rauskommt.

Danach muss ich mich dann um nen gescheiten Algo kümmern.

Gruß
GTA-Place


F34r0fTh3D4rk - Di 28.02.06 12:50

Ein Logarithmus ist eine Mathematische Funktion, siehe auch: http://de.wikipedia.org/wiki/Logarithmus


AXMD - Di 28.02.06 13:23

Einen kleines Teil des Frequenzbereichs dazu verwenden, Musikstücke zu vergleichen, halte ich für wenig sinnvoll. Wenn dann solltest du das über einen größeren Bereich hinwegmachen; wobei der Frequenzbereich sowieso nichtssagend sein kann - wenn du einmal mit 64 und einmal mit 128kBit kodierst und dir den Frequenzbereich ansiehst, wirst du sehen, was ich meine.

AXMD


GTA-Place - Mi 01.03.06 00:20


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
function TMainForm.AnalyzeSong(Song: PChar): Extended;
var
  FFTData: TFFTData;
  FreqSch: Integer;
  Round:   Integer;
  SChan:   DWord;
begin
  SChan := BASS_StreamCreateFile(False, Song, 00, BASS_STREAM_DECODE);

  try
    Result := 0;
    Round  := 0;

    while (Result = 0OR (Round < 100do
    begin
      BASS_ChannelGetData(SChan, @FFTData, BASS_DATA_FFT2048);

      for FreqSch := 0 to 1023 do
        Result := Result + FFTData[FreqSch];

      if not (Result = 0then
        inc(Round);
    end;

    Result := Result / (1024 * 100);
  except
    Result := 0;
  end;

  BASS_StreamFree(SChan);
end;


Jetzt kommt wenigstens immer das selbe raus für die gleiche Datei.


Allesquarks - Mi 01.03.06 11:49

Erhälts du die Musik digital oder analog. Denn eine Fouriertransformation ist eine exakte Mathematische Abbildung und sollte immer zu gleichen Resultaten führen, ebenso genähert über eine schnelle Fouriertransformation (FFT), da der Algorithmus immer das gleiche tuen sollte. Wenn du also andere Fourierkoeffizienten erhälst würde ich zunächst da weiterstöbern. Ein Vergleich verschiedener Musiksongs über die Fourierkoeffizienten würde ich zunächst nicht als abwegig definieren, allerdings würde ich mich für deren Analyse bei Instrumenten wie der Varianz relativ zum Mittelwert bedienen. Vielleicht das ganze vorher noch logarithmieren (wegen der Frequenz-Tonhöhe-Abhängigkeit).

Edit: Sorry hab Kommentar unter dem letzten Beitrag nicht gelesen. Macht meine Ausführungen aber nicht nichtig, sondern nur schon gelöst. Nehme mal an, dass es sich dann auschließlich um digitale Musik handelt.
Ich würde jetzt vorschlagen, dass du ein Lied mal um ne Oktave transponierst und dir dann die Koeffiezienten anschaust. Würde mal nen Bischen rumstöbern, wie die sich verhalten.


delfiphan - Do 02.03.06 05:15

Ich würde dir aber abraten anzufangen einfach irgendetwas zu tun und daraus irgendwie irgendetwas zu basteln. Denn wenn du nicht genau weisst, was du tust, wird es schlussendlich nicht (oder nur extrem schlecht) funktionieren und du wirst am Schluss nichts gelernt haben.

Digitale Signalverarbeitung erfordert gute mathematische Kenntnisse über komplexe Integrale, Faltungen von Funktionen, usw..

Eine Reihe von guten Papers findest du auf der Seite der "International Conference on Music Information Retrieval" (google).

PS: Die Bass.dll mag zwar schön sein und zudem einfach zu bedienen - die Ausgabe der Funktion BASS_ChannelGetData liefert aber ganz sicher kein FFT sondern wohl eher das Powerspektrum, dann noch irgendwie gestreckt und gerundet. Who knows. Jedenfalls würde ich stark bezweifeln, dass die für eine gute Musikerkennung geeignet ist. Ist wohl eher für ein bisschen "coole Graphik" in Musikplayern entworfen...


Heiko - Do 02.03.06 08:07

user profile icondelfiphan hat folgendes geschrieben:
PS: Die Bass.dll mag zwar schön sein und zudem einfach zu bedienen - die Ausgabe der Funktion BASS_ChannelGetData liefert aber ganz sicher kein FFT sondern wohl eher das Powerspektrum, dann noch irgendwie gestreckt und gerundet. Who knows. Jedenfalls würde ich stark bezweifeln, dass die für eine gute Musikerkennung geeignet ist. Ist wohl eher für ein bisschen "coole Graphik" in Musikplayern entworfen...


Und wie gut geeignet ist fmod dafür? Also bringt es bessere Ergebnisse?


delfiphan - Do 02.03.06 21:50

fmod? Kenn ich leider nicht.


GTA-Place - Fr 03.03.06 01:37

Bass.dll hat folgendes geschrieben:
Retrieves the immediate sample data (or an FFT representation of it) of a stream or MOD music channel. Can also be used with a recording channel.


Ich check mal fmod ab.


Heiko - Fr 03.03.06 07:55

@delfiphan: http://www.fmod.de oder http://www.fmod.org


GTA-Place - Fr 03.03.06 10:57

Theoretisch darf ich FFTData[0] nicht in den Schnitt hineinrechen (Phase), oder?

Mir scheint FMOD auf den ersten Blick professioneller zu sein, da FMOD sogar auf
XBOX, GameCube, PSP und bald auch auf PS3 läuft. Die Preise sind auch viel höher
als bei der Bass.dll. Werde FMOD heute mal testen.


EDIT: Schon keine Lust mehr -_-:
- keine Delphi-Examples
- FSound_Init kennt Delphi nicht

EDIT2: Nagut, bei Version 3 funktioniert es.


delfiphan - Fr 03.03.06 21:58

Zitat:
Retrieves the immediate sample data (or an FFT representation of it) of a stream or MOD music channel. Can also be used with a recording channel.
Bevor man eine FFT macht muss man das Signal zuerst mit einer Window-Funktion "filtern" (es gibt je nach Anwendung x verschiedene Fensterfunktionen), danach erst rechnet man die FFT aus. Die FFT liefert dann ein Resultat mit komplexen Zahlen. Aus der bass-Funktion bekommt man ein Array of DWord. Hier steht weder wie das Signal gefiltert wurde, noch was das Resultat eigentlich darstellt.

PS: Für eine Frequenzanalyse würde ich kein Geld aus dem Fenster werfen. Kostenlose FFT Routinen gibt's viele (z.B. hier: http://www.delphi-forum.de/viewtopic.php?t=36027).

Moderiert von user profile iconKlabautermann: URL-Tags hinzugefügt.


GTA-Place - Sa 04.03.06 01:17

Die Bass.dll legt automatisch 'Hanning window' drüber.