Il mese scorso in questa serie abbiamo parlato in modo approfondito della casualità alla base di Sonic pi. Abbiamo capito come poterla sfruttare in modo deterministico per aggiungere nuovi livelli di controllo del nostro codice. Questo mese continueremo questa analisi approfondendo il sistema di tick di Sonic Pi. Alla fine di questo articolo utilizzerai i tick per i tuoi ritmi e nei tuoi riff per diventare un DJ live coder.
Quando facciamo musica spesso vogliamo che accada qualcosa in base al beat in cui ci troviamo. Sonic Pi ha un sistema di conteggio chiamato tick
per avere totale controllo di dove ci troviamo nella battuta e, ovviamente, supporta beat multipli ciascuno col suo tempo.
Diamoci da fare, per avanzare nel beat dobbiamo solo chiamare tick
. Apriamo un buffer vuoto, scriviamo il seguente codice e premiamo su Run:
puts tick #=> 0
Ci verrà restituito il beat corrente, quindi 0
. Nota come anche premendo Run più volte il risultato sarà sempre 0
. Questo perché ad ogni avvio, il beat riparte da 0. Tuttavia, mentre Run è ancora attivo, possiamo avanzare nel beat tutte le volte che vogliamo:
puts tick #=> 0
puts tick #=> 1
puts tick #=> 2
Quando vedi il simbolo #=>
alla fine di una riga vuol dire che quella linea di codice restituirà del testo nel log nella parte destra. Per esempio puts foo #=> 0
significa che il codice puts foo
scriverà 0
nel log.
Abbiamo visto che tick
fa due cose: incrementa di uno il beat e restituisce il valore corrente. A volte vogliamo solo vedere il valore corrente senza incrementalo. Possiamo farlo usando look
:
puts tick #=> 0
puts tick #=> 1
puts look #=> 1
puts look #=> 1
In questo codice usiamo il tick per aumentare la pulsazione due volte e poi usiamo look
, anch’esso due volte. Nel log vedremo questi valori: 0
, 1
, 1
, 1
. I primi due tick restituiscono 0
e 1
come ci aspettiamo i due look
restituiscono l’ultimo valore due volte, ovvero 1
.
Quindi ora possiamo avanzare nel tempo con tick
e controllare il beat con look
. Cosa possiamo fare ancora? Dobbiamo avere qualcosa con cui usare tick. Sonic Pi utilizza gli anelli (ring) per rappresentare i riff, melodie e ritmi e il sistema dei tick è stato pensato per lavorare con essi. Di fatto gli anelli hanno la loro versione di tick
che fa due cose. Innanzitutto funziona come un tick normale e incrementa il beat. In secondo luogo guarda il valore del ring utilizzano il valore del beat come indice. Diamo un’occhiata:
puts (ring :a, :b, :c).tick #=> :a
.tick
è una versione speciale di tick
che ritornerà il primo valore del ring :a
. Possiamo prendere ciascun valore del ring chiamando .tick
più volte:
puts (ring :a, :b, :c).tick #=> :a
puts (ring :a, :b, :c).tick #=> :b
puts (ring :a, :b, :c).tick #=> :c
puts (ring :a, :b, :c).tick #=> :a
puts look #=> 3
Prova a guarda il log e vedrai :a
, :b
, :c
e poi di nuovo :a
. Nota come look
restituisce 3
. Le chiamate a .tick
funzionano come normali chiamate di tick
, incrementano il beat locale.
La vera potenza viene fuori quando utilizziamo tick
con ring e live_loop
. Quando combiniamo queste cose abbiamo tutti gli strumenti per costruite un semplice arpeggiatore. Abbiamo bisogno di quattro cose:
Tutti questi concetti possono essere ritrovati in questo codice:
notes = (ring 57, 62, 55, 59, 64)
live_loop :arp do
use_synth :dpulse
play notes.tick, release: 0.2
sleep 0.125
end
Guardiamo ciascuna linea di codice. Per prima cosa definiamo un ring di note che continuerà a suonare. Dopodiché creiamo un live_loop
chiamato :arp
che continuerà a ripetersi. Ogni volta che si ripete il live_loop
, impostiamo il synth per essere :dpulse
e poi suonando la nota successiva usando .tick
. Ricorda che questo incrementerà il nostro contatore di beat e userà l’ultimo valore di beat come indice nel nostro anello. Alla fine, aspettiamo per 1/8 di beat prima di ricominciare da capo.
Una cosa importante da sapere è che i tick
valgono localmente nel live_loop
. Questo significa che ciascun live_loop
ha il suo contatore beat indipendente. Questa cosa è molto più potente che avere un metronomo globale e un beat. Proviamo a vederlo in azione:
notes = (ring 57, 62, 55, 59, 64)
with_fx :reverb do
live_loop :arp do
use_synth :dpulse
play notes.tick + 12, release: 0.1
sleep 0.125
end
end
live_loop :arp2 do
use_synth :dsaw
play notes.tick - 12, release: 0.2
sleep 0.75
end
Una cosa che causa confusione con il sistema di tick di Sonic Pi è che le persone vogliono utilizzare il tick in più ring nello stesso live_loop
:
use_bpm 300
use_synth :blade
live_loop :foo do
play (ring :e1, :e2, :e3).tick
play (scale :e3, :minor_pentatonic).tick
sleep 1
end
Anche se ciascun live_loop
ha il suo beat counter indipendente, stiamo chiamando .tick
due volte all’interno dello stesso live_loop
. Questo significa che il beat verrà incrementato due volte ogni loop. Questo può generare dei poliritmi interessanti ma spesso non è quello che vogliamo. Ci sono due soluzioni per questo problema. Una è chiamare tick
all’inizio del live_loop
per poi usare .look
per controllare il valore; la seconda è dare un nome a ogni chiamata .tick
come, ad esempio .tick(:foo)
. Sonic Pi creerà e terrà traccia di un contatore di beat per ciascun nome che utilizzerai. In questo modo puoi lavorare con quanti beat tu voglia! Prova a vedere la sezione 9.4 dei tutorial per maggiori informazioni.
Mettiamo insieme tutto quello che abbiamo imparato su tick
, ring
e live_loop
per un ultimo esempio. Come al solito, non trattarlo come un pezzo finito. Prova a cambiare le cose e a giocare con questo codice per vedere cosa riesci a combinare. Alla prossima…
use_bpm 240
notes = (scale :e3, :minor_pentatonic).shuffle
live_loop :foo do
use_synth :blade
with_fx :reverb, reps: 8, room: 1 do
tick
co = (line 70, 130, steps: 32).tick(:cutoff)
play (octs :e3, 3).look, cutoff: co, amp: 2
play notes.look, amp: 4
sleep 1
end
end
live_loop :bar do
tick
sample :bd_ada if (spread 1, 4).look
use_synth :tb303
co = (line 70, 130, steps: 16).look
r = (line 0.1, 0.5, steps: 64).mirror.look
play notes.look, release: r, cutoff: co
sleep 0.5
end