# TODO-1.0

Post-1.0 queue for ReaSampler — chiefly the 9000 instrument, plus two
extension-side bugs. Items 1–3 are the first batch, in Daniel's ordering
(2026-07-28); items 4–13 are a second batch (2026-07-28, later the same day).
Deliberately specified at the level of product
intent, user-visible behavior, and acceptance criteria — **no implementation
design, no file/module references**. These were authored while Phase Q was
restructuring the tree; the implementing engineer maps each spec onto the
post-Q layout at execution time. Each item preserves Daniel's raw ask verbatim
as the source of truth, then breaks it into behavior, open questions, and an
observable acceptance gate.

A follow-up answer round from Daniel (2026-07-28) settled most of the open
questions. Each item now carries his follow-up verbatim alongside the original
ask; settled answers are folded into **Behavior** (marked *settled by
follow-up*), and only the genuinely unresolved remainder stays under **Open
questions**.

A **second follow-up round** (2026-07-28, same day) settled nearly all of the
remainder. Each item carries that round's verbatim as a third provenance block;
answers are folded the same way (marked *settled by second follow-up*).

A **third follow-up round** (2026-07-28, same day) settled item 3's last two
questions (point-count ceiling; delete gesture — reversing the second round's
alt-click answer back to right-click). **All three first-batch items now have
no open questions; the first batch is fully settled at the product level.**

A **second batch** from Daniel (2026-07-28) appends items 4–13 — a mix of bug
reports and enhancements. His message numbered them 1, 2, 3, 4, 3, 4, 5, 6, 7,
8 (two items labelled 3 and two labelled 4). His *sequence* is preserved
exactly; each item carries an unambiguous doc number continuing from 3, with
his original label recorded in the heading (e.g. *his 3, second*) so his
message maps onto the doc. Each item is marked **Bug** or **Enhancement**;
item 9 is explicitly both — a suspected regression plus a feature spec. Bugs
are recorded compactly (symptom, expected behavior, acceptance gate) with **no
root-cause analysis** — same no-code-reads constraint as the first batch.

A **second-batch follow-up round** (2026-07-28, same day) answered items 7, 8,
and 11. Item 7 closes clean. Item 11's answer **supersedes the original ask's
button placement** — a new VELOCITY deck group replaces the per-section
placement, MASTER being reserved for later post-voice-mixer concerns. Item 8's
answer is a **spec change, not a clarification**: the pitch envelope's AD
becomes an **AHD** (a Hold stage is added), and the doc's own prose (items 1
and 8) is updated to match — Daniel's verbatim asks stay exactly as originally
written.

Ordering note: item 1's curve/overlay treatment explicitly anticipates item 2's
filter envelope ("filter to be added"), and item 3 layers on both. They can land
in sequence or together, but 1 and 2 are prerequisites for 3's full surface.
Second-batch interactions: the three bugs (4–6) are independent of the
enhancement chain and can land at any time. Item 8 edits the same overlay
surface as item 1 and is cheapest folded into or immediately after that work;
item 10's per-ring reset presupposes item 1's inner dials; item 11's filter
velocity curve presupposes item 2's filter (though its button now homes in
item 11's own VELOCITY deck, not the Filter deck); item 9's
loop-sustain is a Gate-mode (Staged) feature and composes with item 3's
Gate-unavailable-in-Spline rule. Item 13 (anti-aliasing audit) touches nearly
every surface the other items repaint — sequencing it after the layout/knob
work (1, 8, 10, 11, 12) likely avoids doing the polish twice; that is an
observation, not a decision.

---

## 1 — Envelope editor: per-deck radio switch, segment curve dials, overlay recolor

**Daniel's ask (verbatim, 2026-07-28).**

> The VST envelope editor visual is a great start but we need to add some
> features. The Amp AHDSR is currently always displayed. We need to add a radio
> switch to the corner of each env knob deck which makes THAT envelope editable
> via the graphic waveform overlay. This is currently the amp and pitch
> envelopes, with filter to be added (see below). All envelopes (amp AHDSR,
> Pitch AD, Filter AHDSR) should be enhanced to have editable segment curve
> values. This should be an exponential function with the exponent scalar
> parameter for each sloped segment having possible values from 0.1 to 10. The
> knob deck radial knobs for the sloped curvable segments will have an INNER
> dial, with its own inner arc, hover accent (tertiary purple), needle, and
> numerical label which controls the curve for that sloped segment. Also the
> graphical envelope editor draws its segments in secondary blue, which
> contrasts poorly against the primary green waveform display. Change those to
> tertiary purple.

**Daniel's follow-up (verbatim, 2026-07-28).**

> yes, one overlay (or none). Everything besides Hold and Sustain, right? "is
> 1.0 the linear neutral" CLAUDE, y=x^1.0 is linear!! of course! yes dragging
> on the segment (add a round knot midsegment) adjusts the curve.

**Daniel's second follow-up (verbatim, 2026-07-28).**

> default overlay none
> what about the curves?

("what about the curves?" is Daniel turning the pre-existing-instances
question back — the answer recorded below is derived from this doc's own
acceptance criterion, not a Daniel quote.)

