IF, SWITCH Y RELOJES

IF

Con el mensaje if podemos condicionar la ejecución de funciones. Este mensaje recibe una expresión que al ser evaluada debe regresar los valores true o false (valores booleanos). 

Si la expresión es cierta, se ejecutará la función que se encuentra en el segundo argumento. Si es falsa, se ejecutará la función que se encuentra en el tercer argumento.

El mensaje if  nos regresará el resultado de la función que haya sido evaluada. Si no hay ninguna función para ser evaluada en el caso de que la expresión haya sido falsa, el resultado del mensaje será nil.

if ( expression, { trueFunction }, { falseFunction } )

(
if(
	2.0.rand.postln > 1 ,		// la expresión booleana

	{"la expresion fue cierta" },	// la función a evaluar si
									// la expresión es cierta
												
	{"la expresion fue falsa"};
		// la función a evaluar si
								// la expresión es falsa
  )
)

// si la expresión es falsa y no hay ninguna función que sea evaluada,
// if nos dará nil

if ( 1000.rand > 900, {"mayor que 900"})

// Evalúa el siguiente código varias veces

(
{
var opciones;

opciones	=	[ \aditiva, \substractiva ];

if ( opciones.choose == \aditiva,
	{"aditiva".postln;
	 a = Mix.fill(10, {SinOsc.ar(exprand(30.0, 300.0), 0, 0.07)}) },
	{"substractiva".postln;
	 a = Mix.fill(10, {BPF.ar(BrownNoise.ar, f = exprand(300.0, 3000.0),
											 0.5/f, 4)})}
	);
	
a ! 2 }.scope

)

// Evalúa las siguientes líneas
Expresiones booleanas

1 < 2		// menor que

1 > 2		// mayor que

1 == 2		// igual que (Atención: es muy común cometer el error de 
			// sólo poner un signo de igual ( = ) en vez de dos ( == )
				
1 != 2		// distinto que

1 <= 2		// menor o igual que

1 >=	2	// mayor o igual que

1.odd		// ¿es un número non?

1.even		// ¿es un número par?

////////////////////////////////////////////////////////////////////

Evaluando algunas funciones
 
Si quisieramos evaluar una función es necesario seguir algunos pasos.
Primero construimos la función que queremos evaluar. Por ejemplo:

x={|n| if(n>10,{"es mayor a 10"},{"es menor a 10"})} //construimos la funcion x en donde n 												(argumento) es nuestra incognita;
											         //compilamos el codigo
											         //collider nos contesta a Function
Para darle valores a la función x es necesario la siguiente linea de codigo:

x.value(1) //en donde dentro de los parentesis asignamos el valor que tomara n

Supongamos que queremos evaluar lo siguiente:

a={|n| if(n>10,{"es mayor a 10"},{"es menor a 10"})}
a.value(45)

a={|n| if(n.even,{"es numero par"},{"es numero impar"})}
a.value(8)

a={|n| if(n!=10,{"es distinto a 10"},{"es 10"})}
a.value(10)

//Ahora con Tdef
(
a={|n| if(n>10,{"es mayor a 10"},{"es menor a 10"})};
Tdef(\hu,{
     inf.do{a.value(rrand(2,20)).postln;
                      0.5.wait
                      }}
                     )
                    )
                      
                      Tdef(\hu).play
								Tdef(\hu).stop

////////////////////////////////////////////////////////////////////

RELOJES

iteración

Una operación presenta valores de entrada y de salida. En el siguiente ejemplo a y b toman los valores de entrada y salida

a = 2

b = a + 1

Una iteración es un proceso en el que el valor de salida de una operación se utiliza como un nuevo valor de entrada. Ejemplo

a=0

b=a+1

a=b

b=a+1

a=b

b=a+1

a=b

b=a+1

a=b

b=a+1

a=b

b=a+1

a=b

b=a+1

Pero este algoritmo se simplifica de esta manera.

b = 0

b = b + 1

Si no damos la informaciónn previa éste algoritmo podría interpretarse como una contradicción por lo cual es importante que seamos concientes de lo que implica el algoritmo de iteración dentro del lenguaje de SuperCollider. Matemáticamente el algorítmo simplificado significa esto:

b = 0

b = b + 1  => 0 = 0 + 1 ! Contradicción

Pero  dentro del lenguaje de SuperCollider y otros varios este  algorítmo significa  la iteración que hemos explicado.

////////////////////////////////////////////////////////////////////

Mediante una simple interación como la que vimos podemos construir una estructura que nos será muy útil. 
Esta estructucra simula un contador que nos devuelve una secuencia de números extraída del algoritmo x =  x + 1
Veamos como funciona dentro de un Tdef:

(
Tdef(\reloj,{var contador = 0;
inf.do{contador = contador + 1;
       contador.postln;
        0.1.wait
        }}
       )
      )
      
        Tdef(\reloj).play
        Tdef(\reloj).stop

