docs(TODO-1.0): fold in Daniel's answers — radio none-state, knot curve-drag, Filter ranges/label, dual-state Spline EGs

This commit is contained in:
2026-07-28 18:44:41 -04:00
parent b06b226182
commit a4571cc074
+118 -58
View File
@@ -9,6 +9,12 @@ 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 as the source of truth, then breaks it into behavior, open questions, and an
observable acceptance gate. 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**.
Ordering note: item 1's curve/overlay treatment explicitly anticipates item 2's 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 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. in sequence or together, but 1 and 2 are prerequisites for 3's full surface.
@@ -34,6 +40,12 @@ in sequence or together, but 1 and 2 are prerequisites for 3's full surface.
> contrasts poorly against the primary green waveform display. Change those to > contrasts poorly against the primary green waveform display. Change those to
> tertiary purple. > 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.
**Intent.** Grow the envelope-overlay editor from an amp-only fixture into the **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 shared graphical surface for every envelope in the instrument, and give every
envelope shapeable (non-linear) segments — while fixing the blue-on-green envelope shapeable (non-linear) segments — while fixing the blue-on-green
@@ -46,11 +58,22 @@ contrast failure.
gains a radio switch in the corner of its deck. Selecting a deck's radio 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 makes *that* envelope the one displayed and editable in the graphic waveform
overlay — replacing today's behavior where the Amp AHDSR is always the overlay — replacing today's behavior where the Amp AHDSR is always the
displayed envelope. 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.)*
- **Segment curve values on all envelopes.** Amp AHDSR, Pitch AD, and Filter - **Segment curve values on all envelopes.** Amp AHDSR, Pitch AD, and Filter
AHDSR all gain an editable curve value per *sloped* segment. The curve is an AHDSR all gain an editable curve value per *sloped* segment. The curve is an
exponential function; the per-segment parameter is the exponent scalar, exponential function; the per-segment parameter is the exponent scalar,
range **0.1 to 10**. 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 AD, both stages.
*(Settled by follow-up.)*
- **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 - **Inner dial on curvable-segment knobs.** Every knob-deck radial knob that
controls a sloped, curvable segment gains an **inner dial**: its own inner 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 arc, its own hover accent (tertiary purple), its own needle, and its own
@@ -63,30 +86,28 @@ contrast failure.
**Open questions.** **Open questions.**
- **Radio exclusivity + default.** "Radio" implies exactly one envelope is - **Default overlay selection on open.** Exclusivity and the none-state are
overlay-active at a time across all decks — confirm that reading, and settled; what is the default when the editor opens — the Amp AHDSR (today's
confirm the Amp AHDSR remains the default selection on open. behavior) or none?
- **Which segments are "sloped."** Per envelope type, which segments carry a - **Pre-existing instances.** Should saved instances from before this change
curve dial? (E.g. Attack/Decay/Release obviously slope; Hold and Sustain load with every curve at the linear equivalent (exponent 1.0) so their sound
presumably do not — needs Daniel's confirmation per stage.) is unchanged? (The neutral point itself is settled; this is only the
- **Curve default and neutral point.** Is exponent 1.0 the linear/neutral load-behavior half. The product requirement is "old instances sound
default, and should existing saved instances load with all curves at the identical.")
linear-equivalent so their sound is unchanged? (Persistence extension is
implied; the product requirement is only "old instances sound identical.")
- **Curve editing in the overlay.** Is the curve exponent editable *from the
overlay itself* (e.g. dragging a segment's belly), or is the inner dial the
sole curve-edit affordance and the overlay edits node positions only?
Daniel's ask specifies the dial; overlay curve-drag is not stated either way.
**Acceptance criteria.** **Acceptance criteria.**
- Each envelope deck shows a corner radio switch; activating one puts that - Each envelope deck shows a corner radio switch; activating one puts that
envelope in the overlay, editable there, and the overlay tracks the switch envelope in the overlay, editable there, and the overlay tracks the switch
immediately. immediately. At most one envelope is overlay-active; with none active, the
overlay draws no envelope.
- Every curvable-segment knob shows the inner dial (inner arc, tertiary-purple - Every curvable-segment knob shows the inner dial (inner arc, tertiary-purple
hover accent, needle, numeric label); sweeping it through 0.1 → 10 visibly hover accent, needle, numeric label); sweeping it through 0.1 → 10 visibly
reshapes the overlay segment and audibly reshapes the envelope on played reshapes the overlay segment and audibly reshapes the envelope on played
notes. 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 - Overlay envelope segments render in tertiary purple and are clearly legible
against the primary green waveform. against the primary green waveform.
- A project saved before this change reopens with unchanged audible envelope - A project saved before this change reopens with unchanged audible envelope
@@ -105,6 +126,13 @@ contrast failure.
> mod amt, then the AHDSR controls as described above. The knob deck row will > 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 > 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"
**Intent.** Add the instrument's first filter stage — resonant high-pass and **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 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. AHDSR envelope, and make the knob-deck row read in signal-flow order.
@@ -120,28 +148,35 @@ AHDSR envelope, and make the knob-deck row read in signal-flow order.
- **Parameters.** Mode, cutoff, Q, and mod amt — then the AHDSR controls, - **Parameters.** Mode, cutoff, Q, and mod amt — then the AHDSR controls,
treated exactly as item 1 specifies (curvable sloped segments with inner treated exactly as item 1 specifies (curvable sloped segments with inner
dials, overlay editability via the filter deck's radio switch). 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.)*
- **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: - **Deck reorder.** The knob deck row is relaid out in signal-flow order:
**pitch → filter → amp**. **pitch → filter → amp**.
**Open questions.** **Open questions.**
- **Mode list.** Is mode a discrete selector, and over exactly which entries? - **Other mod sources.** Mod amt targeting cutoff is settled; whether any
"Resonant high and lowpass" confirms HP and LP; whether band-pass/notch or other mod sources (velocity, key-tracking) are in scope now or deferred is
multiple slopes exist depends on the Cortex-M4 source and Daniel's intent. unstated.
- **Ranges and units.** Cutoff range (Hz), Q range, and mod-amt range/polarity - **Parameter storage: per-zone or per-instance.** Per-voice *processing* is
(unipolar or bipolar?) are unstated — likely settled by the Cortex-M4 code settled, but it is compatible with either storage side. Existing playback
plus a Daniel call at implementation time. parameters live per-zone with Sample/Zone panel parity; VOICE and MASTER are
- **Mod routing.** "Mod amt" presumably scales the filter AHDSR's modulation of per-instance exceptions. Which side do the filter *parameters* fall on?
cutoff — confirm the target is cutoff and whether any other mod sources
(velocity, key-tracking) are in scope now or deferred.
- **Scope: per-zone or per-instance.** Existing playback parameters live
per-zone with Sample/Zone panel parity; VOICE and MASTER are per-instance
exceptions. Which side does the filter fall on?
- **Neutral default.** Should the filter default to a bypass/neutral state so - **Neutral default.** Should the filter default to a bypass/neutral state so
pre-existing saved instances (and freshly loaded captures) sound unchanged pre-existing saved instances (and freshly loaded captures) sound unchanged
until the user engages it? until the user engages it?
- **Display name.** Is "MM Preamp Filter" the user-facing label for the deck
group, or working shorthand?
**Acceptance criteria.** **Acceptance criteria.**
@@ -149,11 +184,18 @@ AHDSR envelope, and make the knob-deck row read in signal-flow order.
pipeline point: the filter acts on pitched (post-pitch-envelope) signal, and pipeline point: the filter acts on pitched (post-pitch-envelope) signal, and
the amp envelope still shapes the filtered result (audible ordering: the amp envelope still shapes the filtered result (audible ordering:
pitch → filter → amp). pitch → filter → amp).
- Mode, cutoff, Q, and mod-amt controls appear in a filter deck group; the - Mode, cutoff, Q, and mod-amt controls appear in a deck group labeled
filter AHDSR gets the full item-1 treatment (curve inner dials, corner radio **"Filter"**; the filter AHDSR gets the full item-1 treatment (curve inner
switch, tertiary-purple overlay editing). 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 - High Q audibly emphasizes the cutoff region (resonance) in both HP and LP
modes. modes.
- Two simultaneously sounding voices at different envelope phases are filtered
independently (per-voice processing is audible, not a shared instance-wide
filter).
- The deck row reads pitch → filter → amp left-to-right. - The deck row reads pitch → filter → amp left-to-right.
- A project saved before this change reopens sounding identical (pending the - A project saved before this change reopens sounding identical (pending the
neutral-default confirmation above). neutral-default confirmation above).
@@ -180,6 +222,15 @@ AHDSR envelope, and make the knob-deck row read in signal-flow order.
> for the velocity-amp transfer curve as well as the pitch, filter, and amp EGs > for the velocity-amp transfer curve as well as the pitch, filter, and amp EGs
> (if they are in spline mode). > (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.
**Intent.** Offer a free-drawn alternative to every staged envelope: the user **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 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 the monotonic-spline machinery already proven by the velocity curve — enhanced
@@ -189,6 +240,22 @@ so sharp corners are possible, not everything smoothed.
- **Mode toggle per EG.** Every processor that has an envelope (pitch, filter, - **Mode toggle per EG.** Every processor that has an envelope (pitch, filter,
amp) can switch its Staged EG to a **Spline EG**. 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.)*
- **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 - **Spline foundation.** The Spline EG is based on the monotonic splines used
for the velocity curve. The spline algorithm is singly implemented and for the velocity curve. The spline algorithm is singly implemented and
multi-referenced; the enhancement below applies to that one implementation multi-referenced; the enhancement below applies to that one implementation
@@ -210,30 +277,17 @@ so sharp corners are possible, not everything smoothed.
**Open questions.** **Open questions.**
- **Staged↔Spline toggle semantics.** What happens to a Staged EG's values - **Time-axis storage.** Full-sample coverage is settled ("spline always
when toggling to Spline mode and back? (Convert the staged shape into an covers the full sample length"); what remains is only whether the stored
initial spline? Keep two independent per-mode states? Discard?) Daniel has contour is normalized to the sample length (so it rescales when a
not said — this materially shapes both UX and persistence and needs his different-length capture loads) or anchored some other way.
call.
- **Gate-mode sustain/release.** A Staged Gate envelope holds at Sustain and
releases on note-off; a spline contour drawn "over the full sample length"
is a pure time function. How do note-off, sustain, and looped playback map
onto a Spline EG in Gate mode? (Trigger/one-shot is the natural fit; Gate
needs a stated rule.)
- **Time axis.** Is the contour's time axis normalized to the sample length
(so it rescales with the sample) or absolute seconds? "Over the full sample
length" suggests sample-relative — confirm, especially for looped sustain.
- **Monotonicity meaning.** The velocity spline is monotone to prevent
overshoot on a transfer curve. An EG contour must rise and fall; presumably
"monotonic" here means the per-segment no-overshoot property (values never
exceed the segment's endpoints), not a globally monotone function — confirm
the intended guarantee.
- **Point-editing grammar.** Point add/delete gestures and any point-count - **Point-editing grammar.** Point add/delete gestures and any point-count
bound are unstated. The velocity-curve popup already established right-click bound are unstated. The velocity-curve popup already established right-click
node delete — reuse of that grammar seems natural but is Daniel's call. node delete — reuse of that grammar seems natural but is Daniel's call.
- **Interaction with item-1 curve dials.** In Spline mode, do the staged - **Staged controls while Spline is active.** Sound-wise the staged EG is
segment knobs/inner dials go inert (shape comes wholly from the spline), or inactive in Spline mode (settled by dual-state). Still open at the UI level:
is some hybrid intended? Presumably the former — confirm. do the staged segment knobs/inner dials stay editable (editing the dormant
staged state) or go inert/greyed until the user switches back?
**Acceptance criteria.** **Acceptance criteria.**
@@ -245,8 +299,14 @@ so sharp corners are possible, not everything smoothed.
adjacent segment, and the discontinuous slope is audible where the adjacent segment, and the discontinuous slope is audible where the
modulation target makes it so (e.g. a pitch EG corner). modulation target makes it so (e.g. a pitch EG corner).
- A contour of several segments joined at hard points plays back over the full - A contour of several segments joined at hard points plays back over the full
sample length exactly as drawn. 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.
- 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 - The velocity→amp transfer-curve editor supports the same control-click
hard/smooth toggle with identical rendering behavior. hard/smooth toggle with identical rendering behavior.
- Staged↔Spline toggling behaves per the answered open question above (that
answer gates this item's completion definition).