/ simulated_instruments / cymbal2
Sign in
simulated_instruments / cymbal2
cymbal2 / webapp / README.md
32 lines · 4.8 KBPreviewCodeBlameHistoryRaw
1# Cymbal2 Simulator — web app
3Interactive browser implementation of the physical model described in `../README.md`. The algorithm itself is written in MATLAB syntax, in `../matlab/*.m`, and executed client-side by [numbl](https://numbl.org) inside a Web Worker; the TypeScript here is only the UI, the plots, the WAV encoder, and the marshalling of parameters and tensors in and out of the numbl runtime.
5The signal chain: a prescribed hand stroke drives an Euler-Bernoulli stick with a Hertz-contact mallet head against a von Karman shallow spherical shell on a washer support, integrated step by step in the time domain; the output is the shell's normal acceleration at a pickup point, decimated and normalized.
7## Usage
9```
10npm install
11npm run dev # development server
12npm run build # production build in dist/
13npm run selftest # run ../matlab/cymbal2_validate.m through numbl in Node
14```
16The self-test runs the closed-form and reproducibility checks and the pinned diagnostics; the two full renders inside it make it take a few minutes. The MATLAB code can also be run directly: `cd ../matlab && numbl run cymbal2_demo.m` (or `cymbal2_validate.m`), and runs unchanged in MATLAB proper, where it is several times faster.
18## Where the time goes
20Everywhere. Unlike the sibling `cymbal` app, whose expensive stage (the eigensolves) could be cached and whose synthesis was an oscillator bank, here the sound is a nonlinear time-domain integration of the whole shell, several hundred thousand steps of coupled solves, and every parameter feeds it. There is therefore no debounced auto-render: the Render preview button runs a cheap pass (no oversampling, tail clamped to 1.5 s; the azimuthal grid is kept, because hard strokes diverge without the full wavenumber ladder), Render full runs the real thing, and both report elapsed time and can be cancelled. The only piece the worker caches is the cheap linear mode table that the spectrum plot overlays.
22When the browser exposes WebGPU, the time loop runs on the GPU instead of through the interpreter: the worker still executes the unmodified setup stage (grid, per-wavenumber inverses, mallet, stroke schedule) and output stage through numbl, but hands the operators to a WGSL port of `cymbal2_sim.m` (`src/worker/gpuSim.ts`, eight compute dispatches per time step; the design and its measurements are documented in the [cymbal2-webgpu](https://vault1.magland.org/proof-of-concept/cymbal2-webgpu) exploration). This is 20x or more faster than interpreting the loop, even on an integrated GPU, and the diagnostics panel says which path a render took. The GPU integrates in single precision; the contact diagnostics match the double-precision interpreter to a fraction of a percent, and the trajectory of a crash is chaotic either way. Without WebGPU the interpreter path runs as before, and expect tens of seconds for a preview and many minutes for a full render. One interaction with the code editor: the WGSL mirrors the shipped `cymbal2_sim.m`, so editing that one file falls back to the interpreter, where the edit is live (a warning in the diagnostics says so); edits to every other `.m` file flow through numbl on both paths. `npm i --no-save webgpu && npx tsx scripts/gpu-selftest.ts` runs the GPU loop from Node on desktop WebGPU and checks the pinned diagnostics.
24## Presets
26The Preset selector at the top of the parameter panel replaces the whole parameter set with a named configuration; picking one and then adjusting shows "custom". "Paper demo" is the stroke fitted against the demonstration recording published by the paper's authors (the repository's `cymbal2-paper-demo.wav`); the others span the stroke range from a near-linear tap to the hard-crash ceiling, a roll, the rigid clamp of the earlier literature, two mallets, and two other shells. Every preset is checked to integrate stably at the preview tier, which is the binding case; the notes under the selector say where each one's headroom runs out.
28## Reading and editing the code in the app
30The Code button opens the MATLAB source in a CodeMirror editor with MATLAB syntax highlighting. Every `.m` file in `../matlab` is listed, tagged by whether the app executes it or it is a CLI entry point. The sources are editable and an edit takes effect on the next render, so the physics can be changed in place: setting the curvature term `Rs` large in `cymbal2_system.m` flattens the shell into a plate, and zeroing the `Luu` term in `cymbal2_sim.m` removes the stretching nonlinearity, leaving a linear shell that never crashes however hard it is hit.
32Edits live in memory only. They are deliberately not persisted, so a reload restores the code the app shipped with; "Revert file" and "Revert all" undo them sooner, and a dot marks the files that differ from the shipped source. A fault in edited code is reported with its file and line, the last successful render stays on screen, and reverting recovers.
↑↓ move↵openescclose