Autor |
Beitrag |
Blamaster
      
Beiträge: 164
|
Verfasst: 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
      
Beiträge: 19312
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Sa 17.01.09 18:03
Dafür kannst du sehr gut die BASS DLL verwenden.
www.un4seen.com/bass.html
|
|
Blamaster 
      
Beiträge: 164
|
Verfasst: Sa 17.01.09 18:35
Danke für die Hilfe
mfg Blamaster
|
|
Blamaster 
      
Beiträge: 164
|
Verfasst: 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 ?
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 Buffer.Canvas.Brush.Color := clBlack; Buffer.Canvas.FillRect(Rect(0,0,Buffer.Width,Buffer.Height));
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
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: 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 
      
Beiträge: 164
|
Verfasst: 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
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
      
Beiträge: 19312
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Di 20.01.09 14:33
Blamaster hat folgendes geschrieben : | 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 
      
Beiträge: 164
|
Verfasst: 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
      
Beiträge: 19312
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Di 20.01.09 15:57
|
|
Blamaster 
      
Beiträge: 164
|
Verfasst: 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:
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..1] of 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); if (peak[0]<LOWORD(level)) then peak[0]:=LOWORD(level); if (peak[1]<HIWORD(level)) then peak[1]:=HIWORD(level); if BASS_ChannelIsActive(decoder) <> BASS_ACTIVE_PLAYING then begin position := cardinal(-1); 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); 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 
      
Beiträge: 164
|
Verfasst: 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 
      
Beiträge: 164
|
Verfasst: Do 22.01.09 18:22
Hi,
ich habe jetzt selber nochmal etwas im Board gesucht und rumprobiert und das kam dabei raus:
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
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Do 22.01.09 18:31
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 
      
Beiträge: 164
|
Verfasst: Do 22.01.09 19:18
Also in meinem Fall:
Delphi-Quelltext 1:
| Trunc((i*PB.ClientWidth)/length(WData)) |
?
mfg Yannic
|
|
Blamaster 
      
Beiträge: 164
|
Verfasst: 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:
Delphi-Quelltext
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:
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!
|
|
|