Patterns, Streams, Event
1-La librería de patrones de SuperCollider provee una poderosa y
eficiente manera de modificar dinámicamente los
parámetros de los procesos musicales. Son muy utiles a la
hora de querer construir secciones en donde los valores, asignados a
algun argumento ya sea frecuencia, amplitud, wait etc, adopten una
relevante importancia en
el discurso sonoro, generando campos discursivos muy complejos e
interesantes.
A su vez son una excelente oportunidad para empezar a conocer algunas
estrategias mas cercanas a la escritura de codigo en vivo.
Los Streams y los patterns son usados en diferentes templates que
collider provee.
/////////////////////////////////////////////////////////////////////////////////////
Algunas consideraciones particulares:
1-Un Streams representa una "perezosa" secuencia de valores. Cada nuevo
valor es obtenido mandando el mensaje next al objeto. Al utilizar
Streams las expresiones no tienen que ser evaluadas tan pronto como son
asignadas a una variable ('eager evaluation'), sino sólo cuando
el evaluador es forzado a producir el valor de la expresión
('lazy evaluation').
2- La secuencia puede ser restarteada mandando el mensaje reset al
objeto.
3-Un stream puede ser finito o infinito
-----------------------------------------------------------------------------------
un ejemplo sencillo
Pseq(list, repeats, offset)
Para que nuestros Pseq nos devuelva los valores debemos de agragarle el
mensaje .asStream al final
5.do{|i| (i%5+1).postln}
(
var seq;
seq=Pseq([1,2,3,4,5],inf).asStream;
15.do{(seq.next).postln}
)
Analizemos el ejemplo anterior:
La variable seq esta igualada a un Pseq que nos devuelve una lista de
numeros del 1 al 5. El Pseq en cuestion lleva el mensaje .asStream para
que funciones. Luego se itera la funcion 5 veces para que nos devuelva
los valores del Pseq.
Hay que recordar que los Stream son lazy evaluation por esta cuestion
se le debe de sumar el mensaje .next a la variable.
------------------------------------------------------------------------------------
(
var a, b;
a = Pseries.new(10, 3, 8); // el stream comienza en 10, tiene un "step"
de 3 y una longitud de 8
b = a.asStream;
19.do({ b.next.postln; }); // imprime 9 valores del
stream
)
(
var a, b;
a = Pseq([Pseries.new(10, 3, 8)],inf); // el stream comienza en 10,
tiene un "step" de 3 y una longitud de 8
b = a.asStream;
19.do({ b.next.postln; }); // imprime 9 valores del
stream
)
////////////////////////////
(
SynthDef(\hu,{|gate=1,frecuencia=100|
var sen,env;
sen=Pulse.ar(frecuencia*[1,1.02],0.05);
env=EnvGen.kr(Env.perc(0.2,0.6),doneAction:2);
Out.ar(0,sen*env)
}).send(s)
)
Synth(\hu)
(
w=Pseq([Pseries(30,3,4)],inf).asStream;
Tdef(\lll,{
inf.do{
Synth(\hu,[\frecuencia,(w.next*2).midicps]);
0.2.wait
}}
).play
)
(
w=Pseq([Pseries(30,3.4,4),20.005,20.004,23.2,23.4,20.4,23.4],inf).asStream;
Tdef(\lll,{
inf.do{
Synth(\hu,[\frecuencia,(w.next*2).midicps]);
0.2.wait
}}
).play
)
///////////////////////////////////////////////////////////////////////////////////////////
Los patrones tambien responden a operaciones matematicas
(
var a, b, c;
a = Pseries(0,1,10); //una serie de numeros que comienza en 0, con un
step de 1 y una longitud de 10
b = a.squared; // pattern b es el cuadrado del
pattern a
c = b.asStream;
12.do({ c.next.postln; });
)
-----------------------------------------------------------------------------------
//paterns filtrados
En esta seccion ampliaremos nuestro repertorio de mensajes para iterar
funciones. Hasta ahora conociamos solo el mensaje .do.
Ahora conoceremos .collect, .select y .reject.
. collect
El mensaje .collect evalúa una función por cada elemento
en la colección y nos devuelve una nueva colección con
los resultados de la función.
[ item1, item2 ].collect({ function })
(
[1,2,3,4,5,6].collect({|o| o+100})
)
(
var a, b, c;
a = Pseries.new(0,1,10);//una serie de numeros que comienza en 0, con
un step de 1 y una longitud de 10
b = a.collect({|i| if (i.even, { i * 130 },{ i*200 }); });// b es un
patern que le suma 100 a los valores pares
c = b.asStream;
6.do({ c.next.postln; });
)
apliquemos este algoritmo a un tdef
(
SynthDef(\seno,{|freq=100,gate=1|
var sen,env;
sen=SinOsc.ar(freq,0,0.5);
env=EnvGen.kr(Env.perc(0.1,0.4),doneAction:2);
Out.ar(0,sen*env)
}).send(s)
)
Synth(\seno)
(
a = Pseq([Pseries.new(0,1,10)],inf).asStream;
b = a.collect({|i| if (i.even, { i * 130 },{ i*200 }); });
Tdef(\huu,{
inf.do{
Synth(\seno,[\freq,b.next]);
0.2.wait
}}
).play
)
/////////////////////////////////////////////////////////////////////////////////////////////
. select
El mensaje .select nos devuelve una nueva colección que contiene
todos los elementos a los que la función haya respondido
afirmativamente (con true).
[ item1, item2 ].select({ function })
[1,2,3,4,5].select({|i| i.odd})
(
var a, b, c;
a = Pseries.new(0,1,10);//una serie de numeros que comienza en 0, con
un step de 1 y una longitud de 10
b = a.select({ arg item; item.odd; });// b es un patern que devuelve
solo los valores impares
c = b.asStream;
6.do({ c.next.postln; });
)
(
SynthDef(\seno,{|freq=100,gate=1|
var sen,env;
sen=SinOsc.ar(freq,0,0.5);
env=EnvGen.kr(Env.perc(0.2,0.4),doneAction:2);
Out.ar(0,sen*env)
}).send(s)
)
(
a = Pseq([Pseries.new(0,1,10)],inf).asStream;
b = a.select({|i| i.odd });
Tdef(\huu,{
inf.do{
Synth(\seno,[\freq,b.next*(a+100)]);
(b.next*300).postln;
0.2.wait
}}
).play
)
------------------------------------------------------------------------------------
q=Buffer.read(s,"sounds/melodinen6.wav")
q.numFrames
(
SynthDef(\sample,{|posc=1000,trig=4,gate=1,rate=1|
var sen,env;
sen=PlayBuf.ar(1,q.bufnum,rate,Impulse.kr(trig),posc,loop:1);
env=EnvGen.kr(Env.asr(0,1,0),gate,doneAction:2);
Out.ar(0,sen*env)
}).send(s)
)
m=Synth(\sample)
(
a = Pseq([Pseries.new(0,1,450)],inf).asStream;
b = a.select({|i| i.odd });
d=Pseq([2],inf).asStream;
j=Pseq([Pn(1,5),Pn(1.02,3),1.04],inf).asStream;
Tdef(\jiiii,{m=Synth(\sample);
inf.do{
m.set(\posc,b.next*900,\trig,d.next,\rate,1);
0.1.wait
}}
).play
)
//////////////////////////////////////////////////////////////////////////////////////////////
.reject
El mensaje .reject nos devuelve una nueva colección que contiene
todos los elementos a los que la función haya respondido
negativamente (con false).
(
var a, b, c;
a = Pseries.new(0,1,10);//una serie de numeros que comienza en 0, con
un step de 1 y una longitud de 10
b = a.reject({ arg item; item.odd; });// b es un patern que devuelve
solo los valores que no son impares
c = b.asStream;
6.do({ c.next.postln; });
)
/////////////////////////////////////////////////////////////////////////////////////////////
s.boot
(
SynthDef( \pop, { arg i_out=0, i_dur=1, freq=40 ;
var out,env;
out = Pan2.ar(RLPF.ar(LFSaw.ar( freq
),LFNoise1.kr(2,15,120).midicps,0.1),0);
env=EnvGen.kr( Env.perc(0.4,0.03),
levelScale: 0.1, doneAction: 2 );
14.do({ out = AllpassN.ar(out,
0.05, [0.05.rand, 0.05.rand], 4) });
Out.ar( i_out,
out*env );
}).send(s);
)
Synth(\pop)
s.boot
(
e =
Prand([Pn(40,2),Pseq([30,45,56,43,51]),Prand([54,67,78],5),Pn(45,2)],inf).asStream;
w = e.collect({|i| if(i>53,{i*5},{i*2})});
y=Prand([0.2,0.17,0.1],inf).asStream;
Tdef(\ji,{
inf.do{Synth(\pop,[\freq,w.next]);
y.next.wait
}}
)
)
Tdef(\ji).play
(
SynthDef(\seno,{|freq=100,gate=1|
var sen,env;
sen=SinOsc.ar(freq,0,0.5);
env=EnvGen.kr(Env.perc(0.1,0.14),doneAction:2);
Out.ar(0,sen*env)
}).send(s)
)
(
f=Pseq([520,200,300,500,Pseq([100,130,180],4),Pseq([300],6)],inf).asStream;
Tdef(\lp,{
inf.do{
Synth(\seno,[\freq,f.next]);
0.2.wait
}}
)
)
Tdef(\lp).play