Dibujar música: baile de ataúd en Pure Data

Programacion y Memes


La programación es un proceso al borde de la ciencia y la creatividad. Sin un programa bien diseñado, una computadora es una unidad indefensa que gasta electricidad. La mayoría de los especialistas modernos trabajan con lenguajes simbólicos declarativos: crean programas a partir de comandos de texto: simple: asignación, multiplicación; y complejo - verificando condiciones, ejecutando rutinas en un bucle.

Pero no todos los lenguajes de programación están diseñados para resolver problemas del sistema. Algunos se crean para capacitación, presentaciones y espectáculos digitales. Cuando el rendimiento y la funcionalidad se desvanecen en el fondo, surgen soluciones originales como el entorno de programación visual Pure Data.

En 2020, el baile del video archivado de la ceremonia fúnebre de la agencia Dada awu de Ghana se convirtió en el meme más popular en Rusia. Hoy tenemos que recrear paso a paso el legendario tema musical Coffin Dance, utilizando el entorno de descripción de sonido algorítmico Pure Data.

Sobre programación visual


Mediante la programación visual, es habitual comprender el proceso de describir un programa para un dispositivo informático utilizando elementos gráficos funcionales. Por lo tanto, el uso del diseñador de formularios WPF en el entorno de desarrollo de Visual Studio puede llamarse programación visual de la interfaz. Los diseñadores gráficos aparecieron junto con las primeras computadoras personales. Ahora en las clases de informática, Visual Pascal se está estudiando en algunas escuelas. y la mitad de las mejoras estándar en 1C se pueden hacer sin escribir una línea de código.

Pero los entornos de programación visual en toda regla aparecieron más tarde. Cuando se trata de crear un lenguaje de programación que consista solo en comandos gráficos, surgen una serie de dificultades, por lo que la funcionalidad del lenguaje en sí tiene que ser reducida.
Por lo tanto, las llamadas múltiples del mismo subprograma en diferentes partes del código C ++ son naturales para el programador. En un entorno gráfico, una llamada de subrutina se puede representar, por ejemplo, con una flecha desde un objeto en el texto del programa principal a una subrutina de objeto, y cuando hay demasiadas flechas de este tipo, el código gráfico se vuelve ilegible. Los desarrolladores de entornos de desarrollo educativo a menudo imponen un límite (en la cantidad de llamadas, objetos en el programa, variables utilizadas) para proteger al usuario y hacer que el proceso de programación visual sea más visual.
Un ejemplo de un programa Sanscript simple:

imagen

Pero si se distrae de la programación en sentido amplio, puede encontrar importantes problemas aplicados que se resuelven gráficamente de manera más conveniente y más eficiente que en simbólica. Una de esas tareas: una descripción de los instrumentos virtuales. En los años 80 del siglo pasado, la mayoría de las grabaciones musicales se hicieron en vivo. Los sintetizadores digitales eran inferiores en calidad de sonido a los instrumentos acústicos, y los sistemas digitales verdaderamente "musicales" eran caros.

Todo ha cambiado con la introducción de la tecnología VST, introducida en 1996 como una biblioteca voluminosa para trabajar con sonido. La funcionalidad VST nos permitió describir la arquitectura de sintetizadores digitales reales, procesadores de efectos y emular con mucha precisión su trabajo en una computadora. Sin embargo, solo un equipo de programadores calificados e ingenieros de sonido podría construir tal descripción. La cuestión de crear instrumentos virtuales personalizados permaneció abierta.

En esos mismos años, en un intento de popularizar la síntesis de sonido entre los aficionados, apareció el proyecto experimental Pure Data, un entorno de desarrollo visual centrado en la descripción de sintetizadores simples. En torno a Pure Data, se formó un pequeño grupo de "fanáticos" que promovieron la programación visual en FB, Youtube: escribieron y tradujeron materiales de capacitación, publicaron ejemplos de sintetizadores y mezclas de música completa en un parche (este es el nombre del programa Pure Data por analogía con parches en sintetizadores de hardware modular ) Pero el medio ambiente no ha recibido una amplia distribución en el mundo.

Fundamentos de datos puros


