docs: schedule VST3 parameters into Phase Γ

Automation ships as Γ-W4; the stage ceiling goes to 10 s in W1-T1 ahead of the
one-way door; a new Γ-W3-T2 corrects Ξ's bake reset list. Four waves, ten tracks.
Opens Γ-F7 on parameter order.
This commit is contained in:
2026-08-01 17:26:18 -04:00
parent 256216d670
commit 2fa55658c1
4 changed files with 1278 additions and 202 deletions
+159 -29
View File
@@ -57,6 +57,16 @@ own width formula, not carried over from a prior measurement. The stale geometry
sits under it. The core finding behind the re-approach: three identical bars draw a
*point* and the two ends of a *span* in the same ink, and the crossfade is painted where
its *ingredient* lives rather than where the *event* is heard. §6.
- **VST3 automation parameters SHIP IN THIS PHASE, as its last track** (Ruling 1, Daniel
2026-08-01). The specification is `docs/product/parameter-automation.md` §§610: 44
exposed parameters derived from the three-state commit predicate, a hand-assigned
FOREVER-FROZEN id table in blocks of 100 with steps of 10, and the blob left
authoritative with parameters as a third surface onto the one model.
- **The stage-time ceiling moves 2 s → 10 s, in wave 1** (Daniel, reversing Γ-F3),
*because* parameters now ship in-phase — a range endpoint is host-facing normalization,
free to move now and permanently expensive afterwards. Its real cost is not the constant
but keeping the AHDSR overlay legible when a 30 ms attack is 0.3 % of the schematic
domain; the answer is to make the schematic axis *be* the taper. §4.3.1.
---
@@ -668,10 +678,24 @@ reduction is applied.**
### 3.4 Where the master controls sit in the reset scope
Phase Ξ-W2's resample reset scope is settled by rule ("reset what the bake baked in").
Derived against that rule, surfaced for Ξ-W2's review rather than as a Daniel call:
**rate → reset**, **pitch offset → reset**, **limiter enabled → reset** (master gain is
already on the reset list, so the bake includes the master stage, so the limiter's effect
is in the audio).
Derived against that rule**no new Daniel call**: **rate → reset**, **pitch offset →
reset**, **limiter enabled → reset** (master gain is already on the reset list, so the bake
includes the master stage, so the limiter's effect is in the audio).
**This is now a CORRECTION, not a sequencing note.** The original plan required Phase Γ to
land before Ξ-W2 so the bake's reset list would be complete on the day it shipped. **That
ordering was never Daniel's choice and it is already violated** — Ξ-W2-T1 was underway
before this phase was scoped (Daniel: *"xi was started before I spun you up, we'll have to
correct phase xi inside gamma. wasn't a choice."*). So the three classifications above are
an amendment Phase Γ **owes** to a shipped bake, and Γ-W3-T2 is the track that pays it. The
amendment is verified **against what Ξ-W2-T1 actually shipped**, never against what this
document predicted it would ship.
**A second correction of the same shape arrives with Ruling 1**, and it is Γ-W4-T1's, not
this one's: once these values are exposed as VST3 parameters, the bake's reset must notify
the host, and a host automation lane on a reset-class parameter re-imposes its curve onto
already-baked audio. Full analysis and the disposition:
`docs/product/parameter-automation.md` §9.
### 3.5 Assessment: the `temp_cortex/` limiter reference
@@ -775,16 +799,87 @@ shape):
- Exactly **0 s at norm 0** and exactly `kEnvTimeMaxSeconds` at norm 1. Monotone and
continuous throughout.
- **10 ms lands within 0.12 … 0.20 of travel; 100 ms within 0.42 … 0.52.**
- `kEnvTimeMaxSeconds` is **2.0 s** (`deck_values.h:22`, reading `kGateStageMaxSeconds` at
`envelope_overlay.h:85`) and **does not move in this phase** — settled, Γ-F3. The AHDSR
overlay's schematic scale is derived from it and the two must agree so a maxed knob lands
exactly at the canvas edge; the agreement requirement is documented at
`deck_values.h:19-22`. **Daniel foresees wanting a 10 s ceiling** for sound-design cases
— his example, *"a horrifically long decay with tight exp"* and that ambition is
carried as a `docs/TODO.md` entry rather than dropped. Two things make it cheap later and
both land in this phase: the log taper is precisely what makes a higher ceiling *usable*
rather than unusable at the low end, and the reset-bypasses-the-taper change below
removes the power-of-two dependency that would otherwise block a 10.0 s ceiling outright.
- `kEnvTimeMaxSeconds` **moves 2.0 s → 10.0 s IN THIS PHASE, in this track**
(`deck_values.h:22`, which reads `kGateStageMaxSeconds` at `envelope_overlay.h:85` — the
two move together or not at all). **This reverses Γ-F3** (Daniel, 2026-08-01:
*"extend the stage lengths to 10s"*), and §4.3.1 below is the design work it pulls in.
#### 4.3.1 The 10 s ceiling — why it moved, and what it costs
**Γ-F3 was ruled "not in this phase" and is now reversed.** The reversal is not a change of
mind about the musical range; it is a consequence of Ruling 1 — VST3 parameters now ship at
the end of this same phase (§4.4, `docs/product/parameter-automation.md` §8). The moment
parameters exist, a range endpoint is part of the host-facing normalization exactly as much
as the curve between the endpoints is: re-ceiling re-interprets every recorded automation
point in project files we do not own and cannot migrate. **Raising the ceiling is free this
wave and permanently expensive four waves later.** The `docs/TODO.md` entry that carried the
ambition is discharged here rather than deferred again.
**Three constraints carry forward unchanged.**
1. **`kEnvTimeMaxSeconds` and `kGateStageMaxSeconds` move together.** `deck_values.h` reads
the overlay's constant rather than restating it precisely so the two cannot drift, and the
agreement requirement is documented at `deck_values.h:19-22`.
2. **The reset bypass is now MANDATORY, not merely required-anyway.** `resetDeckParam`'s
exact-default recovery depends on the ceiling being a power of two
(`deck_values.h:42-46`); **2.0 is, 10.0 is not**, and the log taper compounds it. The
bypass below was already required by this track — it is now also the only thing that
makes the new ceiling correct, so it is not a candidate for "simplification" back into a
norm round-trip under any circumstance.
3. **A new, harder correctness case arrives with the parameters, and it is NOT solved by the
bypass.** `ParameterInfo::defaultNormalizedValue` is normalized; a host's reset-to-default
arrives back as `toPlain(defaultNorm)`, and **the host has no bypass to offer**. The taper
must therefore be designed so **every default has an exact normalized preimage** — see
`docs/product/parameter-automation.md` §8 door 3. This binds the taper's *shape*, so it
belongs to this track and cannot be handed forward.
**The real design problem is legibility, and it is in scope here.** The AHDSR overlay's
schematic gives each of the four timed stages an equal slot and maps seconds across it
linearly (`gatePxPerSecond`, `envelope_overlay.cpp:33-34`). At a 2 s ceiling a 30 ms attack
occupies 1.5 % of its stage's domain — small but drawn. **At 10 s it occupies 0.3 %, under a
pixel at the floor width, and becomes visually indistinguishable from zero.** A 5× ceiling
that makes the default attack invisible is not a feature.
**Three directions were considered.**
1. **Content-fit auto-scale** — the schematic's domain follows the largest current stage, so
short envelopes draw large. Rejected: the axis moves under the hand while you drag, every
node shifts when any node moves, and it breaks the documented anchor that a maxed knob
lands exactly at the canvas edge.
2. **A minimum drawn stage width** — every stage gets at least *n* px regardless of value.
Rejected: it decouples the drawn position from the value, so `envelope_edit`'s drag
inverse can no longer be the exact inverse of the draw — which is the one property the
node/knot/knob "surfaces onto ONE model" invariant rests on.
3. **The schematic axis BECOMES the taper — recommended.** A stage's slot width is
`slotPx × taperNorm(seconds)` instead of `slotPx × seconds / ceiling`. The node's position
within its slot then *is* its knob's needle position, drawn a second way.
**Recommended: direction 3.** It is the smallest change that is also the most principled one:
- **Legibility becomes ceiling-independent by construction.** The taper's own landmarks
(10 ms within 0.120.20 of travel, 100 ms within 0.420.52) are landmarks on the overlay
too, at any ceiling this or a future phase picks.
- **It strengthens the one-model invariant rather than straining it.** A node and its knob
become the same normalized quantity; today they are two maps that happen to agree.
- **It costs the drawn curve nothing.** The taper decides only *where a stage's end node
lands*. Within a stage, φ still runs linearly across the stage's pixel span, so a φ^p
segment draws as φ^p exactly as Γ-W1-T3 specifies — the two tracks compose rather than
fight.
- **The AHD policy is untouched.** An AHD maps 1:1 onto the waveform's own time axis and is
PCM-aligned; it must stay linear in seconds, and nothing here changes it. **Only the AHDSR
schematic is tapered**, and it was already documented as schematic-not-time-aligned.
**The cost, named:** within-stage horizontal extent stops being proportional to time, so two
stages can no longer be compared by eye at a 10× ratio the way they can at 2×. The ms labels
Θ-W6-T1 landed carry the actual number, which is what that comparison is actually made
against; and the alternative — a 30 ms attack drawn as zero — loses the comparison entirely.
**The structural consequence, and it is the important one.** The taper is now read by three
consumers: the knob (`deck_values`), the overlay (`envelope_overlay` + `envelope_edit`), and
— from Γ-W4-T1 — the host (`normalizedParamToPlain`). **It must be extracted into one pure
module** rather than living inside `deck_values`, which sits above `envelope_overlay` in the
dependency order. That extraction is what makes "the taper IS the host-facing normalization"
structurally true instead of a comment somebody has to remember.
**Semitone knobs become log2-scaled.** More resolution across 7 … +7 st while still
allowing the extremes:
@@ -818,11 +913,17 @@ allowing the extremes:
### 4.4 Sequencing — why item D goes first
Item D lands **before** the two new PITCH/RATE knobs, so Rate and Pitch are authored into
the finished law rather than retro-fitted into it. It lands **well before** any VST3
parameter work, for a much sharper reason: once parameters are exposed, the taper *is* the
host-facing normalization, and re-tapering silently re-interprets every recorded automation
point in every saved project. **Taper changes are free now and permanently expensive
later.** See `docs/product/parameter-automation.md` §4.
the finished law rather than retro-fitted into it. It lands **three waves before Γ-W4-T1's
VST3 parameter work**, for a much sharper reason: once parameters are exposed, the taper
*is* the host-facing normalization, and re-tapering silently re-interprets every recorded
automation point in every saved project. **Taper changes are free now and permanently
expensive later.** See `docs/product/parameter-automation.md` §4.
That argument used to justify Γ running ahead of a future phase; since Ruling 1 it governs
**wave order inside this one**, which is strictly better — the taper and the parameters that
freeze it are now reviewed against each other rather than across a phase boundary. It is
also why the ceiling moved (§4.3.1) and why §8's one-way-door sweep in the automation doc is
a deliverable rather than a caution.
---
@@ -1251,18 +1352,20 @@ shape is deliberate and its reasoning is documented at the call site.
---
## 8. Forks — all six ruled, none open
## 8. Forks — six ruled (one later reversed), one open
### 8.1 Ruled by Daniel, 2026-08-01
Every fork this doc opened is closed. The rulings are folded into the sections that
depend on them; this table is the index, not a second copy of the reasoning.
The rulings are folded into the sections that depend on them; this table is the index, not a
second copy of the reasoning. **Γ-F3 was ruled and then REVERSED the same day** — the row
below carries both, because a reader who acts on the first ruling would ship the wrong
ceiling.
| Fork | Question | Ruling | Where it landed |
|---|---|---|---|
| **Γ-F1** | Does `kEditorMinHeight` move 680 → 720? | **No — stays 680.** The reflow's 112 px goes entirely to the waveform. | §1.2 / §1.5, unchanged |
| **Γ-F2** | Limiter lookahead, or zero-latency? | **Lookahead with DYNAMIC reported latency** — zero when off, the lookahead when on, reported to the host's PDC. *Overrides this doc's zero-lookahead recommendation.* | **§3.1.1** (new), §7.10 |
| **Γ-F3** | Does the log taper raise the 2 s stage-time ceiling? | **Not in this phase — stays 2.0 s.** The 10 s ambition is preserved as a `docs/TODO.md` entry with its rationale. | §4.3, `docs/TODO.md` |
| **Γ-F3** | Does the log taper raise the 2 s stage-time ceiling? | **REVERSED, same day. Ruled first "not in this phase — stays 2.0 s"; then Daniel: _"extend the stage lengths to 10s."_ The ceiling moves 2.0 → 10.0 in Γ-W1-T1.** The reversal's cause is Ruling 1: parameters now ship in-phase, so the ceiling is a one-way door that has to be walked through *before* them. | **§4.3.1** (new), §4.3; `docs/TODO.md` entry discharged |
| **Γ-F4** | Explicit loop enable? | **Yes — on the CHROME ROW.** Not a deck cell; loop is a waveform-overlay concept and has no deck. | **§6.4** (new), §6.5, §7.9 |
| **Γ-F5** | MASTER's reserved slot: one cell or two? | **One cell.** Two would spend 60 of the 90 px headroom on an unnamed control and freeze row 1 forever. | **§1.6** (new), §1.4 |
| **Γ-F6** | Is the `kLatencyChanged` deactivate/reactivate acceptable as the cost of the toggle? | **Yes — ship dynamic latency as ruled.** No constant-latency fallback, no measurement gate. *Corrected this doc's analysis: the cost is self-inflicted, not SDK-imposed.* | **§3.1.1** (rewritten), §7.10, §7.11, `docs/TODO.md` |
@@ -1322,18 +1425,39 @@ than just counting:
`restartComponent`), not about this flag.
5. **The reduction is filed**, with a trigger condition, in `docs/TODO.md`.
*No fork in this phase is open. Nothing in §§17 awaits a Daniel answer.*
### 8.3 Γ-F7 — OPEN. The parameter order
**Opened 2026-08-01 by Ruling 1** (*"Make the parameter order logical"*), because "logical"
resolves two ways and the choice is frozen forever the day parameters ship.
> **Signal-flow order** — PITCH/RATE → PITCH ENV → FILTER → FILTER ENV → AMP → VELOCITY →
> VOICE → MASTER, the deck's own documented ordering rule, layout-independent.
> **OR the editor's visual row order** after the Γ-W3 reflow — row 1 then row 2 then MASTER,
> matching what the user's eye scans.
Same membership, different sequence; the recommendation, both arguments, and why the
grouping (`IUnitInfo`, one unit per deck group) is settled either way are in
`docs/product/parameter-automation.md` §6.4. **Recommendation: signal flow**, because the
visual layout has moved twice already and this phase moves it again, and freezing a forever
identity to a thing that moves is the wrong coupling.
**Urgency: low, but not zero.** Three waves sit in front of Γ-W4-T1 and nothing before it
depends on the answer. It must close **before Γ-W4 dispatches**, and it cannot be closed by
proposal at review — a forever commitment is a Daniel call.
*Every other fork in this phase is ruled. Nothing in §§17 awaits a Daniel answer.*
---
## 9. Build shape
Sequenced into `docs/PLAN.md` as **Phase Γ** (worktree slug prefix `pg-`), **three waves**
(resequenced by Daniel, 2026-08-01 — see below):
Sequenced into `docs/PLAN.md` as **Phase Γ** (worktree slug prefix `pg-`), **four waves**
(resequenced by Daniel twice on 2026-08-01 — see below):
```
Γ-W1 Foundations [5 tracks, disjoint by surface]
T1 knob-interaction-law ............ item D (editor input + deck_values tapers)
T1 knob-interaction-law ............ item D (editor input + the ONE taper module +
10 s ceiling + AHDSR schematic scale)
T2 master-bus-audio ................ item C (pure limiter + meter ballistics +
processor + LATENCY REPORTING)
T3 contour-trace-curves ............ item E (waveform painter)
@@ -1344,11 +1468,17 @@ Sequenced into `docs/PLAN.md` as **Phase Γ** (worktree slug prefix `pg-`), **th
T1 pitch-rate-deck ................. item A (params + engine + deck descriptor)
T2 loop-crossfade-ux ............... item F (waveform painter + pure marker geometry
+ the chrome-row loop enable)
Γ-W3 The reflow [1 track]
Γ-W3 The reflow, and the bake correction [2 tracks]
T1 deck-reflow ..................... item B's ARRANGEMENT half + C's UI half
T2 bake-reset-amendment ............ the Phase Ξ correction Γ owns (§3.4)
Γ-W4 VST3 parameters [1 track]
T1 vst3-parameter-set .............. Ruling 1 (parameter-automation.md §§6-10)
```
**Two resequencing decisions, both Daniel's (2026-08-01).**
**Three resequencing decisions, all Daniel's (2026-08-01).** The third is Ruling 1: the
parameter system moves from "a future phase" into **Γ-W4**, which is what put the 10 s
ceiling into W1 (§4.3.1) and turned the Ξ ordering constraint into an owned correction
(§3.4). The first two:
1. **Item B splits: canvas early, arrangement late.** The window floor, the width budget it
derives from, and each group's row membership land in W1-T4 so every other UI track is