**Intent.** Grow the envelope-overlay editor from an amp-only fixture into the
shared graphical surface for every envelope in the instrument, and give every
envelope shapeable (non-linear) segments — while fixing the blue-on-green
contrast failure.

**Behavior.**

- **Radio switch per envelope deck.** Each envelope knob-deck group (currently
  AMP ENVELOPE and PITCH ENV; the filter envelope joins when item 2 lands)
  gains a radio switch in the corner of its deck. Selecting a deck's radio
  makes *that* envelope the one displayed and editable in the graphic waveform
  overlay — replacing today's behavior where the Amp AHDSR is always the
  displayed envelope. The switch is exclusive: **one overlay-active envelope at
  a time, or none** — no-envelope-shown is a valid state, not an error.
  *(Settled by follow-up.)*
- **Default overlay: none.** The editor opens with **no envelope selected** —
  the none-state is the default, replacing today's always-on Amp AHDSR.
  *(Settled by second follow-up.)*
- **Pre-existing instances load at exponent 1.0.** Saved instances from before
  this change load **every curve at exponent 1.0** — the linear neutral — so
  their audible envelope behavior is unchanged. *(Derived, not a Daniel quote:
  1.0 is the settled linear neutral, and the acceptance criterion "a project
  saved before this change reopens with unchanged audible envelope behavior"
  admits no other default. Daniel prompted the question; this is the only
  answer consistent with what he has already settled.)*
