The original idea of this repository was to simulate chladni figures, but I wasn't really able to produce recognizable ones. It's still fun to listen to some music and play around with, though. Here's a demo video. The song is The Hole Pt. 1 by Noisia. Apologies for the short duration and horrible video quality, but I had to work hard to get the file size down to the 10MB limit for GitHub.
final-out.mp4
Here's the idea behind it: There's a mesh of particles where every particle is connected to its neighbors via a "spring" as depicted in the following graphic.
A single simulation step will calculate the force of these springs and apply it to the particle. The Iterations parameter controls how often this step is repeated. A larger value will effectively cause faster propagation of changes through the mesh.
Right now the 4 corners of the mesh are fixed in place for no other reason than personal preference. In order to prevent it from forming a hyperbola1 along the edges, the attraction force is only applied along the y-axis.
All of this happens on the CPU (the code for this is located in the ./zig-mesh
directory). Running the simulation on the GPU would probably increase the performance a lot, but that's a task for another day.
The Tension parameter
In this configuration the spring is at equilibrium.
Expanding it to a length greater than its resting length generates a force that pulls the two particles together.
Compression of the spring causes the particles to be pushed apart.
The particle
Most devices will probably render the visualization at something like 60 frames per second. This effectively means that we downsample the audio signal to that rate. Going down from
I have tried the following to make the simulation more "realistic", but I don't think it's possible to run this fully in realtime.
-
Run the simulation for every single audio frame (so 44100 simulations per second, if that's the sampling rate of the audio signal.)
-
Only actually render the visualization at 60 frames per second or whatever the desired rate is.
However, this makes it unwatchable, because you have to wait a pretty large amount of time between every video frame. Assuming an audio sampling rate
You can work around this issue by assembling all of the frames into a video, but last time I checked there was no easy way to do this in the browser. Mind you I wrote this code more than one year ago and things seem to have changed in the meantime. I recently stumbled across the WebCodecs API, which sounds like it could do the job. But this is yet another task for another day.
1At least that's what it looks like. I cannot provide any proper mathematical reasoning for this.