Autor Beitrag
Dunkel
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 682

Mac OS X Snow Leopard
Xcode 3.1
BeitragVerfasst: Mo 29.12.08 20:35 
Hallo zusammen!

Ja, interessanter Thread-Titel, nicht wahr? :wink:

Was verbirgt sich hinter dem TPCMDrawer? Und wie, zum Belzebub, kann man Bilder hören?


Ein wenig zur Vorgeschichte:
Der werte User user profile icondelfiphan hat vor ziemlich genau 2 Jahren ein Rätsel gepostet. Vor 2 Tagen habe ich, beim Stöbern im Forum, genau diese MP3-Datei entdeckt, runtergeladen, mir angehört - und ich war baff, als ich die Auflösung des Rätsels von ihm gesehen habe.
Nach dem dann die Faszination ein wenig nachgelassen hat und ich wieder klar denken konnte :wink: habe ich mich mit der BASS.dll dran gemacht, ähnliche Töne zu kreieren. Das hat auch irgendwann (nach studieren der RIFF WAVE-Spezifikationen, aufarbeiten der theoretischen Hintergründe, ziemlich viel Verzweiflung, ein Schubs in die richtige Richtung von user profile icondelfiphan [vielen Dank nochmal dafür!] und einer Nacht drüber schlafen) recht gut geklappt. Dann habe ich aus dem Projekt, welches die BASS.dll benötigt eine 190-Zeilen-Klasse ohne irgendwelche externen Abhängigkeiten (DLLs, Units, etc.) gebastelt.

Und genau diese PCMDrawer.pas, mit der man ohne großen Aufwand recht nett anzuhörende/anzusehende Audio-Dateien erstellen kann, stelle ich der OpenSource-Gemeinde, unter der "Creative Commons Attribution-ShareAlike (CC by-sa)"-Lizenz zur Verfügung. Kurz gesagt: Ihr könnt alles damit machen, solange Ihr meine Wenigkeit in Euren Resultaten erwähnt und die Projekte in ähnlicher Form verbereitet werden.

Im Anhang befindet sich die PCMDrawerDemo.zip, in der sich der komplette Sourcecode inklusive einer Demo-Echse und einem Kompilat der Demo befindet. In der Beispiel.zip befindet sich eine Bitmap-Datei und das (zu einer MP3 komprimierte) Ergebnis der Demo.


Zum Ansehen der Töne empfehle ich, wie auch user profile icondelfiphan im zitierten Thread, www.tyberis.com/download/SAnalyze.exe.

Viel Spaß damit!

Grüße
Michael
Einloggen, um Attachments anzusehen!
_________________
Ich streite einsam mich mit dieser Oberflächenwelt
Gutes sei ein löblich Brot von dem ich zehre - bis zum Tod [Das Ich - Im Ich]


Zuletzt bearbeitet von Dunkel am Fr 23.01.09 23:22, insgesamt 3-mal bearbeitet
JayEff
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2971

Windows Vista Ultimate
D7 Enterprise
BeitragVerfasst: Mo 29.12.08 21:40 
Außerordentlich cool. :zustimm:

Kleinigkeit: ich frage mich, ob es möglich ist, eine Callback-Prozedure einzubauen, die man dann als Progress benutzen kann. Soll heißen, ich geb der Komponente einen Prozedurenzeiger und sie führt ihn beim konvertieren aus, wobei natürlich ein Wert für z.b. Progressbar.min / max interessant wäre.
Ah, da das eine Komponente ist, wieso nicht gleich ein onProgress ereigniss!
Auf jedenfall ist das eine witzige Idee - funktioniert halt am besten bei Schwarzweiß-bildern einer bestimmten größe, zumindest wenn man das Analysetool von delphifan benutzt, aber trotzdem..!

_________________
>+++[>+++[>++++++++<-]<-]<++++[>++++[>>>+++++++<<<-]<-]<<++
[>++[>++[>>++++<<-]<-]<-]>>>>>++++++++++++++++++.+++++++.>++.-.<<.>>--.<+++++..<+.
Dunkel Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 682

Mac OS X Snow Leopard
Xcode 3.1
BeitragVerfasst: Mo 29.12.08 22:20 
user profile iconJayEff hat folgendes geschrieben Zum zitierten Posting springen:
Außerordentlich cool. :zustimm:

Vielen Dank!

user profile iconJayEff hat folgendes geschrieben Zum zitierten Posting springen:

Kleinigkeit: ich frage mich, ob es möglich ist, eine Callback-Prozedure einzubauen, die man dann als Progress benutzen kann. Soll heißen, ich geb der Komponente einen Prozedurenzeiger und sie führt ihn beim konvertieren aus, wobei natürlich ein Wert für z.b. Progressbar.min / max interessant wäre.

