Sample-Verarbeitung auf dem ST, Teil 2

Sample-Sounds katapultieren den ST in ungeahnte Klangwelten. Im zweiten Teil unseres Grundlagen-Kurses dreht sich alles um das Funktionsprinzip und die Anwendung des vierstimmigen Sample-Wiedergabe-Programms »PlayFour«.

Wir dürfen wohl voraussetzen, daß Sie inzwischen der perfekte »Sampler« sind - dank SMSSEDIT von der letzten TOS-Disk. Mit ein paar einfachen Samples lassen sich ja schon witzige Effekte erzeugen und vielleicht auch die Nachbarn ärgern. Da aber echte Atarianer nie genug bekommen, haben wir für Sie den Sample-Player »getuned«: Er kann nun vier Samples gleichzeitig ausgeben. Deshalb heißt er nun auch nicht mehr nur Player, sondern »PlayFour«.

In diesem Kursteil erläutern wir die Funktion und die Verwendung von PlayFour in eigenen Programmen, doch zunächst sollten Sie sich erst einmal das Demo-Programm »PLAY_4« anschauen und -hören. Leider läuft es nur im monochromen Modus korrekt, in Farbe ist das Lied zu langsam und die Grafik an den falschen Stellen. Da aber die TOS-Disk alle Quellcodes enthält, können Sie das Programm bei Bedarf selbst anpassen. Der eigentliche Clou von PLAY_4 ist die Verwendung von »PlayFour«. PlayFour enthält zahlreiche Soundroutinen, und die Ausgabe der Musik in PLAY_4 geschieht vollkommen interruptgesteuert. Das heißt, der eigentliche Programmkern von PLAY-4 (der die vier Linien auf dem Bildschirm erzeugt) merkt von der Musik überhaupt nichts, außer, daß er etwas langsamer läuft. Dies ist nicht weiter schlimm, denn selbst mit dieser »Bremse« stellt der ST immer noch etwa 40 Bilder pro Sekunde dar. Im Wesentlichen treten bei mehrkanaligen Playern zwei Probleme auf: Zum einen sollen alle Kanäle Samples in unterschiedlicher Tonhöhe ausgeben können, zum zweiten treten dabei umfangreiche Berechnungen auf, die im Vergleich zur einkanaligen Version zusätzlich Zeit kosten.

Die unterschiedlichen Tonhöhen lassen sich relativ einfach in den Griff bekommen: Die Ausgangsbasis ist ein Interrupt, der mit einer festen Frequenz aufgerufen wird (zum Beispiel 12,538 KHz). Wenn jetzt jeder Interrupt-Aufruf einen Wert des Samples ausgibt, so kann man das als die »Schrittweite« 1,00 betrachten. Diese Schrittweite läßt sich aber mit einem geeigneten Algorithmus variieren. Bei der Schrittweite 2,00 wird jedes zweite Byte des Samples übersprungen, und er klingt genau doppelt so hoch wie bei einer Schrittweite von 1,00. Die Annahme liegt nahe, daß sich der Klang verschlechtern könnte, wenn man einfach Werte des Samples ausläßt.

Aber genau aus diesem Grund haben wir Ihnen im ersten Kursteil die Bedeutung des Verhältnisses von Grenzfrequenz und Abtastfrequenz erklärt. Sie erinnern sich: Das Ohr kann nur dann ein Sample richtig rekonstruieren, wenn das Sample maximal Frequenzen bis zur halben Abtastfrequenz enthält. Wenn das Sample sehr gut gefiltert wurde (am besten mit SMSSEDIT) und nur noch Frequenzanteile bis zu einem Viertel der Abtastfrequenz enthält, verschlechtert sich sein Klang bei der Ausgabe mit einer Schrittweite von 2,00 überhaupt nicht.

