Si eres legal, eres legal

28 nov 2008

Si eres legal, eres legal. Y si censuras, censuras. Quiero ver mi comentario publicado.


La piratería destruye la cultura: imponer un canon a todo soporte digital o acusar de robo a toda una Sociedad es la auténtica piratería. Perseguir el libre intercambio de cultura es una medida propia del feudalismo medieval para mantener al pueblo lejos de la música, el cine, el arte. Robar dinero a un artista es un delito, pero compartir música o películas no es robar, nunca lo ha sido y ahora tampoco lo es.

Síntesis aditiva

23 nov 2008

El último día en el GUL estuvimos hablando sobre audio, y les comenté algunos de mis experimentos que hice hace ya muuuuchos años sobre un Amiga 2000 que decidió dejar de funcionar hace ya mucho tiempo. Les propuse algún experimento sobre síntesis aditiva, y como la explicación fue un poco rápida pensé que era mejor escribirlo todo y así se puede leer con tranquilidad.

Mientras escribía esta frase me he acordado de que el monstruo llevaba un Motorola 68K -aparte de otros tres micros llamados Agnus, Denise y Paula- que mi hermano decidió sacar antes de tirarlo, y eso me ha recordado otro cacharro que estará perdido por el trastero alimentado por el mismo micro, una Master System II que quizá sea aprovechable.

La historia era muy divertida: me gustaba la música, y jugaba con trackers. Un día me harté de los dos disquetes de sonidos (samples) que tenía y pensé que sería bueno intentar generar nuevos sonidos. El Aegis Sonix era muy interesante como sintetizador, pero su interfaz para componer era una basura. A mi me gustaban los trackers, concretamente Oktalyzer.

La prueba consistió en crearme un programa (en BASIC) que abría un fichero de audio (en formato IFF, Interchange File Format) y leer los bytes uno a uno, representando en la pantalla un punto por byte, en la X el número de byte y en la Y el código ASCII del mismo; al principio aparecía algo de ruido, pero tras ello comenzaba a verse la forma de onda del sample que había visto tantas veces en Oktalyzer. Por alguna razón que no entendí, la onda estaba partida, cuando se suponía que cruzaba por el cero se salía del límite superior y volvía a entrar por el inferior. Para mi era asombroso, no entendía la razón, pero podía hacer una funcioncita que arreglara ese problema. Años después aprendí los conceptos de byte con signo y byte sin signo y lo que era el complemento a dos.

Mi primo, que sabía mucho de matemáticas, hizo alguna vez unas pruebas en el ordenador donde representaba figuritas muy monas empleando unas funciones llamadas seno y coseno. Yo no sabía lo que eran, pero me gustaba la forma que tenían. Cogí sus programitas y me puse a jugar, sumando senos y cosenos, con argumentos diferentes, restándolos, multiplicándolos, elevándolos al cuadrado… así conseguía dibujar funciones bonitas. Una vez sumé un seno al cuadrado con un coseno al cuadrado y pensé que algo estaba mal porque siempre me daba una línea horizontal en el valor 1.

Hice la prueba de generar un coseno (que por entonces lo único que sabía era que era bonito) e hice la operación contraria, crear un archivo de sonido y leerlo desde oktalyzer. Obviamente el ruido inicial eran cabeceras, así que probé a, simplemente, obviarlas y a ver si colaba. Hoy en día le dices a Oracle 9 que lea un SQL de Oracle 8 y te dice que eres tonto, pero a Oktalyzer le decías que abriera un IFF sin cabecera y lo hacía. Años después aprendí que eso se llama RAW.

Y así comencé a jugar a sintetizar soniquetes. Era muy cansado porque el programa BASIC generaba el sonido, pero para escucharlo tenía que guardarlo en un disquete, irme a Oktalyzer, cargarlo, cerrarlo y volver al BASIC, cambiar el código del programa y empezar de nuevo.

La conclusión fue que todo sonaba igual de mal. No estridente ni insoportable, sino aburrido y falto de timbre. Era como los sonidos de los tecladitos casio baratos.

Entonces pensé que lo mejor era intentar imitar alguno de los sonidos que ya tenía en mis dos disquetes de samples, así que me puse a mirar su forma de onda detenidamente. Para hacer zoom en la forma de onda tuve que emplear, digamos, métodos ópticos, porque Oktalyzer no tenía zoom, así que creo que gané alguna dioptría. La conclusión a la que llegué fue que un sonido era una onda con determinada forma que se iba transformando en otra onda parecida. Yo no sabía nada de frecuencia, así que no sabía que eso es una consecuencia muy simple del hecho de que una función periódica puede representarse como suma de senos a diferentes frecuencias y fases: el desfase relativo de los diferentes senos hace que la función sintetizada empiece teniendo una forma y acabe teniendo otra. Lo que me sorprendía muchísimo era que, aunque la forma de onda inicial y final eran diferentes, el timbre no cambiaba. Es decir, que ambas formas de onda tenían una especie de espíritu, lo que llamamos espectro, todo muy esotérico.

