cdp-playground · parte 1

Cuatro mecanismos
y 220 programas

Un taller de 3 horas donde no se aprende CDP. Se aprende cómo funciona un efecto de sonido por dentro, y CDP es el bisturí. Vamos a usar 8 de sus 220 programas: el 3,6 % del toolkit y el 100 % de los mecanismos.

Duración
3 horas
Nivel
Cero conocimiento de audio. Terminal básica.
Herramientas
CDP 7.1, ffmpeg para convertir, un editor hexadecimal
Te llevás
20 segundos de sonido propio y la razón exacta de por qué suena así
Dos espectrogramas apilados: arriba cuatro pulsos angostos que ocupan el primer cuarto del ancho, abajo los mismos cuatro pulsos cuatro veces más anchos ocupando todo el ancho, con las bandas de frecuencia a la misma altura
Esto es el módulo 6. Arriba el sonido original, abajo el mismo sonido cuatro veces más largo con el tono intacto: 2,000 s → 8,101 s, y el pico sigue en 329,7 Hz. Las dos calles están dibujadas a la misma escala de tiempo. En el módulo 2 vamos a descubrir que esto es imposible, y acá está hecho.

01 La idea

El Composers Desktop Project trae 220 programas de línea de comandos. Un taller que los recorra no es un taller, es un manual, y a la media hora nadie se acuerda de nada. Así que vamos al revés: ocho programas, elegidos porque entre los ocho aparecen todos los mecanismos que existen.

CDP es raro y por eso sirve. Es de 1987, es LGPL, corre en centésimas de segundo y no tiene interfaz gráfica: un programa, una operación, argumentos posicionales. Eso que parece incomodidad es la ventaja pedagógica entera. En un plugin con perillas, "reverb" es una caja negra con un preset llamado Large Hall. Acá reverb te pide siete números y cada uno corresponde a una parte del mecanismo. No se puede usar sin entenderlo.

Al final del taller la pregunta que cada uno tiene que poder contestar no es "¿qué programa hace tal cosa?" sino "¿cuál de los cuatro mecanismos necesito, y por lo tanto en qué familia de programas busco?".

02 Preparación

Esto tiene que estar resuelto antes de arrancar. No gastes tiempo del taller instalando.

Instalar CDP sin compilar nada

El repo oficial de CDP en GitHub no publica binarios. La única fuente precompilada para Linux que funciona hoy viene adentro del release de SoundThread, que empaqueta los ejecutables de CDP tal cual:

curl -LO https://github.com/j-p-higgins/SoundThread/releases/download/v0.4.0-beta/SoundThread_v0-4-0-beta_linux_x86_64.tar.gz
tar xf SoundThread_v0-4-0-beta_linux_x86_64.tar.gz
tar xf SoundThread_v0-4-0-beta_linux_x86_64/cdprogs_linux.tar.gz -C ~/cdp/

export PATH="$HOME/cdp/cdprogs_linux:$PATH"
sndinfo
CDP Release 7.1 2016

Dos minutos, sin cmake, sin dependencias. Fijate que los binarios se identifican como Release 7.1 de 2016 aunque el repo se llame CDP8: la versión que estás enseñando es la 7.1, citá esa.

Material de entrada

Que cada uno traiga un sonido corto y con ataque — un golpe, una nota de guitarra, una sílaba, un portazo. Con ataque, insistí: sin transitorio no se escucha ni un delay ni una reverb, y la mitad del taller se cae. Un acorde de sintetizador sostenido es el peor material posible.

CDP es solo WAV, mono o estéreo. Todo lo demás se convierte antes:

ffmpeg -i lo_que_sea.mp3 -ac 1 -ar 44100 -c:a pcm_s16le fuente.wav

Si alguien llega con las manos vacías, ffmpeg genera material y nadie se queda afuera. Estos dos son los que usa todo este sitio:

# Cuatro blips con decaimiento, uno cada 500 ms: 330 Hz y dos armónicos
ffmpeg -f lavfi -i "aevalsrc='0.6*exp(-9*mod(t,0.5))*(sin(2*PI*330*t)\
+0.5*sin(2*PI*660*t)+0.25*sin(2*PI*990*t))':d=2:s=44100" \
  -ac 1 -c:a pcm_s16le fuente.wav

# Ruido rosa, para medir filtros
ffmpeg -f lavfi -i "anoisesrc=c=pink:d=2:r=44100:a=0.4" \
  -ac 1 -c:a pcm_s16le ruido.wav
Dos formas de onda apiladas: arriba cuatro pulsos con ataque abrupto a la izquierda y cola a la derecha, abajo los mismos cuatro pulsos con el ataque a la derecha
fuente.wav Cuatro blips, 2,000 s, mono, 44.100 Hz, RMS −15,8 dB, pico espectral en 329,7 Hz. La calle de abajo es el módulo 2 adelantado.
Espectrograma de cuatro pulsos: cada uno tiene un frente vertical brillante y una cola que se apaga hacia la derecha
el espectrograma de fuente.wav Lo mismo mirado por frecuencia. El reproductor, en cambio, es ruido.wav: ruido rosa, RMS −22,1 dB, con energía en todas las frecuencias y más abajo que arriba.

Los tres footguns de CDP, dichos ahora

Los tres los vas a encontrar en los primeros veinte minutos. Decilos antes o el grupo los descubre con bronca.

  1. CDP se niega a sobreescribir. Si el archivo de salida existe, el programa aborta, y no hay flag de forzado. Borrá antes o usá nombres nuevos.
  2. El sub-nombre va antes del modo. La forma es PROGRAMA NOMBRE (modo) entrada salida parámetros. Es filter lohi 1 …, nunca filter 1 lohi ….
  3. Correr el programa pelado imprime su uso exacto. Esa es la documentación autoritativa, no la web. Es la versión que tenés instalada, así que no puede estar desactualizada.
