SuperCollider

Existen algunas Notas señaladas dentro del texto. Estas pueden o no ser leidas sin afectar la comprensión de la clase. Sin embargo para el que tenga o quiera tener un conocimiento de música le ayudarán a implementar algunas estructuras musicales dentro del código.

3 clase.

Soluciones a la tarea 3

{LPF.ar(BrownNoise.ar(0.5),160)}.scope
{HPF.ar(Saw.ar(10,0.75)*WhiteNoise.ar(1),10000)}.scope
{Saw.ar(10,0.75)*HPF.ar(WhiteNoise.ar(1),10000)}.scope
{BPF.ar(Saw.ar(2,0.6),3000,100/3000)+BPF.ar(Saw.ar(3,0.4),500,50/500)}.scope
{LFTri.ar(1,0,1)*LPF.ar(Pulse.ar(30,0.1,1))}.scope
{Pulse.ar(117,MouseY.kr(0.5,0.01),0.5)}.scope
{SinOsc.ar(MouseX.kr(60,800),0,0.6)}.scope
{BPF.ar(Dust.ar(100),MouseY.kr(15000,160),60/MouseY.kr(15000,160))}.scope
{Pulse.ar(MouseX.kr(5,20))*(SinOsc.ar(10000,0,0.6)+SinOsc.ar(90,0,0.6))}.scope
{Pulse.ar(MouseY.kr(110,90),0.1,0.5)*Pulse.ar(100,0.1,0.5)+SinOsc.ar(70,0,0.3)+SinOsc.ar(13000,0,0.3)}.scope

Envolventes

La envolvente es la manera en que se despliega un sonido en función del tiempo y la amplitud. Estamos hablando de qué tan fuerte suena nuestro timbre a medida que pasa el tiempo. Por ejemplo una envolvente percusiva es como la de un tambor o un piano, en donde el sonido comienza  muy fuerte e inmediatamente se va escuchando mas quedito. Los elementos de la envolvente más comunmente identificados son:

ataque (attack) : que tan rápido alcanza nuestro sonido su punto de máxima amplitud.
decaimiento (decay): que tan rápido alcanza nuestro sonido su punto de estabilidad o sostenimiento.
sostenimiento (sustain): cuanto tiempo esta nuestro sonido en el punto de estabilidad en el que no sube ni baja de amplitud.
liberación (release): el tiempo que tarda el sonido en llegar del punto de sostenimiento a la amplitud cero.

Estos términos son conocidos en inglés como Attack, Decay, Sustain y Release. Algunas veces se utilizan sus siglas para referirse a la envolvente que posee estos elementos: ADSR. No todas las envolventes tienen todos estos elementos. En algunas envolventes se necesita menos información para crear su contorno. Podemos imaginar por ejemplo una envolvente que sólo tenga ataque y liberación (attack, release). En SuperCollider para generar una envolvente recurrimos a la clase EnvGen. Las envolventes pueden ser pensadas como una secuencia de números que se despliega en el tiempo. Esta secuencia puede ser usada para varios prósitos que pueden involucrar una forma de onda o una modulación. Por el momento nuestras envolventes no generarán sonido, solo determinan la manera en que su amplitud  se desarrolla en el tiempo, asi que EnvGen trabajará con el rate de control .kr.

EnvGen.kr EnvGen.kr(envolvente,gate,doneAction:2)
Genera una envolvente que puede dar forma a la amplitud de nuestro sonido.

envolvente - En el argumento envolvente colocamos alguna de las muchas envolventes que posee SuperCollider en la clase Env.

Env.adsr(ataque, decaimiento, volumen, decaimiento ) /* Envolvente de duracion indeterminada para sonidos sostenidos. El segundo argumento es de volumen, no de duracion. */

Env.perc(ataque, liberación) /* Envolvente de ataque percusivo, argumentos en segundos. Duracion determinada por la suma del attack mas el release.*/
//Ejemplo:
Env.perc(0.01,1).plot  /* Aqui el attack dura 0.01 seg y el release 1 seg. 0.01 + 1 = 1.01 . Observar que con el mensaje .plot podemos ver la gr'afica de la envolvente*/

