ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/docs/poster.sdf
Revision: 1.1
Committed: Sat Feb 3 23:05:01 2001 UTC (25 years, 7 months ago) by root
Branch: MAIN
CVS Tags: HEAD
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 !init OPT_STYLE="paper"
2    
3     !define DOC_NAME "Was Marc Zuhause macht, wenn ihm langweilig ist!"
4     !define DOC_AUTHOR "Marc Lehmann <pcg@goof.com>"
5     !build_title
6    
7     H1: Marc langweilt sich...
8    
9     immer dann, wenn er wenig Abwechslung hat. Wenn er vor einem (nicht
10     sonderlich lebensbedrohlichem und eigentlich völlig unwichtigem) Problem
11     steht, passiert es bisweilen, daß er versucht, es zu lösen. Allerdings
12     nicht sehr ernsthaft, weshalb die "Lösung" meist ein ganz anderes Problem
13     "löst". Manchmal kommt dabei ein Perl-Modul heraus, und einige davon
14     werden sogar veröffentlicht. Oder auf dem Perl-Workshop 2001 in einer
15     POSTER-Session vorgeführt...
16    
17     H2: PDL::Audio - Tonkrachklang mit Perl!
18    
19     Das Problem.. was war das Problem denn gleich noch.. Ach ja, ich wollte
20     die gesprochenen Texte für meinen Anrufbeantworter nachbearbeiten (damit
21     nicht jeder sofort erkennt, wen er anruft, ist ja schließlich nicht
22     die Aufgabe des Telefons... ;).
23    
24     Zuerst habe ich das mit dem freien Sound-Editor "snd" (tolles Ding!)
25     gemacht, teilweise in Scheme (Marc schüttelt sich). "Warum kann man
26     das nicht in Perl???" schrie ich verzweifelt (ich hätte auch ein
27     Kommandozeilentool genommen, so verzweifelt war ich). Jetzt kann man es,
28     und jede Menge zusätzliches Schnickschnack gibt es auch.
29    
30     H3: Code-Beispiele
31    
32     "The Basics". Audiodateien einlesen, ein Klacks:
33    
34     !block perl
35     use PDL;
36     use PDL::Audio;
37    
38     $wav = raudio "kongas.wav"; # Laden
39     $wav->scale2short->playaudio; # Abspielen
40     $wav->scale2short->playaudio(rate => 1000); # Grausam!
41     waudio $wav, "kongas.au"; # Und wieder Speichern!
42     !endblock
43    
44     Da Audiodaten sehr umfangreich sein können, kommt eine Speicherung als
45     normales Perl-Array nicht in Frage. Zum Glück gibt es {{die}} Lösung zur
46     Speicherung und Verarbeitung großer Datenmengen (Vektoren und Matrizen!)
47     in Perl, die {{Perl Data Language}} (PDL). Damit kann man nicht nur Daten
48     kompakt speichern, sondern auch damit rechnen, z.B. eine Wellenform
49     "normalisieren":
50    
51     !block perl
52     $wav -= min($wav);
53     $wav /= max($wav);
54     $wav = ($wav - 0.5) * 2
55     !endblock
56    
57     Oder eine Sinus-Schwingung erzeugen:
58    
59     !block perl
60     $sine = sin (zeroes(10000)->xlinvals(0,6.282));
61     !endblock
62    
63     C<PDL::Audio> hat viele solcher Generatoren für Wellenformen.
64    
65     Und nun: "The Worx". Ok, ich übertreibe, aber es ist nur ein Beispiel:
66    
67     !block perl
68     $snd = raudio "kongas.iff";
69     $snd *= gen_oscil $snd, 9/$snd->rate; # AM-Modulation "flirren"
70     $snd->scale2short->playaudio;
71     !endblock
72    
73     Oder ein bißchen Audio-Synthese (langweiliger Sinuston):
74    
75     !block perl
76     $envelope = gen_env (22500*2, pdl(0,1,2,15,16), pdl(0,1,0.9,0.7,0));
77     $snd = $envelope * gen_oscil $envelope, 900/22500;
78     $snd->scale2short->playaudio(rate => 22500);
79     !endblock
80    
81     Raumschift Enterprise läßt grüßen (FM-Synthese):
82    
83     !block perl
84     $env = gen_env (22050*2, pdl(0,1,2,15,16), pdl(0,1,0.9,0.7,0));
85     my $fm = gen_triangle $env, 16/22500;
86     $fm *= $fm->xlinvals(0,0.1);
87     $snd = $env * gen_oscil $env, 900/22500, 0, $fm;
88     $snd->scale2short->playaudio(rate => 22500);
89     !endblock
90    
91     Oder die original-Strong-Synthese, zum ersten Mal mit PDL!
92    
93     !block perl
94     my $pdl = zeroes 22500*5; # der "Ton"
95     my $freq = int (22500/220); # Grundfrequenz der Saite
96     my $x = $pdl->slice("0:".($freq-1)); $x .= gen_rand $x, 1;
97     # Am Anfang stehen nun Zufallszahlen, es folgt ein
98     # einfacher Filter:
99     $pdl = $pdl->filter_lir(0,1,pdl($freq,$freq+1),pdl(0.5,0.5));
100     $pdl->scale2short->playuaiod(rate => 22500);
101     !endblock
102    
103     Wer das (und mehr) hören will, braucht entweder PDL::Audio oder den
104     Perl-Workshop ;)
105    
106     H2: RCU - Mein Wecker: "Aus!"
107    
108     Irgendjemand hatte die dumme Idee, sich von seinem Anrufbeantworter
109     wecken zu lassen (der Anrufbeantworter versteht natürlich Perl). Nur
110     wie stellt man das Ding (es steht ziemlich weit weg) wieder ab, ohne
111     aufzustehen? Natürlich per Infrarot-Fernbedienung. Klar, dafür gibt es
112     auch ein Perl-Interface, genannt C<RCU> (für Remote-Control-Unit). Damit
113     kann man sein Programm per Linux-Lircd oder mittels Irman (ein sehr
114     populäres Empfangsgerät für Infrarot-Fernbedienungen) fernsteuern.
115    
116     H3: Beispiel, primitive Variante
117    
118     !block perl
119     use RCU;
120    
121     $rcu = new RCU "RCU:Irman";
122    
123     while (($keycode, $repeat) = $rcu->get) {
124     print "Taste $keycode wurde empfangen\n";
125     }
126     !endblock
127    
128     Gibt z.B.:
129    
130     !block verbatim
131     Taste 575000000000 wurde empfangen
132     Taste 55d000000000 wurde empfangen
133     Taste 558000000000 wurde empfangen
134     Taste 558000000000 wurde empfangen
135     !endblock
136    
137     Langweilig. Schlechtes Interface. Aber für Hacks ganz o.k.
138    
139     H3: Beispiel, korrekte Variante
140    
141     Fernbedienungen senden ihre Wiederholungssignale (z.B. wenn man die
142     "Lauter"-Taste lange gedrückt hält) in 0.2s, 0.02, 0.1s oder anderen
143     Intervallen, einen Standard gibt es nicht. Die meisten Programme ändern
144     die Lautstärke jedesmal in festen Schritten, d.h. beim Programmautor
145     klappt's toll, woanders aber weniger, weil es entweder zu langsam oder zu
146     schnell geht.
147    
148     Deshalb gilt: nur Taste-drücken-/Taste-loslassen-Ereignisse sind von
149     Belang, bzw. die Zeit dazwischen. Mit dem C<Event>-Modul ist es einfach:
150    
151     !block perl
152     use Event;
153     use RCU::Event;
154    
155     # ein Timer, der fünfmal pro Sekunde feuert
156     $forward = Event->timer(interval => 0.2, hard => 1, parked => 1, cb => sub {
157     print "Vorwärts, auf, auf!\n";
158     });
159    
160     # der "Kontext", in dem die Tasten interpretiert werden
161     my $ctx = new RCU::Context;
162     $ctx->bind(
163     "sony-cd-(\d+)" => sub { print "Taste ($_[0])\n" },
164     "sony-cd-fwd" => sub { $forward->at($_[1]); $forward->start },
165     "~sony-cd-fwd" => sub { $forward->stop },
166     "sony-cd-stop" => sub { Event::unloop },
167     );
168    
169     # Fernbedienung öffnen
170     $rcu = new RCU::Event "RCU:Irman";
171     # Startkontext setzen
172     $rcu->set_context($ctx);
173    
174     # und los!
175     Event::loop;
176     !endblock
177    
178     H2: Compress::LZF, wenns mal schnell gehen soll
179    
180     Was macht man, wenn man sehr viele "Datenpäckchen" speichern muss, die
181     alle unabhängig sind, Platz wegnehmen und ziemlich gut komprimierbar sind
182     (bei mir z.B. viele Hashes, die mit C<Storable> behandelt wurden). Klar,
183     man komprimiert sie. Aber irgendwie war da nichts richtig freies ("blöde
184     GPL, ich will das kommerziell ausbeuten!"), nichts richtig schnelles (LZO,
185     na gut, aber das ist so umständlich) und irgendwie alles so groß und
186     kompliziert.
187    
188     C<Compress::LZF> ist da anders, es ist klein:
189    
190     !block perl
191     -rwxr-xr-x 8236 Jan 13 19:36 LZF.so
192     !endblock
193    
194     verglichen mit anderen "Monstern":
195    
196     !block perl
197     -rwxr-xr-x 33417 Oct 18 21:56 Zlib.so
198     -rwxr-xr-x 60926 Nov 5 06:48 libz.so.1.1.3
199     !endblock
200    
201     Ausserdem ist es schnell (ja, echt!), frei (BSD-Lizenz), einfach zu
202     installieren (keine Library, kein autoconfig-Zeugs), klein, resistent
203     gegen Bitfehler in seinen Datenstrukturen (naja, wers braucht) und
204     komprimiert durchschnittlich halb so gut wie C<gzip -9> (Bei kleinen
205     Blöcken ist es allerdings viel besser ;), man kann nicht alles haben.
206    
207     Und die Bedienung ist nicht der Rede wert:
208    
209     !block perl
210     use Compress::LZF;
211    
212     $meist_kleiner = compress $data;
213     $original = decompress $meist_kleiner;
214     !endblock
215    
216     C<$meist_kleiner> ist auch in Extremfällen maximal ein Byte größer als
217     das Original.
218    
219     H2: Modem-VBox - Habe ich schon von meinem Anrufbeantworter erzählt?
220    
221     Ja, er spricht Perl, und damit auch C<Modem::VBox>, ein Modulchen,
222     mit dem man Anrufbeantworter, Voiceboxen oder anderes programmieren kann
223     (hey, es ist Perl!). Leider wurde es bisher nur mit Linux-ISDN eingesetzt,
224     aber die benutzten AT-Befehle sind eigentlich universell verbreitet.
225    
226     H3: Meine kleine Voicebox
227    
228     Das mitgelieferte Beispielskript ist etwas zu lang (unter anderem
229     verschickt es aufgenommene Gespräche per e-mail) um es ganz abzudrucken,
230     aber in aller Kürze sieht es so aus:
231    
232     !block perl
233     use Modem::VBox;
234    
235     # Wir VBoxen uns durch
236     $v = new Modem::VBox
237     line => $ARGV[0] || "/dev/ttyI1",
238     modeminit => 'ATZ&D2&B512&E9377358S13.4=0S13.2=1S13.6=0+FCLASS=8',
239     rings => 5, # connect after 5 rings
240     connect_cb => \&main_menu;
241     $v->loop;
242    
243     # Das Hauptmenü
244     sub main_menu {
245     my $context = $v->context->set(
246     # Beispiele für die Menüführung
247     "1\$" => [\&record_menu], # Taste "1": Nachricht hinterlassen
248     "2\$" => [\&music_menu], # Taste "2": Musik spielen
249     "[^12]+\$" => \&not_valid,# alles andere ist ganz, ganz falsch
250     );
251    
252     # Wir sagen "Hallo" und vielleicht noch mehr:
253     $v->play_file("$MSG/welcome"); $v->play_pause(0.2);
254    
255     # Aus dieser Schleife lassen wir sie nicht entkommen!
256     while (my $ev = $v->event) {
257     if ($ev->isbreak) {
258     $v->play_flush;
259     $v->play_pause(0.5);
260     $ev->data->[0]->();
261     return unless $v->connected;
262     }
263    
264     # Wenn nur noch ein Soundfile in der Warteschlange
265     # steht, füge den Hilfetext ("das Menü") an:
266     if ($v->play_count <= 1) {
267     $v->play_file("$MSG/help");
268     $v->play_pause(1);
269     }
270     }
271     }
272    
273     sub not_valid {
274     my $context = $v->context->set(".*" => sub {});
275     $v->play_flush;
276     # Das beliebte
277     # AT&T-Multilingual-The-number-you-have-dialed-is-not-valid
278     $v->play_file ("$MSG/number_not_valid");
279     $v->play_pause (0.4);
280     $v->play_drain;
281     }
282    
283     # usw...
284     !endblock
285    
286     H2: Audio::Play::MPG123 - ich liebe Terminals
287    
288     Es gibt ja sooo tolle mp3-Player. Aber alle machen diese häßlichen
289     "meine-Knöpfe-sind-noch-kleiner"-, "mein-Skin-ist-länger-als-deiner"-
290     und "ich-nehme-gerne-Platz-weg"-Fenster auf. Das mag' ich nicht: Wenn ich
291     Fenster will, mache ich Fenster, wenn ich beim Arbeiten mp3s hören will,
292     muss das per Skript gehen.
293    
294     Das war das Problem...
295    
296     H3: Wie sage ichs mpg123?
297    
298     Das Modul spielt natürlich selbst keine mp3s ab, sondern startet nur (das
299     eigene, gefixte) C<mpg123> nach und bedient es bzw. verarbeitet Ereignisse
300     wie "Lied zu Ende, was nun?".
301    
302     Ein einfaches Abspielprogramm wäre z.B.:
303    
304     !block perl
305     use Audio::Play::MPG123;
306    
307     $player = new Audio::Play::MPG123;
308     $player->load("/root/mp2/Misc/kult.mp3");
309     print $player->artist,"\n";
310     $player->poll(1) until $player->state == 0;
311     !endblock
312    
313     Diese bestechende Simplizität, diese Eleganz, mit der es wirklich nur
314     mp3s abspielt, keine Playlists, keine Buttons, nichts. Schließlich muß
315     man ja irgendwie seiner Creativität Ausdruck geben können. (Ich höre
316     lieber auf bevor es allzu peinlich wird).
317    
318     Dieses Modul hat sogar schon ein Problem gelöst (oder bei der Lösung
319     geholfen), bevor es ein Problem war (ganz untypisch für mich): Der
320     Sound-Treiber meines Notebooks mag es gar nicht, wenn er beim Suspend noch
321     geladen ist. Deshalb gibt mein Abspielprogramm das Audio-Device bei einem
322     SIGPWR frei. Außerdem ist es ganz gut, wenn man sein Notebook Zuhause
323     zuklappt, beim Workshop-Vortrag auf und er spielt {{nicht}} automatisch
324     weiter...
325    
326     Und in der Praxis? Wie mir zugetragen wurde, gibt es für die
327     Mitarbeiter von mp3.com einen Service, bei dem man per Web Musiktitel
328     bestellen kann, mit denen dann die Arbeitsräume beschallt werden. Mit
329     C<Audio::Play::MPG123> und C<mpg123> natürlich.
330    
331     H2: Video Capturing mit Video4linux
332    
333     Hier war das Problem, daß ich eine regelmäßige Serie im Fernsehen
334     aufnehmen wollte, die keinen festen Sendetermin hatte. Der Sender hatte
335     auch eine merkwürdige Vorstellung von VPS, also entschloss ich mich, den
336     Anfang der Sendung aufzunehmen und mit einem Skript täglich auf diese
337     Sequenz zu warten. Als es endlich fehlerlos lief, hatte ich alle Folgen
338     gesehen, aber dafür kann man mit Perl jetzt auch Fernsehbilder (oder
339     Digitalkameras) benutzen, zumindest unter Linux.
340    
341     Doch dann entdeckte ich die vertikale Austastlücke. Intercast, Internet,
342     Videotext, PDC, EPG, sogar MP3s... Toll! Genau beschrieben habe ich das
343     in einem längeren Artikel im Perl-Journal bzw. auf meiner Homepage
344     (http://home.plan9.de/). Vorführen werde ich das nicht können, aber wer
345     mich besucht kann sicherlich einiges darüber erfahren...
346    
347    
348    
349    
350    
351    
352    
353    
354