docs: close out Ξ-W1-T1, Ξ-W1-T2 and Θ-W3-T1 into COMPLETED; map the note directory; document the Release build
This commit is contained in:
@@ -228,3 +228,88 @@ uniform key widths, note-name tooltips, root displayed and settable.
|
||||
carries a "confirm the fix survives DPI scaling" item and now genuinely inherits it.
|
||||
- A stale-hover latch was fixed across **all** drag kinds and both drag-termination
|
||||
paths, wider than the strip work that surfaced it.
|
||||
|
||||
### Θ-W3-T1 — live-parameter-delivery
|
||||
|
||||
Continuous playback controls are now delivered live to sounding voices instead of being
|
||||
latched at note-on. New `src/core/instrument/engine/live_params.{h,cpp}` holds a
|
||||
seqlock-published `LiveValues` block owned at **processor-instance scope**, above
|
||||
`LoadedInstrument`, so `live_` and `draining_` observe the same one (a drain-slot voice
|
||||
tracks the knob, which is the desired behavior). `foldLive(const PlayParams&)` is the
|
||||
single derivation from the value type; `PlayParams` stays a plain copyable value type.
|
||||
|
||||
**Daniel's two decisions, both implemented:**
|
||||
- **Reload tier = Grouping B.** Continuous knobs live (filter cutoff/Q/morph/drive/mod
|
||||
amount/key-track; every stage time and level on all three envelopes). Root note, loop
|
||||
span, and start frame still trigger a full reload.
|
||||
- **Mid-stage rule = candidate (iv), hold normalized stage position.** φ =
|
||||
elapsed/duration held fixed across a duration change, then advancing at
|
||||
1/newDuration — expressed over normalized position specifically so Θ-W3-T2's
|
||||
per-segment curve exponent composes with it.
|
||||
|
||||
**Deviations from spec:**
|
||||
- **Trigger's %-length and fades are NOT live** — they are baked into `SampleData` at
|
||||
build, so reload is the only tier that can deliver them. Consequence: a Trigger-mode
|
||||
instance gets zero live amp delivery until Θ-W3-T2 folds the fade pair into the AHD.
|
||||
The five non-live exclusions (`kKeyTrack`, `kFilterVel`, `kTrigLength`,
|
||||
`kTrigFadeIn`, `kTrigFadeOut`) are documented in `src/core/instrument/ui/deck_groups.h`,
|
||||
now their single home.
|
||||
- Open question 3 resolved as **F2 + seqlock**; open question 4 (sub-block resolution)
|
||||
was not built but not foreclosed — the writer interface assumes no UI thread; open
|
||||
question 5 verified — a live edit still persists, `commitLive` keeps the
|
||||
`setInstrumentParams` write.
|
||||
- A filter envelope only advances while its depth is non-zero (the exact-skip at
|
||||
`modAmount == 0`), which is what keeps the at-rest path byte-identical.
|
||||
|
||||
### Ξ-W1-T1 — tracking-consolidation
|
||||
|
||||
Consolidates the provenance/usage territory into one system: the retired
|
||||
`owned_manifest` gives way to a new `src/core/tracking/` directory holding
|
||||
`origin_ledger` (the record family — `OriginRecord`/`OriginKind`, the insertion-ordered
|
||||
`OriginLedger`, its JSON codec, and the `Fresh`/`Loaded`/`Unreadable`/`FutureVersion`
|
||||
load classification) and `tracking_authority` (the one decision surface:
|
||||
`pruneProtection` and `tiedUsageExists`). Both prune's protected set and the resample's
|
||||
replace-vs-add decision are computed from one borrowed `TrackingState`, so the two
|
||||
safety-critical consumers cannot drift apart. `isAbsolutePath` was hoisted out to a new
|
||||
`src/core/util/relative_path.h`, shared with `bank_model`'s `Sample.relativePath`.
|
||||
|
||||
**Deviations from spec:**
|
||||
- The deferred persisted-instance-identity fix was **not** folded in — open question 5
|
||||
resolved as "restate the deferral." `docs/TODO.md` already carries the sharpened
|
||||
rationale (the session-epoch candidate and its sibling-drop flaw); not duplicated here.
|
||||
- `sample_usage` deliberately **stays in `core/wire`** — the consolidation is of the
|
||||
*decisions*, not the codecs.
|
||||
- A realtime record interrupted by a project switch strands an untracked WAV in the old
|
||||
project's bank folder. Resolved as document-don't-delete (prune is the exclusive
|
||||
deletion authority); `docs/TODO.md` carries the entry.
|
||||
- `PruneReport` fields were renamed; a malformed ledger is now reported as a distinct
|
||||
blocker with its own recovery instructions.
|
||||
|
||||
### Ξ-W1-T2 — note-program-model
|
||||
|
||||
Lands the programmed-capture-signal model as a new pure module directory,
|
||||
`src/core/instrument/note/` — a fourth peer of `engine/`/`map/`/`ui/` under
|
||||
`core/instrument/` — holding `musical_division` (the 1/64–64/1 ladder with
|
||||
dotted/triplet multipliers, the 39-entry picker order), `tempo` (validated BPM plus
|
||||
every beats↔seconds↔ms conversion), and `note_program` (`Velocity`, the denominated
|
||||
`OffsetAmount`, the anchored `StartOffset`/`EndOffset`, the `NoteProgram` record, and
|
||||
`resolveNote`).
|
||||
|
||||
**Deviations / resolutions from spec:**
|
||||
- Open question "negative offsets" resolved: both directions are legal and the sign is
|
||||
uniform (positive is later in time); only an *inverted* window is refused, reported
|
||||
via `ResolvedNote::windowCollapsed`.
|
||||
- Open question "denomination seam" confirmed: note length is musical-division-only;
|
||||
the ms/beats duality belongs to the offsets alone. An offset stores the denomination
|
||||
it was **entered in**, deriving the other view on demand, so a beats offset follows a
|
||||
tempo change and a ms offset holds still.
|
||||
- Module name/location resolved as `src/core/instrument/note/` — three modules, not
|
||||
one, with the layering enforced by the CMake link line.
|
||||
- **Beyond spec:** every value type closes its domain at construction behind a single
|
||||
normalizing door (`makeDivision`, `offsetOf`, `Tempo::fromBpm`, `Velocity::of`), with
|
||||
private value constructors. Consequence: `resolveNote` needs no failure path and
|
||||
`ResolvedNote` no validity flag, because every returned field is finite for every
|
||||
constructible program and tempo. Junk detection is relocated to the future codec,
|
||||
which sees both the bytes it read and the value construction produced. `NoteProgram`
|
||||
deliberately carries no MIDI note number — render pitch is deferred to Ξ-W2 as an
|
||||
additive field.
|
||||
|
||||
Reference in New Issue
Block a user