/ simulated_instruments / maraca
Sign in
simulated_instruments / maraca
maraca / webapp / README.md
45 lines · 4.9 KBPreviewCodeBlameHistoryRaw
1# Maraca 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 seeded stochastic process of grain-shell impacts, Hertz contacts driving the spherical-harmonic modes of a closed shell, exact sphere multipole radiation to the listener point, and Kaiser-windowed anti-aliased decimation to 48 kHz.
7## Usage
9```
10npm install
11npm run dev # development server
12npm run build # production build in dist/
13npm run selftest # run ../matlab/maraca_validate.m through numbl in Node
14```
16The self-test runs the closed-form and reproducibility checks and the pinned diagnostics. The MATLAB code can also be run directly: `cd ../matlab && numbl run maraca_demo.m` (or `maraca_validate.m`).
18## Why it renders fast
20Nothing is integrated. Between impacts every mode is a damped exponential, so the synthesis evaluates `exp(lambda t)` over each inter-impact segment in closed form and adds each impact's velocity jump as it lands. A few thousand impacts across a dozen modes is a few thousand short matrix products, which is why a two-second pattern renders in a fraction of a second rather than needing an ODE solver over 200 000 samples. The cost that remains is the oversampled time axis, and `oversample` trades it against alias rejection in the decimation.
22## Reading and editing the code in the app
24The 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: an edit takes effect on the next render, so changing the physics in the editor is heard and plotted the same way moving a slider is. Changing the Rayleigh speed distribution in `maraca_impacts.m` to a constant, for instance, makes the shake sound immediately mechanical.
26Edits 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 (numbl skips a file it cannot parse and then fails at the call site, so the worker captures the parse warning and reports that instead), the failed render leaves nothing playable, so Play and Download go dead until a render succeeds, and reverting recovers.
28## How rendering is tiered
30Nothing renders on its own: the Render preview button runs a fast pass (oversample 1), Render full runs the full-quality pass, and either can be cancelled while it runs. The status shows the stage, a progress bar and the elapsed time. While the current result is a preview, the Play and Download buttons and the status badge say so. The worker runs each stage as a separate numbl execution and keys its caches by tier: shell, grain, and gesture parameters invalidate the mode basis and the impact process; the listener position and the direct-click gain only re-run radiation; pre-delay, normalization, and bit depth only re-run the output stage. Intermediate tensors stay inside the worker as numbl RuntimeValues. Moving the microphone after a full render reuses the cached impact process and returns a full-quality result.
32The New seed button redraws the whole impact process without touching any other parameter, which is the quickest way to hear how much of a shake's character is the particular draw and how much is the physics. The Loop button repeats the last render continuously, swapping in each new render as it completes. Parameters persist in localStorage; "Reset to defaults" restores the values in `src/params.ts` (which `../matlab/maraca_defaults.m` mirrors).
34## Layout
36- `../matlab/` — the algorithm: `maraca_basis.m`, `maraca_impacts.m`, `maraca_radiate.m`, `maraca_output.m`, `maraca_hankel.m`, `maraca_rng.m`, plus `maraca_render.m` / `maraca_demo.m` / `maraca_validate.m` for CLI use
37- `src/params.ts` — parameter schema, defaults, tier assignment, persistence
38- `src/mfiles.ts` — the `.m` sources, bundled at build time and hashed for cache keying
39- `src/worker/renderWorker.ts` — off-thread numbl execution with tiered caching
40- `src/components/` — 3D scene (three.js), parameter panel, code panel and editor, plots (impact raster, waveform, spectrum, spectrogram, shell mode map)
41- `src/selftest.ts` — Node harness for the MATLAB validation script
43## A note on the seeded generator
45The impact process draws from a 32-bit LCG in `maraca_rng.m` rather than MATLAB's `rand`, so a given seed produces the identical process in the numbl CLI, in Node, and in the browser. That is what lets the self-test pin exact impact counts and momentum sums.
↑↓ move↵openescclose