Sequencing e Pattern¶
Controllo del tempo ¶
Esecuzione di un blocco di codice $\rightarrow$ linea dopo linea alla massima velocità.
(
"riga uno -> primo evento".postln;
"riga due -> secondo evento".postln;
"riga tre -> terzo evento".postln;
"riga quattro -> quarto evento".postln;
"riga cinque -> quinto evento".postln;
)
Anche assegnandolo a una funzione (tra partentesi graffe) per poi valutarla successivamente.
(
f = {
"riga uno -> primo evento".postln;
"riga due -> secondo evento".postln;
"riga tre -> terzo evento".postln;
"riga quattro -> quarto evento".postln;
"riga cinque -> quinto evento".postln;
}
)
f.value; // Valuta la funzione
rappresentazione musicale

Possiamo però organizzare sequenze di eventi organizzati nel tempo attraverso la formalizzazione di una partitura informatica.

Routine ¶
Il modo più semplice per farlo è con l'oggetto Routine.new impiegato nella seguente forma sintattica.
Se dopo la prima esecuzione o dopo averla interrotta vogliamo eseguirla nuovamente dobbiamo prima resettarla.
Non possiamo fermare e riprendere le Routine, ogni volta ripartono da capo.
Una Routine ha come primo argomento una funzione.
(
r = Routine({ // definiamo una Routine
0.5.wait;
"trig_1".postln;
1.wait; // Tempo delta
"trig_2".postln;
1.wait;
"trig_3".postln;
1.wait;
"trig_4".postln;
});
)
r.play; // la eseguiamo
r.stop; // la fermiamo
r.reset; // la resettiamo
r.play; // la eseguiamo nuovamente
Sostituiamo gli eventi con suoni.
s.boot;
s.scope;
(
SynthDef(\sperc, {arg freq=440, amp=0, dur=1, pan=0, t_gate=0;
var sig, env;
sig = SinOsc.ar(freq);
env = Env.perc(0.01, dur-0.01);
env = EnvGen.ar(env, t_gate, doneAction: 2);
sig = sig * amp * env;
sig = Pan2.ar(sig, pan);
Out.ar(0, sig)
}).add;
)
(
r = Routine.new({
Synth.new(\sperc, [\freq, rrand(72,90).midicps, \amp, rand(1.0), \pan, rand2(1.0), \t_gate, 1]);
0.1.wait;
Synth.new(\sperc, [\freq, rrand(72,90).midicps, \amp, rand(1.0), \pan, rand2(1.0), \t_gate, 1]);
0.5.wait;
Synth.new(\sperc, [\freq, rrand(72,90).midicps, \amp, rand(1.0), \pan, rand2(1.0), \t_gate, 1]);
0.2.wait;
Synth.new(\sperc, [\freq, rrand(72,90).midicps, \amp, rand(1.0), \pan, rand2(1.0), \t_gate, 1]);
});
)
r.reset.play // concatenate...
Esiste un'abbreviazione sintattica.
(
r = {
Synth.new(\sperc, [\freq, rrand(72,90).midicps, \amp, rand(1.0), \pan, rand2(1.0), \t_gate, 1]);
0.1.wait;
Synth.new(\sperc, [\freq, rrand(72,90).midicps, \amp, rand(1.0), \pan, rand2(1.0), \t_gate, 1]);
0.5.wait;
Synth.new(\sperc, [\freq, rrand(72,90).midicps, \amp, rand(1.0), \pan, rand2(1.0), \t_gate, 1]);
0.2.wait;
Synth.new(\sperc, [\freq, rrand(72,90).midicps, \amp, rand(1.0), \pan, rand2(1.0), \t_gate, 1]);
}.fork
) // suona subito...
r.reset.play
Task ¶
Se vogliamo stoppare una sequenza per poi ripartire dal punto in cui si è interrotta possiamo utilizzare i Task.
Hanno la medesima sintassi delle Routine con limitazioni:
- le operazioni condizoinali non funzionano correttamente
- non possiamo stoppare e riprendere un processo velocemente.
(
r = Task.new({
Synth.new(\sperc, [\freq, 70.midicps, \amp, 0.2, \t_gate, 1]);
1.wait;
Synth.new(\sperc, [\freq, 74.midicps, \amp, 0.2, \t_gate, 1]);
2.wait;
Synth.new(\sperc, [\freq, 77.midicps, \amp, 0.2, \t_gate, 1]);
2.wait;
Synth.new(\sperc, [\freq, 82.midicps, \amp, 0.2, \t_gate, 1]);
});
)
r.play;
r.pause; // pausa
r.resume; // riprende
r.stop; // come pause
r.reset; // resetta all'inizio la prossima volta che viene eseguito
r.start; // riparte da capo
Clocks ¶
I Clocks sono come dei metronomi ai quali si °agganciano° Routine e Task e sono di tre tipi:
s.boot;
s.scope;
(
SynthDef(\sperc, {arg freq=440, amp=0, dur=1, pan=0, t_gate=0;
var sig, env;
sig = SinOsc.ar(freq);
env = Env.perc(0.01, dur-0.01);
env = EnvGen.ar(env, t_gate, doneAction: 2);
sig = sig * amp * env;
sig = Pan2.ar(sig, pan);
Out.ar(0, sig)
}).add;
)
(
t = SystemClock; // Clock
Routine.new({
Synth.new(\sperc, [\amp, 0.5, \t_gate, 1]);
1.wait; // Secondi
Synth.new(\sperc, [\amp, 0.5, \t_gate, 1]);
0.5.wait;
Synth.new(\sperc, [\amp, 0.5, \t_gate, 1]);
0.5.wait;
Synth.new(\sperc, [\amp, 0.5, \t_gate, 1]);
}).play(t); // Argomento di play
)
TempoClock ¶
- Meno preciso del precedente.
- Agisce nel thread principale.
- Tempi relativi in bps (beat per second non bpm).
- Per convertire bps in bpm (tempo metronomico).
~bpm = 82;
TempoClock(bpm/60); // bps = bpm/60
- Esempio di conversioni temporali.
1 = 1000 ms = 1 quarto = 1/1 = 1.0 bps 0.5 = 500 ms = 1 ottavo = 1/2 = 2.0 bps 0.333 = 333 ms = 1 ottavo terzinato = 1/3 = 3.0 bps 0.25 = 250 ms = 1 sedicesimo = 1/4 = 4.0 bps 0.666 = 666 ms = 1 quarto di terzina = 2/3 = 1.5 bps 0.125 = 125 ms = 1 trentaduesimo = 1/8 = 8.0 bps 1.5 = 1500 ms = 1 quarto puntato = 3/2 = 0.6 bps 2 = 2000 ms = 1 metà = 2/1 = 0.5 bps
- Possiamo definire diverse istanze con tempi differenti.
- Possiamo modificare il beat di ogni istanza.
s.boot;
s.scope;
(
SynthDef(\sperc, {arg freq=440, amp=0, dur=1, pan=0, t_gate=0;
var sig, env;
sig = SinOsc.ar(freq);
env = Env.perc(0.01, dur-0.01);
env = EnvGen.ar(env, t_gate, doneAction: 2);
sig = sig * amp * env;
sig = Pan2.ar(sig, pan);
Out.ar(0, sig)
}).add;
)
(
~bpm = 52;
t = TempoClock(~bpm/60);
Routine.new({
Synth.new(\sperc, [\amp, 0.5, \t_gate, 1]);
1.wait; // Beat
Synth.new(\sperc, [\amp, 0.5, \t_gate, 1]);
0.5.wait;
Synth.new(\sperc, [\amp, 0.5, \t_gate, 1]);
0.5.wait;
Synth.new(\sperc, [\amp, 0.5, \t_gate, 1]);
1.wait;
t.tempo_(160/60); // Cambia il beat
Synth.new(\sperc, [\amp, 0.5, \t_gate, 1]);
1.wait;
Synth.new(\sperc, [\amp, 0.5, \t_gate, 1]);
0.5.wait;
Synth.new(\sperc, [\amp, 0.5, \t_gate, 1]);
0.5.wait;
Synth.new(\sperc, [\amp, 0.5, \t_gate, 1]);
}).play(t); // Argomento di play
)
N.B. Le durate dei suoni sono in tempo assoluto e non in beats.
AppClock ¶
- Simile a systemClock.
- Due differenze.
- Agisce nel thread principale.
- Bassa priorità
- Serve quando vogliamo inviare valori a GUI in modo dinamico.
(
t = AppClock;
w = Window("Clock", Rect(100, 100, 100, 100));
b = NumberBox(w, Rect(10, 30, 80, 20));
w.front;
r = Routine.new({
inf.do({
b.value_(rrand(1,15));
0.1.wait;
})
});
)
r.reset.play(t)
r.stop;
Sequencing ¶
Automatizzare attraverso strutture di controllo informatiche l'esecuzione di sequenze ordinate di eventi sonori nel tempo.
Per tutti gli esempi impiegheremo il seguente synth virtuale polifonico.
s.boot;
s.scope;
(
SynthDef(\sperc, {arg freq=440, amp=0, dur=1, pan=0, t_gate=0;
var sig, env;
sig = SinOsc.ar(freq);
env = Env.perc(0.01, dur-0.01);
env = EnvGen.ar(env, t_gate, doneAction: 2);
sig = sig * amp * env;
sig = Pan2.ar(sig, pan);
Out.ar(0, sig)
}).add;
)
Secondo la teoria della programmazione strutturata ci sono tre possibili schemi:
- Sequenza
- Iterazione
- Selezione
Sequenza ¶
Ogni linea di codice corrisponde ad un evento (sonoro o di altro tipo).
(
r = Routine.new({
Synth.new(\sperc, [\freq, 900, \amp, 0.2, \t_gate, 1]);
0.1.wait;
Synth.new(\sperc, [\freq, 800, \amp, 0.8, \t_gate, 1]);
0.5.wait;
Synth.new(\sperc, [\freq, 900, \amp, 0.1, \t_gate, 1]);
0.2.wait;
Synth.new(\sperc, [\freq, 600, \amp, 1.0, \t_gate, 1]);
//...
});
)
r.reset.play;
Utilizzare questa strategia per una partitura informatica può diventare verboso.
Iterazione ¶
Loop (ritornelli informatici) presenti in tutti i linguaggi formali.
Costrutto sintattico n.do({})
Ha come primo argomento una funzione.
10.do({"ciao".postln}) // valuta 10 volte il contenuto della funzione
Musicalmente possiamo definire accordi come arpeggi velocissimi.
(
3.do({
Synth.new(\sperc, [\freq, rrand(600,1200),\amp,0.2,\t_gate,1]);
})
)
Possiamo definire melodie includendoli in Routine come se fossero dei pattern con ritornelli.
(
b = 92;
t = TempoClock(b/60);
r = Routine({
3.do({
Synth.new(\sperc, [\freq, 600,\amp,0.2,\t_gate,1]);
0.5.wait;
Synth.new(\sperc, [\freq, 800,\amp,0.2,\t_gate,1]);
0.25.wait;
Synth.new(\sperc, [\freq, 950,\amp,0.2,\t_gate,1]);
0.25.wait;
})
}).reset.play(t);
)
Se sostituiamo il numero di ripetizioni con la parola chiave inf il loop andrà avanti all'infinito.
Includere almeno un .wait altrimenti $\rightarrow$ crasch
(
b = 92;
t = TempoClock(b/60);
r = Routine({
inf.do({
Synth.new(\sperc, [\freq, 600,\amp,0.2,\t_gate,1]);
0.5.wait;
Synth.new(\sperc, [\freq, 800,\amp,0.2,\t_gate,1]);
0.25.wait;
Synth.new(\sperc, [\freq, 950,\amp,0.2,\t_gate,1]);
0.25.wait;
})
})
)
r.reset.play(t);
r.stop;
Selezione ¶
Operatori condizionali (<, >, ==, !=)
Aritmetica booleiana (true, false, nil)
Se la condizione è vera (o falsa) esegui questa funzione altrimenti...
Tra due opzioni.
(
a = rand(10).postln;
if(a == 3) // condizione
{Synth.new(\sperc, [\freq, 600,\amp,0.2,\t_gate,1]);} // se vero
{Synth.new(\sperc, [\freq, 1600,\amp,0.2,\t_gate,1]);} // se falso (else)
)
Tra diverse opzioni.
(
a = rand(10).postln;
switch(a) // valore da confrontare
{0} {Synth.new(\sperc, [\freq, 80.midicps,\amp,0.2,\t_gate,1])} // se == 0
{1} {Synth.new(\sperc, [\freq, 81.midicps,\amp,0.2,\t_gate,1]);} // se == 1
{5} {Synth.new(\sperc, [\freq, 85.midicps,\amp,0.2,\t_gate,1]);} // se == 5
{7} {Synth.new(\sperc, [\freq, 87.midicps,\amp,0.2,\t_gate,1]);} // se == 7
)
Includendolo in un loop infinito ad esempio una struttura informatica può rappresentare una struttura musicale.
(
r = Routine({
inf.do({
a = rand(10).postln;
switch(a)
{0} {Synth.new(\sperc, [\freq, 80.midicps,\amp,0.2,\t_gate,1])}
{1} {Synth.new(\sperc, [\freq, 81.midicps,\amp,0.2,\t_gate,1])}
{5} {Synth.new(\sperc, [\freq, 85.midicps,\amp,0.2,\t_gate,1])}
{7} {Synth.new(\sperc, [\freq, 87.midicps,\amp,0.2,\t_gate,1])};
0.15.wait;
})
})
)
r.reset.play;
r.stop;
Doppie condizioni (and, or)
(
a = rand(10).postln;
if( (a > 3) && (a < 6) ) // se maggiore di 3 AND minore di 6 (4 o 5)
{"colpito".postln} // se vero
{"mancato".postln} // se falso (else)
)
Collezioni¶
Collezioni indicizzate.
Elementi inclusi tra parentesi graffe e separati da virgole.
Indici sottintesi che partono da 0.
Rappresentano sequenze o insiemi di qualisasi tipo di data (numeri, Synth, Env, GUI, etc.)