Pero esta estructura nos devuelve una lista de números infinitos¡¡¡...
En ciertas circunstancias necesitaremos limitar la secuencia a cierto número máximo después del cual se reenicia la cuenta.
Para esto es necesario utilizar el modulo (%)

(
Tdef(\reloj,{var contador = 0;
inf.do{contador = contador + 1;
       (contador % 10).postln;
        0.5.wait
        }}
       )
      )
        
        Tdef(\reloj).play  
       	Tdef(\reloj).stop
       
////////////////////////////////////////////////////////////////////

SWITCH

Es una herramienta que nos permite evaluar una variable y, dependiendo de su valor, asignar acciones en respuesta. Observen como en el ejemplo siguiente podemos asignar un valor a la variable 'a' y el switch realizará las acciones que le indiquemos dependiendo si 'a' vale 0, 1, 2, 3 ó 4.

(

a = 3;

switch(a, 0,{'a es igual a cero'.postln;},
		 1,{'a es igual a uno'.postln},
		 2,{'a es igual a dos'.postln},
		 3,{'a es igual a tres'.postln},
		 4,{'a es igual a cuatro'.postln}
	 );
)

Podemos asignar más de una acción dentro de la función de respuesta. Llamemos a un Synth además del postln.

(
SynthDef(\switch, {|freq=100|
			     var sig, env;
			     sig=Pulse.ar(freq,Line.kr(0.5,0.01,0.1))!2;
			     env=EnvGen.kr(Env.perc(0,01,0.1),doneAction:2);
			     Out.ar(0,sig*env);
			     }).send(s);
);

Synth(\switch)

(

a=1;

switch(a, 0,{'a es igual a cero'.postln; Synth(\switch, [\freq, 100])},
		 1,{'a es igual a uno'.postln; Synth(\switch, [\freq, 2000])},
		 2,{'a es igual a dos'.postln; Synth(\switch, [\freq, 300])},
		 3,{'a es igual a tres'.postln; Synth(\switch, [\freq, 400])},
		 4,{'a es igual a cuatro'.postln; Synth(\switch, [\freq, 500])},
		 24,{'a es igual a cuatro'.postln; Synth(\switch, [\freq, 500])}
	 );
)

En definitiva el Switch se puede ver como un conjunto de varios if pero que nos ahorra trabajo de escritura. Vean cómo resolvemos el código anterior pero hecho con if.

(

a=4;

if(a==0,{'a es igual a cero'.postln; Synth(\switch, [\freq, 100])});
if(a==1,{'a es igual a uno'.postln; Synth(\switch, [\freq, 200])});
if(a==2,{'a es igual a dos'.postln; Synth(\switch, [\freq, 300])});
if(a==3,{'a es igual a tres'.postln; Synth(\switch, [\freq, 400])});
if(a==4,{'a es igual a cuatro'.postln; Synth(\switch, [\freq, 500])});
)

////////////////////////////////////////////////////////////////////
(
(
SynthDef(\puls, {|freq|
			     var sig, env;
			     sig=Pulse.ar(300,Line.kr(0.5,0.01,0.1));
			     env=EnvGen.kr(Env.perc(0,01,0.1),doneAction:2);
			     Out.ar(0,sig*env);
			     }).send(s);
);

(
SynthDef(\sin, {|freq|
			     var sig, env;
			     sig=SinOsc.ar(2000,0,0.3);
			     env=EnvGen.kr(Env.perc(0,01,0.1),doneAction:2);
			     Out.ar(0,sig*env);
			     }).send(s);
);

(
SynthDef(\saw, {|freq|
			     var sig, env;
			     sig=Saw.ar(2000,0.8);
			     env=EnvGen.kr(Env.perc(0,01,0.1),doneAction:2);
			     Out.ar(0,sig*env);
			     }).send(s);
);
)

(
Tdef(\sw,{var contador = 0;
    inf.do{contador = contador + 1;
           (contador %3).postln;
switch(contador%3,  0,{Synth(\puls)},
    				      1,{Synth(\sin)},
    				      2,{Synth(\saw)}
    				);
    				0.3.wait
    				}}
    			)
    		)
    		
    				Tdef(\sw).play
        			Tdef(\sw).stop

////////////////////////////////////////////////////////////////////

(
SynthDef(\saw, {|freq|
			     var sig, env;
			     sig=Saw.ar(freq,0.8)!2;
			     env=EnvGen.kr(Env.perc(0,01,0.1),doneAction:2);
			     Out.ar(0,sig*env);
			     }).send(s);
);

(
Tdef(\sw,{var contador=0;
    inf.do{contador=contador+1;
           (contador%3).postln;
    Synth(\saw,[\freq,((contador%[3,10].choose)+1)*100]);
    				
    				0.1.wait
    				}}
    			)
    		)

					Tdef(\sw).play
					Tdef(\sw).stop