Die Frage ist nun, wie der Sound bei einer Schrittweite von beispielsweise 1,63 klingt? Für die Praxis bedeutet das, daß man den genauen Wert des Samples zu den jeweiligen Zeitpunkten errechnen müßte. Leider ist diese Berechnung sehr aufwendig, denn es treten Reihensummen von Sinusfunktionen auf Die nächste Vereinfachung wäre die, daß man den gewünschten Wert aus zwei der benachbarten Abtastwerte interpoliert. Aber auch das ist für den 68000-Prozessor in Echtzeit schon etwas zuviel. Letztendlich bleibt dem soundgierigen ST-Fan nichts anderes übrig, als alle Berechnungen über den Haufen zu werfen und gleich den jeweils nächstliegenden Abtastwert zu nehmen. Natürlich wirkt sich das sofort wieder negativ auf den Klang aus. Glücklicherweise besitzt der ST jede Menge Speicher. Der Fehler des »genommenen« Wertes zum »richtigen« Abtastwert nimmt mit steigender Abtastfrequenz ab, was heißt: Die Klangverschlechterung läßt sich gut in den Griff bekommen, sofern genügend Speicher zur Verfügung steht. Die Samples für die Demo wurden alle (außer den Drums) mit 28 KHz gesampelt und hinterher mit dem Filter von SMSSEDIT auf 5 KHz begrenzt. Warum solche überlangen Samples auf Diskette fast keinen zusätzlichen Speicherplatz kosten, erklären wir später.

Der zweite wichtige Punkt war die Berechnung der jeweils aktuellen Position innerhalb eines Samples anhand der vorgegebenen Schrittweite. Da die Schrittweite ein Dezimalbruch ist, gibt es hier in Assembler ein kleines Problem, denn der 68000 kennt keine Zahlen mit Nachkommastellen. Aber auch dieses Problem läßt sich einfach lösen, man muß nur seine Perspektive verändern. Eine 32-Bit-Zahl könnte auch eine Zahl mit 16 Bit Vorkomma- und 16 Bit Nachkomma-Anteil sein, also eine Fixkommazahl. So läßt sich die Addition zweier Schrittweiten mit einem einfachen »add.i«-Befehl in Assembler bewerkstelligen. Um an den Integer-Teil der Zahl zu gelangen, gibt es in Assembler ebenfalls einen praktischen Befehl: »swap«. Daraus ergibt sich eine sehr schnelle Routine, um Samples mit variabler Schrittweite abzuspielen.

Angenommen, in D0 befindet sich die Schrittweite, D1 enthält den Arbeitsindex (beide im 16.16 Bit Format), A0 zeigt auf den Anfang des Samples und der Abtastwert soll nach D2.b:

add.l	D0, D1	; Schrittweite 16.16 zum Index addieren
swap	D1	; D1: Vorkomma-Anteil holen
move.b	0(A0, D1.w), D2	; Wichtig: D1.w!
swap	D1	; wieder Format 16. 16 restaurieren

Um das Tempo möglichst hoch zu halten, berechnet PlayFour immer einen ganzen Packen Werte im voraus. Diese Werte legt das Programm in einem von zwei Puffern ab, während es die Daten des anderen Puffers gerade ausgibt. PlayFour wurde so entworfen, daß es auf jedem Atari laufen müßte. Auf STEs wird lediglich das Microwire-Interface initialisiert (ein digital steuerbarer Tonhöhenregler). Da der STE von seiner Hardware her nur zwei Samples gleichzeitig - und die auch nur mit konstanter Tonhöhe - ausgeben kann (6,25 KHz, 12,5 KHz, 25 KHz, 50 KHz), läßt sich PlayFour geschickt an die speziellen Eigenschaften des STE anpassen. Es müssen nur noch die Puffer via Software gefüllt werden, die D/A-Ausgabe übernimmt die STE-Hardware. Der Verbrauch an Rechenzeit zum Füllen der Puffer beträgt bei 12,5 KHz Ausgabefrequenz nur lächerliche 22 Prozent.

Doch nun genug der Details, hier kommt die globale Definition von PlayFour: Zum Bearbeiten von PlayFour sollten Sie den TurboAss verwenden (Shareware, zu finden auf der TOS-Diskette 1/91), da wir nur mit ihm die einwandfreie Funktion von PlayFour garantieren können. Assemblieren Sie PLAYFOUR.S mit der Option »SMALLDRI« unter dem Namen PLAYFOUR.O. Damit steht Ihnen eine Objektdatei im DRI-Format zur Verfügung, die Sie zu Ihrem eigenen Programm hinzulinken (C, PASCAL, MODULA 2 ... ) und so alle Funktionen von PlayFour per Funktionsnamen aufrufen können.

