Autor Beitrag
Blamaster
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 164



BeitragVerfasst: Sa 17.01.09 18:01 
Hi,

kennt jemand eine Lösung um die Tonspur einer mp3 Datei Visuell darzustellen ?

Ich meine diese Leisten die es in vielen Musikbearbeitungsprogrammen gibt, bei denen die die hz Zahl jeweils auf einer Zeitleiste angezeigt wird.

Ich hoffe ihr versteht was ich meine ist irgendwie schwer in Worte zu fassen.

mfg Blamaster
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19312
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Sa 17.01.09 18:03 
Dafür kannst du sehr gut die BASS DLL verwenden.
www.un4seen.com/bass.html
Blamaster Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 164



BeitragVerfasst: Sa 17.01.09 18:35 
Danke für die Hilfe :)

mfg Blamaster
Blamaster Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 164



BeitragVerfasst: So 18.01.09 20:52 
So ich habe mich nun etwas mit den Beispielen der Bass Dll beschäftigt.

Momentan verwende ich eine BassPlayer.pas und komme mit der recht gut klar.

Das Custloop Beispiel verstehe ich allerdings noch nicht so richtig.

Der eigentliche Teil der fürs zeichnen der Wave zuständig ist ist doch dieser hier richtig ?

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
procedure TForm1.DrawSpectrum;
var
  i,ht : integer;
begin
  //clear background
  Buffer.Canvas.Brush.Color := clBlack;
  Buffer.Canvas.FillRect(Rect(0,0,Buffer.Width,Buffer.Height));

  //draw peaks
  ht := ClientHeight div 2;
  for i:=0 to length(wavebufL)-1 do
  begin
    Buffer.Canvas.MoveTo(i,ht);
    Buffer.Canvas.Pen.Color := clGreen;
    Buffer.Canvas.LineTo(i,ht-trunc((wavebufL[i]/32768)*ht));
    Buffer.Canvas.Pen.Color := clRed;
    Buffer.Canvas.MoveTo(i,ht+2);
    Buffer.Canvas.LineTo(i,ht+2+trunc((wavebufR[i]/32768)*ht));
  end;
end;


Wenn ich das nun richtig sehe passiert dort doch folgendes:
- erstmal wird der Hintergrund schwarz gefärbt
- dann wird ht die hälfte der Paintbox höhe zugewiesen (einmal für die obere und untere wave)
- nun wird in einer Schleife der wavebufL durchgegangen ----> Was steht im wavebufL ?
- jetzt wird der Startpunkt zum zeichnen festgelegt ----> Wieso wird durch 32768 geteilt und das mal die halbe Fensterhöhe genommen ?

Ich glaube wenn mir das jemand erklären könnte bin ich dem ziel schon recht nahe :)

mfg Yannic
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Mo 19.01.09 13:19 
WaveBufL und WaveBufR sind linker und rechter Audio-Kanal

Durch 32768 wird geteilt, weil Waves meist 16-Bit sind, d.h. Zahlen zwischen -32768 und +32767 beinhalten; die Division wird zur Normierung gebraucht.

Die Multiplikation dient der Skalierung, damit die Zahlenwerte zwischen -1..1 auf die gesamte Fensterhöhe verteilt werden.

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
Blamaster Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 164



BeitragVerfasst: Di 20.01.09 13:49 
Hi,

danke schonmal für die Erklärung ich hatte es genauso vermutet, wusste nur nicht das der 0 Punkt einer TPaintbox oben links ist :oops:

Nun stehe ich allerdings vor 2 weiteren Problem.

Die BassPlayer kompo bietet unter der vorgane length() nur GetFFTData, GetWaveData an.

Und dann stehe ich noch vor dem Problem das wenn ich die Paintbox etwas zeichnen lasse und dann ein anderes Fenster in den Vordergrund hole wird der Inhalt der Paintbox gelöscht. Woran kann das liegen ?

Für den Ersatz der length(WavebufL) habe ich im anhang nochmal die BassPlayer.pas angehängt.

mfg Yannic
Einloggen, um Attachments anzusehen!
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19312
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Di 20.01.09 14:33 
user profile iconBlamaster hat folgendes geschrieben Zum zitierten Posting springen:
Und dann stehe ich noch vor dem Problem das wenn ich die Paintbox etwas zeichnen lasse und dann ein anderes Fenster in den Vordergrund hole wird der Inhalt der Paintbox gelöscht. Woran kann das liegen ?
In eine Paintbox zeichnet man normalerweise nur in OnPaint etwas:
www.michael-puff.de/...ffScreenBitmap.shtml

Wenn du das nicht möchtest, dann kannst du ein TImage verwenden. Dort passiert das nicht.
Blamaster Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 164



BeitragVerfasst: Di 20.01.09 15:29 
Super, auch danke nochmal dafür jetzt ist alles beisammen bis auf mein length(wavebufl) Problem :)

mfg Yannic
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19312
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Di 20.01.09 15:57 
user profile iconBlamaster hat folgendes geschrieben Zum zitierten Posting springen:
Super, auch danke nochmal dafür jetzt ist alles beisammen bis auf mein length(wavebufl) Problem :)
Da weiß ich nicht ganz was du meinst. ;-)
Blamaster Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 164



BeitragVerfasst: Di 20.01.09 18:30 
Hi,

ich habe gerade gesehen as ich mich wirklich unverständlich ausgedrückt habe.

In meinem oben geposteten Codeausschnitt wird ja mit for i:=0 to length(wavebufL)-1 do die Verteilung der peaks auf dem TBitmap realisiert.

Nun dachte ich erst wavebufL währe eine Funktion der Bass.dll dem hab ich gerade gesehen ist aber nicht so.

