# 1 - Hallo zusammen :-)

Willkommen bei Sonic Pi! Hoffentlich bist Du genauso aufgeregt, verrückte Sounds zu machen, denn ich will Dir zeigen, wie das geht. Wir werden viel Spaß dabei haben, alles über Musik, Synthese, Coding, Komposition, Aufführung und andere Dinge zu lernen.

Doch halt, wie unhöflich von mir. Ich sollte mich erst einmal vorstellen - ich bin Sam Aaron - der Typ, der Sonic Pi gebaut hat. Du kannst mich unter @samaaron auf Twitter finden, schau doch mal vorbei. Vielleicht interessierst Du Dich auch für meine Live Coding Performances, wo ich den Code für die Musik direkt vor dem Publikum schreibe.

Bitte schreibe mir, wenn Du irgendwelche Einfälle oder Ideen zur Verbesserung von Sonic Pi hast - Feedback ist sehr hilfreich. Man kann ja nie wissen, vielleicht ist Deine Idee das nächste große Feature!

Dieses Tutorial ist in Abschnitte aufgeteilt, die in Gruppen zu unterschiedlichen Themen aufgeteilt sind. Auch wenn ich es so geschrieben habe, dass man damit von Anfang bis zum Ende einfach lernen kann, kannst Du an jeder Stelle einsteigen, ganz wie es Dir gefällt. Wenn Du etwas im Tutorial vermisst, lass es mich wissen, und ich überlege, wie ich das in zukünftige Versionen einbauen kann.

Besonders gut lernt man Live-Coding, wenn man anderen dabei zuschaut. Ich streame regelmäßig meine Musik auf livecoding.tv/samaaron, also schau doch mal rein, sag hallo oder frag mich dort ein wenig aus. :-)

Ok, dann legen wir los…

# 1.1 - Live-Coding

Mit Sonic Pi kannst Du etwas sehr aufregendes tun: Du kannst Musik aus Code live schreiben und verändern, während sie spielt. Fast so, als wenn Du mit einer Gitarre Musik machst. Mit anderen Worten: Du kannst Sonic Pi mit auf die Bühne nehmen und jammen!

## Mach mal kurz den Kopf frei

Wir werden in diesem Tutorial in die Details von Sonic Pi eintauchen. Jetzt möchte ich Dir aber erst einmal zeigen, wie das ist, live Musik zu coden. Keine Sorge, Du wirst vielleicht nicht sofort alles verstehen. Aber das macht nichts. Genieße kurz diesen Einblick.

## Eine Live-Loop

Lass uns loslegen. Kopiere den folgenden Code nach oben in einen leeren Buffer:

    live_loop :flibble do
      sample :bd_haus, rate: 1
      sleep 0.5
    end

Jetzt drücke den `Ausführen`-Button und Du wirst eine schöne Bass-Drum hören, die schnell vor sich hin hämmert. Mit einem Druck auf den `Stopp`-Button hört die Musik wieder auf. Aber drücke bitte noch nicht darauf… sondern probiere die folgenden Veränderungen aus:

1. Lass den Beat der Bass-Drum weiter laufen.
2. Verändere die Zahl hinter `sleep` von `0.5` auf einen höheren Wert, etwa `1`.
3. Drücke wieder den `Ausführen`-Button.
4. Gemerkt? Die Geschwindigkeit der Bass-Drum hat sich verändert.
5. Merke Dir diesen Moment. Du hast mit Sonic Pi zum ersten Mal live Code geschrieben. Wahrscheinlich wird es nicht das letzte Mal sein…

Ok, das war einfach. Verändern wir also die Zutaten ein wenig. Vor `sample :bd_haus` kannst Du die Zeile `sample :ambi_choir, rate: 0.3` einfügen. Dein Code müsste dann so aussehen:

    live_loop :flibble do
      sample :ambi_choir, rate: 0.3
      sample :bd_haus, rate: 1
      sleep 1
    end

So, jetzt spiele damit herum. Verändere die Werte für `rate:` - was passiert, wenn Du hohe, kleine oder negative Zahlen einträgst? Hast Du gemerkt, wie sich eine sehr kleine Änderung des `rate:`-Wertes für das `:ambi_choir`-Sample auswirkt (z.B. 0.29)? Was passiert bei einem wirklich kleinen `sleep`-Wert? Kannst Du eine Fehlermeldung Deines Computers auslösen, wenn Du den Wert immer kleiner werden lässt? (Wenn das geschieht, nimm einfach wieder einen größeren Wert für `sleep` und drücke auf `Ausführen`.)

Kommentiere eine Code-Zeile aus, indem Du ein `#` an ihren Anfang schreibst:

    live_loop :flibble do
      sample :ambi_choir, rate: 0.3
    #  sample :bd_haus, rate: 1
      sleep 1
    end

Siehst Du? Jetzt ignoriert der Computer diese Zeile und wir hören den Befehl nicht mehr. Was hinter einem `#` steht ist ein Kommentar. Wir können dieses Zeichen benutzen, um Code schnell zu entfernen und später wieder einzufügen.

Zum Abschluss möchte ich Dir etwas zum Spielen geben. Nimm den Code unten und kopiere ihn in einen freien Buffer. Macht nix, Du musst noch nicht alles davon durchschauen, aber Du siehst, dass da zwei Loops sind - zwei Schleifen, die gleichzeitig laufen und sich endlos wiederholen. Jetzt tue, was Du am besten kannst: Experimentiere und spiele herum. Hier sind ein paar Vorschläge:

- Ändere die blauen Werte hinter `rate:` und höre zu, wie sich das Sample verändert.
- Ändere die Zeitwerte von `sleep` und beobachte, wie die beiden Schleifen in unterschiedlicher Weise aneinander vorbei laufen.
- Hole die auskommentierte Sample-Zeile wieder hervor und genieße den Sound einer umgekehrt abgespielten Gitarre.
- Probiere, die blauen Werte von `mix:` auf Werte zwischen `0` (nicht im Mix) und `1` (voll im Mix) zu ändern.

Vergiss nicht, `Ausführen` zu drücken, dann hörst Du sofort beim nächsten Durchlauf der Loops Deine Änderungen. Wenn irgendwas schiefgeht - macht nichts! Drücke `Stopp`, lösche den kaputten Code und fang mit dem ursprünglichen Code noch einmal von vorn an. Denn am besten lernt man beim Fehlermachen…

    live_loop :guit do
      with_fx :echo, mix: 0.3, phase: 0.25 do
        sample :guit_em9, rate: 0.5
      end
    #  sample :guit_em9, rate: -0.5
      sleep 8
    end

    live_loop :boom do
      with_fx :reverb, room: 1 do
        sample :bd_boom, amp: 10, rate: 1
      end
      sleep 8
    end

Spiele also herum und experimentiere, bis Deine Neugierde einsetzt und Du Dich fragst, wie das hier alles eigentlich wirklich funktioniert und was man noch so alles damit anstellen kann. Jetzt bist Du bereit für den Rest dieses Tutorials.

Worauf wartest Du…?

# 1.2 - Die Programmoberfläche von Sonic Pi

Sonic PI hat eine sehr einfache Oberfläche zum Coden von Musik. Schauen wir uns das einmal genauer an.

- A - Wiedergabe-Steuerung
- B - Editor-Steuerung
- C - Info und Hilfe
- D - Code-Editor
- E - Protokoll-Fenster
- F - Hilfe-System

## A. Wiedergabe-Steuerung

Mit diesen pinkfarbenen Buttons kannst Du Klänge abspielen und stoppen. Der `Ausführen`-Button startet den Code im Editor, `Stopp` hält den ablaufenden Code an, `Speichern` schreibt den Code in eine Datei und `Aufnehmen` nimmt den gerade laufenden Sound (in einer WAV-Datei) auf.

## B. Editor-Steuerung

Die orangefarbenen Buttons steuern den Code-Editor. Die `Text vergrößern` und `Text verkleinern`-Buttons verändern die Schriftgröße. `Auto-Align Text`-Button richtet den Code ordentlich aus, damit er professioneller aussieht und besser lesbar ist.

## C. Information und Hilfe

Die blauen Buttons bieten Dir den Zugriff auf Informationen, die Hilfe und die Voreinstellungen. Der `Info`-Button öffnet ein Fenster mit Informationen über Sonic Pi selbst und wo Du mehr Informationen und Hilfe von anderen findest. Der `Hilfe`-Button zeigt/verbirgt das eingebaute Hilfesystem (F) und `Einstellungen` zeigt/verbirgt das Fenster, wo Du einige grundsätzliche Einstellungen regeln kannst.

## D. Code-Editor

In diesem Bereich schreibst Du Deinen Code, komponierst Du Deine Musik und führst sie später auf. Es ist ein einfacher Texteditor, in dem Du Code eingibst und bearbeitest; so eine Art sehr einfache Textverarbeitung wie Word oder Google Docs. Der Editor färbt bestimmte Begriffe automatisch ein, je nachdem, welche Bedeutung sie innerhalb des Codes haben. Am Anfang ist das vielleicht ein wenig merkwürdig, aber Du wirst es bald nützlich finden. Zum Beispiel erkennst Du Zahlen sofort daran, dass sie blau eingefärbt sind.

## E. Protokoll-Fenster

Wenn Dein Code abläuft, siehst Du im Protokoll-Fenster, was das Programm gerade tut. Standardmäßig siehst Du eine Nachricht für jeden erzeugten Klang und die exakte Zeit, wann der Klang ausgelöst wurde. Bei der Suche nach Fehlern kann das sehr hilfreich sein und Du verstehst schneller, was Dein Code macht.

## F. Hilfe-System

Das Hilfe-System im unteren Bereich des Programmfensters ist einer der wichtigsten Teile von Sonic Pi. Du kannst es ein- und ausblenden, indem Du den blauen`Hilfe`-Button klickst. Es enthält Hilfe und Informationen über alle Aspekte von Sonic Pi, einschließlich dieses Tutorials, einer Liste der mitgelieferten Synths, Samples, Beispiele, Effekte (FX1) sowie eine komplette Liste aller Funktionen, die Sonic Pi zum Coden von Musik bereitstellt.

1. Im Englischen wird der Begriff Effekte manchmal lautmalerisch mit FX (“ef-eks”) abgekürzt; FX bezeichnet also die Klangeffekte in Sonic Pi. ↩

# 1.3 - Spielend lernen

Sonic Pi soll Dich dazu animieren, etwas über Computer und Musik zu lernen - und zwar auf eine spielerische und experimentelle Weise. Das allerwichtigste ist, dass Du Spaß hast. Und bevor Du es überhaupt bemerkt hast, wirst Du zufällig gelernt haben, Code zu schreiben, zu komponieren und Musik aufzuführen.

## Es gibt keine Fehler

Einen kleinen Rat möchte ich Dir noch geben, bevor wir anfangen. Ich habe das über die Jahre gelernt, in denen ich Musik live programmiert habe - es gibt keine Fehler, nur Gelegenheiten. Im Jazz habe ich das schön öfters gehört, aber man kann diese Idee auch auf das Live-Coding anwenden. Es spielt keine Rolle, wieviel Erfahrung Du hast, ob Du ein absoluter Anfänger oder ein erfahrender Algoraver bist, Du wirst Code laufen lassen, der vollkommen unerwartete Ergebnisse mit sich bringt. Kann sein, dass es unglaublich cool klingt - dann mache weiter. Kann auch sein, dass es schrecklich klingt und vollkommen fehl am Platz ist. Es spielt keine Rolle, dass so etwas passiert, wichtig ist, was Du damit als nächstes machst. Nimm den Sound, bearbeite ihn und mach daraus etwas Tolles. Die Menge wird durchdrehen.

## Fang einfach an

Wenn man lernt, will man die tollen Sachen am liebsten sofort machen. Vergiss das nicht, aber sieh es als ein Ziel an, welches Du erst etwas später erreichen kannst. Überlege Dir aber zunächst mal die einfachste Sache, die Dir Spaß machen wird, und die lohnend erscheint; diese Sache ist ein kleiner Schritt auf dem Weg zu dem faszinierenden Ding, das Dir im Kopf herumgeht. Wenn Dir dieser einfache Schritt klar ist, versuche ihn umzusetzen, spiele damit herum und finde heraus, auf was für neue Ideen Du kommst. Es wird nicht lange dauern und Du wirst viel Spaß haben und Fortschritte machen.

Und: Sorg dafür, dass Du Deine Werke mit anderen teilst!

# 2 - Synths

Ok, genug der Einführung - jetzt wollen wir Klänge machen.

In diesem Abschnitt besprechen wir, wie man Synths ansteuert und manipuliert. Synth ist die Kurzform von Synthesizer - ein hochtrabendes Wort für ein Ding, das einen Klang erzeugt. Typischerweise sind Synths ziemlich kompliziert im Gebrauch, vor allem analoge Synths mit ihren vielen Kabeln und Modulen. Sonic Pi stellt Dir aber vieles davon auf eine einfache und gut zugängliche Art zur Verfügung.

Die Programmoberfläche von Sonic Pi mag simpel erscheinen, doch wenn Du willst, kannst Du damit sehr tief in ausgeklügelte Klangmanipulationen eintauchen.

Haltet Euch fest…

# 2.1 - Eure ersten Klänge

Seht Euch den folgenden Code an:

    play 70

Damit fängt alles an. Leg los, kopiere und setze das in das Code-Fenster oben im Programm ein (der große weiße Raum unter dem Ausführen-Button). Nun klicke auf Ausführen…

## Beep!

Stark. Klicke den Button nochmal. Und nochmal. Und nochmal…

Wow, verrückt, ich bin sicher, dass könntet Ihr den ganzen Tag lang machen. Aber halt, bevor Ihr Euch in einem endlosen Strom von Piepstönen verliert, versuche es mit einer anderen Zahl:

    play 75

Hörst Du den Unterschied? Nimm eine niedrigere Zahl:

    play 60

Aha, kleine Zahlen erzeugen niedrigere Töne und große Zahlen höhrere. Wie auf dem Klavier spielt man mit den unteren Tasten (die Seite der linken Hand) niedrigere Töne und mit den oberen Tasten (die Seite der rechten Hand) höhere Töne. Tatsächlich stehen die Zahlen und die Töne auf dem Klavier in einer Beziehung zueinander. `play 47` bedeutet, spielt den 47. Ton auf dem Klavier. Also spielt `play 48` die nächste Taste rechts davon, einen Ton höher. Das C in der vierten Oktave hat in dieser Zählweise die Nummer 60. Das kannst Du so spielen: `play 60`.

Keine Sorge, wenn Du keine Ahnung hast, was das alles bedeutet. Mir ging es zu Beginn auch so. Für den Anfang reicht es zu wissen: Kleinere Zahlen bedeuten tiefere Klänge und größere Zahlen bedeuten höhere Klänge.

## Akkorde

Eine Note zu spielen kann ganz lustig sein, aber mehrere zur selben Zeit zu spielen ist noch besser. Versuche es:

    play 72
    play 75
    play 79

Wow! Wenn Du also `play` mehrmals hinschreibst, spielen sie alle zur selben Zeit. Versuche es selbst - welche Nummern klingen gut zusammen? Was klingt fürchterlich? Experimentiere, erforsche und erkunde selbst.

## Melodie

Einzelne Noten und Akkorde zu spielen macht Spaß - aber wie wäre es mit einer Melodie? Was, wenn Du eine Note nach der anderen spielen wolltest und nicht alle zur selben Zeit? Also das geht ganz einfach, Du brauchst nur ein `sleep` zwischen den Noten:

    play 72
    sleep 1
    play 75
    sleep 1
    play 79

Wie hübsch, ein kleines Arpeggio. Was bedeutet die `1` in `sleep 1`? Sie gibt die Dauer von sleep an. Tatsächlich bedeutet das: Schlafe für einen Schlag. Aber vorläufig können wir uns vorstellen, dass es bedeutet: Schlafe für eine Sekunde. Wie könnten wir unser Arpeggio schneller ablaufen lassen? Dazu brauchen wir kürzere Werte für sleep. Wie wäre es z.B. mit `0.5`:

    play 72
    sleep 0.5
    play 75
    sleep 0.5
    play 79

Achte darauf, dass die Melodie nun schneller spielt. Probiere das selbst aus, ändere die Zeiten, verwende unterschiedliche Zeiten und Noten.

Versuche einmal Zwischennoten wie `play 52.3`1 und `play 52.63`. Es gibt überhaupt keinen Grund, nur ganze Zahlen zu verwenden. Spiel damit herum und hab Spaß dabei.

## Traditionelle Notennamen

Für die unter Euch, die das Notenschreiben schon ein bisschen kennen (keine Sorge, wenn nicht - Du brauchst es nicht unbedingt) - vielleicht möchtet Ihr eine Melodie mit Notennamen anstelle von Zahlen schreiben, also C oder F#2. Auch das geht mit Sonic Pi. Du kannst folgendes machen:

    play :C
    sleep 0.5
    play :D
    sleep 0.5
    play :E

Denk daran, vor den Notennamen einen `:` zu stellen, sodass dieser sich Pink einfärbt. Die jeweilige Oktave kannst Du als Zahl dahinter schreiben:

    play :C3
    sleep 0.5
    play :D3
    sleep 0.5
    play :E4

Wenn Du eine Note um einen Halbton erhöhen willst, füge ein `s` hinzu, also `play :Fs3`. Und wenn Du die Note um einen Halbton erniedrigen möchtest, füge ein `b` an, also `play :Eb3`.

Jetzt mach was Verrücktes und baue Deine eigenen Melodien.

## Anmerkungen des Übersetzers

1. Im deutschsprachigen Raum schreibt man solche Zahlen normalerweise mit Komma, also `52,3`. Der Computer versteht aber nur Englisch, deshalb verwenden wir für Zahlen mit Nachkommastellen einen Punkt - also `52.3`. ↩

2. Auch hier gibt es im deutschsprachigen Raum eine andere Schreibweise: Erhöhte oder erniedrigte Noten z.B. das F werden als Fis oder Fes bezeichnet. Im Englischen heisst das Fis “F sharp” oder auch “F#” und das Fes “F flat” oder auch “Fb”.

   Ansonsten sind die Notennamen mit einer Ausnahme gleich: Die Note H ist im Englischen das B. Und das um einen Halbton erniedrigte H heisst bei uns B, während es im Englischen logischerweise als “B flat” bezeichnet wird. Die C-Dur-Tonleiter lautet im Deutschen `C D E F G A H C`, während sie im Englischen so lautet: `C D E F G A B C`.

   Sonic Pi verwendet diese englische Namensgebung für Noten. ↩

# 2.2 - Synth-Parameter: Amp and Pan

Mit Sonic Pi kannst Du nicht nur Noten und Samples abspielen. Ebenso kannst Du die Klänge mit Parametern gestalten und beeinflussen. Wir werden viele davon in diesem Tutorial behandeln, für jeden Parameter gibt es ausführliche Informationen in der Hilfe. Zwei der nützlichsten sehen wir uns gleich mal an: Amplitude und Pan. Aber vorher lass mich kurz erklären, was Parameter eigentlich sind.

## Parameter

Die Synths von Sonic Pi lassen sich über verschiedene Parameter verändern. Parameter sind Regler, die `play` oder `sample` übergeben werden; sie verändern und steuern die Art, wie sich die Klänge anhören. Jeder Synth hat seine eigenen Parameter, um den Klang fein einzustellen. Es gibt auch Parameter, die für viele Klänge gleich sind, z.B. `amp:` und Hüllkurven-Parameter (die wir an anderer Stelle besprechen).

Parameter bestehen aus zwei Teilen: Ihrem Namen (der Name des Reglers) und ihrem Wert (den Wert, auf den Du den Regler setzten möchtest). Zum Beispiel könntest Du einen Parameter mit dem Namen `cheese:` haben, dem Du den Wert `1` geben möchtest.

Parameter werden den Aufrufen von `play` und `sample` mit einem Komma `,` übergeben, dem der Name des Parameters folgt, etwa `amp:` (vergiss den Doppelpunkt nicht `:`), dann eine Leerstelle und schließlich der Wert des Parameters. Zum Beispiel:

    play 50, cheese: 1

(Den Parameter `cheese:` gibt es in Wirklichkeit gar nicht, wir nehmen ihn hier nur als Beispiel).

Du kannst mehrere Parameter hintereinanderschreiben, indem Du sie mit weiteren Kommata abtrennst:

    play 50, cheese: 1, beans: 0.5

Die Reihenfolge der Parameter spielt keine Rolle, so dass die folgende Zeile dasselbe tun würde wie die vorherige:

    play 50, beans: 0.5, cheese: 1

Parameter, die vom Synth nicht erkannt werden, werden einfach links liegen gelassen (so wie `cheese` und `beans`, welches ja wirklich lachhafte Namen für einen Parameter wären!).