Hör' mal, das ist erst Version 0.1 dieser kleinen (aber feinen 8) ) Klasse. Aber daran habe ich auch schon gedacht; ein Thread würde sich auch anbieten, finde ich. Ich bastle nach wie vor daran.

user profile iconJayEff hat folgendes geschrieben Zum zitierten Posting springen:

Auf jedenfall ist das eine witzige Idee - funktioniert halt am besten bei Schwarzweiß-bildern einer bestimmten größe, zumindest wenn man das Analysetool von delphifan benutzt, aber trotzdem..!

v0.1 hat nur die schwarzen Pixel [RGB(0,0,0)] hörbar gemacht, lokal werden nun auch "Graustufen" abgebildet.
Edith flüstert: Ach ja, bis jetzt werden nur Bitmaps mit einer maximalen Höhe von 250 Pixeln komplett dargestellt, in der Breite sind selbstverfreilich keine Grenzen gesetzt.

btw. mein Player AudioDB kann auch solch ein Sonagramm darstellen, sogar in Farbe und bunt; probier es mal damit (wobei ich sagen muss, dass AudioDB die Grafik mehr in die Länge zieht, damals wusste ich halt noch nicht, dass ich so einen Unsinn mit Tönen veranstallten werde... :wink: )

_________________
Ich streite einsam mich mit dieser Oberflächenwelt
Gutes sei ein löblich Brot von dem ich zehre - bis zum Tod [Das Ich - Im Ich]
Dunkel Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 682

Mac OS X Snow Leopard
Xcode 3.1
BeitragVerfasst: Di 30.12.08 02:29 
Direkt mal eine neue Version inklusive Bugfix, da der Header der Wave-Datei nicht WMP-konform geschrieben wurde.
TPCMDrawer kann jetzt auch "Graustufen" darstellen, vorher wurden nur alle schwarzen [RGB(0,0,0)] Pixel hörbar gemacht. Alle Änderungen vom omata wurden übernommen. Die Klasse ist jetzt von TThread abgeleitet, ob es auch so funktioniert wie es funktionieren soll - keine Ahnung, ich hab jetzt auch kein Bock mehr das ausgiebig zu testen :lol: .

Der Download im ersten Beitrag wurde entsprechend aktualisiert.

_________________
Ich streite einsam mich mit dieser Oberflächenwelt
Gutes sei ein löblich Brot von dem ich zehre - bis zum Tod [Das Ich - Im Ich]
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Di 30.12.08 15:20 
Sehr schön :D Satt schwarz-weiss könnte man jetzt noch Graustufenbilder zulassen ;) Oder geht das schon?

Da die Energie (die in den meisten Programmen angezeigt wird) quadratisch zur Amplitude ist müsstest du ganz einfach die Wurzel der Helligkeit als Amplitude nehmen und schon würde das klappen ;)
JayEff
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2971

Windows Vista Ultimate
D7 Enterprise
BeitragVerfasst: Di 30.12.08 19:33 
user profile icondelfiphan hat folgendes geschrieben Zum zitierten Posting springen:
Sehr schön :D Satt schwarz-weiss könnte man jetzt noch Graustufenbilder zulassen ;) Oder geht das schon?
user profile iconDunkel hat folgendes geschrieben Zum zitierten Posting springen:
TPCMDrawer kann jetzt auch "Graustufen" darstellen, vorher wurden nur alle schwarzen [RGB(0,0,0)] Pixel hörbar gemacht.
;)

Ich finde die erzeuge WAV etwas zu leise, wäre gut, wenn das lauter ginge, ausserdem hat deine neue Version von der Demo nicht die ganze Datei ausgewertet, sondern nur die obere Hälfte - dafür war die "Auflösung" des erzeugten "Bildes" in der Frequenzanalyse viel höher, nicht übel!

Dein Demoprojekt friert beim konvertieren immernoch ein, bist du dir sicher, dass du es in einem abgespaltenen Thread rechnen lässt? :shock:

Wie auch immer, ich find's klasse - Wie wär's jetzt noch, wenn du ein farbiges Bild erstmal in Graustufen umrechnen lässt (ist ja nicht schwer, ich hab einen Libraryeintrag dazu, moment... www.delphi-library.d...iewtopic.php?t=70493 Diese Prozedur mit den Parametern StepsCount = Step = 1 und darkness = 0 müsste das gewünschte Ergebnis erzielen.)?

_________________
>+++[>+++[>++++++++<-]<-]<++++[>++++[>>>+++++++<<<-]<-]<<++
[>++[>++[>>++++<<-]<-]<-]>>>>>++++++++++++++++++.+++++++.>++.-.<<.>>--.<+++++..<+.
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Di 30.12.08 19:55 
@JayEff: :oops: hatte nicht den ganzen Thread gelesen, nur das Beispiel angeschaut ;)

