Taller de Audio del Centro Multimedeia del CNA

CONSOL 08

Congreso Nacional de Software Libre 

El jueves 21 de febrero un grupo de colaboradores del Centro Multimedia fue invitado a participar en el Congreso Nacional de Software Libre 08 http://www.consol.org.mx/2010/?pagina=consol celebrado en la UACM.


Se presentaron ponencias acerca de SuperCollider v3, Processing, Arduino y ARTtoolkit,

A continuación el texto que sirvió como referencia para la presentación de SuperCollider v3



introducción


1- Es un poderosos lenguaje de programación para la sintesis de audio y la composición algorítmica basado en Small talk.

2- Originalmente desarrollado por James McCartney.

3- Es un lenguaje interpretado.

4- Hoy en día SuperCollider es distribuido bajo licencia publica.


un breve repaso en la historia de SuperCollider




-la versión 1.0 de Supercollider es considerada la suma de dos programas [Synth-O-Matic y Pyre] que comenzaron siendo objetos para Max/MSP.

-la versión 2.0 es la primera aproximación de lo que conocemos hoy en dia como SuperCollider, es decir, un lenguaje de programación orientado a objetos para la sintesis de audio en tiempo real y/o la composición algorítmica.

-Ambas versiones eran "código-cerrado" y se debian de comprar. Estas aplicaciones solo corria en Mac OS9.

 

James McCartney ingresa a trabajar para Apple y decide abrir el código de Supercollider2, a partir de este momento todas las versiones de SuperCollider serán de código abierto

 

Trabajando para Apple comienza diseñar una nueva versión de SuperCollider radicalmante diferente de las anteriores.

Esta versión es la que conocemos como SuperCollider3 o SuperCollider Server