El entorno de desarrollo de Pure Data se puede descargar de forma gratuita desde el sitio web oficial. El programa distribuye código abierto y está disponible para usuarios de Windows, Linux y MacOS X. Instale y ejecute Pure Data. En el menú Archivo, cree un nuevo parche. Aparecerá la siguiente ventana de edición:

imagen

El menú Put contiene una lista de objetos gráficos a partir de los cuales crearemos nuestro primer sintetizador. Después de seleccionar el elemento apropiado, el elemento se agrega al campo gráfico (Canvas) del parche actual. Los elementos pueden editarse (cambiar la firma, lo que afecta su comportamiento, así como moverse) y conectarse mediante líneas (manteniendo presionado el botón izquierdo del mouse en una de las salidas del objeto de origen, moviendo el cursor a la entrada del objeto de destino y soltándolo). Por ejemplo, crearemos un elemento de tipo "Objeto" con la clave de nombre y un elemento de tipo "Número". Las entradas del elemento están resaltadas en negro y están ubicadas sobre el marco del elemento en sí, y las salidas están debajo de él. Conecte la salida del objeto clave a la entrada del elemento Number.
Obtenemos:

imagen

Todo este tiempo estuvimos en modo de edición de parches. Para ingresar al modo de ejecución, vaya al menú Editar y desmarque el elemento Modo de edición. El puntero del mouse en el contorno debe cambiar de mano a flecha. Ahora presione cualquier tecla en el teclado principal. Veremos cómo cambia el valor de Número cuando se presiona:

imagen

Analicemos el resultado del parche. Después de asignar la clave de nombre al objeto, tiene una salida, pero no entradas. Un objeto con este nombre escucha el teclado y envía un código de tecla cada vez que se presiona en tiempo de ejecución. El elemento Number tiene una entrada y una salida. Tomando un número como entrada, Número lo muestra en la pantalla y envía el mismo valor a la salida. Tenga en cuenta que después de soltar la tecla, el número continúa mostrándose. Esto muestra que las entradas retienen el último valor que aceptan.

Regrese al modo de edición y agregue otro objeto llamado sel 49. Tendrá dos entradas y dos salidas. Este objeto envía una señal a la primera salida cada vez que llega un valor a una de las entradas y coincide con el valor almacenado en la otra entrada. Si la entrada recibe un valor diferente al acumulado, la señal se envía a la segunda salida. La primera parte del nombre sel especifica el tipo de objeto, el segundo 49 escribe el valor predeterminado para la segunda entrada. 49 es el código clave "1".

Una señal es un tipo de datos especial que no puede emitirse simplemente, por ejemplo, enviando un Número a la entrada. Pero con la ayuda de señales puede "comenzar" el trabajo de algunos elementos.

Regrese al menú Put y agregue el elemento Bang a nuestro parche. Conecte la salida de Número a la primera entrada sel 49 y la primera salida sel 49 a la entrada Bang. Recibiremos el siguiente parche:

imagen

Pasaremos al modo de ejecución. Al presionar varias teclas, aparecerán sus códigos. Cuando presiona la "tecla especial" con el código 49, el objeto sel generará una señal que, cuando presione el botón de explosión, la presionará automáticamente:

imagen

el objeto de explosión genera una señal en su única salida cuando se presiona en modo de ejecución, la señal o el valor llega a la entrada. Agregue un poco de sonido a nuestro proyecto. Para que el parche funcione correctamente con datos de audio, el menú Media debe tener una marca de verificación opuesta al elemento DSP On. También deberá ingresar al menú de Configuración Midi e instalar el dispositivo de salida. En Windows:

imagen

Haga clic en Aceptar y regrese al modo de edición. Para trabajar con señales Midi, se utilizan con mayor frecuencia 2 elementos: makenote y objetos noteout. Agregue uno de estos objetos y también cree varios mensajes de Mensaje con los siguientes valores: El

imagen

mensaje es un elemento de programación visual con un comportamiento complejo. Si el mensaje se llama cierto número, al hacer clic en el mensaje o al recibir una señal en su entrada, en ambos casos, este número y señal se emitirán simultáneamente.