- **Segment curve values on all envelopes.** Amp AHDSR, Pitch AHD (AD in the
  original ask; item 8's follow-up adds the Hold stage), and Filter AHDSR all
  gain an editable curve value per *sloped* segment. The curve is an
  exponential function; the per-segment parameter is the exponent scalar,
  range **0.1 to 10**.
- **Which segments are sloped.** **Every stage except Hold and Sustain** — for
  an AHDSR that is Attack, Decay, and Release; for the Pitch AHD (A→H→D since
  item 8's spec change), Attack and Decay — its Hold, like every Hold, is flat
  and carries no curve dial. *(Settled by follow-up; the pitch reading updated
  for item 8's AD→AHD change.)*
- **Linear neutral.** Exponent **1.0 is the linear neutral** (y = x^1.0 is
  linear). *(Settled by follow-up — emphatically.)*
- **Curve editing in the overlay.** Dragging on a segment in the overlay
  **adds a round mid-segment knot** whose drag adjusts that segment's curve —
  the overlay is a curve-edit surface in its own right, alongside (not instead
  of) the inner dial. *(Settled by follow-up.)*
- **Inner dial on curvable-segment knobs.** Every knob-deck radial knob that
  controls a sloped, curvable segment gains an **inner dial**: its own inner
  arc, its own hover accent (tertiary purple), its own needle, and its own
  numerical label. The inner dial controls the curve exponent for that
  segment; the outer knob keeps controlling the segment's time/level value as
  today.
- **Overlay recolor.** The graphical envelope editor's segments change from
  secondary blue to **tertiary purple** (secondary blue contrasts poorly
  against the primary green waveform behind it).

**Open questions.**

- None remaining — both prior questions (default overlay selection,
  pre-existing-instance curve loading) closed by the second follow-up round.

**Acceptance criteria.**

- Each envelope deck shows a corner radio switch; activating one puts that
  envelope in the overlay, editable there, and the overlay tracks the switch
  immediately. At most one envelope is overlay-active; with none active, the
  overlay draws no envelope.
- The editor opens with no envelope overlay-active (default is none, not the
  Amp AHDSR).
- Every curvable-segment knob shows the inner dial (inner arc, tertiary-purple
  hover accent, needle, numeric label); sweeping it through 0.1 → 10 visibly
  reshapes the overlay segment and audibly reshapes the envelope on played
  notes. Hold and Sustain knobs carry no inner dial.
- Dragging on an overlay segment adds a round mid-segment knot; dragging the
  knot adjusts that segment's curve, and the segment's inner dial reflects the
  same value.
- Overlay envelope segments render in tertiary purple and are clearly legible
  against the primary green waveform.
- A project saved before this change reopens with unchanged audible envelope
  behavior: every curve loads at exponent 1.0.

---

## 2 — MM preamp Filter: resonant HP/LP stage in the voice pipeline

**Daniel's ask (verbatim, 2026-07-28).**

> MM preamp Filter: We must implement a new processing point in the sampler
> audio pipeline, after pitch env, before amp, for filtering. The processor for
> this will be based on code I wrote for the cortex M4 for resonant high and
> lowpass filtering. The filter will have parameters for mode, cutoff, Q, and
> mod amt, then the AHDSR controls as described above. The knob deck row will
> then be relaid out in signal flow order: pitch -> filter -> amp

**Daniel's follow-up (verbatim, 2026-07-28).**

> modes beyond the pass filters will be added later. cutoff range full audio
> spectrum, log scaled, fully open to fully closed, Q should go from 0.1 to 10
> again, scaled around root 2 at the center. mod amt targets cutoff, -100% -
> +100% to cover full range from either end. per-voice. label it "Filter"

**Daniel's second follow-up (verbatim, 2026-07-28).**

> oh, zone.
> yes, filter is off by default
> velocity and keytracking with the rest, not deffered.  Same idea as the amp
> velocity transfer curve and pitch key tracking

**Intent.** Add the instrument's first filter stage — resonant high-pass and
low-pass — as a new fixed point in the per-voice signal path, with its own
AHDSR envelope, and make the knob-deck row read in signal-flow order.

**Behavior.**

- **Pipeline position.** A new processing point in the sampler audio pipeline:
  **after the pitch envelope, before the amp stage.**
- **DSP source.** The filter processor is based on Daniel's own Cortex-M4
  resonant high/lowpass filter code. **That code is an input Daniel supplies at
  implementation time** — it is not in this repo and this spec does not
  characterize it beyond "resonant high and lowpass."
- **Parameters.** Mode, cutoff, Q, and mod amt — then the AHDSR controls,
  treated exactly as item 1 specifies (curvable sloped segments with inner
  dials, overlay editability via the filter deck's radio switch).
  *(Ranges settled by follow-up:)*
  - **Mode:** high-pass and low-pass now; **modes beyond the pass filters are
    explicitly deferred to later.**
  - **Cutoff:** the **full audio spectrum, log scaled**, from fully open to
    fully closed.
  - **Q:** **0.1 to 10** (the curve-exponent range again), scaled so **√2 sits
    at the center** of the control.
  - **Mod amt:** **bipolar, −100% to +100%**, targeting **cutoff** — covering
    the full range from either end.
- **Per-voice.** The filter processes **per voice** — each sounding voice runs
  its own filter with its own envelope state. *(Settled by follow-up.)*
- **Per-zone storage.** The filter's parameters are **stored per-zone**,
  alongside the other playback parameters — Sample/Zone panel parity applies,
  same as the existing per-zone controls (VOICE and MASTER remain the
  per-instance exceptions). *(Settled by second follow-up.)*
- **Off by default.** The filter **defaults to off** — pre-existing saved
  instances and freshly loaded captures sound unchanged until the user engages
  it. *(Settled by second follow-up.)*
- **Velocity and key-tracking modulation — in this item, not deferred.** The
  filter gains **velocity** and **key-tracking** modulation now, alongside the
  mod-amt/envelope path: the same idea as the amp's velocity transfer curve
  and the pitch key-tracking, respectively, applied to the filter. The
  follow-up establishes the parallel, not new ranges or control layout — those
  follow the cited precedents. *(Settled by second follow-up.)*
- **Label.** The user-facing deck-group label is **"Filter"**. "MM preamp" is
  working shorthand for the DSP lineage, not UI text. *(Settled by
  follow-up.)*
- **Deck reorder.** The knob deck row is relaid out in signal-flow order:
  **pitch → filter → amp**.

**Open questions.**

- None remaining — all three prior questions (other mod sources, parameter
  storage side, neutral default) closed by the second follow-up round.

**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"**; the filter AHDSR gets the full item-1 treatment (curve inner
  dials, corner radio switch, tertiary-purple overlay editing).
- Cutoff sweeps the full audio spectrum on a log scale, from 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 (resonance) 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 instance-wide
  filter).
- Filter parameters follow Sample/Zone panel parity: they appear and edit on
  both surfaces, and each zone carries its own filter settings (two zones with
  different filter settings audibly differ).
- Velocity and key-tracking modulation of the filter ship with this item and
  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.

---

## 3 — Alternative Spline EGs: hard/smooth multi-segment monotonic splines

**Daniel's ask (verbatim, 2026-07-28).**

> Alternative Spline EGs: Every processor which has an envelope will have the
> ability to change the Staged EG to a Spline EG, based on the monotonic
> splines for the velocity curve. HOWEVER, we will need to enhance the (singly
> implemented, multi referenced) spline algorithm to support multiple segments
> that DON'T minimally smooth the spline, so that hard points are possible. In
> other words, the contour of the EG will be defined by 1 or more monotonic
> spline functions which together form the full time function for that
> processor, such that the first three points could make a curved segment,
> which connects at a sharp angle to the next three points, finishing out the
> contour over the full sample length. Control-clicking a point makes it a
> "hard" or "smooth" point (toggled, smooth by default) which when hard does no
> curve smoothing on either side segment, forming the natural sharp angle
> instead of a continuous derivative. This enhanced spline drawing will be used
> for the velocity-amp transfer curve as well as the pitch, filter, and amp EGs
> (if they are in spline mode).

**Daniel's follow-up (verbatim, 2026-07-28).**

> dual state, save but inactive. Default Curve Spline is a smooth y=1-x. Gate
> mode is not available when the Spline is used, spline always covers the full
> sample length. The spline curves don't have to rise AND fall, they also
> aren't globally monotone, the default curve is a smooth downward slope over
> the length. all the soft points between any hard points will be
> smooth/monotone.

**Daniel's second follow-up (verbatim, 2026-07-28).**

> normalize the spline eg length to the full width, it should represent the
> time axis of the actual sample visually 1:1
> left click add, alt-click delete, cntrl-click toggles point hard or soft.
> spline active -> stage knobs disabled.

**Daniel's third follow-up (verbatim, 2026-07-28).**

> oh, maybe 64? is that way too much?  I don't want to limit from long rhythmic
> phrases, which require a high resolution to be interesting
>
> oh, do right click delete instead for the spline
> 128 then

**Intent.** Offer a free-drawn alternative to every staged envelope: the user
switches any EG from Staged to Spline mode and draws the contour directly, with
the monotonic-spline machinery already proven by the velocity curve — enhanced
so sharp corners are possible, not everything smoothed.

**Behavior.**

- **Mode toggle per EG.** Every processor that has an envelope (pitch, filter,
  amp) can switch its Staged EG to a **Spline EG**.
- **Dual state — save but inactive.** Both the Staged and the Spline state are
  persisted; switching modes keeps the inactive one **saved but inactive**. No
  conversion, no discard — round-tripping Staged↔Spline restores the other
  mode's shape untouched. *(Settled by follow-up.)*
- **Gate unavailable in Spline mode.** Gate mode is **not available while a
  Spline EG is active**; the spline **always covers the full sample length** —
  a pure time function over the sample, i.e. the Trigger/one-shot playback
  model. *(Settled by follow-up.)*
- **Time axis: normalized, visually 1:1.** The spline contour is **normalized
  to the full sample length**, and the overlay represents **the time axis of
  the actual sample visually 1:1** — the contour's full width maps directly
  onto the displayed sample. Consequently a different-length capture rescales
  the stored contour to its own length. *(Settled by second follow-up.)*
- **Point-editing grammar.** **Left-click adds a point; right-click deletes a
  point; control-click toggles a point hard/smooth.** *(Settled by third
  follow-up; control-click hard/smooth confirms the original ask.)* Note for
  readers of the prior revision: the second follow-up answered alt-click
  delete; the third follow-up **supersedes that** with right-click delete —
  which matches the velocity-curve popup's already-shipped right-click node
  delete, giving one point-editing grammar across both spline consumers.
- **Point-count ceiling: 128.** A spline contour holds at most **128 points**
  (floor: the two endpoints implied by full-length coverage). Daniel floated
  64 and raised it to 128 explicitly so the cap does not limit **long rhythmic
  phrases, which require high resolution to be interesting** — at roughly two
  points per articulation event, 64 points is about two bars of 16ths and 128
  about four. The ceiling is a musical bound, not a performance one (segment
  lookup is logarithmic; on-screen the editor's 8 px minimum node separation
  is the practical density limit anyway). **An engineer tempted to lower this
  number should read that motivation first.** *(Settled by third follow-up.)*
- **Staged controls disabled while Spline is active.** While a Spline EG is
  active, that envelope's **staged segment knobs are disabled** — inert, not
  merely inaudible — including their item-1 inner curve dials (the dial is
  part of the knob). The dormant staged state is edited only by switching back
  to Staged mode. *(Settled by second follow-up.)*
- **Not globally monotone.** Spline contours **don't have to rise and fall and
  are not globally monotone**; the monotone guarantee is per-segment — **all
  soft points between any hard points are smooth/monotone** (no overshoot
  between adjacent points). *(Settled by follow-up.)*
- **Default contour.** A new Spline EG defaults to a **smooth y = 1 − x** — a
  smooth downward slope over the full sample length. (Read as the Spline-EG
  default contour; not a change to the velocity→amp transfer curve's existing
  default.) *(Settled by follow-up.)*
- **Spline foundation.** The Spline EG is based on the monotonic splines used
  for the velocity curve. The spline algorithm is singly implemented and
  multi-referenced; the enhancement below applies to that one implementation
  and flows to every consumer.
- **Hard points.** The algorithm is enhanced to support **multiple segments
  that don't minimally smooth the spline**, so hard points are possible: the
  EG contour is defined by **one or more monotonic spline functions** which
  together form the full time function for that processor — e.g. the first
  three points form a curved segment that connects **at a sharp angle** to the
  next three points, finishing the contour over the **full sample length**.
- **Hard/smooth gesture.** **Control-clicking a point toggles it hard/smooth
  (smooth by default).** A hard point does no curve smoothing on either
  adjacent segment — the natural sharp angle stands instead of a continuous
  derivative.
- **Shared across consumers.** The enhanced spline drawing serves the
  **velocity→amp transfer curve** as well as the pitch, filter, and amp EGs
  (when those are in spline mode). The velocity curve gains hard-point support
  by the same enhancement.

**Open questions.**

- None remaining — both prior questions closed by the third follow-up round.
  Point-count bounds: ceiling 128, floor two endpoints. Gesture convergence:
  resolved by the delete-gesture reversal itself — the Spline EG's right-click
  delete now matches the velocity-curve popup's shipped right-click node
  delete, so **no migration is needed on either side**; one grammar serves
  both consumers.

**Acceptance criteria.**

- Each of the pitch, filter, and amp EGs offers a Staged/Spline mode switch;
  in Spline mode the overlay (via the item-1 radio switch) shows and edits the
  drawn contour, and played notes audibly follow it.
- Left-click on the contour adds a point at that position; right-click on a
  point deletes it; control-click toggles it hard/smooth. Points are smooth by
  default; a hard point renders a visible sharp angle with no smoothing on
  either adjacent segment, and the discontinuous slope is audible where the
  modulation target makes it so (e.g. a pitch EG corner).
- A contour accepts points up to the **128-point ceiling**; attempting to add
  beyond it is refused without disturbing the existing contour. The two
  endpoints cannot be deleted (full-length coverage always holds).
- A contour of several segments joined at hard points plays back over the full
  sample length exactly as drawn — including contours that rise and fall
  freely (no globally-monotone restriction), with no overshoot between any
  adjacent pair of points.
- A freshly created Spline EG shows the smooth y = 1 − x default contour.
- While a Spline EG is active, Gate mode is not selectable; the spline plays
  as a pure time function over the full sample length.
- The overlay contour spans the full displayed sample width, 1:1 with the
  sample's time axis; loading a different-length capture rescales the contour
  to the new sample length (normalized storage), with the drawn shape
  preserved proportionally.
- While a Spline EG is active, that envelope's staged segment knobs and their
  inner curve dials render disabled and reject edits; switching back to Staged
  re-enables them with values exactly as left.
- Staged↔Spline round-trip preserves both states: switch to Spline, draw,
  switch back — the staged values are exactly as left; switch forward again —
  the spline contour is exactly as drawn. Both survive save/reload.
- The velocity→amp transfer-curve editor supports the same control-click
  hard/smooth toggle with identical rendering behavior, and its existing
  right-click node delete matches the Spline EG's delete gesture unchanged —
  one point-editing grammar across both consumers.

---

## 4 — Bug: end-of-sample click in Trigger mode under Preserve *(his 1)*

**Daniel's report (verbatim, 2026-07-28).**

> actual bug: in trigger mode, polyphonic or monophonic, in preserved pitch
> mode only, the end of the sample has an audible click.

**Symptom.** In Trigger mode — polyphonic or monophonic alike — with the pitch
engine in **Preserve mode only**, the end of the sample produces an audible
click. The scoping is the useful part of the report and is recorded as given:
Trigger × Preserve × end-of-sample; Varispeed is not implicated. No cause
speculation here.

**Expected behavior.** A Trigger one-shot in Preserve mode ends silently — no
click or discontinuity at the sample end, in either voice mode.

**Acceptance gate.** A Trigger-mode note played in Preserve, in both Poly and
Mono, ends with no audible click at the sample end (verified by ear and by
inspecting the rendered output for a terminal discontinuity). Varispeed
playback is unchanged.

---

## 5 — Bug: drag-out sometimes lands without audio (extension) *(his 2)*

**Daniel's report (verbatim, 2026-07-28).**

> other bug (extension, not VST): Dragging capture out of the pool or bank does
> sometimes doesn't actually contain the audio, and I hae to try dragging
> again.

**Symptom.** Extension side, not the VST. Dragging a capture out of the pool
or a named bank **sometimes** produces a drop that does not actually contain
the audio; retrying the drag works. Both details are load-bearing: the failure
is intermittent, and a retry succeeds.

**Expected behavior.** Every completed drag-out delivers the capture's audio
at the drop target — first try, every time.

**Acceptance gate.** Because the failure is intermittent, the gate is a soak:
across a sustained session of varied drag-outs (pool and bank sources,
including the first drag after other bank activity), every drop yields a
playable file containing the audio, with no retry ever needed.

---

## 6 — Bug: drop onto FX container loads instrument without the capture *(his 3, first)*

**Daniel's report (verbatim, 2026-07-28).**

> drop to FX container bug: the reasmpler 9000 loads, but not with the capture.
> drop to FX button works as expected with capture preloaded.

**Symptom.** Dropping a capture onto an **FX container** loads a ReaSampler
9000 instance, but **without the capture**. Dropping the same capture onto the
**FX button** works as expected — instrument loads with the capture preloaded.

**Expected behavior.** The FX-button path is the reference; the container path
must match it: instrument added *with* the dragged capture loaded.

**Acceptance gate.** A capture dropped onto an FX container yields an
instrument instance with that capture loaded and immediately playable,
indistinguishable (apart from where the FX sits) from the FX-button drop. The
FX-button path remains unregressed.

---

## 7 — Enhancement: stereo waveform shows both channels *(his 4, first)*

**Daniel's ask (verbatim, 2026-07-28).**

> VST Waveform Visualizer: in stereo mode, both L and R channels should show
> in the waveform visual. left on top.  mono mode still shows just one channel
> for unredundancy.

**Daniel's follow-up (verbatim, 2026-07-28).**

> 7) One full height; stereo linked processing, one editor

**Behavior.**

- In **stereo mode**, the waveform visual shows **both L and R channels, left
  on top** (two stacked lanes).
- In **mono mode**, a single channel shows — no redundant duplicate lane.
- The display keys off the active channel mode, per Daniel's phrasing.
- **Overlays draw once, at full height.** Overlays that ride the waveform
  (the envelope overlay, markers, and item 9's loop region if it lands) draw
  **once at full height across both stacked lanes** — not per lane.
  *(Settled by follow-up.)*
- **Stereo processing is linked.** One editor, one set of controls governing
  both channels — no per-channel parameter divergence, no per-channel editing
  surface. *(Settled by follow-up.)*

**Open questions.**

- None remaining — the overlay-layout question closed by the second-batch
  follow-up round.

**Acceptance criteria.**

- A stereo capture in stereo mode shows two stacked lanes, L above R, each a
  true view of its channel's content (an asymmetric-channel capture visibly
  differs between lanes).
- Mono mode shows exactly one lane. Switching modes updates the display
  accordingly.
- In stereo mode, waveform-riding overlays (envelope, markers, loop region if
  present) render once at full stacked height — no duplicated per-lane copies
  — and stay legible across both lanes.
- No per-channel controls appear; every edit applies identically to both
  channels (linked stereo processing, one editor).

---

## 8 — Enhancement: staged-overlay release anchoring; the Pitch AD becomes AHD *(his 3, second)*

**Daniel's ask (verbatim, 2026-07-28).**

> AHDSR visual overlay looks odd, not taking up the whole range.  with no
> release, the sustain portion only travels accross a small portion of the
> panel, making the thing look off center.  to resolve, the release segment
> should be anchored to the right, and draggable from the top node (connecting
> to sustain segment) instead of the bottom corner, which will now be anchored.
> All staged envelope overlays should follow this policy.

**Daniel's follow-up (verbatim, 2026-07-28).**

> 8) For the AD... make it AHD, and the combined A H and D segment lengths
> (time displacement) cannot exceed the full sample length.  Hold goes from 0
> to 100%, and the visual overlay for the envelope is then 1:1 scale with the
> waveform time.  D is not release, so it is not right anchored.

