.

La semana pasada me pasaron el enlace a Quick, Draw!, una especie de Pictionary donde tu pareja que intenta adivinar lo que estás dibujando es una red neuronal. Como juego es gracioso pero lo que me gustó aún más fue descubrir que forma parte de un grupo de experimentos de inteligencia artificial de Google. De ellos, dos tienen un corte claramente musical.

El primero es The Infinite Drum Machine, una caja de ritmos básica que permite utilizar en tu navegador miles de sonidos cotidianos. La gracia de este experimento reside en que la catalogación y agrupación de sonidos la ha hecho una máquina utilizando un algoritmo de aprendizaje automático t-SNE sobre el audio exclusivamente, sin utilizar etiquetas o cualquier otro tipo de indicaciones.

Los que tengan el tiempo y los conocimientos adecuados pueden explorar el código fuente de The Infinite Drum Machine en GitHub, algo en lo que invertiría el primero de los dos requisitos anteriores (si lo tuviera) para ver si puedo adquirir un poco más del segundo requisito.


Fotograma del vídeo de presentación de The Infinite Drum Machine [01m51s].

El segundo experimento que llamó mi atención fue A.I. Duet, una red neuronal ya entrenada que “responde” a las melodías que pueda crear una persona, creada utilizando Tone.js y herramientas de Magenta. Aunque en este caso todavía no hay una versión web donde jugar con el experimento, se puede explorar código fuente de A.I. Duet en GitHub.


Fotograma del vídeo de presentación de A.I. Duet [02m14s].

Debo admitir una cierta envidia sana al ver estos proyectos. Hace no tanto dejaba por aquí un apunte sobre redes neuronales que componían pistas de batería aprendiendo de Metallica y ya entonces me lamentaba de no tener tiempo para explorar estas materias.

.

Hoy se decide la última nota en la melodía de CrowdSound.net, un experimento de composición en masa:

Se está generando una melodía nota a nota, en tiempo real, utilizando el voto popular. […] Esta melodía se convertirá en una canción con una estructura de acordes Do, Sol, La menor, Fa repetida 18 veces. Tendrá una estructura de (Verso / Verso / Coro / Verso / Coro / Conclusión). La canción está a día de hoy en forma de esqueleto.

El resultado del proyecto es curioso, igual que las estadísticas que sacan del proceso, aunque me interesó más ver cómo generaban la partitura con canvas y los sonidos con howler.js. Se puede reproducir la melodía eligiendo con el sonido de qué instrumento se quiere oír, saltar directamente a una parte de la canción y modificar el ritmo de la reproducción.

También resulta curioso, aunque no creo que sea casual, que la progresión armónica utilizada sea la popular I–V–vi–IV. Es casi imposible no oírla a menudo, como señalaron Axis of Awesome, y afianza más mi teoría no verificada ni estudiada (ni siquiera tiene mucho sentido) que su uso debe ser un método para reducir la complejidad de las canciones.

.

Keunwoo Choi es un estudiante del Centro de Música Digital de la Queen Mary, Universidad de Londres. Bajo la tutela del profesor Mark Sandler y el doctor Gyorgy Fazekas ha publicado un texto titulado «Text-based LSTM networks for Automatic Music Composition», disponible en arXiv y que resume en su página web:

RNN de palabras (LSTM) sobre Keras con representaciones textuales empalabradas de ficheros MIDI de la batería de Metallica, provenientes de midiatabase.com.

No es la primera vez que veo el uso de redes neuronales recurrentes para componer música, lo que no quita que me siga pareciendo interesante. Los resultados no son espectaculares pero sí curiosos, y me gustaría tener más tiempo para poder entender mejor cómo se implementa la RNN.

.

Ben Frederickson, un desarrollador de software que vive en Vancouver, ha publicado un par de entradas en su blog sobre cómo calcular la similitud entre dos artistas en términos de distancia. Para ello hace uso de un conjunto de datos sacados de last.fm en 2008 para plantear y desarrollar distintos métodos.

En la primera entrada parte de un criterio de similitud sencillo: el número de usuarios que dos artistas tienen en común. Rápidamente identifica como problema que los grupos más populares los tendrán casi todos los usuarios, con lo que la métrica no resulta especialmente fiable. La solución más sencilla que propone es calcular el coeficiente de Jaccard, aunque también menciona el coeficiente de Sørensen–Dice y el coeficiente de Ochiai. Después explica cómo tratar el problema como uno geométrico, con sus beneficios y penalizaciones, para pasar a comentar y mostrar las ventajas de usar TF-IDF y, finalmente, Okapi BM25.

La segunda entrada se centra en el uso de factorización de matrices para reducir la dimensionalidad de los datos antes de calcular la similitud entre dos artistas. Partiendo de la descomposición en valores singulares para hacer análisis de semántica latente, pasa a explicar e implementar el método descrito en «Collaborative Filtering for Implicit Feedback Datasets».

