6. Musik und Sound

 

Sounds, aber auch die herausragenden Musikfähigkeiten, haben den C64 erst zu dem gemacht, was er ist: Der meistverkaufte Computer der 80-er und 90-er. Dies verdankt er vor allem dem SID-Soundchip. Deshalb gilt: Wer dem C64 Musik entlocken will, muss sich eingehend mit dem SID befassen. Leider stößt BASIC hierbei an seine Grenzen- wieder ein Grund mehr, sich nach dem BASIC-Kurs direkt der Assembler-Programmierung zu widmen. Vieles im Bereich Musik und Sound geht nämlich nicht ohne Maschinenprogramme.

 

6.1 Der SID-Soundchip

 

Der SID (dies ist die Abkürzung von Sound Interface Device) wurde von Michael Yannings Anfang der 80-er Jahre für Commodore entwickelt, um dem Anwender einen einfach zu programmierenden Synthesizer-Chip zur Verfügung zu stellen. Dieser Chip sollte möglichst einfach aufgebaut sein, aber dennoch effizient arbeiten. Heraus kann der SID, der beide Kriterien erfüllt: Der interne Aufbau ist eher schlicht, aber zusammen mit den Möglichkeiten, externe analoge Filter zu verwenden, und der sehr feinen Skalierbarkeit der Ausgabefrequenzen, leistet der SID in Ihrem C64 gute Dienste.

 

6.1.1 Interner Aufbau

 

Um den SID optimal zu programmieren, müssen Sie zunächst ein paar Dinge über den internen Aufbau wissen, und auch ein paar physikalische Grundlagen der Erzeugung von Tönen verstehen. Keine Angst, dies ist wirklich nicht schwer, und Sie müssen auch keine höhere Mathematik beherrschen (na gut, wenn Sie höhere Mathematik beherrschen, wird vieles einfacher). Sie müssen sich einfach zunächst nur einen Zähler vorstellen, der zu dem aktuellen Wert, der bei 0 beginnt, immer jeweils einen bestimmten Betrag addiert - beispielsweise 1. Auf diese Weise erhalten Sie die folgende Zahlenreihe:

 

0, 1, 2, 3, …

 

Stellen Sie sich nun vor, dass der Zähler eine Breite von 24 Bit besitzt, das heißt, dass der höchste Wert, den dieser Zähler annehmen kann, 224-1 ist. Wenn diese Zahl (224-1=16.777.215=$FFFFFF) erreicht ist, dann springt der Zähler wieder auf 0 zurück (dies nennt man dann einen Überlauf).

Angenommen, Sie haben nun die Möglichkeit, Zahlenwerte als Spannungen auszugeben, und diese Spannungen an den Audio-Eingang Ihres Monitors weiterzuleiten. Was würde nun geschehen, wenn Sie einen Zähler in eine Spannung umwandeln, und diese Spannung an den Audio-Ausgang weitergeben? Die Antwort ist, dass im Falle des hier beschriebenen Zählers nicht viel geschehen würde, weil sich der 24-Bit-Zähler, der in jedem Schritt immer nur um 1 erhöht wird, viel zu langsam ändert, als dass Ihr Ohr einen hörbaren Ton daraus machen könnte (naja, im Endeffekt erzeugt Ihr Gehirn die wahrnehmbaren Töne, nicht direkt Ihr Ohr). Aber wie können Sie das vorige Problem lösen, und hörbare Töne erzeugen? Die Antwort ist die Verwendung der Modulo-Funktion. Die Modulo-Funktion liefert den Rest einer Division. Wenn Sie Ihren 24-Bit-Zähler Modulo 4096 nehmen, dann erhalten Sie die folgende Zahlenreihe:

 

0, 1, 2, …, 4095, 0, 1, 2, …

 

Wenn Sie nun annehmen, dass zu Ihrem Zähler einmal pro Mikrosekunde der Wert 1 addiert wird, dann erhalten Sie schon 1.000.000/4.096=244,14 Durchläufe pro Sekunde. Dies ist schon schnell genug, um einen hörbaren Ton zu erzeugen. Und Sie haben noch mehr Glück: Der SID tut genau dies: Er wandelt genau solche Zähler durch einen internen DAC in Spannungen zwischen 0 und 3,3V um. Ein DAC (Digital/Analog Converter) ist ein elektronischer Baustein, der digitale Werte in analoge Spannungen umwandelt. Diese Spannungen können, wenn sie sich schnell genug ändern, dazu benutzt werden, hörbare Töne zu erzeugen. Hierzu werden die Spannungen an einen entsprechenden Verstärker-Baustein in Ihrem Monitor oder an eine Stereoanlage weitergegeben. Und Sie haben auch hier wieder Glück: Der SID generiert Line-Pegel, was nichts anderes bedeutet, als dass Sie den Ausgang des SID direkt in den Line-In-Eingang eines Verstärkers stecken können. Allerdings müssen Sie dazu einen entsprechenden Adapter im Internet bestellen, denn der alte C64 verwendet noch DIN- und keine Chinch-Stecker.

Aber was haben Sie nun von dem bisher Gesagten? Ganz einfach: Der SID besitzt drei Zähler, die unabhängig voneinander arbeiten, und zu denen auch andere Werte addiert werden können, als 1. Zusätzlich können die einzelnen Zähler auch in verschiedener Weise benutzt werden. Der SID kann nämlich aus einem der drei Ausgangszähler in der folgenden Weise die folgenden vier Wellenformen erzeugen:

 

Sägezahn-Wellenform

 

·       Addieren des Referenzwertes für den aktuellen Zähler zum aktuellen Zähler

·       Verschiebung des aktuellen Zählers um 16 Bits nach rechts.

·       Weitergabe der verbleibenden 8 Bits an den DAC (dieser hat beim SID eine breite von 8 Bit)

 

Die Sägezahn-Wellenform ist also eine aufsteigende Zahlenfolge, die ab dem Wert 255 wieder bei 0 anfängt. Die Sägezahn-Wellenform hört sich auch rau an, und hat in der Tat etwas von einer Säge. Verwendet wird diese Wellenform unter anderem für Klavier-Sounds.

 

Dreieck-Wellenform

 

·       Addieren des Referenzwertes für den aktuellen Zähler zum aktuellen Zähler

·       Verschiebung des aktuellen Zählers um 12 Bits nach rechts. Dadurch entsteht ein 4096 mal langsamerer 12-Bit-Zähler.

·       Wenn das oberste Bit des neuen Zählers 0 ist, Weitergabe des um 3 Bits verschobenen neuen Zählers an den DAC

·       Wenn das oberste Bit des neuen Zählers 1 ist, Umdrehen sämtlicher Bits des neuen Zählers, und anschließendes Ausmaskieren des 12. Bits des neuen Zählers. Auch hier werden anschließend nur die Bits 11-4 des neuen Zählers an den DAC weitergereicht.

 

Die Dreieck-Wellenform ist also eine aufsteigende Zahlenfolge, die ab dem Wert 255 aber nicht wieder bei 0 anfängt, sondern anschließend zu einer absteigenden Zahlenfolge wird. Ab dem Wert 0 wird dann wieder mit einer aufsteigenden Zahlenfolge weitergemacht. Dieses Verhalten führt auf dem Oszilloskop zu einer Kurve, die wie ein Dreieck aussieht. Die Dreieck-Wellenform hört sich auch nicht rau an, sondern weich und harmonisch. Leider ist die Dreieck-Wellenform besonders für die unteren Oktaven sehr leise. Diese Wellenform wird für Gitarren-Sounds benutzt, oft auch zusammen mit SID-Filtern.

 

Rechteck-Wellenform

 

·       Addieren des Referenzwertes für den aktuellen Zähler zum aktuellen Zähler

·       Verschiebung des aktuellen Zählers um 12 Bits nach rechts. Dadurch entsteht ein 4096 mal langsamerer 12-Bit-Zähler.

·       Wenn der neue Zähler eine vorher definierte Grenze (die sog. Pulsbreite) unterschreitet, wird der Wert 255 an den DAC weitergegeben

·       Wenn der neue Zähler eine vorher definierte Grenze (die sog. Pulsbreite) überschreitet, wird der Wert 0 an den DAC weitergegeben

 