Indici 0 1 2 3 4 5 6 7 Elementi [ 1.00, 0.75, 0.25, 0.33, 0.33, 0.33, 0.50, 0.50 ]
Tre tipi:
- Literal array - collezioni bloccate, possiamo:
- richiamare i signoli elementi.
- Array - collezioni variabili, possiamo:
- richiamare i signoli elementi.
- sostituire gli elementi.
- dimensioni bloccate.
- Liste - collezioni dinamiche, possiamo:
- richiamare i signoli elementi.
- sostituire gli elementi.
- dimensioni modificabili.
a = #[1,0.75,0.25,0.33,0.33,0.33,0.5,0.5]; // Literal Array
b = [Env.perc(1), Env.triangle(4), Env.sine(0.5)] // Array
c = List["ciao", "miao", "uao"]; // List
Plot - visualizzazione
a.plot;
b.plot;
c.plot; // errore...
Cliccando su m modifichiamo la modalità di visualizzazione.
Aspetto grafico personalizzabile (guardare Help file).
Due argomenti utili per una lettura più corretta.
a = [[0.1,0.5,0.6,0.1,0.9,0.3], [1,5,2,4,8,10,5,6]]; // Array 2D
a.plot;
a.plot(minval:0,maxval:10);
Possiamo richiamare i singoli elementi attraverso l'indice.
Due sintassi equivalenti.
// 0 1 2 3 4 5 6 7
a = [1.00, 0.75, 0.25, 0.33, 0.33, 0.33, 0.5, 0.5];
a.at(3);
a[5];
a.at(9); // non esiste...riporta nil
a.size; // Riporta il numero di elementi
Se non vogliamo richiamare indici inesistenti $\rightarrow$ tre varianti:
a.clipAt(12); // limiti
a.wrapAt(12); // da capo
a.foldAt(12); // torna indietro
Partiture informatiche ¶
Possiamo rappresentare sequenze di parametri musicali sotto forma di collezioni.
(
~note = [ 60, 62, 63, 67, 69, 65].midicps;
~vels = [ 34, 56, 90, 100, 127, 80]/127;
~pan = [ -1, 1, 0.5,-0.2, 0.4, 0];
~durs = [0.25, 0.25, 1.00, 0.5, 0.5, 2.00];
~delt = [0.25, 0.25, 1.00, 0.5, 0.5, 0.5]; // ultimo elemento nel caso di loop
)
Per poi richiamarli in modo sincronizzato attraverso una caratteristica sintattica degli iteratori.
(
n = ~note.size; // numero di elementi dell'array note
r = Routine.new({
n.do({arg i; // contatore
i.postln; // monitor numerico
Synth.new(\sperc, [\freq, ~note.at(i),
\amp, ~vels.at(i),
\pan, ~pan.at(i),
\dur, ~durs.at(i),
\t_gate,1]);
~delt.at(i).wait;
})
})
)
r.reset.play;
Per un pattern musicale infinito.
(
r = Routine.new({
inf.do({arg i;
i.postln;
Synth.new(\sperc, [\freq, ~note.wrapAt(i),
\amp, ~vels.wrapAt(i),
\pan, ~pan.wrapAt(i),
\dur, ~durs.wrapAt(i),
\t_gate,1]);
~delt.wrapAt(i).wait;
})
})
)
r.reset.play;
r.stop;
Array di lunghezza diversa $\rightarrow$ variazioni musicali procedurali.
(
~bpm = 92;
t = TempoClock(~bpm/60);
~note = [60, 62, 63, 67, 69, 65].midicps;
~vels = [34, 56, 127, 80]/127;
~pan = [-1, 1, 0.5];
~durs = [0.25, 1, 0.5, 0.5, 2];
~delt = [1, 0.5, 0.5, 0.5];
r = Routine.new({
inf.do({arg i;
Synth.new(\sperc, [\freq, ~note.foldAt(i),
\amp, ~vels.wrapAt(i),
\pan, ~pan.foldAt(i),
\dur, ~durs.wrapAt(i),
\t_gate,1]);
~delt.foldAt(i).wait;
})
})
)
r.reset.play(t);
r.stop;
Accordi - Array 2d e nested loops
Gestione delle durate in modo relativo