El objeto noteout, cuando recibe el valor en la primera entrada, genera sonido en uno de los canales MIDI. El número de canal puede indicarse explícitamente en el nombre del objeto (en nuestro caso 1 - piano) o transferirse a la tercera nota de entrada. La primera entrada toma el tono en términos de midi: (60 - esto es a la primera octava y luego +1 - un aumento de medio tono, -1 - una disminución de medio tono), y el segundo - una descripción de la nota: volumen, duración, naturaleza de la producción de sonido.
El objeto makenote recibe el tono a la primera entrada y al segundo volumen (0 - silencio, 127 - volumen máximo) traduce el tono a la primera salida y genera una descripción de nota para la segunda nota de entrada en la segunda salida. Los valores predeterminados para la primera y segunda entrada de makenote se especifican inmediatamente después del nombre del objeto. Conecte los elementos como se muestra en la figura y vaya al modo de ejecución:

imagen

cuando hace clic en un mensaje, debe sonar una nota correspondiente al tono en el nombre del mensaje. 60 - nota a, 62 - re, 67 - la. Ahora en modo de edición, conecte la primera salida del selector (objeto sel) con el mensaje 60. Agregue 2 selectores más con códigos para las teclas 2 y 3 en el teclado y obtenga el sintetizador más simple:

imagen

Presionando las teclas 1-3 en makenote enviará un mensaje con el tono apropiado y sonará una nota. En la siguiente sección, intentaremos describir una melodía compleja que se reproducirá secuencialmente, nota por nota, cuando se envía una sola señal.

Recreando la danza del ataúd


Música


Para describir una melodía compleja, necesitamos estudiar 2 objetos importantes: metro yf, así como varios objetos auxiliares. Considere un ejemplo simple:

imagen

El objeto metro tiene dos entradas. Se recibe la primera señal. Cualquier señal que no sea stop incluye un metrónomo. Para deshabilitar, use la señal de salida del mensaje con el texto detenido. La segunda entrada, metro, recibe un intervalo en milisegundos. Cuando se enciende el metrónomo, enviará inmediatamente una señal a su única salida y volverá a enviar la señal cada n milisegundos. El intervalo n puede especificarse mediante el valor predeterminado en el nombre del objeto o transferirse a la segunda entrada. Una vez que ingresamos al modo de ejecución, podemos iniciar el metrónomo con el botón de explosión encima y ver cómo se presiona el botón debajo de cada 0,4 segundos. Al enviar un mensaje con un nuevo intervalo, aceleraremos o disminuiremos la frecuencia de envío de señales. Después de enviar el mensaje de detención, la señalización se detiene.

Recordemos la música de Coffin Dance:


La melodía principal se puede describir mediante una secuencia de 64 notas y pausas de la octava duración, es decir. a las 8 medidas en 4/4. Por lo tanto, debemos organizar el envío cíclico de las 64 señales a los mensajes de nota correspondientes. Para hacer esto, use el objeto f.

F - desde flotante - representa una variable real. El objeto f tiene dos entradas. En la segunda entrada, puede enviar un valor numérico (por ejemplo, de la salida del mensaje o la salida de Number), que se escribe como el valor de la variable. El valor predeterminado es 0. Con la primera entrada y salida, las cosas son un poco más complicadas. Considere un ejemplo:

imagen

Entonces, encontramos una conexión mágica entre los memes "Presione F para rendir respeto" y "Baile de ataúd". Pasemos al modo de ejecución. Cuando hace clic en el mensaje 3, el valor se escribirá en la variable de objeto f, pero en número no lo veremos. Si envía la señal a la primera entrada f con el botón de explosión, lo que sucede en términos de Pure Data es una iteración, a saber:

  • La salida f enviará el valor actual de la variable (3)
  • Object + 5 recibirá el número 3 en la primera entrada y devolverá la suma de dos entradas 8 (aquí el valor en la segunda entrada se establece por defecto después del nombre + objeto de suma)
  • El objeto% 40 recibirá el número 8 en la primera entrada y devolverá el resto de dividir el octavo por 40 (el valor de la segunda entrada se establece por defecto)
  • La variable f recibirá el valor (3 + 5)% 40 = 8 en la segunda entrada. La iteración se completa