**Intent.** A layout-policy change to the staged envelope overlay so it uses
the full panel width: today, with little or no release, the sustain portion
occupies only a small stretch and the whole figure reads off-center. The
follow-up round grew this item beyond layout: it now also carries **the spec
change that turns the pitch envelope from AD into AHD**.

**Behavior.**

- The **release segment anchors to the right edge** of the overlay.
- Release is dragged from its **top node** — the node joining sustain to
  release — instead of the bottom corner. The bottom corner (the envelope's
  end point) becomes **fixed/anchored**, not draggable.
- **The policy applies to the envelopes that have a release** — the amp AHDSR
  today and the filter AHDSR when item 2 lands. **It does not apply to the
  pitch envelope: D is not a release stage, so it is not right-anchored.**
  *(Settled by follow-up — this closes the prior open question about mapping
  the policy onto the pitch envelope: the answer is that the policy does not
  apply there; the envelope gains a Hold stage instead.)*
- **Spec change: the pitch envelope becomes AHD.** The Pitch AD gains a
  **Hold** stage: **Attack → Hold → Decay**. *(Settled by follow-up — a spec
  change, not a clarification. The doc's own prose — here and item 1's
  sloped-segment reading — is updated to match; Daniel's verbatim asks stay
  as written.)*
  - **Hold ranges 0 to 100%.** Of *what* is unstated — see Open questions.
  - **A + H + D combined cannot exceed the sample length:** the three segment
    lengths' total time displacement is hard-bounded by the full sample
    length.
  - **Because of that bound, the pitch-envelope overlay is 1:1 scale with the
    waveform time axis** — the drawn envelope maps directly onto the
    displayed sample's time.
- **Cross-references.** Item 1 reworks this same overlay surface (radio
  switch, mid-segment curve knots, recolor) — this item is cheapest folded
  into or immediately after that work; item 1's sloped-segment rule reads
  Attack and Decay for the pitch AHD (Hold is flat, no curve dial). Item 3's
  Spline overlays are unaffected by construction: a spline always spans the
  full sample width already.

**Open questions.**

- **Hold's 0–100% — percent of what?** Daniel did not say: the full sample
  length, the time remaining after Attack, or something else. A narrow Daniel
  call — do not assume at implementation.
- **Are the 1:1-overlay property and the A+H+D ≤ sample-length bound
  pitch-specific, or intended for all staged envelopes?** Daniel stated both
  in the pitch-AHD context. An AHDSR with a right-anchored release cannot be
  strictly 1:1 across an indefinite sustain, so the two policies appear to
  coexist (right-anchoring for envelopes with a release; the 1:1 time-bounded
  overlay for the pitch AHD) rather than merge — but that is an open reading
  to confirm, not a settled conclusion.

**Acceptance criteria.**

- With release at zero or minimum, the sustain segment extends to (near) the
  right edge — the overlay reads full-width, not bunched left.
- Dragging the sustain→release top node adjusts release; the bottom-right
  corner is fixed and not draggable.
