Panning¶
Indice¶
import os
Intro ¶
Panning o panpot $\rightarrow$ posizionare un segnale monofonico in uno spazio bi o tri-dimensionale delimitato da due o più altoparlanti.
Non confondiamo pannning e spazializzazione:
il primo è dedicato alla posizione e al movimento dei segnali in uno spazio acustico neutro.
la seconda simula posizione e movimento di una sorgente sonora virtuale in relazione a un punto di ascolto e sono computati anche parametri come volume, riverberazione dinamica, assorbimento dell'aria, effetto doppler, etc.
Bus, outputs e inputs ¶
Bus audio $\rightarrow$ canali di ingresso e uscita dei segnali dal software (e dal computer).
Usualmente in un computer abbiamo a disposizione:
- 1 canale in ingresso (microfono)
- 2 canali in uscita (altoparlante sinistro e destro).
I software hanno dei bus audio che possiamo collegare a questi canali come desideriamo.
SuperCollider
Abbiamo a disposizione 128 canali audio (da 0 a 127) chiamati Bus.
Primi tre $\rightarrow$ pubblici (utilizzati per i segnali in ingresso e in uscita dal software)
Gli altri $\rightarrow$ privati (disponibili per eventuali routing interni al software).
Possiamo scrivere qalsiasi tipo di segnale su ognuno di questi con la UGen Out.ar mentre per leggerli dobbiamo utilizzare la UGen In.ar.
Out.ar
Abbiamo già incontrato questa UGen all'interno delle ___SynthDef___.
Argomenti: Out.ar(numero_del_bus, segnale_da_collegare) dove il segnale può anche essere un array di segnali.
Bus 0 $\rightarrow$ per convenzione il canale sinistro.
s.boot;
s.meter;
s.plotTree;
(
SynthDef(\out,{arg t_gate=0, outBus=0;
var sig, env;
sig = WhiteNoise.ar;
env = Env.perc;
env = EnvGen.kr(env,t_gate);
sig = sig * env * 0.5;
Out.ar(outBus, sig)
}).add;
)
a = Synth(\out);
a.set(\outBus,0, \t_gate,1);
a.set(\outBus,1, \t_gate,1);
a.set(\outBus,rand(2).postln, \t_gate,1);
Se segnali multicanale $\rightarrow$ primo argomento: il numero del bus più basso
Gli eventuali ulteriori canali sono inviati automaticamente ai bus vicini in ordine crescente.
s.scope(3);
(
SynthDef(\out2,{arg t_gate=0, outBus=0;
var siga, sigb, env;
siga = WhiteNoise.ar;
sigb = Saw.ar;
env = Env.perc;
env = EnvGen.kr(env,t_gate);
siga = siga * env * 0.2;
sigb = sigb * env * 0.2;
Out.ar(outBus, [siga, sigb]) // Array di segnali
}).add;
)
a = Synth(\out2);
a.set(\outBus,0, \t_gate,1);
a.set(\outBus,1, \t_gate,1);
SoundIn.ar
Per leggere il segnal in ingresso provenienti da microfoni o canali audio esterni.
(
SynthDef(\in, {arg gate=0, inBus=0, outBus=0;
var sigIn, rev, env;
sigIn = SoundIn.ar(inBus);
rev = FreeVerb.ar(sigIn);
env = Linen.kr(gate,0.2,0.5);
rev = rev * env;
Out.ar(outBus, rev)
}).add;
)
a = Synth(\in);
a.set(\gate,1);
a.set(\gate,0);
Pure Data
In PD possiamo specificare i bus in entrata e in uscita come argomenti degli oggetti adc~ e dac~.

os.system('open 7_pan/patch/7.1.pd')
0
Dual mono e multi mono¶
Se duplichiamo un segnale monofonico scrivendolo su due canali attigui e lo diffondiamo tramite due altoparlanti non otteniamo un segnale stereofonico ma dual-mono o multi-mono (due o più segnali monofonici uguali) come se fossero due strumenti acustici che suonano la stessa parte.
(
SynthDef(\dmono,{arg gate=0;
var sig, env;
sig = Pulse.ar;
env = Linen.kr(gate);
sig = sig * env;
Out.ar(0, [sig, sig]) // Due segnali mono identici
}).add;
)
a = Synth(\dmono);
a.set(\gate,1);
a.set(\gate,0);
Lo stesso in PD.

os.system('open 7_pan/patch/7.2.pd')
0
Stereofonia ¶
Due altoparlanti frontali posizionati con un angolo di 60° rispetto al punto di ascolto ottimale.

