Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi FFT Problem in verbindung mit WMP (https://www.delphipraxis.net/92675-fft-problem-verbindung-mit-wmp.html)

EWeiss 24. Mai 2007 08:34


FFT Problem in verbindung mit WMP
 
Liste der Anhänge anzeigen (Anzahl: 2)
Hallo

Hier mal meine FFT Routine..

Delphi-Quellcode:
       
function BASS_WMPVIS_Render(channel: DWORD): boolean; stdcall;

      BASS_ChannelGetData(channel, Data32, FFTSize or
                          DWORD(IfThen(ChanInfo.chans = 2,
                          BASS_DATA_FFT_INDIVIDUAL)));
                         
      if (ChanInfo.chans = 2) then
      begin
        for i := 0 to 1023 do
        try
        begin
          VisData^.frequency[0, i] :=
            Max(0, Min(1023, (Trunc(Power(Data32Pos^, FFTSAmplification) * 1023))));
          Inc(Data32Pos, FFT_SkipCount);

          VisData^.frequency[1, i] :=
            Max(0, Min(1023, (Trunc(Power(Data32Pos^, FFTSAmplification) * 1023))));
          Inc(Data32Pos, FFT_SkipCount);
        end;
        except
          Result := false;
          exit;
        end;
      end
      else
      begin
        for i := 0 to 1023 do
        begin
          VisData^.frequency[0, i] :=
            Max(0, Min(1023, (Trunc(Power(Data32Pos^, FFTSAmplification) * 1023))));
          VisData^.frequency[1, i] :=
            VisData^.frequency[0, i];
          Inc(Data32Pos, FFT_SkipCount);
        end;
      end;
     
      FreeMem(Data32);
      try
        _IWMPEffects.Render(VisData^, BassWMPVis1.ContainerHdc, pRect);
      except
        Result := false;
        exit;
      end;
     
      Result := true;
      BassFuncs^.SetError(BASS_OK);
      exit;
  end;

  Result := False;
  BassFuncs^.SetError(BASS_ERROR_MEM);

end;
Mein Problem ist nun das in dieser schleife bedingt durch TimedLevel
nur 1024 samples übergeben werden können.

Delphi-Quellcode:
      if (ChanInfo.chans = 2) then
      begin
        for i := 0 to 1023 do
        try
        begin
          VisData^.frequency[0, i] :=
            Max(0, Min(1023, (Trunc(Power(Data32Pos^, FFTSAmplification) * 1023))));
          Inc(Data32Pos, FFT_SkipCount);

          VisData^.frequency[1, i] :=
            Max(0, Min(1023, (Trunc(Power(Data32Pos^, FFTSAmplification) * 1023))));
          Inc(Data32Pos, FFT_SkipCount);
        end;
Im Original Quelltext wird aber ein VariablesArray erstellt
TimedLvl.frequency = new byte[2048];
in dem nun unabhängig von TimedLevel die Daten ausgelesen werden können.

Wie kann ich in meiner schleife den rechten Kanal trotzdem auslesen und die samples
von 1024 to 2048 übergeben damit kein rangecheck error auftritt ?

Code:
            // The first value is the DC component so we'll skip it and start at index 1
            for (int i = 1; i < 1024; i++)
            {
                try
                {
                    float val = (fft[i] * 255);

                    if (val < 0)
                        val = 0;

                    if (val > 255)
                        val = 255;

                    audioData[i] = (byte)val;
                    audioData[i + 1024] = (byte)val;
                }

                catch (Exception ex)
                {
                    Console.WriteLine("Exception occurred at index {0}", i);
                    return false;
                }
            }

            return true;
Zur zeit sieht es so aus das rechts und links die gleichen Daten übergeben werden.
Und seltsamer weise (wohl bedingt durch den rechten Kanal) einige Samples bei einigen Plugins fehlen.
Das sieht dann so aus siehe PIC die hellgrüne grundläsche die frei ist.
Müßte eigentlich mit Samples belegt sein.

Gruss Emil

Klaus01 24. Mai 2007 09:32

Re: FFT Problem in verbindung mit WMP
 
Dein
Delphi-Quellcode:
  TimedLevel = record
      frequency : array [0..1, 0..SA_BUFFER_SIZE-1] of byte;
erfasst doch 2048 Byte wenn SA_BUFFER_SIZE = 1024 ist.
Sie sind nur nicht hintereinander angeordnet sondern untereinander.

Kannst Du nicht erst die VisData.frequency[0,i] benutzen und
wenn i > 1024 ist dann VisData.frequency[1,i mod 1024].

Delphi-Quellcode:
for i:=0 to 2047 do
  VisData.frequency[i div 1024, i mod 1024]:=...
Vielleicht habe ich Dein Problem auch nicht klar verstanden.

Grüße
Klaus

EWeiss 24. Mai 2007 10:21

Re: FFT Problem in verbindung mit WMP
 
Zitat:

Zitat von Klaus01
Dein
Delphi-Quellcode:
  TimedLevel = record
      frequency : array [0..1, 0..SA_BUFFER_SIZE-1] of byte;
erfasst doch 2048 Byte wenn SA_BUFFER_SIZE = 1024 ist.
Sie sind nur nicht hintereinander angeordnet sondern untereinander.

Kannst Du nicht erst die VisData.frequency[0,i] benutzen und
wenn i > 1024 ist dann VisData.frequency[1,i mod 1024].

Delphi-Quellcode:
for i:=0 to 2047 do
  VisData.frequency[i div 1024, i mod 1024]:=...
Vielleicht habe ich Dein Problem auch nicht klar verstanden.

Grüße
Klaus

Ja 0 = 1024, 1 = 1024 := sumasumarum 2048;
Mein problem ist nur die übergabe bzw.. die position wo ich den rechten kanal abfragen(übergeben kann)
Du meinst ne if abfrage if i = 1024 then .. hmmm
kann es mal testen ob sich das so einfach umsetzen läßt (meine nicht die IF Abfrage)
aondern generell.

Delphi-Quellcode:
VisData.frequency[i div 1024, i mod 1024]:=..
gruss Emil

EWeiss 24. Mai 2007 11:05

Re: FFT Problem in verbindung mit WMP
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hi Klaus

Supi klappt bestens!
Allerdings nicht mit 'DIV'

Delphi-Quellcode:
VisData.frequency[i + 1024, i mod 1024]:=
                  Max(0, Min(1023, (Trunc(Power(Data32Pos^,
                  FFTSAmplification * 0.5) * 1023))));
Geht zwar auch, aber dann schaltest du die Samples vom rechten Kanal quasi aus[0,i]

Danke

Gruss Emil

EWeiss 25. Mai 2007 03:44

Re: FFT Problem in verbindung mit WMP
 
Hmmm klappt doch nicht!
Habe zum testen den channel auf 1 gestellt(MONO) und nicht wieder entfernt.

Nach einigen änderungen ist mir das aufgefallen und habe es geändert.
Jetzt läuft er auf 2 Kanälen stürzt aber mit einen Stack overflow ab.

Kommt keine Meldung wo der Fehler auftritt.

Irgendwie stimmt das mit VisData.frequency[i + 1024, i mod 1024]:= .. i + 1024 nicht
auch mit div geht es nicht!

Eigentlich darf hier das Array auch nicht größer als 1 sein [0..1]
Bei i + 1024 ist es sehr viel größer oder ? ;)