user profile iconDunkel hat folgendes geschrieben Zum zitierten Posting springen:
AudioDB die Grafik mehr in die Länge zieht

Die Umkehrrechnung von Wav zu einzelnen Frequenzen ist leider nicht eindeutig :( Da hier mit Wellen gearbeitet wird gibt's genau wie in der Quantenphysik eine Unschärferelation. Beim Zurückrechnen der ursprünglichen Daten hat man entweder eine bessere Auflösung in der Zeit und eine schlechtere Frequenzauflösung oder umgekehrt. Eine exakte Rekonstruktion ist im allgemeinen Fall nicht möglich. :(
Es gibt auch Programme, die zeigen das ganze auf einer logarithmischen Skala an. Das kann das Bild dann nochmals etwas verzerren.
Dunkel Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 682

Mac OS X Snow Leopard
Xcode 3.1
BeitragVerfasst: Di 30.12.08 21:38 
user profile iconJayEff hat folgendes geschrieben Zum zitierten Posting springen:
Ich finde die erzeuge WAV etwas zu leise, wäre gut, wenn das lauter ginge,

Hmmm... bei manchen Bildern kann man's lauter machen, bei manchen übersteuert die Ausgabe da zu sehr, so dass keine klaren Geräusche/Bilder mehr generiert werden. Ich bastle momentan an einem GUI um diverse Einstellungen komfortabel vornehemn zu können.

user profile iconJayEff hat folgendes geschrieben Zum zitierten Posting springen:
ausserdem hat deine neue Version von der Demo nicht die ganze Datei ausgewertet, sondern nur die obere Hälfte - dafür war die "Auflösung" des erzeugten "Bildes" in der Frequenzanalyse viel höher, nicht übel!

Nur die obere Hälfte? OK....

user profile iconJayEff hat folgendes geschrieben Zum zitierten Posting springen:

Dein Demoprojekt friert beim konvertieren immernoch ein, bist du dir sicher, dass du es in einem abgespaltenen Thread rechnen lässt? :shock:

Die Klasse TPCMDrawer ist nur von TTHread abgeleitet, das Demoprojekt nutzt diese Möglichkeit aber noch nicht. Der Quellcode ist für alle da, viel Spaß beim Umschreiben auf eine gethreadete Version. :wink:

user profile iconJayEff hat folgendes geschrieben Zum zitierten Posting springen:

Wie auch immer, ich find's klasse - Wie wär's jetzt noch, wenn du ein farbiges Bild erstmal in Graustufen umrechnen lässt (ist ja nicht schwer, ich hab einen Libraryeintrag dazu, moment... www.delphi-library.d...iewtopic.php?t=70493 Diese Prozedur mit den Parametern StepsCount = Step = 1 und darkness = 0 müsste das gewünschte Ergebnis erzielen.)?

Ja, hab ich auch schon drüber nachgedacht. Da Ergebnis von bunten Bildern ist nicht wirklich pralle. Mal schaun'.

Edith flüstert: hab ich gerade testweise implementiert; kein Unterschied zu meiner Methode
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
  color:= fBitmap.Canvas.Pixels[fBitmapPosCounter, fBitmap.Height - i];
  r:= GetRValue(color);
  g:= GetGValue(color);
  b:= GetBValue(color);
  if fRevertColor then
    c:= 255 - ((r+b+g) div 3)
  else
    c:= ((r+b+g) div 3);

Farben in "Pseudo-Graustufen" zu verwandeln. Ich lasse es trotzdem mal als Option drin. Danke!

_________________
Ich streite einsam mich mit dieser Oberflächenwelt
Gutes sei ein löblich Brot von dem ich zehre - bis zum Tod [Das Ich - Im Ich]
Dunkel Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 682

Mac OS X Snow Leopard
Xcode 3.1
BeitragVerfasst: Do 01.01.09 19:10 
Ich hab' mal ein wenig dran weitergebastelt.

Das Demoprojekt ist jetzt auch endlich erwachsen, Laden von Bitmaps und JPEGs funktioniert via Drag&Drop aus dem Explorer, die Bilder können verkleinert/vergrößert werden, an diversen Einstellungen kann nach Lust und Laune herumgespielt werden, Threading ist endlich implementiert.

ToDos: Geschwindigkeit! Mal gucken, ob man Multithreading implementieren kann.

Viel Spaß damit!

_________________
Ich streite einsam mich mit dieser Oberflächenwelt
Gutes sei ein löblich Brot von dem ich zehre - bis zum Tod [Das Ich - Im Ich]
JayEff
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2971

Windows Vista Ultimate
D7 Enterprise
BeitragVerfasst: Do 01.01.09 21:13 
user profile iconDunkel hat folgendes geschrieben Zum zitierten Posting springen:
ToDos: Geschwindigkeit! Mal gucken, ob man Multithreading implementieren kann.
Bevor du mit multithreading anfängst, konvertiere mal dashier:
ausblenden 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:
procedure TPCMDrawer.ReadPictureData;
var
  i: integer;
  r, g, b, c: byte;
  color: integer;
begin
  for i := 0 to fBitmap.Height - 1 do
    begin
      color := fBitmap.Canvas.Pixels[fBitmapPosCounter, fBitmap.Height - i];
      r := GetRValue(color);
      g := GetGValue(color);
      b := GetBValue(color);
      if fReverseColors then
        c := 255 - ((r+b+g) div 3)
      else
        c := ((r+b+g) div 3);

      if c >= cIgnoreColorLower then
        fPixelData[i].Amplitude := Trunc(c / 255 * fAmplitude)
      else
        fPixelData[i].Amplitude := 0;
     end;
  Inc(fBitmapPosCounter);
end;
in Scanline Code... Es kann sein, dass du die bitmap erstmal kippen musst, da du ja spaltenweise konvertieren musst und es scheinbar kein Scanline für Spalten gibt. Scanline ist schneller als pixels. SEHR viel schneller:
ausblenden volle Höhe 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:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
procedure TForm1.Button2Click(Sender: TObject);
type
  pixel = array[0..2of byte;
var
  p : ^pixel;
  x, y : Integer;
  ticks : Cardinal;
begin
  ticks := GetTickCount;
  for y := 0 to Image1.ClientHeight - 1 do
  begin
    p := Image1.Picture.Bitmap.ScanLine[y];
    for x := 0 to Image1.ClientWidth do
    begin
      p^[0] := Byte(p^[0] + 100);
      p^[1] := Byte(p^[1] + 100);
      p^[2] := Byte(p^[2] + 100);
      inc(p);
    end;
  end;
  Label1.Caption := IntToStr(GetTickCount - ticks);
  Image1.Refresh;
end;

procedure TForm1.Button3Click(Sender: TObject);
var
  x, y : Integer;
  c : TColor;
  r, g, b : Byte;
  ticks : Cardinal;
begin
  ticks := GetTickCount;
  for x := 0 to Image1.ClientWidth do
    for y := 0 to Image1.ClientHeight do
    begin
      c := Image1.Canvas.Pixels[x, y];
      r := GetRValue(c);
      g := GetGValue(c);
      b := GetBValue(c);
      r := Byte(r + 100);
      g := Byte(g + 100);
      b := Byte(b + 100);
      Image1.Canvas.Pixels[x, y] := RGB(r, g, b);
    end;
  Label1.Caption := IntToStr(GetTickCount - ticks);
end;

Das Image ist 937x449px groß. Button3 braucht 2600 ms. Button2 braucht unter 1 ms. Nur so zum Vergleich. :mrgreen:

_________________
>+++[>+++[>++++++++<-]<-]<++++[>++++[>>>+++++++<<<-]<-]<<++
[>++[>++[>>++++<<-]<-]<-]>>>>>++++++++++++++++++.+++++++.>++.-.<<.>>--.<+++++..<+.
Dunkel Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 682

Mac OS X Snow Leopard
Xcode 3.1
BeitragVerfasst: Do 01.01.09 22:39 
Danke für den Vorschlag, werde ich auf jeden Fall implementieren. :D

Mit Multithreading habe ich angefangen, die ersten Versuche mit 2 Threads (ich habe ein DualCore, deswegen bietet sich das an) bringen in etwa 40% Geschwindigkeitszuwachs. Mit Scanline ist da wahrscheinlich noch wesentlich mehr rauszuholen. I'll try...

_________________
Ich streite einsam mich mit dieser Oberflächenwelt
Gutes sei ein löblich Brot von dem ich zehre - bis zum Tod [Das Ich - Im Ich]
Dunkel Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 682

Mac OS X Snow Leopard
Xcode 3.1
BeitragVerfasst: Fr 23.01.09 23:22 
Lange nicht mehr dran weitergebastelt und doch ist zwischenzeitlich das Projekt gewachsen. :)

Ich hab mal ein neues ZIP-Archiv an den ersten Beitrag gepinnt. In ihr befindet sich ein etwas ausgereifter Editor, um Geräusche aus Bildern zu kreieren. Mit integriert ist auch eine Sonagramm-Visualisierung.

Den Quelltext der TPCMDrawer-Klasse muss ich noch ein wenig "schönschreiben", dann werde ich ihn auch im ersten Beitrag aktualisieren.

_________________
Ich streite einsam mich mit dieser Oberflächenwelt
Gutes sei ein löblich Brot von dem ich zehre - bis zum Tod [Das Ich - Im Ich]