Env.asr(ataque, volumen, decaimiento ) /* Envolvente de duracion indeterminada para sonidos sostenidos. El segundo argumento es de volumen, no de duracion. */
Env.asr(0.01,1,1).plot /* Se tardara una centésima de segundo en alcanzar su amplitud máxima, que es 1 como lo indica el segundo argumento. Una vez alcanzada se quedara ahí hasta que nosotros le indiquemos cuando generar el release que se tardará 1 segundo en alcanzar el cero. */

gate - 1 abre la envolvente, 0 la cierra. Default 1. Las envolventes de duración determinada como  Env.perc no necesitan cerrarse.

doneAction - una acción que se realiza cuando la envolvente ha finalizado. doneAction:2 elimina el Synth del servidor.

Ejemplo de Env.asr (Ustedes solo fijense en la letra grande, aunque no les hace daño la chiquita.)

SynthDef("prueba", {|gate| Out.ar(0,Pulse.ar(15)*EnvGen.kr(Env.asr(0.01,1,3),gate,doneAction:2))}).send(s)                                                          

a=Synth("prueba", ["gate", 1]) // Lo prenden
a.set("gate", 0)  // Lo apagan

Para aplicar la envolvente a un sonido multiplicamos la envolvente por el sonido. Ejemplos:

{Saw.ar(40)*EnvGen.kr(Env.perc(0.01,1),doneAction:2)}.scope

{Saw.ar(40)*EnvGen.kr(Env.asr(1,1,4),Line.kr(1,0,2),doneAction:2)}.scope 

Observar que en el argumento gate hemos colocado un UGen Line que genera una línea de números que va desde el 1 al 0 en 2 segundos. Esto nos abre y cierra la envolvente automáticamente (ver el Help de Line)

Canales
El sonido análogo o digital puede salir por uno o varios canales. Nosotros estamos acostumbrados a escuchar la música en dos canales que suenan en una bocina cada uno. Esto es conocido como estereofonía y es por eso que al aparato de sonido de nuestro auto o casa le llamamos "el estereo".
Existen aparatos que nos permiten sacar el sonido por mas de dos canales. Estos aparatos son conocidos como tarjetas o interfaces de audio. Las hay de 2,4 u 8 canales por lo menos. Además estas interfaces se pueden conectar entre sí sumando la cantidad de canales. En SuperCollider existen varias clases que nos ayudan a trabajar con los canales de audio por donde queremos que salga nuestro sonido. Aqui veremos 2: Out.ar y Pan2.ar.

Out.ar Out.ar(canal,señal)
Saca el sonido por un canal especifico. Ese canal específico define un punto de partida u offset apartir del cual se va a distribuir el sonido.

canal :  0 = izq, 1 = der.  3,4,5,...multicanal
señal :  cualquier oscilador que puede estar multiplicado por una envolvente.

Ejemplos:

{Out.ar(0,Saw.ar(40)*EnvGen.kr(Env.perc(0.01,1),doneAction:2))}.scope  // izquierda

{Out.ar(1,Saw.ar(40)*EnvGen.kr(Env.perc(0.01,1),doneAction:2))}.scope  // derecha

Pan2.ar Pan.ar(señal,posicion)
Distribuye el sonido entre dos canales consecutivos conservando su potencia. Es decir, que no suena mas fuerte cuando esta en los dos canales al mismo tiempo ni mas quedito cuando está solo en uno o en otro. Si el Pan2 esta dentro de un Out los canales consecutivos en los que se distribuyen se cuentan a aprtir del offset del Out.

señal : cualquier oscilador o generador de sonido
posicion : -1 izquierda, 1 derecha y con todo el intervalo continuo extrapolando el sonido entre los dos canales o bocinas.

{Pan2.ar(Pulse.ar(100,0.01),-1)}.scope
{Pan2.ar(Pulse.ar(100,0.01),-0.7)}.scope
{Pan2.ar(Pulse.ar(100,0.01),0)}.scope // En medio.
{Pan2.ar(Pulse.ar(100,0.01),0.3)}.scope
{Pan2.ar(Pulse.ar(100,0.01),1)}.scope

{Out.ar(0,Pan2.ar(Dust.ar(1000),0))}.scope // distribuye la señal entre el canal 0 y 1
{Out.ar(1,Pan2.ar(Dust.ar(1000),0))}.scope // distribuye la señal entre el canal 1 y 2. Si no tenemos una interfase de audio que nos permita expandir los canales solo se va a escuchar al canal 1. Solo tenemos 2 canales en nuestras computadoras que el Collider reconoce como el 0 y el 1.