Delphi-Quellcode:
VisData.frequency[1, i mod 1024]:= ..
Gibt mir auch die Samples des Rechten Kanal nicht richtig zur auswertung.

Delphi-Quellcode:
VisData.frequency[i div 1024, i mod 1024]:=
i div 1024 ist eins! nur dann kann ich direkt die 1 eingeben und muss die nicht extra berechnen.


EDIT:
Das hier funktioniert 100% ist aber nur MONO bzw. 1 Kanal(links)
Delphi-Quellcode:
        for i := 0 to 1023 do
        begin
          VisData^.frequency[0, i] :=
            Max(0, Min(1023, (Trunc(Power(Data32Pos^, FFTSAmplification * 1.0) * 1023))));
          VisData^.frequency[1, i] := VisData^.frequency[0, i];
          Inc(Data32Pos, FFT_SkipCount);
        end;
gruss Emil

Klaus01 25. Mai 2007 05:57

Re: FFT Problem in verbindung mit WMP
 
Guten Morgen Emil,

Delphi-Quellcode:
for i:=0 to 2047 do
  VisData^.frequency[i div 1024, i mod 1024]:=..
war auch die Antwort auf diese Frage:

Zitat:

Wie kann ich in meiner schleife den rechten Kanal trotzdem auslesen und die samples
von 1024 to 2048 übergeben damit kein rangecheck error auftritt ?
In Deinem Array ist der linke Kanal im Index 0 und der rechte Kanal im Index 1, oder?