Wenn Du aus Versehen zweimal denselben Parameter benutzt, gewinnt der letzte. Im folgenden Beispiel wird `beans` den Wert 2 bekommen und nicht 0.5:

    play 50, beans: 0.5, cheese: 3, eggs: 0.1, beans: 2

Viele Dinge in Sonic Pi lassen sich über Parameter steuern; nimm Dir ein bisschen Zeit zu lernen, wie Du sie einsetzen kannst, und Du bist startklar. Jetzt spielen wir mal mit unserem ersten Parameter: `amp:`.

## Amplitude

Die Amplitude ist die Weise, wie sich der Computer die Lautstärke eines Klangs vorstellt. Eine hohe Amplitude ergibt einen lauteren Klang und eine niedrige Amplitude ergibt einen leiseren Klang. So wie Sonic Pi Zahlen dazu benutzt, um Zeit und Töne darzustellen, so benutzt es Zahlen auch dazu, um die Lautstärke abzubilden. Eine Amplitude von 0 bedeutet Stille (Du wirst nichts hören), eine Amplitude von 1 steht für normale Lautstärke. Du kannst die Amplitude aufdrehen auf 2, 10, 100. Aber Vorsicht: Wenn die Amplitude aller gemeinsamen Klänge zu hoch wird, setzt Sonic Pi einen sogenannten Kompressor ein, damit die Klänge nicht zu laut für Dein Ohr werden. Oft klingt das dann matschig und schräg. Verwende also lieber niedrigere Amplituden, das heißt zwischen 0 und 0.5, um die Kompression zu verhindern.

## Amp verwenden

Um die Amplitude eines Klangs zu ändern, setze den Parameter `amp:` ein. Mit 0.5 lässt Du zum Beispiel den Klang mit halber Amplitude spielen:

    play 60, amp: 0.5

Und für die doppelte Amplitude:

    play 60, amp: 2

Der Parameter `amp:` beeinflusst nur den Aufruf von `play`, mit dem er unmittelbar zusammenhängt. Das heißt, in dem folgenden Beispiel wird der erste Aufruf von `play` mit halber Lautstärke gespielt und der zweite wieder mit der Standardlautstärke (1) 1:

    play 60, amp: 0.5
    sleep 0.5
    play 65

Natürlich kannst Du für jeden Aufruf von `play` andere Werte für `amp:` festlegen:

    play 50, amp: 0.1
    sleep 0.25
    play 55, amp: 0.2
    sleep 0.25
    play 57, amp: 0.4
    sleep 0.25
    play 62, amp: 1

## Panning

Ein weiterer interessanter Parameter ist `pan:`. Er gibt an, aus welcher Richtung der Klang kommt, wenn wir in Stereo hören. Der Wert -1 schiebt den Klang ganz nach links, 0 steht für die Mitte und 1 lässt den Klang nur aus dem rechten Lautsprecher kommen. Natürlich kannst Du jeden Wert zwischen -1 und 1 verwenden, um Deine Klänge im Stereofeld zu positionieren.

Spiel einen Klang, der nur aus linken Lautsprecher kommt:

    play 60, pan: -1

Jetzt aus dem rechten Lautsprecher:

    play 60, pan: 1

Nun lass den Klang aus der Mitte herauskommen (die Standardposition):

    play 60, pan: 0

Jetzt leg’ los und arbeite mit der Amplitude und dem Panning von Deinen Klängen.

1. In Programmiersprachen nennt man einen Standardwert einen `Default`. Genauer gesagt ist ein `Default`-Wert der Wert, der automatisch gesetzt wird, also die `Voreinstellung` im Programm. ↩

# 2.3 - Synths wechseln

Bis jetzt hatten wir viel Spaß mit Tönen und Samples. Aber wahrscheinlich wird Dir langsam langweilig, immer denselben Klang zu hören. Ist das alles, was Sonic Pi anzubieten hat? Besteht das Live-Coding nicht aus mehr als Pieptönen? Aber klar doch, und in diesem Abschnitt sehen wir uns die spannenden Sounds an, die Sonic Pi mitbringt.

## Synths

Sonic Pi bringt eine Palette an Instrumenten mit, die Synths heissen, eine Kurzform für Synthesizer. Samples sind vorher aufgenommene Klänge; demgegenüber erzeugen Synths neue Klänge, je nachdem, wie Du sie anlegst (wie das geht, werden wir später sehen). Die Synths von Sonic Pi sind sehr wirkungsvoll und ausdrucksstark und man kann damit tolle Sachen machen. Als erstes lernen wir, wie man einen Synth auswählt, den man benutzen möchte.

## Brilliante Sägen und Prophets1

Einen spaßigen Sound ergibt die Sägezahn-Welle - probieren wir es mal aus:

    use_synth :saw
    play 38
    sleep 0.25
    play 50
    sleep 0.25
    play 62

Nehmen wir einen anderen Klang - den Prophet:

    use_synth :prophet
    play 38
    sleep 0.25
    play 50
    sleep 0.25
    play 62

Wie wäre es damit, beide Sounds zu verbinden? Zuerst nacheinander:

    use_synth :saw
    play 38
    sleep 0.25
    play 50
    sleep 0.25
    use_synth :prophet
    play 57
    sleep 0.25

Nun gleichzeitig:

    use_synth :tb303
    play 38
    sleep 0.25
    use_synth :dsaw
    play 50
    sleep 0.25
    use_synth :prophet
    play 57
    sleep 0.25

Hast Du bemerkt, dass das `use_synth`-Kommando nur die nachfolgenden `play`-Kommandos beeinflusst? Stell es Dir als einen großen Schalter vor - neue Aufrufe von `play` werden immer den Synth benutzen, auf den der Schalter gerade zeigt. Du kannst diesen Schalter mit `use_synth` auf einen anderen Synth umschalten.

## Synths entdecken

Du kannst herausfinden, welche Synths Sonic Pi für Dich bereitstellt, indem Du im Menü auf der linken Seite Synths anklickst (gleich neben Fx). Es gibt über 20 Stück. Das sind einige meiner Lieblings-Synths:

- `:prophet`
- `:dsaw`
- `:fm`
- `:tb303`
- `:pulse`

Spiel mal ein bisschen herum, indem Du in Deinem Stück die Synths wechselst. Kombiniere unterschiedliche Synths oder setze sie für unterschiedliche Stellen in Deinem Stück ein.

1. Der Name “Sägezahn” (engl. saw) kommt von der Wellenform, die dieser Synthesizer produziert. Wenn man sich diesen Klang mit einem Oszilloskop anzeigen lässt, sieht er aus wie die Zähne einer Säge. Der Name “Prophet” kommt von einem Synthesizer, der Ende der 70er Jahre vom amerikanischen Hersteller Sequential Circuits hergestellt worden ist. ↩

# 2.4 - Dauer und Hüllkurven

Wie wir schon vorher gesehen haben, können wir mit dem `sleep`-Kommando steuern, wann ein Klang zu spielen anfängt. Bislang konnten wir aber noch nicht die Dauer eines Klangs steuern (außer bei Samples, die wir strecken oder verdichten können).

Um die Dauer von Klängen auf einfache, aber tiefgehende Weise zu beeinflussen, bietet Sonic Pi das Prinzip der ADSR-Hüllkurve 1. (Wir werden später sehen, was ADSR genau bedeutet). Eine Hüllkurve hat zwei nutzbringende Eigenschaften:

- Kontrolle über die Dauer eines Klangs
- Kontrolle über die Amplitude (Lautstärke) eines Klangs

## Dauer

Die Dauer bestimmt, wie lange ein Klang klingt. Eine erhöhte Dauer bedeutet, dass Du den Klang länger hören kannst. Alle Klänge in Sonic Pi haben eine Hüllkurve, die beeinflusst werden kann, und die gesamte Dauer dieser Hüllkurve bestimmt die Dauer des Klangs. Deshalb kann man über die Kontrolle der Hüllkurve die Dauer des Klangs beeinflussen.

## Amplitude

Die ADSR-Hüllkurve kontrolliert nicht nur die Dauer, sondern ermöglicht Dir auch die genaue Kontrolle über die Amplitude eines Klangs. Alle Klänge beginnen und enden mit Stille; dazwischen ist irgendetwas hörbar. Hüllkurven erlauben Dir, die Amplitude der hörbaren Anteile des Klanges zu verschieben, zu verlängern und zu verkürzen. Es ist so, als würdest Du jemanden sagen, wie er die Lautstärke einer Musik lauter und leiser dreht. Du könntest denjenigen z.B. bitten: “Fang bitte mit einer Stille an, dreh dann die Lautstärke langsam bis zum Anschlag hoch, lass es eine Weile so und blende dann schnell runter, bis man nichts mehr hört”. Genau dafür sind in Sonic Pi die Hüllkurven da.

Wie wir vorher schon gesehen haben, bedeutet eine Amplitude von 0 Stille und eine Amplitude von 1 entspricht der normalen Lautstärke.

## Release-Zeit

Standardmäßig haben alle Synths eine Release-Zeit von der Länge 1. Das bedeutet, sie haben eine Dauer von 1 Schlagzeit (die in der Grundeinstellung 1 Sekunde lang ist), bevor sie verklungen sind. Über das das `release`-Argument der Funktion `play` können wir diese Dauer verändern. Damit ein Synth 2 Schläge lang spielt, übergeben wir z.B. einen `release` von `2`:

    play 60, release: 2

Mit einer sehr kurzen Release-Zeit können wir den Synth-Klang auch sehr kurz machen:

    play 60, release: 0.2

Also was ist nun die Release-Zeit? Es ist die Zeit, die der Klang braucht, um von der vollen Höhe der Kurve (typischerweise der Wert 1) bis auf Null abzufallen. Das nennt man auch die Release-Phase und es ist ein linearer Übergang (d.h. eine gerade Linie). Die folgende Abbildung zeigt, wie ein solcher Übergang aussieht:

Die senkrechte Linie ganz links im Bild zeigt, dass der Klang mit einer Amplitude von 0 startet, jedoch sofort auf die volle Höhe geht (das ist die Attack-Phase, die wir gleich ansehen werden). Wenn die volle Höhe erreicht ist, geht die Amplitude in einer geraden Linie bis auf Null zurück, wobei dies so lange dauert, wie es mit `release` festgelegt wurde. Je länger die Release-Zeit eines Synth, desto länger klingt dieser aus.

Deshalb kannst Du die Länge eines Klangs ändern, wenn Du seine Release-Zeit änderst. Spiele einmal mit unterschiedlichen Release-Zeiten herum.

## Attack-Zeit

Standardmäßig ist die Attack-Phase für alle Synths 0, was bedeutet, dass diese sofort von der Amplitude 0 auf 1 hochgehen. Dies gibt dem Synth einen perkussiven Klang. Vielleicht möchtest Du den Klang jedoch einblenden. Dies kannst Du mit dem `attack`-Argument erreichen. Blende einige Klänge ein:

    play 60, attack: 2
    sleep 3
    play 65, attack: 0.5

Du kannst mehrere Argumente zur selben Zeit anwenden. Zum Beispiel für eine kurze Attack- und eine lange Release-Zeit:

    play 60, attack: 0.7, release: 4

Diese Hüllkurve mit einem kurzen Attack und langem Release sieht so aus:

Natürlich kann man die Dinge auch umdrehen. Versuche einen langen Attack und einen kurzen Release:

    play 60, attack: 4, release: 0.7

Schließlich kannst Du auch einen kurzen Attack und Release für kürzere Klänge verwenden.

    play 60, attack: 0.5, release: 0.5

## Sustain-Zeit

Zusätzlich zu den Attack- und Release-Zeiten kannst Du auch die Sustain-Zeit bestimmen. Das ist die Zeitdauer, die der Klang anhält, wenn er die eingestellte Lautstärke erreicht hat, also zwischen dem Attack- und dem Release-Stadium.

    play 60, attack: 0.3, sustain: 1, release: 1

Die Sustain-Zeit kann man gut dafür gebrauchen, um wichtige Klänge in einem Mix hervorzuheben, bevor möglicherweise der Release einsetzt. Natürlich kann man ohne weiteres sowohl den Attack als auch den Release auf 0 setzen und nur den Sustain gebrauchen. Damit bekommt man einen Klang ohne Ein- und Ausblendung. Aber vorsicht, ein Release von 0 kann Klickgeräusche in der Aufnahme verursachen. Meist ist es besser, einen geringen Wert wie z.B. 0.2 zu verwenden.

## Decay-Zeit

Und schließlich, falls Du alles ganz genau beeinflussen möchtest, kannst Du noch die Decay-Zeit festlegen. Das ist eine Phase der Hüllkurve, die zwischen die Attack- und die Release-Phase passt; sie gibt die Zeit an, wo die Amplitude vom `attack_level` zum `sustain_level` hinunterfällt. Normalerweise steht das Decay-Argument auf 0, während sowohl das Attack- als auch das Sustain-Level auf 1 stehen. Damit die Decay-Zeit einen hörbaren Effekt hat, müssen Attack und Sustain also auch angegeben werden:

    play 60, attack: 0.1, attack_level: 1, decay: 0.2, sustain_level: 0.4, sustain: 1, release: 0.5

## ADSR-Hüllkurven

Fassen wir noch einmal zusammen: Die ADSR-Hüllkurven von Sonic Pi bestehen aus den folgenden Phasen:

1. attack - die Zeit, welche die Amplitude von 0 bis zum `attack_level` benötigt,
2. decay - die Zeit, in der die Amplitude vom `attack_level` zum `sustain_level` übergeht,
3. sustain - die Zeit, in der sich die Amplitude auf dem `sustain_level` hält,
4. release - die Zeit, welche die Amplitude vom `sustain_level` auf 0 bringt

Eins ist wichtig: der Klang dauert so lange wie die Summe aller Zeiten der unterschiedlichen Phasen. Deshalb hat der folgende Klang eine Dauer von 0.5 + 1 + 2 + 0.5 = 4 Schlägen:

    play 60, attack: 0.5, decay: 1, sustain_level: 0.4, sustain: 2, release: 0.5

Jetzt weisst Du, wie Du Deine Klänge mit Hüllkurven verändern kannst…

1. Der englische Begriff für Hüllkurve heißt Envelope.

   ADSR steht als Kurzform für die Begriffe Attack, Decay, Sustain und Release, die in diesem Kapitel erklärt werden. ↩

# 3 - Samples

Du kannst auch aufgenommene Sounds in Deiner Musik verwenden. In der großen Tradition des Hip-Hop nennen wir diese aufgenommenen Sounds auch Samples. Also, wenn Du ein Mikrophon mit nach draußen nimmst und den zarten Klang der Regentropfen auf einem Zeltdach aufnimmst, dann ist das Ergebnis ein Sample.

Mit Samples kann man in Sonic Pi viele tolle Sachen machen. Es sind nicht nur 90 freie Samples zum sofortigen Gebrauch dabei, sondern Du kannst auch Deine eigenen Samples einbauen und verändern.

Legen wir los…

# 3.1 - Samples ansteuern

Pieptöne zu spielen ist erst der Anfang. Mit aufgenommenen Samples hat man noch viel mehr Spaß. Probier mal:

    sample :ambi_lunar_land

Sonic Pi enthält viele Samples, mit denen Du spielen kannst. Du kannst sie ebenso wie das `play`-Kommando benutzen. Um mehrere Samples gleichzeitig zu spielen, schreib sie einfach untereinander:

    play 36
    play 48
    sample :ambi_lunar_land
    sample :ambi_drone

Wenn Du sie nacheinander spielen willst, füge einen `sleep`-Befehl ein:

    sample :ambi_lunar_land
    sleep 1
    play 48
    sleep 0.5
    play 36
    sample :ambi_drone
    sleep 1
    play 36

Hast Du bemerkt, dass Sonic Pi nicht wartet, bis ein Klang beendet ist, bevor der nächste beginnt? Der `sleep`-Befehl beschreibt nur, wann ein Klang ausgelöst wird, und wann der nächste nachfolgt. Damit kannst Du Klänge in Schichten übereinander legen und interessante überlappende Effekte herstellen. Später sehen wir uns an, wie man die Länge von Klängen mit Hüllkurven kontrollieren kann.

## Samples entdecken

Die Samples, die Sonic Pi mitbringt, kannst Du auf zwei Arten entdecken. Erstens kannst Du dieses Hilfesystem benutzen. Klicke auf `Samples` im Menü auf der linken Seite, wähle eine Gruppe aus und lass Dir die Liste aller verfügbaren Klänge anzeigen.

Zweitens hilft Dir das Auto-Completion System. Tipp einfach den Anfang eines Gruppennamens von Samples ein, also: `sample :ambi_`. Nun klappt ein Menü auf, aus dem Du ein Sample auswählen kannst. Versuche einen der folgenden Anfänge von Gruppennamen:

- `:ambi_`
- `:bass_`
- `:elec_`
- `:perc_`
- `:guit_`
- `:drum_`
- `:misc_`
- `:bd_`

Jetzt leg los und mische Samples in Deine Komposition!

# 3.2 - Sample-Parameter: Amp und Pan

Genauso wie mit den Synths können wir auch unsere Sounds mit Parametern steuern. Der selbe Parameter-Mechanismus funktioniert auch mit Samples. Besuchen wir unsere Freunde `amp:` and `pan:` noch einmal.

## Die Amplitude von Samples verändern

Du kannst die Amplitude (Lautstärke) von Samples so steuern, wie Du es schon von den Synths kennst:

    sample :ambi_lunar_land, amp: 0.5

## Das Stereo-Feld von Samples verändern

Wir können auch den `pan:`-Parameter auf Samples anwenden. Hier zum Beispiel spielen wir den Amen-Break zunächst für das linke und nach der Hälfte für das rechte Ohr:

    sample :loop_amen, pan: -1
    sleep 0.877
    sample :loop_amen, pan: 1

0.877 ist genau die Hälfte der Dauer des Amen-Breaks in Sekunden.

Beachte: Samples berücksichtigen nicht die Grundeinstellungen für einen Synth, die Du mit `use_synth_defaults` setzen kannst (aber dazu kommen wir später noch).

# 3.3 - Samples dehnen

Jetzt können wir schon eine ganze Menge Synths und Samples spielen, um damit Musik zu machen. Es wird Zeit zu lernen, wie wir diese Synths und Samples verändern können. Das macht unsere Musik einzigartiger und spannender. Als erstes sehen wir uns an, wie wir Samples strecken und stauchen können.

## Wie Samples Klänge darstellen

Samples sind aufgenommene Klänge und werden als eine Zahlenreihe von Messwerten (deshalb “Sample”) gespeichert. Diese Zahlen sagen der Lautsprechermembran, wie sie sich bewegen muss, um den Klang wiederzugeben. Die Lautsprechermembran kann sich nach innen und nach außen bewegen und die Zahlen geben deshalb an, wie weit sich die Membran zu jedem Zeitpunkt nach innen oder außen bewegen soll. Um einen Klang als Aufnahme wirklichkeitsgetreu wiederzugeben, muss das Sample je Sekunde viele tausend Zahlen speichern. Sonic Pi nimmt diese Zahlenreihe und gibt sie in der richtigen Samplerate 1 an den Lautsprecher in Deinem Computer, so dass der Klang richtig wiedergegeben wird. Es macht aber auch Spaß, die Samplerate zu beeinflussen, denn das verändert den Klang.

## Die Samplerate ändern

Lass uns mit einem der Ambient-Klänge spielen: `ambi_choir`. Um diesen mit Standard-Samplerate wiederzugeben, kannst Du dem `sample` das Argument2 `rate:` übergeben:

    sample :ambi_choir, rate: 1

Das Sample wird unverändert mit der normalen Samplerate (1) abgespielt, also nichts Besonderes. Aber wir können die Zahl jederzeit verändern. Was passiert bei `0.5`?

    sample :ambi_choir, rate: 0.5

Wow! Was ist denn jetzt los? Also, hier passieren zwei Dinge. Erstens braucht das Sample doppelt so lange und zweitens klingt er eine Oktave niedriger. Sehen wir uns das mal genauer an.

## Lasst uns stretchen

Mit dem Amen-Break-Sample macht das strecken und zusammenstauchen besonders viel Spass. Mit der normalen Samplerate passt das Sample gut in einen Drum ‘n’ Bass-Track:

    sample :loop_amen

Wenn wir die Samplerate ändern, dann können wir die Stilrichtungen wechseln. Versuche es mal mit halber Samplerate für Hip-Hop der alten Schule:

    sample :loop_amen, rate: 0.5

Wenn wir es beschleunigen, betreten wir das Jungle-Territorium:

    sample :loop_amen, rate: 1.5

