• Non ci sono risultati.

UGen e UGen-Graph

Nel documento Introduzione a SuperCollider (pagine 145-152)

Introduzione a SuperCollider

1. direttamente In altre parole, sclang-interprete è un buon posto per l’utente da dove parlare al server al livello di quest’ultimo (da dove spedire messag-

5.5 UGen e UGen-Graph

Le UGen sono unità atomiche di elaborazione del segnale. Le UGen pos- sono avere più entrate, ma hanno sempre soltanto un’uscita. Una UGen può ricevere in entrata un’altra UGen: questo processo si chiama patching, e può es- sere tradotto (non letteralmente ma ad sensum) con “innesto”, così come to patch

ro formano uno UGen-graph, un grafo di UGen, una struttura che rende conto delle relazioni tra UGen. Poiché le UGen generano segnali, lo UGen-graph de- scrive il flusso dei segnali che dalle diverse sorgenti si “raccolgono” nel segnale. Altra metafora: lo UGen-graph è la cartina geografica di un fiume che raccoglie contributi di diversi affluenti per poi terminare in mare.

Nella definizione della synthDef "pulseSine", il programma utilizza la for- mattazione e una scrittura inusualmente prolissa per rendere più chiara possibi- le l’organizzazione del patching. Nell’esempio, le righe 2-11 descrivono il grafo delle UGen con un esempio di patching tra (Out, SinOsc, LFPulse). Si osservi come quest’ultima (un generatore di onde quadre) aggiorni i propri valori ri- calcolando il valore in uscita a tasso di controllo, secondo quanto previsto dal messaggio kr inviato a LFPulse.

È opportuno ora soffermarsi di più su una UGen, in particolare su SinOsc. Per sapere come si comporta ci si può evidentemente rivolgere all’help file rela- tivo. Un’altra opzione, utile in fase di studio almeno, consiste nell’accedere alla definizione nel codice sorgente.

1 SinOsc : UGen { 2 *ar {

3 arg freq=440.0, phase=0.0, mul=1.0, add=0.0; 4 ^this.multiNew(’audio’, freq, phase).madd(mul, add) 5 }

6 *kr {

7 arg freq=440.0, phase=0.0, mul=1.0, add=0.0;

8 ^this.multiNew(’control’, freq, phase).madd(mul, add) 9 }

10 }

Si noti come SinOsc erediti da UGen, la superclasse generica di tutte le UGen. In più, definisce soltanto due metodi di classe, ar e kr. Lasciando perdere l’ul- tima riga di ogni metodo, si nota come i metodi prevedano un certo numero di argomenti a cui può essere passato un valore “da fuori”. Ancora, tutti gli

argomenti tipicamente sono provvisti di un valore predefinito. Nell’esempio

seguente le tre righe sono equivalenti9

1 SinOsc.ar;

2 SinOsc.ar(440.0, 0.0, 1.0, 0.0);

3 SinOsc.ar(freq: 440.0, phase: 0.0, mul: 1.0, add: 0.0);

Il primo infatti, in assenza di indicazioni, utilizza i valori predefiniti per il metodo ar. Il secondo specifica per ogni argomento un valore. Il terzo infine fa uso di keywords, che come si sa permettono un ordine libero degli argomenti nella scrittura. Gli ultimi due argomenti sono mul e add, e sono condivisi dal- la maggior parte delle UGen: mul è un moltiplicatore del segnale mentre add è un incremento (positivo o negativo) che viene sommato al segnale. Il segna- le generato da una UGen tipicamente è normalizzato e la sua ampiezza oscilla

nell’escursione[−1, 1] (altre volte, in caso di UGen dedicate a segnali unipola-

ri, è compreso in[0, 1]). L’argomento mul definisce un moltiplicatore che opera

sull’ampiezza così definita, mentra add è un incremento che si aggiunge allo

stesso segnale. I valori predefiniti per mul e add sono1 e 0: il segnale è molti-

plicato per1 e sommato a 0 ed è perciò immutato rispetto all’escursione pre-

definita. A scanso di equivoci, “moltiplicare” e “aggiungere” significa che ogni campione del segnale è moltiplicato e sommato per i valori specificati nei due argomenti. Invece in questo esempio:

1 SinOsc.ar(220, mul:0.5, add:0) ; 2 SinOsc.ar(220, mul:0.5, add:0.5) ;

alla riga 1 il segnale generato attraverso il metodo ar risulta moltiplicato

per 0.5 (e sommato a 0, ma è irrilevante): la sua ampiezza sarà compresa in

[−1.0, 1.0] × 0.5 = [−0.5, 0.5]; mentre alla riga 2 il segnale viene sommato a 0.5:

la sua ampiezza sarà compresa in[−1.0, 1.0] × 0.5 + 0.5 = [−0.5, 0.5] + 0.5 =

9 Ovviamente è inutile valutarle nell’interprete, non succede nulla, perché de-

scrivono oggetti che hanno senso una volta inseriti in una synthDef e inviati al server.

valore costante0.5 indica che ogni nuovo campione verrà moltiplicato per 0.5. Si potrebbe pensare allora che mul sia un segnale, ma costante. A tal proposito si può prendere in considerazione la UGen Line. Come dice l’help file, si tratta di un generatore di “linee”: una linea qui è un segnale che “generates a line from the start value to the end value”. I primi tre argomenti di Line sono start, end, dur: Line genera una sequenza di valori che vanno da start a dur in dur secondi. Nel codice seguente

1 SinOsc.ar(220)*Line.kr(0.5,0.5, 10) ;

Line genera per10 secondi una sequenza di valori pari a 0.5 (cioè una pro-

gressione da0.5 a 0.5). Il segnale in uscita dall’oscillatore SinOsc viene moltipli-

cato per l’uscita di Line. Ad ogni istante di tempo il campione calcolato dalla prima UGen viene moltiplicato per il campione calcolato dalla seconda (che ha

sempre valore0.5). Si noti che il segnale risultante è uguale a quello precedente.

L’esempio intende dimostrare come si può pensare ad una costante (un valore) nei termini di un segnale (una sequenza di valori): è chiaro che l’aspetto inte- ressante nell’uso di Line sta invece proprio nel fatto che i valori che la UGen genera non sono costanti ma variano invece secondo una progressione lineare tra un due estremi.

L’esempio seguente produce un crescendo dal niente, proprio perché start = 0:

1 SinOsc.ar(220)*Line.ar(0.0,1.0, 10) ;

Se dunque una costante può essere pensata come un segnale, allora è pos- sibile pensare ad ogni valore di un argomento in una UGen come ad un segnale costante. E pensare perciò al caso in cui invece di una UGen che generi costanti ci sia una UGen che generi (come usuale) sequenze di valori diversi. Il patching è appunto l’innesto di una UGen in un argomento di un’altra o il calcolo di un segnale a partire dal contributo offerto da più UGen in una qualche relazione reciproca (qui di moltiplicazione). L’esempio permette di capire come gli ar- gomenti possano essere descritti non da costanti ma da variabili, cioè da altri

segnali. In altre parole, i segnali possono modificare qualsiasi aspetto control- labile di altri segnali. Si ricordi che il tasso di campionamento stabilisce a che

frequenza il grafo debba essere percorso. In altre parole, a ogni istante 𝑠𝑟1 tutte

le UGen ricalcolano il loro valore che viene utilizzato dove richiesto.

out:0

Out bus: channelsArray: amp:0.25

* a: b: kfreq:5

* a: b: 50

LFPulse freq: iphase: 0 width: 0.25 SinOsc freq: phase: 0

* a: b:

Fig. 5.7 Rappresentazione dello UGen-graph.

Nella figura 5.7 è rappresentato il diagramma di flusso della synthDef "pul- seSineGraph". Gli elementi grigi descrivono il flusso a tasso audio, quelli blu il flusso di controllo, i riquadrati di tipo connettore i valori numerici. LFPulse lavora a tasso di controllo, mentre kfreq, amp, out vengono modificate a tasso di evento (ogni qualvolta un utente modifica i parametri). I blocchi “* a b” indi- cano blocchi di moltiplicazione. I valori di argomenti nelle UGen non specificati sono indicati attraverso i valori predefiniti.

Il segnale moltiplicatore è prodotto da LFPulse, un generatore di onde qua- dre, con frequenza kfreq (quindi collegata alla frequenza della sinusoide). Il

che, quando l’ampiezza è0.0, il segnale risultante ha ampiezza 0.0 (silenzio),

quando l’ampiezza è0.5, in uscita si ha il segnale di partenza scalato per 0.5.

In sostanza, si produce una intermittenza. Si noti che nell’esempio la frequenza della sinusoide è correlata alla frequenza di intermittenza (più è acuta la fre- quenza, più frequentemente è intermittente).

Riassumendo: le UGen sono unità atomiche di elaborazione, descritte dal lato del linguaggio SuperCollider come classi che rispondono ai metodi ar e kr, i quali ricevono argomenti che ne costituiscono i parametri. Durante la fa- se di sintesi in tempo reale, le UGen generano in uscita segnali, cioè sequenze di valori a tasso audio. I valori di questi argomenti possono essere altri segnali (patching). Nell’esempio della synthDef pulseSine la scrittura è stata piutto- sto prolissa, in particolare nell’uso delle keywords nelle UGen. I due esempi seguenti sono del tutto identici alla versione precedente. Il primo è una forma di scrittura compatta che è tipico delle synthDef ma che è di solito abbastanza complesso da decifrare per il neofita (con un po’ di esercizio ci si fa l’occhio). Il secondo è una versione invece piuttosto prolissa ma molto chiara. Si ricordi che lo UGen-graph è descritto linguisticamente da una funzione, e dunque per esso valgono le considerazioni sulle funzioni. Nell’esempio, vengono usate due variabili (pulser, sine) a cui vengono associati i due segnali, per rendere più chiaro il flusso dell’informazione.

1 // compatta

2 SynthDef.new(\pulseSine , { arg out = 0, amp = 0.25, kfreq = 5 ; 3 Out.ar(out, SinOsc.ar(

4 kfreq*50, mul: LFPulse.kr(kfreq, width: 0.25) 5 )*amp);

6 }).add; 8 // espansa

9 SynthDef.new(\pulseSine , { arg out = 0, amp = 0.25, kfreq = 5 ;

10 var pulser, sine;

11 pulser = LFPulse.kr(freq: kfreq, width: 0.25) ;

12 sine = SinOsc.ar(freq: kfreq*50, mul: pulser) ; 13 sine = sine*amp;

14 Out.ar(bus:out, channelsArray: sine);

Le UGen sono unità atomiche di elaborazione del segnale. Il loro numero è molto grande. Per verificarlo si può valutare UGen.subclasses.size: nella in-

stallazione di chi scrive sono305. Una classificazione approssimativa permette

di distinguere:

• Generazione: sintesi del segnale, in forma deterministica o casuale (oscilla- tori, generatori di rumore) ;

• Elaborazione: trasformazione di un segnale in ingresso (filtri, ritardi, river- beri) ;

• Spazializzazione: diffusione su più canali di un segnale in ingresso ; • Analisi: analisi di un segnale per l’estrazione di parametri;

• Conversione: conversione di segnali da audio a controllo e viceversa; • Buffer: lettura/scrittura di buffer;

• Inviluppi: generazione/lettura di inviluppi; • Trigger: segnali di innesco di vario tipo;

• Input/Output: accesso alla scheda audio in ingresso o in uscita; • Info: permettono di accedere a informazioni audio a lato server;

• Interazione con l’utente: permettono di recuperare a lato server l’interazio- ne (ad esempio via mouse) con l’utente;

SC fornisce una classificazione interna delle UGen, la seguente, in cui sono listate le UGen relative (sempre rispetto all’installazione presa in considerazio- ne): Algebraic (5) Analysis (74) Analysis:Synthesis (11) Base (4) Buffer (42) Conversion (5) Convolution (6) Delays (34) Demand (28) Deprecated (1) Dynamics (4) Envelopes (8) FFT (85) Filters (107) Generators (156) GranularSynthesis (32) InOut (20) Info (15) InfoUGens (1) Maths (17) Multichannel (126) PhysicalModels (2) Random (19) Reverbs (3) Synth control (13) Triggers (31) Unclassified (4) Undocumented (218) User interaction (4)

Nel documento Introduzione a SuperCollider (pagine 145-152)