Simulating Acoustic Resonance: Generative Chladni Figures in Python
2026/9/4
Generative art often draws inspiration from the hidden mathematical patterns of the physical world. One of the most mesmerizing physical phenomena is cymatics—specifically, Chladni figures. When a metal or wooden plate is covered in fine sand and bowed with a violin bow, the sand violently dances away from the vibrating areas and settles into the "nodal lines" where the plate is perfectly still, revealing stunning geometric mandalas of sound.In my latest generative sketch, I set out to simulate this exact phenomenon. Instead of a physical plate, the sketch uses a digital canvas where 150,000 glowing sand particles are subjected to a mathematical standing wave. As the simulated acoustic frequency slowly shifts, the intricate geometric patterns dissolve into chaotic noise before seamlessly reforming into new, higher-order symmetric mandalas.Python and the py5 library provided the ideal ecosystem for this simulation. Rendering 150,000 independent particles at 60 frames per second requires efficient math processing, which Python's NumPy library handles effortlessly. Meanwhile, py5's elegant drawing API and blending modes allow the particles to emit a soft, realistic glow as they sweep across the canvas.
Visual & Aesthetic Approach
The core of the simulation relies on a mathematical representation of a 2D standing wave. The wave equation determines the amplitude of vibration at any point on the canvas. To simulate the physical behavior of sand, the particles are accelerated along the negative gradient of the wave's squared amplitude—meaning they are pushed away from the violently vibrating "antinodes" and dragged toward the perfectly still "nodes."To capture the physical, tangible feel of the original acoustic experiments, I chose an "Elegant Contrast" color palette. The background is a warm, dark mahogany, evoking the wooden soundboards of classical instruments. Against this dark void, the particles are rendered in bright, glowing golden-white, creating a stark, beautiful contrast that highlights the intricate webbing of the resonance patterns. A subtle motion blur is applied each frame to give the shifting sand a fluid, organic quality.Code & Technical Breakdown
The heavy lifting of the physics simulation is handled by the chladni_val_and_grad function. Rather than just calculating the height of the wave, we need the derivative (the slope) to know which way the sand should slide.def chladni_val_and_grad(x, y, n, m, a=1.0, b=1.0):
# Map coordinates to [-pi, pi] based on screen size
scale = np.pi / min(SIZE) * 2.0
sx = (x - SIZE[0]/2) * scale
sy = (y - SIZE[1]/2) * scale
# ... trigonometric calculations ...
L = a * snx * smy + b * smx * sny
dL_dx = (a * n * cnx * smy + b * m * cmx * sny) * scale
dL_dy = (a * m * snx * cmy + b * n * smx * cny) * scale
fx = -2.0 * L * dL_dx
fy = -2.0 * L * dL_dy
return fx, fyThe equation L defines the classic Chladni standing wave pattern, blending sine and cosine waves defined by the harmonic frequencies n and m. By calculating the partial derivatives dL_dx and dL_dy, we generate the force vectors fx and fy. These vectors effectively act as gravity, pulling particles down the slope of the vibration toward the nodal lines where L = 0.Inside the main draw() loop, these forces are applied to our massive particle arrays:
# Smoothly transition parameters
t = py5.frame_count * 0.005
n = 2.0 + np.sin(t * 1.3) * 1.5
m = 3.0 + np.cos(t * 0.9) * 2.0
fx, fy = chladni_val_and_grad(px, py, n, m)
# Accelerate
force_mult = 50.0
vx += fx * force_mult + nx * noise_str
vy += fy * force_mult + ny * noise_str
# Drag
vx *= 0.90
vy *= 0.90
px += vx
py += vyWe continuously modulate the harmonic frequencies n and m using sine waves. This causes the standing wave to slowly morph. A touch of Perlin noise (nx, ny) is added to the forces to simulate the chaotic bouncing of sand grains and prevent particles from getting perfectly stuck. A strong drag factor (`0.90`) acts as friction, ensuring the particles settle quickly into the new patterns as the frequencies shift.