Und als letzten Trick - sehen wir mal, was passiert, wenn wir eine negative Rate angeben:

    sample :loop_amen, rate: -1

Boah! Er wird rückwärts gespielt! Jetzt probiere mit vielen unterschiedlichen Samples und unterschiedlichen Sampleraten herum. Versuch es mit sehr hohen oder mit verrückt langsamen. Finde heraus, welche spannenden Klänge Du damit produzieren kannst.

## Eine einfache Erklärung der Samplerate

Man kann sich Samples gut als Sprungfedern vorstellen. Wenn man die Samplerate verändert, ist das so, als ob man die Feder zusammendrückt oder auseinanderzieht. Wenn Du ein Sample mit der doppelten Samplerate abspielst, dann drückst Du die Feder zusammen, bis sie nur noch die Hälfte ihrer normalen Länge hat. Das Sample braucht also auch nur die Hälfte der Abspielzeit. Wenn Du das Sample mit halber Samplerate spielst, dann ziehst Du die Feder auf ihre doppelte Länge auseinander. Das Sample dauert also nun doppelt so lange. Je mehr Du zusammendrückst (höhere Rate), desto kürzer das Sample, je mehr Du auseinanderziehst (geringere Rate), desto länger dauert das Sample.

Wenn man eine Feder zusammendrückt, dann erhöht man ihre Dichtheit (die Anzahl der Windungen je Zentimeter) - das ist so ähnlich wie bei einem Sample, der höher klingt. Wenn man die Feder auseinanderzieht, dann verringert sich ihre Dichtheit, vergleichbar einem Klang, der tiefer klingt.

## Die Mathematik hinter der Samplerate

(Dieser Abschnitt ist für diejenigen, die es genauer wissen möchten. Wenn nicht, könnt Ihr den gerne überspringen…)

Wie wir oben gesehen haben, wird ein Sample durch eine lange Liste von Zahlen dargestellt, die der Lautsprechermembran sagen, wo sie zu welchem Zeitpunkt sein soll. Wir können diese Zahlenliste nehmen und eine Kurve zeichnen, die ungefähr so aussieht:

Vielleicht hast Du Bilder wie dieses schon einmal gesehen. Das ist die Kurvenform eines Sample. Es ist bloß eine Kurve, die aus Zahlen gebildet ist. Typischerweise wird eine solche Kurve aus 44100 Datenpunkten je Sekunde gebildet (das hat mit dem Nyquist-Shannon-Abtasttheorem zu tun). Wenn also das Sample 2 Sekunden dauert, dann wird die Kurve aus 88200 Zahlen gebildet, die wir an den Lautsprecher mit einer Datenrate von 44100 Datenpunkten pro Sekunde senden. Natürlich könnten wir es mit der doppelten Datenrate senden, also 88200 Datenpunkten pro Sekunde. Dann würde das Sample nur eine Sekunde lang dauern. Wir können es auch mit der halben Datenrate abspielen; das wären dann 22050 Datenpunkte pro Sekunde und würde 4 Sekunden dauern.

Die Dauer des Sample ist also abhängig von der Datenrate:

- Wird die Abtastrate verdoppelt, halbiert das die Abspielzeit,
- wird die Abtastrate halbiert, dann verdoppelt sich die Abspielzeit.
- Verwendest Du eine Abtastrate von einem Viertel, dann vervierfachst Du die Abspielzeit,
- verwendest Du eine Abtastrate von 1/10, dann dauert die Abspielzeit 10mal länger.

Wir können das in einer Formel zusammenfassen:

    neue_sample_dauer = (1 / rate) * sample_dauer

Eine Veränderung der Samplerate beeinflusst auch die Tonhöhen des Samples. Die Frequenz oder Tonhöhe einer Kurve wird dadurch bestimmt, wie schnell sie hoch und runter geht. Unsere Gehirne machen aus schnellen Bewegungen einer Lautsprechermembran hohe Töne und aus langsamen tiefe. Deshalb kannst Du manchmal sogar sehen, wie sich ein großer Basslautsprecher bewegt, wenn ein sehr tiefer Ton rauskommt. Er bewegt sich dann wesentlich langsamer als ein Lautsprecher, der hohe Töne wiedergibt.

Wenn Du eine Kurve nimmst und sie zusammendrückst, wird sie je Sekunde öfter hoch und runter gehen als vorher. Der Ton wird dann auch höher sein. Wenn man die Auf- und Abbewegungen je Sekunde verdoppelt (Oszillationen), dann wird die Frequenz, die Tonhöhe, verdoppelt. Also, wenn Du Dein Sample mit doppelter Samplerate abspielst, wird es auch doppelt so hoch klingen; andererseits: eine Halbierung der Samplerate wird auch die Frequenz halbieren. Andere Sampleraten werden dementsprechend die Tonhöhe beinflussen.

1. Die Samplerate heißt auch Samplingrate oder Abtastrate; rate steht für die Frequenz, mit der Sonic Pi die Zahlen, die im Sample den Klang darstellen, an die Lautsprechermembran sendet. ↩

2. Argument ist ein anderer Begriff für Parameter; an dieser Stelle bedeuten beide Begriffe dasselbe. ↩

# 3.4 - Enveloped Samples

Es ist auch möglich, die Dauer und Amplitude eines Sample mit einer ADSR-Hüllkurve zu verändern. Das funktioniert jedoch ein wenig anders als die ADSR-Hüllkurven bei den Synths. Mit Sample-Hüllkurven kannst Du die Amplitude und die Dauer eines Samples nur verringern - niemals vergrößern. Das Sample wird entweder stoppen, wenn seine normale Laufzeit vorbei ist, oder wenn die Hüllkurve das Sample begrenzt - je nachdem welche kürzer ist. Mit einem sehr langen `release` kannst Du ein Sample also nicht über seine normale Laufzeit hinaus verlängern.

## Amen-Hüllkuven

Kommen wir zu unserem treuen Freund zurück, dem Amen-Break:

    sample :loop_amen

Ohne Parameter hören wir das Sample in seiner gesamten Länge und mit voller Lautstärke. Mit dem `attack`-Parameter können wir das Sample einblenden lassen:

    sample :loop_amen, attack: 1

Wähle für eine kürzere Blende einen kürzeren Attack-Wert:

    sample :loop_amen, attack: 0.3

## Auto-Sustain

Beim Sustain-Wert unterscheidet sich das Verhalten einer ADSR-Hüllkuve. Bei der Hüllkurve für Standard-Synths steht der Sustain normalerweise auf 0 - außer Du setzt den Wert ausdrücklich. Bei Samples wird der Sustain-Wert auf einen automagical Wert gesetzt - nämlich die Zeit, die es braucht, bis das gesamte Sample abgelaufen ist. Darum hören wir das Sample komplett, wenn wir keine Default-Werte übergeben. Wenn die Werte für Attack, Decay, Sustain und Release alle 0 wären, würden wir keinen Pieps hören. Deshalb berechnet Sonic Pi zunächst, wie lange das Sample von sich aus dauert, zieht etwaige Dauern für Attack, Decay und Release davon ab und setzt die restliche Zeit als Sustain-Wert. Wenn die Werte von Attack, Decay und Release zusammengenommen länger dauern als das gesamte Sample, wird der Sustain-Wert einfach auf 0 gesetzt.

## Ausblenden

Um das auszuprobieren, schauen wir uns den Amen-Break genauer an. Wir fragen Sonic Pi, wie lang das Sample ist:

    print sample_duration :loop_amen

Es wird `1.753310657596372` ausgeben; das ist die Länge des Sample in Sekunden. Wir runden das einmal bequemerweise auf `1.75` ab. Wenn wir nun den Release-Wert auf `0.75` setzen, wird etwas erstaunliches passieren:

    sample :loop_amen, release: 0.75

Die erste Sekunde des Sample wird mit voller Lautstärke gespielt, danach wird über eine Periode von 0.75 Sekunden ausgeblendet. Das ist der Auto-Sustain in Aktion. Standardmäßig berechnet Sonic Pi den Release immer vom Ende des Samples aus. Wenn unser Sample 10.75 Sekunden lang wäre, würden die ersten 10 Sekunden in voller Lautstärke gespielt bevor dann eine Ausblende über 0.75 Sekunden erfolgt.

Zur Erinnerung: Standardmäßig blendet `release:` das Ende des Sample aus.

## Ein- und Ausblenden

Wir können `attack:` und `release:` zusammen mit Auto-Sustain nutzen, um über die Laufzeit des Sample ein- und auszublenden:

    sample :loop_amen, attack: 0.75, release: 0.75

Da die Gesamtdauer des Sample 1.75s beträgt und unsere Attack- und Release-Phasen zusammen 1.5s ergeben, erhält der Sustain automatisch den Wert 0.25s.

## Ausdrücklich angegebener Sustain

Wir können ohne weiteres das normales Synth-ADSR-Verhalten aktivieren, indem wir dem `sustain` den Wert 0 geben:

    sample :loop_amen, sustain: 0, release: 0.75

Jetzt spielt unser Sample insgesamt nur 0.75 Sekunden. Mit dem Standardwert 0 für `attack:` und `decay:` springt das Sample direkt auf die volle Lautstärke, bleibt dort für 0s und fällt dann innerhalb der Release-Phase mit einer Dauer von 0.75s auf den Lautstärkenwert 0 ab.

## Perkussive Becken

Wir können dieses Verhalten gut dazu benutzen, um länger klingende Samples in kürzere, perkussivere Versionen zu verwandeln. Sieh Dir das Sample `:drum_cymbal_open` an:

    sample :drum_cymbal_open

Man kann hören, wie das Becken eine Zeit lang ausklingt. Mit ein paar kleinen Änderungen an der Hüllkurve klingt es perkussiver:

    sample :drum_cymbal_open, attack: 0.01, sustain: 0, release: 0.1

Indem Du die Sustain-Dauer verlängerst, kannst Du es so klingen lassen, als ob das Becken erst angeschlagen und dann abgedämpft würde:

    sample :drum_cymbal_open, attack: 0.01, sustain: 0.3, release: 0.1

Jetzt versuch einmal, Hüllkuven über Samples zu legen. Verändere auch die Samplerate; damit kannst Du sehr interessante Ergebnisse erzielen.

# 3.5 - Teil-Samples

Dieses Kapitel schließt unsere Erkundung von Sonic Pi’s Sample-Player ab. Fassen wir noch einmal zusammen. Wir haben uns angesehen, wie wir Samples abspielen können:

    sample :loop_amen

Dann haben wir gesehen, dass wir die Samplerate ändern können - etwa um ein Sample mit halber Geschwindigkeit abzuspielen:

    sample :loop_amen, rate: 0.5

Als nächstes haben wir einen Blick darauf geworfen, wie wir ein Sample ein- und ausblenden lassen (hier zum Beispiel mit halber Geschwindigkeit):

    sample :loop_amen, rate: 0.5, attack: 1

Wir haben uns auch angeschaut, wie wir ein Sample am Anfang perkussiver klingen lassen können, indem wir `sustain:` ausdrücklich einen Wert zuweisen, und sowohl der Attack als auch der Release kurze Werte bekommen:

    sample :loop_amen, rate: 2, attack: 0.01, sustain: 0, release: 0.35

Wäre es aber nicht toll, wenn wir ein Sample nicht immer vom Anfang starten lassen müssten? Wäre es nicht auch prima, wenn das Ende des klingenden Sample nicht immer seinem wirklichen Ende entsprechen müsste?

## Einen Startpunkt bestimmen

Es ist möglich, einen beliebigen Startpunkt eines Sample als Wert zwischen 0 und auszuwählen, wobei 0 der Anfang, 1 das Ende und 0.5 die Mitte des Samples darstellt. Spielen wir die zweite Hälfte des Amen Break:

    sample :loop_amen, start: 0.5

Oder vielleicht das letzte Viertel des Sample:

    sample :loop_amen, start: 0.75

## Einen Endpunkt bestimmen

Gleichermaßen können wir über einen Wert zwischen 0 und 1 einen beliebigen Endpunkt im Sample festlegen. Beenden wir den Amen-Break nach der ersten Hälfte:

    sample :loop_amen, finish: 0.5

## Start- und Endpunkt bestimmen

Natürlich können das auch kombinieren und einen beliebigen Abschnitt des Sample abspielen. Wie wäre es mit einem kurzen Abschnitt aus der Mitte:

    sample :loop_amen, start: 0.4, finish: 0.6

Was passiert, wenn wir eine Startposition nach der Endposition auswählen?

    sample :loop_amen, start: 0.6, finish: 0.4

Cool! Dann spielt es rückwärts!

## In Kombination mit der Samplerate

Diese neue Fähigkeit, beliebige Abschnitte eines Klangs zu spielen, lässt sich mit unserem Freund `rate:` kombinieren. Zum Beispiel können wir einen sehr kurzen Abschnitt des Amen-Breaks sehr langsam spielen:

    sample :loop_amen, start: 0.5, finish: 0.7, rate: 0.2

## In Kombination mit Hüllkurven

Schließlich können wir all dies mit unseren ADSR-Hüllkurven kombinieren und interessante Ergebnisse damit erzielen:

    sample :loop_amen, start: 0.5, finish: 0.8, rate: -0.2, attack: 0.3, release: 1

Jetzt leg los und hab Spaß, Samples mit diesem Zeug aufzumischen…

# 3.6 - Samples aus externen Quellen

Mit den mitgelieferten Samples kannst Du schnell einsteigen, aber vielleicht möchtest Du mit neuen aufgenommenen Klängen in Deiner Musik experimentieren. Sonic Pi unterstützt das ausdrücklich. Lass uns aber zunächst über die Übertragbarkeit Deines Stücks sprechen.

## Übertragbarkeit

Wenn Du Dein Stück nur mit Hilfe der eingebauten Synths und Samples komponierst, braucht man nur den Code, um Deine Musik so abzuspielen, wie Du sie geschrieben hast. Denk darüber einen Augenblick nach - das ist erstaunlich! Ein bisschen Text, den Du per Email verschicken oder auf Gist ablegen kannst, reicht vollkommen aus, um Deine Klänge wieder abzuspielen. So wird es sehr einfach, Deine Kompositionen mit Deinen Freunden zu teilen. Sie brauchen nur ein wenig Code von Dir.

Wenn Du nun selbst aufgenommene Samples verwendest, verlierst Du diese Übertragbarkeit. Und zwar deshalb, weil man zum Abspielen auf einem anderen Rechner nicht nur den Code braucht, sondern auch Deine Samples.

## Lokale Samples

Wie geht das nun, eine beliebige WAV- oder AIFF-Datei auf Deinem Computer zu spielen? Dafür musst Du dem Ausdruck `sample` nur den Pfad der Datei übergeben:

    # Raspberry Pi, Mac, Linux
    sample "/Users/sam/Desktop/my-sound.wav"
    # Windows
    sample "C:/Users/sam/Desktop/my-sound.wav"

Sonic Pi wird das Sample nun automatisch laden und spielen. Alle anderen Standard-Parameter, die Du schon kennengelernt hast, kannst Du jetzt auch für Dein eigenes Sample einsetzen:

    # Raspberry Pi, Mac, Linux
    sample "/Users/sam/Desktop/my-sound.wav", rate: 0.5, amp: 0.3
    # Windows
    sample "C:/Users/sam/Desktop/my-sound.wav", rate: 0.5, amp: 0.3

# 4 - Randomisierung1

Zufallszahlen sind eine tolle Möglichkeit, Deine Musik interessant zu gestalten. Sonic Pi bietet einige Funktionen, um Zufallsfaktoren in Deine Musik einzubauen. Aber bevor wir starten, müssen wir noch einer schockierenden Wahrheit ins Gesicht sehen: In Sonic Pi bedeutet zufällig nicht wirklich zufällig. Was zum Teufel soll das bedeuten? Nun, das verrate ich Dir jetzt.

## Wiederholbarkeit

Eine wirklich nützliche Zufallsfunktion ist `rrand`. Sie liefert Dir einen zufälligen Wert zwischen zwei Zahlen - einem Minimal- und einem Maximalwert. (`rrand` ist ein Kürzel für das englische ranged random, also eine Zufallszahl innerhalb eines bestimmten Wertebereichs).

    play rrand(50, 95)

Oh, eine zufällige Note wird gespielt. Es war die Note `83.7527`. Eine nette Note zwischen 50 und 100. Aber hallo, habe ich gerade diese angeblich zufällige Note exakt vorhergesagt? Da ist doch etwas nicht ganz astrein. Lasse den Code noch einmal ablaufen. Wieder `83.7527`, oder? Das kann doch kein Zufall sein!

Die Antwort ist, es ist nicht wirklich zufällig, sondern pseudo-zufällig. Sonic Pi liefert Dir Reihenfolgen von Zufallszahlen, die wiederholbar sind. Das ist sehr nützlich, denn so ist sichergestellt, dass die Musik von Deinem Rechner auf anderen Rechnern identisch klingt - sogar dann, wenn Du einen Zufallsfaktor einbaust.

Klar, wenn in einem bestimmten Musikstück jedesmal die `83.7527` als ‘zufällige’ Zahl gewählt würde, dann wäre das nicht besonders interessant. Aber so ist es auch nicht. Versuch folgendes:

    loop do
      play rrand(50, 95)
      sleep 0.5
    end

Jawohl! Nun klingt es zufällig. Innerhalb eines bestimmten Code-Durchgangs liefern Aufrufe von Zufallsfunktionen auch zufällige Werte. Der nächste Durchgang wird jedoch genau die selbe Folge von Zufallswerten liefern und also auch genau gleich klingen. Es ist, als ob der Code immer zu demselben Zeitpunkt zurückspringt, wenn der Ausführen-Button geklickt wird. Es ist der Groundhog-Day2 der musikalischen Synthese.

## Ruhelose Glocken

Ein großartiges Beispiel von Zufall in Aktion bietet der “Haunted Bells”-Code. Die “ruhelosen Glocken” spielen das Sample `:perc_bell` mit einer zufälligen Samplerate und Pausenzeit in einer Endlosschleife3 ab:

    loop do
      sample :perc_bell, rate: (rrand 0.125, 1.5)
      sleep rrand(0.2, 2)
    end

## Zufällig abschneiden (random cutoff)

Ein anderes spannendes Beispiel für die Randomisierung ist das zufällige Abschneiden hoher Töne4 eines Synth-Klangs. Der `:tb303`-Emulator ist ein guter Synth, um das auszuprobieren:

    use_synth :tb303

    loop do
      play 50, release: 0.1, cutoff: rrand(60, 120)
      sleep 0.125
    end

## Startpunkt der Zufallsfolge (random seed)

Was aber, wenn Du die Abfolge von Zufallszahlen, die Sonic Pi Dir liefert, nicht magst? Nun, mit `use_random_seed`5 kannst Du unterschiedliche Startpunkte für diese Folge angeben. Der Standard-Startpunkt ist die 0. Wähle also einfach einen anderen Startpunkt und mache eine andere Zufallserfahrung!

Sieh Dir den folgenden Code an:

    5.times do
      play rrand(50, 100)
      sleep 0.5
    end

Jedes Mal, wenn Du den Code ablaufen läßt, hörst Du dieselbe Folge von 5 Tönen. Um eine andere Folge zu bekommen, setze einfach einen anderen Startpunkt:

    use_random_seed 40
    5.times do
      play rrand(50, 100)
      sleep 0.5
    end

Nun produziert Sonic Pi eine andere Folge von 5 Tönen. Indem Du den Startpunkt wechselst und Dir die Ergebnisse anhörst, kannst Du eine Folge finden, die Dir gefällt - und wenn Du den Code dann an andere weitergibst, werden sie genau das hören, was auch Du gehört hast.

Schauen wir uns noch eine andere nützliche Zufallsfunktion an.

## Auswählen (choose)

Häufig kommt es vor, dass man aus einer Liste von Dingen eines zufällig auswählen möchte. Zum Beispiel möchte ich einen Ton aus der folgenden Liste auswählen: 60, 65 oder 72. Dafür ist `choose` da. Zuerst musst Du Deine Zahlen in eine Liste packen. Dafür schreibst Du sie jeweils durch Kommata getrennt in eckige Klammern. Dann übergibst Du diese Liste dem Kommando `choose`:

    choose([60, 65, 72])

Hören wir uns das an:

    loop do
      play choose([60, 65, 72])
      sleep 1
    end

## rrand

`rrand` haben wir schon kennengelernt, aber sehen wir uns das noch einmal genauer an. Es liefert eine zufällige Zahl zwischen zwei Werten, aber ohne diese Werte selbst; man sagt auch exklusiv dieser beiden Werte. Das bedeutet, dass sowohl der minimale als auch der maximale Wert niemals ausgegeben werden, immer nur eine Zahl zwischen diesen beiden Werten. Die Zahl wird immer eine Gleitkommazahl (engl. Float) sein, also keine ganze Zahl, sondern eine mit einem Komma6. Einige Beispiele für Gleitkommazahlen, die der wiederholte Aufruf von `rrand(20, 110)` ausgeben könnte:

- 87.5054931640625
- 86.05255126953125
- 61.77825927734375

## rrand_i

Manchmal braucht man eine zufällige, aber ganze Zahl, eben keine Gleitkommazahl. Hier rettet einen `rrand_i`7. Es funktioniert ähnlich `rrand`, kann jedoch auch den minimalen oder maximalen Wert, den man übergeben hat, als mögliche Zufallszahl auswählen (man kann auch sagen: es ist inklusiv, also nicht exklusive der Werte, mit denen man den Bereich für die Auswahl festgelegt hat). `rrand_i(20, 110)` könnte zum Beispiel die folgenden Werte ausgeben:

- 88
- 86
- 62

## rand

`rand` gibt eine zufällige Gleitkommazahl zwischen 0 (inklusiv) und einem übergebenen Maximalwert (exklusiv) zurück. Standardmäßig - wenn also kein Maximalwert angegeben wird - wird ein Wert zwischen 0 und 1 geliefert. Deshalb kann man `rand` gut dafür gebrauchen, zufällige Werte für `amp:` (also die Lautstärke) auszuwählen.

    loop do
      play 60, amp: rand
      sleep 0.25
    end

## rand_i

Ähnlich wie bei `rrand_i` und `rrand`, wählt `rand_i` eine zufällige ganze Zahl zwischen 0 und einem angegebenen Maximalwert aus.

## dice

Manchmal möchte man so tun, als würde man würfeln (engl. to dice) - das ist ein Sonderfall von `rrand_i`, wobei der kleinste Wert immer die 1 ist. Wenn man `dice` verwendet, muss man dabei immer bestimmen, wie viele Seiten der Würfel hat. Ein normaler Würfel hat 6 Seiten, also wird `dice(6)` entsprechend funktionieren und den Wert 1, 2, 3, 4, 5 oder 6 zurückgeben. Aber - angenommen wir befänden uns in einen Fantasy-Rollenspiel - ist es Dir vielleicht lieber, wenn der Würfel 4 oder 12, 20 oder sogar 120 Seiten hat!?

## one_in

Schließlich könnte es sein, das Du so tun willst, als ob Du beim Würfeln eine 6 hast - also den höchten Wert erreichst. `one_in` gibt - mit einer Wahrscheinlichkeit 1 im Verhältnis zur Menge der Würfelseiten - den Wert wahr (engl. true) zurück, falls die höchste Zahl gewürfelt wurde. `one_in(6)` wird also mit einer Wahrscheinlichkeit von 1 zu 6 wahr, ansonsten falsch (engl. false). Wahr- und Falsch-Werte sind sehr nützlich, wenn es um `if`-Anweisungen geht, die wir in einem folgenden Kapitel dieses Tutorials besprechen.

Jetzt los, bring Deinen Code mit ein paar Zufälligkeiten durcheinander!

1. Randomisierung (engl. Randomisation) bedeutet hier, dass man eine Auswahl von Zahlen zufällig gestaltet, also jedesmal eine andere Zahl bekommt. ↩

2. Im Film Groundhog Day (deutsch: Und täglich grüßt das Murmeltier) erlebt Bill Murray immer wieder denselben Tag. ↩

3. Ein Schleife wird mit dem Ausdruck `loop` eingeleitet. Alles was innerhalb der Schleife steht, wird so oft wie angegeben oder unendlich oft wiederholt. ↩

4. In Sonic Pi wird das Abschneiden oder Verkürzen hoher Töne (Filtern) mit dem Ausdruck `cutoff` bezeichnet. ↩

5. Das englische Wort Seed bedeutet im Deutschen Keim oder Samen; hier wird es als Startpunkt übersetzt. ↩

6. Die Sache wird noch dadurch ein wenig komplizierter, dass im Englischen anstelle eines Kommas ein Punkt steht. Die Gleitkommazahl `5,978` ist also im Englischen die Floating Point Number (kurz: Float) `5.978`. Alle Zahlen mit Kommawerten werden also in Sonic Pi mit einem Punkt dargestellt. ↩

7. Das kleine i in `rrand_i` steht für englisch Integer als eine ganze Zahl im Unterschied zu den Gleitkommazahlen. ↩

# 5 - Programmstrukturen

Jetzt kennst Du schon die wichtigsten Grundlagen. Du weißt, wie man Klänge mit `play` und `sample` erzeugt, und kannst einfache Melodien und Rhythmen bauen, indem Du `sleep` zwischen die Klänge setzt. Du fragst Dich nun vielleicht, was Dir die Welt des Codes noch alles zu bieten hat…

Ich denke, da kommen noch einige tolle Sachen auf Dich zu! Du wirst sehen, dass grundlegende Programmstrukturen wie Schleifen, Bedingungen, Funktionen und Threads großartige Werkzeuge sind, wenn Du Deine musikalischen Ideen ausdrücken willst.

Sehen wir uns also die Grundlagen an…

# 5.1 - Blocks

Eine Struktur, die man häufig in Sonic Pi sieht, ist der Block. Blocks erlauben uns, nützliche Dinge mit größeren Codeabschnitten zu tun. Mit Synth- oder Sample-Parametern konnten wir etwas ändern, was in einer Codezeile geschah. Manchmal aber möchten wir etwas mit einer ganzen Reihe von Codezeilen anstellen. Zum Beispiel möchten wir diese in einer Schleife ablaufen lassen, Hall hinzufügen, bei vorgegebenen Wiederholungen nur eine von fünf ablaufen lassen etc. Schau Dir den folgenden Code an:

    play 50
    sleep 0.5
    sample :elec_plip
    sleep 0.5
    play 62

Um etwas mit einem mehrzeiligen Codestück zu tun, müssen wir Sonic Pi sagen, wo der Code-Block anfängt, und wo er aufhört. Dazu verwenden wir `do` für den Anfang und `end` für das Ende. So zum Beispiel:

    do
      play 50
      sleep 0.5
      sample :elec_plip
      sleep 0.5
      play 62
    end

Das ist aber noch nicht alles und wird so nicht funktionieren (versuche es und Du wirst einen Fehler erhalten), weil wir Sonic Pi noch nicht gesagt haben, was wir mit diesem do/end-Block machen wollen. Dafür setzen wir noch einen speziellen Ausdruck vor das `do`. Solche Ausdrücke werden wir in diesem Tutorial gleich kennenlernen. Zunächst einmal ist wichtig, dass wir mehrere Codezeilen mit `do` und `end` zusammenfassen und Sonic Pi sagen können, dass wir mit diesem Codestück etwas Bestimmtes machen wollen.

# 5.2 - Iteration und Schleifen

Bislang haben wir einige Zeit damit verbracht, uns unterschiedliche Klänge anzusehen, die Du mit `play` und `sample` erzeugen kannst. Wir haben auch gelernt, wie Du den Ablauf dieser Klänge mit `sleep` steuern kannst.

Wahrscheinlich hast Du entdeckt, dass man mit diesen Grundbausteinen schon vieles bauen kann. Eine ganz neue Dimension eröffnet sich jedoch, wenn wir beginnen, die Musik und die Kompositionen über den Code weitergehend zu strukturieren. In den nächsten Abschnitten schauen wir einige wirkungsvolle neue Werkzeuge dafür an. Als erstes kommen die Iteration und die Schleife (engl. Loop) dran.

## Wiederholung

Möchtest Du Code, den Du geschrieben hast, einige Male wiederholen? Zum Beispiel hast Du vielleicht ungefähr so etwas:

    play 50
    sleep 0.5
    sample :elec_blup
    sleep 0.5
    play 62
    sleep 0.25

Was, wenn Du das drei Mal wiederholen wolltest? Naja, die Lösung ist einfach! Du kannst den Code kopieren und drei Mal hintereinander einfügen:

    play 50
    sleep 0.5
    sample :elec_blup
    sleep 0.5
    play 62
    sleep 0.25

    play 50
    sleep 0.5
    sample :elec_blup
    sleep 0.5
    play 62
    sleep 0.25

    play 50
    sleep 0.5
    sample :elec_blup
    sleep 0.5
    play 62
    sleep 0.25

Das ist natürlich eine Menge Code! Was wäre, wenn Du das Sample in `:elec_plip` umändern wolltest? Du müsstest alle Stellen mit `:elec_blub` finden und ändern. Und weiter: Was, wenn Du das ursprüngliche Codestück 50 oder 1000 Mal wiederholen wolltest? Das wäre noch mehr Code, und Du müsstest eine Menge Zeilen bearbeiten, wenn Du etwas ändern wolltest.

## Iteration

Wenn man Code wiederholt ablaufen lassen wollte, müsste man eigentlich nur sagen: Mach das drei Mal. Und so ist es auch in etwa. Erinnerst Du Dich an unseren Freund, den Code-Block? Wir können damit den Anfang und das Ende des Codes markieren, den wir drei Mal wiederholen wollen. Dann benutzen wir den speziellen Ausdruck `3.times`. Wir schreiben zwar nicht mach das drei Mal, wir schreiben `3.times do` - also nicht besonders schwierig. Denk aber daran, ans Ende des zu wiederholenden Code-Blocks gehört ein `end`.

    3.times do
      play 50
      sleep 0.5
      sample :elec_blup
      sleep 0.5
      play 62
      sleep 0.25
    end

Na, ist das nicht viel eleganter als kopieren und einfügen? Wir können das gut gebrauchen, um eine Menge sich wiederholender Strukturen zu erzeugen.

    4.times do
      play 50
      sleep 0.5
    end

    8.times do
      play 55, release: 0.2
      sleep 0.25
    end

    4.times do
      play 50
      sleep 0.5
    end

## Verschachtelte Iterationen

Wir können Iterationen in andere Iterationen hinein packen, um damit interessante Muster zu erzeugen. Zum Beispiel:

    4.times do
      sample :drum_heavy_kick
      2.times do
        sample :elec_blip2, rate: 2
        sleep 0.25
      end
      sample :elec_snare
      4.times do
        sample :drum_tom_mid_soft
        sleep 0.125
      end
    end

## Schleifen

Wenn Du etwas sehr oft wiederholen möchtest, könnte es sein, dass Du mit sehr hohen Zahlen arbeiten musst, wie zum Beispiel `1000.times do`. In einem solchen Fall macht es mehr Sinn, Sonic Pi dazu zu bringen, den Code in einer Endlos-Schleife zu wiederholen (zumindest, bis Du den Stopp-Button klickst!). Wiederholen wir den Amen Break unendlich oft:

    loop do
      sample :loop_amen
      sleep sample_duration :loop_amen
    end

Eine wichtige Sache bei Endlos-Schleifen ist, dass sie für den Code wie schwarze Löcher sind. Wenn der Code einmal in einer Endlos-Schleife läuft, kann er diese nicht mehr verlassen, bis Du auf Stopp klickst - ansonsten wird er für immer weiterlaufen. Das bedeutet, wenn hinter Deiner Endlos-Schleife noch weiterer Code steht, wirst Du diesen nie hören. Zum Beispiel wird das Becken hinter dieser Schleife nie spielen:

    loop do
      play 50
      sleep 1
    end

    sample :drum_cymbal_open

Jetzt fang an und strukturiere Deinen Code mit Wiederholungen und Schleifen!

# 5.3 - Bedingungen

Wahrscheinlich willst Du häufig nicht nur einen einen zufälligen Ton abspielen (siehe das Kapitel über Zufallszahlen), sondern auch eine zufällige Entscheidung treffen: je nachdem wie diese ausfällt, möchtest Du dann den einen oder anderen Code ausführen. Zum Beispiel könnte es sein, dass Du zufällig entweder eine Trommel oder ein Becken anschlagen möchtest. Das können wir mit einem `if`-Ausdruck erreichen.

## Wirf eine Münze

Werfen wir also ein Münze: bei Kopf, spiele eine Trommel, bei Zahl, ein Becken. Das ist leicht. Wir können den Münzwurf mit unserer `one_in`-Funktion nachbilden (eingeführt im Kapitel über Randomisierung), indem wir eine Wahrscheinlichkeit von 1 aus 2 angeben: `one_in(2)`. Das Ergebnis dieser Berechnung benutzen wir, um zwischen zwei Codestücken auszuwählen, entweder den Code für die Trommel oder für das Becken:

    loop do

      if one_in(2)
        sample :drum_heavy_kick
      else
        sample :drum_cymbal_closed
      end

      sleep 0.5

    end

Denke daran, dass `if`-Anweisungen drei Teile haben:

- die Frage, die gestellt wird,
- die erste Wahl des Codes, der ablaufen soll (wenn die Antwort auf die Frage ein Ja ist),
- die zweite Wahl des Codes, der ablaufen soll (wenn die Antwort auf die Frage ein Nein ist).

Für Programmiersprachen typisch steht für das Ja der Ausdruck `true` (wahr) und für das Nein der Ausdruck `false` (falsch). Also müssen wir eine Frage finden, die uns eine Antwort gibt, die entweder wahr oder falsch ist; genau das erledigt im Beispiel `one_in`.

Beachte, dass die erste Wahl zwischen `if` und `else` und die zweite Wahl zwischen `else` und `end` eingeschlossen wird. So wie bei den do/end-Blöcken kannst Du beliebig viele Codezeilen an beide Stellen schreiben. Zum Beispiel:

    loop do

      if one_in(2)
        sample :drum_heavy_kick
        sleep 0.5
      else
        sample :drum_cymbal_closed
        sleep 0.25
      end

    end

Dieses Mal schläft der Klang unterschiedlich lange, je nachdem, welche Auswahl getroffen wird.

## Einfaches if

Manchmal möchtest Du wahlweise nur eine Codezeile ausführen. Dafür hängst Du ein `if` und die Frage an das Ende der Codezeile, zum Beispiel:

    use_synth :dsaw

    loop do
      play 50, amp: 0.3, release: 2
      play 53, amp: 0.3, release: 2 if one_in(2)
      play 57, amp: 0.3, release: 2 if one_in(3)
      play 60, amp: 0.3, release: 2 if one_in(4)
      sleep 1.5
    end

Dieses Beispiel setzt einen Akkord aus verschiedenen Noten zusammen, wobei die Chance, dass bestimmte Noten gespielt werden, eine unterschiedliche Wahrscheinlichkeit hat.

# 5.4 - Threads1

Mal angenommen, Du hast eine Killer-Basslinie und einen krassen Beat gebaut. Wie kannst Du beides zur selben Zeit spielen lassen? Eine Möglichkeit ist es, beide Sounds per Hand ineinander zu weben - erst spielt der Bass ein bisschen, dann das Schlagzeug, dann der Bass etwas mehr… Beides aufeinander zeitlich abzustimmen wird jedoch immer schwieriger, vor allem, wenn noch mehr Sounds dazukommen sollen.

Was, wenn Sonic Pi Sounds automatisch für Dich ineinanderflechten könnte? Kann es auch, und zwar mit einem besonderen Ding, welches Thread heisst.

## Unendliche Schleifen

Damit das nächste Beispiel nicht zu kompliziert wird, musst Du Dir einfach vorstellen, dass dies Deine Killer-Basslinie und Dein krasser Beat sind.

    loop do
      sample :drum_heavy_kick
      sleep 1
    end

    loop do
      use_synth :fm
      play 40, release: 0.2
      sleep 0.5
    end

Wir haben das früher schon besprochen, Endlos-Schleifen sind wie schwarze Löcher für ein Programm; läuft es einmal in die Schleife kommt es da nicht mehr raus, bis Du den `Stopp`-Button klickst. Wie also können wir beide Schleifen zur selben Zeit abspielen? Wir müssen Sonic Pi sagen, dass wir einen bestimmten Abschnitt gleichzeitig mit dem Rest des Codes starten möchten. Hierbei helfen uns Threads.

## Threads kommen zur Hilfe

Wenn wir die erste Schleife in einen `in_thread`-do/end-Block hineinpacken, sagen wir Sonic Pi, es soll den Inhalt dieses do/end-Blocks genau zur selben Zeit wie die nachfolgende Anweisung ausführen. Und das ist in diesem Fall die zweite Schleife. Probier es aus, und Du wirst den Beat zusammen mit der Basslinie hören!

    in_thread do
      loop do
        sample :drum_heavy_kick
        sleep 1
      end
    end

    loop do
      use_synth :fm
      play 40, release: 0.2
      sleep 0.5
    end

Angenommen, dass wir obendrauf noch einen Synth legen wollten. Ungefähr so:

    in_thread do
      loop do
        sample :drum_heavy_kick
        sleep 1
      end
    end

    loop do
      use_synth :fm
      play 40, release: 0.2
      sleep 0.5
    end

    loop do
      use_synth :zawa
      play 52, release: 2.5, phase: 2, amp: 0.5
      sleep 2
    end

Jetzt haben wir das gleiche Problem wir vorhin. Die erste Schleife wird durch das `in_thread` zur selben Zeit wie die zweite gespielt. Aber die dritte Schleife wird nie erreicht. Also brauchen wir einen weiteren Thread:

    in_thread do
      loop do
        sample :drum_heavy_kick
        sleep 1
      end
    end

    in_thread do
      loop do
        use_synth :fm
        play 40, release: 0.2
        sleep 0.5
      end
    end

    loop do
      use_synth :zawa
      play 52, release: 2.5, phase: 2, amp: 0.5
      sleep 2
    end

## Ablauf in Threads

Was Dich vielleicht erstaunt: Wenn Du den Ausführen-Button klickst, erzeugst Du tatsächlich einen neuen Thread, innerhalb dessen der Code abläuft. Deshalb entstehen immer neue Soundschichten, wenn Du den Ausführen-Button wiederholt klickst. Weil die Abläufe Threads sind, werden sie automatisch die Sounds verflechten.

## Geltungsbereich2

Wenn Du Dich besser mit Sonic Pi auskennst, wirst Du herausfinden, dass Threads die wichtigsten Bausteine für Deine Musik sind. Eine wesentliche Funktion, die Threads haben, ist es, aktuelle Einstellungen, die für einen Thread gelten, von anderen Threads zu isolieren. Was genau bedeutet das? Wenn Du etwa einen Synths mit `use_synth` durch einen anderen austauschst, dann veränderst Du den Synth lediglich für den aktuellen Thread - kein anderer der laufenden Threads bekommt den neuen Synth. Sehen wir uns das mal in der Praxis an:

    play 50
    sleep 1

    in_thread do
      use_synth :tb303
      play 50
    end

    sleep 1
    play 50

Hast Du gehört, dass sich der mittlere Klang von den anderen beiden unterschieden hat? Die `use_synth`-Anweisung hat sich nur auf den Thread ausgewirkt, in dem sie auch stand und nicht auf den äußeren Haupt-Thread.

## Vererbung

Wenn Du einen neuen Thread mit `in_thread` erzeugst, wird dieser vom vorherigen alle Einstellungen automatisch erben. Sehen wir uns das an:

    use_synth :tb303
    play 50
    sleep 1

    in_thread do
      play 55
    end

Hast Du bemerkt, dass der zweite Ton mit dem `:tb303`-Synth gespielt wird, obwohl er in einem anderen Thread läuft? Jede der Einstellungen, die mit den unterschiedlichen `use_*`-Ausdrücken vorgenommen wird, verhält sich genauso.

Wenn neue Threads starten, erben sie alle Einstellungen von ihren Eltern. Wenn Du aber Einstellungen innerhalb dieser neuen Threads änderst, haben diese keine Einfluss auf die Eltern-Threads.

## Threads benennen

Schließlich kannst Du Deinen Treads Namen geben.

    in_thread(name: :bass) do
      loop do
        use_synth :prophet
        play chord(:e2, :m7).choose, release: 0.6
        sleep 0.5
      end
    end

    in_thread(name: :drums) do
      loop do
        sample :elec_snare
        sleep 1
      end
    end

Sieh Dir das Protokoll-Fenster an, wenn Du diesen Code laufen lässt. Siehst Du, wie die Namen der Threads ausgeben werden?

    [Run 36, Time 4.0, Thread :bass]
     |- synth :prophet, {release: 0.6, note: 47}

## Nur ein Name pro Thread erlaubt

Eine letzte Anmerkungen zu Threads mit Namen: Ein mit einem bestimmten Namen benannter Thread kann zur Zeit nur einmal laufen. Probieren wir das aus. Sieh Dir den folgenden Code an:

    in_thread do
      loop do
        sample :loop_amen
        sleep sample_duration :loop_amen
      end
    end

