Pit Stop 2

Funzioni, arg, var. Un riassunto sintattico

Creiamo un blocco di codice e immaginiamo che lo spazio al suo interno sia città in cui ci troviamo.

(
// Citta' attuale
)  

All’interno di questo blocco di codice scriviamo una funzione e immaginiamo che lo spazio al suo interno sia l’edificio dove ci troviamo.

(
{ "Questo edificio" }
)    

E’ la prima volta che visitiamo questa città e non ne conosciamo la toponomastica. Se usciamo dall’edificio dobbiamo pensare a un modo per poterlo ritrovare. Gli diamo un nome, un indirizzo, un’etichetta. In termini informatici "lo assegnamo a una variabile". Globale.

(
a = { "Questo edificio" }
)    

Ora sappiamo che l’edificio in questione si chiama a o meglio è situato in uno spazio che ha come indirizzo la lettera a. All’interno dell’edificio ci sono quattro stanze. Vuote. Così come abbiamo fatto per l’edificio stesso, assegnamo un nome diverso ad ogni stanza per poterci orientare tra i diversi vani interni. In termini informatici "assegnamo una variabile locale" ad ogni stanza.

(
a = {var stanza1, stanza2, stanza3, stanza4;}
)

Ora possiamo ritrovare ogni singolo vano all’interno dell’edificio e volendo, possiamo collegarli tra loro o mettere e togliere qualsiasi cosa all’interno delle singole stanze.

(
a = {var stanza1, stanza2, stanza3, stanza4;
         stanza1 = SinOsc.ar;     // mettiamo un oscillatore sinusoidale nella stanza chiamata ''stanza1''
         stanza2 = WhiteNoise.ar; // mettiamo un generatore di rumore bianco nella stanza chiamata ''stanza2''
         stanza3 = 123;           // mettiamo il numero 123 nella stanza chiamata ''stanza3''

         [stanza1,stanza2,stanza3].postln
     }.value
)    

Avendo identificato tutti i luoghi con indirizzi, possiamo ora inviare messaggi e comandi ovunque, semplicemente specificandone l’indirizzo. Prima però dobbiamo trasformare le variabili locali in argomenti.

(
a = {arg stanza1 = SinOsc.ar,
         stanza2 = WhiteNoise.ar,
         stanza3 = 123;

         [stanza1,stanza2,stanza3].postln
     }
)    

Dopodichè possiamo sia inviare un messaggio a tutto l’edificio:

a.value;  

Che messaggi differenti alle singole stanze:

a.value(450, "ciao", SinOsc.ar);
a.value;
a.value(\vado, "al", 'mare');
a.value;
b = a.value(\vado, "al", 'mare');
b.value;
a.value;

Eseguendo in successione le righe precedenti notiamo che in realtà il "contenuto" delle stanze cambia solo temporaneamente, quando lo specifichiamo, in quanto ogni volta che richiamiamo la variabile a il codice al suo interno viene rieseguito riga dopo riga, dall’alto al basso, riassegnando agli argomenti i valori di default. Questa è anche la ragione per la quale quando abbiamo modificato le variabili in argomenti non le abbiamo prima dichiarate e poi riempite ma abbiamo fatto tutto assieme. Se non specifichiamo alcun valore di default Super Coliider assumerà nil.

Clock

SystemClock

(                                           // tempo in secondi
t = SystemClock.sched(3.0,                  // ritardo iniziale
	                 {"trigger".postln; // azione
	                  0.5}              // tempo delta tra le valutazioni della funzione
                      )                     
)                                           
t.clear; // Distrugge il SystemClck

// Beat irregolare:
(
t = SystemClock;
t.sched(2.0,                     // 2 secondi di attesa
           {"nota".postln;       // azione
           rrand(0.2,1).postln}  // tempo delta variabile
       )
)
t.clear;

// Tempo delta 'nil' = 1 sola valutazione
SystemClock.sched( 20.0, {"nota".postln; nil} )

// Tempo trascorso dal lancio di SuperCollider (secondi)
Main.elapsedTime;

// Oppure
(
SystemClock.schedAbs(0, {arg ...args;
                         args.postln;
                         0.5}
	              )
)

TempoClock