modify loudness
USAGE: modify loudness 1 infile         outfile gain
OR:    modify loudness 2 infile         outfile gain
OR:    modify loudness 3 infile         outfile [-llevel]
...
1) GAIN:         adjust level by factor GAIN.
2) dBGAIN:       adjust level by GAIN dB. Range +-96.0
3) NORMALISE:    force level (if ness) to max possible, or to LEVEL given.
6) INVERT PHASE: Invert phase of the sound.

03 Los cuatro mecanismos

Esta sección es el mapa. Sirve para que después del taller cada uno sepa dónde volver a buscar entre los 220 programas, y para poder ubicar cualquier efecto que se cruce en la vida — un plugin, una perilla, un preset — en uno de estos cuatro casilleros.

  1. Moldear amplitud en el tiempo. Multiplicar la señal por un número, o por una curva. Ganancia, normalización, fades, envolventes, tremolo, compresión, inversión de fase. En CDP: modify loudness, envel. Es el mecanismo más barato y el más subestimado.
  2. Desplazar una copia en el tiempo. Sumar la señal con una versión retrasada de sí misma. Según cuánto la retrases se llama eco, reverb, flanger, chorus o filtro peine — y son el mismo mecanismo. En CDP: modify revecho, reverb.
  3. Seleccionar o rechazar frecuencias. Dejar pasar una parte del espectro y atenuar el resto. Lopass, hipass, band, EQ, wah. En CDP: la familia filter.
  4. Cambiar de representación. Salir del dominio del tiempo, operar sobre frecuencias, y volver. Todo lo que en el dominio temporal es imposible vive acá: estirar sin cambiar el tono, morphing, congelar un espectro. En CDP: pvoc para ir y volver, y después stretch, blur, morph, spec.

Los tres primeros son operaciones sobre muestras. El cuarto es de otra naturaleza: no es un efecto, es un cambio de coordenadas. Cuesta caro — vas a ver que el archivo se agranda 16 veces — y compra cosas que de otra forma no existen.

Cómo predecir un efecto desconocido

  • ¿Cambia el volumen a lo largo del tiempo y nada más? Mecanismo 1
  • ¿Suena "espacial", "metálico", "doble"? Mecanismo 2, y el parámetro que importa es una escala de tiempo
  • ¿Suena "oscuro", "chico", "telefónico"? Mecanismo 3
  • ¿Hace algo que en una cinta magnética sería físicamente imposible? Mecanismo 4

La prueba de la cinta

  • Ese último criterio es el más útil de todos. Una cinta puede ir más rápido, más lento, para atrás, o pasar por un filtro
  • Lo que no puede es durar el doble sin bajar de tono, porque la velocidad de lectura fija las dos cosas a la vez
  • Si un efecto rompe la prueba de la cinta, está operando sobre otra representación. No hay tercera opción

04 El taller

Nueve módulos, 3 horas, 8 programas, 14 comandos. Cada módulo tiene la misma estructura: un mecanismo, algo que hacés con las manos, y el momento en que las dos cosas encajan.

Por qué tan pocos comandos

El límite no es el cómputo. Todo lo que hay en este sitio renderiza en centésimas de segundo — medido, no estimado:

ComandoTiempo real
modify revecho0,004 s
filter lohi0,006 s
pvoc anal0,022 s
stretch time0,024 s
pvoc synth0,075 s

El límite es escuchar. Un resultado de 2 segundos cuesta 2 segundos como mínimo y se escucha tres veces. Explorar un efecto en serio — correrlo, escuchar, tocar un parámetro, escuchar de nuevo, discutir qué cambió — cuesta 8 a 10 minutos reales de reloj.

180 minutos, menos 15 de arranque, menos 10 de cierre, menos 10 de pausa, dejan 145. Eso son 14 comandos bien hechos, no 220 mal vistos.

HoraMinMóduloProgramaMec.
0:00150 · Qué es un archivo de sonidosndinfo
0:15201 · Amplitudmodify loudness1
0:35202 · Tiempo, y el par soldadomodify radical, modify speed
0:55253 · El delay es el padre de todomodify revecho2
1:2010pausa
1:30204 · Selección de frecuenciasfilter lohi, reverb3
1:50255 · Cambiar de representaciónpvoc4
2:15206 · Romper la soldadurastretch, blur4
2:35157 · Datamosh para oídosdd + pvoc
2:50108 · Compartir y nombrar

Módulo 0

Qué es un archivo de sonido

15 min

Concepto Muestreo, cuantización, metadatos

sndinfo props fuente.wav
samples: ............ 88200
file type: ........... SOUND
sample rate: ........ 44100
channels: ........... 1
sample type:  16bit
No PEAK chunk in this file

Cuatro números y ya está todo. 88.200 muestras a 44.100 por segundo son 2 segundos exactos: que alguien haga la división en voz alta, porque de ahí sale la definición operativa de sample rate y no hace falta ninguna otra. Cada muestra es un entero de 16 bits, o sea uno de 65.536 valores posibles de presión de aire. Nada más. No hay ondas guardadas en el archivo, hay una lista de números y un acuerdo sobre a qué ritmo leerlos.

Ahora corré cualquier programa de CDP y volvé a mirar el mismo audio:

modify loudness 1 fuente.wav copia.wav 1.0
sndinfo props copia.wav
ls -l fuente.wav copia.wav
PEAK data at: Thu Aug 27 19:28:48 2026
CH 1:   amp = 0.8291 (-1.63 dB)   Frame 18

176478 fuente.wav
178528 copia.wav

Multiplicamos por 1,0 — o sea, no cambiamos una sola muestra — y el archivo engordó 2.050 bytes. Desapareció el No PEAK chunk y apareció un bloque que dice que el pico vale 0,8291, o sea −1,63 dB, y que está en el frame 18. Es un caché: CDP anota el máximo para no tener que releer el archivo entero la próxima vez que lo necesite.

Mirá los chunks de los dos archivos, con los mismos 176.400 bytes de audio adentro:

fuente.wav   fmt 16              LIST 26     data 176400
copia.wav    fmt 16  PEAK 16  cue 28  LIST 2016  data 176400

CDP agregó tres cosas y agrandó una cuarta. Un WAV no es "los números y nada más": es un contenedor con lugar para que cada programa deje sus propias anotaciones, y todo programa que lo toque deja rastro.

El momento fuente.wav pesa 176.478 bytes y las muestras son 176.400. Los 78 que sobran son el encabezado: el acuerdo. Nada del sonido está en esos 78 bytes, y sin ellos no hay sonido. Cambiás el acuerdo y los mismos bytes son otra cosa — y en el módulo 5 vamos a hacer exactamente eso a propósito.

Módulo 1

Amplitud

20 min

Mecanismo 1 Moldear amplitud en el tiempo

El mecanismo más barato: multiplicar cada muestra por un número. Un programa, cuatro modos, y cada modo enseña algo distinto.

modify loudness 1 fuente.wav mitad.wav   0.5    # factor
modify loudness 2 fuente.wav menos6.wav  -6     # decibeles
modify loudness 3 fuente.wav norm.wav           # normalizar
modify loudness 6 fuente.wav fase.wav           # invertir fase
SalidaRMSPico
fuente.wav−15,8 dB−1,6 dB
mitad.wav factor 0,5−21,8 dB−7,6 dB
menos6.wav −6 dB−21,8 dB−7,6 dB
norm.wav−15,1 dB−0,9 dB
fase.wav−15,8 dB−1,6 dB

Las filas dos y tres son idénticas, y esa es la primera lección: multiplicar por 0,5 y restar 6 dB son la misma operación en dos unidades. Un decibel no es una cosa, es una forma de escribir una multiplicación. Que alguien despeje por qué 0,5 son exactamente −6: porque 20·log₁₀(0,5) = −6,02.

La cuarta fila trae la trampa. Al normalizar, CDP dice lo que hizo:

Normalising with Gain Factor = 1.085559

Multiplicó todo por 1,0856 para que el pico llegue al máximo. Normalizar es una sola multiplicación: no cambia ninguna relación interna del sonido, solo lo corre entero. Por eso normalizar no es comprimir, y por eso normalizar casi nunca hace que algo "suene mejor" — el pico llega más alto y todo lo demás queda exactamente igual de lejos del pico.

Y después está la fila resaltada, que es el módulo entero.

Tres formas de onda apiladas: arriba cuatro pulsos, en el medio los mismos pulsos con la mitad de altura, abajo una calle completamente negra sin ninguna onda
Calle 1: la fuente. Calle 2: modify loudness 1 con factor 0,5. Calle 3: la fuente sumada a su propia fase invertida. La calle no está vacía ni la figura está cortada: eso es el resultado, y mide −91,0 dB. El reproductor toca esa tercera calle. No vas a escuchar nada, y ese es el punto.

Escuchá fase.wav solo y es indistinguible del original — mismo RMS, mismo pico, mismo todo. La inversión de fase es inaudible. Ahora sumalo con el original:

  1. ×1 la fuente RMS −15,8 dB
  2. ×0,5 mitad de ganancia RMS −21,8 dB

    Se oye más bajo. Nada más. Es el mecanismo 1 completo.

  3. fase fase invertida RMS −15,8 dB

    Comparalo con la primera fila. No los vas a poder distinguir, y sin embargo cada muestra tiene el signo cambiado.

ffmpeg -i fuente.wav -i fase.wav \
  -filter_complex "[0:a][1:a]amix=inputs=2:normalize=0" suma.wav
mean_volume: -91.0 dB    max_volume: -91.0 dB

−91 dB es el piso de ruido de los 16 bits. O sea: cero, hasta donde el formato puede representar cero.

El momento Una operación que por sí sola no hace nada audible puede aniquilar completamente al sonido cuando se combina. Escuchar un archivo aislado no alcanza para saber qué le pasó: la fase no está en el volumen, está en la relación entre las muestras. Y esa es la razón por la que existe la cancelación de ruido, por la que un cable mal soldado te mata los graves, y por la que el mecanismo 2 — que es literalmente sumar copias desplazadas — va a hacer cosas que todavía no parecen posibles.

Módulo 2

Tiempo, y el par soldado

20 min

Concepto Remuestreo, acoplamiento de parámetros

Arrancá con el regalo. Reverse es gratis, instantáneo y siempre gusta:

modify radical 1 fuente.wav reverso.wav
Dos formas de onda apiladas: arriba cuatro pulsos con ataque abrupto a la izquierda, abajo los mismos con el ataque a la derecha
La misma lista de números, leída al revés. Los ataques pasaron de la izquierda a la derecha de cada pulso. RMS idéntico, −15,8 dB: no se agregó ni se quitó nada, se reordenó.

Ahora la parte incómoda. Cambiemos la velocidad:

modify speed 1 fuente.wav rapido.wav  1.5   # factor de velocidad
modify speed 2 fuente.wav siete.wav   7     # semitonos
SalidaDuraciónPico espectral
fuente.wav2,000 s329,7 Hz
rapido.wav ×1,51,333 s495,3 Hz
siete.wav +7 semitonos1,335 s493,9 Hz
rapido.wav: más corto y más agudo, las dos cosas juntas y sin opción.

Mirá los cocientes. La duración se dividió por 2,000/1,333 = 1,5004. El tono se multiplicó por 495,3/329,7 = 1,5023. Son el mismo número. No es coincidencia y no es un límite del programa: es la misma operación. Cambiar la velocidad es leer las mismas muestras a otro ritmo, y eso mueve la duración y la frecuencia en proporción exacta e inversa.

Y las filas dos y tres vuelven a ser la misma cosa en otras unidades: 27/12 = 1,4983 ≈ 1,5. El modo 2 no desacopla nada, solo te deja escribir el factor en semitonos.

El momento En el dominio del tiempo, la velocidad y el tono son un par soldado. No hay flag, no hay modo, no hay programa de CDP que los separe, porque no es una limitación del software: es lo que significa una muestra. Es la prueba de la cinta. Dejá la frustración plantada acá — es a propósito, y el módulo 6 la paga entera.

Módulo 3

El delay es el padre de todo

25 min — el mejor módulo del taller

Mecanismo 2 Desplazar una copia en el tiempo

Un solo programa. Un solo parámetro. Cuatro órdenes de magnitud. Cuatro efectos con nombre propio.

modify revecho 1 fuente.wav eco.wav      250   0.5 0.4 0.5
modify revecho 1 fuente.wav espacio.wav   40   0.5 0.4 0.5
modify revecho 1 fuente.wav flanger.wav    5   0.5 0.4 0.5
modify revecho 1 fuente.wav peine.wav      0.5 0.5 0.4 0.5

Los cuatro argumentos son delay en milisegundos, mezcla, realimentación y cola. Lo único que cambia entre las cuatro líneas es el primero.

  1. 250 ms eco RMS −19,8 dB

    Repeticiones separadas, contables. Oís dos eventos distintos.

  2. 40 ms espacio / slapback RMS −21,3 dB

    Ya no contás repeticiones. Empieza a sonar como un lugar.

  3. 5 ms flanger / doblaje RMS −24,3 dB

    Un solo evento, con el timbre cambiado. El delay se volvió color.

  4. 0,5 ms filtro peine RMS −20,8 dB

    Ni rastro de repetición. Es un filtro, y no hay ningún filtro en el comando.

Que el grupo los nombre de oído antes de que vos digas cómo se llaman. Cuatro efectos que en cualquier catálogo de plugins están en cuatro cajas separadas, producidos por el mismo programa con el mismo parámetro. Ninguna otra lección de audio tiene esta relación señal/esfuerzo.

Fijate en la columna de RMS, porque no baja de forma monótona: −19,8, −21,3, −24,3 y de golpe vuelve a subir a −20,8. Que alguien explique por qué antes de seguir. La respuesta es que a 0,5 ms la copia llega tan pegada al original que en las frecuencias bajas está prácticamente en fase, y sumar dos señales en fase da +6 dB. A 5 ms está lo bastante desfasada para cancelar. Ese ida y vuelta entre reforzar y cancelar, frecuencia por frecuencia, tiene un nombre y una forma.

Dos formas de onda apiladas: arriba cuatro pulsos limpios, abajo los mismos cuatro con un pulso más chico después de cada uno y una repetición extra al final
Delay de 250 ms, visto en el tiempo. Cada pulso arrastra su copia más chica, y al final aparece un eco que ya no tiene original. Acá el mecanismo se ve directamente: hay dos cosas donde había una.
Dos espectrogramas apilados: arriba ruido rosa parejo, abajo el mismo ruido atravesado por franjas horizontales oscuras regularmente espaciadas
Delay de 0,5 ms, visto en frecuencia. Arriba ruido rosa; abajo el mismo ruido con un delay de medio milisegundo. Aparecieron franjas horizontales oscuras, parejamente espaciadas: las frecuencias que se cancelaron. Eso es un peine, y de ahí el nombre. Esta figura usa ruido y no los blips por la misma razón por la que un técnico mide una sala con ruido y no con una nota: hace falta energía en todas las frecuencias para ver cuáles faltan.

El momento Es el mismo parámetro cruzando de un eje al otro. A 250 ms el delay se ve en el eje del tiempo y se oye como repetición. A 0,5 ms desaparece del tiempo y aparece en el eje de la frecuencia, donde se oye como timbre. No cambió el mecanismo: cambió en qué representación es visible. Tiempo y frecuencia no son dos temas del audio, son dos vistas de la misma cosa — y el módulo 5 va a hacer explícito ese cambio de vista.

Módulo 4

Selección de frecuencias

20 min

Mecanismo 3 Seleccionar o rechazar frecuencias

filter lohi 1 ruido.wav lopass.wav -96 1000 2000
filter lohi 1 ruido.wav hipass.wav -96 2000 1000

Las dos líneas son idénticas salvo el orden de los dos últimos números, y una es un lopass y la otra un hipass. No hay flag que lo diga. Los argumentos son atenuación, pass-band y stop-band, y la dirección del filtro está implícita: si el stop-band está arriba del pass-band, corta agudos; si está abajo, corta graves. Es un diseño elegante y vale enseñarlo explícitamente, porque obliga a pensar el filtro como "qué dejo pasar y qué freno" en vez de memorizar dos nombres.