Kopiere das einmal in einen Buffer und klicke den `Ausführen`-Button. Klick in noch ein paarmal. Hör Dir diese Kakophonie mehrerer Amen Breaks an, die ryhtmisch nicht unbedingt passend zueinander ablaufen. Ok, jetzt kannst Du auf `Stopp` klicken.

Dieses Verhalten konnten wir schon woanders sehen - wenn Du den `Ausführen`-Button klickst, legen sich die neuen Klänge über die schon laufenden. Wenn eine Schleife abläuft, und Du den `Ausführen`-Button dreimal klickst, bekommst Du drei Ebenen mit Schleifen, die gleichzeitig ablaufen.

Mit benannten Threads ist das jedoch anders:

    in_thread(name: :amen) do
      loop do
        sample :loop_amen
        sleep sample_duration :loop_amen
      end
    end

Versuche mit diesem Code den `Ausführen`-Button mehrmals zu klicken. Du wirst immer nur eine Amen-Break-Schleife hören. Das kannst Du auch im Protokoll sehen:

    ==> Skipping thread creation: thread with name :amen already exists.

Sonic Pi sagt Dir, dass ein Thread mit dem Namen `:amen` bereits läuft und es deshalb keinen neuen startet.

Vielleicht erscheint Dir dieses Verhalten im Moment noch nicht sinnvoll - aber es wird sehr nützlich sein, wenn wir ins Live-Coding einsteigen…

1. Im Deutschen bedeutet thread Kette, Faden oder Strang. Der Thread ist jedoch für Programmiersprachen eine so typische Idee, dass eine Übersetzung nur insoweit sinnvoll ist, dass Du Dir die Idee, die hinter diesem Begriff steht, besser merken kannst. Weil niemand beim Programmieren über eine Kette oder einen Faden spricht, werden wir hier nur den englischen Begriff benutzen. ↩

2. Scope bedeutet ins Deutsche übersetzt soviel wie Geltungsbereich. Für die Zukunft ist es aber ganz gut, sich den englischen Begriff zu merken, da auch dieser im Programmierbereich häufig vorkommt. ↩

# 5.5 - Funktionen

Wenn Du einmal damit angefangen hast, mehr Code zu schreiben, dann wirst Du nach Wegen suchen, wie Du die Dinge organisieren und strukturieren kannst. Damit wird alles ordentlicher und einfacher zu verstehen. Funktionen sind sehr praktisch, um das zu erreichen. Sie geben uns die Möglichkeit, einem Bündel von Codezeilen einen Namen zu geben. Sehen wir uns das an.

## Funktionen definieren

    define :foo do
      play 50
      sleep 1
      play 55
      sleep 2
    end

Hier haben wir eine neue Funktion mit dem Namen `foo` definiert. Wir machen das mit unserem alten Freund, dem do/end-Block und dem Zauberwort `define` gefolgt von dem Namen, den wir unserer Funktion geben möchten. Wir müssen die Funktion nicht unbedingt `foo` nennen, wir können sie auch irgendwie anders nennen; zum Beispiel `bar`, `baz` oder idealerweise einen für Dich bedeutsamen Namen wie `main_section` (etwa: Hauptteil) oder `lead_riff` (etwa: Leitfigur).

Denk daran, bei der Definition einer Funktion einen Doppelpunkt `:` vor ihren Namen zu stellen.

## Funktionen aufrufen

Wenn wir unsere Funktion definiert haben, können wir sie einfach über ihren Namen aufrufen:

    define :foo do
      play 50
      sleep 1
      play 55
      sleep 0.5
    end

    foo

    sleep 1

    2.times do
      foo
    end

Wir können `foo` sogar in Iterations-Blocks aufrufen und überall da, wo wir auch `play` oder `sample` hätten benutzen können. Das gibt uns eine große Ausdrucksfreiheit und wir können sinnvolle Worte bilden, die wir in unseren Kompositionen verwenden.

## Funktionen bleiben in Erinnerung

Wenn Du bislang den `Ausführen`-Button geklickt hast, startete Sonic Pi jedesmal aufs Neue ohne irgendwelche Vorgaben. Es berücksichtigt nichts, außer dem, was im jeweiligen Buffer steht. Du kannst Dich nicht auf irgendwelchen Code beziehen, der in einem anderen Buffer oder einem anderen Thread steht. Funktionen ändern das jedoch. Wenn Du eine Funktion definierst, dann erinnert sich Sonic Pi daran. Probieren wir das aus. Ersetze den den gesamten Code in Deinem Buffer durch:

    foo

Klick den `Ausführen`-Button und höre, wie Deine Funktion spielt. Wo wurde dieser Code gespeichert? Woher weiss Sonic Pi, was es zu spielen hat? Sonic Pi hat sich Deine Funktion einfach gemerkt. Also sogar, nachdem Du den Code aus dem Buffer gelöscht hast, wusste Sonic Pi noch, was Du geschrieben hattest. Dies funktioniert nur mit Funktionen, die Du mit `define` (und `defonce`) definiert hast.

## Funktionen parametrisieren

Du kannst Deinen Funktionen beibringen, Argumente zu übernehmen, genau so, wie Du z.B. `rrand` einen Minimal- und einen Maximalwert übergeben kannst. Sehen wir uns das an:

    define :my_player do |n|
      play n
    end

    my_player 80
    sleep 0.5
    my_player 90

Das ist jetzt nicht besonders aufregend, zeigt aber, worum es hier geht. Wir haben unsere eigene Version von `play` mit dem Namen `my_player` erschaffen. Diese ist parametrisiert - sie akzeptiert also Argumente.

Die Parameter müssen nach dem `do` stehen, welches zum `define` des do/end-Blocks gehört; sie werden von senkrechten Strichen (auch: Verkettungszeichen) umgeben und durch Kommata getrennt. Du kannst beliebige Worte als Parameternamen verwenden.

Die Zauberei findet innerhalb des `define`-do/end-Blocks statt. Du kannst die Parameternamen so benutzen, als wären sie wirkliche Werte. In diesem Beispiel spiele ich den Ton `n`. Du kannst die Parameter als eine Art Versprechen ansehen, dass sie durch wirkliche Werte ersetzt werden, wenn der Code läuft. Das machst Du, indem Du der Funktion beim Aufruf einen Parameter mitgibst. Ich tue das hier mit `my_player 80`, um den Ton 80 zu spielen. Innerhalb der Funktionsdefinition wird `n` nun durch 80 ersetzt, sodass `play n` sich in `play 80` verwandelt. Wenn ich die Funktion erneut mit `my_player 90` aufrufe, wird `n` durch 90 ersetzt, sodass sich `play n` in `play 90` verwandelt.

Sehen wir uns interessantere Beispiele an:

    define :chord_player do |root, repeats|
      repeats.times do
        play chord(root, :minor), release: 0.3
        sleep 0.5
      end
    end

    chord_player :e3, 2
    sleep 0.5
    chord_player :a3, 3
    chord_player :g3, 4
    sleep 0.5
    chord_player :e3, 3

Hier habe ich `repeats` so benutzt, als ob es eine Zahl in der Zeile `repeats.times do` wäre. Zusätzlich habe ich `roots` so verwendet, als ob es ein Notenname im Aufruf `play` wäre.

Siehst Du? Unser Code wird sehr aussagekräftig und leichter lesbar, wenn wir eine Menge der Programmlogik in Funktionen verschieben.

# 5.6 - Variablen

Es ist sehr nützlich beim Coden, Namen für Dinge zu vergeben. Sonic Pi macht es Dir hier sehr leicht: Schreib einfach den Namen, den Du gerne verwenden möchtest, dann ein Gleichheitszeichen (`=`) und dann das Ding, welches Du Dir merken möchtest.

    sample_name = :loop_amen

Hier haben wir uns das Symbol `:loop_amen` mit der Variable `sample_name` gemerkt. Wir können nun `sample_name` überall da benutzen, wo wir auch `loop_amen` benutzen könnten. Zum Beispiel:

    sample_name = :loop_amen
    sample sample_name

Es gibt drei Hauptgründe, Variablen in Sonic Pi zu nutzen: Bedeutung vermitteln, Wiederholung steuern und Ergebnisse von Dingen speichern.

## Bedeutung vermitteln

Wenn Du Code schreibst, könntest Du denken, dass Du einfach nur dem Computer sagst, was er tun soll - solange der Computer das versteht, ist es okay. Es ist jedoch wichtig daran zu denken, dass nicht nur der Computer den Code liest. Andere Leute könnten den Code auch lesen und wollen verstehen, was da vor sich geht. Wahrscheinlich wirst Du den Code auch später selbst wieder lesen und möchtest verstehen, was er bedeutet. Obwohl Dir jetzt vielleicht alles offensichtlich erscheint - wahrscheinlich ist es für andere nicht ganz so offensichtlich und vielleicht nicht einmal für Dich in der Zukunft!

Kommentare sind eine Möglichkeit, anderen dabei zu helfen, Deinen Code zu verstehen. Weiterhin kannst Du sinnvolle Namen für Deine Variablen verwenden. Sie Dir diesen Code an:

    sleep 1.7533

Warum steht hier die Zahl `1.7533`. Woher kommt diese Zahl? Was bedeutet sie? Sieh Dir zum Vergleich diesen Code an:

    loop_amen_duration = 1.7533
    sleep loop_amen_duration

Aha, jetzt ist viel klarer, was `1.7533` bedeutet: Es ist die Dauer des Sample `loop_amen`! Natürlich kannst Du jetzt sagen, warum nicht einfach schreiben:

    sleep sample_duration(:loop_amen)

Das ist natürlich auch ein sehr guter Weg, die Absicht mitzuteilen, die hinter dem Code steht.

## Wiederholungen steuern

In Deinem Code wirst Du oft Dinge wiederholen, und wenn Du irgendwo etwas ändern willst, musst Du das an vielen Stellen tun. Schau Dir mal diesen Code an:

    sample :loop_amen
    sleep sample_duration(:loop_amen)
    sample :loop_amen, rate: 0.5
    sleep sample_duration(:loop_amen, rate: 0.5)
    sample :loop_amen
    sleep sample_duration(:loop_amen)

Hier machen wir eine ganze Menge mit dem `:loop_amen`! Was wäre, wenn Du das Ganze mit einem anderen Loop-Sample wie zum Beispiel `:loop_garzul` hören wollten? Wir müssten alle `:loop_amen` suchen und mit `:loop_garzul` ersetzen. Das mag in Ordnung sein, wenn Du viel Zeit hast - aber was, wenn Du gerade auf einer Bühne stehst? Manchmal hast Du nicht den Luxus, Zeit zu haben - vor allem dann nicht, wenn Du willst, dass die Leute weitertanzen.

Was wäre, wenn Du den Code so geschrieben hättest:

    sample_name = :loop_amen
    sample sample_name
    sleep sample_duration(sample_name)
    sample sample_name, rate: 0.5
    sleep sample_duration(sample_name, rate: 0.5)
    sample sample_name
    sleep sample_duration(sample_name)

Das tut genau dasselbe wie der Code weiter oben (probier es aus). Außerdem bekommen wir die Möglichkeit, durch die Änderung der einen Zeile `sample_name = :loop_amen` in `sample_name = :loop_garzul` die vielen anderen Stellen durch die Magie der Variablen zu verändern.

## Ergebnisse von Dingen speichern

Wenn man schließlich die Ergebnisse von irgendwelchen Dingen speichern möchte, dann ist das ebenfalls ein guter Grund dafür, Variablen zu verwenden. Du möchtest vielleicht irgendetwas mit der Dauer eines Sample anstellen:

    sd = sample_duration(:loop_amen)

Wir können nun `sd` überall da einsetzen, wo wir die Länge von `:loop_amen` brauchen.

Noch wichtiger vielleicht: Eine Variable erlaubt es uns, das Ergebnis eines Aufrufs von `play` oder `sample` zu speichern:

    s = play 50, release: 8

Jetzt haben wir `s` als Variable eingefangen und gemerkt. Und das erlaubt es uns, einen Synth zu steuern während er läuft:

    s = play 50, release: 8
    sleep 2
    control s, note: 62

Das nur als kleine Vorschau, wie man Synths steuert. Das schauen wir uns später noch genauer an.

# 5.7 - Synchronisation von Threads

Bald wirst Du ausreichend vertraut damit sein, live mit einer Anzahl von gleichzeitig ablaufenden Funktionen und Threads zu coden. Dann wirst Du bemerken, dass es ziemlich leicht ist, einen einzelnen Thread mit einem Fehler zum Abbruch zu bringen. Das ist nicht weiter schlimm, da Du den Thread mit einem Klick auf `Ausführen` ja einfach neu starten kannst. Wenn Du den Thread aber neu startest, dann läuft er nicht mehr zusammen mit den anderen so wie vorher, er ist nun aus dem Takt mit den ursprünglichen Threads.

## Vererbte Zeit

Wir haben zuvor erwähnt, dass neue Threads beim Start mit `in_thread` alle ihre Einstellungen vom Eltern-Thread erben. Das schließt auch die aktuelle Zeit mit ein. Das bedeutet, dass Threads bei gleichzeitigem Start immer miteinander im Takt sind.

Wenn Du aber einen Thread alleine startest, spielt er in seinem eigenen Takt, der höchstwahrscheinlich nicht mit irgendeinem der anderen laufenden Threads zusammenpasst.

## Cue und Sync

Sonic Pi hat mit den Funktionen `cue` und `sync` eine Lösung für dieses Problem.

`cue` erlaubt es uns, regelmäßige Signale an alle anderen Threads mit einem Taktgeber zu versenden. Standardmäßig sind die anderen Threads an solchen Signale nicht interessiert und werden sie ignorieren. Mit der `sync`-Funktion kann man jedoch erreichen, dass ein anderer Thread auf diesen Taktgeber hört.

Eine wichtige Sache, derer man sich bewusst sein sollte: `sync` ist so ähnlich `sleep`, weil es den aktuellen Thread für eine bestimmte Zeit anhält und dieser so lange nichts tut. Allerdings sagt man mit `sleep`, wie lange man warten möchte, während man bei `sync` nicht weiss, wie lange gewartet wird - denn `sync` wartet auf das nächste `cue` eines anderen Threads; das kann kürzer oder länger dauern.

Sehen wir uns das etwas genauer an:

    in_thread do
      loop do
        cue :tick
        sleep 1
      end
    end

    in_thread do
      loop do
        sync :tick
        sample :drum_heavy_kick
      end
    end

Hier haben wir zwei Threads - einer davon arbeitet wie ein Metronom; er spielt nichts, aber sendet bei jedem Schlag ein `:tick`-Taktgebersignal. Der zweite Thread synchronisiert sich mit den `tick`-Signalen, und wenn er eins davon erhält, übernimmt er die Zeit vom `cue`-Thread und läuft weiter.

Als Ergebnis hören wir den `:drum_heavy_kick` Sample genau dann, wenn der andere Thread ein `:tick`-Signal sendet, auch dann, wenn beide Threads gar nicht zur selben Zeit gestartet sind.

    in_thread do
      loop do
        cue :tick
        sleep 1
      end
    end

    sleep(0.3)

    in_thread do
      loop do
        sync :tick
        sample :drum_heavy_kick
      end
    end

Dieser freche (zweite) Aufruf von `sleep` würde eigentlich den zweiten Thread gegenüber dem ersten aus dem Takt bringen. Weil wir aber `cue` und `sync` verwenden, synchronisieren wir beide Threads automatisch und umgehen dabei, dass beide in der Zeit auseinanderfallen.

## Cue benennen

Du kannst `cue`-Signale benennen, wie Du willst - nicht nur mit `:tick`. Du musst nur sicherstellen, dass irgendein anderer Thread sich mit eben diesem Namen synchronisiert - ansonsten wartet der zweite Thread dann für immer (oder jedenfalls bis Du den `Stopp`-Button klickst).

Lasst uns ein paar Namen für `cue` ausprobieren:

    in_thread do
      loop do
        cue [:foo, :bar, :baz].choose
        sleep 0.5
      end
    end

    in_thread do
      loop do
        sync :foo
        sample :elec_beep
      end
    end

    in_thread do
      loop do
        sync :bar
        sample :elec_flip
      end
    end

    in_thread do
      loop do
        sync :baz
        sample :elec_blup
      end
    end

Hier haben wir eine `cue`-Hauptschleife, die auf Zufallsbasis einen von drei Namen des Taktgebers `:foo`, `:bar` oder `:baz` aussendet. Wir haben auch drei Schleifen-Threads, die jeder für sich mit einem der Namen synchronisiert werden und dann jeweils ein anderes Sample spielen. Im Endeffekt hören wir bei jedem halben Schlag einen Klang, da jeder der `sync`-Threads auf Zufallsbasis mit dem `cue`-Thread synchronisiert ist, und sein Sample spielt, wenn er dran ist.

Das funktioniert natürlich auch, wenn Du die Reihenfolge der Threads umkehrst: Die die `sync`-Threads sitzen einfach da und warten auf ihren nächsten `cue`.

# 6 - Studio-Klangeffekte

Es lohnt sich, mit Sonic Pi Deine Klänge mit Studio-Effekten zu verändern - Du wirst sehen, wie spannend das ist und wieviel Spaß das macht. Zum Beispiel kannst Du zu Teilen Deiner Komposition Hall-Effekte (‘Reverb’) hinzufügen. Oder etwas Echo (‘Echo’). Oder vielleicht möchtest Du Deine Bassmelodien verzerren (‘Distortion’) oder schwabbeln lassen (‘Wobble’).

Sonic Pi kannst Du sehr mächtige Klangeffekte auf ganz einfache Art einfügen. Du kannst sie sogar miteinander verketten oder sie ineinander verschachteln (zum Beispiel könntest Du einen Ton zuerst verzerren, dann Echo hinzufügen und zum Schluss noch etwas Hall). Jede individuelle Effekteinheit lässt sich mit Parametern steuern (ganz ähnlich, wie sich auch Synths und Samples steuern lassen). Du kannst sogar die Parameter eines Klangeffektes ändern, während der Effekt läuft. Zum Beispiel könntest Du den Halleffekt Deiner Bassmelodie während des Stückes langsam anheben.

## Gitarreneffekte

Wenn sich das alles etwas kompliziert anhören sollte, keine Sorge! Spiel ein bisschen mit den Effekten herum und es wird Dir ganz schnell alles viel einfacher vorkommen. Bevor Du loslegst, könnte dieser kleine Vergleich nützlich sein: Die Effekte in Sonic Pi funktionieren so ähnlich wie Gitarreneffektpedale. Es gibt eine Vielzahl von solchen Effektpedalen zu kaufen. Manche Gitarristen benutzen gerne Hall-Effekte (‘Reverb’), andere bevorzugen ein Verzerrerpedal (‘Distortion’), etc. Als Gitarrist kann man einfach seine Gitarre an ein Effektpedal anstecken - z.B. ‘Distortion’ - und dann mit einem weiteren Kabel noch ein Hallpedal anhängen. So entsteht eine Kette von Effekten. Das Ausgangssignal des Hall-Effektpedals am Ende der Kette kann man dann in einen Verstärker leiten:

    Gitarre -> Verzerrer -> Hall -> Verstärker

Man nennt diese Vorgehensweise ‘Effektverkettung’. Und genau das kannst Du mit Sonic Pi machen. Jedes Effektpedal hat normalerweise einige Drehknöpfe und Schalter, mit denen man exakt steuern kann, wieviel Verzerrung, Hall, oder Echo erzeugt werden soll. Und eines noch zum Schluss: Du kannst Dir sicher vorstellen, dass ein Gitarisst mit Gitarrespielen beschäftigt sein könnte, während jemand anderes die Effekte steuert. Das ist auch bei Sonic Pi möglich - aber anstatt auf jemand anderen dafür angewiesen zu sein, steht für Dich Dein Computer am Effektmischer und hilft Dir.

Aber jetzt ist es höchste Zeit, die Effektfunktionen auszuprobieren!

# 6.1 - FX hinzufügen

In diesem Abschnitt sehen wir uns zwei Effekte genauer an: Hall und Echo. Wir werden lernen, wie diese Effekte zu benutzen sind, wie man ihre Parameter steuern kann, und wie man sie verketten kann.

Das FX-System von Sonic Pi benutzt sogenannte Code-Blocks. Falls Du Abschnitt 5.1 des Tutorials noch nicht gelesen hast, sieh es Dir doch kurz an und kehre dann hierher zurück.

## Hall (‘Reverb’)

Um den Hall-Effekt zu benutzen, fügen wir `with_fx :reverb` als Spezialcode zu unserem bestehenden Code-Block hinzu. Und zwar so:

    with_fx :reverb do
      play 50
      sleep 0.5
      sample :elec_plip
      sleep 0.5
      play 62
    end

