# Threads

Fizeste uma killer bassline e um fat beat. Como os tocar ao mesmo tempo? Uma solução é interligar os dois manualmente - tocar algum baixo, depois um pouco de bateria, e mais algum baixo… No entanto, o tempo torna-se difícil de pensar, especialmente se começares a entrelaçar mais elementos.

E se o Sonic Pi pode-se entrelaçar as coisas por ti automaticamente? Bem, ele pode, e fazes isso com algo chamado thread.

## Loops infinitos

Para manter este exemplo simples, terás que imaginar que isto é um fat beat e uma killer bassline:

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

Como discutimos previamente, loops são buracos negros para o programa. Uma vez neles nunca poderás sair até premires stop. Então como tocar ambos os loops ao mesmo tempo? Teremos que dizer ao Sonic Pi que queremos começar algo ao mesmo tempo que o resto do código. É ai que os threads vêm ao nosso auxilio.

## Threads ao auxilio

    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

Envolvendo o primeiro loop num `in_thread` do bloco do/end dizemos aos Sonic Pi para correr o conteúdo do bloco exactamente ao mesmo tempo que a declaração seguinte ao bloco (que até é o segundo loop). Experimenta e ouvirás a bateria e o baixo entrelaçados.

Agora e se queremos adicionar um synth por cima. Algo como:

    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

Teremos o mesmo problema que anteriormente. O primeiro loop é tocado ao mesmo tempo que o segundo devido ao `in_thread`. No entanto, o terceiro loop nunca é alcançado. Assim necessitamos de outro 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

## Correr como threads

O que te pode supreender é que quando carregas no botão Run, está a criar um novo thread para o código correr. É por isso que carregando múltiplas vezes irá adicionar camadas de som umas sobre as outras. As próprias corridas são threads, elas irão entrelaçar automaticamente os sons por ti.

## Scope

Quando aprenderes a conquistar o Sonic Pi, aprenderas que os threads são o bloco de construção mais importante da tua musica. Um dos importantes trabalhos que fazem é isolar a noção de settings actuais de outros threads. O que significa isso? Bem, quando trocas de synth usando o `use_synth` apenas estás a mudar de sintetizador na thread actual - nenhum outro thread terá a mudança de sintetizador. Vamos ver isto em pratica:

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

Repara como o som do meio foi diferente dos restantes? A declaração `use_synth` apenas afectou o thread onde estava e não o thread principal exterior que corre.

## Herança

Quando crias um novo thread com `in_thread`, o novo thread irá automaticamente herdar todas as settings actuais do thread corrente. Vamos ver isso:

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

Repara como a segunda nota foi tocada com o sintetizador `:tb303` apesar de ter sido tocada de uma thread separada? Todas as settings modificadas com as várias funções `use_*` irão se comportar da mesma maneira.

Quando os threads são criados eles herdam todas as settings dos seus pais mas não passam para eles qualquer mudança que tenham.

## Nomeando threads

Finalmente, podemos dar nomes aos nossos 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

Vê o painel de registro quando corres este código. Vê como o regsitro reporta o nome do thread na mensagem?

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

## Apenas é permitido um Thread por nome

Uma ultima coisa sobre nomear threads é que apenas um thread de um determinado nome pode estar a correr ao mesmo tempo. Vamos explorar isto. Considera o seguinte código:

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

Vamos lá e cola isso num buffer e carrega o butão Run. Carrega-o uma série de vezes. Ouve a cacofonia de vários amen break looping fora de tempo entre eles. Ok, podes carregar o Stop agora.

Este é o comportamento que vemos sempre - se carregares o botão Run, as camadas de som sobrepõem-se às do som existente. Assim se tiveres um loop e carregares o botão Run 3 vezes, terás 3 camadas de loops a correr simultaneamente.

No entanto, com threads com nome é diferente:

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

Experimenta carregar o botão Run 3 vezes com este código. Apenas irás ouvir um amen break loop. Verás também isto no registro:

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

Sonic Pi diz que um thread com o nome `:amen`já está a tocar, e assim não irá criar outro.

Este comportamento pode não ser imediatamente útil para ti por enquanto - mas será muito quando começarmos com o live code…