AW: Optimierung von Pixel
Zitat:
Die Läuft top. Habe jetzt mit der Änderung bei der Progressbar von 31 Sec auf 14 runterschrauben können mit der 35MB Mp3 Zitat:
Dachte erst das läge am 24 BIT Format aber das ist ja bei beiden gleich. Zitat:
Zitat:
gruss |
AW: Optimierung von Pixel
Zitat:
|
AW: Optimierung von Pixel
Zitat:
Oder aber das Bitmap in der höhe entsprechend anpassen. Nebenbei nach deiner Änderung sind Pixel/ScanLine fast identisch.. beide 14 Sec Einen gewinn Zuwachs habe ich im Moment bzg. ScanLine noch nicht. Pixel := 13:78 ScanLine := 14:60 Sogar langsamer.. gruss |
AW: Optimierung von Pixel
Zitat:
Wenn du alle Daten der FFT in 160 Pixeln Höhe anzeigen willst, musst du entweder die Daten oder das Bitmap skalieren. Anders gehts dann nicht. |
AW: Optimierung von Pixel
Zitat:
Ich lese ja nur soviel Pixel wie das Bitmap in der Höhe ist
Delphi-Quellcode:
for i := 0 to BUFFER_SIZE - 1 do
Daher verstehe ich auch nicht wie da ein Buffer Overflow entstehen sollte. gruss |
AW: Optimierung von Pixel
Du übergibst deinen zu kurzen Buffer mit
Delphi-Quellcode:
in die Obhut der Bass.dll, und sagst ihr: "Hallo Bass.dll, bitte fülle diesen Buffer mit den FFT Daten eines 512 Byte langen Samples.". Die Bass.dll sieht nur einen Pointer auf ein Stück speicher, und glaubt dir blind, dass du genug Speicher für all die Werte die sie nun schreiben will reserviert hast, und legt los alle 512 Werte zu schreiben.
BASS_ChannelGetData(Channel, Pointer(Buffer), BASS_DATA_FFT512);
Aber du hattest eigentlich nur 160 Bytes für den Buffer reserviert. Was eventuell hinter deinen 160 Bytes steht, weiss maximal der Speichermanager. Aber weder du noch die Bass.dll wissen das. Es wäre nichts ungewöhnliches, wenn dort z.B. die Daten für einen der Buttons in deinem Programm lägen o.ä., und die Bass.dll würde die dann einfach so ungeprüft übernageln. Was das mit dem Verhalten von dem Button anstellt, ist vermutlich klar. Dein Lesen ist nicht das Problem. |
AW: Optimierung von Pixel
Zitat:
Delphi-Quellcode:
und hier
SetLength(Buffer, BUFFER_SIZE); // Reserviert Speicher für 159x Single/Float
Delphi-Quellcode:
BASS_ChannelGetData(Channel, Pointer(Buffer), BASS_DATA_FFT512); // Schreibt 256x Single/Float in den Buffer
|
AW: Optimierung von Pixel
Zitat:
|
AW: Optimierung von Pixel
Zitat:
Aber ich verwende davon nur 160 Floats. Es dürfte doch kein Problem sein aus einem Array nur so viele Einträge zu verwenden wie man sie benötigt vorausgesetzt ich verwende nicht mehr wie enthalten sind. :) wo entsteht bei dieser Konstellation ein Überlauf ? Zitat:
gruss |
AW: Optimierung von Pixel
In deinem Fall kann Scanline seinen eigentlichen Vorteil gar nicht richtig ausspielen. Mit ScanLine kann man sehr schnell eine ganze Zeile des Bitmaps bearbeiten. Dein Code arbeitet aber spaltenorientiert, weswegen du immer nur ein Pixel der jeweiligen Scanline änderst und beim nächsten Aufruf bereits eine andere Scanline brauchst.
Eventuell kannst du noch etwas Performance herausholen, wenn du die Scanlines cached:
Delphi-Quellcode:
var
ScanLines: TArray<PRGBTriple>; { nach Zuweisung von Bitmap.Height werden die Scanlines im Array mit der ersten Spalte initialisiert } SetLength(ScanLines, BitMap.Height); for I := 0 to Length(ScanLines) - 1 do begin ScanLines[I] := Bitmap.ScanLine[I]; end; { statt SetPixel } aColor := HSLtoRGB(H, S, L); // hier könnte man noch etwas herausholen, wenn direkt die RGB-Werte zurückgegeben werden. P := ScanLines[BUFFER_SIZE - i]; P^.rgbtRed := GetRValue(aColor); // dann spart man sich hier wieder das auslesen P^.rgbtGreen := GetGValue(aColor); P^.rgbtBlue := GetBValue(aColor); { nach Inc(ColumnCounter) werden die ScanLine-Pointer um eine Spalte weiter gerückt. } for I := 0 to Length(ScanLines) - 1 do begin Inc(ScanLines[I]); end; Vorausgesetzt, es gibt eine Prozedur
Delphi-Quellcode:
könnte der relevante Code etwa so aussehen:
procedure HSLtoRGB(H, S, L: double; out R, G, B: Byte);
Delphi-Quellcode:
SetLength(ScanLines, BitMap.Height);
for I := 0 to Length(ScanLines) - 1 do begin 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; P := ScanLines[BUFFER_SIZE - i]; HSLtoRGB(H, S, L, P.rgbtRed, P.rgbtGreen, P.rgbtBlue); end; for I := 0 to Length(ScanLines) - 1 do begin Inc(ScanLines[I]); end; 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; Wenn nicht schon geschehen, solltest man auch mal die Basiszeit der Analyse ermitteln, die sowieso verbraucht wird ohne in das Bitmap zu schreiben. |
AW: Optimierung von Pixel
Übrigens: Der Buffer-Overflow schlägt gnadenlos auf das Scanlines-Array zu. Der Code funktioniert nur, wenn man
Delphi-Quellcode:
verwendet.
SetLength(Buffer, 256);
|
AW: Optimierung von Pixel
Zitat:
Delphi-Quellcode:
Aufruf.
BASS_ChannelGetData(Channel, Pointer(Buffer), BASS_DATA_FFT512)
Zitat:
Nach eine generelle Frage: Würde es nicht mehr Sinn machen, nur die ersten paar Sekunden zu visualisieren und danach on-demand jeweils die nächsten paar Sekunden ab aktueller Abspielposition? |
AW: Optimierung von Pixel
Zitat:
|
AW: Optimierung von Pixel
Zitat:
Ich bin nur von meinem Code ausgegangen die Bass.dll hat mich dabei weniger interessiert ;) Gut das macht die Profis (Informatiker) aus. Letztendlich habe ich mich nur um meinen Code gekümmert so das dieser Fehlerfrei läuft. Wie oder ob die Bass.dll das abfängt liegt nicht in meinem ermessen. Zumindest werden keine Exception geworfen. Zitat:
Und ja wird verwendet.
Delphi-Quellcode:
SetLength(Buffer, BUFFER_SIZE);
Zitat:
Ich möchte nicht zur Laufzeit in Realzeit Rendern sondern erst das komplette Bitmap erstellen deshalb dieses Example. Also ich möchte erst sehen wie das Spectrogram aussieht und dann mit "LineTo" anzeigen wo man sich gerade an welcher Position im Stream befindet. Mit einem Loop könnte man dann später einen bestimmten Bereich immer wieder spielen. (Dafür muss ich aber vorher schon sehen wo ich mich befinde) Realzeit Render, was ich nicht möchte ;)
Delphi-Quellcode:
begin
OffsetX := 2; // normal 256x512 for i := 0 to pred(Height) do begin MagLn := round(Sqrt(FFTData[i + 1]) * 3 * Width); k := Height - i - 1; x := BuffBMP.ScanLine[k]; if bRTLScroll then begin //copy original scanline Move(x[OffsetX], x[0], (Width - OffsetX)); //draw new pixels for m := 0 to pred(OffsetX) do x[Width - OffsetX + m] := MagLn; end else //Left to right begin //copy original scanline Move(x[0], x[OffsetX], (Width - OffsetX)); //draw new pixels for m := 0 to pred(OffsetX) do x[m] := MagLn; end; end; end; Zitat:
Ich könnte das Bitmap noch verkleinern\zusammenschrumpfen und zusätzlich noch interpolieren Aber ich möchte jedes Pixel sehen (etwas fürs Auge) und nicht alles zusammenstauchen nur damit es auf dem Bitmap beliebiger länge passt. Mir ist auch klar das ich nur die ersten 512 Blöcke verwende und diese nicht den gesamten Frequenzbereich zurückgeben. Deshalb kann ich für 44100 Hz, den Bereich von 22,5 kHz bis 0 (Nyquist-Transformation) nicht anzeigen. Aber das sind bekannte Probleme. Wichtiger ist erst mal die Performance (Geschwindigkeit) Andere frage kann es sein das ScanLine nicht richtig funktioniert weil das Spectrogram vertikal zeichnet und ScanLine horizontal arbeitet? gruss |
AW: Optimierung von Pixel
Zitat:
Zitat:
|
AW: Optimierung von Pixel
Zitat:
Habe das Bitmap auf 256 hochgesetzt dauert jetzt zwar 5 Sek länger aber was soll's Ich denke da kann man noch an verschiedenen stellen schrauben. Wenn ich analysiert habe warum ScanLine nicht das gewünschte Ergebnis liefert. wenn Pixel und ScanLine das gleiche liefern +- 1 Sec kann was nicht stimmen. gruss |
AW: Optimierung von Pixel
Zitat:
Zitat:
SetPixel: 4,0 s ScanLine: 1,5 s ohne Grafik: 1,3 s Rechnet man die Basiszeit von 1,3 s runter, ergeben sich 2,7 Sekunden bei SetPixel und 0,2 Sekunden bei Scanline. Das ist immerhin ein Faktor von 13,5! |
AW: Optimierung von Pixel
Zitat:
Wenn ja wie sieht die Aktualisierung aus? Mariah Carey - Breakdown.mp3 320k, 10,8 MB Pixel 5:97 sec (liegt daran weil mein Bitmap jetzt 256 Hoch ist) ScanLine kann ich im Moment nicht testen.. muss erst den Fehler vom Medium Code beheben. Fehler "Bereichsüberschreitung bei ZeilenIndex" wenn mein Buffer 256 groß ist. gruss |
AW: Optimierung von Pixel
Zitat:
|
AW: Optimierung von Pixel
Zitat:
gruss |
AW: Optimierung von Pixel
Zitat:
|
AW: Optimierung von Pixel
Zitat:
nach deinen Änderungen in dem Quellcode. OK. Ich habe es mal selbst gemacht. Und hänge deine Änderungen mal an. Ein Problem habe ich noch. Warum akzeptiert ScanLine keinen Buffer von 256?
Delphi-Quellcode:
BUFFER_SIZE = 256;
funktioniert mit Pixel aber nicht mit ScanLine. Dort muss ich den Buffer mit 255 definieren. PS: Nach deinen Änderungen Mariah Carey - Breakdown.mp3 320k, 10,8 MB Pixel 05:72 sec ScanLine 02:41 sec Das ist doch schon mal was und man sieht einen merkbaren Unterschied. gruss |
AW: Optimierung von Pixel
Aktueller Test.. Denke diese ScanLine Optimierung von Uwe ist bisher die beste.
Alt: erster Versuch Das analysieren einer MP3 "Pink Floyd - Echoes"
ScanLine: 109138 ticks Pixel: 109404 ticks Letzte: Optimiert von Uwe
ScanLine: 7971 ticks 07:97 sec Pixel: 19500 ticks 19:50 sec Das ist doch schon mal ein Riesen fortschritt.
Delphi-Quellcode:
gruss
SetLength(Buffer, BUFFER_SIZE);
ColumnCounter := 0; start := GetTickCount; 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 P := ScanLines[BUFFER_SIZE - i]; HSLtoRGB(H, S, L, P^.rgbtRed, P^.rgbtGreen, P^.rgbtBlue); end else begin HSLtoRGB(H, S, L, R, G, B); Bitmap.Canvas.Pixels[ColumnCounter, BUFFER_SIZE - i] := RGB(R, G, B) 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; |
AW: Optimierung von Pixel
Wenn du die Zuweisung auf Pixels auskommentierst und im Pixel-Mode laufen lässt, erfolgt gar keine Grafikausgabe. Das ist die untere Grenze für die Laufzeit. Die Differenz zu den Laufzeiten bei aktiver Grafikausgabe (Pixel oder Scanline) ist dann die eigentliche Zeit, die für die Grafikausgabe benötigt wird.
|
AW: Optimierung von Pixel
Zitat:
dann benötige ich für die Grafik gerade mal 2 Sekunden. Pixel mit Grafik 19 sec ohne 9 Hier sind es hingegen schon 10 Sekunden. Man merkt auf jeden fall das sich etwas getan hat. gruss |
AW: Optimierung von Pixel
Ws st dnn 9?
|
AW: Optimierung von Pixel
Zitat:
gruss |
AW: Optimierung von Pixel
Zitat:
Letztlich ist aber die Variante, die die Scanlines puffert, sicherlich schneller. Mich würde aber dennoch interessieren, wo das Problem mit meinem Vorschlag war, wo ein 1-zeiliges Bitmap gedreht ge-PlgBlt-ed wurde. Mangels Delphi kann ich das gerade nicht weiter testen, aber noch sehe ich mildes Potenzial darin. |
AW: Optimierung von Pixel
Zitat:
EDIT: Ok es liegt daran weil die Schleife bei 0 anfängt und
Delphi-Quellcode:
nun mal 256 sind das hat zur folge das P dann nicht initialisiert wird und NIL ist.
ScanLines[BUFFER_SIZE - i]
muss halt auf NIL prüfen Wie gesagt schade das der Channel bei dir 0 ist. Zitat:
Ich hatte Probleme bei der Grafik Darstellung kann natürlich auch daran liegen das ich deinen Code falsch interpretiert habe und deshalb die Implementierung fehlgeschlagen ist. Versucht habe ich es auf jeden fall :) Zitat:
gruss |
AW: Optimierung von Pixel
Zitat:
Delphi-Quellcode:
Wenn du diese Funktion mit dem Parameter BASS_DATA_FFT512 aufrufst, werden immer zwingend 256 Single-Werte ab der Speicherposition des ersten Elementes deines Arrays geschrieben. Selbst wenn dein Array nur 1 Element lang wäre. Die Prozedur weiss nicht wie lang das Array ist, und geht - weil du mit BASS_DATA_FFT512 aufgerufen hast - davon aus, dass du dafür gesorgt hast, dass der Speicher lang genug reserviert ist.
function GetData(aChannel, aMaxData, aPosition: Integer): Single;
begin ... end; procedure BASS_ChannelGetData(aChannel: Integer; buf: Pointer, aDataType: TBassDataType); var i: Integer; begin case aDataType of BASS_DATA_FFT256: for i := 0 to 127 do Single((buf+(i*4))^) := GetData(aChannel, 127, i); BASS_DATA_FFT512: for i := 0 to 255 do Single((buf+(i*4))^) := GetData(aChannel, 255, i); BASS_DATA_FFT1024: for i := 0 to 511 do Single((buf+(i*4))^) := GetData(aChannel, 511, i); ... end; end; Wenn dies nicht der Fall ist, liegen im Speicher hinter dem zu kurzen Array potenziell andere Variablen, möglicherweise sogar welche, die überhaupt nichts mit dem Programmteil zu tun haben, sondern vielleicht irgendwas in der VCL oder weiss der Geier. Die DLL würde diese dann ohne Gnade überschreiben, und wenn sie dann später mal gebraucht würden, knallt es. Auch wieder möglicherweise an komplett anderen Stellen, die keinen Rückschluss darauf zulassen, dass der eigentliche Fehler hier an dieser Stelle passiert ist. Wenn man sich solche Schnitzer eingefangen hat, kann man in größeren Programmen Tage bis Wochen damit verbringen sie zu finden. Anderes Thema: ---------------------------------- Ich habe erst jetzt realisiert, dass du ja gar nicht beim Abspielen "live" das FFT Bild malst, sondern vorab! Das eröffnet eine interessante Möglichkeit: Man könnte das Bild zunächst um 90° gedreht auf ein Puffer-Bitmap zeichnen, weil du damit dann nämlich schön alle Zeilen (lies: Scanlines) nacheinander durchgehen kannst, und nicht wie jetzt diese puffern und umherspringen musst. Das fertige Puffer-Bitmap zum Schluss dann mit PlgBlt() gedreht in das Image malen, und fertig. Das sollte ruck zuck gehen. Leider hast du alle Anhänge gelöscht (wieso!?!?), so dass ich das nicht testweise bauen kann. Schade. |
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 20:41 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