AW: Optimierung von Pixel
Ich werde deine Ausführung nochmal genau durchgehen.
So das ich genau verstehe warum und wieso.. ;) Danke! Zitat:
Den Buffer auf 256 einstellen und anschließend nur 160 Pixel daraus lesen also abhängig von der höhe der Bitmap? Dann ist der Speicher mit 256 Bytes gefüllt verwende dann aber nur 160 davon. Wenn es das ist was ihr meint. Dann wird aber genau wie vorher nicht der gesamte Bereich des Spectrums gezeichnet weil das Bitmap halt kleiner ist. Der Speicher hingegen ist dann aber korrekt gefüllt. Zitat:
Habe noch etwas geändert bzg. dem Fehler mit ScanLine prüfe jetzt auf <> NIL. Damit bei der Rückgabe der Farben kein ZeilenFehler auftritt. Hoffe nur du bekommst jetzt einen Channel :) gruss |
AW: Optimierung von Pixel
Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
Schönes sonniges Wochenende! |
AW: Optimierung von Pixel
Zitat:
In dem Beispiel funktioniert jetzt auch das weiterschalten der Seiten. Zitat:
gruss |
AW: Optimierung von Pixel
Um das mit dem Buffer nochmal zu veranschaulichen: Stell dir vor, du hast einen Kaffeeautomaten (die BASS-Funktion), der dir immer genau eine Tasse Kaffee ausspuckt, wenn du auf den Knopf drückst. Wenn du jetzt Lust auf wenig Kaffee hast und nur eine Espresso-Tasse (zu kleiner Puffer) drunterstellst, dann gibt es eine Sauerei :mrgreen:
|
AW: Optimierung von Pixel
Zitat:
gruss |
AW: Optimierung von Pixel
Ich habe das Ganze mal unter Lazarus ans Laufen bekommen, und auch gefunden warum ich keinen gültigen Channel bekam: Du übergibst das Flag BASS_UNICODE ohne Wenn und Aber, aber ich habe nur Delphi 2007 im Büro. Daher war der Dateiname bei mir nicht in Unicode. Da wäre ggf. eine Fallunterscheidung nicht übel, die du zum Abspielen weiter unten sogar schon drin hast.
Die Ergebnisse sind zwischen Delphi und FPC sicherlich kaum zu vergleichen. Ich habe jetzt z.B. mit der 64Bit Variante der Bass.dll gearbeitet, weil Lazarus offenbar keinen Win32 Compiler installiert hat (und ich keine Lust hatte zu suchen wie ich das zurechtstückeln muss). Ich habe ein fast genau 2min langes MP3 geladen, und brauchte trotz Verwendung von TCanvas.Pixels[] nur 2 Sekunden. Allerdings arbeitet TCanvas.Pixels[] in FPC auch komplett anders als unter Delphi, und Scanline gibt es erst gar nicht. Von daher praktisch keine Chance da für dich brauchbare Zeiten zu messen. Was ich aber gemacht habe, ist zu messen wie lange die gesamte Prozedur dauerte, und wie viel davon auf das reine Malen entfielen. Bei 2sek gesamt wurden 1,25sek zum Zeichnen gebraucht. Der Rest war Bass-Daten abfragen, die Schleifen und Farbumrechnungen. (Was übrigens zumindest unter Lazarus sehr viel gefressen hat, war das immer wieder Abfragen von Radiobutton1.Checked!) Hier mal, wie du ähnlich messen kannst. (Erheblich präziser als mit GetTickCount!) Die entsprechenden Zeilen habe ich mal via Kommentar markiert, damit sie besser auffallen.
Delphi-Quellcode:
Die Zeit wird hierbei in Sekunden angegeben. (Deshalb die 3 Nachkommastellen um die Anzeige bis auf Millisekunden genau zu haben.)
procedure TForm1.SampleAudioStream(FileName: String);
Const BUFFER_SIZE = 256; var Buffer: array of Single; Info: BASS_CHANNELINFO; i: integer; Progress: integer; H, S, L: double; Value: double; StreamLength: Int64; ScanLines: TArray<PRGBTriple>; P: PRGBTriple; R, G, B: Byte; pcFrequency: Int64; // <--------------------- Zeitmessung timeAll0, timeAll1, timeAll: Int64; // <----- Zeitmessung timeDraw0, timeDraw1, timeDraw: Int64; // <-- Zeitmessung begin Channel := BASS_MusicLoad(false, PChar(FileName), 0, 0, BASS_MUSIC_DECODE OR BASS_MUSIC_STOPBACK OR BASS_MUSIC_CALCLEN {$IFDEF UNICODE} OR BASS_UNICODE {$ENDIF} OR BASS_SAMPLE_FLOAT, 0); if Channel = 0 then begin Channel := BASS_StreamCreateFile(false, PChar(FileName), 0, 0, BASS_STREAM_DECODE OR BASS_MP3_SETPOS OR BASS_SAMPLE_FLOAT {$IFDEF UNICODE} OR BASS_UNICODE {$ENDIF}); end; if Channel = 0 then begin Exit; end; Form2.ProgressBar1.position := 0; Form2.Show; BASS_ChannelGetInfo(Channel, Info); StreamLength := BASS_ChannelGetLength(Channel, BASS_POS_BYTE); Bitmap.Height := 256; Bitmap.Width := (StreamLength div 512 div 4) div Info.chans; PB.Width := Bitmap.Width; PB.Height := Bitmap.Height; PB.Parent.DoubleBuffered := true; S := 0.9; SetLength(Buffer, BUFFER_SIZE); ColumnCounter := 0; QueryPerformanceFrequency(pcFrequency); // <------ Zeitmessung QueryPerformanceCounter(timeAll0); // <----------- Zeitmessung timeDraw := 0; // <------------------------------- Zeitmessung if RadioButton1.Checked then begin SetLength(ScanLines, Bitmap.Height); for i := 0 to Length(ScanLines) - 1 do ScanLines[i] := Bitmap.Scanline[i]; end; while BASS_ChannelIsActive(Channel) <> BASS_ACTIVE_STOPPED do begin BASS_ChannelGetData(Channel, Pointer(Buffer), BASS_DATA_FFT512); for i := 0 to BUFFER_SIZE - 1 do begin Value := SQRT(SQRT(Buffer[i])); H := 0 + Value / 1.5; L := Value; if RadioButton1.Checked then begin QueryPerformanceCounter(timeDraw0); // <-------------------- Zeitmessung P := ScanLines[BUFFER_SIZE - i]; if Assigned(P) then HSLtoRGB(H, S, L, P^.rgbtRed, P^.rgbtGreen, P^.rgbtBlue); QueryPerformanceCounter(timeDraw1); // <------------------- Zeitmessung timeDraw := timeDraw + (timeDraw1-timeDraw0); // <--------- Zeitmessung end else begin QueryPerformanceCounter(timeDraw0); // <------------------- Zeitmessung HSLtoRGB(H, S, L, R, G, B); Bitmap.Canvas.Pixels[ColumnCounter, BUFFER_SIZE - i] := RGB(R, G, B) QueryPerformanceCounter(timeDraw1); // <------------------- Zeitmessung timeDraw := timeDraw + (timeDraw1-timeDraw0); // <--------- Zeitmessung end; end; if RadioButton1.Checked then begin for i := 0 to Length(ScanLines) - 1 do Inc(ScanLines[i]); end else Inc(ColumnCounter); Progress := trunc(100 * (Bass_ChannelGetPosition(Channel, BASS_POS_BYTE) / BASS_ChannelGetLength (Channel, BASS_POS_BYTE))); if (Form2.ProgressBar1.position <> Progress) then begin Form2.ProgressBar1.position := Progress; PB.Refresh; end; end; QueryPerformanceCounter(timeAll1); // <-------------------------------------------------- Zeitmessung timeAll := timeAll1-timeAll0; // <------------------------------------------------------- Zeitmessung Label1.Caption := 'Gesamtzeit: '+FloatToStrF(timeAll/pcFrequency, ffFixed, 8, 3); // <--- Zeitmessung Label2.Caption := 'Draw-Zeit: '+FloatToStrF(timeDraw/pcFrequency, ffFixed, 8, 3); // <--- Zeitmessung Form2.Hide; Bass_StreamFree(Channel); Channel := BASS_StreamCreateFile(false, PChar(FileName), 0, 0, 0 {$IFDEF UNICODE} or BASS_UNICODE {$ENDIF}); if Channel = 0 then begin Channel := BASS_MusicLoad(false, PChar(FileName), 0, 0, BASS_MUSIC_RAMPS or BASS_MUSIC_POSRESET or BASS_MUSIC_PRESCAN {$IFDEF UNICODE} or BASS_UNICODE {$ENDIF}, 0); if (Channel = 0) then Exit; end; DestBitmap.Width := PB.Width; DestBitmap.Height := PB.Height; BitBlt(DestBitmap.Canvas.handle, 0, 0, PB.Width, PB.Height, Bitmap.Canvas.handle, 0, 0, SrcCopy); bpp := BASS_ChannelGetLength(Channel, BASS_POS_BYTE) div PB.Width; BASS_ChannelSetSync(Channel, BASS_SYNC_END or BASS_SYNC_MIXTIME, 0, LoopSyncProc, nil); BASS_ChannelPlay(Channel, false); Timer1.Enabled := true; end; Das könnte gut dabei helfen zu ermitteln, ob das eigentliche Zeichnen wirklich der Flaschenhals ist, und ob es sich lohnt in dessen Optimierung überhaupt noch viel Zeit zu stecken. (Ich kann mir gut vorstellen, dass das Berechnen des Fortschritts wegen der vielen Calls zur Bass.dll auch ganz schön zu Buche schlägt. Tut's zumindest unter Lazarus nicht. Der Unterschied ist im normalen Schwankungsbereich.) |
AW: Optimierung von Pixel
Zitat:
Frequente Aufrufe bestimmter Windows APIs können allerdings durch den Kontext-Switch in Kernel-Mode und wieder zurück (SYSENTER) extrem teuer sein. |
AW: Optimierung von Pixel
Zitat:
Man schaut immer zu sehr auf seine eigene Developer Umgebung. ;) Zitat:
Zitat:
Werde da mal eine Variable für anlegen um den zugriff auf das Control zu verhindern. QueryPerformanceCounter ist natürlich etwas genauer als GeTickCount.. wird umgebaut. Danke für das Testen wenn auch unter Lazarus. Anbei vergleich von Pixel/ScanLine als Bilder und neue Version mit deiner Zeitmessung incl. Variable anstelle von Radiobutton1.Checked. BASS_UNICODE ist abgesichert.. gruss |
AW: Optimierung von Pixel
Zitat:
Zitat:
Zitat:
Zitat:
300ms zum Zeichnen sind schon gar nicht so übel. Vor allem weil es ja nur ca. 30% der Gesamtzeit ausmacht. So ganz so viel ist da dann gar nicht mehr herauszuholen. |
AW: Optimierung von Pixel
Zitat:
Die Ergebnisse sind schon mal nicht schlecht ;) Danke für deine Zeit die du geopfert hast. Vielleicht ist es ja auch etwas für andere die so was schon immer mal realisieren wollten. gruss |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:52 Uhr. |
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