Por lo tanto, después de la primera iteración, vemos el valor 3 en el número de entrada y tiene un valor real de 8 para la variable f. En la próxima iteración, el número obtendrá los ocho guardados antes, y f aumentará en otros 5 y tomará el valor 13. Cuando se trata de la iteración con la salida 38, obtenemos el valor (38 + 5)% 40 = 3 para la variable f. Por lo tanto, los valores f y los valores de salida se repetirán cíclicamente. El uso del módulo de suma y división le permite obtener un ciclo con cualquier período y cualquier valor para las iteraciones.

Conecte la salida del metrónomo a la primera entrada f, y configure varios selectores y botones en la salida f. Inicie el metrónomo y vea cómo se iluminan los botones a su vez y después de presionar automáticamente el último botón, el ciclo se repite. Parche:

imagen

Para que el ciclo se ejecute cada vez desde el valor 3, conecté la salida del mensaje de parada a la entrada del mensaje 3 enviando el valor inicial a f.

Describamos la melodía. Para hacer esto, cree un parche limpio y describa el metrónomo con un intervalo de 230 (exactamente 230 milisegundos dura una octava nota en la melodía) y un ciclo de 64 notas. Para seleccionar los valores, usamos la variable f y el nuevo elemento moses para nosotros, cuya funcionalidad se describirá a continuación. También agregamos algunos objetos makenote, mensajes con notas, notas con los canales 1 (piano) y 10 (batería), y combinamos los selectores moses de cada iteración con las notas correspondientes. Consigue el parche:

imagen

Como puede ver, con la programación visual, el uso de una gran cantidad de objetos reduce la legibilidad del programa. De hecho, un parche es una combinación de elementos simples. Considere la siguiente "rutina":

imagen

El objeto Moisés almacena un número en la segunda entrada, que se puede configurar de forma predeterminada. Si la primera entrada recibe un número menor que el valor almacenado de la segunda entrada, se envía una señal desde la primera salida de Moisés, de lo contrario, la señal se envía desde la segunda salida. Por lo tanto, la primera salida de Moisés 1 se comporta de manera similar a la primera salida de Sel 0. Veamos un grupo de + 63% 64. Le permite reducir los valores en el bucle en uno. Si uno fue de entrada, entonces la salida será 0, para la entrada 0 la salida será 63; obtenemos un ciclo de 64 elementos en el orden inverso. Si conectamos la salida de este paquete a la entrada de la siguiente construcción + 63% 64 y conectamos Moisés 1 a la salida de cada paquete, pero para cada uno de los 64 valores posibles de f, exactamente un Moisés enviará una señal a la primera salida. Entonces, el número 7 debe reducirse 7 veces en 1,para obtener 0, el séptimo musgo 1 en la iteración 7 recibirá 0 en la primera entrada y enviará una señal a la nota correspondiente. Si para 64 selectores necesita editar manualmente los valores predeterminados de los parámetros, entonces se pueden copiar las subrutinas + 63% 64 moses 1 y conectar las salidas del% 64 anterior a las entradas + 63 obtiene un complejo selector cíclico de 64 posiciones.

El parche de melodía utiliza la duplicación de objetos de nota. Esta técnica le permite aumentar el volumen sin pasar por la marca de límite. Entonces, si conecta el mismo makenote 67 127 a 2 noteout 1, pero cuando envía una señal desde la primera entrada de makenote, la nota la (código 67, primera octava) se reproducirá con un volumen de 127 * 2 = 254. Instrumentos MIDI en Pure Data muy silencioso, por lo que esta técnica es útil para crear melodías de conjunto (en nuestro caso, se tocan 2 pianos en los canales 1 y 5 y el kit de batería 10 con volumen triple).

Para decorar la simulación (el proceso de mover datos entre objetos del código de parche en tiempo de ejecución), es conveniente usar botones duplicados. En el ejemplo anterior, sus 6 objetos de explosión tienen una silueta del botón Reproducir, que se resalta automáticamente cuando se presiona el botón de explosión extrema a la derecha. El procesamiento de la señal de explosión es un proceso que requiere muchos recursos, pero en la siguiente sección colocaremos una gran variedad de botones e intentaremos representar un baile del video con su ayuda.

