# Threads

(“Thread” = terme technique intraduisible et dont la traduction la plus proche est “fil”.) Ainsi vous avez fait votre ligne de basse géniale et un super motif de batterie. Comment les jouer en même temps ? Une solution est de les intercaler manuellement - jouer un peu de basse, puis quelques sons de batterie, puis encore un peu de basse… Cependant, la synchronisation devient rapidement dure à concevoir, en particulier quand vous commencez à intercaler plus d’éléments.

Et si Sonic Pi pouvait vous synchroniser les choses automatiquement ? Eh bien, il le peut, et ça se fait avec une chose spéciale appelée thread.

## Boucles infinies

Pour garder cet exemple simple, vous devez imaginer que ceci est un super motif de batterie et une ligne de basse géniale :

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

Comme nous en avons parlé précédemment, les boucles sont comme des trous noirs pour un programme. Dès que vous êtes entré dans une boucle, vous ne pouvez jamais en sortir à moins de presser stop. Comment pouvons-nous jouer les deux boucles en même temps ? Nous devons dire à Sonic Pi que nous voulons démarrer quelque chose en même temps que le reste du code. C’est là que les threads arrivent à la rescousse.

## Threads à la rescousse

    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

En encadrant la première boucle dans un bloc do/end `in_thread`, nous disons à Sonic Pi d’exécuter le contenu du bloc do/end exactement en même temps que l’ordre suivant le bloc do/end (qui se trouve être la seconde boucle). Essayez-le et vous entendrez à la fois la batterie et la ligne de basse synchronisées !

Maintenant, que faire si nous voulons ajouter un synthé par-dessus. Quelque chose comme :

    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

Maintenant, nous avons le même problème qu’avant. La première boucle est jouée en même temps que la seconde grâce au `in_thread`. Toutefois, la troisième boucle n’est jamais atteinte. Nous avons donc besoin d’un nouveau 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

## Les exécutions sont des threads

Ce qui peut vous surprendre est que quand vous pressez le bouton Run, vous êtes réellement en train de créer un nouveau thread pour l’exécution du code. C’est pour cela qu’en le pressant de multiples fois, vous superposerez des couches de sons les unes sur les autres. Comme les “runs” sont eux-même des threads, ils intercaleront les sons automatiquement pour vous.

## Portée

Etudiant comment maîtriser Sonic Pi, vous apprendrez que les threads sont les composants les plus importants de votre musique. L’une des responsabilités importantes qu’ils ont est d’isoler la notion de paramètres courants vis à vis des autres threads. Qu’est-ce que cela signifie ? Eh bien, quand vous commutez les synthés avec `use_synth`, vous ne commutez réellement que le synthé dans le thread courant - aucun autre thread n’aura son synthé commuté. Voyons cela en action :

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

Avez-vous remarqué que le son du milieu était différent des autres ? L’ordre `use_synth` affecte uniquement le thread dans lequel il était et pas le thread extérieur principal.

## Héritage

Quand vous créez un nouveau thread avec `in_thread`, le nouveau thread hérite automatiquement de tous les paramètres courants du thread courant. Voyons cela :

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

Notez que la seconde note est jouée avec le synthé `:tb303` bien qu’elle soit jouée depuis un thread distinct. Chacun des paramètres modifiés avec les différentes fonctions `use_*` se comportera exactement de la même manière.

Quand les threads sont créés, ils héritent de tous les paramètres de leur parent mais par la suite ils ne partagent plus aucun changement avec leur parent.

## Nommage des threads

Enfin nous pouvons donner des noms à nos threads :

    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

Regardez le panneau “trace” quand vous exécutez ce code. Voyez-vous comment la “trace” rapporte le nom du thread avec le message ?

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

## Seulement un thread autorisé par nom

Une dernière chose à savoir au sujet des threads nommés est que seul un thread d’un nom donné peut être en cours d’exécution au même moment. Explorons ceci. Considérez le code suivant :

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

Allez-y et collez cela dans un tampon puis pressez le bouton “Exécuter”. Pressez-le encore quelques fois. Écoutez la cacophonie des breaks amen multiples qui bouclent les uns sur les autres de façon désynchronisée. D’accord, vous pouvez maintenant presser “Arrêter”.

C’est le comportement que nous avons vu encore et encore - si vous pressez le bouton “Run”, le son s’étend au dessus de tout son existant. Donc, si vous avez une boucle et que vous pressez le bouton “Run” trois fois, vous aurez trois couches de boucles jouant simultanément.

Cependant, avec les threads nommés, c’est différent :

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

Essayez de presser le bouton “Run” plusieurs fois avec ce code. Vous n’entendrez qu’une boucle du break amen. Vous allez aussi voir ceci dans la trace :

    ==> Sautant la création d'un thread : le thread avec le nom :amen existe déjà.

Sonic Pi vous dit qu’un thread avec le nom `:amen` est déjà en train d’être joué, donc il ne va pas en créer un autre.

Ce comportement peut ne pas vous sembler utile immédiatement - mais il sera très pratique quand nous commencerons à coder en “live”…