(
~bpm = 100;
t = TempoClock(~bpm/60);
~tsec = 60/~bpm; // conversione unità da tempo relativo a assoluto
~note = [[90,93], 100, [98,99,102,100], 97, 96, [93,89,87]].midicps;
~vels = [ 60, 90, 70, 90, 80, 70] / 127;
~durs = [ 0.25, 0.25, 1, 1, 1, 1] * ~tsec; // Calcola le durate in modo relativo
~dt = [ 0.25, 0.25, 1, 1, 1, 1]; // Come i tempi delta...
~ns = ~note.size;
r = Routine.new({
~ns.do({arg i;
if(~note[i].isNumber) // se è un numero:
{Synth(\sperc, [\freq, ~note[i], // note singole
\amp, ~vels[i],
\dur, ~durs.[i],
\t_gate, 1])}
// ...se è un Array:
{~note[i].size.do({arg id; // loop (accordi)
Synth(\sperc, [\freq, ~note[i][id],
\amp, ~vels[i],
\dur, ~durs[i],
\t_gate, 1])
})};
~dt[i].wait
})
})
)
r.reset.play(t)
Randomness
Otteniamo valori pseudorandomici attraverso diverse strategie.
rand(12.0); // tra 0 e n-1 (range)
rrand(34, 50); // tra min e max (compresi)
rand2(1.0); // tra +/- range
[12, 34.5, 56].choose; // sceglie un elemento
[12, 34.5, 56].wchoose([0.1,0.7,0.2]); // sceglie un elemento con disstribuzione delle probabilità (0-1)
Formalizziamo diverse situazioni musicali in funzioni per poi richiamarle in sequenza attraverso una Routine dedicata.
(
~bpm = 100;
t = TempoClock(~bpm/60);
~seq_1 = {
Routine.new({
10.do({Synth.new(\sperc, [\freq, 100.midicps,
\amp, rand(0.5),
\pan, [-1, 1].choose,
\dur, 0.1,
\t_gate,1]);
0.1.wait
})
}).play(t)
};
~seq_2 = {var note, vels, pan, durs, delt;
note = [60, 62, 63, 67, 69, 65].midicps;
vels = [34, 56, 127, 80]/127;
pan = [-1, 1, 0.5];
durs = [0.25, 1, 0.5, 0.5, 2];
delt = [1, 0.5, 0.5, 0.5];
r = Routine.new({
inf.do({arg i;
Synth.new(\sperc, [\freq, note.foldAt(i),
\amp, vels.wrapAt(i),
\pan, pan.foldAt(i),
\dur, durs.wrapAt(i),
\t_gate,1]);
delt.foldAt(i).wait;
})
}).play(t)
};
~score = Routine.new({
~seq_2.value;
5.wait;
10.do({
n = rand(2); // 0 - 1
if(n == 1) {~seq_1.value};
rrand(0.5, 3).wait;
});
r.stop;
4.wait;
~seq_1.value;
1.wait;
3.do({
Synth.new(\sperc, [\freq, rrand(70,90).midicps,
\amp, 0.2, \dur, 4, \t_gate,1])
})
});
)
~score.reset.play(t);
Pattern ¶
Libreria di oggetti dedicata al sequencing.
Alternativa a Routine e Task.
Tutti gli oggetti della libreria cominciano con la P maiuscola.
Due strumenti per gi esempi.
s.boot;
s.meter;
s.plotTree;
(
SynthDef(\sperc,
{arg freq=440, amp=0.5, dur=0.5;
var env, osc;
env = Env.perc(0.01, dur-0.01).kr(2,1);
osc = SinOsc.ar(freq, 0, amp.lag(0.02));
Out.ar(0, env*osc)}
).add;
b = Buffer.read(s,Platform.resourceDir +/+ "sounds/a11wlk01.wav"); // Audio file
SynthDef(\samp,
{arg pos=0, dur=1, amp=0.5;
var rata,inizio,fine,env,osc;
rata = SampleRate.ir; // Sample rate
inizio = pos*rata; // punto iniziale in frame
fine = dur*rata+inizio; // punto finale in frame
env = Env.linen(0.01,dur-0.02,0.01).kr(2,1); // Inviluppo trapezoidale
osc = BufRd.ar(1, b.bufnum, Line.ar(inizio,fine,dur),0);
Out.ar(0, env*osc*amp.lag(0.02))}
).add;
)
Pbind ¶
Invia in modo dinamico a un ricevente un messaggio (tipicamente un valore).
Sintassi simile al metodo .set(\chiave, valore) con il quale inviamo i parametri ai Synth.
Se non specifichiamo nulla assume dei valori di default
- Synth
- Altezza
- Tempo delta
- Durata
- Dinamica
- Pan
etc.
Pbind().play;
Definire i parametri.
Selezioniamo un Synth diverso da quello di default (uno di quelli definiti in precedenza).
Synth(\sperc);
(
Pbind(\instrument,\sperc, // specifica il Synth)
\freq, 90.midicps, // frequenze (midinote)
\amp, 64/127, // ampiezze (velocity)
\delta, 0.33 // tempo delta (beats)
).play;
)
Synth(\samp);
(
Pbind(\instrument,\samp, // specifica il Synth)
\pos, 0.76, // posizione puntatore
\dur, 0.1, // durata
\amp, 0.6, // ampiezza
\delta, 0.33 // tempo delta (beats)
).play;
)
Pn ¶
Se vogliamo sequenze finite specifichiamo il numero di eventi.
Pbind(\delta, 0.5 ).play; // Sequenza infinita (\etichetta, valore)
Pbind(\delta, Pn(0.5,4)).play; // Sequenza finita (\etichetta, pattern)
Pbind(\dur, Pn(0.5,inf)).play; // Sequenza infinita (\etichetta, pattern)
Se vogliamo interrompere ina sequenza infinita dal codice $\rightarrow$ Synth custom
(
b = 92;
t = TempoClock(b/60);
p = Pbind(\instrument,\sperc, // Custom Synth
\freq, 678,
\amp, 0.5,
\delta, Pn(0.5,inf)
).play(t);
)
p.stop; t.clear;
(
Pbind(\freq, Pwhite(60,72).midicps,
\dur, Pwhite(0.1,0.6)).play;
)
(
p = Pbind(\instrument, \sperc,
\freq, Pseq(#[60,61,62,63].midicps, inf),
\amp, Pseq(#[34,54,84,104]/127, inf),
).play;
)
p.stop
Array di lunghezza diversa $\rightarrow$ interrompe la sequenza al temine del più corto.
(
Pbind(\instrument, \sperc,
\freq, Pseq(#[60,61,62,63,64,65,66].midicps, 1),
\amp, Pseq(#[34,54,84,104]/127, 1),
).play;
)
(
Pbind(\instrument, \sperc,
\freq, Pseq(#[60,61,62,63].midicps, 2), // 2 ripetizioni
\amp, Pseq(#[34,54,84,104]/127, 1), // 1 ripetizione
).play;
)
(
Pbind(\instrument, \sperc,
\freq, Pseq(#[60,61,62,63,64,65,66,67].midicps, 1), // Termina con la sequenza più lunga
\amp, Pseq(#[34,54,84,104]/127, inf), // keyword inf
).play;
)
Pause e durate - keyword \rest.
(
Pbind(\instrument, \sperc,
\freq, Pseq(#[60,61,\rest,62,63,64,\rest,65,66,67].midicps, 1),
\amp, Pseq(#[34,54,84, 104]/127, inf),
\dur, Pseq(#[0.2,0.5,1, 0.55,0.74,1], inf)
).play;
)
In un contesto non deterministico $\rightarrow$ keyword \type.
Pif() - test eseguito ad ogni passo.
Pfunc() - valuta una funzione.
Pstutter() - accetta una variabile definita con Pkey().
(
Pbind(
\sudd, Pwhite(1,8,inf),
\delta, Pstutter(Pkey(\sudd), 1/Pkey(\sudd)),
\type, Pif(Pfunc({rand(2)==0}),\note,\rest), // nota o pausa
).play;
)