docs: close out wave Theta-W4, and defer the deck layout rework to TODO
This commit is contained in:
@@ -460,3 +460,47 @@ bumped to **v11** (`kParamsLoopVersion`), appended at the tail; slot 12 is reser
|
||||
smooth on real material, whether the top-strip tab is discoverable, and the LICE
|
||||
rendering of the tab and crossfade fill. Also open: whether the crossfade default
|
||||
should stay 0 (a smooth seam becomes opt-in).
|
||||
|
||||
### Θ-W4-T2 — velocity-deck-and-bipolar-curves
|
||||
|
||||
Gives the three velocity-curve popups (amp, pitch, filter) one home — a new deck group
|
||||
labelled VELOCITY — and makes the pitch and filter transfer curves bipolar. No
|
||||
velocity-curve button remains in MASTER, PITCH, or Filter. Pitch and filter curves now
|
||||
run y range [−1, 1], default flat at 0, so velocity modulation of pitch and filter is off
|
||||
until the user draws a curve; amp stays unipolar [0, 1] with its flat-unity default
|
||||
unchanged. The domain is modelled as a `CurveDomain { Unipolar, Bipolar }` field on
|
||||
`VelocityCurve`, with `curveYMin`/`curveNeutral` deriving from it; `VelocityPoint::amp`
|
||||
was renamed to `value`. A velocity→pitch transfer curve is new — it did not previously
|
||||
exist. Full scale is `kVelocityPitchRangeSemitones = 24.0`, now the single constant the
|
||||
shell's pitch-depth control also consumes; it folds into `baseRatio_` once at note-on, so
|
||||
`process()` gains no per-frame work. The preview button's text is replaced by a drawn
|
||||
play triangle — `previewGlyph()` returns three vertices from the pure layer, the shell
|
||||
passes them to `LICE_FillTriangle`, which was already in the build: no new dependency, no
|
||||
asset. Params payload is **v12** (`kParamsVelocityVersion = 12`), appending the
|
||||
velocity→pitch curve after Θ-W4-T1's loop block.
|
||||
|
||||
**Daniel's ruling — the depth knob stays.** The implementation initially *removed*
|
||||
`FilterParams::velAmount` and the `kFilterVel` depth knob, arguing a bipolar curve is
|
||||
both shape and amount. Daniel rejected that: the knob scalar AND the curve both apply.
|
||||
The depth control was restored, and the filter's velocity contribution is
|
||||
`velAmount × curve.eval(v)` with the curve bipolar. Consequence: with `velAmount`
|
||||
surviving, the pre-v12 migration became a **pure domain re-tag** — a pre-v12 unipolar
|
||||
curve's y values already sit inside [−1, +1], so `velAmount` and every knot carry
|
||||
forward bit-identically, with no scaling transform and no version branch in the reader.
|
||||
The earlier fold-and-rescale approach (and its degree-1-homogeneity argument, which was
|
||||
only exact to within double rounding) was removed entirely.
|
||||
|
||||
**`kFilterVel` also crossed from non-live to live** — a user-visible contract change
|
||||
beyond simple restoration. Rationale: it is a depth over a latched value, the same shape
|
||||
as `kFilterKeyTrack`, live since Θ-W3; the note latches `curve.eval(velocity)` and the
|
||||
depth multiply happens in `applyLive` at block boundaries, gliding through the existing
|
||||
cutoff ramp at zero per-sample cost.
|
||||
|
||||
**Deviations from spec / code review:** Code review ran on two surfaces
|
||||
(engine/persistence, UI/editor) and found one Critical plus two actionable Majors and ten
|
||||
Minors, all remediated. The Critical: `editedCurve()`'s `kNone` fallback let
|
||||
Esc-during-a-curve-node-drag write the pitch or filter curve — bipolar domain and all —
|
||||
over the amp gain curve and persist it. Fixed on both routes (the popup close now
|
||||
cancels the drag; the mutable accessor refuses `kNone`). It has **no automated
|
||||
regression pin** — `src/shell/instrument/` has no test target, and the bug is shell
|
||||
state-machine coupling with no pure-layer equivalent.
|
||||
|
||||
Reference in New Issue
Block a user