# Threads

Nun hast du also eine Killer-Basslinie und einen krassen Beat gebaut. Wie kannst du beide zur selben Zeit spielen lassen? Eine Möglichkeit ist, beide Sounds per Hand miteinander zu verweben - spiele erst den Bass ein bisschen, dann das Schlagzeug, dann den Bass etwas mehr… Beides zeitlich aufeinander abzustimmen wird jedoch gedanklich bald immer schwieriger, vor allem, wenn noch mehr Klänge dazukommen sollen.

Was, wenn Sonic Pi Klänge automatisch für dich miteinander verweben könnte? Nun, das kann es, und zwar erreichst du das mit einem besonderen Ding, welches Thread (Strang) genannt wird.

## Unendliche Schleifen

Damit dieses 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, 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 auf Stopp 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 Reihenfolgen (threads).

## Threads als Rettung

    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

Indem wir die erste Schleife in einen `in_thread`-do/end-Block hinein packen, sagen wir Sonic Pi, es soll den Inhalt dieses do/end-Blocks genau zur selben Zeit wie nächste Anweisung nach dem do/end-Block ausführen (und das ist in diesem Fall die zweite Schleife). Probiere es aus, und du wirst den Beat und die Basslinie miteinander verwoben hören!

Mal angenommen, wir wollten darüber noch einen Synth hinzufügen. 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 wie 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

## Ausführen als Thread

Was dich vielleicht erstaunt: Wenn du auf Ausführen klickst, erzeugst du eigentlich einen neuen Thread, innerhalb dessen der Programm-Code abläuft. Deshalb entstehen immer neue Klangschichten, wenn du wiederholt auf Ausführen klickst. Weil diese Abläufe jeweils für sich Threads sind, werden sie automatisch die Klänge für dich miteinander verweben.

## Bereich

Während du Sonic Pi besser zu meistern lernst, wirst du auch herausfinden, dass Threads die wichtigsten Bausteine für deine Musik sind. Eine der wichtigen Aufgaben die sie ausführen, ist die aktuellen Einstellungen, die für einen Thread gelten, von anderen Threads zu isolieren. Was genau bedeutet das? Nun, wenn du etwa einen Synth mit `use_synth` durch einen anderen ersetzt, dann veränderst du den Synth lediglich für den aktuellen Thread - bei keinem anderen der laufenden Threads wird der Synth ersetzt. Sehen wir uns das mal in Aktion an:

    play 50
    sleep 1
    in_thread do
      use_synth :tb303
      play 50
    end
    sleep 1
    play 50

Bemerke, wie 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, aber nicht auf den äußeren ausführenden Thread.

## Vererbung

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

    use_synth :tb303
    play 50
    sleep 1
    in_thread do
      play 55
    end

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

Wenn neue Threads erzeugt werden, erben sie alle Einstellungen von ihren Eltern. Aber Änderungen der Einstellungen innerhalb dieser neuen Threads haben umgekehrt keinen Einfluss auf die Eltern.

## Threads benennen

Und schließlich können wir unseren Threads auch 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

Achte auf das Protokoll-Fenster, wenn du diesen Code laufen lässt. Siehst du, wie das Protokoll mit den Nachrichten auch die Namen der Threads ausgibt?

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

## Nur ein Thread pro Name erlaubt

Eine letzte Anmerkung zu Threads mit Namen: Es kann nur ein Thread gleichen Namens zur selben Zeit laufen. Probieren wir das aus. Sieh dir folgenden Code an:

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

Kopiere das einmal in einen Puffer und klicke auf `Ausführen`. Klicke noch ein paar mal darauf. Hör dir diese Kakophonie mehrerer Amen-Breaks an, die rhythmisch nicht unbedingt passend zueinander ablaufen. Ok, du kannst jetzt Stopp klicken.

Dieses Verhalten haben wir bereits öfter gesehen - wenn du die `Ausführen`-Schaltfläche klickst, legen sich Klänge über alle bereits laufenden Klänge. Wenn du eine Schleife hast und dreimal auf `Ausführen` klickst, bekommst du drei Ebenen mit Schleifen, die gleichzeitig spielen.

Bei benannten Threads jedoch ist das anders:

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

Versuche bei diesem Code den `Ausführen`-Schalter 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 teilt dir mit, dass ein Thread mit dem Namen `:amen` bereits läuft und es deshalb keinen weiteren erzeugt.

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