TUTORIAL DE SUPERCOLLIDER 3 - PARTE 6 Rodrigo F. Cadiz, basado en apuntes de Gary S. Kendall Northwestern University ( Server.internal.boot; Server.default = Server.internal; s = Server.default; ) SynthDefs (definicion de sintetizador) - Equivalente a un "patch" or "preset" - Se puede escribir codigo para un SynthDef - SynthDefs con "compilados" por sclang en una especie de bytecode - Se pueden precompilar y almacenar en disco - Tienen dos partes: un nombre y una funcion (ugenGraphFunc) SynthDef( "aSynthDef", // primer argumento: nombre { .... yo soy una ugenGraphFunc ... } // segundo argumento: ugenGraphFunc ) Ejemplo: To make the template functional ( a = SynthDef( "aSynthDef", // nombre { // funcion arg freq = 440; // argumentos a la funcion x = SinOsc.ar(freq, 0, 0.5); Out.ar(0, x) } ).load(s); ) load escribe la definicion y la envia al servidor a.play(s); or a.play; play ejecuta la synthdef Notes: Arguments are important because these can change from note to note. The audio output of Synths is generally handled with the Out unit generator. *ar(bus, channelsArray) - write a signal to an audio bus. The output bus numbers start at 0 and go up by integer for each additional channels. The stereo output channels are 0 and 1. Synth - Representacion en el cliente de un nodo de sintetizador en el servidor - Representa una unica unidad productora de sonido - Lo que hace depende de su SynthDef Ejemplos: y = Synth.new("aSynthDef"); o y = Synth("aSynthDef", nil, s); o y = Synth.new("aSynthDef", [\argument1, value,\argument2, value, etc.], s); y.free; // Con argumentos y = Synth("aSynthDef", [\freq, 262]); z = Synth("aSynthDef", [\freq, 392]); y.free; z.free; Ejemplos ( // DEFINIR UN SYNTHDEF SynthDef( "Ringing", { arg freq; // frequencia es el unico argumento var out; out = RLPF.ar( LFSaw.ar( freq, mul: EnvGen.kr( Env.perc, levelScale: 0.3, doneAction: 2 )), LFNoise1.kr(1, 36, 110).midicps, 0.1 ); 4.do({ out = AllpassN.ar(out, 0.05, [0.05.rand, 0.05.rand], 4) }); Out.ar( 0, out ); }).send(s); ) ( { // Tocar una nota Synth( "Ringing", [ \freq, 440 ] ); }).play(s); ( // Tocar dos notas al mismo tiempo ( { Synth( "Ringing", [ \freq, 440 ] ); Synth( "Ringing", [ \freq, 660 ] ); }).play; ) ( // Para tener pausas, Synth estar dentro de una Routine Routine({ Synth( "Ringing", [ \freq, 440 ] ); 1.0.wait; Synth( "Ringing", [ \freq, 660 ] ); }).play; ) ( // Loop dentro de la Routine permite repetir un patron Routine({ loop ({ Synth( "Ringing", [ \freq, 440 ] ); 1.0.wait; Synth( "Ringing", [ \freq, 660 ] ); 1.0.wait; }); }).play; ) Convirtiendo de forma antigua a nueva Ejemplo anterior { var env, amp; env = Env.perc(attackTime:0.2); amp = EnvGen.kr(envelope: env, levelScale: 0.5, doneAction: 2); SinOsc.ar(freq: 440,phase: 0,mul: amp) }.play; Usando SynthDef y frecuencia como argumento ( // DEFINIR UN SYNTHDEF SynthDef( "SinEnv", { arg frequency; var out, env, amp; env = Env.perc(attackTime:0.2); amp = EnvGen.kr(envelope: env, levelScale: 0.5, doneAction: 2); // argument is now used as the frequency value out = SinOsc.ar(freq: frequency,phase: 0,mul: amp); Out.ar( 0, out ); }).send(s); ) ( // Tocar dos notas ( { Synth( "SinEnv", [ \frequency, 440 ] ); Synth( "SinEnv", [ \frequency, 660 ] ); }).play; ) ( // Loop Routine({ loop ({ Synth( "SinEnv", [ \frequency, 440 ] ); 1.0.wait; Synth( "SinEnv", [ \frequency, 660 ] ); 1.0.wait; }); }).play; ) Se puede agregar un argumento para el canal de salida ( // DEFINICION SynthDef( "SinEnv", { arg frequency, chan; var out, env, amp; env = Env.perc(attackTime:0.2); amp = EnvGen.kr(envelope: env, levelScale: 0.5, doneAction: 2); // argument is now used as the frequency value out = SinOsc.ar(freq: frequency,phase: 0,mul: amp); Out.ar( chan, out ); }).send(s); ) ( // Tocar dos notas ( { Synth( "SinEnv", [ \frequency, 440,\chan, 0 ] ); Synth( "SinEnv", [ \frequency, 660, \chan, 1] ); }).play; ) ( // Loop Routine({ loop ({ Synth( "SinEnv", [ \frequency, 440,\chan, 0 ] ); 1.0.wait; Synth( "SinEnv", [ \frequency, 660, \chan, 1 ] ); 1.0.wait; }); }).play; ) Ejemplo mas complejo ( // Flujo de tonos basado en una escala de Do Mayor var stream, dur, cScale; dur = 1/4; cScale = [60, 62, 64, 65, 67, 69, 71, 72]; // Routines pueden generar secuencias de tonos stream = Routine({ loop({cScale.choose.yield}); }); // Rountines pueden ser tocadas Routine({ loop({ Synth( "Ringing", [ \freq, stream.next.midicps ] ); dur.wait; // used by .play to schedule next occurence }) }).play ) ( // Ejemplo anterior, esta vez los tonos son aleatorios var stream, dur; dur = 1/4; // esta rutina produce una secuencia randon de tonos stream = Routine.new({ loop({ if (0.5.coin, { // run of fifths: 24.yield; // C1 31.yield; // G1 36.yield; // C2 43.yield; // G2 48.yield; // C3 55.yield; // G3 }); rrand(2,5).do({ // arpegio variado 60.yield; // C4 #[63,65].choose.yield; // Eb, F 67.yield; // G #[70,72,74].choose.yield; // Bb, C5, D }); // melodia aleatoria rrand(3,9).do({ #[74,75,77,79,81].choose.yield }); // D5, Eb, F, G, A }); }); // tocar la rutina Routine({ loop({ Synth( "Ringing", [ \freq, stream.next.midicps ] ); dur.wait; }) }).play )