Sistema monodimensionale frontale.
Possiamo posizionare e muovere una o più sorgenti sonore monofoniche (source) nello spazio compreso tra l'altoparlante sinistro e quello destro (fronte stereofonico).
La distanza può essere simulata solo alle spalle della linea immaginaria che collega i due diffusori.
Per ottenere un segnale stereofonico dobbiamo prendere un segnale monofonico e distribuire la sua ampiezza tra due canali attigui in modo che la somma delle ampiezze in uscita dai due altoparlanti sia la stessa del segnale monofonico originale e mai superiore a 1.0.
Il rapporto tra le ampiezze in uscita dagli altoparlanti definisce la posizione della sorgente nel fronte stereofonico.

s.boot;
s.meter;
s.plotTree;
(
SynthDef(\stereo,
{arg pan=0.5; // 0 = sinistra, 0.5 = centro, 1 = destra
var sig, sx, dx;
sig = SinOsc.ar;
sx = 1.0 - pan; // Ampiezza altoparlante sinistro
dx = pan; // Ampiezza altoparlante destro
Out.ar(0, [sx, dx] * sig)
}).add;
)
a = Synth(\stereo);
a.set(\pan,0); // Sinistra
a.set(\pan,0.5); // Centro
a.set(\pan,1); // Destra
Abbiamo impiegato un solo valore per controllare il panning calcolando automaticamente le ampiezze del segnale in uscita.
La percezione dell'intensità del suono alle diverse posizioni non è uguale.
Al centro risulta più debole rispetto a quando è ai lati.
Possibile soluzione $\rightarrow$ calcolare la radice quadrata del fattore di moltiplicazione delle ampiezze.
La somma dei segnali quando è posizionata al centro è maggiore di 1.0 ($\sqrt{0.5} = 0.707*2=1.141$) ma il risultato percettivo è corretto.
(
SynthDef(\stereo,
{arg pan=0.5; // 0 = sinistra, 0.5 = centro, 1 = destra
var sig, sx, dx;
sig = SinOsc.ar;
sx = (1.0 - pan).sqrt; // Ampiezza altoparlante sinistro
dx = pan.sqrt; // Ampiezza altoparlante destro
Out.ar(0, [sx, dx] * sig)
}).add;
)
a = Synth(\stereo);
a.set(\pan,0); // Sinistra
a.set(\pan,0.5); // Centro
a.set(\pan,1); // Destra
In SuperCollider realizziamo quanto appena illustrato con due UGens dedicate.
- ___LinPan2___ - panning lineare con il suono che risulta più flebile al centro.
- ___Pan2___ - con la correzione percettiva (equal power).
Entrambe accettano i seguenti argomenti: segnale_mono, posizione (-1.0 = sinistra, 0 = centro 1.0 = destra), level.

Possiamo utilizzare l'argomento level per allontanare il suono diminuendone l'intensità (legge della distanza inversa).

