fix(a-app): gate modular MLP routing on example count to preserve default patch

Modular mode's default patch sets MM_Matrix/s00_d08_amp = 1.0 via
_setRawByLabel at engine init, but on the first inference tick
routeOutputs writes the untrained MLP's output (~0.5 normalised) to
every paramMeta index. For matrix cells the raw range is [-1, 1], so
normalised 0.5 denormalises to 0 — clobbering the default amp routing
and killing all audio.

Skip the setParam loop for modular when iml.exampleCount === 0, so the
worklet keeps running on the default patch we already pushed at init.
Once the user captures at least one training example the MLP has a
target to reproduce, and routing resumes normally.

Only affects modular mode; other engines are unchanged.
This commit is contained in:
monkey-w1n5t0n 2026-04-11 08:20:24 +02:00
parent e6938ebb8b
commit 70c858016f

View file

@ -2398,8 +2398,16 @@ function routeOutputs(outputs) {
modularUI.updateLive(overridden); modularUI.updateLive(overridden);
} }
// Modular mode cold-start gate: with no training examples, an untrained
// MLP produces outputs around 0.5 which denormalise to ~0 for matrix
// cells (min=-1, max=1) and clobber the default patch's s00_d08_amp=1.0.
// Result: silence. Until the user captures at least one example, leave
// the worklet running on the default patch we already pushed at init.
const skipModularRouting = activeEngine?.id === 'modular' &&
(iml?.exampleCount ?? 0) === 0;
// Engine param updates: throttle + dead-zone filter // Engine param updates: throttle + dead-zone filter
if (activeEngine && activeEngine.running) { if (activeEngine && activeEngine.running && !skipModularRouting) {
const now = performance.now(); const now = performance.now();
if (now - _lastParamSendTime >= PARAM_SEND_INTERVAL) { if (now - _lastParamSendTime >= PARAM_SEND_INTERVAL) {
_lastParamSendTime = now; _lastParamSendTime = now;