|
Pagina 4 di 6
3.4 Controllers continui: variamo l’ampiezza e la frequenza del vibrato
mentre suoniamo le note.
| ;vibrato.orc |
|
|
| instr |
1 |
|
| ifreq |
cpsmidi |
|
| iamp |
ampmidi |
10000 |
| kfrqvib |
midic7 |
1, 0, 1 |
| kampvib |
midic7 |
2, 0, 1 |
| kvib |
oscili |
kampvib, kfrqvib, 1 |
| kenv |
linsegr |
0, .1, 1, .3, .5, .2, 0 |
| a1 |
oscili |
iamp, ifreq*powoftwo(kvib), 1 |
|
out |
a1*kenv |
|
endin |
|
Questo esempio permette di suonare una nota sulla master-keyboard variando sia la
frequenza che l’ampiezza del vibrato allo stesso tempo. Il vibrato è generato da un
ulteriore oscillatore (operante a k-rate), che genera un segnale di controllo che viene
moltiplicato per la frequenza base dell’oscillatore audio. La frequenza e l’ampiezza
dell’oscillatore che genera il vibrato possono essere variate in modo continuo per mezzo
di messaggi MIDI di control-change.
Gli argomenti di ingresso di midic7 sono tre (più uno opzionale) cioè: il numero di
controller MIDI (per esempio, 1 corrisponde alla modulation-wheel, 2 al breath-control
ecc.) e i valori di minimo e massimo, usati per riscalare l’uscita.
Notare l’uso della funzione powoftwo( ) che restituisce un moltiplicatore che varia
esponenzialmente anziché linearmente: se avessimo usato direttamente una somma tra il
segnale di vibrato e la frequenza base della nota, il vibrato avrebbe prodotto grandi
variazioni frequenziali nella gamma grave e piccole variazioni nella gamma acuta. Nel
nostro caso, moltiplicare la frequenza base per una potenza permette di esprimere la
variazione in ottave anziché in Hertz. Sebbene la trattazione matematica di questo
concetto non sia eccessivamente complicata, va comunque oltre gli scopi di questa
lettura. Diamo semplicemente per scontato che l’intervallo della seconda istanza
dell’opcode midic7 (che controlla l’ampiezza del vibrato) viene espressa in ottave e che
varia tra 0 e 1.
3.5 Un vibrato più complesso, con delay e tremolo controllabili in tempo reale
L’esempio precedente non è stato ottimizzato per la velocità: se l’esecutore suonasse
più di una nota contemporaneamente, verrebbero attivate istanze differenti dell’opcode
midic7 che generano lo stesso identico segnale: questo sarebbe un inutile spreco di
tempo di calcolo da parte del processore. Per spiegare come risolvere questo
inconveniente, è necessario riflettere un po’ sul funzionamento degli strumenti e degli
opcode di Csound.
Uno strumento è un modello (un template in inglese) usato come schema di base da
Csound quando deve attivare la nota corrispondente. Quando questo accade, viene creata
una istanza di quello strumento, insieme con i suoi dati.
Gli strumenti di Csound sono polifonici, così è possibile attivare allo stesso tempo più
di una nota dello stesso strumento con parametri differenti. Ognuna di queste note è in
effetti una istanza dello strumento a cui si riferisce.
In maniera simile, diverse istanze dello stesso opcode possono essere contenute nello
stesso strumento (in effetti ciò accadeva nel precedente esempio con l’opcode midic7).
Così abbiamo una gerarchia di istanze: note diverse dello stesso strumento attivano
istanze diverse di quello strumento, ognuna delle può contenere più istanze dello stesso
opcode. Le variabili di Csound rappresentano segnali, che possono essere segnali di
controllo, segnali audio o parametri di inizializzazione (questi ultimi rimangono costanti
per tutta la durata della nota corrispondente).
E’ importante notare che le variabili contenute in uno strumento sono in genere locali,
questo significa che variabili con lo stesso nome, situate in strumenti diversi sono
variabili differenti in tutti i sensi. In più, anche considerando lo stesso strumento,
variabili con lo stesso nome sono differenti in ciascuna nota (o istanza) dello strumento
stesso, e contengono valori differenti e indipendenti, in accordo ai parametri con cui la
nota corrispondente viene attivata.
Ritornando all’esempio precedente, quando l’esecutore attiva un accordo consistente
di 3 note, le 2 istanze di midic7 contenute nello strumento 1 sono in effetti moltiplicate
per 3, per un totale di 6 istanze contemporanee di midic7, che sono un’inutile spreco di
tempo di calcolo perché producono tutte gli stessi identici valori. E’ meglio usare midic7
in uno strumento separato che viene attivato una sola volta, e che rimane attivo per tutta
la durata della sessione corrente. Questo strumento verrà attivato dallo score, invece che
dal MIDI.
Per permettere che il segnale prodotto da tale strumento sia visibile dall’esterno (e in
particolare dallo strumento attivato dal MIDI che necessita di accedere ai valori generati
dai controller), è necessario usare le variabili globali.
Le variabili globali hanno visibilità a livello di orchestra, non di strumento; questo
significa che esse sono condivise e visibili da tutti gli strumenti dell’orchestra. In più, a
differenza dalle variabili locali, esse sono uniche e comuni a tutte le istanze di tutti gli
strumenti correntemente attive.
Diamo un’occhiata allo strumento seguente:
| ;orchestra |
|
|
|
| sr |
= |
44100 |
|
| kr |
= |
441 |
|
| ksmps |
= |
100 |
|
| nchnls |
= |
1 |
|
| gi1 |
ftgen |
1, 0, 1024, 10, 1, .2, 0, 0, .1, 0, 0, .05 |
; tabella audio |
| gi1 |
ftgen |
2, 0, 129, 7, 0, 4, -1, 64, -1, 4, 0, 56, 0 |
; tabella del tremolo |
;## tabelle del vibrato
| gi1 |
ftgen |
50, 0, 513, 10, 1 |
; sine |
| gi1 |
ftgen |
51, 0, 513, 7, 1, 511, -1 |
; dente di sega discendente |
| gi1 |
ftgen |
52, 0, 513, 7, -1, 511, 1 |
; dente di sega ascendente |
| gi1 |
ftgen |
53, 0, 513, 7, 0, 128, 1, 256, -1, 128, 0 |
; triangolare |
| gi1 |
ftgen |
54, 0, 513, 7, 1, 256, -1, 255, 0 |
; square |
| gi1 |
ftgen |
55, 0, 513, 7, 0, 170, 0, 0, 1, 170, 1, 0, -1, 170, -1, 0, 0 |
; a 3 gradini |
| gi1 |
ftgen |
56, 0, 513, 7, 0, 128, 0, 0, 1, 128, 1, 0, 0, 128, 0, 0, -1, 128, -1, 0, 0 ;4 |
; 4 gradini |
| gi1 |
ftgen |
57, 0, 513, 7, 1, 128, 1, 0, 0, 128, 0, 0, -1, 128, -1, 0, 0, 128, 0 ;4 |
; 4 gradini 2 |
| gi1 |
ftgen |
58, 0, 513, 7, -1, 128, -1, 0, 0, 128, 0, 0, 1, 128, 1, 0, 0, 128, 0 ;4 |
; 4 gradini 3 |
; quarta, quinta e ottava
| gi1 |
ftgen |
59, 0, 513, 7, 0, 128, 0, 0, 5, 128, 5, 0, 7, 128, 7, 0, 12, 128, 12 |
; ottava, quarta, quinta ed unisono
| gi1 |
ftgen |
60, 0, 513, 7, 12, 128, 12, 0, 5, 128, 5, 0, 7, 128, 7, 0, 0, 128, 0 |
;4 glissando
| gi1 |
ftgen |
61, 0, 513, 7, -1, 90, -1, 38, 0, 90, 0, 38, 1, 90, 1, 38, 0, 90, 0, 38, -1 |
|
| gi1 |
ftgen |
100, 0, 8193, 5, .001, 8193, 1 |
; curva esponenziale per il mapping dello slider |
| gk1 |
init 0 |
|
|
| gk2 |
init 0 |
|
|
| gk3 |
init 0 |
|
|
| gk4 |
init 0 |
|
|
| gk5 |
init 0 |
|
|
| gk6 |
init 0 |
|
|
| gk7 |
init 0 |
|
|
| gk8 |
init 0 |
|
|
| gaout |
init 0 |
|
|
;////////////////////////////
instr 1
;////////////////////////////
| kvib |
oscili |
gk1, gk2, i(gk3)+.5 |
| atrem |
oscili |
gk4, gk5, 2 |
| ifreq |
cpsmidi |
|
| iamp |
ampmidi |
10000 |
| aenv |
linsegr |
0, .05, 1, .2, .2, 10, .2, .2, 0 |
| a1 |
oscili |
aenv*iamp*(1+atrem), ifreq*powoftwo(kvib),1 |
| vincr |
gaout |
a1 |
| endin |
|
|
;////////////////////////////
instr 100
;////////////////////////////
|
initc7 |
1, 3, (50-50)/(61.5-50) |
|
| gk1 |
ctrl7 |
1, 1, 0, 1 |
; ampiezza del vibrato |
| gk2 |
ctrl7 |
1, 2, .5, 20, 101, 2, .5, 20, 100 |
; frequenza del vibrato |
| gk3 |
ctrl7 |
1, 3, 50, 61.5 |
; tabella del vibrato |
| gk4 |
ctrl7 |
1, 4, 0, 1 ; |
; profondità del tremolo |
| gk5 |
ctrl7 |
1, 5, 2, 20, 100 |
; frequenza del tremolo |
| gk6 |
ctrl7 |
1, 6, 0, 1 |
; rapporto wet/dry |
| gk7 |
ctrl7 |
1, 7, 0, 1 |
; feedback del delay |
| gk8 |
ctrl7 |
1, 8, 1, 1000 |
; tempo di delay |
| gk8 |
tonek |
gk8,2 |
|
| a8 |
interp |
gk8 |
|
| a1 |
init 0 |
|
|
| a1 |
vdelay |
gaout+a1*gk7,a8,1000 |
|
|
out |
a1*gk6+gaout*(1-gk6) |
|
| clear |
gaout |
|
|
| endin |
|
|
|
| ;score |
|
|
|
| i100 0 3600 |
|
|
|
Come potete vedere, lo score non necessita dell’opcode f0, perché la durata della
sessione in tempo reale viene già portata a 3600 secondi dall’unica nota che attiva lo
strumento “globale” 100. Vedremo lo scopo dello strumento 100 più avanti.
Lo strumento 1 ha tre oscillatori. Il primo e il secondo oscillatore generano il vibrato
e il tremolo, mentre il terzo genera il segnale audio. Seguono alcune osservazioni circa
lo strumento 1:
1. l’ampiezza del vibrato viene definita esternamente dallo strumento 1, così come la
frequenza del vibrato, il numero di tabella del vibrato, la profondità del tremolo e
la frequenza del tremolo. Questi parametri vengono forniti agli oscillatori dalle
variabili globali gk1, gk2, gk3, gk4 e gk5. Più avanti vedremo il punto in cui tali
variabili vengono riempite.
2. l’opcode out non è presente all’interno dello strumento 1, invece l’uscita viene
assegnata alla variabile globale gaout. Il motivo per cui si usa la variabile globale,
invece di mandare il segnale audio direttamente all’opcode out, è che questo
segnale deve essere riutilizzato da un altro strumento, per aggiungere un effetto (un
delay in questo caso) e occorre bilanciare il rapporto wet/dry (bagnato/secco ossia
con o senza effetto) prima di assegnarlo all’opcode out. Per abbinare un segnale
alla variabile globale gaout una semplice assegnazione non è sufficiente, perché
tale variabile è in comune con tutte le istanze dello strumento 1, quindi se tale
strumento venisse usato polifonicamente e la sua uscita fosse semplicemente
assegnata a gaout, il segnale generato da altre istanze concorrenti dello strumento
1 sarebbe semplicemente rimpiazzato da quella relativa all’istanza presente. In
questo caso, quando gaout venisse connessa all’opcode out dello strumento 100, il
segnale sarebbe monofonico e non polifonico, perché conterrebbe soltanto l’uscita
dell’ultima istanza dello strumento 1 (ossia l’ultima voce suonata della polifonia).
Per evitare questo inconveniente, dobbiamo missare l’uscita dello strumento 1 con
il contenuto precedente di gaout, invece che assegnare direttamente il valore. Nel
nostro caso questa operazione viene fatta con l’opcode vincr, che fa la stessa cosa
della linea seguente:
gaout = gaout + a1
...ma è più veloce. E’ un accumulatore, progettato specificamente per sommare un
segnale ad una linea di missaggio. Dopo aver connesso gaout all’opcode out
(situato nello strumento 100), è necessario azzerare la variabile gaout, altrimenti
potrebbe ‘esplodere’ perché i valori continuerebbero ad accumularsi
indefinitamente.
Per porre la variabile gaout a zero, sarebbe sufficiente la seguente linea:
gaout = 0
...ma viene usato l’opcode clear, perché è stato progettato apposta per svolgere
questo compito in maniera più veloce (in questo caso particolare l’incremento di
velocità non è così evidente, ma quando ci sono diverse variabili a dover essere
azzerate nella stessa linea, lo diventa. Vedere il manuale).
Lo strumento 100 viene attivato dallo score solo una volta per ogni sessione in tempo
reale. Questo strumento si occupa di tre cose:
1. gestisce i messaggi MIDI di control-change, riempiendo le variabili globali, che
hanno il seguente scopo:
gk1 - ampiezza del vibrato
gk2 - frequenza del vibrato
gk3 - numero di tabella del vibrato
gk4 - profondità del tremolo
gk5 - frequenza del tremolo
gk6 - rapporto wet/dry del delay
gk7 - feedback del delay (per supportare l’eco)
gk8 - tempo del delay
2. genera l’effetto di delay (che è unico per tutte le note di tutti gli strumenti)
3. gestisce l’uscita master.
Osserviamo questo strumento. Sicuramente avrete notato che non c’è nessuna istanza
di midic7 nello strumento 1, infatti in questo caso i messaggi MIDI di control-change
sono gestiti da diverse istanze di ctrl7, che è un opcode simile a midic7, ma che permette
di definire il canale MIDI. Di conseguenza ctrl7 può essere usato anche negli strumenti
attivati dallo score, mentre se si assegna midic7 ad uno strumento attivato dallo score,
Csound si bloccherà, dal momento che in midic7 il canale MIDI è implicitamente lo
stesso dello strumento con cui viene attivato.
Notare che le variabili globali devono essere inizializzate prima di ogni strumento,
nella sezione dello header dell’orchestra, altrimenti verrebbero prodotti degli errori
dovuti all’uso di variabili senza inizializzazione.
Lo scopo di initc7 è quello di inizializzare il primo valore in uscita del corrispettivo
opcode che gestisce i messaggi MIDI di control-change (funziona sia con midic7 che
con ctrl7, vedi il manuale).
|