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