Animación


Para la animación, necesitamos las mismas variables f, objetos: operadores aritméticos y un metrónomo, así como selectores. Esta vez solo necesitamos 8 cuadros, por lo que utilizaremos objetos sel. Cree un campo de 20x10 a partir de los botones de explosión (utilizaremos la operación de copia). Después de colocar el parche con la melodía en el centro, obtenemos la siguiente figura:

imagen

simplemente puede conectar las salidas izquierdas de cada selector a los botones que se deben presionar en este marco y enviar la señal desde el metrónomo a la entrada de una nueva variable de ciclo f. Pero este enfoque tiene 2 defectos:

  • 0.23 segundos por cuadro, demasiado rápido para nuestro baile. Y el uso del segundo metrónomo nos sacará del ritmo: noteout y bang tienen un retraso diferente en respuesta a la señal;
  • el botón permanece presionado durante 0.05 segundos desde el momento en que se recibió la señal, lo que significa que durante los restantes 0.18 segundos la "pantalla" de la animación estará en blanco y la imagen en el bucle parpadeará.

Para resolver estos problemas, usamos la división. La siguiente construcción:

imagen

toma el valor de entrada f de la melodía del ciclo principal. Después de dividir por 2, obtenemos una desaceleración del cambio de cuadro: para 0 y 1, se mostrará el cuadro 1, para 2 y 3, el cuadro 2 y así sucesivamente. Para cada cuadro, todavía se envía una señal cada 0.23 segundos. Ahora usemos otro ciclo:

imagen

Para sincronizar con la melodía principal, se le ha agregado un retraso: la señal de inclusión pasa primero del selector a través del botón y solo luego a la primera entrada del metrónomo. Ahora, si crea una explosión y conecta su salida a todos los botones de píxeles de un cierto cuadro, entonces el cuadro de arriba puede resaltar el cuadro cada 0.046 segundos, que es más rápido que la frecuencia de actualización de los botones, es decir. el marco se iluminará continuamente hasta que cambie el siguiente marco. Un ciclo de 5 iteraciones asegura que los cuadros no serán estratificados, ya que 0.046 * 5 = 0.23 segundos - el período de los selectores de cuadros.

Al crear una animación, la computadora se bloqueaba regularmente, pero era posible dibujar 5 imágenes diferentes y crear un ciclo de 8 cuadros a partir de ellas en el orden:

1 2 3 2 1 4 5 2

El parche final con Coffin Dance (muchos elementos decorativos - botones y comentarios añadidos) en modo de edición:

imagen

apenas es posible analizar el código fuente de la simulación en esta imagen infernal, sin embargo, el parche funciona correctamente:

imagen

en la esquina inferior derecha se usa un contador para detener automáticamente al jugador después del 121 notas Inicialmente, se suponía una animación de 48x24 píxeles, pero la computadora la rechazó categóricamente con un rugido triste del refrigerador y un reinicio inesperado de Windows en modo seguro. El original pixel art 48x24 del artista LikaLou adjunto al final del video. Entonces, después de 3 días de "dibujar música" tenemos Coffin Dance en Pure Data:


Conclusión


La programación visual de memes es una actividad divertida, aunque lleva mucho tiempo y a veces destruye su hardware. Incluso una tarea de baile fúnebre aparentemente tan simple requiere un enfoque modular para crear un programa, conocimiento de las características no solo del lenguaje de implementación, sino también del entorno de desarrollo.

Usando el parche de ejemplo para Coffin Dance, puede juzgar el nivel de desarrollo de la programación visual. Existen lenguajes gráficos que se adaptan bien a algunas tareas de aplicación, si son entornos de desarrollo convenientes. Pero la industria de la programación visual en su conjunto está en su infancia.

Referencias


Sitio web oficial de Pure Data
Conceptos básicos de programación visual en Pure Data
Acerca del artículo VST estándar
Coffin Dance en Wikipedia
Coffin Dance en Pure Data: video original

All Articles