Wenn Du nun diesen Code-Block abspielst, wirst Du hören, dass der Hall-Effekt hinzugefügt wurde. Hört sich gut an, nicht wahr! Mit Hall-Effekt hört sich alles immer ziemlich gut an.

Aber was passiert, wenn wir den Code außerhalb des do/end-Code-Blocks hinzufügen:

    with_fx :reverb do
      play 50
      sleep 0.5
      sample :elec_plip
      sleep 0.5
      play 62
    end

    sleep 1
    play 55

Wie Du sicher bemerkt hast, wird nun die letzte Note (55) nicht mehr mit Hall-Effekt abgespielt. Der Grund dafür ist, dass sich die Note ausserhalb des do/end Code-Blocks befindet und deshalb unsere Anweisung zum Hall-Effekt für sie nicht mehr gültig ist.

Wenn Du Noten vor dem do/end-Code-Block einfügst, verhält es sich ganz ähnlich, und sie werden ebenfalls ohne Hall-Effekt abgespielt:

    play 55
    sleep 1

    with_fx :reverb do
      play 50
      sleep 0.5
      sample :elec_plip
      sleep 0.5
      play 62
    end

    sleep 1
    play 55

## Echo

Es stehen noch viele weitere Effekte zur Auswahl. Wie wäre es zum Beispiel mit etwas Echo?

    with_fx :echo do
      play 50
      sleep 0.5
      sample :elec_plip
      sleep 0.5
      play 62
    end

Die FX-Blocks von Sonic Pi sind besonders vielfältig einsetzbar, denn sie lassen sich über Parameter steuern. Genauso wie die Befehle `play` und `sample`, die wir ja schon kennen. Ein spannender Echo-Parameter ist zum Beispiel `phase:`. Dieser Parameter stellt die Dauer des Echos in Schlägen dar. Versuchen wir, das Echo etwas langsamer zu machen:

    with_fx :echo, phase: 0.5 do
      play 50
      sleep 0.5
      sample :elec_plip
      sleep 0.5
      play 62
    end

Und jetzt lass uns das Echo wieder schneller machen:

    with_fx :echo, phase: 0.125 do
      play 50
      sleep 0.5
      sample :elec_plip
      sleep 0.5
      play 62
    end

Wie wäre es nun mit einem langsam ausschwingenden Echo? Wir können dafür einfach den `decay:`-Wert auf 8 Schläge verlängern:

    with_fx :echo, phase: 0.5, decay: 8 do
      play 50
      sleep 0.5
      sample :elec_plip
      sleep 0.5
      play 62
    end

## FX verschachteln

Interessant wird es, wenn wir die FX-Blocks ineinander verschachteln. So können eine Vielzahl verschiedener FX leicht verkettet werden. Wie wäre es zum Beispiel damit, einen Code-Block zuerst mit Echo und dann mit Hall zu versehen? Das geht ganz einfach, Du musst nur die beiden Code-Blocks ineinander verschachteln:

    with_fx :reverb do
      with_fx :echo, phase: 0.5, decay: 8 do
        play 50
        sleep 0.5
        sample :elec_blup
        sleep 0.5
        play 62
      end
    end

Stell Dir das so vor, als ob die erzeugten Klänge von innen nach außen fließen würden. Der erzeugte Klang des innersten do/end-Code-Blocks (zum Beispiel ‘play 50’) wird zuerst durch den Echo-FX-Block gesendet, und danach noch durch den Hall-FX-Block.

Es ist ganz einfach, mit vielschichtigen Verschachtelungen verrückte Ergebnisse zu erzielen. Aber sei vorsichtig, weil FX viel Rechenkraft des Computers verbraucht, besonders dann, wenn Du mehrere FX zugleich benutzt. Sei also etwas sparsam mit Deinen FX, wenn Du mit eher rechenschwachen Geräten wie dem Raspberry Pi arbeitest.

## Weitere FX entdecken

Sonic Pi bringt eine Vielzahl von FX mit, die Du ausprobieren kannst. Eine komplette Liste findest Du im Hilfe-Fenster, wenn Du dort links auf ‘FX’ klickst. Hier sind einige meiner Favoriten:

- wobble
- reverb
- echo
- distortion
- slicer

Jetzt aber los, mach was Verrücktes und baue überall in Deinem Code FX ein. Du wirst unglaubliche neue Klänge erzeugen!

# 6.2 - FX Praxis

Auf den ersten Blick mögen die Effekte von Sonic Pi sehr einfach aussehen, aber in Wirklichkeit sind sie höchst komplexe Gebilde. Ihre scheinbare Einfachheit verleitet manche dazu, zu viele FX in ihre Projekte einzubauen. Das kann durchaus Spaß machen, wenn Du über einen sehr starken Computer hast. Aber falls Du - so wie ich - einen einfachen Raspberry Pi zum Musikmachen benutzt, musst Du darauf achten, die Maschine nicht zu überlasten. Nur so kannst Du sicher gehen, dass Sonic Pi ordentlich funktioniert und im Takt bleibt.

Sie Dir den folgenden Code an:

    loop do
      with_fx :reverb do
        play 60, release: 0.1
        sleep 0.125
      end
    end

Hier spielen wir die Note 60 mit sehr kurzem `release:`-Wert, und erzeugen so einen sehr kurzen Ton. Wir wollen außerdem einen Hall-Effekt, und haben deshalb den notwendigen Code-Block außen herum geschrieben. Soweit sieht alles gut aus. Oder doch nicht?

Sehen wir uns genauer an, was der Code hier macht. Zuerst einmal haben wir einen Loop, und wie wir ja schon wissen wird alles, was innerhalb der Endlosschleife geschrieben ist, für immer und ewig wiederholt. Außerdem haben wir einen `with_fx:`-do/end-Block. Das bedeutet, dass bei jeder Wiederholung des Loops ein neuer Hall-Effekt erzeugt wird. Das ist so, als ob wir jedes Mal, wenn wir eine Gitarrenseite zupfen, ein neues Pedal an die Effektkette hängen würden. Es ist ja ganz nett, das wir das machen können, aber es ist möglicherweise nicht das, was wir eigentlich wollen. Ein kleiner Raspberry Pi wird an diesem Code schwer zu arbeiten haben. Die `with_fx:`-Funktion erledigt die ganze Arbeit, bei jeder Wiederholung des Loops den Hall-Effekt zu erzeugen, dann zu warten, und dann den Effekt wieder zu entfernen, aber insgesamt werden dabei wertvolle CPU Ressourcen verbraucht.

Wie können wir einen ähnlichen Code-Block schreiben, bei dem unser Gitarrist nur ein einzelnes Hall-Effektpedal zur Klangerzeugung benutzt? Ganz einfach:

    with_fx :reverb do
      loop do
        play 60, release: 0.1
        sleep 0.125
      end
    end

Nun haben wir unseren Loop ins Innere des `with_fx:`-Blocks verpackt. So wird nur noch ein einziger Hall-Effekt erzeugt und auf alle Noten im Loop angewandt. Dieser Code-Block ist viel effizienter und wird auf jedem Raspberry Pi gut funktionieren.

Als Kompromiss könnten wir `with_fx:` auch als ‘iteration’ innerhalb eines Loops schreiben:

    loop do
      with_fx :reverb do
        16.times do
          play 60, release: 0.1
          sleep 0.125
        end
      end
    end

Somit wird die `with_fx:`-Funktion aus dem Inneren des Loops geholt, und der Code erzeugt jetzt nur noch einen Hall-Effekt alle 16 Noten.

Denk daran, man kann nichts falsch machen, dafür aber unendlich viele Varianten ausprobieren! Jede dieser Varianten wird sich jedoch ein bisschen anders anhören, und jeweils mehr oder weniger gut funktionieren. Es ist also empfehlenswert, so viel wie möglich zu experimentieren, bis Du die Variante gefunden hast, die am besten funktioniert und den Einschränkungen Deines Computers am besten gerecht wird.

# 7 - Laufende Sounds steuern

Bisher haben wir uns angeschaut, wie man Synths und Samples starten und ihre Standard-Einstellungen wie Lautstärke, Position im Stereofeld, Hüllkurven und so weiter anpassen kann. Jeder abgespielte Ton ist im Grunde genommen ein eigener Klang mit seinen eigenen Parametern für seine Abspieldauer.

Wäre es nicht cool, wenn man diese Parameter verändern könnte - während der Ton noch abgespielt wird? Etwa so, wie Du eine noch schwingende Saite beim Gitarrespielen ziehen kannst?

Glück gehabt - dieses Kapitel wird Dir genau das zeigen.

# 7.1 - Laufende Synths steuern

Bisher haben wir uns nur damit befasst, neue Sounds und Effekte zu starten.

Mit Sonic Pi kannst Du aber auch laufende Klänge steuern und verändern. Um das zu tun, speichern wir die Referenz zu einem Synth in einer Variable:

    s = play 60, release: 5

Jetzt haben wir eine run-local Variable `s`. Sie repräsentiert einen Synth, der die Note 60 spielt. Beachte, dass diese Variable eine lokale ist - Du kannst nicht von anderen Runs, wie beispielsweise Funktionen, auf sie zugreifen.

Sobald wir die Referenz in der Variable `s` haben, können wir den Synth mit Hilfe der `control`-Funktion steuern:

    s = play 60, release: 5
    sleep 0.5
    control s, note: 65
    sleep 0.5
    control s, note: 67
    sleep 3
    control s, note: 72

Wichtig ist hier, dass wir nicht vier verschiedene Synths starten - wir starten einen einzigen und ändern danach dreimal die Tonhöhe, während er noch spielt.

Wir können jeden der Standard-Parameter an die `control`-Funktion übergeben. Das erlaubt Dir, Dinge wie `amp:`, `cutoff:` oder `pan:` zu kontrollieren.

## Nicht-kontrollierbare Parameter

Manche Parameter lassen sich nach dem Start des Synths nicht mehr verändern. Das trifft auf alle ADSR-Hüllkurven-Parameter zu. Welche Parameter kontrollierbar sind, kannst Du in der Dokumentation im Hilfe-System herausfinden. Parameter, die mit Can not be changed once set markiert sind, lassen sich nach dem Synth-Start nicht mehr verändern.

# 7.2 - Effekte steuern

Man kann auch Effekte steuern, allerdings geht das ein wenig anders:

    with_fx :reverb do |r|
      play 50
      sleep 0.5
      control r, mix: 0.7
      play 55
      sleep 1
      control r, mix: 0.9
      sleep 1
      play 62
    end

Statt eine Variable zu verwenden, nutzen wir die senkrechten Striche des do/end-Blocks. Innerhalb der Striche `|`, müssen wir einen eindeutigen Namen für unseren laufenden Effekt vergeben, den wir dann innerhalb des do/end-Blocks verwenden. Dieses Verhalten ist das gleiche wie bei parametrisierten Funktionen.

Jetzt los - steuere ein paar Synths und Effekte!

# 7.3 - Gleitende Parameter

Vielleicht ist Dir beim Erforschen der Synth- und FX-Argumente aufgefallen, dass manche Parameter mit `_slide` enden. Vielleicht hast Du sie sogar ausprobiert und keine Auswirkung bemerkt. Das liegt daran, dass dies keine normalen Parameter sind. Diese besonderen Parameter funktionieren nur dann, wenn Du Synths wie im letzten Kapitel beschrieben steuerst.

Schau Dir das folgende Beispiel an:

    s = play 60, release: 5
    sleep 0.5
    control s, note: 65
    sleep 0.5
    control s, note: 67
    sleep 3
    control s, note: 72

Hier kannst Du hören, wie sich die Tonhöhe unmittelbar bei jedem Aufruf von `control` ändert. Vielleicht möchtest Du aber, dass die Tonhöhe sich gleitend zwischen den Aufrufen verändert. Um dort, wo wir den Parameter `note:` verwenden, gleitende Übergänge hinzuzufügen, nutzen wir den `note_slide:`-Parameter des Synth:

    s = play 60, release: 5, note_slide: 1
    sleep 0.5
    control s, note: 65
    sleep 0.5
    control s, note: 67
    sleep 3
    control s, note: 72

Jetzt hören wir, wie die Noten zwischen den `control`-Aufrufen “gezogen” werden. Hört sich gut an, oder? Mit einer kürzeren Dauer wie beispielsweise `note_slide: 0,2` kannst Du den Übergang beschleunigen. Oder ihn mit einer längeren Slide-Dauer verlangsamen.

Jeder steuerbare Parameter hat einen entsprechenden `_slide`-Parameter, mit dem Du spielen kannst.

## Gleiten ist klebrig

Nachdem Du einmal einen `_slide` Parameter auf einem laufenden Synth angegeben hast, bleibt er bestehen und wird jedesmal genutzt, wenn Du den entsprechenden Parameter steuerst. Um das Gleiten auszuschalten, musst Du den `_slide` Wert vor dem nächsten `control`-Aufruf auf 0 setzen.

## Gleitende Effekt-Parameter

Genauso ist es möglich, Effekt-Parameter gleiten zu lassen:

    with_fx :wobble, phase: 1, phase_slide: 5 do |e|
      use_synth :dsaw
      play 50, release: 5
      control e, phase: 0.025
    end

Und jetzt lass die Dinge ein wenig gleiten. Viel Spaß mit den weichen Übergängen…

# 8 - Datenstrukturen

Ein sehr praktisches Werkzeug im Werkzeugkasten jedes Programmierers sind Datenstrukturen.

Manchmal möchtest Du mehr als eine Sache darstellen oder verwenden. Es könnte beispielsweise nützlich sein, sich eine Reihe von Noten zu merken, um sie dann nacheinander abzuspielen. In Programmiersprachen sind Datenstrukturen genau für diesen Zweck da.

Es sind viele aufregende und exotische Datenstrukturen für Programmierer verfügbar - und es werden immer noch neue erfunden. Für unsere Zwecke benötigen wir vorerst jedoch nur eine sehr einfache Datenstruktur: Die Liste.

Lass uns das gleich im Detail anschauen. Wir werden uns die Grundform einer Liste anschauen und wie man sie verwendet, um Skalen und Akkorde abzubilden.

# 8.1 - Listen

In diesem Abschnitt werden wir uns eine sehr nützliche Datenstruktur anschauen - die Liste.

Wir hatten schon einmal in dem Abschnitt über Randomisierung kurz mit ihr zu tun, als wir die zu spielenden Noten zufällig aus einer Liste auswählten:

    play choose([50, 55, 62])

In diesem Abschnitt erforschen wir, wie man Akkorde und Skalen mit Listen darstellen kann. Rufen wir uns wieder in Erinnerung, wie wir einen Akkord spielen könnten. Wenn wir `sleep` nicht verwenden, werden alle Töne zur gleichen Zeit abgespielt:

    play 52
    play 55
    play 59

Wir können diesen Code aber auch anders schreiben.

## Eine Liste abspielen

Eine Möglichkeit ist es, alle Noten aus einer Liste zu spielen: `[52, 55, 59]`. Unsere freundliche Funktion `play` ist schlau genug, um zu wissen, wie man eine Liste von Noten abspielt. Versuche es einmal:

    play [52, 55, 59]

Prima, das kann man schon viel besser lesen. Das Abspielen einer Liste hindert uns aber nicht daran, die gewohnten Parameter zu verwenden:

    play [52, 55, 59], amp: 0.3

Natürlich kannst Du auch die traditionellen Namen der Noten anstelle der MIDI-Nummern verwenden:

    play [:E3, :G3, :B3]

Die Glücklichen unter Euch, die ein bisschen Musiktheorie gelernt haben, erkannten den Akkord vielleicht: Es ist E-Moll in der dritten Oktave.

## Listenzugriffe

Sehr nützlich an Listen ist, dass man auf die enthaltenen Informationen zugreifen kann. Das klingt vielleicht seltsam, aber es ist nicht komplizierter als beispielsweise das Öffnen eines Buches auf der Seite 23. Eine Liste fragt man einfach “Was ist das Element am Index 23?”. Du musst Dir nur eine Merkwürdigkeit merken: Beim Programmieren beginnt man beim Zählen der Listenelemente normalerweise mit 0 statt mit 1.

Listenindizes zählen wir also nicht 1,2,3,… sondern 0,1,2,…

Wir schauen uns das etwas genauer an. Nehmen wir diese Liste:

    [52, 55, 59]

Nicht besonders beängstigend. Was ist das zweite Element dieser Liste? Natürlich, das ist `55`. Das war einfach. Jetzt versuchen wir, ob wir nicht den Computer dazu bringen können, die Frage für uns zu beantworten:

    puts [52, 55, 59][1]

Falls Du so etwas noch nie gesehen hast, mag das ein bisschen seltsam wirken. Aber vertrau mir, das ist nicht schwierig zu durchschauen. Die Zeile oben besteht aus drei Teilen: Dem Wort `puts`, unserer Liste `52, 55, 59` und unserem Index `[1]`. Als Erstes sagen wir `puts`, damit Sonic Pi die Antwort für uns ins Protokoll schreibt. Danach übergeben wir unsere Liste und am Ende den Index, mit dem wir nach dem zweiten Element der Liste fragen. Den Index müssen wir mit eckigen Klammern umschließen, und da wir bei `0` zu zählen beginnen, ist der Index des zweiten Elements `1`. Wie hier unten:

    # indexes:  0   1   2
               [52, 55, 59]

Versuche mal, den Code `puts [52, 55, 59][1]` auszuführen, dann wirst Du sehen, dass `55` im Protokoll erscheint. Ändere mal den Index `1` in einen anderen, probiere längere Listen aus und denke darüber nach, wie Du Listen in Deinem nächsten Code-Jam verwenden könntest. Welche Strukturen aus der Musik könnte man denn als eine Reihe von Zahlen interpretieren?

# 8.2 - Akkorde

Sonic Pi kann Dir den Namen eines Akkords in eine Liste seiner Töne übersetzen. Versuche es selbst:

    play chord(:E3, :minor)

Jetzt tut sich was. Das sieht doch schon viel schöner aus als einfache Listen (und ist für andere viel einfacher lesbar). Welche Akkorde kennt Sonic Pi noch? Naja, viele. Probier mal ein paar von diesen aus:

- `chord(:E3, :m7)`
- `chord(:E3, :minor)`
- `chord(:E3, :dim7)`
- `chord(:E3, :dom7)`

## Arpeggios

Um Akkorde einfach in Arpeggios umzuwandeln, können wir die Funktion `play_pattern` verwenden:

    play_pattern chord(:E3, :m7)

Ok, das war nichts besonderes - das ging wirklich langsam. `play_pattern` spielt jede Note in der Liste hintereinander, getrennt durch Aufrufe von `sleep 1` ab. Wir können die Funktion `play_pattern_timed` verwenden, um unsere eigenen Zeitdauern zu verwenden und das Ganze zu beschleunigen:

    play_pattern_timed chord(:E3, :m7), 0.25

Wir können sogar eine Liste von Dauern übergeben; Sonic Pi verwendet diese nacheinander und wiederholt sie solange wie notwendig:

    play_pattern_timed chord(:E3, :m13), [0.25, 0.5]

Das bedeutet das gleiche wie:

    play 52
    sleep 0.25
    play 55
    sleep 0.5
    play 59
    sleep 0.25
    play 62
    sleep 0.5
    play 66
    sleep 0.25
    play 69
    sleep 0.5
    play 73

Was würdest Du lieber schreiben?

# 8.3 - Skalen

Sonic Pi kennt eine große Anzahl von Skalen. Wie wäre es, eine C3-Dur-Skala zu spielen?

    play_pattern_timed scale(:c3, :major), 0.125, release: 0.1

Wir können die Skala auch über mehrere Oktaven spielen lassen:

    play_pattern_timed scale(:c3, :major, num_octaves: 3), 0.125, release: 0.1

Und wie wär’s mit allen Noten einer pentatonischen Tonleiter?

    play_pattern_timed scale(:c3, :major_pentatonic, num_octaves: 3), 0.125, release: 0.1

## Zufällige Noten

Akkorde und Skalen sind gute Methoden, eine zufällige Auswahl auf etwas von Bedeutung einzugrenzen. Spiele einmal mit diesem Beispiel, das zufällige Noten aus dem E-Moll-Akkord in der 3. Oktave auswählt:

    use_synth :tb303
    loop do
      play choose(chord(:E3, :minor)), release: 0.3, cutoff: rrand(60, 120)
      sleep 0.25
    end

Probiere auch verschiedene Akkord-Namen und Cut-Off-Bereiche aus.

## Akkorde und Skalen entdecken

Um herauszufinden, welche Skalen und Akkorde Sonic Pi unterstützt, klicke einfach auf den `Lang`-Button ganz auf der linke Seite dieses Tutorials und wähle entweder `chord` oder `scale` aus der API-Liste. Scrolle im Hauptfenster herunter, bist Du eine lange Liste von Akkorden oder Skalen findest.