Sollten Fragen zu einzelnen Punkten auftauchen: Drucken Sie die Quellcodes (PLAY_4.C und PLAYFOUR.S) aus. Die Funktionen im einzelnen:

Das Sample wird dabei an die mit »adr« bezeichnete Adresse geladen, »fname« zeigt auf den Namen der Datei. Danach rechnet das Programm das Sample auf die »vol« entsprechende Lautstärke um (0..32..63), Empfehlung für »vol«: etwa 32. Schließlich wird das Sample unter der Nummer »index« intern in PlayFour registriert (siehe »prg_chg()«). Rückgabewert ist entweder eine Fehlernummer (negativ) oder die Anzahl der geladenen Bytes. Es sind maximal 32 Samples erlaubt. Die Indizes »index« dürfen dabei beliebig sein, jeweils aber nur einmal vorkommen.

Die einzelnen Befehle zu der vier Stimmen:

PlayFour wurde so ausgelegt, daß es sich auch einfach über MIDI steuern lassen würde. Da es 16 MIDI-Kanäle gibt (aber nur vier ST-Stimmen), teilen sich immer vier MIDI-Kanäle eine Stimme (die Stimme wird immer aus dem Kanal modulo vier berechnet). Für jeden MIDI-Kanal läßt sich ein eigenes Sample einstellen. Der höchste MIDI-Kanal (16) nimmt eine Sonderstellung ein: Bei Notendaten auf diesem MIDI-Kanal werden die Tonhöhen als Samplenummern interpretiert, damit verhält sich PlayFour wie ein Drumcomputer.

Von den nächsten Befehlen ist pro Stimme immer nur einer erlaubt, das heißt, nur jeweils der letzte ist gültig.

Variablen:

Wir hoffen, diese Minimalanleitung genügt Ihnen zum Einstieg in die Welt des Digisounds. In jedem Fall sollten Sie die beiden Listings (PLAY_4.C und PLAYFOUR.S) ausdrucken, da sich in ihnen weitere Kommentare befinden, die Ihnen weitere Hilfestellungen bieten. Sie haben sich vielleicht schon gefragt, warum wir Ihnen nur die grundlegenden Befehle, nicht aber gleich einen ordentlichen Editor anbieten - schließlich hat der Autor ja irgendwie auch den Demosong eingetippt. Tatsache ist, daß der Editor der Demosongs ein simpler Speichermonitor war. Also: Programmierer, ran an die Maschine! Wir würden gerne über Ihren PlayFour-Editor in der TOS berichten. Zu guter Letzt lüften wir das Rätsel der Datei »SOUNDS.LSD«. Wie bereits oben erwähnt, wurden die Samples der Demo mit hohen Abtastraten gesampelt. Sie belegen im Original (also im »*.SMS«-Format) zusammen fast 100 KByte. Leider wäre das für die TOS-Disk zuviel. Daher waren wir gezwungen, die Samples zu komprimieren. Ein mögliches Verfahren ist sehr simpel und wurde in ähnlicher Form bereits in TOS 4/91 von Frank Mathy vorgestellt. Bei einem sauber abgetasteten Sample liegen benachbarte Abtastwerte nie sehr weit auseinander, man kann nun Differenzen zwischen den einzelnen Werten bilden. Dabei treten betragsmäßig kleine Werte viel häufiger auf als große Werte. Bildet man aus den auftretenden Differenzen einen nach den Häufigkeiten ihres Auftretens gewichteten Baum, so lassen sich die Längen der Äste des Baumes als Anzahl der Stellen eines binären Wortes interpretieren. Werden die Differenzen des Samples nach den Ästen des Baumes codiert, so ergeben sich beachtliche Einsparungen.

Bei LSD handelt es sich um einen Packer, der unter anderem nach diesem Verfahren arbeitet (LSD ist ebenfalls Public Domain). Je höher die Abtastfrequenz eines Samples war, desto besser läßt es sich also packen. Die Routine »cread0« im C-Listing entpackt die Datei SOUNDS.LSD. Hinterher trägt PlayFour die Adressen der verwendeten Samples in die Tabelle »psamples« ein, über die das Programm auf Samples zugreift. In diesem Fall konnten wir so fast 60 KByte einsparen. (ts)


Jürgen Piscol
Aus: TOS 07 / 1991, Seite 79

Links

Copyright-Bestimmungen: siehe Über diese Seite