Memorie e oscillatori¶
Indice¶
Arrays, Buffers e Wavetables ¶
Sono tutte allocazioni di memoria temporanea (RAM).
Collezioni di dati ordinate e indicizzate.
Si differenziano dal tipo di codifica e dal formato informatico.
Array (Client side)
Possono contenere qualsiasi tipo di data e avere diversi tipi di formato.
// 0 1 2 Indici
a = [12, 23, 34]; // Elementi
a.plot; // Visualizza il contenuto (tasto 'm' cambia vista)
a = [\ciao, \miao, 34.5, SinOsc.ar]; // Qualsiasi tipo di data
Buffer (Server side)
Sono 32-bit floating point Array multicanale allocati nella memoria di un Server.
A ogni Buffer è associato un indice e una rata di campionamento che può essere diversa da quella del Server sul quele è riservato.
s.boot;
s.scope;
b = Buffer.alloc(s, 100, 1); // server, samples, n_chan
b.free; // Distrugge il Buffer
Buffer.freeAll; // Distrugge tutti i buffers sul Server
Tre principali modalità di impiego.
- Caricare soundfiles nella RAM da una memoria di massa
b = Buffer.read(s, "voce.wav".resolveRelative);
b.play; // Monitor uditivo
b.plot; // Monitor visivo
b.free;
- Riservare uno spazio di memoria vuoto da riempire con segnali provenienti da una sorgente inerna o esterna (microfoni o oscillatori).
b = Buffer.alloc(s, s.sampleRate * 2, 1); // 2 secondi...
SynthDef.new(\rec, {RecordBuf.ar(SoundIn.ar,c,loop:0,doneAction:2)}).play
b.play; // Monitor uditivo
b.plot; // Monitor visivo
b.free;
- Wavetable - Riservare uno spazio di memoria vuoto di dimensioni ridotte (512, 1024, 2048 4096, 8192 samples) in cui disegnare un singolo ciclo di forma d'onda o altro tipo di data come ad esempio i risultati di un'analisi FFT, una tranfert functions, etc...
b = Buffer.alloc(s, 512, 1); // 512 campioni...
b.sine1([1,0.5,0.7,0.3],true,false); // Disegna una forma d'onda
SynthDef.new(\rec, {Out.ar(0,OscN.ar(b)*0.2)}).play; // Monitor uditivo
b.plot; // Monitor visivo
b.free;
In nessuno di questi tre casi le dimensioni del Buffer in campioni non dà alcuna indicazione riguardo a durata e frequenza dell'informazione sonora in esso contenuta se non è messo in relazione con una rata di campionamento.
Lookup ¶
Buffer e Arrays intesi come collezioni indicizzate non hanno una dimensione temporale.
Il suono consiste in variazioni di pressione atmosferica nel tempo.
Per riprodurre dinamicamente queste variazioni possiamo ottenere i singoli valori y memorizzati in un Buffer (ampiezze istantanee che corrispondono alla misura della pressione atmosferica in quel momento) richiamandone gli indici sottintesi (valori x).
Per realizzare ad esempio un playback possiamo utilizzare un fasore (o contatore) i cui valori in uscita (y) andranno da 0 al size - 1 del Buffer da rileggere.
Rappresentazione grafica.
(
a = (0..30);
b = Signal.sineFill(30,[0.4,0.6,0.2]);
[a,b].plot(discrete:true);
)
Rappresentazione sonora.
s.boot;
s.scope;
b.free;
b = Buffer.read(s, "voce.wav".resolveRelative); // Carica un soundfile (mettere nella stessa cartella del file di SuperCollider)
(
SynthDef.new(\play, {var pha, sig;
pha = Phasor.ar(0,MouseY.kr(0,10),0,BufFrames.kr(b));
pha.linlin(0,BufFrames.kr(b),0,1).scope;
sig = BufRd.ar(1,b,pha);
Out.ar(0,sig*0.2)}
).add;
)
Synth.new(\play);
Mentre il playback è in esecuzione proviamo a trasformare il Buffer in una wavetable modificandone size e contenuto.
b.free;
b = Buffer.alloc(s, 512, 1); // 512 campioni...
b.sine1([1,0.5,0.7,0.3],true,false); // Forma d'onda
Il lookup tabellare è un processo fondamentale dell'informatica musicale posto alla base di moltissime procedure che vanno dal sequencing (Client side) alle diverse tecniche di sintesi ed elaborazione del suono.
Questo processo è alla base del funzionamento delle tre principali tipologie di oscillatori.
Tipologie di oscillatori ¶
- Sample playback oscillator (campionatore).
- rate
- posizione iniziale
- direzione di lettura
s.boot;
s.scope;
Buffer.freeAll;
b = Buffer.read(s, "voce.wav".resolveRelative);
b.plot;
b.play;
(
SynthDef(\ply1, {var sig;
sig = PlayBuf.ar(1,b,doneAction:2);
Out.ar(0,sig)
}).add;
)
Synth(\ply1);
- Buffer reading oscillator (elaboratore).
- segnale puntatore
(
SynthDef(\ply2, {var sig;
sig = BufRd.ar(1,b,LFNoise2.ar(1) * BufFrames.kr(b));
Out.ar(0,sig)
}).add;
)
a = Synth(\ply2);
a.free;
- Interpolating wavetable oscillator (oscilaltore tabellare)
b.free;
b = Buffer.alloc(s, 512, 1);
b.sine1(1.0/[1,2,3,4,5,6], true, true, true);
b.plot;
(
SynthDef(\ply3, {var sig;
sig = Osc.ar(b,MouseY.kr(200,800) * 0.4);
Out.ar(0,sig!2)
}).add;
)
a = Synth(\ply3);
a.free;
Nei prossimi paragrafi esploreremo le peculiarità di questi oscillatori mettendoli in relazione con i diversi tipi di memorie illustrati.