(                      // tempo in beat
t = TempoClock.new(1); // crea un'istanza di TempoClock con il beat a 1 bps = 60 bpm
t.sched(1.0,
           {"nota".postln;
            1 }         // tempo delta in beats non secondi!
       )
)
t.tempo_(2);           // modifica il tempo: 1 = 2 bps (120 bpm)
t.tempo = 5;           // altra scrittura...
t.clear;               // distrugge il TempoClock

// Se vogliamo specificare i tempi in millisecondi:
t = TempoClock(1000);
t.sched(1000.0, {"nota".postln; 200})
t.clear;

// Se vogliamo specificare i tempi in bpm:
b = 120;                       // bpm
t = TempoClock(b/60);          // bpm --> bps
t.sched(0, {"nota".postln; 2}) // 0.5 beat (1/2 beat)
t.clear;

// Se vogliamo specificare un tempo di default:
TempoClock.default.tempo_(1);

// Monitoraggio del tempo (cronometro)
(
t = TempoClock(2);
t.schedAbs(0, {arg ...args; // recupera tutti gli argomenti.
               args.postln; // li stampa
               1.0 })       // tempo di campionamento del tempo                        
)
t.clear;

// Singole informazioni da trigger
t = TempoClock(0.5);
t.elapsedBeats;       // che numero di beat siamo
t.elapsedBeats.ceil;  // il prossimo beat
t.elapsedBeats.floor; // il beat precedente

AppClock

E’ un Clock a bassa priorità del tutto simile a SystemClock da utilizzare quando vogliamo generare oggetti grafici dinamici. In taluni casi possiamo ovviare al suo utilizzo invocando su una funzione il metodo .defer.

Routine

(
d = SystemClock;      // definiamo un Metronomo (Clock)
r = Routine({         // definiamo una Routine
             0.5.yield;
             "trig_1".postln;
             2.yield;
             "trig_2".postln;
             2.yield;
             "trig_3".postln;
             2.yield;
             "trig_4".postln;
             });
)

r.play(d);       // eseguiamo
r.stop;          // stoppiamo prima che finisca
r.reset.play(d); // eseguiamo nuovamente da capo

//=====================================================================

// {}.fork(t)
(
b = 52;
t = TempoClock(b/60);
r = {"trigger_1".postln; 1.wait;
     "trigger_2".postln; 1.wait;
     "trigger_3".postln; 1.wait;
     "trigger_4".postln; 1.wait;
     "trigger_5".postln; 1.wait;
     "trigger_6".postln;
}.fork(t)
)
r.stop; 

Task

(
b = 52;
t = TempoClock(b/60);
r = Task({"trigger_1".postln; 1.wait;
          "trigger_2".postln; 1.wait;
          "trigger_3".postln; 1.wait;
          "trigger_4".postln; 1.wait;
          "trigger_5".postln; 1.wait;
          "trigger_6".postln; 1.wait;
          "trigger_7".postln; 1.wait;
          "trigger_8".postln; 1.wait;
          "trigger_9".postln;
})
)

r.play(t);
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

Nesting

                                 10.0;                 // un numero   
                            rand(10.0);                // random    
                       dup({rand(10.0)}, 8);           // replica
                  sort(dup({rand(10.0)}, 8));          // ordina
            round(sort(dup({rand(10.0)}, 8)), 0.01);   // arrotonda
     postln(round(sort(dup({rand(10.0)}, 8)), 0.01));  // stampa
plot(postln(round(sort(dup({rand(10.0)}, 8)), 0.01))); // plot

//=====================================================================

10.0;                                                  // un numero
10.0.rand;                                             // random
10.0.rand.round(0.01);                                 // arrotonda
{10.0.rand.round(0.01)}.dup(8);                        // replica
{10.0.rand.round(0.01)}.dup(8).sort;                   // ordina
{10.0.rand.round(0.01)}.dup(8).sort.postln;            // stampa
{10.0.rand.round(0.01)}.dup(8).sort.postln.plot;       // plot

//=====================================================================

(
var nelementi,range,valori,lista,ordina,semplifica;

    nelementi  = 8;             // variabili locali (input)
    range      = 100.0; 
    
    valori     = {rand(range)}; // algoritmo
    lista      = dup(valori, nelementi);
    ordina     = sort(lista);
    semplifica = round(ordina,0.01);
    
                                // risultati (output)
semplifica.postln;              // stampa
semplifica.plot;                // visualizza
)