docs: spec Phase Γ — the instrument's control surface

Two-row deck reflow (sound/contour), double-height MASTER with limiter and
meter, PITCH/RATE deck, unit-driven knob law, contour-trace fix, and a
re-approached loop/crossfade UX. Folds rulings Γ-F1..Γ-F5; opens Γ-F6.
This commit is contained in:
2026-08-01 16:29:32 -04:00
parent 6c982cd617
commit eb777f55e1
4 changed files with 2316 additions and 44 deletions
+40 -36
View File
@@ -208,50 +208,54 @@ Forward-looking follow-ups. Deferred by decision, not oversight — each entry r
**Done looks like.** Switching projects mid-record leaves the recorded file with a ledger record in the project it belongs to, so a later prune of that project can reclaim it normally.
## The deck layout needs a real rework — one row, taller decks, controls stacked within a deck
## Raise the stage-time ceiling above 2 s for long-decay sound design
**Context (what shipped — Θ-W4-T2).** The VELOCITY deck group landed with the amp, pitch,
and filter velocity-curve buttons together, but the group placement lands wherever the
existing per-row deck layout happens to put it. Daniel does not want multiple rows of
decks. He wants **one row**, with the decks **much taller** to accommodate the controls —
knobs stacked *within* a deck rather than strung out in a long line of small knobs. His
example: the filter's static control knobs go **above** the filter envelope knobs.
**He has further design notes coming**, so this is not ready to implement — it is
recorded here so it is not lost and not attempted piecemeal.
**Context (Daniel, 2026-08-01 — Phase Γ fork Γ-F3).** Every stage-time knob spans `[0, kEnvTimeMaxSeconds]` (`core/instrument/ui/deck_values.h:22`), which reads the AHDSR overlay's schematic scale `kGateStageMaxSeconds = 2.0` (`core/instrument/ui/envelope_overlay.h:85`). Γ-F3 asked whether Phase Γ's log taper should also raise that ceiling. **Ruled: not in Phase Γ — the ceiling stays 2.0 s.** But the ambition is real and is recorded here rather than dropped: Daniel *"can foresee wanting 10-second stages"* for certain sound-design cases, his example being **"a horrifically long decay with tight exp[onent]"** — a very long stage whose curve exponent puts almost all the motion at one end. That shape is unreachable at a 2 s ceiling.
**The wart.** Θ-W4-T2's acceptance criterion "VELOCITY sits immediately to the left of
the VOICE group" is **not met at the default window size**. This is **superseded by the
deferred rework**, not silently dropped — recorded here so a later reader does not see an
unmet criterion with no explanation.
**Why it is deferred rather than done.** It is a musical-range question, not a correctness one, and the right time to answer it is with the new taper in the DAW under the hand — a 5× ceiling change judged from a spec is a guess.
**Intended fix.** Not yet specified beyond the shape above (one row, taller decks,
within-deck knob stacking) — Daniel's further design notes are still to come.
**Two things landing in Phase Γ make it cheap afterwards.**
1. **The log taper (Γ-W1-T1) is what makes a higher ceiling usable rather than unusable.** Under the current linear map, a 10 s ceiling would put 10 ms at 0.001 of travel — one pixel of a 128 px drag — so the ceiling and the low-end resolution were in direct conflict. Under the log taper the low end keeps its resolution regardless of where the ceiling sits (Γ-W1-T1's landmarks: 10 ms within 0.120.20 of travel, 100 ms within 0.420.52). **The taper is the prerequisite, and it is why this is a follow-up rather than a dead end.**
2. **`resetDeckParam` bypassing the taper (also Γ-W1-T1) removes the power-of-two blocker.** `deck_values.h:42-46` records that exact default recovery currently depends on the ceiling being a power of two — `x/2^n*2^n` is lossless, an arbitrary ceiling is not. **2.0 is a power of two; 10.0 is not**, so under today's norm round-trip a 10 s ceiling would land every stage-time reset a mantissa bit off its own default. Γ-W1-T1 makes reset write the default value directly, which retires that dependency outright.
**The constraint the fix MUST handle.** Not yet known — this is exactly why the rework is
deferred rather than attempted against the current spec.
**The constraint the change MUST handle.** `kEnvTimeMaxSeconds` and `kGateStageMaxSeconds` **move together, or not at all.** The AHDSR overlay's schematic scale is derived from the ceiling so that a maxed knob lands exactly at the canvas edge — the agreement requirement is documented at `deck_values.h:19-22`, and `deck_values.h` reads the overlay's constant rather than restating it precisely so the two cannot drift. Raising the ceiling therefore also stretches every drawn AHDSR: at 10 s, a 30 ms attack occupies 0.3% of the schematic's stage domain and becomes visually indistinguishable from zero. **Whether the overlay's schematic scale should stay linear in seconds at a 10 s ceiling, or take a taper of its own, is the real design question underneath this entry** — the constant change is trivial; keeping the drawing legible is not.
**The measured geometry — the data the rework starts from.** Measured at the 840 px
floor window, `availWidth = 824`, Gate mode. Group widths: PITCH 150, PITCH ENV 204,
FILTER 440, FILTER ENV 252, AMP 252, VELOCITY 156, VOICE 152, MASTER 60. Row 1 = PITCH +
PITCH ENV + FILTER (818 of 824). Row 2 = FILTER ENV + AMP + VELOCITY (684). Row 3 = VOICE
+ MASTER (224). Deck height 280 px; waveform band 246 px against a 150 px two-lane floor,
so 96 px of margin. No reordering can fit two rows — 1666 px of groups plus 72 px of gaps
against a 1648 px two-row capacity. Two rows first fit at a 936 px window.
**Priority / risk.** Low / deferred by ruling. No correctness risk: the persisted payload stores raw seconds, so a ceiling change re-tapers needle angles only and every saved project reloads bit-identical (the same persistence-neutrality Γ-W1-T1's own taper changes are held to). **One timing risk that is NOT low:** if VST3 automation parameters ship before this, the ceiling becomes part of the host-facing normalization and moving it silently re-interprets every recorded automation point — the same one-way door `docs/product/parameter-automation.md` §4 states for the taper itself. **If this is wanted, it wants to happen before the parameter system, not after.**
**Unresolved measurement discrepancy.** The VELOCITY↔VOICE adjacency threshold was
measured at a 864 px window by the implementation and stated as 872 px by code review;
the implementation flagged the difference rather than asserting the reviewer wrong, and
it was not re-measured because the deferral made it moot.
**Done looks like.** A stage time of several seconds is reachable by hand with no loss of resolution below 100 ms; the AHDSR overlay still reads legibly at both ends of the range; `kEnvTimeMaxSeconds` and `kGateStageMaxSeconds` still agree; and a project saved at the old ceiling reloads with identical stored seconds and identical audio.
**Priority / risk.** Deliberate deferral, not oversight. Daniel wants to finish his
design notes before this is attempted, to avoid building a layout that gets reworked
piecemeal.
## The deck layout rework — SPECCED, and the original shape SUPERSEDED
**Done looks like.** One row of decks, each much taller than today's, with each deck's
controls stacked internally (e.g. the filter's static control knobs above its envelope
knobs) per Daniel's design notes once they land. The VELOCITY↔VOICE adjacency criterion
is re-evaluated (or explicitly retired) against the new layout rather than the old
per-row one.
**Status (2026-08-01): no longer a deferral. The design notes Daniel owed this entry have
arrived, and they change the shape.** The rework is specced in
`docs/product/instrument-control-surface.md` §1 and sequenced as **Phase Γ** in
`docs/PLAN.md`. This entry is retained only until that work lands, because one loose end
below (the Θ-W4-T2 acceptance criterion) still needs an explicit disposition.
**What was superseded, and confirmed superseded by Daniel.** The original entry recorded a
directive of Daniel's for **one row of much *taller* decks with knobs stacked *within* a
deck** (his example: the filter's static knobs above its envelope knobs). **The new framing
replaces that.** The decks stay **single-height with knobs side-by-side**; what becomes
one row is the **sound** category (PITCH/RATE, FILTER, VELOCITY, VOICE), with the three
envelope decks on a second **contour** row and MASTER as a double-height deck spanning both.
The within-deck stacking idea is retired, not deferred.
**The measured-geometry block that used to live here has been deleted, not moved.** It was
taken at the 840 px floor with `kDeckCellW = 48` and is wrong twice over — Θ-W6-T1 changed
both the floor (980) and the cell metrics (60 × 74). The current, re-derived geometry — every
group's width, both row totals, and the resulting 1190 × 680 floor — is the table in
`docs/product/instrument-control-surface.md` §1.2. **Do not resurrect the old numbers.**
The unresolved 864-vs-872 px VELOCITY↔VOICE adjacency-threshold discrepancy is retired with
them; it was measured against a layout that no longer exists.
**The one live loose end.** Θ-W4-T2's acceptance criterion *"VELOCITY sits immediately to
the left of the VOICE group"* is not met at the default window size today. Under the new
layout it **is** met by construction — row 1 is PITCH/RATE, FILTER, VELOCITY, VOICE, in that
order, at every window width — so the criterion is satisfied rather than retired. Confirm it
when Phase Γ-W3 lands and remove this entry.
**Done looks like.** Phase Γ-W3 (`deck-reflow`) has landed; the VELOCITY↔VOICE adjacency
criterion is confirmed met at the floor width; this entry is removed.
## The AA waveform stroke's cost on the docked bank panel's card thumbnails