OSC
Open Sound Control
Protocolo de comunicación que permite que instrumentos
electrónicos, computadoras, y dispositivos multimedia se
comuniquen entre si en tiempo real sobre una red. El OSC está
diseñado para trabajar sobre los sistemas de redes modernos como
internet, o en redes locales usando TCP/IP, ethernet y redes
inalámbricas. OSC utiliza puertos UDP para establecer conexiones
entre aplicaciones y dispositivos. El mismo SuperCollider usa OSC para
la comunicación servidor-cliente.
NetAddr(IP, puerto)
Dirección para identificar dispositivos conectados en una red
IP = Internet Protocol. El IP de la computadora a la que queremos
enviar datos. Puede ser la misma computadora
desde donde se estan enviando. Es un
número de cuatro cifras separadas por puntos (e.g.
192.164.0.100) que sirve para identificar a
cada dispositivo en red. Se escribe como
string, asi que hay que ponerlo entre comillas. Para mandar datos
internamente se usa un ip de regreso : "127.0.0.1"
puerto = El puerto UDP al que queremos enviar los mensajes.
SuperCollider trabaja con el puerto 57120.
Con el método .sendMsg podemos enviar mensajes a esta
dirección. La sintaxis es asi: sendMsg(commandName, mensaje1,
mensaje2, ...)
Ejemplo :
e=NetAddr("192.168.9.100", 57120)
e.sendMsg("/conejos", "Blas", "Bugsbunny", "Frank")
OSCresponder(NetAddr, commandName, acción)
Responde con acciones determinadas al recibir un commandName
específico de un NetAddr específico.
addr = El NetAddr de donde se quiere recibir. Si queremos recibir de
donde sea escribimos nil.
commandName = Un String que sirve como identificador en la
distribución de los datos. Se escribe dentro de comillas " " y
precedido por una diagonal /. Ejemplo: "/uno".
acción = Una función en donde se especifican las acciones
que el OSCresponder llevará acabo al recibir mensajes. Sus
argumentos son: time,
theResponder, message y addr. El argumento message es un array siendo
el primer elemento el commandName y el segundo
el mensaje. Es por eso
que normalmente evaluaremos el argumento asi: message[1].
Al declarar un OSCresponder es necesario añadir el método
.add al final para que se active. Para desactivarlo recurrimos al
método .remove.
Ejemplo 1
Creamos un NetAddr y lo asignamos a una variable. Aqui usaremos n.
Primero crearemos una conexión interna por lo que usaremos el IP
"127.0.01" y el puerto 57120. Después creamos un OSCresponder y
lo asignamos a otra variable, en este caso o. Le pedimos al
OSCresponder que reciba del NetAddr n que es el que acabamos de crear.
Despues le indicamos que reciba datos identificados con el commandName
"/colores". Por último definimos la acción como una
función de la manera que ya conocemos: entre llaves y declarando
sus argumentos. Al final del OSCresponder escribimos el argumento .add.
Podemos comenzar a enviar mensajes a nuestro NetAddr que esta
identificado con la variable n con el método .sendMsg. En los
argumentos escribimos el commandName al que queremos enviar y
desoués el mensaje. Si queremos que el OSCresponder deje de
responder le enviamos el método .remove. Podemos tener varios
OSCresponder con distintos commandNames, solo hay que identificar el
commandName cuando se envíe el mensaje al NetAddr.
n=NetAddr("127.0.0.1", 57120) // El IP de regreso y el
puerto asignado a SuperCollider.
o=OSCresponder(n, "/colores", {|timepo, responder, mensaje, direccion|
[timepo, responder, mensaje, direccion].postln}).add
n.sendMsg("/colores", "rojo")
o.remove
p=OSCresponder(n, "/texturas", {|timepo, responder, mensaje, direccion|
mensaje[1].postln}).add
n.sendMsg("/texturas", "terso")
o.add
n.sendMsg("/colores", "amarillo")
Si se desea establecer comunicación via internet hay que conocer
el IP externo de nuestro router en casa o donde estemos. Para esto se
hace una cosa que se llama Port Forwarding. Cuando tenemos un router
que nos conecta a internet éste crea una red local que
distribuye el servicio entre las computadoras que tengamos y les asigna
un IP local. Con este IP local no podemos comunicarnos via internet.
Necesitamos el IP esxterno que es con el que el router se identifica en
el mundo exterior. Existen varias páginas de internet que
ofrecen el servicio de PortForwarding. Una es www.portforward.com.
Después de conocer nuestro IP externo es necesario abrir los
puertos para superCollider (57120). Para esto es necesario configurar
el router desde la página web de la empresa que lo fabrica. Ahi
hay que indicar que "pinche" un agujero en le firewall para que deje
pasar los datos. Este agujero es el puerto en cuestión.
Ejemplo 2
Podemos insertar un switch en la acción del OSCresponder tal y
como lo hemos hacho con el Tdef, con el SCPopUpMenu y con el MIDIIn.
(
(
SynthDef(\juego2, {|freq2,freq, dur, amp, pan=0|
var sig, env;
sig=Pan2.ar(Saw.ar(Line.kr(freq2,freq,
dur),amp),pan);//+SinOsc.ar(freq,0,amp/3),pan;
env=EnvGen.kr(Env([0,1,1,0],[0,dur,0]),doneAction:2);
Out.ar(0,sig.wrap2(0.24)*env*1);
}).send(s);
);
/*
Synth(\juego2, [\freq, 10, \freq2, 6200, \dur, 0.1, \amp, 0.75])
*/
(
SynthDef(\explosion2, {|freq, dur, amp|
var sig, env;
sig=Pulse.ar(freq,0.5,amp);
sig=LPF.ar(sig,Line.kr(10000,30))!2;
env=EnvGen.kr(Env([0,1,1,0],[0.01,dur,0.5]),doneAction:2);
Out.ar(0,sig*env*0.25);
}).send(s);
);
/*
15.do{|i| Synth(\explosion2, [\freq, rrand(20,25)*(1+(i*0.1)), \dur,
0.15, \amp, 0.1575])}
*/
)
(
h=OSCresponder(nil, "/bermejo", {|a,b,c,d|
c[1].postln;
switch(c[1], 1, {Synth(\juego2, [\freq, 10, \freq2, 6200, \dur, 0.1,
\amp, 0.75])},
2, {15.do{|i| Synth(\explosion2, [\freq, rrand(20,25)*(1+(i*0.1)),
\dur, 0.15, \amp, 2])}}
)
}).add
)
n.sendMsg("/bermejo", 1)
n.sendMsg("/bermejo", 2)
Ejemplo 3
Una aplicación muy util del OSC es la sincronía entre
computadoras. Podemos hacer un Tdef maestro que corra en una
computadora y que esta mande los pulsos via OSC a otras computadoras
esclavas.
(
Tdef(\maestro, {
inf.do{|i|
n.sendMsg("/pulso", i);
0.1.wait;
}
})
)
(
var array1=[0,4,8,12,14], array2=Array.rand(5,0,15), array3=[7,9];
j=OSCresponder(nil, "/pulso", {|a,b,c|
if(array1.find([c[1]%16])!=nil, {Synth(\juego2, [\freq, 10000, \freq2,
6200, \dur, 0.05, \amp, 0.75])});
if(array2.find([c[1]%16])!=nil, {Synth(\juego2, [\freq, 100, \freq2,
600, \dur, 0.05, \amp, 0.75])});
if(array3.find([c[1]%16])!=nil, {5.do{|i|
{Pulse.ar((i*2).midiratio*[60,62,64,66].choose.midicps,0.5,1/5)*Line.kr(1,0,0.4,doneAction:2)}.play}});
if(c[1]%4==0, {{var
freq=[0,3,5,7,10].choose.midiratio*32.midicps;Pulse.ar(freq,0.5,1/2)+SinOsc.ar(freq)*Line.kr(1,0,0.4,doneAction:2)}.play});
}).add
)
l=Tdef(\maestro).play
l.stop