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.
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 ]