Back to blog

What Does a Klein Bottle Sound Like?

Long story short, this:

Colab link

Background

So I've always been fascinated by shaders, I think it's really cool that you can make an image from first principles just by writing some code (check out Inigo Quilez's channel for really good examples of this). I recently wondered if you can do the same thing with sound, looks like you totally can! I ran into the NESS Project, which does exactly this. They were able to simulate a wide variety of instruments, very realistically. A primary technique here is to use FDTD to simulate the sound waves propagating through the instruments & through the air.

So my thought is, can we do this with instruments that we can't physically build? Like say a 4D Klein bottle? Yes, we can! The computation scales pretty intensely when you go from 3 → 4 dimensions, but for a small room (2x2x2x2 meters) this computation is still feasible on a free GPU instance.

Scaling Laws

We can grab a convenient equation for minimum grid size using the Courant Limit from Numerical Sound Synthesis. cΔtΔx1d given this, minimum cell length is Δx=cΔtd. If we want to render in the full range of human hearing, our max frequency would be about 20 kHz, so accounting for the Nyquist rate (we need at least 2 samples per cycle), Δx=cd2fmax=343·42·20,000=0.017 m. That means we have for a cubic room of length 2, we need 24m40.0174m4/cell=1.9×108 cells for 4D, given 40K updates per second, this will be on the order of 7.6×1012cell updates per second of sound simulation. This means we can render short sounds in a few minutes on a modern GPU! Given that I don't really want to deal with the tens of thousands of lines of raw C++ from the NESS project, I'll have Claude re-implement the bare bones FDTD algorithm in JAX, so we can run this in a Colab.

Implementation

So the high level plan here is that we have Claude borrow the FDTD algorithm & room dynamics from NESS & re-implement everything in JAX.

That brings us to the question: what do we want to simulate here? How do we turn these manifolds into instruments? Well one idea is to simulate the wave propagation if you were to model the manifold out of some material and strike it with a mallet or something like that. That seems reasonable enough, we'll start with that!

So now we need to simulate the propagation of a wave across this manifold, and we need some way to integrate this simulation with FDTD by modeling the barrier between the wave propagation of the manifold and the changes in pressure in the air. The NESS folks use FDTD to model some of their surfaces, but we're dealing with weird topologies here and FDTD needs a regular grid, which might be hard to map to our topologies. I think we might want to do some exploration with other manifolds, not just a Klein bottle, so let's see if we can simulate wave propagation over an arbitrary manifold. After a little bit of research with Claude, it looks like there is a way to create a mesh of the surface and integrate FEM with FDTD. Claude took it from there, and we got some pretty cool results!

Results

One detail to note here, I turned some of the constants down so that things were easier to compute, I turned dx to 0.03 and c_surf (the surface wave propagation speed) to 110. This modification results in lower frequencies than the sound I posted at the top, so you may want headphones for these.

Striking the Klein bottle sounds like this!

Klein bottle

I was hoping for something a bit more interesting, this sort of sounds like hitting a big gong. Comparing to the sphere and torus, the Klein bottle is a bit more wavey?

Torus
Sphere

I think some of the varieties in pitch can be due to the size of the object, not necessarily the topology. I could put in some more work here to solve for this but I think it's currently pretty clear that the difference between the manifolds is primarily the beating with the Klein Bottle, so I won't bother.

Validation

All of this was vibe coded with Claude Code (the new Colab MCP is really cool). I manually reviewed this, but admittedly I didn't dive into every detail of the mathematical implementation. So I figured it would be great to have some way to independently validate this simulation.

A surface's resonant frequencies are the eigenvalues μ of its Laplace–Beltrami operator (discretized here as the cotangent Laplacian on the mesh), via f=cμ/2π. If we solve that eigenvalue problem, we can independently check that the peaks of the radiated-audio spectrum land on those frequencies. I've plotted this below along with the mic pressure and spectrogram.

Validation plot: predicted Laplace–Beltrami eigenvalue frequencies overlaid on the radiated-audio spectrum, with mic pressure and spectrogram.

The eigenvalues look about right (given there is some absorption & interference from the simulated room), it is weird that the mic pressure drops off over time though. After doing a bit more research with Claude, it looks like the size of the room is causing the pressure drop, because of some of the absorption from the walls. I've tried this again on a much bigger room (which took 40min on an 80GB A100), and we got rid of the pressure drop off. The sound is basically the same though.

Klein bottle (bigger room)
Validation plot for the larger-room simulation, showing the pressure drop-off resolved.

Further Exploration

My Colab is available here klein_bottle_sound.ipynb this can run in about 10 minutes or so with a free T4 GPU instance! I've included a bunch of constants for physical parameters, so feel free to change a bunch of things and mess around with this to get some cool sounds! This is also way faster if you pay for an A100 instance (like 30s or so).

Overall, I was expecting this to sound super alien & weird, and I was a bit surprised when this sounded somewhat normal. While looking into the Laplace-Beltrami operator from the validation above, I stumbled across the paper Can One Hear the Shape of a Drum and the follow up paper No... gee wish I read that before starting this project, oh well!

To try and coax some more interesting sounds out of this setup, I changed the “strike” part of a simulation to a “bow”. What I mean by that is we simulate a violin bow interacting with part of the surface, in that it will self-oscillate into a continuous drone. I was hoping this would showcase the weird topology of the Klein bottle more.

Klein bottle
Torus
Sphere

The Klein Bottle definitely seems like it's beating more, and it's producing more of a grungy sound, super cool! I think with that, I'll say I'm relatively satisfied with this project now.

One more interesting thing that I noticed here was some of the effects around 4D wave propagation. I was messing around with some other damping coefficients, I wanted to see what it would sound like if it didn't ring quite as long. Looks like that's actually infeasible in 4D! Huygens' Principle states that the wavefront of a source of spherical wavelets cancel in such a way that you hear a sharp drop off in odd dimensional spaces. That's why you don't hear claps “ring” in 3D, but this isn't the case for 4D! I was almost tempted to extend this project to 5D to see what the Klein bottle would sound like there, but I've already sunk too much time into this, so I'll have to put that aside for now.

Robert Diersing