-
Forum: Multimedia
by Zacherl,
11. Apr 2016
Das hatte ich irgendwo weiter vorne auch schon in Betracht gezogen. Sprich: ScanLine von der ersten Zeile anfordern und danach den Begin er weiteren Zeilen im zurückgelieferten Zeiger manuell berechnen.
Allerdings gibt es da ein paar Edge-Cases, die man beachten müsste. Windows erlaubt z.b. Bottom-up Bitmaps, bei denen man die Indizes der Zeilen invertieren müsste. Auch kann man die Zeilen...
-
Forum: Multimedia
by Zacherl,
11. Apr 2016
Ganz normale Calls sind in der Regel zu vernachlässigen. Hat man natürlich bisschen Overhead durch das Pushen der Rücksprungadresse und je nach Aufrufkonvention der Parameter, aber Performance-kritisch wird das nicht.
Frequente Aufrufe bestimmter Windows APIs können allerdings durch den Kontext-Switch in Kernel-Mode und wieder zurück (SYSENTER) extrem teuer sein.
-
Forum: Multimedia
by Zacherl,
8. Apr 2016
Das ist alles korrekt. Du darfst zu wenig lesen, aber du darfst nicht zu viel lesen und ebenfalls nicht zu viel schreiben. Aber genau das zu viel Schreiben passiert beim BASS_ChannelGetData(Channel, Pointer(Buffer), BASS_DATA_FFT512) Aufruf.
Laut Dokumentation werden mit dem FFT512 Parameter 256 Floats geschrieben, also 1024 Bytes.
Nach eine generelle Frage:
Würde es nicht mehr Sinn...
-
Forum: Multimedia
by Zacherl,
8. Apr 2016
Hier SetLength(Buffer, BUFFER_SIZE); // Reserviert Speicher für 159x Single/Float und hier BASS_ChannelGetData(Channel, Pointer(Buffer), BASS_DATA_FFT512); // Schreibt 256x Single/Float in den Buffer
-
Forum: Multimedia
by Zacherl,
8. Apr 2016
Genau das verursacht einen schönen Buffer Overflow, weil BASS_ChannelGetData mit BASS_DATA_FFT512 trotzdem 256 Floats einliest, der Buffer aber nur Platz für 159 Stück hat.
-
Forum: Multimedia
by Zacherl,
8. Apr 2016
Die Farben sind irgendwie anders. Aber das Problem liegt nicht zwingend in deinem Code :lol: Es gibt diverse Buffer Overflows in der Analyse Funktion, die das wohl verursachen werden. BASS_ChannelGetData mit BASS_DATA_FFT512 liefert nämlich 256 Float Values, aber das Buffer Array ist nur für 159 Floats Platz hat. Deshalb sieht die grafische Darstellung generell schon irgendwie gestaucht / falsch...
-
Forum: Multimedia
by Zacherl,
8. Apr 2016
Das bringt dir schonmal ne ganze Menge Performance:
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;
Application.ProcessMessages;
end;
-
Forum: Multimedia
by Zacherl,
8. Apr 2016
Bei meiner Delphi Version schon. Als Workaround könntest du das Refreshen immer nur dann ausführen, wenn sich wirklich der Progress geändert hat im Vergleich zum vorherigen Durchgang des Loops. Das wären dann maximal 100 Aufrufe im ganzen Loop.
-
Forum: Multimedia
by Zacherl,
8. Apr 2016
Habe es bei mir zum Testen ebenfalls auskommentiert. Das Application.ProcessMessages auch. Trotzdem sehe ich den Fortschritt .. ist das bei dir nicht der Fall?
Der Vorteil skaliert halt stark mit der Größe des Bitmaps. Würde auf jeden Fall trotzdem ScanLine benutzen.
-
Forum: Multimedia
by Zacherl,
8. Apr 2016
PB.Refresh verbraucht fast deine ganze CPU Zeit.
-
Forum: Multimedia
by Zacherl,
8. Apr 2016
Hat mich selbst stark gewundert, weil der erste Aufruf von ScanLine den Bitmap-Buffer eigentlich cached. Allerdings werden da neben dem Anfordern des Buffers noch 100 andere Sachen in der Funktion gemacht, die ich mir jetzt nicht genauer angeschaut habe. Diese Funktionen werden wohl der Grund für den Performanceverlust sein.
-
Forum: Multimedia
by Zacherl,
8. Apr 2016
Mediums Funktion ist sogar LANGSAMER als Canvas.Pixels :lol: Mein Testcode
var
B: TBitmap;
X, Y: Integer;
P: PRGBTriple;
C: Cardinal;
begin
B := TBitmap.Create;
try
B.PixelFormat := pf24Bit;
-
Forum: Multimedia
by Zacherl,
7. Apr 2016
Die API kopiert ja soweit ich weiß auch nur den Inhalt des Bitmaps und du benötigst dann SetDIBits zum Ändern. Bei der ScanLine Methode arbeitest du direkt mit dem internen Speicher. Ohne Kopieren und ohne zusäzliche API Aufrufe. Die Performance sollte deshalb noch deutlich höher sein.
-
Forum: Multimedia
by Zacherl,
7. Apr 2016
Exzellenter Hinweis, wenn man die Wahl hat auf pf32Bit zu stellen. Ansonsten siehe meinen editierten Post.
Auch nur bei pf32Bit! Dann sollte man auch auf jeden Fall Neutral Generals Hinweis beachten. Dadurch wird der Code deutlich verständlicher. Und wie gesagt, sind die RGB Werte nicht in der korrekten Reihenfolge. HLSToRGB müsste bei deinem Ansatz deshalb entsprechend angepasst werden.
-
Forum: Multimedia
by Zacherl,
7. Apr 2016
Du kannst beides damit machen:
var
B: TBitmap;
X, Y: Integer;
P: PByte;
begin
B := TBitmap.Create;
try
B.PixelFormat := pf24Bit;
B.Width := 200;
-
Forum: Multimedia
by Zacherl,
7. Apr 2016
Prinzipiell wie mit Pixels, nur dass du jetzt jeweils eine Zeile des Bitmaps direkt füllen kannst (eventuell würde es sogar gehen mit dem Pointer der 1. Zeile sämtliche Daten zu schreiben, aber da Bitmapdaten auch nicht-durchgehend sein können , würde ich das vermutlich nicht riskieren).
Achten musst du nur auf die Anzahl der Bits pro Pixel. Meistens ist das in Delphi benutze Format pf24Bit....
-
Forum: Multimedia
by Zacherl,
7. Apr 2016
Canvas.Pixel macht bei JEDEM Aufruf einen API Call. Reine Schätzung, aber Canvas.ScanLine ist locker um den Faktor 1000 schneller (eher mehr). Dort schreibst du die Daten praktisch direkt in den internen Bitmapspeicher.
Einen Pixelbuffer brauchst du meiner Meinung nach nicht. Nichts anderes liefert Canvas.ScanLine doch: Einen Zeiger auf den Pixelbuffer des Bitmaps.