Tres espectrogramas apilados: arriba ruido rosa completo, en el medio solo la franja inferior, abajo una franja superior fina y tenue
Calle 1: ruido rosa entero. Calle 2: lopass, se fue todo lo de arriba. Calle 3: hipass, quedó una banda fina y notablemente más apagada. Las tres calles cubren la misma ventana de 3 segundos; el negro de la derecha es que el filtro devuelve más largo de lo que entró.
  1. lopass 1000 → 2000 RMS −26,9 dB
  2. hipass 2000 → 1000 RMS −31,7 dB

El hipass quedó 4,8 dB más bajo que el lopass, con el mismo −96 de atenuación y el mismo cruce. Que alguien explique por qué, porque la respuesta define qué es el ruido rosa: tiene la misma energía por octava, y como las octavas graves son angostas en Hz y las agudas anchísimas, la mayor parte de la energía está abajo. Tirar lo de arriba cuesta poco; tirar lo de abajo cuesta mucho. El filtro no es el que cambió: cambió qué había para tirar.

Dos detalles que el programa cuenta solo y conviene mirar:

INFO: Order of filter is 16

Pedimos −96 dB de atenuación y CDP eligió orden 16. Más atenuación es más orden, y más orden es más cómputo y más retardo. Probá con -24 y mirá cómo baja el orden: ahí está, en un solo número, el compromiso entre lo bueno que es un filtro y lo que cuesta. La entrada de 2,000 s además salió de 3,000 s — un segundo de cola, porque un filtro tiene memoria y sigue sonando después de que la entrada terminó.

Un efecto compuesto

Ahora que están los mecanismos 2 y 3, se puede desarmar algo real:

reverb fuente.wav reverb.wav 0.3 0.5 1.2 0.7 5000 0.5
medium-room: using 40 early reflections
predelay = 0.0332 secs
Siete números: ganancia de reverb, mezcla, tiempo de decaimiento, absorción, corte del lopass y cola. La absorción de 0,7 y el lpfreq de 5000 son mecanismo 3; las 40 reflexiones tempranas son mecanismo 2, cuarenta veces.

Una reverb no es un mecanismo nuevo: es una red de Schroeder, o sea muchísimos delays cortos con filtros adentro del lazo de realimentación. Los seis filtros peine y cuatro pasa-todo están ahí, y CDP incluso te deja pasarle los tiempos a mano en un archivo de texto. Eso que en un plugin es el preset Large Hall acá son siete números que corresponden uno a uno a partes del mecanismo.

El momento Los efectos "grandes" son composiciones de los chicos. Una vez que tenés los cuatro mecanismos, la pregunta frente a cualquier efecto desconocido deja de ser "¿qué es esto?" y pasa a ser "¿de qué está hecho?".

Módulo 5

Cambiar de representación

25 min

Mecanismo 4 Cambiar de representación

Hasta acá todo fue operar sobre muestras. Ahora salimos del dominio del tiempo. El viaje redondo, sin procesar nada en el medio:

pvoc anal 1 fuente.wav espectro.ana -c1024 -o3
pvoc synth espectro.ana vuelta.wav

ls -l fuente.wav espectro.ana

fuente.wav176.478 bytes

espectro.ana2.866.662 bytes

Expansión: 16,2×

Que primero adivinen y después midan. Casi todos esperan que la representación en frecuencia sea más chica, porque suena a compresión. Es dieciséis veces más grande: describir un sonido en términos de frecuencia cuesta muchísimo más que guardar el sonido.

Espectrograma de cuatro pulsos, cada uno con un frente vertical brillante y una cola que se apaga
Esto es, literalmente, lo que hay adentro del .ana. El reproductor toca el viaje redondo completo sin ningún proceso en el medio: RMS −15,9 dB contra los −15,8 originales, y 2,023 s contra 2,000. El análisis y la resíntesis casi no cuestan nada — casi.

Esos 23 milisegundos de más no son un bug: son el largo de la ventana de análisis. No podés hablar de "la frecuencia en el instante t" porque una frecuencia necesita tiempo para existir. El programa tiene que mirar 1024 muestras para decir algo sobre frecuencia, y eso deja huella.

El flag que es el principio de incertidumbre

pvoc anal 1 fuente.wav corto.ana  -c256  -o3
pvoc anal 1 fuente.wav largo.ana  -c4096 -o3

-c es la cantidad de puntos de análisis. Más puntos es mejor resolución en frecuencia y peor en tiempo: con 4096 puntos distinguís dos notas muy cercanas pero un golpe seco se te embarra; con 256 el golpe queda nítido y las notas se confunden. No se puede tener las dos. Es una cota matemática, la misma que en física se llama principio de incertidumbre, y acá aparece como un flag de línea de comandos que tenés que elegir a mano cada vez.

El .ana es un WAV que miente

xxd -l 48 espectro.ana
00000000: 5249 4646 debd 2b00 5741 5645 666d 7420  RIFF..+.WAVEfmt
00000010: 1200 0000 0300 0204 5801 0000 c08a 1500  ........X.......
00000020: 0810 2000 0000 4c49 5354 e007 0000 6164  .. ...LIST....ad

Es un RIFF WAVE. Encabezado RIFF…WAVEfmt, format tag 0x0003 (punto flotante), y un chunk LIST/adtl/note. Mirá qué dice el encabezado:

Campo WAVValorQué significa en realidad
nChannels1026Floats por frame: 513 bins × 2 (amplitud y frecuencia)
nSamplesPerSec344Frames espectrales por segundo
nBlockAlign4104Bytes de un frame
data2.864.592Exactamente 698 frames