(
SynthDef(\pan,
{arg pos=0, lev=1;
var sig;
sig = SinOsc.ar;
//sig = LinPan2.ar(sig, pos, lev);
sig = Pan2.ar(sig, pos, lev);
Out.ar(0, sig)
}).add;
)
a = Synth(\pan);
a.set(\pan, rand2(1.0).postln);
In PD abbiamo due possibilità per realizzare un panning stereofonico.
- effettuando i calcoli con gli oggetti.
os.system('open 7_pan/patch/7.3.pd')
0
- utlizzando l'oggetto pan2~ della libreria ELSE.
os.system('open 7_pan/patch/7.4.pd')
0
Movimenti ¶
Negli esempi di paragrafo precedente abbiamo cambiato la posizione in modo repentino.
Se vogliamo realizzare un movimento all'interno del fronte stereofonico possiamo utilizzare inviluppi oppure segnali di controllo.
Inviluppi e smoothing ¶
Gli inviluppi non servono solo per controllare l'ampiezza ma qualsiasi parametro.
Basta impiegare il range di livelli corretto che nel caso del panning è compreso tra -1.0 e +1.0 per quanto riguarda la posizione e tra 0.0 e 1.0 per quanto riguarda la distanza.
(
SynthDef(\muovi,
{arg t_gate=0, dur=1, amp=0;
var sig, pos, dist;
sig = SinOsc.ar;
pos = Env.new([-1, 1, 0, 0.5, -0.7, 0], // Posizione
[ 1, 0.2, 2, 0.3, 1 ].normalizeSum * dur, // Tempi (relativi)
0); // Lineare
dist= Env.new([1, 0.2, 1], // Distanza
[ 0.5, 0.5 ].normalizeSum * dur,
-4); // Quartica
pos = EnvGen.kr(pos,t_gate); // Segnali di controllo
dist= EnvGen.kr(dist,t_gate);
sig = Pan2.ar(sig, pos, dist);
sig = sig * amp;
Out.ar(0, sig)
}).add;
)
a = Synth(\muovi);
a.set(\dur, 10, \amp, 0.5, \t_gate, 1);
Una rampa può essere: ___dal valore che hai vai a questo nuovo valore in tot tempo___.
Equivale al concetto di smoothing (arrotondamento) o lag dei segnali.
Lo smoothing può essere lineare o non lineare.
In SuperCollider la UGen ___Lag___ compie questa operazione con una rampa non lineare (maggiormente percepibile).
(
SynthDef(\smooth,
{arg pos=0, ptime=0.5; // Posizione e tempo delta per raggiungere il nuovo valore
var sig, pan;
sig = SinOsc.ar;
pan = Lag.kr(pos, ptime); // Trasforma il float in segnale di controllo
//pan = pos.lag(ptime); // Sintassi alternativa
sig = Pan2.ar(sig, pan);
Out.ar(0, sig)
}).add;
)
a = Synth(\pan);
a.set(\smooth, rand2(1.0).postln);
In PD possiamo utilizzare line~ oppure f2s~ della libreria ELSE.
Per entrambi dobbiamo specificare il tempo di smoothing i millisecondi.

os.system('open 7_pan/patch/7.5.pd')
0
Segnali di controllo ¶
Nel paragrafo precedente abbiamo trasformato valori (int e/o float) in segnali di controllo.
Una tecnica derivata dall'audio analogico consiste nell'utilizzare direttamente segnali di controllo a frequenze subaudio per controllare il panning.
Possiamo chiamare le UGen o gli oggetti di PD utilizzati per questo compito Low Frequency Oscillator (LFO).
Dovrebbe risultare ora chiaro il motivo per il quale abbiamo riscalato i valori in un range tra -1.0 e +1.0.
I parametri che possiamo comtrollare in questo caso sono.
forma d'onda del segnale di controllo.
Immagine traslata:
- asse verticale $\rightarrow$ tempo
- asse orizzontale $\rightarrow$ movimenti
// Qualsiasi UGen che genera un segnale compreso tra +1 e -1
s.scope;
{LFTri.ar(5)}.play;
{SinOsc.ar(5)}.play;
{LFNoise0.ar(5)}.play;
{LFNoise1.ar(5)}.play;
{LFNoise2.ar(5)}.play;
- frequenza del movimento da una posizione all'altra con valori sub-audio ovvero inferiori ai 20Hz.

(
SynthDef(\vel,
{arg vel=0;
var sig, lfo;
sig = SinOsc.ar;
lfo = SinOsc.ar(vel/2); // vel/2 per segnali periodici bipolari
//lfo = LFNoise1.ar(vel); // Random
sig = Pan2.ar(sig, lfo);
Out.ar(0, sig)
}).add;
)
a = Synth(\vel);
a.set(\vel, 2);
- posizione iniziale e il direzione del movimento per le UGens che hanno un agomento per la fase (in radianti).
(
{[SinOsc.ar(220,0), // 0 = parte dal centro e va verso 1,
SinOsc.ar(220,pi), // pi = parte dal centro e va verso -1
SinOsc.ar(220,0.5pi), // 0.5pi = parte da 1 e va verso -1
SinOsc.ar(220,-0.5pi)] // -0.5pi = parte da -1 e va verso 1
}.plot
)
- spread o larghezza del movimento nel fronte stereofonico controllabile con gli argomenti mul e add del segnale di controllo.
(
SynthDef(\spread,
{arg vel=1, min= -0.3, max= 0.2; // Limiti
var sig, range, offset, lfo;
sig = SinOsc.ar;
range = (max - min) / 2;
offset = min + range;
lfo = SinOsc.ar(vel/2, mul:range, add:offset).scope;
sig = Pan2.ar(sig, lfo);
Out.ar(0, sig)
}).add;
)
a = Synth(\spread);
a.set(\min, -0.5, \max, 0.1);
In PD possiamo utilizzare qualsiasi oscillatore che produca un segnale audio.

os.system('open 7_pan/patch/7.6.pd')
0