Jeremy Magland Bead drum: hex-lattice round head, felt mallet contact, top view and cross-section; shared instrument page
| .github | |
| src | |
| test | |
| .gitignore | |
| index.html | |
| package-lock.json | |
| package.json | |
| README.md | |
| tsconfig.json | |
| vite.config.ts |
toy-instruments#
Live: https://magland.github.io/toy-instruments/ (deployed from main by .github/workflows/pages.yml).
A browser gallery of toy physical-model instruments. Pick an instrument, set its geometry, properties and excitation, run the simulation, and get the pickup waveform, a spectrogram, a playable/downloadable .wav, and the bead displacements over time. Static site (Vite + TypeScript); the solver runs in a Web Worker.
npm install
npm run dev # http://localhost:5173
npm test # vitest
npm run build # static site in dist/
String of beads (first instrument)#
npoint masses on springs with stiffnessk, spacingLat equilibrium, pre-tensionT(rest lengthL0 = L - T/k). Beads move in 3D and the springs are real (exact length), so geometric nonlinearity is kept: pitch glide at large amplitude, transverse-longitudinal coupling, whirling.- Ends: clamped (fixed point), sliding (massless ring on a rod: x fixed, free across, holds tension), or free (no support; only consistent with
T = 0). Any bead can be pinned. - Excitation: pluck (triangle between the nearest supports, released at rest), strike (Gaussian initial velocity), hammer (raised-cosine force pulse). Direction is an angle in the y-z plane.
- Damping from two decay times:
sigma(omega) = sigma0 + sigma1 omega^2, fitted to T60 at two frequencies for transverse modes.sigma0is mass-proportional;sigma1is a dashpot on each spring's relative velocity. - Audio: pickup acceleration (forces / mass, at the full-step velocity), from one bead or summed over all beads, along y, z or x. The
.wavis normalized to -1 dBFS. - Solver: velocity Verlet (explicit, symplectic without damping).
dt = cfl * 2 / omega_max(Gershgorin bound with axialkand transverseT/l), rounded down to a whole number of steps per audio sample. - 3D model view (three.js): Setup shows the beads at rest with supports (wall = clamped, translucent plane + ring = sliding), pinned beads (cubes), excitation (pluck shape, strike velocity arrows, hammer force arrows) and pickup (bead + axis arrow). Replay animates the saved frames ("Replay frames" per second, default 2000) with adjustable exaggeration, on a timeline shared with the 2D side/top views and space-time image.
- Checks shown per run: energy balance (energy + dissipated - work in - initial) relative to peak energy, largest strain. Linear transverse and longitudinal modes (Sturm bisection on the tridiagonal stiffness) are marked on the spectrum.
String tests (test/string.test.ts): modes vs the discrete-string formula; small mode-1 motion vs cos(omega_1 t); energy balance with and without damping/forcing; decay at the requested T60.
Bead drum#
- Round head: beads on a triangular (hex) lattice in the x-z plane, cut to a circle; every missing neighbour of an edge bead is a fixed rim point. Vibration along y.
- Inputs are continuum values: diameter, rings (spacing a = R / (rings + 1)), surface density, tension tau (N/m), in-plane stiffness E t (N/m). Lattice: spring tension f = tau a / sqrt(3), stiffness k = sqrt(3) E t / 2 (Poisson ratio 1/3), bead mass = density * sqrt(3)/2 a^2.
- Excitation: felt mallet (point mass, contact force K delta^p on a Gaussian patch, integrated with the beads; contact time and rebounds come out of the simulation), strike, force pulse, press (initial dent).
- Damping as for the string (dashpots calibrated to the springs' transverse stiffness f / a).
- Extra views: top-down displacement map and cross-section along the diameter through the strike point; mallet contact force.
- Presets: a fast tom with in-plane stiffness softened ~70x (about 8x slower than real time for 571 beads in Chromium) and a realistic Mylar one (~6x more steps).
- Tests (
test/drum.test.ts): every bead has six springs; a small centre press rings within 1.3% of the ideal membrane fundamental 2.405 c / (2 pi R); the mallet bounces off and energy balances.
Layout#
src/sim/generic 3D bead-spring system, solver, worker.src/instruments/<id>/model (parameters to system), presets, page. Register new instruments insrc/instruments/registry.ts.src/ui/instrumentPage.tsthe shared page (controls, 3D model, setup, run, audio, plots); an instrument supplies setup rows and extra cards.src/ui/reusable controls form, line plot, spectrogram, chain displacement viewer, 3D scene, shared playback timeline, FFT, WAV.