Así que decidí hacer una prueba más: me hice un programa que consistía en dos ventanas en las que podías dibujar una forma de onda inicial y final, y él te interpolaba linealmente todos los pasos intermedios, generando así un sonido con un timbre mucho más interesante. Extendí la aplicación, inspirado en unas fotos del Fairlight CMI, para hacer que pudieras generar sonidos con varias interpolaciones; mi primo, el de los senos y cosenos, me dio un par de funciones interesantes para interpolar de forma no lineal (ahora creo que era una exponencial) y estaba yo tan contento con mi superprograma que hasta le hice fotos. Vete a saber dónde estarán ahora.

Es curioso que los sonidos que se generaban siempre tenían un timbre metálico, daba igual qué ondas pintaras, será cosa de la interpolación lineal.

El experimento que propuse es hacerse una síntesis aditiva, que consiste en lo siguiente:

Tenemos un banco de frecuencias que cubren todo el rango audible. Para cada componente i con frecuencia f_i tenemos una amplitud A_i y una fase p_i, que se pueden representar fácilmente con barras de deslizamiento verticales. Cada componente será entonces:

c_i(t) = A_i * cos(f_i * t + p_i)

Por ello, el sonido sintetizado será

s(t) = \sum_i c_i(t)

Lo que viene siendo una serie de Fourier. Juega con las barritas de desplazamiento vertical y podrás generar sonidos más o menos interesantes, pero seguirán sonando muy sintéticos, muy casiotone. Cuando haces que tu GRI (generador de ruido insoportable, guitarra, teclado, flauta o lo que sea) favorito produzca una nota, el sonido que se genera cambia de timbre con el tiempo. El cambio no es brusco (vamos, no empieza sonando a guitarra y acaba sonando a castañuela) pero si suficiente como para que el sonido esté coloreado y que tenga un timbre interesante y atractivo.

Para hacer esto podemos optar por una solución muy simple, que es semejante a la que empleaba yo hace tantos años con mi Amiga, pero en frecuencia en lugar de en tiempo: crear un conjunto de configuraciones (es decir, un conjunto de slides verticales) para diferentes tiempos, e interpolarlos. En definitiva, se trata de que tanto la amplitud como la fase de la componente i no sean constantes, sino que dependan del tiempo:

c_i(t) = A_i(t) * cos(f_i * t + p_i(t))

Tendríamos así una envolvente en amplitud y fase para cada componente. Esto es lo que se viene llamando síntesis aditiva y puede dar resultados muy interesantes.

Para hacer sonar esta onda recién sintetizada puedes optar por dos opciones: la de tiempo real (meter el flujo de señal en la tarjeta de sonido) o la de tiempo virtual (volcar a disco y cargar desde, p.ej. audacity o cualquier otro que soporte RAW). Obviamente la primera es más interesante, pero la segunda es más fácil. En cualquiera de los dos casos tendrás que tomar cada una de las muestras y volcarlas como un chorro de bytes a un archivo, por lo que tendrás que considerar dos cosas:

1- La profundidad de bits. 16 es un buena profundidad, por lo que cada muestra deberá estar representada por un valor numérico comprendido entre 0 y 65535 y ocupa exactamente 16 bit en disco. Si haces “cat” deberás ver chino avanzado.
2- La frecuencia de muestreo. 44,1KHz es un buen punto de partida. Es decir, que queremos reproducir 44100 muestras por segundo. Si vuelcas 44100 muestras en disco deberá durar un segundo.

Si vuelcas a RAW tendrás que decirle a tu programa-lector-RAW que emplee estos mismos parámetros (recuerda, ¡no hay cabeceras en el archivo de sonido!). Si quieres reproducir el sonido en tiempo real tendrás que emplear los parámetros en la configuración de ALSA (si prefieres usar la emulación OSS genial, porque creo que es más fácil mediante un par de IOCTLs y volcar el stream directamente a /dev/dsp)

O lo que es lo mismo, usa Python y alguna biblioteca para sonido.

Recuerda que la tarjeta de sonido reproduce a la velocidad que tu le digas y no a la velocidad con la que generas muestras. Si tienes un core 2 duo podrás generar muchos miles de muestras por segundo, así que lo que deberás hacer es emplear algún temporizador para ir generando las muestras bajo demanda, por ejemplo cada segundo generas 44100 muestras. No olvides que hay fluctuaciones de reloj, que lo que deberás hacer siempre es dormir, despertar y mirar a qué hora te has despertado para ajustar el número exacto de muestras a generar. Pero puedes ignorar estas pequeñeces hasta que tengas una buena interfaz gráfica, cómoda y creativa.

Y a partir de aquí, captura los eventos de teclado y mapea cada tecla con una frecuencia fundamental que será la de la escala bien temperada. qwertyui = do re mi fa sol la si do. Busca la tabla de frecuencias f_base en la web y empléalas para desplazar el conjunto de componentes generadas y poder, así, tocar diferentes notas:

c_i(t) = A_i(t) * cos((f_i + f_base) * t + p_i(t))

Si usas un teclado MIDI, ALSA debería darte la oportunidad de leer los eventos MIDI. Si tu teclado es bueno podrás leer también la velocidad y el after touch. En fin, las posibilidades son bestiales, solo hace falta un poco de ilusión y ganas. Probablemente ya haya docenas de programas que hagan todo esto, pero no se trata de hacerlo sino de aprender a hacerlo, ¿no?

(c) 2010 voiser.es | Creado con WordPress | Tema basado en Barecity