Moisés Gabriel Cachay Tello
Creator, destructor.
* con Python
Puede verse esta presentación online visitando:
El código fuente mostrado aquí puede encontrarse en la siguiente dirección:
La naturaleza del Sonido
¿Qué es el sonido?
El mundo físico
El mundo digital
La naturaleza del Sonido
El mundo Físico
La perturbación de un objeto produce una onda que se propaga a través de un medio (como el aire).
La naturaleza del Sonido
El mundo Físico
Estas ondas tienen ciertas características:
La naturaleza del Sonido
El mundo Físico
Las ondas llegan a nuestros oidos tras propagarse y nuestros cerebros las interpretan como 'sonido'.
La naturaleza del Sonido
El mundo Físico
La forma / complejidad de la onda depende del objeto que la produce.
La naturaleza del Sonido
El mundo Digital
En el mundo físico, las ondas son infinitamente densas; en el mundo digital, tenemos espacio limitado. Por tanto guardamos 'muestras' de las ondas.
La naturaleza del Sonido
El mundo Digital
Estas muestras no son más que cantidades numéricas que representan la forma de la onda a lo largo del tiempo.
La naturaleza del Sonido
El mundo Digital
Una cantidad de muestras considerable es necesaria para asegurar la calidad del sonido. Se tiene como estándar 44100 muestras por segundo.
La naturaleza del Sonido
El mundo Digital
Adicionalmente, otro factor en la calidad es la cantidad de bits de cada muestra. Mientras más bits tengamos, el sonido será más fiel al original en amplitud. 16 bits es el estándar actual.
¿Y Ahora qué?
¡Ya podemos trabajar sobre el sonido en forma de código y empezar a hablar sobre música!
La Música y el Código
¿Cuánto sabemos? ¿Cuánto sabremos?
La Música y el Código
¡Escúchame mundo!
440 Hz
La Música y el Código
¡Escúchame mundo!
frecuencia = 440.0
muestras_por_segundo = 44100
duracion = 1.0
muestras_totales = duracion * muestras_por_segundo
ciclos_por_muestra = frecuencia / muestras_por_segundo
incremento = 2 * math.pi * ciclos_por_muestra
fase = 0
muestras = []
for i in range(int(muestras_totales)):
muestra = math.sin(fase)
fase += incremento
muestras.append(muestra)
La Música y el Código
¡Escúchame mundo!
nombre_archivo = 'a.wav'
archivo = wave.open(nombre_archivo, 'w')
archivo.setparams((1, 2, muestras_por_segundo, 0, 'NONE', 'not compressed'))
valores = []
for muestra in muestras:
valor_bit = struct.pack('h', muestra * 32767)
valores.append(valor_bit)
valores_str = ''.join(valores)
archivo.writeframes(valores_str)
archivo.close()
La Música y el Código
Octavas
La Música y el Código
Octavas
frecuencias = [220.0, 440.0, 880.0]
muestras_por_segundo = 44100
duracion = 1.0
muestras_totales = duracion * muestras_por_segundo
muestras = []
for frecuencia in frecuencias:
ciclos_por_muestra = frecuencia / muestras_por_segundo
incremento = 2 * math.pi * ciclos_por_muestra
fase = 0
for i in range(int(muestras_totales)):
muestra = math.sin(fase)
fase += incremento
muestras.append(muestra)
La Música y el Código
Tonos y Semitonos
S
T
S
La Música y el Código
Tonos y Semitonos
La Música y el Código
Tonos y Semitonos
raiz_doceava_de_dos = 2 ** (1.0/12)
actual = 220.0
frecuencias = [actual]
for i in range(12):
actual *= raiz_doceava_de_dos
frecuencias.append(actual)
La Música y el Código
Escalas
La Música y el Código
Escala Mayor
T T S T T T S
T
T
S
T
T
T
S
La Música y el Código
Escala Mayor
TONO = 2
SEMITONO = 1
escala = [TONO, TONO, SEMITONO, TONO, TONO, TONO, SEMITONO]
actual = 0
frecuencias_escala = [frecuencias[0]]
for intervalo in escala:
actual += intervalo
frecuencias_escala.append(frecuencias[actual])
La Música y el Código
Escala Menor
T S T T S T T
T
T
S
T
T
T
S
La Música y el Código
Escala Menor
TONO = 2
SEMITONO = 1
escala = [TONO, SEMITONO, TONO, TONO, SEMITONO, TONO, TONO]
actual = 0
frecuencias_escala = [frecuencias[0]]
for intervalo in escala:
actual += intervalo
frecuencias_escala.append(frecuencias[actual])
La Música y el Código
Modos en las Escalas
La Música y el Código
Modos en las Escalas
notas = []
modo = [TONO, TONO, SEMITONO, TONO, TONO, TONO, SEMITONO]
inicio = 0
for i in range(8):
actual = inicio
frecuencias_modo = [frecuencias[actual]]
for intervalo in modo:
actual += intervalo
frecuencias_modo.append(frecuencias[actual])
notas += frecuencias_modo
inicio += modo[0]
modo = rotate(modo)
La Música y el Código
Terceras
La Música y el Código
Terceras
escala = [TONO, TONO, SEMITONO, TONO, TONO, TONO, SEMITONO]
escala *= 2
notas = [frecuencias[0]]
actual = 0
for grupo in grouper(escala, 2, 0):
actual += sum(grupo)
notas.append(frecuencias[actual])
La Música y el Código
Acordes
La Música y el Código
Acordes
muestras = [0 for i in range(int(muestras_totales))]
for frecuencia in notas:
ciclos_por_muestra = frecuencia / muestras_por_segundo
incremento = 2 * math.pi * ciclos_por_muestra
fase = 0
for i in range(int(muestras_totales)):
muestras[i] += math.sin(fase)
fase += incremento
maximo = max([abs(muestra) for muestra in muestras])
multiplicador = 1.0 / maximo
muestras = [multiplicador * muestra for muestra in muestras]
La Música y el Código
Escalas de Acordes
La Música y el Código
Escalas de Acordes
inicio = 0
for x in range(8):
actual = inicio
notas = [frecuencias[actual]]
for grupo in grouper(escala, 2, 0):
actual += sum(grupo)
notas.append(frecuencias[actual])
acordes.append(notas)
inicio += escala[0]
escala = rotate(escala)
La Música y el Código
Progresiones de Acordes
La Música y el Código
Progresiones de Acordes
I, II, III, IV, V, VI, VII = range(7)
acordes_cancion = (acordes[I], acordes[V], acordes[VI],
acordes[IV], acordes[I])
I V vi VI
La Música y el Código
Progresiones de Acordes
Epílogo
Abstracciones
from pyo import *
s = Server().boot()
s.start()
freqs = midiToHz([60 ,64, 67, 60+12, 64+6, 67+12])
rnd = Choice(choice=freqs, freq=[1, 4])
rnd2 = Choice(choice=freqs, freq=[4, 8])
a = SineLoop(freq=[rnd, rnd2], mul=.15).out()
s.gui(locals())
Epílogo
Abstracciones
Rhodey voc => JCRev r => Echo a => Echo b => Echo c => dac;
220.0 => voc.freq;
0.8 => voc.gain;
.8 => r.gain;
.2 => r.mix;
1000::ms => a.max => b.max => c.max;
750::ms => a.delay => b.delay => c.delay;
.50 => a.mix => b.mix => c.mix;
fun void vecho_Shred() {
0.0 => float decider;
0.0 => float mix;
0.0 => float old;
0.0 => float inc;
0 => int n;
while( true ) {
Math.random2f( 0, 1 ) => decider;
if( decider < .3 ) 0.0 => mix;
else if( decider < .6 ) .08 => mix;
else if( decider < .8 ) .5 => mix;
else .15 => mix;
(mix-old)/1000.0 => inc;
1000 => n;
while( n-- ) {
old + inc => old;
old => a.mix => b.mix => c.mix;
1::ms => now;
}
mix => old;
Math.random2(2,6)::second => now;
}
}
spork ~ vecho_Shred();
[ 0, 2, 4, 7, 9 ] @=> int scale[];
while( true ) {
scale[Math.random2(0,scale.cap()-1)] => int freq;
Std.mtof( ( 33 + Math.random2(0,1) * 12 + freq ) ) => voc.freq;
Math.random2f( 0.6, 0.8 ) => voc.noteOn;
if( Math.randomf() > 0.85 )
{ 1000::ms => now; }
else if( Math.randomf() > .85 )
{ 500::ms => now; }
else if( Math.randomf() > .1 )
{ .250::second => now; }
else {
0 => int i;
2 * Math.random2( 1, 3 ) => int pick;
0 => int pick_dir;
0.0 => float pluck;
for( ; i < pick; i++ ) {
Math.random2f(.4,.6) + i*.035 => pluck;
pluck + -0.02 * (i * pick_dir) => voc.noteOn;
!pick_dir => pick_dir;
250::ms => now;
}
}
}
Epílogo
Abstracciones
define :play_bb do |n|
sample :drum_heavy_kick
sample :ambi_drone, rate: [0.25, 0.5, 0.125, 1].choose, amp: 0.25 if rand < 0.125
sample :ambi_lunar_land, rate: [0.5, 0.125, 1, -1, -0.5].choose, amp: 0.25 if rand < 0.125
sample :loop_amen, attack: 0, release: 0.05, start: 1 - (1.0 / n), rate: [1,1,1,1,1,1,-1].choose
sleep sample_duration(:loop_amen) / n
end
loop {play_bb([1,2,4,8,16].choose)}
Epílogo
Abstracciones
(ns overtone.examples.compositions.funk
(:use [overtone.live]))
(definst string [note 60 amp 1.0 dur 0.5 decay 30 coef 0.3 gate 1]
(let [freq (midicps note)
noize (* 0.8 (white-noise))
dly (/ 1.0 freq)
plk (pluck noize gate dly dly decay coef)
dist (distort plk)
filt (rlpf dist (* 12 freq) 0.6)
clp (clip2 filt 0.8)
reverb (free-verb clp 0.4 0.8 0.2)]
(* amp (env-gen (perc 0.0001 dur) :action 0) reverb)))
(def snare (sample (freesound-path 26903)))
(def kick (sample (freesound-path 2086)))
(def close-hihat (sample (freesound-path 802)))
(def open-hihat (sample (freesound-path 26657)))
(defn subdivide
[a b position]
(+ a (* position (/ (- b a) 4) )))
(defn drums [nome]
(let [beat (nome)]
; hi-hat pattern
(at (nome beat) (close-hihat))
(at (nome (+ 1 beat)) (open-hihat))
(at (nome (+ 2 beat)) (close-hihat))
(at (nome (+ 3 beat)) (close-hihat))
(at (nome (+ 4 beat)) (close-hihat))
(at (nome (+ 5 beat)) (open-hihat))
(at (nome (+ 6 beat)) (close-hihat))
(at (nome (+ 7 beat)) (close-hihat))
; snare pattern
(at (nome (+ 2 beat)) (snare))
(at (subdivide (nome (+ 2 beat)) (nome (+ 4 beat)) 3) (snare))
(at (subdivide (nome (+ 4 beat)) (nome (+ 6 beat)) 1) (snare))
(at (nome (+ 6 beat)) (snare))
(at (subdivide (nome (+ 6 beat)) (nome (+ 8 beat)) 3) (snare))
; kick drum pattern
(at (nome beat) (kick))
(at (nome (+ 5 beat)) (kick))
(at (nome (+ 7 beat)) (kick))
(apply-by (nome (+ 8 beat)) drums nome [])))
(defn bass [nome]
(let [beat (nome)]
(at (nome beat) (string 51))
(at (subdivide (nome beat) (nome (+ 2 beat)) 1) (string 51))
(at (subdivide (nome beat) (nome (+ 2 beat)) 3) (string 51))
(at (subdivide (nome (+ beat 1)) (nome (+ 3 beat)) 1) (string 51))
(at (subdivide (nome (+ beat 1)) (nome (+ 3 beat)) 3) (string 51))
(at (nome (+ 4 beat)) (string 51))
(at (subdivide (nome (+ 4 beat)) (nome (+ 6 beat)) 1) (string 49))
(at (nome (+ 5 beat)) (string 46))
(at (nome (+ 6 beat)) (string 51))
(at (subdivide (nome (+ 6 beat)) (nome (+ 8 beat)) 1) (string 49))
(at (nome (+ 7 beat)) (string 46))
(at (nome (+ 8 beat)) (string 51))
(at (nome (+ 12 beat)) (string 51))
(at (subdivide (nome (+ 12 beat)) (nome (+ 14 beat)) 1) (string 51))
(apply-by (nome (+ 16 beat)) bass nome [])))
(defn section [nome]
(drums nome)
(bass nome))
(def met (metronome (* 100 2)))
(section met)
;; (stop)
Epílogo
Abstracciones
#include <stdio.h>
int main() {
int t;
for(t=0;;t++) {
putchar(((t/16)>>t/2*t) & (t/2<<2) | t/4>>2);
}
}
Final
La presentación puede verse online en cualquier momento accediendo a:
Contacto:
By Moisés Gabriel Cachay Tello
Una breve introducción a la generación de sonido digital y su consecuente aplicación en la programación creativa de música algorítmica. Basado en 'A gentle introduction to music theory in Ruby' de Alex Speller.