Para el desarrollo ha usado python, acompañando los resultados de gráficos interactivos hechos con D3.js, lo que hace la lectura aún más interesante.

.

Veía hace unos días una reseña en Hacker News sobre un sintetizador multi-toque hecho con Typescript/React aunque su creador, Luke Phillips, no da detalles de la implementación:

No es la primera vez que menciono sintetizadores hechos con JavaScript, siendo el más conocido probablemente el que hizo Google como homenaje al Dr. Moog.

.

Veo el siguiente código en el blog de Robert Elder:

cat /dev/urandom | hexdump -v -e '/1 "%u\n"' | awk '{ split("0,2,4,5,7,9,11,12",a,","); for (i = 0; i < 1; i+= 0.0001) printf("%08X\n", 100*sin(1382*exp((a[$1 % 8]/12)*log(2))*i)) }' | xxd -r -p | aplay -c 2 -f S32_LE -r 16000

Introducido en una terminal de un sistema Linux con los programas necesarios, genera una melodía aleatoria. En el primer enlace hay una explicación detallada de lo que hace exactamente, aunque se resumir con cada orden entubada:

  1. cat /dev/urandom

    Vuelca los contenidos de /dev/urandom a stdout.

  2. hexdump -v -e '/1 "%u\n"'

    Convierte bytes binarios en enteros (opción -e '/1 "%u\n"') incluyendo las repeticiones (opción -v).

  3. awk '{ split("0,2,4,5,7,9,11,12",a,","); for (i = 0; i < 1; i+= 0.0001) printf("%08X\n", 100*sin(1382*exp((a[$1 % 8]/12)*log(2))*i)) }'

    Procesa la información con AWK de modo que:

    1. split("0,2,4,5,7,9,11,12",a,",");

      Crea un array a con los número de semitonos relativos a la nota base en una escala mayor. Este array se usa para calcular la frecuencia en hercios de una nota de temperamento igual con esta fórmula: 440 × 2^(número de semitonos / 12) 440Hz representa la frecuencia de un La 440.

    2. for (i = 0; i < 1; i+= 0.0001)

      Un contador para generar los tonos. Variar el incremento de cada iteración altera el tempo y la frecuencia percibida de la melodía.

    3. printf("%08X\n", 100*sin(1382*exp((a[$1 % 8]/12)*log(2))*i))

      Imprime números hexadecimales de 4 octetos representando la amplitud de la onda sonora en un momento determinado. La fórmula 100*sin(1382*exp((a[$1 % 8]/12)*log(2))*i)) se puede descomponer en varias partes:

      1. a[$1 % 8] / 12

        A partir del valor aleatorio de la entrada ($1) elige el semitono de la escala y lo divide por doce.

      2. exp(… * log(2))

        AWK no tiene una función para calcular potencias de una base cualquiera pero sí calcula potencias del número e y logaritmos naturales, así que para obtener 2x hay que calcular e(x × ln(2)).

      3. 1382

        Es un valor aproximado de 440 × π.

      4. 100

        Un factor de escala para la amplitud de la onda y, por consiguiente, el volumen.

  4. xxd -r -p

    Convierte los 8 bytes de valores hexadecimales en binario.

  5. aplay -c 2 -f S32_LE -r 16000

    Reproduce el sonido equivalente.

.

El mes pasado me topé con “Beat Detection Algorithms”, un texto en dos partes (1 y 2) sobre la implementación en Scala de un par de algoritmos sencillos con el objetivo titular. Aparte de la explicación de la teoría tras estas implementaciones se puede encontrar el resultado integrado en el código fuente de un proyecto del autor.

Recuerdo haber echado un ojo a este tipo de análisis matemático (aunque sin llegar a aplicarlo) a finales de la década de los 90, en la estela de la demoscene y con el ascenso de WinAmp y sus complementos de visualización. Remontándome sólo al año pasado, tenía apuntado un artículo sobre detección de pulsaciones usando Web Audio, encontrado a través de EchoJS, nuevamente sin llevarlo a la práctica por mi parte.


Grimes – Go: Peaks with a lowpass, highpass, and bandpass filter, respectively.

Este último enlace lo tenía apuntado junto con otra reseña en EchoJS de un proyecto denominado WaveGL, cuyo objetivo era “generar audio en la GPU y transmitirlo a la tarjeta de audio” y del que señalaban uno de varios ejemplos. Con tantos proyectos de programación que he visto recientemente no estaría mal sacar un poco de tiempo para programar por gusto en lugar de por compromiso.

.

No recuerdo dónde oí por primera vez “una idea es una responsabilidad” pero me resulta admirable la gente que es capaz de ponerla en práctica. Una de estas personas es Paul Lewis, trabajador de Google, que se planteaba los siguiente:

Given we have the Web Audio API and getUserMedia, I wondered if I could make a passable guitar tuner. Looks like I can, and in the process I learned way more stuff about audio than I care to mention. Cool stuff, though! I thought I’d do a breakdown of what went into building it.

No contento con desarrollar su idea en su página explica algunos detalles de todo este proyecto personal. Una lectura muy interesante y muy recomendable.

.

Una red neuronal recurrente, o RNN (Recurrent Neural Network) es una clase de red de neuronas artificial en las que las conexiones entre unidades forman un ciclo dirigido. Si no lo he entendido mal, esto quiere decir que la secuencia cíclica de vértices (o nodos) y aristas en un camino es determinada completamente por el conjunto de aristas que usa: sólo se puede recorrer en una dirección. Esto creo un estado interno de la red que le permite exhibir un comportamiento temporal dinámico y procesar secuencias arbitrarias de entradas. También se puede entender como una red neuronal recursiva, igualmente abreviada como RNN, con una estructura en cadena.

Todo esto viene a colación una serie de relativamente breves pero interesantísimos textos de Bob L. Sturm titulados “Deep learning for assisting the process of music composition”, partes 1, 2, 3 y 4. En ellos deja constancia de algunas reflexiones sobre un proyecto veraniego realizado en colaboración con João Felipe Santos denominado The Infinite Irish Trad Session:

So João grabbed all the tunes he could from The Session, I parsed and editted the text file to produce a 13 MB file of 23,962 tunes, and João set to using it to train an RNN with 3 hidden layers having 512 units each. Once finished, João had the system generate a 21 MB text file of new ABC tunes, which I am parsing into its 72,000+ tunes. I convert each ABC tune to MIDI, process it in python (with python-midi) to give a more human-like performance (including some musicians who lack good timing, and a sometimes over-active bodhran player who loves to have the last notes :), and then synthesize the parts with timidity, and finally mix it all together and add effects with sox. Each successful synthesis is then served to my home directory, and a cronjob generates a new playlist every five minutes from the 22000+ tunes already synthesized (that is 18,964,140 kilobytes, which at 128 kbps is a 41 hour trad session!).

Hope you have some craic!

El resultado son composiciones como esta:

Parte del trabajo se apoya en el trabajo de Andrej Karpathy sobre redes LSTM, cuyo artículo “The Unreasonable Effectiveness of Recurrent Neural Networks” explica con algo más de detalle qué son las RNN y sus virtudes.

Todo esto me llegó vía Hacker News, igual que el artículo sobre composición algorítmica de hace unos meses.

.

Hay un gran artículo de Batuhan Bozkurt de mediados de 2009 que describe tanto el origen como el proceso de recreación de Deep Note utilizando SuperCollider. Años después veo este post de Stuart Memo (que de hecho cita al primero) donde explica su experimento intentando aproximar el sonido usando JavaScript:

El sonido [se genera] básicamente [con] 30 osciladores de onda cuadrada emitiendo aleatoriamente en frencuencias entre 200Hz y 400Hz. [El resultado] es filtrado para producir el efecto de barrido que se oye.

El resultado se puede oír en CodePen y tiene una semblanza con la composición del Dr. James A. Moorer.

.

A la imagen anterior llegué pasando por un artículo de Wired de Natah Hurst acerca de otro proyecto de Amanda Ghassaei, siendo la misma persona que hizo los discos usando impresión en 3D. En esta ocasión utiliza un láser para grabar sobre distintas superficies, incluyendo madera, y en los enlaces anteriores se pueden ver y oír vídeos con los resultados. Con todo, yo me quedo con el aspecto de estos grabados:

La autora de estos experimentos habla de intentar grabar canciones en secciones transversales de un árbol, sobre los anillos, lo que me recordó a otro artefacto que “reproduce” precisamente esos anillos.

.

Con años de retraso, leo el artículo The First Computer Musician de R. Luke Dubois:

En 1957 un ingeniero de 30 años llamado Max Mathews consigió una computadora IBM 704 en los laboratorios Bell Telephone de Murray Hill, Nueva Jersey, para generar 17 segundos de música, que después grabó para la posteridad. Aunque no fue la primera persona en producir sonidos con una computadora, Max fue el primero en hacerlo con una combinación replicable de hardware y software que permitía al usuario especificar qué tonos quería oír. Esta pieza de música, llamada “The Silver Scale” y compuesta por un colega en los laboratorios Bell llamado Newman Guttman, no pretendía ser una obra maestra. Era una prueba de concepto, y puso los cimientos para un avance revolucionario en la música, un hecho cuyos ecos pueden sentirse en todas partes hoy en día.

El texto completo merece la pena ser leído y en la Wikipedia hay más datos de este ingeniero. Entre esto y la charla de Chris Wilson que vi el otro día uno podría sentirse motivado a hacer algo creativoy ver si realmente se tiene ese talento.


Max Mathews, 2011. Imagen vista en Wikimedia Commons.