Die Rechteck-Wellenform springt dauernd zwischen den Werten 0 und 255 hin und her. Dieses Verhalten führt auf dem Oszilloskop zu einer Kurve, die wie ein Rechteck aussieht. Die Rechteck-Wellenform hört sich synthetisch an, etwa so, wie eine alte Videopac-Spielekonsole. Die Rechteck-Wellenform wird oft zusammen mit SID-Filtern benutzt, um z.B. Motorengeräusche nachzuahmen. Allerdings erzeugen Kolben bei der Explosion im Motor oft komplexe Wellenformen, die nicht naturgetreu vom SID nachgeahmt werden können.

 

Rauschen

 

Der SID kann auch aus einem Zähler mittels eines Algorithmus Pseudo-Zufallswerte generieren und an den DAC weiterleiten. Zufallswerte werden vom Ohr als Rauschen wahrgenommen. Rauschen kann zusammen mit einem ausklingenden Ton für Explosionen oder Wasser-Sounds benutzt werden.

 

6.2 Ausgabe von Tönen mit einer Stimme

 

Nun wollen wir den Kammerton A4 (440 Hz) ausgeben. Dazu benutzen wir den ersten der drei verfügbaren Zähler, die auch als die erste von drei Stimmen bezeichnet wird (Stimme 0). Damit Sie auf die einzelnen Zähler zugreifen können, blendet der SID seine Prozessorregister in den Speicher des C64 so ein, dass das erste Register (SID-Register Nr. 0) an der Adresse 54272 liegt.

 

6.2.1 Frequenzauswahl mit den SID-Registern

 

Der SID wird nun mit etwa 1 MHz getaktet, und läuft synchron zum 6510-Prozessor. Das bedeutet, dass im Falle der Sägezahn-Wellenform Ihr Ton nur mit 1/16 Hz ausgegeben wird, wenn Sie pro Mikrosekunde den Wert 1 zu dem entsprechenden Zähler addieren. Dies können Sie leicht ausrechnen: Von dem Zähler, der bis 16.777.215 zählt, werden nur die obersten 12 Bits für die Erzeugung der Wellenformen benutzt, dies entspricht dann nur noch 4.096 Zählerschritten pro Sekunde. Da jedoch die Sägezahnwellenform diesen neuen Zähler noch einmal auf einen Bereich zwischen 0 und 255 abbildet, erhalten Sie dann nur noch eine Frequenz von 256/4096=1/16 Hz. Wenn Sie dann zu dem ursprünglichen Zähler jede Mikrosekunde statt 1 den Wert 2 addieren, erhalten Sie eine Frequenz von 2/16 Hz. Für den Kammerton A4 ist also der in jedem Schritt zu addierende Wert 440/(1/16)=7040. Diesen Wert müssen Sie nun in die SID-Register Nr. 0 und 1 schreiben. Hierbei enthält dann SID-Register Nr. 0 das erste Byte des Wertes 7040 (Lo-Byte), und SID-Register Nr. 1 das zweite Byte des Wertes 7040 (Hi-Byte). Die zwei folgenden BASIC-Zeilen leisten dies nun:

 

10 SI=54272: F=7040

20 HI=INT(F/256): LO=F-256*HI

30 POKE SI+1,HI: POKE SI,LO

 

Wenn Sie die Zähler initialisiert haben, müssen Sie den Ton mit voller Lautstärke einschalten. Dies erreichen Sie, indem Sie den Wert 15 in SID-Register Nr. 24 schreiben:

 

40 POKE SI+24,15

 

Nun müssen Sie die Wellenform auswählen, die Sie verwenden wollen. Für die erste Stimme müssen Sie dazu einen der folgenden Werte in SID-Register Nr. 4 schreiben:

 

·       16 (Bit 4=1) für die Dreieck-Wellenform

·       32 (Bit 5=1) für die Sägezahn-Wellenform

·       64 (Bit 6=1) für die Rechteck-Wellenform

·       128 (Bit 7=1) für Rauschen

 

Sie schreiben also

 

50 POKE SI+4,32

 

und geben anschließend RUN ein. Leider geschieht nichts und Sie hören keinen Ton. Dies liegt daran, dass die Sache so einfach dann auch wieder nicht ist. Sie haben dem SID nämlich überhaupt nicht mitgeteilt, wann Ihr Kammerton A4 abgespielt werden soll, und erst recht nicht, wie lange. Soll der Ton gehalten werden? Soll der Ton anschwellen, oder sogar nachhallen? Zu diesem Zweck müssen Sie zusätzlich noch eine Hüllkurve angeben. Die Hüllkurve ist das, was den Ton selbst ausmacht. Ohne Definition einer Hüllkurve hören Sie deswegen nichts. Die Hüllkurve wird durch die folgenden 4 Parameter definiert:

 

·       Die Anschwellzeit A (attack), die angibt, wie lange der Ton braucht, um zu seiner vollen Lautstärke zu kommen

·       Die Abschwellzeit D (decay), die angibt, wie lange der Ton braucht, um bis zu seinem Haltepegel abzuklingen

·       Der Haltepegel S (sustain), der die Lautstärke eines eventuell gehaltenen Tons angibt (also der Haltepegel)

·       Die Ausklingzeit R (release), die die Nachklingzeit vom Haltepegel auf 0 angibt.

 

Das Einstellen der Hüllkurve, also die Programmierung des Hüllkurvengenerators, ist auf dem SID etwas speziell zu handhaben. Es wurde, um Platz zu sparen, das Startbit (das sog. Gate-Bit) für den Ton in Register Nr. 4 untergebracht. Sie müssen also den Ton zusammen mit der Wellenformauswahl starten. Auch die Werte für A, D, S und R müssen Sie in spezieller Weise handhaben, nämlich als einzelne Nibbles. So stehen z.B. bei der ersten Stimme (Stimme 0) die Werte für A und D im hohen bzw. niedrigen Nibble von SID-Register Nr. 5. Auch bei den Werten für S und R ist dies so, und S steht im hohen, und R im niedrigen Nibble von SID-Register Nr. 6. Dies bedeutet natürlich auch, dass Sie die Werte für A, D, S und R nicht direkt in Millisekunden eingeben können, sondern stattdessen folgende Tabelle verwenden müssen:

 

Attack-Zeit

 

Wert

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

Zeit (ms)

2

8

16

24

38

56

68

80

100

250

500

800

1000

3000

5000

8000

 

Decay/Release-Zeit

 

Wert

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

Zeit (ms)

6

24

48

72

114

168

204

240

300

750

1500

2400

3000

9000

15000

24000

 

Für das letzte Beispiel bedeutet dies: Sie müssen das Programm so abändern, dass Sie erst die Tonfrequenz auswählen, und dann die Hüllkurve erstellen. Um anschließend den Ton zu starten, und den SID in den Zyklus Attack/Decay/Sustain zu versetzen, müssen Sie zusammen mit der Wellenform das Gate-Bit (Bit 0 in SID-Register Nr. 4) auf 1 setzen. Dies führt dann zu dem folgenden, einwandfrei laufenden Programm:

 

16-A440

10 SI=54272: F=7040: POKE SI+24,15

20 HI=INT(F/256): LO=F-256*HI

30 POKE SI+1,HI: POKE SI,LO

40 POKE SI+5,10: POKE SI+6,0: REM A=0, D=10, D=0, R=0

50 POKE SI+4,32

60 POKE SI+4,33

 

An dem letzten Beispiel sehen Sie sehr schön, wie die Tonausgabe durch das Gate-Bit gesteuert wird: Wenn das Gate-Bit 0 ist, geht der SID in die Release-Phase über (die hier nicht verwendet wird), wenn das Gate-Bit 1 ist, geht der SID in die Attack-Phase über, der nahtlos die Decay- und die Sustain-Phase folgen. Wenn dann der Wert für S und R=0 ist, dann kann der Ton durch Setzen des Gate-Bits auf 0 direkt gestoppt werden. Da der SID unabhängig vom Hauptprozessor läuft, benutzen viele Spiele die oben verwendete Technik, S und R auf 0 zu setzen, um Melodien im Hintergrund abzuspielen. Allerdings werden bei Spielen oft Maschinenprogramme benutzt, die die SID-Register viel schneller beschreiben können, als BASIC.

 

