![]() |
Problem mit Oszilloskop-Darstellung
Liste der Anhänge anzeigen (Anzahl: 2)
Grüße, liebe Community.
Ich habe das Problem, ein Oszilloskop ordentlich darzustellen. Die Daten kommen als ein Byte-Strom von einer Audio-Quelle (TAudioIn-Komponente, LineIn / Mikro) und werden in einem BufferFilled-Event verarbeitet. Dabei werden sie (wegen Stereo) in Links / Rechts getrennt und (wegen 16bit) in Words konvertiert und danach in zwei TImages gezeichnet. Soweit die Theorie. Die Praxis sieht jedoch so aus, dass ein ziemlich Grafik-Salat auf den Bildschirm gezaubert wird, statt einem gewünschten sauberen Oszilloskop. Nur der rechte Kanal (unten) sieht annähernd einem Oszilloskop ähnlich. (Siehe Anhang 1, Bild) Der Author der "TAudio"-Komponente hat auch ein kleines Oszilloskop-Beispiel als PPT-Präsentation auf seiner HP ( ![]() Hier mal mein Code. Sorry, wenn einige Teile umständlich programmiert sind, aber ich bin nicht unbedingt das Abstraktions- und Mathegenie. :mrgreen: Ich habe das Problem auch mal als kleines Demo-Programm angehängt, inkl. Komponente und .exe-Datei (nat. frei von irgendwelchem "Müll"). (Anhang 2, Zip-Archiv) Wäre nett, wenn da mal jemand drüber schauen und mich erleuchten könnte, was ich falsch mache. ;)
Delphi-Quellcode:
type
TDataArray = Array of Byte; TWordDataArray = Array of Word; procedure DrawOscilloscope (Buffer: PChar; Size: Integer; OscRight, OscLeft: TBitmap; LW, LH, RW, RH: Integer); // ---------------- procedure CreateLocalBitmaps (var bmpL, bmpR: TBitmap); begin bmpL := TBitmap.Create; bmpL.Width := LW; bmpL.Height := LH; // **** bmpL.Canvas.Pen.Width := 1; bmpL.Canvas.Pen.Color := clRed; bmpL.Canvas.MoveTo (0, round (bmpL.Height / 2)); bmpL.Canvas.LineTo (bmpL.Width, round (bmpL.Height / 2)); bmpL.Canvas.Pen.Width := 1; bmpL.Canvas.Pen.Color := clGreen; // **** bmpR := TBitmap.Create; bmpR.Width := RW; bmpR.Height := RH; // **** bmpR.Canvas.Pen.Width := 1; bmpR.Canvas.Pen.Color := clRed; bmpR.Canvas.MoveTo (0, round (bmpR.Height / 2)); bmpR.Canvas.LineTo (bmpR.Width, round (bmpR.Height / 2)); bmpR.Canvas.Pen.Width := 1; bmpR.Canvas.Pen.Color := clGreen; end; // ---------------- procedure FreeLocalBitmaps (var bmpL, bmpR: TBitmap); begin FreeAndNil (bmpL); FreeAndNil (bmpR); end; // ---------------- procedure FillBuffer (Buffer: PChar; StartIndex, BufferSize: Integer; out FilledBuffer: TDataArray); var a, b: Integer; begin SetLength (FilledBuffer, 0); a := StartIndex; repeat b := Length (FilledBuffer); SetLength (FilledBuffer, b + 1); FilledBuffer[b] := Byte (Buffer[a]); inc (a, 2); if (a > BufferSize) then break; until FALSE; end; // ---------------- procedure CheckBufferLengths (var BufferL, BufferR: TDataArray); var l1, l2: Integer; begin l1 := Length (BufferL); l2 := Length (BufferR); if (l1 > l2) then begin SetLength (BufferL, l2); l1 := l2; end; if (l2 > l1) then begin SetLength (BufferR, l1); l2 := l1; end; end; // ---------------- procedure MakeWordBuffer (Buffer: TDataArray; var WordBuffer: TWordDataArray); var a, b, l: Integer; begin SetLength (WordBuffer, 0); // **** l := Length (Buffer); a := 0; repeat b := Length (WordBuffer); SetLength (WordBuffer, b + 1); WordBuffer[b] := MakeWord (Buffer[a + 1], Buffer[a]); inc (a, 2); if (a > l) then break; until FALSE; end; // ---------------- function SampleToScreen (Buffer: TWordDataArray; SampleIndex: Integer):Integer; begin Result := Round (Buffer[SampleIndex] * LH / High (Word)); end; var BufferL, BufferR: TDataArray; WordBufferL, WordBufferR: TWordDataArray; b, a, N: Integer; bmpL, bmpR: TBitmap; begin // Lokale temp. Bitmaps erstellen CreateLocalBitmaps (bmpL, bmpR); // **** // Puffer nach L & R trennen FillBuffer (Buffer, 0, Size, BufferL); FillBuffer (Buffer, 1, Size, BufferR); // **** // Pufferlängen ggf. abgleichen CheckBufferLengths (BufferL, BufferR); // **** // Puffer-Bytes nach Word konvertieren MakeWordBuffer (BufferL, WordBufferL); MakeWordBuffer (BufferR, WordBufferR); // **** // In lokale Bitmaps zeichnen ... bmpL.Canvas.LineTo (0, SampleToScreen (WordBufferL, 0)); bmpR.Canvas.LineTo (0, SampleToScreen (WordBufferR, 0)); N := Size div 4; b := LW; if N < b then b := N; for a := 0 to b - 1 do begin bmpL.Canvas.LineTo (round (a * LW / b), SampleToScreen (WordBufferL, round (a * N / b))); bmpR.Canvas.LineTo (round (a * LW / b), SampleToScreen (WordBufferR, round (a * N / b))); end; // ... und an "öffentliche" Bitmaps übergeben OscLeft.Assign (bmpL); OscRight.Assign (bmpR); // Daten freigeben FreeLocalBitmaps (bmpL, bmpR); end; |
Re: Problem mit Oszilloskop-Darstellung
Ok, mir sind grad die Tomaten von den Augen gefallen ... :wall: ... Schuss in's Knie :firejump:
|
Re: Problem mit Oszilloskop-Darstellung
;) na, die Daten sind nicht unsigned sondern haben ein Vorzeichen. Du hast also mit ShortInt und SmallInt zu arbeiten und dein Oszi muß bei der Ausgabe von einer virtuellen X Achse ausgehen die zb. bei 128 Pixeln liegt wenn du Byte (SmallInt) daten anzeigen möchtest. Richtig ?
Gruß Hagen |
Re: Problem mit Oszilloskop-Darstellung
Hallo Hagen,
ja, so in die Richtung lag der Fehler. Ich hab mir auch den Umweg gemacht, die Daten Byteweise nach Word zu konvertieren, statt diese zu Typecasten (z.B. mit DatenPuffer := Pointer (Buffer) oder CopyMemory (@DatenPuffer, Buffer, Size), wobei DatenPuffer ein Array[...] of SmallInt ist). Auch habe ich einen Schusselfehler gehabt, den Anfangscursor nicht mit MoveTo zu setzen, sondern habe LineTo verwendet. >.< |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:09 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz