4ddcc1bCymbal simulator: shell-of-revolution modal model with a nonlinear energy cascade, numbl MATLAB reference, and interactive web appJeremy Magland 1// The MATLAB implementation, loaded from ../matlab at build time. The app
2// keeps an editable in-memory copy of these sources (see App.tsx); edits feed
3// straight into the render worker and are deliberately not persisted, so a
4// reload restores the shipped code.
6export interface MFile {
7 name: string;
8 source: string;
9}
11const modules = import.meta.glob('../../matlab/*.m', {
12 eager: true,
13 query: '?raw',
14 import: 'default',
15}) as Record<string, string>;
17export const DEFAULT_MFILES: MFile[] = Object.entries(modules)
18 .map(([path, source]) => ({ name: path.split('/').pop()!, source }))
19 .sort((a, b) => a.name.localeCompare(b.name));
21// Files the app itself executes. The others are entry points for running the
22// model from the numbl CLI, and editing them changes nothing in the browser.
23export const EXECUTED_BY_APP = new Set([
24 'cymbal_profile.m',
25 'cymbal_shell.m',
26 'cymbal_basis.m',
27 'cymbal_at.m',
28 'cymbal_point.m',
29 'cymbal_strikes.m',
30 'cymbal_rng.m',
7da0671Hammer the cymbal: hybridize near-degenerate modes, add the turbulent fluctuation about the mean cascade, and flatten the decay across the bandJeremy Magland 31 'cymbal_rngv.m',
4ddcc1bCymbal simulator: shell-of-revolution modal model with a nonlinear energy cascade, numbl MATLAB reference, and interactive web appJeremy Magland 32 'cymbal_cascade.m',
33 'cymbal_radiate.m',
34 'cymbal_output.m',
35]);
37// Cheap content hash (FNV-1a) so the worker can key its caches on the code.
38export function hashMFiles(files: MFile[]): string {
39 let h = 0x811c9dc5;
40 for (const f of files) {
41 const s = f.name + ' ' + f.source + '';
42 for (let i = 0; i < s.length; i++) {
43 h ^= s.charCodeAt(i);
44 h = Math.imul(h, 0x01000193);
45 }
46 }
47 return (h >>> 0).toString(36);
48}