Lenguaje

.midicps // convierte un  numero de código MIDI a su equivalente en frecuencia en hertz.
.cpsmidi // convierte una frecuencia en hertz a su equivalente en código MIDI.

El código MIDI para designar las notas son

60=Do (índice 5 o central)
61=Do # o Re b
62=Re
63=Re # o Mi b
64=Mi
65=Fa
66=Fa # o Sol b
67=Sol
68=Sol # o La b
69=La
70=La # o Si b
71=Si
72=Do (índice 6. Una octava erriba del Do índice 5)

Si queremos convertir el código MIDI 60 ( Do ) en frecuencia en Hertz lo hacemos mandándole el mensaje .midicps (cps=cilos por segundo)

60.midicps
69.midicps

Para el inverso aplicamos el mensaje cpsmidi

261.6255653006.cpsmidi
440.cpsmidi

.midiratio // convierte intervalos en razones o quebrados

Los intervalos para usar con el mensaje midiratio son expresados en cantidad de semitonos. Está relacionado con el método de Forte para los pitch class sets:

0=unísono
1=segunda menor
2=segunda mayor
3=tercera menor
4=tercera mayor
5=cuarta justa
6=tritono
7=quinta justa
8=sexta menor
9=sexta mayor
10=séptima menor
11=séptima mayor
12=octava

Los número negativos denotan intervalos descendentes. Entonces para aplicar este mensaje mandamos el mensaje . midiratio al intervalo que deseamos obtener y lo multiplicamos por una frecuencia fundamemntal que nosotros damos. Ejemplo:

440 * 3.midiratio // nos da una tercera menor a partir de La.
440 * -5.midiratio // nos da una carta descendente a partir de La.

Array  // un conjunto de elementos ordenados. Se escriben dentro de corchetes [ ] y se separan por comas.

['hola', 'hi', 'salud', 'ciao']
[0,1,2,3,4]

[0,1,2,3,4].choose
[60,62,64,65,67].midicps // Nota 1
[ 261.6255653006, 293.66476791741, 329.62755691287, 349.228231433, 391.99543598175 ].cpsmidi

Tarea 3

{____.ar(0,SinOsc.ar)}.scope;
{Pan2.ar(WhiteNoise.ar,____)}.scope;
{Out.ar(1,Saw.ar(100)*EnvGen.kr(__Env__.perc(0.01,2),doneAction:___2))}.scope;
{______.ar(WhiteNoise.ar,[100,200,400,1000,1500,5000].________,0.1)*EnvGen.kr(Env.perc(0.01,0.5),doneAction:2)}.play;
{Pan2.ar(SinOsc.ar([60,64,67,72].choose._______),[____,____].choose)}.play;
{[LPF,HPF].______.ar(BrownNoise.ar,800)}.play;

Notas

1

Un poco de música para el que quiera

Diferentes escalas usando el código MIDI

[60,62,64,65,67,69,71,72].midicps // un array con las notas de la escala mayor
[60,62,63,65,67,68,70,72].midicps // un array con las notas de la escala menor natural
[60,62,64,66,68,70,72].midicps // la escala de tonos enteros
[60,62,63,65,66,68,69.72].midicps // La escala simétrica tono, 1/2tono
[60, 61, 63, 64, 66, 67.72, 71].midicps // La escala simétrica 1/2tono, tono 

Las mismas escalas expresadas en intervalos y usando midiratio

[ 0, 2, 4, 5, 7, 9, 11, 12 ].midiratio // un array con las notas de la escala mayor
[ 0, 2, 3, 5, 7, 8, 10, 12 ].midiratio // un array con las notas de la escala menor natural
[ 0, 2, 4, 6, 8, 10, 12 ].midiratio // la escala de tonos enteros
[ 0, 2, 3, 5, 6, 8, 9, 12 ].midiratio // La escala simétrica tono, 1/2tono
[ 0, 1, 3, 4, 6, 7, 12, 11 ].midiratio // La escala simétrica 1/2tono, tono 

Notar que para convertir las escalas expresadas en MIDI en el priper conjunto de arrays a las escalas expresadas en intervalos del segundo conjunto basta con restarles 60. Veamoslo en el primer ejemplo de las escala mayor

[60,62,64,65,67,69,71,72]-60 == [ 0, 2, 4, 5, 7, 9, 11, 12 ]