Im beispielcode scheint die Berechnung über folgende Codestelle zu erfolgen:

ausblenden volle Höhe 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:
43:
44:
45:
procedure TForm1.ScanPeaks2(decoder : HSTREAM);
var
  cpos,level : DWord;
  peak : array[0..1of DWORD;
  position : DWORD;
  counter : integer;
begin
  cpos := 0;
  peak[0] := 0;
  peak[1] := 0;
  counter := 0;
  
  while not killscan do
  begin
    level := BASS_ChannelGetLevel(decoder); // scan peaks
    if (peak[0]<LOWORD(level)) then
      peak[0]:=LOWORD(level); // set left peak
    if (peak[1]<HIWORD(level)) then
      peak[1]:=HIWORD(level); // set right peak
    if BASS_ChannelIsActive(decoder) <> BASS_ACTIVE_PLAYING then
    begin
      position := cardinal(-1); // reached the end
    end else
      position := BASS_ChannelGetPosition(decoder,BASS_POS_BYTE) div bpp;

    if position > cpos then
    begin
      inc(counter);
      if counter <= length(wavebufL)-1 then
      begin
        wavebufL[counter] := peak[0];
        wavebufR[counter] := peak[1];
      end;

      if (position >= dword(ClientWidth)) then
        break;
      cpos := position;
     end;


    peak[0] := 0;
    peak[1] := 0;
  end;
  BASS_StreamFree(decoder); // free the decoder
end;


Diese verstehe ich nun allerdings mehr oder weniger überhaupt nicht so richtig, deswegen wollte ich wissen ob sich mit der angehängten BassPlayer.pas und ihren Funktionen die obige Verteilung der Peaks auf dem TBitmap auch anders bzw einfacher relaisieren lässt.

Ich hoffe ich habe mich da jetzt verständlicher ausgedrückt :)

mfg Yannic
Blamaster Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 164



BeitragVerfasst: Di 20.01.09 23:15 
Hi,

ich habe jetzt nochmal den aktzellen Source meines "Versuch Programm" angehängt.

Das Programm funktioniert soweit auch schon (spectrum wird gezeichnet).

Nur soll sich das Spektrum nicht zeitgleich der wiedergabe aufbauen, sondern bereits direkt nach dem einfügen.

mfg Yannic
Einloggen, um Attachments anzusehen!
Blamaster Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 164



BeitragVerfasst: Do 22.01.09 18:22 
Hi,

ich habe jetzt selber nochmal etwas im Board gesucht und rumprobiert und das kam dabei raus:

ausblenden 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:
procedure TForm1.Button3Click(Sender: TObject);
var
Rp,Lp: SmallInt;
Y: LongInt;
i: Integer;
begin
WData:= MPlayer.GetWaveData;

Rp := SmallInt(LOWORD(WData[0]));
Lp := SmallInt(HIWORD(WData[0]));
Y := Trunc(((Rp+Lp)/(2*65535)*PB.ClientHeight));

bmp.Canvas.Pen.Color:= clGreen;
bmp.Canvas.MoveTo(0,Y + PB.ClientHeight div 2);

for i := 1 to length(WData) do
begin
Rp := SmallInt(LOWORD(WData[i]));
Lp := SmallInt(HIWORD(WData[i]));
Y := Trunc(((Rp+Lp)/(2*65535)*PB.ClientHeight));
bmp.Canvas.LineTo(i,Y + PB.ClientHeight div 2);
end;

PB.Refresh;

end;


Soweir funktioniert es nun auch wie gewünscht. Allerdings habe ich noch probleme mit der Verteilung der Grafik in der Breite. ei der höhe ist es ja nun so das wenn ich das TBitmap noch oben höher oder tiefer ziehe, die Wete automatisch angepasst werden.

Bei der Länge habe ich da allerdings gerade noch so meine Probleme. Wie kann ich es umsetzen das egal wie breit mein TBitmap ist die Grafik über die ganze Breite richtig verteilt wird ?

mfg Yannic
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Do 22.01.09 18:31 
ausblenden Delphi-Quelltext
1:
PosX := Wert * Breite / AnzahlWerte;					

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
Blamaster Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 164



BeitragVerfasst: Do 22.01.09 19:18 
Also in meinem Fall:

ausblenden Delphi-Quelltext
1:
Trunc((i*PB.ClientWidth)/length(WData))					


?

mfg Yannic
Blamaster Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 164



BeitragVerfasst: Sa 24.01.09 21:01 
Hi,

ich habe gerade nochmal eine Frage zum Quelltext der CustomLoop bei den Bass Beispielen. (Datei im Anhang)

Dort gibt es ja in der ScanPeaks2 Procedure folgende codestelle:

ausblenden Delphi-Quelltext
1:
while not killscan do					


Welche Funktion hat die ? Wenn ich mir den ganzen Source richtig ansehe gibt es nur 3 Stellen an denen die Killscan auftaucht einmal beim deklarieren dann an der while not Stelle und zuletzt bei schließen des Formulars. Könnte man die while dann nicht auch gleich durch eine for Schleife ersetzen ? Also z.B. for i:= 1 to length(WavebufL) do .... ?

Und dann verstehe ich den Sinn von folgender Code Stelle noch nicht wirklich:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
if position > cpos then
    begin
      inc(counter);
      if counter <= length(wavebufL)-1 then
      begin
        wavebufL[counter] := peak[0];
        wavebufR[counter] := peak[1];
      end;

      if (position >= dword(ClientWidth)) then
        break;
      cpos := position;
     end;


Hoffe da kann mir nochmal jemand auf die sprünge helfen.

mfg Blamaster
Einloggen, um Attachments anzusehen!