Cómo generar música usando simulación física





Las simulaciones de física tienen una característica increíble: se pueden detener, rebobinar y reproducir. Esta es una herramienta muy poderosa que puede usarse para generar mundos inusuales. En esta publicación, describiré cómo usé esto para sincronizar el sonido de las bolas golpeando música famosa. ¡Pregunto a los interesados ​​bajo el corte!



Introducción



Me encanta crear todo tipo de visualizaciones sofisticadas, simulaciones de física y todo ese tipo de cosas. Entonces, hace dos o tres años, cuando estaba desarrollando mi siguiente idea , tuve una idea, pero ¿y si generamos el mundo físico para que los procesos que tienen lugar en él creen una melodía? De hecho, en una simulación por computadora, siempre podemos retroceder, revisar las opciones, elegir la mejor y, al mismo tiempo, tenemos toda la información sobre la melodía: notas, tiempo de reproducción de una nota. Entonces tuve esta idea de vivir en mi cabeza hasta tiempos mejores, hasta que tuve tiempo de escribir algo en cuarentena, así apareció este proyecto con este artículo.



Modelo



Para empezar, decidí elegir un modelo bastante simple. En mi modelo, solo hay dos tipos de objetos: canicas y plataformas o tablas. Las plataformas tienen coordenadas estrictamente fijas, se establecen en dos puntos finales y tienen un ancho constante. Las bolas caen bajo la influencia de la gravedad y pueden rebotar en las plataformas de acuerdo con las leyes de la física. Además, decidí usar solo colisiones absolutamente elásticas para que la energía del sistema siempre permanezca sin cambios. Pero lo más importante es que cuando la bola y la plataforma chocan, se reproduce un sonido, cada plataforma tiene su propio sonido y puede constar de varias notas a la vez.



Por lo tanto, nuestro mundo consta de muchas plataformas, cada una de las cuales tiene un sonido asignado. Y las bolas que caen en este mundo pueden crear una secuencia de sonidos, y en nuestro caso, incluso una melodía.



Algoritmo



Descubrimos el modelo, pero ¿cómo generar un mundo así para que los sonidos de las bolas que golpean se alineen en una melodía conocida ?



Decidí usar el más torpe, sin embargo, que resultó ser bastante buena, la fuerza bruta recursiva, y en la gente común de fuerza bruta . Pero para que todo funcionara como debería, tuve que usar algunos trucos. Todos los pasos posteriores se realizan dentro de una función recursiva:



  1. Simulamos el mundo, hasta el próximo momento en que necesites tocar una nota.
  2. Si durante la simulación hubo una colisión no deseada, volvemos al nivel superior.
  3. , , , . , . -70 +70. «» ( , , ).
  4. 4. .
  5. 5. ,
  6. 6. , , metro tics, no se produjeron colisiones y, de ser así, devolver el mundo resultante como resultado.


En la imagen se puede ver la visualización de un paso de este algoritmo:







Nota
, , , . , , . , . , .



Recursion atascada



Como cualquier algoritmo de fuerza bruta , este tiene un inconveniente en forma de "recursividad estancada", esto sucede cuando alguna plataforma "mala" no permite que el mapa se genere en el futuro, pero al mismo tiempo te permite generar una parte suficientemente grande del mismo, pero no completamente ... En este caso, la recursividad se bloqueará hasta que enumere todas las opciones en el subárbol de recursividad que genera esta plataforma "mala". No hay problema cuando la altura de este subárbol no supera los 4-8 niveles de recursividad, pero a veces puede llegar a los 20-30 niveles, lo que hace que sea simplemente imposible iterar a través de todas las variantes de este subárbol.



Por lo tanto, en mi implementación, decidí usar una heurística para superar el estancamiento. La idea es colapsar parte de la recursividad cuando se detectan tales casos. Me pareció más obvio volver are los niveles de recursividad son mayores si durante kiteraciones, no pudimos mejorar la longitud máxima de la ruta generada en las plataformas. En mi caso elijok como el 10% del número de notas, y recomo 2000.



Puede ver el resultado de esta heurística en la demostración, cuando el progreso de la generación de mapas a veces se restablecerá en un 10%. Pero al mismo tiempo, te permite completar la generación de la tarjeta en un tiempo razonable.



Generación iterativa



Ahora solucionemos el siguiente problema: después del inicio de la generación del mapa, la página se congela durante 10-30 segundos y es imposible entender lo que está sucediendo, todo se ha caído, o simplemente lleva mucho tiempo generar el mapa. Por lo tanto, decidí escribir también una implementación iterativa del algoritmo de generación para que puedas construir consistentemente un mapa en pequeñas porciones.

No tuve que inventar algo nuevo, simplemente reescribí el algoritmo recursivo en una pila explícita. Así, apareció una barra de progreso en la página que te ayudará a entender que el código no ha caído, solo lleva bastante tiempo encontrar una ubicación adecuada de plataformas para tu pista.







En algunos casos, la generación puede tardar demasiado, para esto agregué el botón Reproducir , que detiene la generación e inicia la simulación del mundo.



Descargar tono de llamada



Para descargar la melodía, utilizo archivos midi, pero antes de eso lo ejecuté a través de tonejs.github.io/Midi para convertirlo en un json compatible con el navegador (pero en este momento la demostración no tiene la funcionalidad de descargar mi archivo, solo está disponible una opción de una lista preparada).



También es importante tener en cuenta que a menudo habrá varias pistas paralelas dentro del archivo midi, pero dado que mi algoritmo hasta ahora solo funciona con una bola, solo una pista se cargará con la mayor cantidad de notas.



resultados



Después de agregar algunos efectos, grabé el primer video:





Después de revisarlo varias docenas de cientos de veces, decidí mejorar ligeramente la parte visual. Agregué un fondo de dos capas en movimiento, hice un efecto de brillo en la pelota y en las plataformas al impactar, reemplacé las notas voladoras con chispas. Después de eso, todo comenzó a verse mucho mejor, el resultado final está en el video:





El video puede mostrar una desincronización, lo noté más tarde. Si va a la página con la demostración , no debería haber ninguna desincronización (el sonido en realidad se reproduce solo cuando se registra el ritmo).



Como resultado, me sé todas estas melodías de memoria y mis oídos reconocen cualquier melodía por las dos primeras notas.



¿Que sigue?



Tengo planes de agregar la capacidad de generar tales mapas para varias bolas a la vez. Tengo ideas sobre cómo hacer esto, probé varias opciones, pero hasta ahora todas funcionan muy lentamente para generar una pista completa.



Otra idea mía fue agregar nuevos objetos: botones, trampolines, pistolas (?), Anillos ... la lista se puede complementar :) Pueden diversificar significativamente el mundo.



El código



Puede encontrar todo el código fuente en mi repositorio. ¡



Cualquier sugerencia, solicitud de extracción, cuestionario es bienvenida!



All Articles