New "Modular" engine in a-immersive with three hot-swappable Faust sub-engines (subtractive/additive/fm) sharing a common modulation pool: 16 ADSR slots + 32 LFO slots (single-knob sine->tri->square->saw wavemorph) routed through a 48-source x 10-destination matrix per engine. Per-connection scalar amounts in [-1, 1], summed at each destination. Default MLP output count is 512 (32 mod-source params + 480 matrix cells); model reinits on sub-engine swap, count change, or engine-param exposure toggle. Faust layer: - mod-pool.lib: shared ADSR/LFO/source-bus library - gen-modular-dsp.py: byte-reproducible generator (source of truth) - modular-subtractive: faithful Minimoog (3 osc, ladder filter, no envs) - modular-additive: 64-partial, spectral shape + formants, no envs/LFOs - modular-fm: 4-op matrix + self-feedback, no envs - All three share d08=amp, d09=pan conventions - MODULAR_DESTINATIONS.md: authoritative destination table JS layer: - ModularEngine: self-contained SynthEngine with getState/setState, setSubEngine, setModSourceCount, setExposeEngineParam - modular-ui: drawer with sub-engine toggle, ADSR/LFO count steppers, per-slot enable switches, matrix grid editor (tap-cycle, long-press precise, right-click menu, negative amounts), preset overlay - modular-presets: 6 named presets (Slow pad, Plucky bass, Crystal, DX bell, Morphing drone + default) - a-app.js: Modular mode registered, paramMeta:change -> resizeMLP, modular DSP state persisted under modularDspState, window.__nisps debug hooks for programmatic control Tests: tests/e2e/modular-mode.spec.js (11 Playwright tests, all passing including DSP state survives reload, sub-engine swap keeps paramCount, preset apply verification). Also fixes a pre-existing build.sh bug where the -e flag caused faust to overwrite .wasm outputs with expanded DSP source text, leaving additive/fm-matrix/eoc-* committed as invalid WebAssembly. Rebuilt all affected engines with the corrected script. Added an early-message buffer to faust-worklet-processor.js so setParam calls arriving before wasm instantiation are queued rather than dropped (needed when the user configures modular state before clicking Start Audio).
1 line
No EOL
6.9 KiB
JSON
1 line
No EOL
6.9 KiB
JSON
{"name": "eoc-master","filename": "eoc-master.dsp","version": "2.79.3","compile_options": "-lang wasm -ct 1 -cn eoc_master -es 1 -mcd 16 -mdd 1024 -mdy 33 -single -ftz 0","library_list": ["/nix/store/yjqpc2a6b2m08zwwrgsdlqsi40m5wnpp-faust-2.79.3/share/faust/stdfaust.lib","/nix/store/yjqpc2a6b2m08zwwrgsdlqsi40m5wnpp-faust-2.79.3/share/faust/filters.lib","/nix/store/yjqpc2a6b2m08zwwrgsdlqsi40m5wnpp-faust-2.79.3/share/faust/maths.lib","/nix/store/yjqpc2a6b2m08zwwrgsdlqsi40m5wnpp-faust-2.79.3/share/faust/platform.lib","/nix/store/yjqpc2a6b2m08zwwrgsdlqsi40m5wnpp-faust-2.79.3/share/faust/basics.lib"],"include_pathnames": ["/nix/store/yjqpc2a6b2m08zwwrgsdlqsi40m5wnpp-faust-2.79.3/share/faust","/usr/local/share/faust","/usr/share/faust",".","/home/w1n5t0n/src/MEMLNaut-NISPS/playground/faust"],"size": 88,"code": "Ly8gZW9jLW1hc3Rlci5kc3Ag4oCUIE1hc3RlciBidXMgZWZmZWN0IGZvciB0aGUgRU9DIHJhY2suCi8vCi8vIFBhcmFtZXRlcnMgKDQpOgovLyAgIGdhaW4gICAgICAgICAgICBbMS4wLCAgMC0yXSAgICAgICAgb3V0cHV0IGdhaW4gbXVsdGlwbGllcgovLyAgIHdpZHRoICAgICAgICAgICBbMS4wLCAgMC0yXSAgICAgICAgc3RlcmVvIHdpZHRoOiAwPW1vbm8sIDE9bm9ybWFsLCAyPWV4dHJhLXdpZGUKLy8gICBsaW1pdGVyX3RocmVzaCAgWy0xLjAsIC0xMiB0byAwXSAgIGJyaWNrLXdhbGwgbGltaXRlciB0aHJlc2hvbGQgKGRCKQovLyAgIGRjX2Jsb2NrICAgICAgICBbMV0gICAgICAgICAgICAgICAgbmVudHJ5OiAwPW9mZiwgMT1vbiDigJQgREMgYmxvY2tpbmcgZmlsdGVyCgppbXBvcnQoInN0ZGZhdXN0LmxpYiIpOwoKLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCi8vIFVJCi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKZ2FpbiAgICAgICAgICAgPSBoc2xpZGVyKCJnYWluIiwgICAgICAgICAgICAgICAgICAxLjAsICAwLCAgICAyLCAgIDAuMDAxKTsKd2lkdGggICAgICAgICAgPSBoc2xpZGVyKCJ3aWR0aCIsICAgICAgICAgICAgICAgICAxLjAsICAwLCAgICAyLCAgIDAuMDAxKTsKbGltaXRlcl90aHJlc2ggPSBoc2xpZGVyKCJsaW1pdGVyX3RocmVzaFt1bml0OmRCXSIsIC0xLjAsIC0xMiwgMCwgMC4xKTsKZGNfYmxvY2tfb24gICAgPSBuZW50cnkoImRjX2Jsb2NrIiwgICAgICAgICAgICAgICAxLCAgICAwLCAgICAxLCAgIDEpOwoKLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCi8vIERDIGJsb2NraW5nIGZpbHRlciAofjEwSHogb25lLXBvbGUgSFApCi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKZGNCbG9jayhvbiwgeCkgPSBvbiAqIGZpLmhpZ2hwYXNzKDEsIDEwLjAsIHgpICsgKDEuMCAtIG9uKSAqIHg7CgovLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KLy8gU3RlcmVvIHdpZHRoIHZpYSBtaWQtc2lkZSBwcm9jZXNzaW5nCi8vICAgd2lkdGggPSAwOiBtb25vIChzaWRlIHJlbW92ZWQpCi8vICAgd2lkdGggPSAxOiBvcmlnaW5hbCBzdGVyZW8KLy8gICB3aWR0aCA9IDI6IGVuaGFuY2VkIHN0ZXJlbyAoZG91YmxlZCBzaWRlcykKLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpzdGVyZW9XaWR0aChpbkwsIGluUikgPSBvdXRMLCBvdXRSCndpdGggewogICAgdyAgICA9IHdpZHRoOwogICAgbWlkICA9IChpbkwgKyBpblIpICogMC41OwogICAgc2lkZSA9IChpbkwgLSBpblIpICogMC41OwogICAgb3V0TCA9IG1pZCArIHNpZGUgKiB3OwogICAgb3V0UiA9IG1pZCAtIHNpZGUgKiB3Owp9OwoKLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCi8vIEJyaWNrLXdhbGwgbGltaXRlcjogcGVhay1mb2xsb3dpbmcgZ2FpbiByZWR1Y3Rpb24uCi8vIFVzZXMgYSBsZWFreSBlbnZlbG9wZSBmb2xsb3dlciB3aXRoIGZhc3QgYXR0YWNrICh+MC41bXMpIGFuZCBzbG93IHJlbGVhc2UgKH4xMDBtcykuCi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKdGhyZXNoTGluID0gYmEuZGIybGluZWFyKGxpbWl0ZXJfdGhyZXNoKTsKCi8vIExlYWt5LXBlYWsgZW52ZWxvcGUgZm9sbG93ZXI6IGV4cG9uZW50aWFsIHJlbGVhc2UgfjEwMG1zCi8vIFRha2VzIGEgc2lnbmFsLCBvdXRwdXRzIGl0cyBwZWFrIGVudmVsb3BlCnJlbGVhc2VDb2VmZiA9IGV4cCgtMS4wIC8gKGZsb2F0KG1hLlNSKSAqIDAuMTAwKSk7CgpwZWFrRW52ID0gYWJzIDogKCsgfiAqKHJlbGVhc2VDb2VmZikpOwoKLy8gR2FpbiByZWR1Y3Rpb246IGNsYW1wIHRvIHRocmVzaG9sZApsaW1pdGVyR1IoZW52KSA9IHRocmVzaExpbiAvIG1heCh0aHJlc2hMaW4sIGVudik7CgovLyBTdGVyZW8gbGltaXRlcjogbGlua2VkIEwvUiBnYWluIHJlZHVjdGlvbiBmcm9tIG1heCBvZiBib3RoIHBlYWtzCmxpbWl0ZXIoaW5MLCBpblIpID0gaW5MICogZ3IsIGluUiAqIGdyCndpdGggewogICAgZW52TCA9IHBlYWtFbnYoaW5MKTsKICAgIGVudlIgPSBwZWFrRW52KGluUik7CiAgICBwZWFrU3RlcmVvID0gbWF4KGVudkwsIGVudlIpOwogICAgZ3IgPSBsaW1pdGVyR1IocGVha1N0ZXJlbyk7Cn07CgovLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KLy8gTWFpbiBwcm9jZXNzCi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKcHJvY2VzcyhpbkwsIGluUikgPSBvdXRMLCBvdXRSCndpdGggewogICAgLy8gMS4gREMgYmxvY2sKICAgIGRjTCA9IGRjQmxvY2soZGNfYmxvY2tfb24sIGluTCk7CiAgICBkY1IgPSBkY0Jsb2NrKGRjX2Jsb2NrX29uLCBpblIpOwogICAgLy8gMi4gR2FpbgogICAgZ0wgPSBkY0wgKiBnYWluOwogICAgZ1IgPSBkY1IgKiBnYWluOwogICAgLy8gMy4gU3RlcmVvIHdpZHRoCiAgICB3TCA9IHN0ZXJlb1dpZHRoKGdMLCBnUikgOiBfLCE7CiAgICB3UiA9IHN0ZXJlb1dpZHRoKGdMLCBnUikgOiAhLF87CiAgICAvLyA0LiBMaW1pdGVyCiAgICBvdXRMID0gbGltaXRlcih3TCwgd1IpIDogXywhOwogICAgb3V0UiA9IGxpbWl0ZXIod0wsIHdSKSA6ICEsXzsKfTsK","inputs": 2,"outputs": 2,"meta": [ { "basics.lib/name": "Faust Basic Element Library" },{ "basics.lib/version": "1.21.0" },{ "compile_options": "-lang wasm -ct 1 -cn eoc_master -es 1 -mcd 16 -mdd 1024 -mdy 33 -single -ftz 0" },{ "filename": "eoc-master.dsp" },{ "filters.lib/highpass:author": "Julius O. Smith III" },{ "filters.lib/highpass:copyright": "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>" },{ "filters.lib/lowpass0_highpass1": "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>" },{ "filters.lib/lowpass0_highpass1:author": "Julius O. Smith III" },{ "filters.lib/name": "Faust Filters Library" },{ "filters.lib/tf1:author": "Julius O. Smith III" },{ "filters.lib/tf1:copyright": "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>" },{ "filters.lib/tf1:license": "MIT-style STK-4.3 license" },{ "filters.lib/tf1s:author": "Julius O. Smith III" },{ "filters.lib/tf1s:copyright": "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>" },{ "filters.lib/tf1s:license": "MIT-style STK-4.3 license" },{ "filters.lib/version": "1.7.1" },{ "maths.lib/author": "GRAME" },{ "maths.lib/copyright": "GRAME" },{ "maths.lib/license": "LGPL with exception" },{ "maths.lib/name": "Faust Math Library" },{ "maths.lib/version": "2.8.1" },{ "name": "eoc-master" },{ "platform.lib/name": "Generic Platform Library" },{ "platform.lib/version": "1.3.0" }],"ui": [ {"type": "vgroup","label": "eoc-master","items": [ {"type": "nentry","label": "dc_block","varname": "fEntry0","shortname": "dc_block","address": "/eoc-master/dc_block","index": 40,"init": 1,"min": 0,"max": 1,"step": 1},{"type": "hslider","label": "gain","varname": "fHslider2","shortname": "gain","address": "/eoc-master/gain","index": 64,"init": 1,"min": 0,"max": 2,"step": 0.001},{"type": "hslider","label": "limiter_thresh","varname": "fHslider0","shortname": "limiter_thresh","address": "/eoc-master/limiter_thresh","index": 0,"meta": [{ "unit": "dB" }],"init": -1,"min": -12,"max": 0,"step": 0.1},{"type": "hslider","label": "width","varname": "fHslider1","shortname": "width","address": "/eoc-master/width","index": 60,"init": 1,"min": 0,"max": 2,"step": 0.001}]}]} |