how it works
How Eigendrum turns a shape into a sound
Every frequency you hear is computed from the outline you drew. Nothing is sampled and no overtone is faked. Here is the whole chain, from a closed curve to a decaying sum of sinusoids.
A drumhead clamped at its rim cannot vibrate in just any shape. It can only vibrate in a specific, discrete set of standing waves, each with its own frequency, and both the shapes and the frequencies are decided entirely by the outline. They are the solutions of
−∇²u = λu inside the region, u = 0 on the boundary
which is the Dirichlet eigenvalue problem for the Laplacian. Each solution u is a mode: a fixed pattern of hills and valleys that the membrane can hold. Each eigenvalue λ gives that mode's frequency, proportional to √λ. The u = 0 condition is the clamp - the rim is glued down and cannot move.
For a handful of shapes this can be solved with pencil and paper. For everything else, including anything you draw by hand, it cannot. So Eigendrum solves it numerically, in four steps.
1. Mesh the region
The outline is filled with a lattice of right-isosceles triangles. Triangles whose centroid falls inside the shape are kept, the resulting jagged boundary is projected onto the true outline, and then the mesh is repaired: boundary nodes slide along the curve to even out their spacing, the degenerate splinters that snapping leaves behind are dropped, and the interior is smoothed.
There is deliberately no Delaunay triangulation here. A lattice has a property Delaunay does not: it can represent particular directions exactly. The mesher splits every lattice cell into four triangles around its centre - a union-jack - rather than along a single diagonal. A single diagonal silently staircases the other 45-degree direction, and that mattered enormously: it made two shapes that should be indistinguishable differ by 0.13%. With both diagonals represented exactly, they agree to every digit.
2. Assemble the matrices
Each triangle contributes to two matrices. The stiffness matrix K encodes how much energy it costs to bend the membrane; the mass matrix M encodes how much inertia there is to move. Eigendrum uses P1 elements, meaning the displacement is assumed to vary linearly across each triangle, which makes both matrices computable in closed form per element.
The clamped rim is imposed by simply never assembling rows for boundary nodes. There is no penalty term and no constraint equation - the boundary degrees of freedom just do not exist, which is both the cheapest and the most exact way to say "this cannot move".
3. Solve for the lowest eigenvalues
What is wanted is the smallest sixteen eigenvalues of Kφ = λMφ. That "smallest" is the awkward part. The standard workhorse for large sparse eigenproblems, Lanczos iteration, naturally converges to the largest eigenvalues. So Eigendrum uses block inverse iteration with a Rayleigh-Ritz projection, which converges to the bottom of the spectrum instead.
Inverse iteration needs to solve K y = b a few hundred times. Doing that iteratively would be painful, because the stiffness matrix has a condition number around 1/h², so a conjugate gradient solve would need hundreds of iterations of its own. Instead K is reordered with reverse Cuthill-McKee to pull its non-zeros close to the diagonal, then factorised once with a banded Cholesky. After that, every solve is two triangular sweeps. A 2000-unknown drum finishes in roughly 700 ms in a browser worker.
4. Turn eigenvectors into sound
Frequencies come straight from √λ. Amplitudes are harder, and this is the step that is easy to get wrong - it was wrong here for a while, and the result sounded like a gong rather than a drum. Three factors apply between the geometry and the loudspeaker, and only the last is a modelling choice.
Mass normalisation
The projection ∫φ g of the mallet onto a mode is that mode's coefficient only if the modes are orthonormal in the mass inner product. The solver normalises them to unit peak instead, because the colour map needs a predictable range. So the projection has to be divided by ∫φ², which varies by a factor of about two across the first sixteen modes of a disk, and by up to 3.6× on some shapes. Skip it and modes are mis-weighted essentially at random.
The 1/ω rolloff
A mallet delivers an impulse of force. Force sets initial velocity, not initial displacement. Solving u(0) = 0, u′(0) = a gives u(t) = (a/ω) sin ωt - so displacement carries a 6 dB/octave rolloff that the raw projection knows nothing about.
Contact time
No real beater is instantaneous. A force pulse lasting T cannot pump a mode whose period is far shorter than T, which is modelled here as a one-pole rolloff. It is fixed at a ratio of the fundamental rather than at an absolute frequency, so the timbre does not drift when you move the pitch slider.
Decay is Rayleigh damping, C = αM + βK, which in modal coordinates reads 1/τ = α + βω². Loss rising with the square of frequency is the physical case, and it is why a drum's high inharmonic partials vanish in tens of milliseconds while the fundamental rings on. That fast darkening is most of what makes a drum read as a pitched thud rather than a chord.
Why striking a nodal line is silent
Hitting a spot drives each mode in proportion to how much that mode moves at that point. A nodal line is a curve where a mode does not move at all, so a mallet landing there cannot pump that mode, and it is simply absent from the sound.
None of that was programmed in. It falls out of the projection, and it is covered by a test: strike a circle dead centre and the radially symmetric fundamental is driven hard, while the next two modes stay essentially silent, because each has a nodal diameter running straight through the centre.
Why you can trust the numbers
A few shapes do have spectra that can be written down exactly, and the solver is checked against them on every change. Worst relative error over the lowest eight modes:
| shape | 1200 nodes | 2600 | 6000 |
|---|---|---|---|
| unit square | 0.846% | 0.375% | 0.160% |
| rectangle 1.5 × 0.8 | 1.141% | 0.548% | 0.233% |
| right isosceles triangle | 1.103% | 0.519% | 0.227% |
| unit disk | 0.946% | 0.437% | 0.192% |
The errors fall in the ratio 1 : 0.47 : 0.21 against predicted h² ratios of 1 : 0.471 : 0.207. That is clean second-order convergence, which is exactly what P1 elements should give.
Two further checks are worth naming. First, every error is positive. A conforming finite element method minimises the Rayleigh quotient over a restricted subspace of the true space, so it can never undershoot the exact eigenvalue. An answer below the true one would mean a bug, not a coarse mesh, and the test suite asserts it never happens. Second, a circle's overtones come out as ratios of Bessel function zeros - not because anyone typed Bessel zeros in, but because that is what a circular drum does.
What the shape decides, and what it does not
Being clear about this is the point of the whole project.
- Fixed by the outline, not adjustable. The frequency ratios. The mode shapes. Which modes a given strike position can excite.
- Not fixed by the outline, so exposed as sliders. Absolute pitch, which is size and tension. How fast each overtone fades, which is material and air. Outlines are scaled to equal area before solving, so what you hear is shape and not size.
- Modelled, and neither of the above. The mallet - its width is a slider, its contact time is fixed. Both change how much of each mode a strike reaches; neither can move a mode's frequency.