diff --git a/docs/superpowers/specs/2026-06-28-matrix-instrument-editor-design.md b/docs/superpowers/specs/2026-06-28-matrix-instrument-editor-design.md new file mode 100644 index 0000000..390f54f --- /dev/null +++ b/docs/superpowers/specs/2026-06-28-matrix-instrument-editor-design.md @@ -0,0 +1,154 @@ +# Matrix complete per-instrument editor — design + +Date: 2026-06-28 +Status: approved (brainstorming), pending implementation plan +Scope: `sound_algo/data_only/matrix.scd` + `web_realart/public/control/` +Builds on: instrument selection, capture→effect, and the color editor +(`2026-06-28-matrix-instrument-selection.md`, `-capture-effect-design.md`, +`-color-editor-design.md`) — all already implemented on main. + +## Goal + +Clicking a matrix voice opens ONE complete editor modal for that instrument, +consolidating every per-instrument control (today scattered across the row) and +adding two new capabilities: a per-color 16-step note+velocity sequencer that +replaces the voice's base pattern, and a panel to bind recognized poses to +instrument actions. + +## Decisions (from brainstorming) + +- ONE modal per instrument (not three subsystems), opened by clicking the voice. + It has tabs: **Instrument · Colors · Sequence · Assignments · Poses**. +- Consolidation: the per-row sticky instrument `` (+ a small "default" + the kit context). + - *Colors*: the existing 6-color variation/sound editor (port from the color modal). + - *Sequence*: a 6 x 16 grid (rows = colors 1-6, columns = 16 steps); each cell + toggles a step and exposes degree (a small numeric/stepper) + velocity (a slider + or click-height). Empty row = "base pattern" indicator. + - *Assignments*: the source/target/depth mod controls (port from the row). + - *Poses*: a small list — bind a poseId (text/select) to an action + (trigger color N / gate) — "plug a pose in". + - An AUDITION toggle (existing) cycles the 6 colors. +- **State:** the modal reads a single `matInstEdit[vi]` object hydrated from + `/matrix/instedit`; control changes send the granular OSC messages above and update + local state. Persisted in the matrix localStorage. + +## Persistence + +The `.matrix` Event already carries `grid, instruments, mods, colorDefs`. Extend: +- `colorDefs[vi][color]` gains `steps` (16 x (degree,vel)|rest) — already nested in + the colorDef Event, so it round-trips via the existing colorDefs serialization. +- add `poseBindings` (16 x list of (poseId, action, color)). +Backward-compat: files without `steps`/`poseBindings` load with empty sequences +(→ base fallback) and no pose bindings. Web localStorage gains the same under `cdef` ++ a new `pose` key, tolerant of prior shapes. + +## Error handling / robustness + +- `~matSetStep`/`~matSetPoseBind`/`~matSetColorDef` validate ranges and ignore bad + input (consistent with the existing setters). +- Empty sequence → base Pdef (never silent unless the base is). A sequence with all + rests is treated as empty (base fallback) to avoid an accidentally-muted voice. +- `/matrix/pose` with an unknown poseId → no binding matches → no-op. +- nil-guarded, idempotent reload; defaults reproduce current behavior. + +## Testing + +- **SC** (`data_only/test/test_matrix.scd`, headless, P:0 B:0): + - `steps` defaults empty; `~matStepsEmpty` true; `~matVariation` with empty steps + still yields the base-equivalent event (parity). + - `~matSetStep.(5, 2, 3, 7, 0.8)` writes the step; consuming the color's pattern + yields the degree/vel at that step; a non-empty sequence produces a Pbind whose + first non-rest event carries the expected `\degree`. + - all-rest sequence → treated as empty (base fallback). + - `~matSetPoseBind` + `/matrix/pose` runs the bound action; unknown poseId no-ops. + - `~matInstEditPush` emits `/matrix/instedit` with the voice's full state. + - persistence round-trip of steps + poseBindings; legacy files default cleanly. +- **Web**: `node --check`; manual — open the modal from a voice; each tab edits and + round-trips; a sequence replaces the base on the next bar; audition cycles colors; + a pose bind fires on `/matrix/pose`. + +## Out of scope + +- Pose RECOGNITION / named-pose detection in the capture pipeline (this spec only + consumes `/matrix/pose ` — the detector plugs in later). +- Per-step micro-timing/ratchets/probability; variable step counts (fixed 16); + cross-instrument sequence linking; MIDI export.