Home

Sequencing e Pattern¶

Indice¶

  • Controllo del tempo
    • Routine
    • Task
  • Clocks
    • SystemClock
    • TempoClock
    • AppoClock
  • Sequencing
    • Sequenza
    • Iterazione
    • Selezione
    • Collezioni
  • Partiture informatiche
  • Pattern
    • Pbind
    • Pn
    • Pwhite
    • Pseq

Controllo del tempo ¶

Esecuzione di un blocco di codice $\rightarrow$ linea dopo linea alla massima velocità.

In [ ]:
(
"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.

In [ ]:
(
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

No description has been provided for this image

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

No description has been provided for this image

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.

In [ ]:
(
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.

In [ ]:
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.

In [ ]:
(
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.
In [ ]:
(
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:

SystemClock ¶

  • Di default.
  • Alta priorità.
  • Agisce in un thread separato rispetto a quello principale.
  • Tempi assoluti in secondi.
In [ ]:
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).
In [ ]:
~bpm = 82;

TempoClock(bpm/60); // bps = bpm/60
  • Esempio di conversioni temporali.
    No description has been provided for this image
        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.
In [ ]:
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.
In [ ]:
(
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.

In [ ]:
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).

In [ ]:
(
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.

In [ ]:
10.do({"ciao".postln})    // valuta 10 volte il contenuto della funzione

Musicalmente possiamo definire accordi come arpeggi velocissimi.

In [ ]:
(
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.

In [ ]:
(
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

In [ ]:
(
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.

In [ ]:
(
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.

In [ ]:
(
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.

In [ ]:
(
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)

In [ ]:
(
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.)

No description has been provided for this image
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.
In [ ]:
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

In [ ]:
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.

In [ ]:
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.

In [ ]:
//   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:

In [ ]:
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.

In [ ]:
(
~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.

In [ ]:
(
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.

In [ ]:
(
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.

In [ ]:
(
~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

No description has been provided for this image
In [ ]:
(
~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.

In [ ]:
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.

In [ ]:
(
~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.

In [ ]:
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.

In [ ]:
Pbind().play;

Definire i parametri.

Selezioniamo un Synth diverso da quello di default (uno di quelli definiti in precedenza).

In [ ]:
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.

In [ ]:
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

In [ ]:
(
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; 

Pwhite ¶

Generatore di valori pseudocasuali.

Distribuzione lineare tra min e max

In [ ]:
(
Pbind(\freq, Pwhite(60,72).midicps,
	  \dur,  Pwhite(0.1,0.6)).play;
)

Pseq ¶

Se vogliamo sequenze deterministiche.

Pattern con ripetizioni infinite.

In [ ]:
(
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.

In [ ]:
(
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.

In [ ]:
(
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().

In [ ]:
(
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;
)