diff --git a/web/routes/uix/docs/sound/+page.svelte b/web/routes/uix/docs/sound/+page.svelte index 821346459..a34c8cfd9 100644 --- a/web/routes/uix/docs/sound/+page.svelte +++ b/web/routes/uix/docs/sound/+page.svelte @@ -85,15 +85,35 @@ const AXES = ['gain', 'pitch', 'contour', 'centroid', 'roughness', 'duration'] as const; - function play(name: string) { + /** + * Emit the CHOSEN name. The signal carries it as a per-event override, which + * the resolver applies at layer 1.5 — the same slot a component's pack rule + * lands in — so what you hear is exactly what the table above computes. + * + * It used to emit without the name at all: the engine then resolved against + * the registered packs, none of which match this page's bare stage element, + * so EVERY chip played the family base. Sixteen buttons, one sound. The page + * was measuring one thing and playing another. + */ + function play(name: string, withIntent = true) { if (!stage) return; void uix.events?.emit({ name: 'probe', family: family as never, target: stage, - ...(intent !== 'neutral' ? { intent: intent as never } : {}) + overrides: { sound: name as SoundName }, + ...(withIntent && intent !== 'neutral' ? { intent: intent as never } : {}) }); - void name; + } + + /** Play the three layers in sequence, so the arithmetic becomes audible. */ + async function playLayers() { + if (!stage) return; + void uix.events?.emit({ name: 'probe', family: family as never, target: stage }); + await new Promise((r) => setTimeout(r, 520)); + play(sound, false); + await new Promise((r) => setTimeout(r, 520)); + play(sound, true); } function playName(name: string) {