Hoy en día, gracias a la comunidad dedicada a mantener el proyecto, SuperCollider3 corre en OSX, Linux [Debian, Ubuntu, Fedora, pure dyne [sobre Emac's]]-

Gran parte de los desarrolladores enfocan sus investigaciones en la versiones de SuperCollider para OSX, aunque las versiones para Linux son muy estables.

nota: en Ubuntu, por nombrar el caso mas conocido para mi, la creación de GUI's se hacen por medio de Swing OSC y algunas libreria externas no estan incluidas como por ejemplo BBCUT.

 

la ultima version de SuperCollider es la 3.4 http://sourceforge.net/project/showfiles.php?group_id=54622

 

//////////// change log /////////////

// user-visible changes in preparing SC v3.2, SuperCollider book release:

// HEADLINES:

2007-11-xx new suite of machine listening ugens - Loudness, BeatTrack, Onsets, KeyTrack, SpecCentroid, SpecPcile, SpecFlatness - nc, ds
2008-01-06 FreeBSD compatibility - hb
2008-01-10 Quarks updating on OSX should now be easier for first-time users; commands are run in a separate terminal window - ds
2008-01-15 "Advanced find" in Mac interface - jt
2008-01-20 Buffer.copy changed to match other .copy methods - now copies language-side object rather than server buffer. Buffer.copyData can be used to copy data from one server buffer to another - jh
2008-01-20 - add volume controls to the Server and Server guis - jp
2008-01-xx Pattern library implementation changes, Pfx, Pbus, Pgroup etc. - rk, jr, jh
2008-01-26 TDuty outputs trigger first, not level. for backwards compatibility TDuty_old - jr
2008-02-03 moved the search location for "startup.rtf" on Mac - now searches in system, then user, "Application Support/SuperCollider" folders - ds
// BUGFIXES:

2007-11-16 bug fixes for MIDIIn in connect/disconnect methods. split MIDIOut.sysex into user method and primitive (breaks with previous implementation). default value for uid arg in MIDIOut.new. - mb
2007-11-18 fixed a bug in prTry / protect - jr
2007-11-27 lock avoided in nextTimeOnGrid
2007-12-12 Node-setn fixed when using integers as control indices - jr
2008-01-16 fixed Pen: bug with fillRect, fillOval and fillColor (bugtracker id 1837775) - jt
2008-01-20 CheckBadValues rate-checking was too restrictive - ds
2008-01-20 fix for Saw and Pulse's offset noise on first instantiation, thanks to hisao takagi - ds
2008-01-26 TDuty / Duty does not drift anymore - jr
2008-02-07 Fixed hang and incorrect background drawing in Cocoa scrollviews - sw
// OTHER ADDITIONS / IMPROVEMENTS:

2007-11-16 MIDIOut.connect and disconnect - mb
2007-11-18 added T2A UGen - jr
2007-11-18 Refactoring of Document class, including new CocoaDocument class to handle the Cocoa-specific (SuperCollider.app) document management - ds
2007-11-18 More macros available in the plugin API for UGen programmers: GET_BUF, SIMPLE_GET_BUF, FULLRATE, RGET, RPUT - ds
2007-11-20 UnixPlatform:arch method - jp
2007-11-20 FFTTrigger UGen - a ugen to create "fake" (empty) FFT chains - jp
2007-11-21 StartUp protects its added functions from each other - if one fails this no longer prevents others from running - ds
2007-11-25 added Pclutch and moved StreamClutch to common - jr
2007-11-27 Function:inEnvir added - jh
2007-12-12 added Collection.flatIf - jr
2007-12-15 added control rate functionality to NumRunningSynths - jr
2008-01-08 martin rumori's DiskIn bugfix and loop enhancement - jp
2008-01-10 String:runInTerminal method - ds
2008-01-11 poll now works for scalar ugens - jr
2008-01-15 Collection:maxIndex and Collection:minIndex - nc
2008-01-24 Server.options.rendezvous to (de)activate Rendezvous if desired - ds
2008-01-24 demand ugens accept audio rate inputs correctly - jr
2008-01-26 added Dbufwr ugen, for writing to buffers from a demand ugen chain - jr
2008-01-27 Main:version and associated methods for programmatically determining which version SC is - ds
2008-02-03 Server:defaultRecDir class variable, to allow user to specify default rec location - ds
2008-02-07 SCScrollView and SCScrollTopView no longer fire their action when scrolled programatically - sw

///////////////////////////// SuperCollider v3.1.1, released 2007-11-16 /////////////////////////////

// user-visible changes in preparing SC v3.1.1, bugfix release of v3.1:

// BUGFIXES:

2007-11-09 re-organized the main help file - rb
2007-11-14 fix for .asStringPrec, to avoid crashes on intel systems for large precision values - jt
// OTHER ADDITIONS / IMPROVEMENTS:

2007-11-14 added a preprocessor to the interpreter - jr
2007-11-14 added a startup message specifying how to get help - rk
///////////////////////////// SuperCollider v3.1, released 2007-10-31 /////////////////////////////

// user-visible changes since 2007-09-22 (for first point release):

// HEADLINES:

2007-09-27 SparseArray class added - jr
2007-09-28 Help.gui added - ds
2007-10-01 FFT and IFFT rewrite - now using more efficient libs, also allows user to vary the overlap and the window type, also large-sized FFTs are possible - ds
2007-10-02 UnpackFFT and PackFFT added - these allow for flexible frequency-domain manipulations inside synths - ds
2007-10-04 Pkey and Pif added - hjh
2007-10-05 reformed Patterns - all patterns accept patterns as arguments - jr
2007-10-08 change to UGen plugin loading fixes the audio dropout issue that various users have experienced - rb
2007-10-08 GeneralHID crossplatform HID wrapper - mb
2007-xx-xx many improvements to Quarks package-management system. gui improvements, dependency-handling improvements, etc - various
2007-10-20 added a Glossary file - sw
2007-10-xx various new help files added, and many help files improved - various
2007-10-26 changed Cmd-? to Cmd-D in lieu of the default help menu shortcut in Leopard. Also changed Cmd-Shift-K (clear post window) to Cmd-Shift-C to avoid accidental recompiles. - rb
// OTHER ADDITIONS / IMPROVEMENTS:

2007-09-22 change log added, much rejoicing
2007-09-25 added packagesource.sh script to produce source code bundles - ds
2007-09-28 IdentityDictionary:doesNotUnderstand now warns if adding a pseudo-method which overrides a real method - jr
2007-09-28 String:openHTMLFile added - ds
2007-10-04 Integer:collect and Integer:collectAs methods added - ds/jr
2007-10-05 Dwhite:new and Dbrown:new have default values for lo and hi - jr
2007-10-10 SC no longer automatically writes data (synthdefs, archive.scxtar) to the application folder - instead writes to "app support". This fixes problems with running SC using an unprivileged user account - ds
2007-10-16 SequenceableCollection:median speed improvement, approx ten times faster in many cases - ds
2007-10-20 Object:deprecated and DeprecatedError added to allow for method deprecation - sw
2007-10-21 Amplitude : attackTime and releaseTime can be modulated now - jr
2007-10-25 Collection : histo method improved and moved from mathLib to common - jr
2007-10-30 improvements to cocoa Gui, including SCUserView improved to support layering and own draw hook - jt, sciss
2007-10-31 refactored Pbrown, added Pgbrown - jr
// BUGFIXES:

2007-09-29 takekos bug fixed (obscure issue with garbage collection in arrays) - jm
2007-10-01 fixed off by one bug in Dswitch and Dswitch1 that caused a server crash - jr
2007-10-09 fixed deadlock and other problems in NSAttributedStringAdditions.m - rb
2007-10-11 fixed inaccurate automatic determination of whether SC is running as standalone - ds
2007-10-14 .quark files now saved correctly as plain-text, not RTF - ds
2007-10-24 fixed a bug in Pbeta - jp

Instalación

OSX:

Se puede obtener SuperCollider3 en binario pre-copilado o en codigo fuente. El binario puede ser bajado desde http://sourceforge.net/projects/supercollider. El codigo fuente puede ser bajado de SourceForge CVS repository.

Linux: 

No hay binario para Linux. Hay que copilar el codigo fuente desde el sistema de control de versiones [CVS]. requerimientos:

 
ALSA,Jack
libsndfile>=1.0
gcc>=3.0
pkgconfig>=0.14.0
autoconf>=2.52
automake>=1.4-p4
libtool>=1.4.2a

aqui un link para la instalación en Ubuntu 7.10: http://swiki.hfbk-hamburg.de:8888/MusicTechnology/847

Arquitectura


SuperCollider trabaja sobre la estructura cliente servidor, de hecho Supercollider son dos programaen uno.  

scsynth ------> como el servidor
sclang -------> como cliente
el cliente se comunica con el servidor mediante el protocolo OSC [open sound control, que en pocas palabras, es un versión aumentada y corregida del protocolo MIDI]

scsynth, el servidor..

1-el servidor de supercollider es el que lo hace un lenguaje realmente poderoso. 2-tu puedes crear multiples synth's en el servidor, cada synth crea un nodo que posibilita la comunicacion con el. 3-los nodos puedes ser agrupados y contralados al mismo tiempo.

 

 

sclang, el cliente..

1-el cliente es usado para definir los synth y pasarlos al servidor. Este tambien es usado para generar GUI's y que estas envien informacion al servidor. 2-Los Synth son definidos a partir de SynthDef. 3-Los SynthDef contienen informacion acerca de como estan creada las interralaciones entre variables y ugen´s.

Ugen's


1-Los Ugen son objetos que procesan o generan señales de audio 2-Estas correr a dos velocidades audio rate:44100, y control rate

++algunos ejemplos++


 

s.boot //prendemos el servidor local

//un SynthDef con el tag consol para poder indentificarlo.
//un filtro resonante de bajos aplicado a un oscilador diente de sierra.

(
SynthDef(\consol,{|gate=1,amp=0.6,frec=100,cutoff=100,ancho=0.1,rq=0.1|
 var sen,env;
 sen=RLPF.ar(Saw.ar(frec*[1,1.01],amp),cutoff,rq);
 env=EnvGen.kr(Env.asr(1,amp,0.4),gate,doneAction:2);
 Out.ar(0,sen*env)
 }).send(s)
 )
 //suena el Synth.
 a=Synth(\consol)
 
 //con el metodo .set modificamos los argumentos.
 a.set(\frec,100,\rq,0.2,\cutoff,1400)
 
 a.set(\gate,0)
//el mismo ejemplo salvo por una diferencia, la frecuencia del oscilador es modificada por los valores del mouse en X

(
SynthDef(\consol,{|gate=1,amp=0.6,frec=100,cutoff=4300,ancho=0.1,rq=0.2|
 var sen,env;
 sen=RHPF.ar(Saw.ar(MouseX.kr(200,1000)*[1,1.01],amp),cutoff,rq);
 env=EnvGen.kr(Env.asr(0,amp,0),gate,doneAction:2);
 Out.ar(0,sen*env)
 }).send(s)
 )

a=Synth(\consol)
a.set(\gate,0)

       
(
SynthDef("serrucho",{ | freq, gate, pan |
    var signal, env;
 signal= Saw.ar(Lag2.kr(freq, Rand(0.52, 1.5)) +
 LFNoise2.kr(Rand(35.0, 385.0),XLine.kr(freq, 1, Rand(0.3, 4.0))));
 signal= Pan2.ar(signal, pan);
    env= EnvGen.kr(Env.asr(0.001, 0.3, Rand(0.1, 3.0)),gate,doneAction: 2);
             Out.ar(0, signal * env)}).send(s)
    )
                                                

(
var ventana, boton, synth, freq;
 ventana= SCWindow("Serrucho", Rect(819, 3, 200, 200));
    boton= SCButton(ventana, Rect(30, 20, 140, 140));
   
    boton.states= [[ "Un Serrucho", Color.white, Color(1.0, 0.4) ],
            [ "Glissando de 3 octavas",Color.white, Color(1.0, 0.7) ],
            [ "Apagalo", Color.white, Color.gray(0.6) ]];
   
    boton.action = {| estado |
    if (estado.value == 1,{ synth = Synth("serrucho",
 [\freq, freq = exprand(100.0, 2000.0),
             \pan, 1.0.rand2,
         \gate, 1 ])});
    if (estado.value == 2,{ synth.set(\freq, freq * 0.125 ) });
    if (estado.value == 0,{ synth.set(\gate, 0) })};
    ventana.front
    )   
//algo que nos puede motivar

s.boot
(
(
SynthDef(\bombon, {|freq, dur, amp, wrap=0.6|
    var sig, env;
    sig=SinOsc.ar(Line.kr(freq*1.5,[freq,freq*1.1], dur),pi/2,amp);
 sig=sig+EnvGen.ar(Env([0,1],[0]))*amp;
    sig=Pan2.ar(sig,0);
    env=EnvGen.kr(Env.perc(0,dur),doneAction:2);
    Out.ar(0,sig.wrap2(wrap)*env);
    }).send(s);
);

(
SynthDef(\tarolam, {|freq, dur, amp|
    var sig, env;
    sig=SinOsc.ar(Line.kr(freq*1.5,[freq,freq*1.1], dur),pi/2,amp);
    sig=sig+HPF.ar(WhiteNoise.ar(amp/2),1000);
    //sig=sig+EnvGen.ar(Env([0,1],[0]));
    sig=Pan2.ar(sig,0);
    env=EnvGen.kr(Env.perc(0,dur),doneAction:2);
    Out.ar(0,sig*env);
    }).send(s);
);

(
SynthDef(\hi, {|freq, dur, amp|

var sig, env;

sig=SinOsc.ar(Array.rand(10,1000,17000),0,amp/10).mean;
sig=sig+RHPF.ar(WhiteNoise.ar(amp/8),1000);
//sig=sig+EnvGen.ar(Env([0,1],[0]));
sig=Pan2.ar(sig,0);
env=EnvGen.kr(Env.perc(0,dur),doneAction:2);
Out.ar(0,sig*env);
}).send(s);
);

(
SynthDef(\abierto, {|freq, dur, amp|
    var sig, env;
    sig=SinOsc.ar(Array.rand(10,1000,17000),0,amp/10).mean;
    sig=sig+RHPF.ar(WhiteNoise.ar(amp/8),1000);
    sig=Pan2.ar(sig,0);
    env=EnvGen.kr(Env([0,1,1,0],[0,dur,0]),doneAction:2);
    Out.ar(0,sig*env);
}).send(s);
);



(
// Comentando y descomentando se puede cambiar el buffer
//a=Buffer.read(s,"sounds/a11wlk01-44_1.aiff");
//b=1;
a=Buffer.read(s,"sounds/frase4.AIFF");b=0.5;
SynthDef(\buf, {|dur, amp=1, pos, rate|
 var sig, env;
 sig=RHPF.ar(PlayBuf.ar(1,a.bufnum,rate,1,pos),MouseY.kr(1000,60),0.1, amp);
    sig=Pan2.ar(sig,0);
    env=EnvGen.kr(Env([0,1,1,0],[0,dur,0]),doneAction:2);
    Out.ar(0,sig*env*amp*b);
}).send(s);
)
)

Synth(\bombon, [\freq, 50, \dur, 0.5, \amp, 0.5])
Synth(\tarolam, [\freq, 200, \dur, 0.1, \amp, 0.5])
Synth(\hi, [\freq, 2000, \dur, 0.1, \amp, 0.5])
Synth(\buf, [\rate, 20, \dur, 0.5, \amp, 0.5, \pos, 107520/10])

~ampbombo=1;
~ampTarola=1;
~ampTarola=0;
~ampbombo=0;

~tempoBatacaViernes=0.15
//~tempoBatacaViernes=Array.rand(3,1,0.01).choose

//Tdef(\cambioTempo, {inf.do{~tempoBatacaViernes=Array.rand(3,1,0.01).choose;0.2.wait}}).play
//Tdef(\cambioTempo).stop

~pseqBuf=(0!12)++Array.rand(4,13,15)
~pseqBuf.size

~pseqBuf=(0!10)++Array.rand(6,13,15)

(
Tdef(\bataca, {var si=0, volBombon=[0,2,3,7].choose.midiratio*30;
inf.do{|i|
  switch(si%16, 0,{Synth(\bombon, [\freq, volBombon, \dur, 0.95, \amp, 0.5*~ampbombo])},
     2,{Synth(\buf, [\rate, 2, \dur, 0.15, \amp, 0.5, \pos, 107520/10])},
     15,{Synth(\buf, [\rate, 21, \dur, 0.15, \amp, 0.5, \pos, 107520/10])},
     7,{Synth(\buf, [\rate, 1, \dur, 0.2, \amp, 0.5, \pos, 107520/10])},
     3,{Synth(\bombon, [\freq, volBombon, \dur, 0.95, \amp, 0.5*~ampbombo])},
     4,{Synth(\tarolam, [\freq, 200, \dur, 0.1, \amp, 0.5*~ampTarola])},
     6,{Synth(\bombon, [\freq, volBombon, \dur, 0.95, \amp, 0.5*~ampbombo])},
     10,{Synth(\bombon, [\freq, volBombon, \dur, 0.95, \amp, 0.5*~ampbombo])},
     12,{Synth(\tarolam, [\freq, 200, \dur, 0.1, \amp, 0.5*~ampTarola])},
     14,{Synth(\abierto, [\freq, 200, \dur, ~tempoBatacaViernes*2, \amp, 0.375])}
                               );
Synth(\hi, [\freq, 2000, \dur, 0.1, \amp, 0.25]);
 if(si%16==16.rand,{Synth(\tarolam, [\freq, 200, \dur, 0.1, \amp, 0.25*~ampTarola])});
 if(0.4.coin,{Synth(\bombon, [\freq, 50, \dur, 0.5, \amp, 0.25*~ampbombo])});
//if(0.5.coin,{Synth(\buf, [\rate, rrand(0.2,0.5), \dur, rrand(0.1,0.7), \amp, 0.5, \pos, 107520/10])});
    si=si+1;
    ~tempoBatacaViernes.wait;
}}).quant_(0)
)

Tdef(\bataca).play;
Tdef(\bataca).stop;

(
Tdef(\bataca, {var si=0, volBombon=Array.rand(4,30,50).midicps.choose;
inf.do{|i|switch(si%16, 0,{Synth(\bombon, [\freq, volBombon, \dur, 0.95, \amp, 0.5*~ampbombo]);
(
SynthDef(\bajoBombon, {|gate=1| var freq, sig, env;
freq=Demand.kr(Impulse.kr(1/~tempoBatacaViernes),0,
 Dseq(Array.rand(4,30,50).midicps,100000));
sig=SinOsc.ar([freq,freq*2],0,[0.5,0.025]);
 env=EnvGen.kr(Env.asr(0,1,0),gate, doneAction:2);
Out.ar(0,sig*env);
}).send(s);
);
~bajoBombon.set(\gate, 0);
~bajoBombon=Synth(\bajoBombon);
},
2,{Synth(\buf, [\rate, 2, \dur, 0.15, \amp, 0.5, \pos, 107520/10])},
15,{Synth(\buf, [\rate, 21, \dur, 0.15, \amp, 0.5, \pos, 107520/10])},
7,{Synth(\buf, [\rate, 1, \dur, 0.2, \amp, 0.5, \pos, 107520/10])},
3,{Synth(\bombon, [\freq, volBombon, \dur, 0.95, \amp, 0.5*~ampbombo])},
4,{Synth(\tarolam, [\freq, 200, \dur, 0.1, \amp, 0.5*~ampTarola])},
6,{Synth(\bombon, [\freq, volBombon, \dur, 0.95, \amp, 0.5*~ampbombo])},
10,{Synth(\bombon, [\freq, volBombon, \dur, 0.95, \amp, 0.5*~ampbombo])},
12,{Synth(\tarolam, [\freq, 200, \dur, 0.1, \amp, 0.5*~ampTarola])},
14,{Synth(\abierto, [\freq, 200, \dur, ~tempoBatacaViernes2, \amp, 0.375])}
                               );
Synth(\hi, [\freq, 2000, \dur, 0.1, \amp, 0.25]);
 if(si%16==16.rand,{Synth(\tarolam,
 [\freq, 200, \dur, 0.1, \amp, 0.25*~ampTarola])});
 if(0.4.coin,{Synth(\bombon,
 [\freq, volBombon, \dur, 0.5, \amp, 0.25*~ampbombo])});
 if(~pseqBuf.find([i%16])!=nil,
 {Synth(\buf, [\rate, rrand(0.2,0.5), \dur,
 ~tempoBatacaViernes*8, \amp, 1/3, \pos, 107520/10])});
        si=si+1;
        ~tempoBatacaViernes.wait;
        }}).quant_(0)
)



Tdef(\bataca).play;
Tdef(\bataca).stop;
~bajoBombon=Synth(\bajoBombon);


(
SynthDef(\bajoBombon, {|gate=1| var sig, env;
sig=SinOsc.ar(Demand.kr(Impulse.kr(1/~tempoBatacaViernes),
0,Dseq(Array.rand(4,30,50).midicps,100000)),0,0.25);
env=EnvGen.kr(Env.asr(0,1,0),gate, doneAction:2);
Out.ar(0,sig*env);
}).send(s);
);
~bajoBombon.set(\gate, 0);
~bajoBombon=Synth(\bajoBombon);

~replace={ReplaceOut(0,RHPF.ar(In.ar(0),MouseY.kr(100,15000),0.1))}
~replace.