Ein Stacküberlauf, deutet meines Erachtens eher auf eine sehr lange/endlos Schleife hin.

Grüße
Klaus

EWeiss 25. Mai 2007 06:19

Re: FFT Problem in verbindung mit WMP
 
Auch guten Morgen.
Zitat:

Zitat von Klaus01
Guten Morgen Emil,

In Deinem Array ist der linke Kanal im Index 0 und der rechte Kanal im Index 1, oder?

Grüße
Klaus

Ja.

Zitat:

Ein Stacküberlauf, deutet meines Erachtens eher auf eine sehr lange/endlos Schleife hin.

Hier nochmal die ganze schleife.
Welche eigentlich keinen überlauf verursacht.

Delphi-Quellcode:
      BASS_ChannelGetData(channel, Data32, FFTSize or
                          DWORD(IfThen(ChanInfo.chans = 2,
                          BASS_DATA_FFT_INDIVIDUAL)));


      if (ChanInfo.chans = 2) then
      begin
        for i := 0 to 2047 do
        try
        begin
          if i < 1024 then
          begin
            VisData^.frequency[0, i] :=
                              Max(0, Min(1023, (Trunc(Power(Data32Pos^,
                              FFTSAmplification * 0.8) * 1023))));
              Inc(Data32Pos, FFT_SkipCount);
          end else
          begin
            VisData.frequency[1, i mod 1024]:=
                             Max(0, Min(1023, (Trunc(Power(Data32Pos^,
                             FFTSAmplification * 0.8) * 1023))));
              Inc(Data32Pos, FFT_SkipCount);
          end;
        end;
        except
          Result := false;
          exit;
        end;
      end
      else
      begin
        for i := 0 to 1023 do
        begin
          VisData^.frequency[0, i] :=
            Max(0, Min(1023, (Trunc(Power(Data32Pos^, FFTSAmplification * 1.0) * 1023))));
          VisData^.frequency[1, i] := VisData^.frequency[0, i];
          Inc(Data32Pos, FFT_SkipCount);
        end;
      end;
Der fehler tritt bei mehr als 1023 auf .

Hier mal die Definition von BASS_DATA_FFT_INDIVIDUAL

Zitat:

BASS_DATA_FFT_INDIVIDUAL Use this flag to request separate FFT data for each channel. The size of the data returned is multiplied by the number channels.

-> So stereo will return 2 times the data requested (left and right = 2 channels).
-> So you will get both channels data with one single request.
gruss Emil

Klaus01 25. Mai 2007 07:24

Re: FFT Problem in verbindung mit WMP
 
Hallo Emil,

Deine Schleifen gehen bei Stereo immer fix von 0 bis 2047.
Ist das kein Problem, wenn die SampleRate <> 1024/2048 ist?

Sollte i dann nicht eher anhänging von der SampleRate laufen?

http://www.developpez.net/forums/arc.../t-181962.html
Zitat:

BASS_DATA_FFT512 512 sample FFT (returns 256 floating-point values)
BASS_DATA_FFT1024 1024 sample FFT (returns 512 floating-point values)
BASS_DATA_FFT2048 2048 sample FFT (returns 1024 floating-point values)
BASS_DATA_FFT4096 4096 sample FFT (returns 2048 floating-point values)

Wie Du merkst, verstehe ich noch nicht wie Du die Daten bekommst und wie sie angeordnet sind.


Und noch vielleicht ein Copy und Paste Fehler:
Delphi-Quellcode:
begin
  VisData.frequency[1, i mod 1024]:=
                     Max(0, Min(1023, (Trunc(Power(Data32Pos^,
                     FFTSAmplification * 0.8) * 1023))));
  Inc(Data32Pos, FFT_SkipCount);
end;
sollte doch

Delphi-Quellcode:
begin
  VisData^.frequency[1, i mod 1024]:=
                     Max(0, Min(1023, (Trunc(Power(Data32Pos^,
                     FFTSAmplification * 0.8) * 1023))));
  Inc(Data32Pos, FFT_SkipCount);
end;
heißen, oder?


Grüße
Klaus

EWeiss 25. Mai 2007 07:54

Re: FFT Problem in verbindung mit WMP
 
Hi Klaus

Zitat:

Und noch vielleicht ein Copy und Paste Fehler:
Richtig ;)
Habe es von meiner Winamp Render function eingefügt
da hieß die abfrage anders. Aber gut das du mich drauf aufmerksam gemacht hast.

Zitat:

BASS_DATA_FFT512 512 sample FFT (returns 256 floating-point values)
BASS_DATA_FFT1024 1024 sample FFT (returns 512 floating-point values)
BASS_DATA_FFT2048 2048 sample FFT (returns 1024 floating-point values)
BASS_DATA_FFT4096 4096 sample FFT (returns 2048 floating-point values)
Auch richtig!

Das handhabe ich auch so.
Delphi-Quellcode:
    case (FFT_WMP_SkipCount) of
      1: FFTSize := BASS_DATA_FFT1024;
      2: FFTSize := BASS_DATA_FFT2048;
      3: FFTSize := BASS_DATA_FFT4096;
      else
        FFT_WMP_SkipCount := 1;
        FFTSize := BASS_DATA_FFT1024;
    end;

    BASS_ChannelGetData(channel, Data32, FFTSize or
                        DWORD(IfThen(ChanInfo.chans = 2,
                        BASS_DATA_FFT_INDIVIDUAL)));
Durch das Flag BASS_DATA_FFT_INDIVIDUAL werden die daten unter verwendung von BASS_DATA_FFT2048
mit 2 mal 1024 samples zurückgegeben!

Was ich nicht verstehe das die gleiche Renderfunktion in winamp funktioniert
Der unterschied liegt doch nur in der übergabe der Samples welche hier 575 entsprechen.

EDIT:
Das ist die letzte Fehlermeldung!

Zitat:

Debug Output: Invalid allocation size - FFFFE810 (exceeded 7ffdefff) Process WMPTest.exe (1256)
gruss Emil

Klaus01 25. Mai 2007 09:19

Re: FFT Problem in verbindung mit WMP
 
Zitat:

Debug Output: Invalid allocation size - FFFFE810 (exceeded 7ffdefff) Process WMPTest.exe (1256)
Da wird versucht Speicher einer Größe von 4294961168 (Cardinal Wertebereich) Bytes zu allozieren.
Erlaubt sind aber nur 2147348479 (LongInt) Bytes.

Und die einzige Stelle wo Speicher reserviert wird ist diese:
Delphi-Quellcode:
BASS_ChannelGetData(channel, Data32, FFTSize or DWORD(IfThen(ChanInfo.chans = 2,BASS_DATA_FFT_INDIVIDUAL)));
Was Du damit meinst,
Zitat:

Der unterschied liegt doch nur in der übergabe der Samples welche hier 575 entsprechen gesamt 288.
, keine Ahnung.

Grüße
Klaus, der mit seinem Latein am Ende ist.


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:55 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