CDP guardó un espectrograma adentro de un encabezado de audio mintiendo sobre qué es una muestra. Para el formato WAV este archivo es audio de 1026 canales a 344 Hz. Los parámetros reales están en el chunk de texto, en hexadecimal ASCII: analwinlen 1024, decfactor 128, original sample rate 44100. Y andá a ver qué dice cada programa del mismo archivo:

sndinfo props espectro.ana
ffprobe espectro.ana
file type: .......... ANALYSIS DATA        ← CDP
analysis window len:  1024
decimation factor: .. 128

[pcm_f32le] Too many channels: 1026       ← ffprobe se niega

El momento ffmpeg rechaza un archivo que CDP lee sin problema, y el archivo no está mal formado: los dos programas leen el mismo encabezado y hacen cumplir cláusulas distintas del mismo contrato. Un formato de archivo no es una cosa que un archivo es, es un acuerdo entre quien escribe y quien lee — y cuando los dos lados no acordaron lo mismo, uno de los dos parece roto. Guardá esto, porque el módulo 7 es lo que pasa cuando quien lee confía demasiado.

Módulo 6

Romper la soldadura

20 min

Mecanismo 4 El pago del módulo 2

pvoc anal 1 fuente.wav espectro.ana -c1024 -o3
stretch time 1 espectro.ana largo.ana 4
pvoc synth largo.ana largo.wav

Duración: 2,000 s → 8,101 s

Pico espectral: 329,7 Hz → 329,7 Hz

Cuatro veces más largo, tono intacto

Esto es exactamente lo que en el módulo 2 demostramos que era imposible. Y lo sigue siendo — en el dominio del tiempo. Acá no estiramos muestras: estiramos una lista de frames espectrales, poniendo cuatro donde había uno. El archivo .ana pasó de 2.866.662 a 11.460.438 bytes, o sea ×3,998: cuatro veces más frames, y cada frame sigue diciendo las mismas frecuencias.

Dos espectrogramas a la misma escala de tiempo: arriba cuatro pulsos angostos en el primer cuarto del ancho, abajo los mismos cuatro pulsos cuatro veces más anchos ocupando todo
Las dos calles a la misma escala de tiempo, por eso la de arriba ocupa un cuarto. Las bandas de frecuencia están a la misma altura en las dos: eso es el tono sin tocar. Lo único que cambió es cuánto duran.

El momento No podés separar el tono del tiempo hasta que dejás de pensar en muestras y empezás a pensar en frecuencias. El problema no se resolvió con un algoritmo más inteligente: se resolvió cambiando de representación, y ahí lo imposible se volvió una multiplicación. Eso es lo que hace un cambio de coordenadas, en audio y en cualquier otra parte.

Un efecto que solo existe acá

blur blur espectro.ana borroso.ana 20
pvoc synth borroso.ana borroso.wav
Dos espectrogramas apilados: arriba cuatro pulsos con frentes verticales nítidos, abajo los mismos pulsos con los frentes desdibujados y la energía extendida horizontalmente
blur blur con 20: promedia cada bin con los 20 frames vecinos. Los ataques se desdibujan y el sonido queda suspendido, sin ataque. RMS −18,8 dB contra −15,9: promediar bajó el nivel, porque los picos se repartieron.

Este efecto no tiene equivalente temporal. No es "un filtro" ni "un delay": es promediar el espectro a lo largo del tiempo, algo que solo se puede formular si tenés el espectro como dato. Es la prueba de que el mecanismo 4 no es un atajo para hacer más rápido lo de siempre, es un lugar donde hay operaciones nuevas.

Y ahora al revés, para que no quede magia

distort divide fuente.wav octava.wav 2
SalidaDuraciónPicoDominio
fuente.wav2,000 s329,7 Hz
largo.wav8,101 s329,7 Hzfrecuencia
octava.wav1,997 s165,5 Hztiempo
distort divide baja una octava exacta — 329,7 → 165,5 Hz — y deja la duración donde estaba, sin salir del dominio del tiempo. Trabaja sobre wavesets: encuentra los cruces por cero y reescribe los ciclos.

Es el desacoplamiento espejo: el módulo 6 cambió el tiempo sin tocar el tono, y esto cambia el tono sin tocar el tiempo, en el dominio donde dijimos que no se podía. La moraleja fina no es "el dominio del tiempo no puede", es "la operación de leer más rápido no puede". Cambiá de operación y el dominio del tiempo también tiene salidas. Los wavesets son el concepto insignia de CDP y merecen su propia sesión; acá alcanza con que exista la duda.

Módulo 7

Datamosh para oídos

15 min — el clímax

Concepto Estado inválido, propagación de errores, NaN

El .ana es una lista de 698 frames de 4104 bytes, uno atrás del otro. Rompámoslo a mano:

cp espectro.ana roto.ana
dd if=/dev/urandom of=roto.ana bs=1 seek=800000 count=120000 conv=notrunc
pvoc synth roto.ana roto.wav

pvoc synth no protesta. No hay checksum, no hay validación, no hay un solo mensaje de error. Escribe un WAV de 2,000 s perfectamente válido, y CDP después vuelve a leer su propia salida sin quejarse.

Dos espectrogramas apilados: arriba cuatro pulsos completos, abajo un pulso entero, un segundo pulso reducido a una línea vertical fina, y después nada más que negro
Arriba el archivo intacto. Abajo el mismo archivo con 120 KB de /dev/urandom encima. Escuchá: suena bien, y de golpe se muere. El silencio empieza en 0,556 s, que es exactamente el frame donde cae el byte 800.000. Todo lo que viene después del agujero está intacto en el archivo y no se oye nunca.

