From a4571cc0745972e535d7a98bbe8de17066b16d31 Mon Sep 17 00:00:00 2001 From: daniel-c-harvey Date: Tue, 28 Jul 2026 18:44:41 -0400 Subject: [PATCH] =?UTF-8?q?docs(TODO-1.0):=20fold=20in=20Daniel's=20answer?= =?UTF-8?q?s=20=E2=80=94=20radio=20none-state,=20knot=20curve-drag,=20Filt?= =?UTF-8?q?er=20ranges/label,=20dual-state=20Spline=20EGs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TODO-1.0.md | 176 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 118 insertions(+), 58 deletions(-) diff --git a/TODO-1.0.md b/TODO-1.0.md index 3de84d9..96e28f8 100644 --- a/TODO-1.0.md +++ b/TODO-1.0.md @@ -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 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 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. @@ -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 > 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 shared graphical surface for every envelope in the instrument, and give every 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 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. + 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 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 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 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 @@ -63,30 +86,28 @@ contrast failure. **Open questions.** -- **Radio exclusivity + default.** "Radio" implies exactly one envelope is - overlay-active at a time across all decks — confirm that reading, and - confirm the Amp AHDSR remains the default selection on open. -- **Which segments are "sloped."** Per envelope type, which segments carry a - curve dial? (E.g. Attack/Decay/Release obviously slope; Hold and Sustain - presumably do not — needs Daniel's confirmation per stage.) -- **Curve default and neutral point.** Is exponent 1.0 the linear/neutral - default, and should existing saved instances load with all curves at the - 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. +- **Default overlay selection on open.** Exclusivity and the none-state are + settled; what is the default when the editor opens — the Amp AHDSR (today's + behavior) or none? +- **Pre-existing instances.** Should saved instances from before this change + load with every curve at the linear equivalent (exponent 1.0) so their sound + is unchanged? (The neutral point itself is settled; this is only the + load-behavior half. The product requirement is "old instances sound + identical.") **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. + 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 hover accent, needle, numeric label); sweeping it through 0.1 → 10 visibly 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 against the primary green waveform. - 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 > 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 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. @@ -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, 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.)* +- **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.** -- **Mode list.** Is mode a discrete selector, and over exactly which entries? - "Resonant high and lowpass" confirms HP and LP; whether band-pass/notch or - multiple slopes exist depends on the Cortex-M4 source and Daniel's intent. -- **Ranges and units.** Cutoff range (Hz), Q range, and mod-amt range/polarity - (unipolar or bipolar?) are unstated — likely settled by the Cortex-M4 code - plus a Daniel call at implementation time. -- **Mod routing.** "Mod amt" presumably scales the filter AHDSR's modulation of - 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? +- **Other mod sources.** Mod amt targeting cutoff is settled; whether any + other mod sources (velocity, key-tracking) are in scope now or deferred is + unstated. +- **Parameter storage: per-zone or per-instance.** Per-voice *processing* is + settled, but it is compatible with either storage side. Existing playback + parameters live per-zone with Sample/Zone panel parity; VOICE and MASTER are + per-instance exceptions. Which side do the filter *parameters* fall on? - **Neutral default.** Should the filter default to a bypass/neutral state so pre-existing saved instances (and freshly loaded captures) sound unchanged until the user engages it? -- **Display name.** Is "MM Preamp Filter" the user-facing label for the deck - group, or working shorthand? **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 the amp envelope still shapes the filtered result (audible ordering: pitch → filter → amp). -- Mode, cutoff, Q, and mod-amt controls appear in a filter deck group; the - filter AHDSR gets the full item-1 treatment (curve inner dials, corner radio - switch, tertiary-purple overlay editing). +- 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). - The deck row reads pitch → filter → amp left-to-right. - A project saved before this change reopens sounding identical (pending the 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 > (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 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 @@ -189,6 +240,22 @@ so sharp corners are possible, not everything smoothed. - **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.)* +- **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 @@ -210,30 +277,17 @@ so sharp corners are possible, not everything smoothed. **Open questions.** -- **Staged↔Spline toggle semantics.** What happens to a Staged EG's values - when toggling to Spline mode and back? (Convert the staged shape into an - initial spline? Keep two independent per-mode states? Discard?) Daniel has - not said — this materially shapes both UX and persistence and needs his - 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. +- **Time-axis storage.** Full-sample coverage is settled ("spline always + covers the full sample length"); what remains is only whether the stored + contour is normalized to the sample length (so it rescales when a + different-length capture loads) or anchored some other way. - **Point-editing grammar.** Point add/delete gestures and any point-count bound are unstated. The velocity-curve popup already established right-click 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 - segment knobs/inner dials go inert (shape comes wholly from the spline), or - is some hybrid intended? Presumably the former — confirm. +- **Staged controls while Spline is active.** Sound-wise the staged EG is + inactive in Spline mode (settled by dual-state). Still open at the UI level: + 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.** @@ -245,8 +299,14 @@ so sharp corners are possible, not everything smoothed. adjacent segment, and the discontinuous slope is audible where the 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 - 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 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).