Viel Spaß und nicht vergessen: Es gibt keine Fehler, nur Möglichkeiten.

# 8.4 - Ringe

Eine interessante Spielart von normalen Listen sind Ringe. Wenn Du ein bisschen Programmiererfahrung hast, könntest Du Ringspeicher (engl. ‘Ring Buffer’) oder Ring-Arrays kennen. Wir nennen die hier nur Ring - das ist kurz und einfach.

Im vorherigen Abschnitt über Listen haben wir gesehen, dass wir Elemente aus einer Liste über den Index holen können:

    puts [52, 55, 59][1]

Was passiert jetzt wohl, wenn Du den Index `100` abfragen willst? Offensichtlich gibt es kein Element mit dem Index 100, da die Liste nur drei Elemente enthält. Also gibt Sonic Pi `nil` zurück, was “nichts” bedeutet. Stell Dir vor, einen Zähler wie den aktuellen Takt zu haben, der kontinuierlich wächst. Lass uns so einen Zähler und unsere Liste anlegen:

    counter = 0
    notes = [52, 55, 59]

Jetzt können wir mit unserem Zähler auf eine Note in unserer Liste zugreifen:

    puts notes[counter]

Super, da kam `52` heraus. Jetzt erhöhen wir den Zähler (`inc`, die Abkürzung für englisch “to increment” = erhöhen) und bekommen damit eine neue Note:

    counter = (inc counter)
    puts notes[counter]

Ok, jetzt kommen `55` und beim nächsten Mal `59` heraus. Wenn wir das jedoch jetzt noch einmal machen, werden wir aber nicht mehr genug Zahlen in unserer Liste haben und werden stattdessen `nil` zurück bekommen. Was wäre, wenn wir dann einfach wieder vom Anfang der Liste anfangen wollten? Genau dafür gibt es Ringe.

## Ringe erzeugen

Es gibt zwei Möglichkeiten, Ringe zu erzeugen. Die erste ist, die `ring` Funktion mit den gewünschten Elementen des Rings als Parameter zu verwenden:

    (ring 52, 55, 59)

Die zweite Möglichkeit ist es, eine normale Liste mit der Nachricht `.ring` zu einem Ring umzuwandeln:

    [52, 55, 59].ring

## Auf Ringelemente zugreifen

Sobald wir einen Ring haben, können wir ihn auf die gleiche Art wie eine Liste verwenden. Die einzige Ausnahme ist, dass Du Indizes verwenden kannst, die negativ oder größer als der Ringinhalt sind. Diese fangen dann wieder am Anfang an, um immer auf ein Element des Rings zu zeigen:

    (ring 52, 55, 59)[0] #=> 52
    (ring 52, 55, 59)[1] #=> 55
    (ring 52, 55, 59)[2] #=> 59
    (ring 52, 55, 59)[3] #=> 52
    (ring 52, 55, 59)[-1] #=> 59

## Ringe verwenden

Angenommen, wir bilden die Nummer des aktuellen Takts in einer Variable ab. Diese Nummer können wir als Zugriffsindex für unseren Ring verwenden, um abzuspielende Note, Release-Zeiten oder andere sinnvolle Dinge, die wir in unserem Ring abgelegt haben, abzurufen.

## Skalen und Akkorde sind Ringe

Gut zu wissen: Die Listen, die von `scale` und `chord` zurückgegeben werden, sind Ringe. Du kannst also mit beliebigen Indizes auf sie zuzugreifen.

## Ring-Konstruktoren

Zusätzlich zu `ring` gibt es noch eine Anzahl weiterer Funktionen, die Ringe für uns erzeugen:

- `range` lädt ein, einen Startpunkt, einen Endpunkt und eine Schrittgröße zu definieren.
- `bools` erlaubt Dir `1`er und `0`er als prägnante Darstellung boolscher Werte zu nutzen.
- `knit` erlaubt Dir, eine Abfolge wiederholter Werte zu “stricken” (engl. “to knit”).
- `spread` verteilt boolschen Werte mit dem Euklidischen Algorithmus in einem Ring.

Mehr Informationen zu diesen Funktionen findest Du in der entsprechenden Dokumentation.

# 9 - Live-Coding

So, und jetzt wird es aufregend! Mit Sonic Pi kannst Du den Code für Deine Musik live schreiben und verändern. Du kannst also während eines Auftritts mit Sonic Pi live Musik machen - wie mit einer Gitarre.

Das Großartige daran ist, dass Du noch während des Komponierens sofort die Rückmeldung vom Publikum erhältst. Starte einen einfachen Loop und spiele daran herum, bis er genau richtig klingt. Der größte Vorteil ist aber, dass Du Sonic Pi bei einem Gig mit auf die Bühne nehmen kannst.

In diesem Abschnitt behandeln wir die Grundlagen, mit denen Du Deine Kompositionen von statischem Code in rasante Performances verwandeln kannst.

Halt Dich fest…

# 9.1 - Live-Coding

Inzwischen haben wir genug gelernt, nun können wir wirklich Spaß haben.

In diesem Abschnitt nutzen wir alles, was wir bisher in diesem Tutorial gelernt haben und zeigen Dir, wie Du Deine Kompositionen live aufführen und in Performances verwandeln kannst. Dazu benötigen wir vor allem drei Zutaten:

- Die Fähigkeit, Code zu schreiben, der Töne erzeugt - CHECK!
- Die Fähigkeit, Funktionen zu schreiben - CHECK!
- Die Fähigkeit, (named) Threads zu verwenden - CHECK!

Ok, es kann also los gehen. Lass uns unsere ersten Sounds live coden. Zuerst brauchen wir eine Funktion, die den abzuspielenden Code enthält. Wir fangen ganz einfach an. Außerdem wollen wir diese Funktion in einer Schleife in einem Thread aufrufen:

    define :my_loop do
      play 50
      sleep 1
    end

    in_thread(name: :looper) do
      loop do
        my_loop
      end
    end

Wenn Dir das ein bisschen zu kompliziert aussieht, lies bitte noch einmal die Abschnitte über Funktionen und Threads durch. Wenn Du diese Dinge verstanden hast, wird es Dir nicht mehr sehr kompliziert vorkommen.

Wir haben hier eine Funktion, welche die Note 50 spielt und danach eine Schlagzeit lang schläft. Dann definieren wir einen benamten Thread, den wir `:looper` nennen. Dieser ruft in einer Endlosschleife `my_loop` auf.

Wenn Du diesen Code ausführst, wirst Du immer und immer wieder die Note 50 hören…

## Hochschalten

Jetzt geht es richtig los. Während der Code noch läuft, ändere die 50 in eine andere Zahl, zum Beispiel 55, und drücke den `Ausführen`-Button erneut. Woah! Es hat sich verändert! Live!

Wir haben keine neue Ebene bekommen, da wir einen benannten Thread verwendet haben und es nur einen Thread pro Name geben kann. Der Ton hat sich geändert, weil wir die Funktion umgeschrieben haben. Wir haben also `:my_loop` eine veränderte Funktion verpasst. Der `:looper`-Thread hat einfach diese veränderte Funktion aufgerufen.

Verändere die Funktion noch einmal, ändere die Note und die Pausenzeit. Wie wäre es damit, ein `use_synth`-Statement einzufügen?

Ändere die Funktion zum Beispiel in folgenden Code:

    define :my_loop do
      use_synth :tb303
      play 50, release: 0.3
      sleep 0.25
    end

Jetzt klingt es schon ganz interessant, wir können es aber noch ein bisschen aufpeppen. Anstatt immer wieder die gleiche Note zu spielen, versuche es einmal mit einem Akkord.

    define :my_loop do
      use_synth :tb303
      play chord(:e3, :minor), release: 0.3
      sleep 0.5
    end

Und wie wäre es damit, zufällige Töne des Akkords zu spielen:

    define :my_loop do
      use_synth :tb303
      play choose(chord(:e3, :minor)), release: 0.3
      sleep 0.25
    end

Oder einen zufälligen Cut-Off-Wert:

    define :my_loop do
      use_synth :tb303
      play choose(chord(:e3, :minor)), release: 0.2, cutoff: rrand(60, 130)
      sleep 0.25
    end

Und zum Schluss noch ein Schlagzeug dazu:

    define :my_loop do
      use_synth :tb303
      sample :drum_bass_hard, rate: rrand(0.5, 2)
      play choose(chord(:e3, :minor)), release: 0.2, cutoff: rrand(60, 130)
      sleep 0.25
    end

So langsam wird das hier alles viel spannender!

Bevor Du jetzt aufspringst und mit Funktionen und Threads live codest, solltest Du lieber erst einmal eine Pause machen und das nächste Kapitel über den `live_loop` lesen. Denn dieser wird für immer verändern, wie Du in Sonic Pi programmierst…

# 9.2 - Live-Loops

Ok, dieses Kapitel des Tutorials ist ein Juwel. Wenn Du nur einen Abschnitt lesen würdest, sollte es dieser sein. Mit `live_loop` kannst Du genau das, was Du im letzten Abschnitt gelernt hast, viel einfacher und mit weniger Code tun. Falls Du den letzten Abschnitt nicht gelesen hast: `live_loop` ist der beste Weg, mit Sonic Pi zu jammen.

Also los. Schreibe folgendes in einen neuen Buffer:

    live_loop :foo do
      play 60
      sleep 1
    end

Jetzt klicke den `Ausführen`-Button. Du hörst zu jeder Schlagzeit ein einfaches Piepen. Kein besonderer Spaß. Drücke aber noch nicht den `Stopp`-Button. Ändere die `60` in `65` und drücke wieder `Ausführen`.

Whoa! Es hat sich automatisch verändert, ohne einen Takt auszulassen. Das ist Live-Coding. Warum es jetzt nicht ein wenig bassiger machen? Verändere Deinen Code, während er abläuft:

    live_loop :foo do
      use_synth :prophet
      play :e1, release: 8
      sleep 8
    end

Dann drücke `Ausführen`.

Lass uns den Cut-Off ein wenig bewegen:

    live_loop :foo do
      use_synth :prophet
      play :e1, release: 8, cutoff: rrand(70, 130)
      sleep 8
    end

Drücke wieder `Ausführen`.

Füge ein Schlagzeug hinzu:

    live_loop :foo do
      sample :loop_garzul
      use_synth :prophet
      play :e1, release: 8, cutoff: rrand(70, 130)
      sleep 8
    end

Ändere den Ton von `e1` nach `c1`:

    live_loop :foo do
      sample :loop_garzul
      use_synth :prophet
      play :c1, release: 8, cutoff: rrand(70, 130)
      sleep 8
    end

Und jetzt hör auf, mir zuzuhören. Spiele selbst herum, viel Spaß!

# 9.3 - Mehrere Live-Loops

Schau Dir den folgenden Live-Loop an:

    live_loop :foo do
      play 50
      sleep 1
    end

Vielleicht fragst Du Dich, warum er den Namen `:foo` braucht. Dieser Name ist wichtig, weil er sicherstellt, dass sich dieser Live-Loop von allen anderen Live-Loops unterscheidet.

Es können nie zwei Live-Loops mit dem selben Namen gleichzeitig laufen.

Wir müssen also unterschiedliche Namen vergeben, damit wir mehrere gleichzeitig laufende Live-Loops spielen können.

    live_loop :foo do
      use_synth :prophet
      play :c1, release: 8, cutoff: rrand(70, 130)
      sleep 8
    end

    live_loop :bar do
      sample :bd_haus
      sleep 0.5
    end

Jetzt kannst Du beide Live-Loops unabhängig voneinander verändern und alles funktioniert - einfach so.

## Live-Loops synchronisieren

Du hast vielleicht schon bemerkt, dass Live-Loops automatisch mit dem Thread-Cue-Mechanismus arbeiten, den wir uns im Abschnitt über Thread-Synchronisation bereits angeschaut haben.

In jedem Durchlauf des Live-Loops generiert er ein neues `cue`-Event mit dem Namen des Loops. Anhand dieser Cues können wir für unsere Loops mit `sync` sicherstellen, dass sie zueinander synchron laufen, ohne dass wir das Abspielen zwischendurch stoppen müssen.

Schau Dir diesen schlecht synchronisierten Code an:

    live_loop :foo do
      play :e4, release: 0.5
      sleep 0.4
    end

    live_loop :bar do
      sample :bd_haus
      sleep 1
    end

Jetzt versuchen wir, das Timing zu korrigieren ohne den Loop zu stoppen. Zuerst reparieren wir den Loop `:foo`, indem wir die Sleep-Dauer zu einem Faktor von 1 machen - dafür funktioniert zum Beispiel `0.5`.

    live_loop :foo do
      play :e4, release: 0.5
      sleep 0.5
    end

    live_loop :bar do
      sample :bd_haus
      sleep 1
    end

Damit sind wir aber noch nicht ganz fertig. Du hörst schon, dass die Beats nicht so recht zusammenpassen. Der Grund dafür ist, dass diese Loops out of phase sind. Das können wir reparieren, indem wir einen Loop mit dem anderen synchronisieren:

    live_loop :foo do
      play :e4, release: 0.5
      sleep 0.5
    end

    live_loop :bar do
      sync :foo
      sample :bd_haus
      sleep 1
    end

Wow, jetzt passt alles genau zusammen - und das, ohne dass wir die Loops anhalten mussten.

Jetzt fangt an und coded live in Live-Loops!

# 9.4 - Ticks verwenden

Beim Live-Coding wirst Du in Deinen Loops sehr oft Ringe verwenden. Aus einem Ring wirst Du Noten für Melodien, Pausen für Rhythmen, Akkordfolgen, Klangvariatonen und ähnliches entnehmen.

## Ticks und Ringe

Das Tick-System ist ein sehr praktisches Werkzeug, um in einem `live_loop` mit Ringen zu hantieren. Du kannst damit einen Ring durchticken. Hier ein Beispiel:

    live_loop :arp do
      play (scale :e3, :minor_pentatonic).tick, release: 0.1
      sleep 0.125
    end

In diesem Beispiel tickt der Code einmal jede Note der pentatonischen E3-Moll-Tonleiter durch. Dafür fügst Du einfach ein `.tick` hinter der Tonleiter-Deklaration an. Dieser Tick gilt nur für diese Live-Loop und jede Live-Loop kann seinen eigenen, unabhängigen Tick haben:

    live_loop :arp do
      play (scale :e3, :minor_pentatonic).tick, release: 0.1
      sleep 0.125
    end

    live_loop :arp2 do
      use_synth :dsaw
      play (scale :e2, :minor_pentatonic, num_octaves: 3).tick, release: 0.25
      sleep 0.25
    end

## Tick

Du kannst auch den aktuellen Tick mit der Standard-Funktion `tick` abfragen und den Wert als Index verwenden:

    live_loop :arp do
      idx = tick
      play (scale :e3, :minor_pentatonic)[idx], release: 0.1
      sleep 0.125
    end

Aber eigentlich ist es viel einfacher, wenn Du `.tick` am Ende anfügst. Die `tick`-Funktion kannst Du benutzen, wenn Du aufwändigere Dinge machen möchtest; oder wenn du Ticks für andere Dinge verwenden möchtest als Werte aus einem Ring anzusteuern.

## Look

Die Magie des Ticks ist, dass er sich nach jedem Aufruf erhöht, so dass Du bei der nächsten Verwendung auch den nächsten Tick bekommst. In den Beispielen findest Du einige Sonic-Pi-Codes, die `.tick` verwenden, schau sie Dir mal näher an.

Manchmal willst Du aber den aktuellen Tick benutzen, ohne dass er gleich um einen Wert weiter tickt. Dafür gibt es die `look`-Funktion. Du kannst sie wie zuvor mit `look` als Funktion aufrufen oder mit `.look` an einen Ring anfügen.

## Namen für Ticks

Gelegentlich wirst Du auch mal mehr als einen Tick pro Live-Loop brauchen. Gib den Ticks dafür Namen:

    live_loop :arp do
      play (scale :e3, :minor_pentatonic).tick(:foo), release: 0.1
      sleep (ring 0.125, 0.25).tick(:bar)
    end

In diesem Beispiel markiert ein Tick die Position in der Tonleiter, ein zweiter Tick wählt die Pausenwerte. Beide Ticks befinden sich im gleichen Live-Loop, also geben wir ihnen zur Unterscheidung eindeutige Namen. Du kennst das Prinzip schon von den Live-Loops - einfach ein `:` gefolgt vom Namen. Im Beispiel heißt der eine Tick `:foo` und der andere `:bar`. Willst Du die Tick-Werte mit `look` nur abfragen, musst Du ebenso den Namen nennen.

## Mach’s nicht zu kompliziert

Mit Ticks kannst Du viele großartige Dinge machen, aber versuche nicht, gleich alles in diesem Kapitel zu lernen und anzuwenden. Für den Anfang reicht es völlig, wenn Du nur durch einen Ring durchtickst und das Prinzip kennenlernst. Damit kannst Du in Deinen `live_loop`s schon eine Menge anfangen.

Schau Dir die Dokumentation an, Du wirst dort viele praktische Beispiele entdecken. Viel Spaß beim Durchticken!

# 10 - Unentbehrliche Kenntnisse

In diesem Kapitel findest Du sehr nützliches - nein, unentbehrliches - Wissen, um das Bestmögliche aus Deinem Sonic Pi herauszuholen.

Wir behandeln viele der verfügbaren Tastaturkürzel, zeigen, wie Du Deine Ergebnisse mit anderen teilen kannst, und geben Dir Tipps für Auftritte mit Sonic Pi.

# 10.1 - Tastaturkürzel

Sonic Pi ist zu gleichen Teilen Musikinstrument und Programmierumgebung. Mit Tastaturkürzeln kannst Du Sonic Pi viel effizienter und natürlicher spielen - insbesondere, wenn Du live vor Publikum spielst.

Sehr vieles in Sonic Pi kann mit der Tastatur gesteuert werden. Je vertrauter Du mit Sonic Pi wirst, umso mehr wirst Du diese Tastaturkürzel verwenden. Ich selbst tippe, ohne die Tastatur anzusehen (und kann Dir nur empfehlen, das Zehnfingersystem auch zu lernen). Und ich bin jedes Mal frustriert, wenn ich zur Maus greifen muss, denn das macht mich langsam. Deshalb benutze ich ständig Tastaturkürzel!

Wer die Tastaturkürzel beherrscht, kann auch seine Tastatur viel effektiver benutzen und in kürzester Zeit wirst Du programmieren wie ein Profi.

Versuche aber nicht, alle auf einmal zu lernen, merke Dir erst einmal die, die Du am häufigsten brauchst. Später kannst Du Dein Repertoire nach und nach erweitern.

## Konsistenz auf verschiedenen Plattformen

Stell Dir vor, Du lernst Klarinette. Du kannst davon ausgehen, dass alle Klarinetten aller Marken gleiche Mechaniken und Fingersätze haben. Hätten sie das nicht, könntest Du nicht ohne weiteres zwischen verschiedenen Klarinetten hin- und her wechseln. Sondern müsstest immer bei einer Marke bleiben.

Unglücklicherweise haben die drei wesentlichen Betriebssysteme (Linux, Mac OS X und Windows) alle ihre eigenen typischen Tastaturkürzel für Aktionen wie z.B. Kopieren, Ausschneiden und Einfügen. Sonic Pi nutzt diese Standards wo immer möglich. Jedoch liegt die Priorität auf plattformübergreifender Konsistenz innerhalb von Sonic Pi, nicht auf dem Versuch, die Standards der jeweiligen Plattform vollumfänglich zu erfüllen. Das bedeutet, dass die in Sonic Pi auf dem Raspberry Pi gelernten Tastaturkürzel ebenso auf einem Mac oder PC mit Sonic Pi funktionieren.

## Control und Meta

Für diese Konsistenz müssen wir auch die Namen der Tastaturkürzel entsprechend auswählen. In Sonic Pi verwenden wir die Namen Control und Meta für die beiden wichtigsten Kombinationstasten. Control (Ctrl - oder Strg für “Steuerung” auf deutschen Tastaturen) ist auf allen Plattformen gleich. Auf Linux und Windows ist Meta die Alt-Taste, während Meta auf dem Mac die Command-Taste ist. Um konsistent zu bleiben, nutzen wir den Begriff Meta - diesem musst Du mental die passende Taste Deines Betriebssystems zuordnen.

## Abkürzungen

Um die Dinge einfach und lesbar zu halten, werden wir die Abkürzungen C- für Control und eine weitere Taste sowie M- für Meta und eine weitere Taste verwenden.