Esto no es lo que uno espera. La intuición dice "se va a escuchar sucio ahí donde rompí y después se recupera". No: muere en el byte exacto que tocaste y no vuelve. Y el daño no es proporcional al tamaño del agujero. Rompé un solo frame, en la mitad justa:

./scripts/romper-ana.py espectro.ana unframe.ana frame 349
pvoc synth unframe.ana unframe.wav

Dañado: 4.104 bytes de 2.866.662 = 0,143 % del archivo

Audio limpio hasta: 1,00 s

Perdido: el 50 % del sonido

Por qué muere, y no se ensucia

Cada frame tiene dos números por bin: una amplitud y una frecuencia. Rompelos por separado y el resultado es completamente distinto. Esto no se puede hacer con dd, porque dd sabe pisar rangos de bytes y acá hay que pisar un campo:

./scripts/romper-ana.py espectro.ana a.ana amp 300 400   # solo amplitudes
./scripts/romper-ana.py espectro.ana b.ana frq 300 400   # solo frecuencias
./scripts/romper-ana.py espectro.ana c.ana orden         # solo el orden
Tres espectrogramas apilados: en el primero el tercer pulso es un estallido de ruido que llega arriba y el cuarto pulso vuelve a la normalidad; en el segundo el tercer pulso es una veta fina y el cuarto queda distinto del original; en el tercero los cuatro pulsos tienen el ataque del lado derecho
La misma corrupción, en tres campos distintos del mismo archivo. Tres resultados que no se parecen en nada.
  1. amp solo amplitudes se recupera

    Estalla durante los frames que rompiste y después vuelve exactamente a lo que era. El daño dura lo que dura el agujero.

  2. frq solo frecuencias no se recupera

    Sigue habiendo sonido hasta el final, pero ya nunca vuelve a ser el original. Mismos frames dañados, daño permanente.

  3. orden frames invertidos todo válido

    No se corrompió ni un byte: los mismos frames en otro orden. Suena entero y suena distinto.

Ahí está el mecanismo. La amplitud es un valor local: se usa para un frame y se descarta. La frecuencia alimenta un acumulador de fase: la fase de cada frame es la suma corrida de todas las desviaciones anteriores, o sea es estado que se arrastra hasta el final del archivo. Rompé un valor local y el daño es local. Rompé el estado y el daño es para siempre.

Y cuando en vez de valores plausibles metés bytes al azar, esos bytes leídos como float32 dan NaN e infinitos — en nuestro caso 3.044 NaN y 260.577 valores por encima de 10¹⁰. NaN es contagioso bajo la suma: en cuanto entra al acumulador, todo lo que sale después es NaN, y el escritor de WAV convierte NaN a cero. De ahí el silencio absoluto. No es que el programa se rinda: es aritmética de punto flotante haciendo exactamente lo que dice IEEE 754.

La discusión — acá aterriza la parte de computación

Nada está corrupto

En la variante orden cada float del archivo es un valor perfectamente válido. No corrompimos ningún dato. Lo inválido es la secuencia. Y esa es la forma exacta de toda una familia de bugs reales: use-after-free, lecturas parciales, condiciones de carrera, paquetes reenviados en un protocolo sin protección de replay. En todos, los datos son válidos y el orden no. Acá lo escuchás.

Silencio contra manchón

Un decodificador de video roto te deja ver el error: arrastra píxeles y hace glitch art, porque tiene una función de ocultación de errores escrita a propósito. pvoc synth con la misma clase de daño te deja silencio. Misma arquitectura — una máquina de estados que confía en el estado anterior —, estéticas opuestas. La diferencia no es la cantidad de daño: es en qué aritmética cae el programa cuando falla. Uno cae en una rutina de relleno; el otro cae en NaN.

Por qué nadie valida

Validar cada frame costaría casi lo mismo que procesarlo, y CDP es una herramienta de estudio: la entrada la genera el propio CDP dos comandos antes. La permisividad no es descuido, es una decisión de modelo de amenaza. La misma decisión, en un parser que recibe datos de internet, es una vulnerabilidad. En criptografía ser permisivo es el bug; acá es la función.

El momento Un frame de 4.104 bytes — el 0,143 % del archivo — borra la mitad del sonido, y 120 KB de basura no hacen más daño que eso. El tamaño del agujero casi no importa: importa qué campo rompiste y dónde. Aprender a mirar un sistema y preguntar "¿cuál de estos datos es estado?" es la diferencia entre adivinar y depurar.

Módulo 8

Compartir y nombrar

10 min

Concepto Cierre y evaluación

Cada uno exporta 20 segundos y los escuchamos todos seguidos. Antes de que suene el suyo, dice una sola frase: cuál de los cuatro mecanismos usó su cadena.

ffmpeg -i mi_cadena.wav -t 20 -c:a libmp3lame -b:a 128k entrega.mp3

Esa frase es toda la evaluación del taller. Si puede decirla, entendió amplitud, delay, filtrado y cambio de representación. Si no puede, el sonido queda igual de lindo — pero volvemos 15 minutos al módulo 3, que es donde se arma todo lo demás.

El momento El que aparece cuando alguien escucha la cadena de otro y dice, sin que se lo pidan, "eso es un delay corto, no un filtro". Ahí dejaron de escuchar efectos y empezaron a escuchar mecanismos.

05 Lo que queda afuera

Decilo explícitamente para que nadie sienta que le faltó algo. Usamos 8 de 220 programas y las omisiones son deliberadas, no descuidos.