- The envelopes with a release (amp, and filter once present) follow the same
  anchoring policy; the pitch envelope's Decay is **not** right-anchored.
- The pitch envelope plays and displays three stages — Attack, Hold, Decay —
  with Hold spanning 0–100% of its (to-be-confirmed) reference; no
  combination of A, H, and D settings yields a combined time displacement
  exceeding the sample length.
- The pitch-envelope overlay is 1:1 with the waveform's time axis: a stage
  boundary at N seconds sits over the waveform at N seconds.

---

## 9 — Bug + Enhancement: loop points — suspected regression, and the Gate-mode loop-sustain spec *(his 4, second)*

**Daniel's ask (verbatim, 2026-07-28).**

> I think loop points got lost.  ideally if in gate mode we have a loopable
> section with parameterized start end points and parameterized crossfade on
> reset, which will function as the sustain for indefinite playback until note
> off and release.

**This item is both** a regression report and a feature spec, and is recorded
as both.

**Regression half (Bug).** Daniel's observation: loop points appear to have
been lost. Whether they were genuinely removed from playback or are merely
unexposed in the current UI is a code question that **cannot be answered here**
under the no-code-reads constraint — it must be verified as the first act of
implementation, not guessed in this document.

**Feature half (Enhancement — spec as given).** In **Gate mode**: a loopable
section with **parameterized start and end points** and a **parameterized
crossfade on loop reset**. The loop functions as the sustain — indefinite
playback cycling the loop until note-off, then release.