6.2.2 Die SID-Register (Quelle: https://www.c64-wiki.de/wiki/SID)

 

Wie auch schon im Falle des VIC möchte ich Ihnen nun eine Zusammenstellung sämtlicher Register des SID vorstellen. Auch diese Tabelle werden Sie wahrscheinlich in Zukunft noch oft benötigen.

 

SID-Register

Adresse

Bedeutung

0

54272

Frequenz Stimme 0 Lo-Byte

1

54273

Frequenz Stimme 0 Hi-Byte

2

54274

Rechteck-Pulsbreite Stimme 0 Lo-Byte

3

54275

Rechteck-Pulsbreite Stimme 0 Hi-Nibble

4

54276

Wellenform Stimme 0 und SID-Status-Register**

Bit 7: Rauschen

Bit 6: Rechteck

Bit 5: Sägezahn

Bit 4: Dreieck

Ein gesetztes Wellenform-Bit wählt die Wellenform aus, es kann nur immer eine Wellenform ausgewählt werden, wobei das höchste Bit, das gesetzt ist, entscheidet, welche Wellenform benutzt wird.

Bit 3: Testbit

Erst Testbit auf 1 setzen, dann auslesen. Wenn das Testbit noch 1 ist, ist der SID OK.

Bit 2: Ring-Modus

Ist dieses Bit 1, können mehrere SID-Chips im Verbund arbeiten. Wenn die Verbindung erfolgreich ist, ist das Sync-Bit (Bit 1) gesetzt.

Bit 0: Gate-Flag

1=ADS-Phase einleiten

0=Release-Phase einleiten

5

54277

Hi-Nibble: Attack-Zeit für Stimme 0

Lo-Nibble: Decay-Zeit für Stimme 0

6

54278

Hi-Nibble: Sustain (Haltepegel) für Stimme 0

Lo-Nibble: Release-Zeit für Stimme 0 (Gate 0=0)

7

54279

Frequenz Stimme 1 Lo-Byte

8

54280

Frequenz Stimme 1 Hi-Byte

9

54281

Rechteck-Pulsbreite Stimme 1 Lo-Byte

10

54282

Rechteck-Pulsbreite Stimme 1 Hi-Nibble

11

54283

Wellenform Stimme 1 (Bit 1-3 unbenutzt)

Wellenform- und Gate-Bits stimmen mit Stimme 0 überein

12

54284

Hi-Nibble: Attack-Zeit für Stimme 1

Lo-Nibble: Decay-Zeit für Stimme 1

13

54285

Hi-Nibble: Sustain (Haltepegel) für Stimme 1

Lo-Nibble: Release-Zeit für Stimme 1 (Gate 1=0)

14

54286

Frequenz Stimme 2 Lo-Byte

15

54287

Frequenz Stimme 2 Hi-Byte

16

54288

Rechteck-Pulsbreite Stimme 2 Lo-Byte

17

54289

Rechteck-Pulsbreite Stimme 2 Hi-Nibble

18

54290

Wellenform Stimme 2 (Bit 1-3 unbenutzt)

Wellenform- und Gate-Bits stimmen mit Stimme 0 überein

19

54291

Hi-Nibble: Attack-Zeit für Stimme 2

Lo-Nibbe: Decay-Zeit für Stimme 2

20

54292

Hi-Nibble: Sustain (Haltepegel) für Stimme 2

Lo-Nibble: Release-Zeit für Stimme 2 (Gate 2=0)

21

54293

Grenzfrequenz für den SID-Filter (Lo-Byte)*

22

54294

Grenzfrequenz für den SID-Filter (Hi-Byte)*

23

54295

Hi-Nibble: Resonanz (Stärke) des SID-Filters

Lo-Nibble: Gefilterte Stimmen (Bit 0-2), aber immer nur eine einzige

Bit 3: Externer Filter (einschalten=1), z.B. über eine Subgruppe am Mischpult

(Ist Bit 3 gesetzt, so werden sämtliche Stimmen gefiltert)

24

54296

Lo-Nibble: Lautstärke 0-15 für alle Stimmen

Hi-Nibble: Filtermodus (es kann immer nur ein einziger Filter aktiv sein)

Bit 7: Ausschalten von Stimme 2

Bit 6: Wählen des Hochpassfilters (1=an)

Bit 5: Wählen des Bandpassfilters (1=an)

Bit 4:  Wählen des Tiefpassfilters (1=an)

25

54297

X-Koordinate (0-255) eines Paddles oder einer Maus, wenn dieses Gerät angeschlossen ist, ansonsten 0

26

54298

Y-Koordinate (0-255) eines Paddles oder einer Maus, wenn dieses Gerät angeschlossen ist, ansonsten 0

27

54299

Oszillator-Register für Stimme 2:

Hier erscheinen die 8-Bit-Werte, die Stimme 2 an den DAC weitergibt. Wenn Stimme 2 ausgeschaltet wurde, dann werden hier bei Auswahl der Rauschen-Wellenform Pseudo-Zufallszahlen erzeugt.

28

54300

Hüllkurven-Geber für Stimme 2:

Hier erscheint der aktuelle Lautstärke-Wert, den der Hüllkurvengenerator gerade für Stimme 2 benutzt. Mit schnellen Maschinensprache-Routinen kann man diesen Wert auslesen, und mit den Frequenzregistern für die anderen Stimmen koppeln. Auf diese Weise können interessante Effekte programmiert werden.

* Die Grenzfrequenz des SID-Filters hängt davon ab, mit welchem externen Kondensator man den SID beschaltet. Beim C64 ist die Grenzfrequenz ungefähr mit dem binären 12-Bit-Wert identisch, den Sie in die SID-Register 21 und 22 eintragen. Wenn Sie also hier den Wert 1000 eintragen (SID-Register Nr. 21=232, SID-Register Nr. 22=3), dann erhalten Sie auch ungefähr eine Grenzfrequenz von 1000 Hz. Da jede Stimme ein eigenes Filter-Bit besitzt, kann der SID-Filter für jede Stimme unabhängig benutzt werden, allerdings gelten die Filtereinstellungen global. Das heißt, dass nicht z.B. Stimme 0 den Hochpassfilter, und Stimme 1 den Tiefpassfilter benutzen kann.

** Das SID-Status-Register ist entgegen der Angaben in der Dokumentation des SID durch MOS Technology Inc. nur ein einziges Mal vorhanden, und nicht für jede Stimme separat. Das heißt, dass nur mit dem SID-Register Nr. 4 (und nicht mit SID-Register Nr. 11 und 18) der SID z.B. in den Ring-Modus versetzt werden kann. Auch das Test-Flag gibt es, wie auch das Sync-Bit, nur in SID-Register Nr. 4.

 

6.3   Abspielen von Songs

 

Kommen wir nun zum ersten Beispiel. In diesem Listing wird ein einfacher Song abgespielt, den Sie in ähnlicher Weise auch immer wieder im Internet antreffen, z.B. auf www.poke-53280.com, wo ich dann dieses Listing auch herhabe.

 

17-SIMPLESONG

10 SI=54272

20 POKE SI+24,15: REM VOLLE LAUTSTAERKE

30 POKE SI+5,9:POKE SI+6,0:REM KLAVIER

40 READ HF,LF,L:IF HF<0 THEN END

50 POKE SI,LF:POKE SI+1,HF

60 POKE SI+4,33:REM GATE-BIT=1 STARTET DEN TON (ADS-PHASE)

70 FOR T=1 TO L:NEXT T:REM WARTESCHLEIFE FUER DEN TON

80 POKE SI+4,32:REM GATE-BIT=0 STARTET DIE R-PHASE

90 FOR T=0 TO 50:NEXT T:REM TON ETWAS AUSKLINGEN LASSEN

100 GOTO 40

110 DATA 25,177,250,28,214,250

120 DATA 25,177,250,25,177,250

130 DATA 25,177,125,28,214,125

140 DATA 32,94,250,25,177,250

150 DATA 28,214,250,19,63,250

160 DATA 19,63,250,19,63,250

170 DATA 21,154,125,24,125,63

180 DATA 25,177,250,24,63,125

190 DATA 19,63,250,-1,-1,-1

 

Im letzten Beispiel wird nur der Wert für Decay benutzt (D=9), nicht aber der Wert für Attack (A=0), Sustain (D=0) und Release (R=0), was bedeutet, dass der Ton sofort präsent ist, und innerhalb von 0,75 Sekunden vollständig abschwellt. Deshalb muss in Zeile 30 auch nur der Wert 9 in SID-Register Nr. 5 eingetragen werden, SID-Register Nr. 6 wird dagegen auf 0 gesetzt. Natürlich müssen Sie auch beim SID vorher in Zeile 10 die Basisadresse durch die Anweisung SI=54272 festlegen, denn sonst können Sie nicht anhand der Nummer auf die Register zugreifen. Anders, als beim VIC, müssen Sie den SID allerdings dadurch initialisieren, dass Sie in Zeile 20 das Lautstärkeregister auf den Wert 15 setzen, denn sonst hören Sie keinen Ton.

Nach der Initialisierung der SID-Register muss der Song in einer Schleife (Zeile 40-100) abgespielt werden. Der Song selbst steht in DATA-Zeilen (Zeile 110-190). Der Song besitzt nur eine Stimme, und die Werte für die Frequenzangaben für die einzelnen Noten wurden in diesem Beispiel so in den DATA-Zeilen abgelegt, dass sie direkt in die SID-Register geschrieben werden können. Zeile 40 liest diese Daten nun als Dreierpäckchen der Form {Hi-Byte (HF), Lo-Byte (LF), Länge (L)} aus, und schreibt Lo- und Hi-Byte in SID-Register Nr. 0 und 1. SID-Register Nr. 0 enthält das Lo-Byte, und SID-Register Nr. 1 das Hi-Byte für die Frequenzangabe für Stimme 0. So erhalten Sie einen gültigen 16-Bit-Wert, der für den Zähler der ersten Stimme benutzt werden kann. In Zeile 60 wird nun die Sägezahn-Wellenform zusammen mit einem gesetzten Gate-Bit in SID-Register Nr. 4 eingetragen, wodurch auch gleich der Ton gestartet wird. Da der Ton sofort auf 0 abschwillt, kann das Programm direkt nach Starten des Tons in eine Warteschleife (Zeile 70) eintreten. Wie lange diese Schleife läuft, bestimmt das dritte Byte des zuvor ausgelesenen Dreierpäckchens (also die Variable L). Nach der Warteschleife für die Notendauer wird das Gate-Bit in SID-Register Nr. 4 wieder gelöscht, und der Ton wird in Zeile 90 noch etwas nachklingen lassen. Diese Zeile wurde eingefügt, damit zwischen zwei gleichen Noten eine kleine Pause ist. Ohne diese Pause würde man zwei hintereinander folgende gleiche Noten als eine einzige Note wahrnehmen.

Der Song endet, wenn für Frequenz und Länge der Wert -1 aus den DATA-Zeilen gelesen wird. Diese Werte werden für die SID-Register nicht verwendet, und können deshalb als Stopp-Marker dienen.

Kommen wir nun zum nächsten Beispiel. Das Listing ist mit dem vorigen Listing identisch, demonstriert Ihnen aber durch einen Fortschrittsbalken, dass der SID wirklich unabhängig von Ihrem Hauptprogramm arbeitet.

 

18-SIMPLESONG2

10 SI=54272:K=0:PRINT"[SHIFT+CLR/HOME]SPIELE SONG"

20 POKE SI+24,15:REM VOLLE LAUTSTAERKE

30 POKE SI+5,9:POKE SI+6,0:REM KLAVIER

40 READ HF,LF,L:IF HF<0 THEN END

50 POKE SI,LF:POKE SI+1,HF

60 POKE SI+4,32:POKE SI+4,33

70 FOR T=1 TO L

80 POKE 1064+(K/10),46:K=K+1

90 NEXT T

100 GOTO 40

110 DATA 25,177,25,28,214,25

120 DATA 25,177,25,25,177,25

130 DATA 25,177,12,28,214,12

140 DATA 32,94,25,25,177,25

150 DATA 28,214,25,19,63,25

160 DATA 19,63,25,19,63,25

170 DATA 21,154,12,24,63,12

180 DATA 25,177,25,24,63,12

190 DATA 19,63,25,-1,-1,-1

 

Die Warteschleife in Zeile 70-90 wartet nicht nur die Zeit L, die Sie bei der Notendauer angeben, sondern schreibt auch gleichzeitig einen Fortschrittsbalken in Form von Pünktchen in die zweite Zeile Ihres Bildschirms. Hierdurch müssen Sie jedoch die Längenangabe für Ihre Noten durch 10 teilen, was leider ein reiner Erfahrungswert ist.

 

6.3.1 Notenwerte in Frequenzen umrechnen

 

Vielleicht gefallen Ihnen die letzten Beispiele nicht so wirklich. Zugegeben: Mir auch nicht! Aber das ist auch kein Wunder, denn ich habe die letzten Beispiele bewusst so gewählt, weil sie eben Unzulänglichkeiten enthalten. Die größte Unzulänglichkeit ist, dass Sie Ihre Noten nicht direkt in Ihren DATA-Zeilen angeben können, z.B. durch die Anzahl der Halbtonschritte ab einem bestimmten tiefsten, gerade noch hörbaren Ton. Dieser tiefste, gerade noch hörbare Ton ist auf dem SID beispielsweise 8,176 Hz und entspricht dem Ton C1, der noch einmal um zwei Oktaven erniedrigt wird.

Wählen wir nun den tiefst möglichen Ton, der auf dem SID einer Frequenz von 8,176 Hz entspricht, als Ausgangspunkt einer Abbildungsfunktion von Notenwerten auf eine Frequenz in Hz. Sie denken vielleicht nun, dass dies nicht so schwer sein kann, denn im Endeffekt müssen Sie ja nur eine simple Geradengleichung der Form

 

y=ax+b

 

aufstellen, und für b=8,176 Hz, sowie für a Ihren Notenwert (gemessen in Halbtonschritten) einsetzen. Leider ist es aber so, dass sich in jeder neuen Oktave die Frequenz verdoppelt, und Sie es dann auch niemals schaffen, eine lineare Abstufung zwischen den Noten zu erhalten. Das menschliche Ohr hört also logarithmisch, deshalb benötigen sie auch die folgende Gleichung, um Noten auf Frequenzen abzubilden:

 

F(x)=a0*2x/12

 

F(x) ist hier die Frequenz, gemessen in Hz, und a0 ist die Frequenz des tiefsten Tons, den Sie auf Ihrem wie immer gearteten Instrument spielen können. Die Variable x beschreibt dann die Anzahl der Schritte, die Sie ab dem Ton a0 gehen müssen, um zu Ihrer gewünschten Note zu gelangen.

Natürlich können Sie schon sehr gut BASIC, und es ist für Sie deshalb ein Leichtes, eine FOR-Schleife zu erstellen, die die Frequenzwerte für die einzelnen Noten in einem Array ablegt. Dieses Array müssen Sie anschließend nur noch auslesen. Und da Sie wissen, dass die Frequenzwerte in Schritten von 1/16 Hz in die SID-Register 0 und 1 eingetragen werden müssen, können Sie diese dann auch direkt in POKE-Anweisungen einbauen.

Leider liegt der Teufel wie immer im Detail, denn der SID ist, wie auch der VIC, fest mit dem Speicher des C64 verbunden. Schlimmer noch: Der SID wird über den Prozessortakt gesteuert, und diesen Prozessortakt gibt im Endeffekt der VIC vor. Der VIC gibt also den Takt an, und dies ist auch gut so: Wenn der VIC nicht den Takt angeben würde, dann würde auch das Fernsehbild nicht korrekt mit dem Rasterstrahl synchronisiert. Und Sie sähen dann auch… Genau: Gar nichts! Aber auch dies ist nicht alles: Es gibt zusätzlich noch verschiedene Fernsehnormen. Die Fernsehnorm, die der C64 von Haus aus verwendet, ist die amerikanische NTSC-Norm (National Television System Company Standard). Ein NTSC-Bild besteht aus 480 Zeilen mit 720 Spalten, und wird mit 60 Hz Bildrate aufgebaut. Der VIC (und auch der SID) läuft dann mit 975,5 kHz Taktfrequenz. Wenn Sie allerdings in Deutschland leben, dann benutzen Sie wahrscheinlich die PAL-Fernsehnorm (Phase Alternate Line Imaging) mit 576 Zeilen und 720 Spalten, was dann dazu führt, dass Ihr SID mit 982,5 kHz getaktet wird. Wenn Sie es also sehr genau nehmen, dann müssen Sie die Frequenztabelle für Ihre Noten noch entsprechend korrigieren, je nachdem, welche Fernsehnorm Sie verwenden. Das nächste Listing tut genau dies: Es erzeugt eine Frequenztabelle für Ihre Notenwerte (C/-1 ist mit 8,176 Hz der tiefste Ton), und wählt für diese anschließend die PAL-Fernsehnorm aus (wenn Sie einen amerikanischen NTSC-C64 verwenden, müssen Sie Zeile 11 entsprechend anpassen). Anschließend wird der Song mit Notenwerten, anstatt mit SID-Register-Werten abgespielt.

 

19-SIMPLESONG3

10 SI=54272:K=0:PRINT"[SHIFT+CLR/HOME]SPIELE SONG"

11 FF=982.5:REM FREQUENZ DES CPU IN MHZ (PAL=982.5, NTSC=975.5)

12 FF=16*(1000/FF)

15 DIM NT(110)

16 FOR I=0 TO 109:NT(I)=INT(FF*(8.176*2^(I/12))):NEXT I

20 POKE SI+24,15:REM VOLLE LAUTSTAERKE

30 POKE SI+5,9:POKE SI+6,0:REM KLAVIER

40 READ NO,L:IF NO<0 THEN END

45 NO=NT(NO)

50 POKE SI+1,NO/256:POKE SI,NO-256*INT(NO/256)

60 POKE SI+4,32:POKE SI+4,33

70 FOR T=1 TO L

80 POKE 1064+(K/10),46:K=K+1

90 NEXT T

100 GOTO 40

110 DATA 71,25,73,25,71,25,71,25,71,12,73,12,75,25,71,25,73,25,66,25

120 DATA 66,25,66,25,68,12,70,12,71,25,70,12,66,25,-1,-1

 

Im Array NT (note table) stehen hier Werte zwischen 0 und 65535, es wird also das Hi- und das Lo-Byte zu einem einzigen Wert zusammengefasst. Natürlich muss dann das Hi-Byte und das Lo-Byte in Zeile 50 wieder getrennt, und anschließend korrekt in die SID-Register Nr. 0 und 1 geschrieben werden. Die Notentabelle selbst wird in Zeile 16 durch die Formel F(x)=a0*2I/12 berechnet (I ist hier der Schleifenzähler), allerdings müssen die einzelnen Frequenzwerte noch zusätzlich mit dem Faktor FF skaliert werden (der für einen PAL-C64 FF=1000/982.5 ist). In die Notentabelle passen 110 Frequenzwerte, danach ist der zulässige Wertebereich von 0-65535 überschritten. Der Song selbst verwendet aus dieser Tabelle allerdings nur die Oktaven zwischen C3 und C5.

 

6.3.2 Verwenden mehrerer Stimmen

 

Das nächste Beispiel spielt nun den Song aus dem letzten Beispiel mit mehreren Stimmen ab. Hierbei sind sämtliche Noten sämtlicher Stimmen identisch, Ihr Song sollte also auf diese Weise dreimal lauter klingen, als im Beispiel davor.

 

20-ESGEHTNICHT

10 SI=54272:K=0:SA=8192:PRINT"[SHIFT+CLR/HOME]SPIELE SONG"

11 FF=982.5:REM FREQUENZ DES CPU IN MHZ (PAL=982.5, NTSC=975.5)

12 FF=16*(1000/FF)

15 DIM NT(110):DIM NP(3):DIM NZ(3,2)

16 FOR I=0 TO 109:NT(I)=INT(FF*(8.176*2^(I/12))):NEXT I

20 POKE SI+24,15:REM VOLLE LAUTSTAERKE

30 POKE SI+5,9:POKE SI+6,0:REM STIMME 0

31 POKE SI+12,9:POKE SI+13,0:REM STIMME 1

32 POKE SI+19,9:POKE SI+20,0:REM STIMME 2

35 VO=0:NP(0)=8192

40 READ NO,L:IF NO<0 THEN GOTO 60

45 POKE SA,NO:POKE SA+1,L:SA=SA+2

60 POKE SA,255:POKE SA+1,255:SA=SA+2

70 VO=VO+1:IF VO=3 THEN GOTO 90

80 NP(VO)=SA:GOTO 40

90 CL=TI:REM COMPUTERUHR NACH CL UEBERTRAGEN

100 IF (TI-CL)=0 THEN GOTO 100

110 FOR I=0 TO 2

120 NZ(I,0)=NZ(I,0)+CL:IF NZ(I,0)>NZ(I,1) THEN NO=PEEK(NP(I)):VO=I: GOSUB 2000

130 NEXT I

140 IF NO=-1 THEN END

150 CL=TI:GOTO 100

1000 REM *** STIMME 0 ***

1010 DATA 71,25,73,25,71,25,71,25,71,12,73,12,75,25,71,25,73,25,66,25

1020 DATA 66,25,66,25,68,12,70,12,71,25,70,12,66,25,-1,-1

1030 REM *** STIMME 1 ***

1040 DATA 71,25,73,25,71,25,71,25,71,12,73,12,75,25,71,25,73,25,66,25

1050 DATA 66,25,66,25,68,12,70,12,71,25,70,12,66,25,-1,-1

1060 REM *** STIMME 2 ***

1070 DATA 71,25,73,25,71,25,71,25,71,12,73,12,75,25,71,25,73,25,66,25

1080 DATA 66,25,66,25,68,12,70,12,71,25,70,12,66,25,-1,-1

2000 REM *** NOTENSPIELER ***

2001 IF NO=255 THEN RETURN

2002 IF NO=0 THEN GOTO 2040:REM 0=PAUSE

2005 NO=NT(NO)

2010 OF=7*VO:REM OFFSET FUER STIMME

2020 POKE SI+OF+1,NO/256:POKE SI+OF,NO-(256*INT(NO/256))

2030 POKE SI+OF+4,32:POKE SI+OF+4,33

2040 NP(VO)=NP(VO)+1

2050 NZ(VO,1)=PEEK(NP(VO))

2060 NZ(VO,0)=0:NP(VO)=NP(VO)+1

2070 RETURN

 

Ich habe nun das letzte Listing bewusst nicht ausgiebig kommentiert, und auch bewusst den Namen „es geht nicht“ gewählt. Sie sollen auch das letzte Beispiel nur mit RUN ausführen. Wundern Sie sich bitte nicht darüber, dass nach einiger Zeit ein Song erklingt, bei dem die Noten der einzelnen Stimmen verzögert abgespielt werden, obwohl sämtliche Stimmen durch die Computeruhr synchronisiert werden, und auch alle die gleichen Noten enthalten. Versuchen Sie auch bitte, den Fehler im Programm zu finden, und studieren den Code ausgiebig. Doch ich versichere Ihnen: Wie Sie es auch anstellen, Sie bekommen es mit BASIC nicht hin, die einzelnen Gate-Bits für Ihre Stimmen gleichzeitig einzuschalten, so, dass Sie keine Verzögerung im Anschlag der Noten wahrnehmen. Dies liegt einfach daran, dass der POKE-Befehl zu langsam arbeitet. Selbst, wenn Sie die Computeruhr benutzen, um den Anschlagzeitpunkt für die einzelnen Noten zu bestimmen, ändert dies nichts an der Tatsache, dass Sie allein mit BASIC keine mehrstimmigen Stücke wiedergeben können. Auch hier brauchen Sie wieder Maschinensprache-Routinen.

 

6.4   Sound-Beispiele

 

Musik ist nur die eine Seite des SID-Soundchips, Sounds sind die andere. Nicht nur Spiele leben von Sounds, auch Anwendungen werden z.B. durch Klicks bei der Auswahl von Funktionen „aufgepeppt“. Sounds sind im Gegensatz zu Musik nur kurze Geräusche, die meistens auch abhängig von einem Ereignis abgespielt werden - dies können Sie dann auch mit dem langsamen BASIC erreichen. Wenn Sie z.B. einen Kämpfer durch ein Labyrinth steuern, dann können Sie bei jedem Schritt einen dumpfen Klick wiedergeben. Wenn Sie dann mit einem Monster zusammenstoßen, können Sie auch hier einen entsprechenden Sound wiedergeben.

Sounds sind im Gegensatz zu Musik zwar auch mit BASIC, aber trotzdem sehr viel schwerer zu programmieren, auch wenn sie nur kurz erklingen. Das liegt vor Allem daran, dass Sounds oft den gesamten SID ausreizen müssen, um bestimmte Effekte zu erzielen. Während Sie also für Musik „nur“ Noten oder Partituren lesen müssen, und Sie oft schon mit einem normalen Klavierklang sehr weit kommen (wenn Sie dann mit Assembler einen präzisen Notenplayer umsetzen können), erfordern Sounds, dass Sie sich mit sämtlichen SID-Registern gut auskennen. Ferner gibt es auch kein Patentrezept für Sounds. Sie können z.B. für diese, genau wie bei Musikstücken auch, Interrupt-Routinen verwenden. Meistens verwenden sogar Sounds und Musikstücke die gleiche Interrupt-Routine, was manchmal sehr komplizierte Assembler-Programme erfordert. Andererseits können Sie auch nur die Musikstücke im Hintergrund abspielen, und die Sounds stattdessen abhängig von bestimmten Variablen machen, wie z.B. der y-Position des Spielers: Wenn sich der Spieler im Sprung nach oben bewegt, wird ein aufsteigender Ton erzeugt, wenn der Spieler im Sprung nach unten fällt, wird ein absteigender Ton erzeugt. Auch die Frequenz eines Motorgeräusches kann z.B. vom aktuellen Gang anhängig sein, oder sogar direkt von einer Geschwindigkeitsvariablen für das Scrolling-Tempo.

Die Programmierung von Sounds erfordert also sehr viel Erfahrung und Übung, deshalb kann ich Ihnen auch nur Beispiele für Unterprogramme angeben (aufzurufen mit GOSUB), die immer wieder so oder so ähnlich eingesetzt werden können. Das ausgiebig kommentierte nächste Listing enthält eine Sammlung beliebter Sound-Effekte, die Sie mit der entsprechenden Taste aus einem Menü auswählen können.

 

21-SOUNDDEMO

5 SI=54272:POKE SI+24,15

10 POKE 53280,0:POKE 53281,0:PRINT"[CTRL+WHT][SHIFT+CLR/HOME]";

20 PRINT"         * * * SOUND-DEMO * * *"

30 PRINT

40 PRINT"AUSWAHL MIT FOLGENDEN TASTEN:"

50 PRINT"1:EXPLOSION"

60 PRINT"2:DUMPFE EXPLOSION"

70 PRINT"3:MOTORENBRUMMEN (BENZINER)"

80 PRINT"4:MOTORENBRUMMEN (DIESEL)"

90 PRINT"5:RAUMSCHIFFANTRIEB"

100 PRINT"6:SPRUNG"

110 PRINT"7:FALL INS WASSER"

120 PRINT"8:WASSERRAUSCHEN"

130 PRINT"9:KURZES TUTEN"

140 PRINT"0:KURZER CLICK"

150 PRINT"F1:SCHRITT"

160 PRINT"F2:FALL INS BODENLOSE"

170 PRINT"F3:LASERSCHUSS"

180 PRINT"F4:PROGRAMM BEENDEN"

190 GET A$:IF A$="" THEN 190

200 IF A$="1" THEN GOSUB 1000

210 IF A$="2" THEN GOSUB 1100

220 IF A$="3" THEN GOSUB 1200

230 IF A$="4" THEN GOSUB 1300

240 IF A$="5" THEN GOSUB 1400

250 IF A$="6" THEN GOSUB 1500

260 IF A$="7" THEN GOSUB 1600

270 IF A$="8" THEN GOSUB 1700

280 IF A$="9" THEN GOSUB 1800

290 IF A$="0" THEN GOSUB 1900

300 IF A$="[F1]" THEN GOSUB 2000

310 IF A$="[F2]" THEN GOSUB 2100

320 IF A$="[F3]" THEN GOSUB 2200

330 IF A$="[F4]" THEN END

340 GOTO 190

1000 REM *** EXPLOSION ***

1010 POKE SI+5,11:POKE SI+6,0

1020 POKE SI,0:POKE SI+1,5

1030 POKE SI+4,128:POKE SI+4,129

1040 RETURN

1100 REM *** DUMPFE EXPLOSION ***

1110 POKE SI+5,11:POKE SI+6,0

1120 POKE SI,0:POKE SI+1,2

1130 POKE SI+4,128:POKE SI+4,129

1140 RETURN

1200 REM *** MOTOR (BENZIN) ***

1210 POKE SI+2,0:POKE SI+3,8:REM RECHTECKWELLE MIT 50% PULSBREITE

1220 POKE SI+5,0:POKE SI+6,255

1230 POKE SI,0:POKE SI+1,1

1240 POKE SI+4,64:POKE SI+4,65

1250 RETURN

1300 REM *** MOTOR (DIESEL) ***

1310 POKE SI+2,0:POKE SI+3,12:REM RECHTECKWELLE MIT 75% PULSBREITE

1320 POKE SI+5,0:POKE SI+6,255

1330 POKE SI,0:POKE SI+1,1

1340 POKE SI+4,64:POKE SI+4,65

1350 RETURN

1400 REM *** RAUMSCHIFF ***

1410 POKE SI+5,0:POKE SI+6,255

1420 POKE SI,0:POKE SI+1,5

1430 POKE SI+4,128:POKE SI+4,129

1440 RETURN

1500 REM *** SPRUNG ***

1510 POKE SI+5,0:POKE SI+6,255

1520 POKE SI,0:POKE SI+1,1

1530 POKE SI+4,16:POKE SI+4,17

1540 FOR I=1 TO 75:POKE SI+1,I:NEXT I

1550 FOR I=75 TO 1 STEP -1:POKE SI+1,I: NEXT I

1560 POKE SI+5,0:POKE SI+6,0

1570 RETURN

1600 REM *** FALL INS WASSER ***

1610 POKE SI+5,170:POKE SI+6,170

1620 POKE SI,0:POKE SI+1,50:POKE SI+4,118

1630 POKE SI+4,129

1640 FOR I=1 TO 500:NEXT I

1650 POKE SI+4,128

1660 RETURN

1700 REM *** WASERRAUSCHEN ***

1710 POKE SI+5,0:POKE SI+6,255

1720 POKE SI,0:POKE SI+1,100

1730 POKE SI+4,128:POKE SI+4,129

1740 RETURN

1800 REM *** KURZES TUTEN ***

1810 POKE SI+5,0:POKE SI+6,255: POKE SI+2,0:POKE SI+3,8

1820 POKE SI,0:POKE SI+1,20

1830 POKE SI+4,64:POKE SI+4,65

1840 FOR I=0 TO 50:NEXT I

1850 POKE SI+5,0:POKE SI+6,0

1860 RETURN

1900 REM *** KURZER CLICK ***

1910 POKE SI+5,3:POKE SI+6,0

1920 POKE SI,0:POKE SI+1,150

1930 POKE SI+4,128:POKE SI+4,129

1940 RETURN

2000 REM *** SCHRITT ***

2010 POKE SI+5,5:POKE SI+6,0

2020 POKE SI,0:POKE SI+1,10

2030 POKE SI+4,128:POKE SI+4,129

2040 RETURN

2100 REM *** FALL INS BODENLOSE ***

2110 POKE SI+5,0:POKE SI+6,255

2120 POKE SI,0:POKE SI+1,150

2130 POKE SI+4,16:POKE SI+4,17

2140 FOR I=150 TO 1 STEP -1

2150 POKE SI,0:POKE SI+1,I

2160 FOR J=1 TO 10:NEXT J

2170 NEXT I

2180 RETURN

2200 REM *** LASERSCHUSS ***

2210 POKE SI+5,0:POKE SI+6,255

2220 POKE SI,0:POKE SI+1,150

2230 POKE SI+4,128:POKE SI+4,129

2240 FOR I=150 TO 0 STEP -1

2250 POKE SI,0:POKE SI+1,I

2260 NEXT I

2270 POKE SI+5,6:POKE SI+6,0

2280 RETURN

 

In Zeile 5 wird erst einmal der SID initialisiert, indem die Basisadresse SI auf 54272, und die Lautstärke auf 100% gesetzt wird. Anschließend wird in Zeile 10 für das Menü ein schwarzer Hintergrund mit weißer Schrift ausgewählt. In den Zeilen 20-180 wird dann das Menü mit Hilfe von PRINT-Befehlen auf dem Bildschirm ausgegeben. In Zeile 190 wartet das Programm auf eine Taste, und ruft in den Zeilen 200-330 je nach vorher betätigter Taste ein entsprechendes Unterprogramm auf, das den ausgewählten Sound abspielt. Die Sound-Routinen werden nun ausführlich erklärt.

 

Explosion (Zeile 1000-1040, Taste 1)

 

In Zeile 1010 wird mit POKE SI+5,11:POKE SI+6,0 Attack=0 gesetzt, was bedeutet, dass der Ton sofort präsent ist. Decay wird hier auf 11, und Sustain und Release auf 0 gesetzt. Der Ton schwillt sofort ab, und hat auch keinen Haltepegel. In Zeile 1020 wird nun mit POKE SI,0:POKE SI+1,5 eine Frequenz von etwa 50 Hz ausgewählt, die zusammen mit der Rauschen-Wellenform einen sehr dumpfen Ton ergibt. Zusammen mit einem Decay-Wert von 11 ergibt sich nun der Eindruck einer Explosion, die nur langsam ausklingt. In Zeile 1030 wird nun der Sound durch POKE SI+4,128:POKE SI+4,129 gestartet. Da Sustain und Release den Wert 0 haben, wird der Sound erst gestoppt (Gate=0) und anschließend direkt danach wieder gestartet (Gate=1). In Zeile 1040 (RETURN-Anweisung) kehrt das Unterprogramm zum Hauptprogramm zurück, während der Ton weiter abgespielt wird.

 

dumpfe Explosion (Zeile 1100-1140, Taste 2)

 

Die dumpfe Explosion, die bei der Vernichtung sehr großer Raumschiffe abgespielt werden kann (bzw. nach Besiegen eines Endgegners), ist identisch mit dem Unterprogramm in Zeile 1000-1040 (normale Explosion), außer dass in Zeile 1120 nur eine Frequenz von 20 Hz ausgewählt wird. Der Ton ist also um 2,5 Oktaven tiefer, und deshalb sehr dumpf und laut.

 

Benzinmotor (Zeile 1200-1250)

 

Motorkolben erzeugen normalerweise bei der Explosion des Kraftstoffgemisches sehr komplexe Klangmuster. Diese Klangmuster kann der SID nicht darstellen, jedoch kann die Explosion im Kolben sehr gut durch die Rechteckwelle angenähert werden. Im Endeffekt bilden Sie an dieser Stelle einen idealen Motor ab: Das Gemisch zündet, und sofort danach erfolgt genau eine Umdrehung, die auch nur ein ganz kurzes Geräusch erzeugt. Um die Rechteckwelle zu benutzen, muss in Zeile 1210 durch POKE SI+2,0:POKE SI+3,8 die Pulsbreite (also der Bereich, in dem die Lautstärke 100% beträgt) ausgewählt werden. Eine Pulsbreite von 50 Prozent (das ist der Wert 2048, ausgedrückt auch hier wieder durch Lo- und Hi-Byte) erzeugt an dieser Stelle einen Klang, der einem Benzinmotor ähnelt (Erfahrungswert!). Um den Eindruck eines kontinuierlich laufenden Motors zu erzeugen, wird nun mit den folgenden Zeilen ein Dauerton erzeugt:

 

1220 POKE SI+5,0:POKE SI+6,255

1230 POKE SI,0:POKE SI+1,1

 

Attack und Decay ist an dieser Stelle 0, der Ton ist also sofort präsent. Allerdings ist Sustain=15 und Release=15, wodurch der SID direkt nach dem Start des Tones auf einer Lautstärke von 100% „hängenbleibt“. Die Frequenz des Tones ist mit etwa 15 Hz sehr niedrig und entspricht dem Standgas eines Motors. Wenn Sie eine andere Drehzahl wünschen, müssen Sie entsprechend in SID-Register Nr. 0 und 1 einen anderen Wert eintragen. In Zeile 1240 starten Sie den Sound nun durch POKE SI+4,64:POKE SI+4,65, wodurch die Rechteck-Wellenform ausgewählt wird. Zeile 1250 kehrt mit RETURN aus dem Unterprogramm zurück, während der Ton weiter abgespielt wird.

 

Dieselmotor (Zeile 1300-1350)

 

Da der Dieselmotor nur eine andere Bauart eines Motors mit einem anderen Kraftstoff ist, entspricht dieses Unterprogramm dem Unterprogramm in Zeile 1200-1250, außer dass hier die Pulsbreite der Rechteck-Welle 75% beträgt. Dadurch hört sich der Ton dumpfer und tiefer an, und „nagelt“ auch, so, wie man es von Dieselmotoren gewohnt ist.

 

Raumschiff (Zeile 1400-1440)

 

Diesen Sound kennen Sie bereits: Es wird ein tiefes Rauschen erzeugt, und in Zeile 1410 durch POKE SI+5,0:POKE SI+6,255 als Dauerton ausgegeben (Atack=0, Decay=0, Sustain=15, Release=15). Die Frequenz wird in Zeile 1420 durch POKE SI,0:POKE SI+1,5 festgelegt und in Zeile 1430 durch POKE SI+4,128:POKE SI+4,129 auf die Wellenform „Rauschen“ eingestellt. Die RETURN-Anweisung in Zeile 1440 kehrt danach zum Hauptprogramm zurück, während der Ton weiter abgespielt wird.

 

Sprung (Zeile 1500-1570)

 

Dieser Sound kann nicht im Hintergrund abgespielt werden, deshalb kehrt die RETURN-Anweisung in Zeile 1570 erst zum Hauptprogramm zurück, nachdem der komplette Sound abgespielt wurde. Auch für den Sprung wird in Zeile 1510 mit POKE SI+5,0:POKE SI+6,255 ein Dauerton erzeugt, der nur mit 15 Hz startet (Zeile 1520), und sich anschließend ändert. Zu diesem Zweck wird zunächst in Zeile 1530 durch POKE SI+4,16:POKE SI+4,17 die Dreieck-Wellenform ausgewählt, und gleichzeitig das Gate-Bit auf 1 gesetzt. Hierdurch ist der Ton sofort präsent, klingt aber nicht aus. Dies ist auch der Trick, der bei der Simulation eines Sprunges benutzt wird: Sie können die Frequenz ändern, während der Ton abgespielt wird. Dies geschieht in den folgenden zwei Schleifen:

 

1540 FOR I=1 TO 75:POKE SI+1,I:NEXT I

1550 FOR I=75 TO 1 STEP -1:POKE SI+1,I:NEXT I

 

Einmal steigt die Frequenz an (auf etwa 1200 Hz), und anschließend fällt sie wieder ab (auf die Ausgangsfrequenz von 15 Hz). Da BASIC-Schleifen sehr langsam sind, wird hier nur das Hi-Byte für das Frequenzregister geändert. Wenn der Sound vollständig abgespielt wurde, muss der Dauerton wieder aufgehoben werden, bevor das Unterprogramm zum Hauptprogramm zurückkehrt. Dies leisten die folgenden Zeilen:

 

1560 POKE SI+5,0:POKE SI+6,0

1570 RETURN

 

Fall ins Wasser (Zeile 1600-1660)

 

Wenn Sie von einem Sprungbrett ins Wasser springen, erzeugen Sie einen etwas komplexeren Klang, als bei einer Explosion: Erstens erzeugen Sie ein relativ hohes Rauschen, und zweitens verdrängen Sie das Wasser, während Sie in dieses eintauchen. Das bedeutet, dass Sie einen anschwellenden Ton programmieren müssen, der dann auch, nachdem Sie in das Wasser eingetaucht sind, noch einige Zeit anhält. Natürlich muss nach der Haltephase der Sound ausklingen. Für den Fall in das Wasser habe ich nun Attack, Decay, Sustain und Release auf 10 gesetzt, und die Frequenz auf den Ton A5 (880 Hz, PAL-Version) gesetzt. Dies leisten die folgenden BASIC-Zeilen:

 

1610 POKE SI+5,170:POKE SI+6,170

1620 POKE SI,0:POKE SI+1,50:POKE SI+4,118

 

Die Werte in den SID-Registern Nr. 5 und 6 kommen auf die folgende Weise zustande: Das hohe Nibble hat den Wert 10, was in BASIC dem Wert 16*10=160 entspricht. Dazu wird noch das niedrige Nibble mit dem Wert 10 addiert, macht zusammen 16*10+10=170.

Der Sound durchläuft sämtliche Phasen des ADSR-Zyklus, deshalb muss dieser in Zeile 1630 durch Setzen des Gate-Bits mit POKE SI+4,129 gestartet werden (hier wird dann auch gleichzeitig die Rauschen-Wellenform ausgewählt). Nun schwillt der Ton an, klingt ab, und verbleibt anschließend eine viertel Sekunde lang auf dem Sustain-Pegel (62,5%). Um dies zu gewährleisten, wird die folgende Warteschleife verwendet:

 

1640 FOR I=1 TO 500:NEXT I

 

Erst nach der Warteschleife wird der Release-Zyklus gestartet, indem in Zeile 1650 mit POKE SI+4,128 das Gate-Bit auf 0 gesetzt wird. In Zeile 1660 kehrt dann das Unterprogramm mit RETURN zum Hauptprogramm zurück.

 

Wasserrauschen (Zeile 1700-1740)

 

Sie können nicht nur ins Wasser springen, sondern sich auch außerhalb des Wassers befinden. In diesem Fall hören Sie (z.B. wenn Sie neben einem Wasserfall stehen) einen kontinuierlichen hohen Ton (in diesem Fall ist es ein hoher Dauerton mit etwa 1500 Hz). Dieser wird mit den folgenden BASIC-Zeilen erzeugt

 

1710 POKE SI+5,0:POKE SI+6,255

1720 POKE SI,0:POKE SI+1,100

 

Auch bei diesem Sound kehrt das Unterprogramm direkt nach der Initialisierung mit den folgenden BASIC-Zeilen sofort zum Hauptprogramm zurück:

 

1730 POKE SI+4,128:POKE SI+4,129

1740 RETURN

 

Viele Spiele, vor Allem Adventures, verwenden ähnliche Zeilen, um einen Raum mit Hintergrundgeräuschen „aufzupeppen“. Vor Allem Wasserfälle kommen deshalb oft in Adventures vor.

 

Kurzes Tuten (Zeile 1800-1860)

 

Nicht nur Spiele, sondern auch Anwendungen benutzen Sounds, um bestimmte Zustände anzuzeigen. So werden z.B. Tastatureingaben manchmal von einem kurzen Ton begleitet. Ein solches kurzes Tuten erzeugt das Unterprogramm in Zeile 1800-1860. Das Tuten besteht aus zwei Teilen. Der erste Teil erzeugt mit den folgenden BASIC-Zeilen einen Dauerton mit einer Rechteck-Wellenform:

 

1810 POKE SI+5,0:POKE SI+6,255:POKE SI+2,0:POKE SI+3,8

1820 POKE SI,0:POKE SI+1,20

1830 POKE SI+4,64:POKE SI+4,65

 

Anschließend tritt das Programm in die folgende kurze Warteschleife ein:

 

1840 FOR I=0 TO 50:NEXT I

 

Die Warteschleife sorgt dafür, dass der Ton eine kurze Zeit hörbar ist, allerdings dürfen Sie nicht zu lange warten, sonst wird Ihre Eingaberoutine zu langsam. Nach der Warteschleife wird der Sound mit folgenden Zeilen gestoppt:

 

1850 POKE SI+5,0:POKE SI+6,0

1860 RETURN

 

Sie setzen hier A=D=S=R=0, sodass der Sound sofort ausklingt, und der SID anschließend auch sofort wieder auf eine Änderung des Gate-Bits wartet. Man nennt diese Phase auch manchmal IDLE-Phase, was aber nicht ganz korrekt ist, weil der SID im Endeffekt nie „faul“ ist und nichts tut.

 

Kurzer Click (Zeile 1900-1940)

 

Bei einem kurzen Click, der entweder bei einem Schritt, oder aber auch z.B. bei Berühren einer Bande ausgelöst werden kann, können Sie keine Warteschleife ausführen, weil Sie vielleicht nachher noch andere Ereignisse abfragen müssen. Deshalb geht das Click-Beispiel einen ähnlichen Weg, wie der Klavier-Sound: Es wird in Zeile 1910 durch POKE SI+5,3:POKE SI+6,0 nur ein Decay-Wert definiert, Attack, Sustain und Release sind 0. Ein Wert von D=3 ist sehr gering, und bewirkt, dass der Click gerade mal 0,1 Sekunden lang abgespielt wird. Dies ist kurz, reicht aber aus, um ein Geräusch wahrzunehmen. Die Frequenz wird an dieser Stelle in Zeile 1920 durch POKE SI,0:POKE SI+1,150 sehr hoch eingestellt, was den Klang dann noch einmal deutlicher zutage treten lässt. Der Click benutzt dann auch die Rauschen - Wellenform (Zeile 1930). Auch dieses Unterprogramm kehrt in Zeile 1940 unverzüglich zum Hauptprogramm zurück. Allerdings kann es geschehen, dass besonders ältere Menschen über 70 Ihren Klick-Sound nicht wahrnehmen können (zu hohe Frequenz, zu kurze Dauer).

 

Schritt (Zeile 2000-2040)

 

In diesem Unterprogramm wird bewusst ein Sound erzeugt, der zu einem Schritt passt, den z.B. ein Kämpfer in einem Labyrinth-Spiel bei jeder Joystick-Bewegung ausführt. Dieses Beispiel ist identisch mit dem Unterprogramm in Zeile 1900-1940, allerdings ist hier die Tonfrequenz eine Oktave tiefer, und auch der Ton klingt etwas länger aus.

 

Fall ins Bodenlose (Zeile 2100-2180)

 

Dieser Fall besitzt keinen Startpunkt am unteren Ende der Frequenzskala, wie z.B. der Sprung - dieser Fall geht einfach ins Bodenlose. Wie auch schon beim Sprung, wird mit den folgenden BASIC-Zeilen ein Dauerton erzeugt:

 

2110 POKE SI+5,0:POKE SI+6,255

2120 POKE SI,0:POKE SI+1,150

2130 POKE SI+4,16:POKE SI+4,17

 

Die hier gewählte Wellenform ist die Dreieck-Wellenform, und die Frequenz wird auch hier während der Tonausgabe geändert. Allerdings dauert der Fall länger, als ein Sprung, deshalb wird hier die folgende verschachtelte Schleife verwendet:

 

2140 FOR I=150 TO 1 STEP -1

2150 POKE SI,0:POKE SI+1,I

2160 FOR J=1 TO 10:NEXT J

2170 NEXT I

 

Die äußere Schleife ändert das Hi-Byte für den Frequenzwert im Bereich von 150 bis 0, die innere Schleife führt dann zusätzlich zur Frequenzänderung eine kleine Warteschleife aus. Erst durch diese Maßnahme wird der Sprung zum langsamen Fallen. Erst nach Abspielen des kompletten Sounds kehrt das Unterprogramm in Zeile 2180 zum Hauptprogramm zurück.

 

Laserschuss (Zeile 2200-2280)

 

Auch der Laserschuss verwendet einen Dauerton, der variiert wird, allerdings wird die Rauschen-Wellenform anstatt der Dreieck-Wellenform verwendet.

 

6.5 Wirklich synchrone Stimmen

 

Wie schon gesagt, können Sie wirklich synchrone Stimmen in einem Musikstück nur durch Maschinensprache erreichen. Die Synchronisierung der Stimmen wird hier dadurch erreicht, dass der Player an den Timer-Interrupt gebunden wird, der normalerweise genau 60-mal in der Sekunde vom Kernal aufgerufen wird. Das heißt dann auch, dass der Player bei jedem Aufruf immer nur ein kleines Stückchen Ihres Songs abspielt. Da aber der Player so schnell hintereinander immer wieder aufgerufen wird, klingt die Wiedergabe sehr flüssig, und die Stimmen sind dann auch synchron. Dies heißt natürlich nun auch folgendes: Sie sind nun mit BASIC an die Grenze des Machbaren gestoßen, und müssen Maschinensprache lernen, wenn Sie noch mehr aus Ihrem SID herausholen wollen.