AfueraPor qué
Wavesets (distort)Concepto insignia de CDP, merece sesión propia
Granular (modify brassage)Sesión propia
Morphing (morph)Necesita dos fuentes y preparación
Texturas (texture)Necesita archivos de datos de notas
Convolución (fastconv)Necesita respuestas al impulso
Edición (sfedit, submix)Es edición, no efectos
Envolventes (envel)Se solapa con el módulo 1
Automatización breakpoint filesSesión propia
Los otros 212 programasNo entran en 3 horas

06 Para seguir

Ordenado por lo que enseña, no por dificultad. El primero es el que más rinde.

  1. Editar el .ana a mano con un editor hexadecimal

    Acá es más fácil que con un AVI, porque el .ana es RIFF WAVE plano: encontrá el chunk data, contá frames de 4104 bytes y pisá el que quieras. Cuando termines vas a haber escrito un parser de formato binario a mano, que es el verdadero premio.

    xxd -l 64 espectro.ana
    xxd -s 2070 -l 32 espectro.ana    # primer frame
  2. Encontrar el frame exacto donde muere

    Buscá por bisección el byte mínimo que hay que romper para matar el archivo, y verificá que el silencio arranca siempre en (offset − 2070) / 4104 frames, o sea a los frame / 344,5 segundos. Predecir un bug antes de reproducirlo es el ejercicio completo de depuración.

  3. Barrer el tamaño de ventana y escuchar el compromiso

    Corré el viaje redondo con -c256, -c1024, -c4096 y -c16384 sobre un material con ataques fuertes. Escuchá cómo los transitorios se van embarrando a medida que gana resolución en frecuencia. El principio de incertidumbre, a oído.

    for c in 256 1024 4096 16384; do
      pvoc anal 1 fuente.wav v$c.ana -c$c -o3
      pvoc synth v$c.ana v$c.wav
    done
    ls -l v*.ana
    -c256    2.855.550 B
    -c1024   2.866.662 B
    -c4096   2.969.022 B

    Y ahí está el mejor detalle: multiplicar los puntos de análisis por 16 cambió el tamaño del archivo en un 4 %. Dieciséis veces más bins, pero dieciséis veces menos frames. El compromiso no es una preferencia estética, es una cantidad conservada, y se ve en el conteo de bytes.

  4. Cadenas de varios pasos, y el orden que importa

    Hacé filterrevecho y después revechofilter con los mismos parámetros, y compará. No conmutan. Un delay filtrado y un filtro con delay son dos efectos distintos, y entender por qué es entender que un pipeline no es una bolsa de operaciones.

  5. Automatizar con breakpoint files

    Casi todos los parámetros de CDP aceptan, en vez de un número, un archivo de texto de dos columnas: tiempo y valor. Ahí empieza la composición. Las reglas exactas de interpolación conviene confirmarlas corriendo — filestxt.htm en la documentación es el punto de partida.

    printf '0 0.1\n1 1.0\n2 0.1\n' > env.txt
    modify loudness 11 fuente.wav sube_baja.wav env.txt

07 Glosario

El vocabulario de audio está casi todo en inglés. Estas son las traducciones que usamos, con el término original al lado para que puedan googlear.

Muestra sample
Un número: la presión de aire en un instante. A 44.100 por segundo y 16 bits cada uno, eso es un CD.
Frecuencia de muestreo sample rate
Cuántas muestras por segundo. Fija la frecuencia más alta representable, que es la mitad.
Amplitud
Qué tan grande es el número. Se percibe como volumen, pero no es lo mismo.
Fase phase
En qué punto de su ciclo está una onda. Invisible en un archivo solo, decisiva al sumar dos.
RMS
Promedio cuadrático: el nivel "sostenido" de un sonido, a diferencia del pico. En dB, negativo.
Decibel dB
Una multiplicación escrita en escala logarítmica. −6 dB es multiplicar por 0,5.
Transitorio transient
El ataque, el arranque abrupto de un sonido. Sin transitorios no se escucha ningún efecto de tiempo.
Delay
Una copia de la señal, corrida en el tiempo, sumada al original. El mecanismo 2 entero.
Realimentación feedback
Volver a meter la salida en la entrada. Es lo que convierte un delay en muchos.
Filtro peine comb filter
Lo que hace un delay muy corto: cancela y refuerza frecuencias alternadamente. Se ve como franjas.
Pass-band / stop-band
Lo que un filtro deja pasar y lo que frena. Su orden relativo decide si es lopass o hipass.
Orden de un filtro filter order
Cuántos coeficientes usa. Más orden es corte más filoso, más cómputo y más retardo.
Cola tail
Lo que un efecto sigue sonando después de que la entrada terminó. Por eso las salidas son más largas.
Espectro spectrum
El mismo sonido descrito por frecuencias en vez de por muestras.
Phase vocoder
El algoritmo que va y vuelve entre muestras y espectro. En CDP, pvoc.
Bin
Una franja de frecuencia del análisis. Con -c1024 hay 513 bins.
Frame espectral spectral frame
Una foto del espectro en un instante. El .ana es una lista de estas fotos.
Ventana de análisis window
Cuántas muestras se miran juntas. Grande da precisión en frecuencia; chica, en tiempo. No las dos.
Waveset
Un tramo entre cruces por cero. La unidad con la que distort reescribe la forma de onda.
NaN
Not a Number. Un valor de punto flotante que contamina todo cálculo en el que participa.
Chunk
Un bloque con nombre y largo dentro de un archivo RIFF. fmt, data, PEAK, LIST.