- **Cross-reference item 3.** Gate mode is unavailable while a Spline EG is
  active (settled), so loop-sustain is a **Staged/Gate-mode feature**; Spline
  mode remains full-sample-length playback with no loop.

**Open questions.**

- The regression verification above (removed vs. unexposed).
- The crossfade parameter's units and range are unspecified — Daniel call, or
  a proposed default surfaced at implementation review.
- Storage side: presumably per-zone alongside the other playback parameters
  (Sample/Zone panel parity, with VOICE/MASTER the per-instance exceptions) —
  confirm.
- Editing surface for loop start/end (waveform markers, knobs, or both) is
  unspecified; the waveform display is the natural home for range markers, but
  Daniel has not said.

**Acceptance criteria.**

- In Gate mode with a loop defined, a held note sustains indefinitely, audibly
  cycling the loop section; note-off exits into the release stage.
- With a nonzero crossfade, the loop seam is smooth — no click at the loop
  reset; crossfade length audibly follows its parameter.
- Loop start, end, and crossfade are user-parameterized, editable, and
  persisted across save/reload.
- Whatever the regression finding, the end state is loop points exposed and
  functional per this spec.

---

## 10 — Enhancement: knob and label sizing, ms units, double-click reset *(his 5)*

**Daniel's ask (verbatim, 2026-07-28).**

> Radial knobs and text labels are too small.  The labels for time constants
> should be in ms not seconds.  double clicking any radial knob resets to
> default (applies to the dual-ring radial knobs as individual sections)

**Behavior.**

- Radial knobs and their text labels grow — both are currently too small. No
  target size was given; this is a visual-judgment change accepted by eye.
- Time-constant labels display in **ms, not seconds**. (A display-unit change;
  this spec makes no claim about internal representation.)
- **Double-click on any radial knob resets it to its default value.**
- On item 1's **dual-ring knobs, each ring is its own reset target**:
  double-click on the outer ring resets the time/level value; double-click on
  the inner curve dial resets the exponent to 1.0 (the settled linear
  neutral) — each independently, without touching the other ring.
- **Cross-reference item 1** (introduces the dual-ring knobs this refines).

**Open questions.**

- None beyond the sizing being judged by eye (see acceptance).

**Acceptance criteria.**

- Knobs and labels are legibly larger; Daniel signs off on the result by eye.
- Every time-constant label reads in ms.
- Double-click resets any radial knob to its default; on dual-ring knobs,
  double-clicking the inner dial resets only the exponent (to 1.0) and
  double-clicking the outer ring resets only the value.

---

## 11 — Enhancement: preview glyph; VELOCITY deck for velocity-curve buttons; bipolar pitch/filter curves *(his 6)*

**Daniel's ask (verbatim, 2026-07-28).**

> Preview button inner text should go and be replaced with an appropriate
> glyph of your choosing (no dependencies just load a bitmap staticly or
> something, whatever plays nice with LICE.  Amp velocity curve button moves
> to the master section.  pitch velocity curve goes in the pitch section.
> filter velocity curve button goes in the filter section.  filter and pitch
> velocity transfer functions default to y=0 and y range is [-1,1] (where as
> amp stays unipolar at [0,1]).

**Daniel's follow-up (verbatim, 2026-07-28).**

> 11) actually, that is a real contention point... MASTER is for other things,
> post voice mixer (I will add to this later).  The velocity popup buttons
> should all go together in a new control deck group labelled VELOCITY, to the
> left of VOICE

**Behavior.**

- **Preview glyph.** The preview button's inner text is replaced with a glyph.
  Proposed (product level): a right-pointing **play triangle** — the universal
  "audition" read. Daniel's constraint: **no new dependencies** — a statically
  embedded bitmap or equivalent that plays nicely with the existing drawing
  path is fine.
- **Velocity-curve button placement — the VELOCITY deck.** All three
  velocity-curve popup buttons (amp, pitch, filter) live **together in a new
  control deck group labelled "VELOCITY", placed to the left of the VOICE
  group**. *(Settled by follow-up.)* Note for readers of the prior revision:
  this **supersedes the original ask's per-section placement** (amp → MASTER,
  pitch → PITCH, filter → Filter). Daniel confirmed the MASTER placement was
  a real contention point — **MASTER is reserved for other, post-voice-mixer
  concerns** (he will add to it later), so the velocity curves do not belong
  there.
