docs: close out Θ-W2-T1 filter-voice-path into COMPLETED

Move the landed filter-voice-path track from PLAN.md into COMPLETED.md with full
narrative (quantizer removal, editor floor raise). Mark Θ-W2 fully landed, matching
W1's phrasing; fix a stale forward reference.
This commit is contained in:
2026-07-30 18:23:42 -04:00
parent 9b1a49c640
commit 413967a205
2 changed files with 48 additions and 73 deletions
+10 -73
View File
@@ -145,8 +145,8 @@ collision is real and the serialization is the correct answer.
the full narrative of each. Between them: the zone subsystem is retired, the wave's two
responsibility seams (the `sampler_core` split, the Sample-face band split) are in
place, the two extension-side capture-handoff defects are fixed, and the filter DSP has
landed as a standalone pure module with no call site — Θ-W2-T1 integrates it into the
voice path.
landed as a standalone pure module — Θ-W2-T1 has since wired it into the voice path (see
below).
---
@@ -158,77 +158,14 @@ band-stack allocator that T2 and T3 fill; and W1-T1's key-range answer, which de
what T3's piano strip displays. Authoring any of this against the per-zone model means
writing storage plumbing W1 deletes.
**Θ-W2-T2 (`stereo-waveform-lanes`) and Θ-W2-T3 (`toolbar-and-piano-strip`) have
landed** — see `docs/COMPLETED.md`. Between them: the waveform band now shows both
channels in stereo mode behind a type-enforced full-height overlay contract, and the
chrome band's toolbar and piano strip are cleaned up per spec. **One track remains:**
Θ-W2-T1 (`filter-voice-path`), which puts the filter into the per-voice signal path and
gives it its deck. The three tracks were disjoint by band — T1 owns the parameter model
and the deck band, T2 owned the waveform band, T3 the chrome band — and none
re-allocates the band stack.
#### Θ-W2-T1 — `filter-voice-path`
**Goal.** Put the filter into the per-voice signal path as a new fixed processing point,
give it its deck, and relay the deck row in signal-flow order.
**Consolidates item 2 (integration half).** The DSP module is Θ-W1-T3. The filter
envelope's *curve treatment and mode-driven shape* arrive in Θ-W3 — this track ships the
filter envelope in the existing staged AHDSR shape.
**Surface boundary — owns:** `core/instrument/engine/` voice-render filter call site +
`zone_params.h` (filter parameters), `core/instrument/map/component_state_io` (version
bump for the filter parameters), `core/instrument/ui/knob_deck` + the **deck band** of
the Sample face (geometry, paint, input). Reads the band allocator; does not change it.
**Behavior.**
- **Pipeline position.** A new processing point in the sampler audio pipeline: **after
the pitch envelope, before the amp stage.** The amp envelope still shapes the filtered
result.
- **Per-voice.** Each sounding voice runs its own filter with its own envelope state —
not a shared instance-wide filter.
- **Parameters:** mode, cutoff, Q, mod amt — then the AHDSR controls.
- **Mod amt: bipolar, 100% to +100%, targeting cutoff** — covering the full range
from either end.
- Cutoff / Q / mode ranges are the module's, from Θ-W1-T3.
- **Velocity and key-tracking modulation ship with this item — not deferred.** The
filter gains velocity modulation following the amp's velocity-transfer-curve pattern
and key-tracking following the pitch key-tracking pattern. The follow-up established
the parallel, not new ranges or control layout — follow the cited precedents. (The
*bipolar domain and default* of the filter velocity curve, and its button's home, are
item 11 — Θ-W4-T2. This track wires the modulation path; that track shapes the curve.)
- **Off by default.** Pre-existing saved instances and freshly loaded captures sound
unchanged until the user engages it.
- **Parameters live in the instrument's one parameter set** (post-item-16) — no per-zone
storage, no Sample/Zone parity.
- **Label.** The user-facing deck-group label is **"Filter"**. "MM preamp" is working
shorthand for the DSP lineage, not UI text.
- **Deck reorder.** The knob deck row is relaid out in signal-flow order:
**pitch → filter → amp**.
**Acceptance criteria.**
- With the filter engaged, played notes are audibly filtered at the specified pipeline
point: the filter acts on pitched (post-pitch-envelope) signal and the amp envelope
still shapes the filtered result — audible ordering pitch → filter → amp.
- Mode, cutoff, Q, and mod-amt controls appear in a deck group labeled **"Filter"**.
- Cutoff sweeps the full audio spectrum on a log scale, fully open to fully closed; Q
spans 0.1 → 10 with √2 at the control's center; mod amt at 100% and at +100% each
drive cutoff across the full range, from opposite ends.
- High Q audibly emphasizes the cutoff region in both HP and LP modes.
- **Two simultaneously sounding voices at different envelope phases are filtered
independently** — per-voice processing is audible, not a shared filter.
- Filter parameters live in the one parameter set: they edit in one place and govern the
instrument as a whole.
- Velocity and key-tracking modulation of the filter are audible — velocity following
the amp-velocity-transfer-curve pattern, key-tracking following the
pitch-key-tracking pattern.
- The deck row reads pitch → filter → amp left-to-right.
- **The filter is off by default:** a project saved before this change reopens sounding
identical, and a freshly loaded capture sounds unchanged until the filter is engaged.
- The filter tick adds no allocation and no virtual dispatch to `process()`.
**Open questions.** None carried from item 2 — all three of its prior questions (other
mod sources, parameter storage side, neutral default) closed in the source doc.
**All three tracks have landed** Θ-W2-T1 (`filter-voice-path`), Θ-W2-T2
(`stereo-waveform-lanes`), and Θ-W2-T3 (`toolbar-and-piano-strip`) — see
`docs/COMPLETED.md` for the full narrative of each. Between them: the filter sits in the
per-voice signal path with its own deck, the waveform band shows both channels in
stereo mode behind a type-enforced full-height overlay contract, and the chrome band's
toolbar and piano strip are cleaned up per spec. The three tracks were disjoint by
band — T1 owned the parameter model and the deck band, T2 owned the waveform band, T3
the chrome band — and none re-allocated the band stack.
---