Wenn ein Tastaturkürzel beispielsweise erfordert, dass Du Meta und r gleichzeitig drückst, werden wir die Abkürzung `M-r` verwenden. Der Bindestrich in der Mitte (-) bedeutet nur “zur gleichen Zeit”.

Hier sind ein paar der Tastaturkürzel, die ich am nützlichsten finde.

## Starten und Stoppen

Du musst nicht immer zur Maus greifen, um Deinen Code auszuführen. Drücke stattdessen einfach `M-r` zum Abspielen. Mit `M-s` stoppst Du die Musik.

## Navigation

Ohne die Tastenkürzel zur Navigation bin ich verloren. Deshalb empfehle ich Dir dringend, diese Kürzel zu lernen. Sie funktionieren besonders gut, wenn Du das Zehnfingersystem schon halbwegs beherrschst, da sie normale Buchstaben verwenden - so musst Du Deine Hand nicht zur Maus oder zu den Pfeiltasten bewegen.

Mit `C-a` springst Du an den Anfang, mit `C-e` ans Ende einer Zeile. Eine Zeile nach oben geht es mit `C-p`, eine nach unten mit `C-n`, ein Zeichen vorwärts mit `C-f` und eines nach hinten mit `C-b`.

Du kannst auch alle Zeichen von der akutellen Cursorposition bis zum Ende der Zeile mit `C-k` löschen.

## Code aufräumen

Um Deinen Code sauber einzurücken, drücke `M-m`.

## Hilfesystem

Zum Hilfesystem kommst Du mit `M-i`. Noch hilfreicher ist allerdings `C-i`, damit wird Dir für das Wort, auf dem der Cursor gerade steht, sofort die passende Stelle in der Dokumentation gezeigt. Sofortige Hilfe!

Eine Liste aller Tastaturkürzel ist in Kapitel 10.2 “Cheatsheet für Tastenkürzel” enthalten.

# 10.2 - Cheatsheet für Tastaturkürzel

In diesem Abschnitt findest Du eine Zusammenfassung der wichtigsten Tastenkürzel von Sonic Pi. In Abschnitt 10.1 erklärte ich Dir bereits, warum diese so nützlich sind.

## Konventionen

Wir verwenden die folgenden Konventionen (Meta ist Alt auf Windows und Linux und Cmd auf dem Mac wie in 10.1 beschrieben):

- `C-a` bedeutet, die Control (Strg auf deutschen Tastaturen) zu drücken und zu halten, dabei a zu drücken und danach beide Tasten wieder los zu lassen.
- `M-r` bedeutet, Meta zu drücken und zu halten, dabei die r-Taste zu drücken und danach beide wieder los zu lassen
- `S-M-z` bedeutet, die Meta-Taste zu drücken und zu halten, dann Shift zu drücken und zu halten und schließlich die z-Taste und alle drei Tasten gleichzeitig wieder los zu lassen.
- `C-M-f` bedeutet, Control zu drücken und zu halten, dann Meta zu drücken und zu halten, dann f zu drücken und alle drei Tasten gleichzeitig wieder los zu lassen.

## Steuerung der Hauptanwendung

- `M-r` - Code ausführen
- `M-s` - Code-Ausführung stoppen
- `M-i` - Hilfesystem ein-/ausschalten
- `M-p` - Einstellungen ein-/ausschalten
- `M-<` - Zum Buffer links wechseln
- `M->` - Zum Buffer rechts wechseln
- `M-+` - Schrift des Buffers vergrößern
- `M--` - Schrift des Buffers verkleinern

## Auswahl/Kopieren/Einfügen

- `M-a` - Alles auswählen
- `M-c` - Auswahl in den Zwischenspeicher kopieren
- `M-x` - Auswahl ausschneiden und im Zwischenspeicher ablegen
- `C-k` - Text ab Cursor bis zum Ende der Zeile ausschneiden
- `M-v` - Inhalt des Zwischenspeichers in den Editor kopieren
- `C-SPACE` - Markierung setzen. Textauswahl ab jetzt von hier bis zum Cursor. `C-g` löscht die Markierung.

## Text-Manipulation

- `M-m` - Gesamten Code ausrichten
- `Tab` - Aktuelle Codezeile oder Auswahl ausrichten
- `C-l` - Editor zentrieren
- `M-/` - Aktuelle Codezeile auskommentieren
- `M-u` - Das nächste Wort oder Auswahl in Großbuchstaben wandeln
- `M-l` - Das nächste Wort oder Auswahl in Kleinbuchstaben wandeln

## Navigation

- `C-a` - An den Anfang der Zeile springen
- `C-e` - Ans Ende der Zeile springen
- `C-p` - Zur vorherigen Zeile springen
- `C-n` - Zur nächsten Zeile springen
- `C-f` - Ein Zeichen vorwärts
- `C-b` - Ein Zeichen zurück
- `M-f` - Ein Wort nach vorne
- `M-b` - Ein Wort zurück
- `C-M-n` - Zeile oder Auswahl nach unten schieben
- `C-M-p` - Zeile oder Auswahl nach unten schieben
- `S-M-u` - 10 Zeilen nach oben springen
- `S-M-d` - 10 Zeilen nach unten springen

## Löschen

- `C-h` - Vorangegangenes Zeichen löschen
- `C-d` - Nächstes Zeichen löschen

## Fortgeschrittene Funktionen des Editors

- `C-i` - Dokumentation für das Wort unter dem Cursor anzeigen
- `M-z` - Rückgängig (“Undo”)
- `S-M-z` - Wiederholen (“Redo”)
- `C-k` - Alle Zeichen vom Cursor bis zum Zeilenende löschen
- `C-g` - Escape
- `S-M-f` - Vollbildmodus ein-/ausschalten
- `S-M-b` - Buttons ein-/ausschalten
- `S-M-l` - Protokollfenster ein-/ausschalten
- `S-M-m` - Dunkle Benutzeroberfläche ein-/ausschalten

# 10.3 - Teilen

In Sonic Pi geht es vor allen Dingen um das Teilen und gemeinsame Lernen.

Sobald Du gelernt hast, Musik zu programmieren, kannst Du Deine Kompositionen ganz leicht mit anderen teilen: Schicke Deinen Code einfach mit einer Email an Deine Freunde.

Ich möchte Dich ermuntern, Deinen Code mit anderen zu teilen, so dass sie von Deiner Arbeit lernen und Teile davon in neuen Mash-Ups verwenden können.

Du hast keine Ahnung, wo Du Deine Werke am besten mit anderen teilen kannst? Ich empfehle Dir für Deinen Code GitHub und für Deine Musik SoundCloud. So erreichst Du schnell ein großes Publikum.

## Code -> GitHub

GitHub wird von professionellen Entwicklern und auch Künstlern verwendet, um Code zu teilen und zusammenzuarbeiten. Auf GitHub gibt es einen eigenen Bereich namens Gist, damit kann man besonders einfach ein neues Stück Code (egal ob fertig oder nicht) veröffentlichen. Mit einem Gist können dann auch andere Deinen Code übernehmen, kommentieren und verbessern.

## Audio -> SoundCloud

Statt Code kannst Du auch eine Musikaufnahme veröffentlichen und dafür eine Audiodatei zu SoundCloud hochladen. Dort können andere Nutzer Kommentare dazu abgeben und die Musik diskutieren. Es ist empfehlenswert, bei einer Veröffentlichung auf Soundcloud zusätzlich einen Link zu einem Gist mit Deinen Code in die Beschreibung aufzunehmen.

Um Dein Stück aufzunehmen, drücke den `Aufnehmen`-Knopf in der Werkzeugleiste, die Aufnahme startet dann sofort. Drücke `Ausführen`, um Deinen Code zu starten, wenn er nicht bereits läuft. Wenn Du fertig bist, drücke den den blinkenden `Aufnehmen`-Knopf erneut. Du wirst dann nach einem Dateinamen gefragt, unter dem die Aufnahme als WAV-Datei gespeichert wird. Es gibt viele Werkzeuge, um eine WAV-Datei in ein MP3 zu wandeln, z.B. das Programm Audacity.

## Hoffnung

Ich möchte Dich ermuntern, Deine Arbeiten zu teilen, und hoffe sehr, dass wir uns gegenseitig neue Sonic-Pi-Tipps und -Tricks beibringen werden. Ich bin schon sehr gespannt darauf, was Du mir zeigen wirst.

# 10.4 - Auftritte

Einer der aufregendsten Aspekte von Sonic Pi ist, dass Du von nun an Code als Musikinstrument verwenden kannst. Vor Publikum zu programmieren wird damit ein neuer Weg, um Musik aufzuführen.

Das nennen wir Live-Coding.

## Zeig Deinen Bildschirm

Wenn Du live programmierst, empfehle ich Dir, Deinem Publikum Deinen Bildschirm zu zeigen. Beim Gitarrespielen versteckst Du ja auch nicht Deine Finger und die Saiten Deines Instruments. Wenn ich zu Hause übe, verwende ich einen Raspberry Pi und projiziere den Bildschirm mit einem kleinen Beamer an meine Wohnzimmerwand. Du könntest auch Deinen Fernseher oder einen Projektor in der Schule/Arbeit verwenden und eine kleine Show geben. Versuch es, das macht eine Menge Spaß.

## Gründe eine Band

Spiele nicht nur alleine - gründe eine Live-Coding-Band! Mit anderen zu jammen macht großen Spaß. Einer könnte die Beats programmieren, ein anderer flächige Hintergrundklänge und so weiter. Probiert aus, welche interessanten Klangkombinationen Ihr finden könnt.

## TOPLAP

Live-Coding ist nicht wirklich neu - eine kleine Gruppe von Enthusiasten macht das schon seit Jahren, typischerweise mit selbstgebauten, individuellen Systemen.

Bei TOPLAP erfährst Du mehr über diese anderen Live-Coder und ihre Geräte.

## Algorave

Einige Live-Coder spielen auch in Nightclubs. Mehr über dieses spezielle Genre erfährst Du auf Algorave.

# 11 - Minecraft Pi

Raspbian, das Linux-Betriebssystem für Raspberry Pi, bringt eine spezielle Version von Minecraft als Teil der Vorinstallation mit. Und mit Sonic Pi kannst Du über eine einfache API jetzt auch Minecraft Pi steuern.

## Keine Bibliotheken notwendig

Die Verbindung zwischen Minecraft Pi und Sonic Pi ist so einfach zu nutzen, dass Du nichts dafür vorbereiten musst. Starte einfach Minecraft Pi und baue eine Welt. Du kannst sofort die `mc_*`-Funktionen in Deinem Code genau wie `play` oder `synth` einsetzen. Es gibt nichts zu installieren und keine Bibliotheken zu importieren - alles ist fix und fertig und sofort startklar für Dich.

## Automatische Verbindung

Die Minecraft-Pi-API kümmert sich automatisch um die Verbindung zur laufenden Minecraft-Pi-Applikation. Du musst also nichts dafür tun. Sonic Pi wird sich allerdings freundlich beschweren, wenn Du die API benutzen möchtest und Minecraft Pi nicht gleichzeitig läuft. Und falls Du die Minecraft-Pi-Applikation beendest, während Dein Code die API in einem `live_loop` ansprechen will, wird der Loop beendet und Du erhältst eine entsprechende Fehlermeldung. Starte dann Minecraft Pi wieder neu, die API wird sich von selbst damit verbinden und Dein Code funktioniert wieder.

## Gemacht für Live-Coding

Die Minecraft-Pi-API ist dazu da, dass sie problemlos in in einem `live_loop` funktioniert. Das heißt, Du kannst damit Veränderungen in Deiner Minecraft-Welt mit Veränderungen in Deinen Sonic-Pi-Sounds synchronisieren. Zack, Minecraft-basierte Musik-Videos! Bedenke aber, dass Minecraft Pi eine Alpha-Version ist und die Software ein paar kleinere Bugs hat. Wenn ein solches Problem mit Minecraft Pi auftritt, starte es einfach neu. Sonic Pi nimmt dann automatisch eine neue Verbindung über seine API auf.

## Raspberry Pi 2 empfohlen

Minecraft Pi und Sonic Pi mit seinen Sound-Möglichkeiten sind beides sehr rechenintensive Programme. Der alte Raspberry ist davon schnell überfordert und ein Raspberry Pi 2 mit seinem schnelleren Prozessor deshalb sehr zu empfehlen!

## API-Support

Zur Zeit kann Sonic Pi einige Grundfunktionen zur Manipulation von Minecraft-Blöcken und dem Spieler ausführen. Details dazu findest Du im nächsten Abschnitt 11.1. Für ein späteres Release plane ich, auch Event-Callbacks aus Minecraft Pi zu unterstützen, so dass der Code in Sonic Pi von Ereignissen erfahren kann, die der Spieler in Minecraft Pi ausgelöst hat.

# 11.1 - Grundfunktionen der Minecraft-Pi-API

Folgende Aktionen kannst Du mit der API von Sonic Pi aus in Minecraft Pi auslösen:

- Anzeige von Chat-Nachrichten
- die Spielerposition setzen
- die Spielerposition auslesen
- den Typ eines Minecraft-Blocks an einer Koordinate setzen
- den Typ eines Minecraft-Blocks an einer Koordinate auslesen

Schauen wir uns diese der Reihe nach an.

## Anzeige von Chat-Nachrichten

Ich zeige Dir mal, wie einfach es ist, von Sonic Pi aus die Kontrolle über Minecraft Pi zu übernehmen. Starte also zunächst Sonic Pi und Minecraft Pi und betrete eine Minecraft-Welt, in der Du herumlaufen kannst.

Jetzt schreibe folgenden Code in einem leeren Buffer von Sonic Pi :

    mc_message "Hallo, hier ist Sonic Pi"

Führe den Code aus und Du wirst die Nachricht im Minecraft-Fenster aufblitzen sehen. Gratuliere, das ist Dein erster Minecraft-Code! War doch gar nicht schwer, oder?

## Die Spielerposition setzen

Und jetzt zaubern wir ein wenig. Teleportiere Dich einfach, wohin Du willst! Probiere das hier aus:

    mc_teleport 50, 50, 50

Nach Klick auf Ausführen - Paff! - bist Du sofort an einem anderen Ort in Deiner Minecraft-Welt. Vermutlich irgendwie hoch oben in der Luft und Du bist aufs Land oder Wasser herunter gefallen. Was bedeuten diese Zahlen: `50, 50, 50`? Das sind die Koordinaten der Zielposition für den Teleport. Probiere jetzt in Deinem Code ein paar Koordinaten aus, damit Du weißt, wie sie funktionieren. Koordinaten sind für Minecraft-Programme sehr sehr wichtig.

## Koordinaten

Stelle Dir eine alte Piraten-Schatzkarte vor - beim großen `X` ist der Schatz vergraben. Die genaue Position des `X` lässt sich mit zwei Zahlen beschreiben - wie weit ist das Kreuz horizontal vom Papierrand entfernt und wie weit vertikal. Angenommen, es ist `10cm` vom linken Rand und `8cm` vom unteren Rand entfernt. Diese beiden Zahlen `10` und `8` sind Koordinaten. Auch andere vergrabene Schätze auf der Karte lassen sich mit ihrem jeweiligen Koordinaten-Zahlenpaar genau beschreiben. Etwa die große Goldkiste bei `2` von links und `9` von unten…

In Minecraft Pi reichen zwei Zahlen nicht mehr aus. Wir brauchen auch eine Höhenangabe und damit besteht eine Koordinate in Minecraft aus drei Zahlen:

- Wie weit von rechts nach links innerhalb der Welt - `x`
- Wie weit von vorn nach hinten innerhalb der Welt - `z`
- Wie hoch vom Boden aus innerhalb der Welt - `y`

Diese Minecraft-Koordinaten schreiben wir dann in der Reihenfolge `x`, `y`, `z` auf.

## Wo befindest Du Dich?

Spielen wir also ein wenig mit den Koordinaten herum. Bewege Dich in Minecraft Pi an einen schönen Ort und wechsele dann zu Sonic Pi. Nun führe folgenden Code aus:

    puts mc_location

Drücke Ausführen und im Log erscheinen die Koordinaten, an denen Du Dich in Minecraft befindest. Merke sie Dir, bewege Dich in Minecraft ein wenig weiter und führe den Code noch einmal aus. Hast Du gesehen, wie sich die Koordinaten geändert haben? Probiere das noch ein bisschen aus, damit Du ein Gefühl dafür bekommst, wie sich die Koordinaten mit Deiner Bewegung in der Minecraft-Welt verändern. Wenn Du erst einmal verstanden hast, wie Koordinaten funktionieren, wird das Programmieren mit der Minecraft-Pi-API ganz einfach.

## Lass uns etwas bauen!

Jetzt weißt Du, wie Du Deine Position auslesen und Dich an beliebige Stellen teleportieren kannst. Als nächstes können wir mit Code Dinge in Minecraft bauen. Zum Beispiel ein Block aus Glas an Koordinate `40, 50, 60`, das geht ganz einfach:

    mc_set_block :glass, 40, 50, 60

Haha, das war ja wirklich ganz einfach. Nach getaner Arbeit springst Du schnell in die Nähe und schaust Dir das Ergebnis an:

    mc_teleport 35, 50, 60

Dreh Dich ein wenig und Du wirst Deinen Glasblock sehen! Ändern wir kurz das Material und machen einen Block aus Diamant daraus:

    mc_set_block :diamond, 40, 50, 60

Wenn Du in die richtige Richtung schaust, konntest Du eben sogar dabei zusehen, wie sich der Block verändert. Hier geschieht etwas aufregendes…

## Blöcke ansehen

Du kannst Minecraft Pi auch fragen, welcher Typ Block sich an einer Koordinate befindet. Der folgende Code tut dies für den Diamantblock, den Du gerade gebaut hast:

    puts mc_get_block 40, 50, 60

Yay! Es ist `:diamond`. Ändere das Material des Blocks wieder zu Glas und lese den Typ noch einmal aus - meldet der Code jetzt `:glass` zurück? Ich bin sicher, dass er das tut. :-)

## Mögliche Materialtypen in Minecraft

Bevor Du jetzt mit Code durch Minecraft Pi tobst, hier noch eine praktische Liste aller Material-Typen für Minecraft-Blöcke:

        :air
        :stone
        :grass
        :dirt
        :cobblestone
        :wood_plank
        :sapling
        :bedrock
        :water_flowing
        :water
        :water_stationary
        :lava_flowing
        :lava
        :lava_stationary
        :sand
        :gravel
        :gold_ore
        :iron_ore
        :coal_ore
        :wood
        :leaves
        :glass
        :lapis
        :lapis_lazuli_block
        :sandstone
        :bed
        :cobweb
        :grass_tall
        :flower_yellow
        :flower_cyan
        :mushroom_brown
        :mushroom_red
        :gold_block
        :gold
        :iron_block
        :iron
        :stone_slab_double
        :stone_slab
        :brick
        :brick_block
        :tnt
        :bookshelf
        :moss_stone
        :obsidian
        :torch
        :fire
        :stairs_wood
        :chest
        :diamond_ore
        :diamond_block
        :diamond
        :crafting_table
        :farmland
        :furnace_inactive
        :furnace_active
        :door_wood
        :ladder
        :stairs_cobblestone
        :door_iron
        :redstone_ore
        :snow
        :ice
        :snow_block
        :cactus
        :clay
        :sugar_cane
        :fence
        :glowstone_block
        :bedrock_invisible
        :stone_brick
        :glass_pane
        :melon
        :fence_gate
        :glowing_obsidian
        :nether_reactor_core

# 12 - Abschluss

Damit bist Du am Ende des Tutorials von Sonic Pi angekommen. Hoffentlich hast Du etwas dabei gelernt. Falls Du das Gefühl hast, nicht alles verstanden zu haben - keine Angst, spiele einfach weiter und hab Spaß dabei. Dann wird immer mehr hängenbleiben. Und greife einfach auf das Tutorial zurück, wenn Du eine Frage hast, die vielleicht in einem der vorherigen Kapitel behandelt wurde.

Sind noch Fragen übrig, die über die Einführung hinausgehen? Du kannst damit ins Sonic Pi Forum kommen und Dein Anliegen dort beschreiben. Dort sind viele nette Menschen, die Dir gerne weiterhelfen.

Du bist auch eingeladen, Dir den Rest der Dokumentation im Hilfe-System genauer anzuschauen. Es gibt noch eine Reihe von Features, die in dieser Einführung nicht behandelt wurden und darauf warten, von Dir entdeckt zu werden.

Also: Spiele herum, hab Spaß, teile Deinen Code, tritt vor Freunden auf, zeige was Du auf dem Monitor hast und nicht vergessen:

There are no mistakes, only opportunities. (Es gibt keine Fehler, nur Möglichkeiten.)

Sam Aaron