- **Storage stays per-zone.** The velocity transfer curves are stored
  **per-zone**, with the other playback parameters — Sample/Zone panel parity
  applies. *(Derived, not a Daniel quote: the storage doubt existed only
  because the proposed MASTER placement implied per-instance storage; with
  the buttons in their own VELOCITY group that doubt is gone, and the
  project's settled convention — playback parameters are per-zone, VOICE and
  MASTER the per-instance exceptions — decides it.)*
- **Bipolar pitch/filter transfer functions.** Pitch and filter velocity
  transfer functions are **bipolar: y range [−1, 1], default y = 0** — flat at
  zero, meaning velocity modulation of pitch and filter is **off until the
  user draws a curve**. **Amp stays unipolar at [0, 1]**, and its existing
  flat default (every velocity → unity) is unchanged.
- **Cross-references.** Item 2 introduces the filter's velocity modulation —
  this item specifies that curve's domain and default, and homes its button
  in the VELOCITY deck. Item 3's shared spline editor serves these curves, so
  it must render and edit a **bipolar y-domain** for pitch and filter
  alongside the amp curve's unipolar one.

**Open questions.**

- Whether a user-facing pitch velocity transfer curve already exists or is
  introduced by this item — unverifiable here under the no-code-reads
  constraint; if absent, this item introduces it. (The former second question
  — amp-curve storage under the MASTER placement — dissolved with the
  placement's supersession; storage is settled per-zone above.)

**Acceptance criteria.**

- The preview button shows the glyph (no text) and stays legible in all
  interaction states; no new build or runtime dependency is introduced.
- The three velocity-curve buttons sit together in a deck group labelled
  **VELOCITY**, immediately to the left of the VOICE group; no velocity-curve
  button appears in MASTER, PITCH, or Filter.
- The velocity curves follow Sample/Zone panel parity and persist per-zone
  (two zones with different curves audibly differ).
- Opening the pitch or filter curve shows a bipolar editor ([−1, 1]) defaulted
  flat at y = 0; played velocities produce no pitch/filter modulation until a
  curve is drawn, then audibly follow it.
- The amp curve's domain ([0, 1]) and flat-unity default are unchanged.

---

## 12 — Enhancement: top toolbar cleanup; full-width piano strip; uniform keys; note-name tooltips *(his 7)*

**Daniel's ask (verbatim, 2026-07-28).**

> top toolbar text font should be cleaned up to match, and the zone count
> label is not needed in the title.  next to the browse and zoom buttons, we
> can move the preview and mono stereo controls, in order to allow the note
> range piano roll control to take up full width.  also we need to clean up
> the piano key pattern, idk if it's pixel aliasing but it looks like some
> keys are skinnier than others.  NOte value (C4, etc) should display in
> tooltip on hover over the piano notes.

**Behavior.**

- **Font cleanup.** One consistent font treatment across the top toolbar text.
- **Zone count label removed** from the title.
- **Preview and mono/stereo controls relocate** next to the browse and zoom
  buttons, freeing the **note-range piano strip to take the full width**.
- **Uniform piano keys.** Some keys currently render skinnier than others —
  Daniel suspects pixel aliasing, but the requirement stands regardless of
  cause: keys of the same class render at uniform width. (No cause analysis
  here.)
- **Note-name tooltips.** Hovering a piano key shows its note value (C4 etc.,
  DAW convention), following the instrument's existing tooltip conventions
  where they apply.
- **Cross-references.** Item 11 also changes the preview button (glyph); the
  two compose — the glyph button in its new toolbar position. Item 13's
  anti-aliasing audit covers the key-pattern rendering if aliasing turns out
  to be the cause.

**Acceptance criteria.**

- Top toolbar text renders in one consistent font treatment; the title carries
  no zone count.
- Preview and mono/stereo sit adjacent to browse/zoom; the piano strip spans
  the full editor width.
- Same-class keys are equal pixel width at any window width and DPI scale.
- Hovering any piano key shows its note name in a tooltip.

---

## 13 — Enhancement (audit): antialiased rendering for high-DPI *(his 8)*

**Daniel's ask (verbatim, 2026-07-28).**

> We should finally review to make sure we are rendering with some kind of
> antialiasing equivalent for high DPI high res clean rendering.  It still
> looks pixely in places (radial arcs, waveform lines, env segment slopes)

**Intent.** A review pass, not a point fix: audit the editor's drawn surfaces
and confirm they render with antialiasing (or an equivalent) suitable for
high-DPI, high-resolution displays. Daniel named the visibly pixely surfaces:
**radial arcs, waveform lines, envelope segment slopes**.

**Behavior.**

- Audit each class of drawn surface; where one renders visibly aliased, bring
  it to the smooth standard. The outcome is observable, not procedural: the
  named surfaces (and any others the audit turns up) render without visible
  stair-stepping.
- **Sequencing observation** (not a decision): this touches nearly every
  surface items 1, 3, 7, 8, 10, 11, and 12 repaint — running it after the
  layout/knob work likely avoids doing the polish twice.

**Acceptance criteria.**

- Radial arcs (including item 1's inner dials), waveform lines (including
  item 7's stereo lanes), and envelope segment slopes (staged and spline)
  render smooth — no visible jaggies at 100% scale or on a high-DPI display.
- The audit produces a short disposition list: surfaces checked, which needed
  work, which were already clean.
- Daniel signs off by eye on the named surfaces.
