Phase 26: add common parameter targets, step automation and MIDI control mapping
This commit is contained in:
parent
7bff7b535d
commit
901a536f10
38 changed files with 740 additions and 67 deletions
106
docs/CONTROL.md
106
docs/CONTROL.md
|
|
@ -1,7 +1,7 @@
|
|||
# Automation and expressive control (Phase 16)
|
||||
# Automation and expressive control (Phases 16 and 26)
|
||||
|
||||
Track Gain/Pan lanes in the Mixer apply to audio and scheduled instrument voices.
|
||||
They use absolute project ticks, linear interpolation, hold-first/last outside
|
||||
They use absolute project ticks, linear or hold interpolation, hold-first/last outside
|
||||
points and the constant project tempo snapshot. A clip trim/move does not move
|
||||
track or effect automation: lanes belong to the project timeline. Instrument
|
||||
volume is controlled by its track Gain lane; the current sine has no timbre
|
||||
|
|
@ -25,9 +25,9 @@ clock is called from the host audio path. Native ABI 2 callers continue to use
|
|||
sample-offset parameter events, applied before equal-offset MIDI events.
|
||||
|
||||
Live MIDI input maps CC7 to per-channel volume (0..1), CC10 to pan (64 center),
|
||||
and CC64 to sustain (>=64 down). Volume/pan ramp over 5 ms. These fixed mappings
|
||||
and CC64 to sustain (>=64 down). Volume/pan ramp over 5 ms. These default mappings
|
||||
apply to live sine voices, not track faders or prerecorded clips; controller
|
||||
capture, configurable learn and plugin MIDI are not supported. CC120/123 and
|
||||
capture, automatic learn and plugin MIDI are not supported. CC120/123 and
|
||||
Panic release all live voices and sustain and suppress already-started scheduled
|
||||
notes. Note-on velocity zero decodes to note-off. Repeated live note-on on one
|
||||
channel/pitch retriggers one voice; note-off releases it or marks it pending while
|
||||
|
|
@ -47,3 +47,101 @@ make test test-control test-plugins test-gui-plugins test-plugins-real
|
|||
|
||||
Physical controller devices and listening remain unqualified; no tempo map,
|
||||
latency compensation, MIDI capture, pitch bend or plugin crash isolation is added.
|
||||
|
||||
## Phase 26: common parameter targets
|
||||
|
||||
`xtc_control.h` identifies a parameter by `(kind, stable owner ID, parameter ID)`.
|
||||
IDs never mean a dense list index and are not DSP pointers:
|
||||
|
||||
| Kind | Owner | Parameter IDs | Metadata/reset defaults |
|
||||
| --- | --- | --- | --- |
|
||||
| TRACK | Track or mix-bus stable uint64 ID | 0 gain, 1 pan | Gain 0..4 linear, default 1; pan -1..1 balance, default 0 |
|
||||
| PLUGIN | LADSPA graph node ID | Actual input-control port | Descriptor name, bounds, default and discrete/logarithmic hints; units unspecified |
|
||||
| LIVE | MIDI channel 0..15 | 0 volume, 1 pan, 2 sustain | Volume 0..1 default 1; pan -1..1 default 0; sustain boolean default 0 |
|
||||
|
||||
`xtc_project_parameter` returns copied metadata, static configuration and whether
|
||||
a lane exists. LIVE values are reset defaults, not callback-owned controller
|
||||
readbacks. `xtc_project_set_parameter` changes TRACK/PLUGIN static configuration
|
||||
without deleting automation. `xtc_project_automate` sets/replaces/removes points
|
||||
for TRACK/PLUGIN through one C contract. LIVE static setters and timeline lanes
|
||||
are unsupported: these controls belong to incoming MIDI events, not the arranged
|
||||
instrument. Plugin metadata/control edits execute trusted discovery on the
|
||||
control thread; they never run inside audio. Model-only clients must compile and
|
||||
publish accepted snapshots before rendering; GUI edits do this transactionally.
|
||||
|
||||
Unknown owners/ports fail without touching the destination model/output. Missing
|
||||
plugin modules fail discovery rather than guessing ranges or installing a dummy.
|
||||
Track deletion removes its lanes; plugin deletion removes its embedded lanes.
|
||||
Compatible plugin replacement resets controls/automation as described in
|
||||
PLUGIN_HOSTING.md. Persisted dangling references reject the complete load;
|
||||
the current project remains intact. The GUI reports rejected edits/Open failures.
|
||||
|
||||
## Interpolation and precedence
|
||||
|
||||
The Mixer Interpolation chooser selects Linear or Hold (step) for the point
|
||||
being added/replaced. A point owns the segment beginning there. At a hold point,
|
||||
its value remains until the next point's exact sample. Linear segments interpolate
|
||||
between endpoint values without an extra smoothing stage. Hold first/last before/
|
||||
after the lane. Gain/pan for tracks and buses support both; integer/toggle LADSPA
|
||||
controls require hold. Existing files migrate mixer points to linear.
|
||||
|
||||
Automation is absolute project time, independent of clip starts, ends, trims,
|
||||
splits and moves; it neither restarts nor resets at a clip boundary. Tick-to-sample
|
||||
rounding uses the prepared constant tempo/rate; distinct ticks landing on the
|
||||
same sample choose the greatest tick. Empty lanes restore the static value.
|
||||
Static edits while a lane exists change the fallback value, not the audible lane.
|
||||
GUI changes stop/rebuild snapshots; live mutation of faders/plugin instances is
|
||||
not introduced. Plugin reset removes lanes only when explicitly applied.
|
||||
|
||||
At each sample, arranged track/bus and plugin lanes apply to their own targets.
|
||||
Incoming MIDI volume/pan/sustain affect only live sine voices on that channel,
|
||||
never those lanes or the static project controls. Equal-offset MIDI events run
|
||||
in input order before synthesis. A controller event then affects that sample's
|
||||
ramp; gain/pan reach the target over max(1, rate/200) frames. Sustain changes at
|
||||
the event sample. Panic CC120/123 remains reserved and also suppresses already
|
||||
started arranged notes according to the existing panic contract.
|
||||
|
||||
Seek/discontinuous positions clear live voices and runtime controllers to their
|
||||
reset values but retain prepared bindings. Arranged lanes evaluate directly at
|
||||
the new position. Backward jumps evaluate the earlier timeline again; tests
|
||||
exercise explicit wraps. There is no loop transport feature or promise to
|
||||
restore opaque LADSPA delay history across jumps (transport reset retains it).
|
||||
|
||||
## Configurable live MIDI bindings
|
||||
|
||||
Audio → MIDI controller mapping lists the current 16 channels. Enter
|
||||
`channel volume_CC pan_CC sustain_CC`, for example `2 1 74 11`. Channels are
|
||||
zero-based; CCs are 0..127, or 128 to disable a target. Enabled CCs must be distinct
|
||||
within a channel; CC120 and CC123 cannot be rebound. All channels default to
|
||||
7/10/64. Rebinding replaces the old binding; it is not an additional route. An
|
||||
unmapped CC does nothing. Other channels remain independent. The same volume,
|
||||
pan and sustain transfer functions apply regardless of the chosen CC number.
|
||||
Disabling a target leaves it at its runtime reset value until plan replacement.
|
||||
Changing a map stops/rebuilds playback and is one undoable edit; maps survive
|
||||
save/Open and undo/redo. Cancel and invalid/duplicate/reserved bindings retain
|
||||
the prior configuration. There is no automatic learn, arbitrary plugin/track CC
|
||||
mapping, MIDI capture or write/touch/latch automation mode.
|
||||
|
||||
Plans copy only 48 binding bytes on the control thread. The callback compares
|
||||
at most three CC numbers per control event, uses existing preallocated ramps/
|
||||
voices and the existing 256-event block budget. Decode now accepts all valid
|
||||
three-byte CC messages; even unmapped CCs count against that event budget.
|
||||
Mixer points compile to bounded sorted arrays with binary lane lookup; processing
|
||||
does no allocation, sort, file/module I/O, locking or GUI work. LADSPA automated
|
||||
run(1) cost and native plugin trust limits remain unchanged.
|
||||
|
||||
## Persistence and verification
|
||||
|
||||
Project v10 appends a mixer interpolation field and 16 controller-map records;
|
||||
v1–v9 migrate to linear mixer lanes and default 7/10/64 maps. LADSPA point encoding
|
||||
is unchanged. Public `xtc_automation_point` gains `step`: rebuild clients and
|
||||
initialize it to 0 (linear) or 1 (hold). See PROJECT_FORMAT.md for exact grammar.
|
||||
|
||||
`test_parameters` covers metadata, missing targets, static/automation precedence,
|
||||
exact hold/linear boundaries, save/reopen, malformed maps, low-rate sample
|
||||
collisions, odd blocks, seeks and backward jumps. `test_control` compares default
|
||||
and remapped event streams, stereo pan, disabled/unmapped controls and immutable
|
||||
plan maps across resets. Plugin tests cover common-target edits and persistence;
|
||||
GUI tests cover interpolation, map rollback, undo/redo and save/Open. Existing
|
||||
callback guards and sanitizers verify host ownership constraints. Physical
|
||||
controller devices, listening and extended high-density endurance are pending.
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
events/block, 32 voices, 65536 frames/block. See API headers for exact bounds.
|
||||
- WAV samples preload with the memory/format limits in AUDIO_FILES.md. Callback
|
||||
overflow reports/silences; there is no CPU preemption or expensive-plugin rescue.
|
||||
- Live MIDI fixed volume/pan/sustain mapping; no controller learn, capture, SMF
|
||||
- Live MIDI configurable per-channel volume/pan/sustain CC mapping; no controller learn, capture, SMF
|
||||
import, pitch bend, custom-instrument chooser or instrument timbre controls.
|
||||
- Native ABI 1 graph nodes are session-only. ABI 2 state is parameter-only. LADSPA
|
||||
supports the documented mono amp/inverter/sine set; no opaque state, native
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
zoom/selection and graph positions are session UI state. Undo retains 32 edits
|
||||
plus baseline; allocation failures are reported, not silently hidden. Media is
|
||||
never removed by undo/delete. Broad screen-reader/accessibility testing is pending.
|
||||
- Format v9 reads v1–v8 and uses relative local media references. External absolute
|
||||
- Format v10 reads v1–v9 and uses relative local media references. External absolute
|
||||
media/module paths need manual repair after relocation. Saving does not bundle
|
||||
media; missing media stays referenced, missing plugins reject GUI installation.
|
||||
Unknown data is rejected rather than stripped. Post-rename directory-sync errors
|
||||
|
|
@ -54,3 +54,8 @@ PERFORMANCE.md, PLUGIN_HOSTING.md and RECOVERY.md for tested contracts/evidence.
|
|||
requires the same mono audio layout and resets controls/automation. Missing
|
||||
modules reject Open while retaining the current project; GUI module relink for
|
||||
unopened documents is deferred. In-process plugin crashes/hangs are uncontained.
|
||||
|
||||
- Common parameter targets cover track/bus gain/pan, LADSPA controls and metadata
|
||||
for live sine volume/pan/sustain. Live mappings do not drive arranged lanes,
|
||||
faders or plugins. No automation capture, touch/latch/write modes or loop
|
||||
transport. Backward jumps are deterministic for lanes, not opaque plugin tails.
|
||||
|
|
|
|||
|
|
@ -131,3 +131,8 @@ repeats/fresh IDs, rejected batch rollback, capacity, undo snapshots, equal-offs
|
|||
live order, adjacent/overlapping notes, exact block partitions and seek chase.
|
||||
`make test-gui` covers mouse edits and the new commands with undo/redo and engine
|
||||
reinstallation. Listening and physical MIDI-device validation remain pending.
|
||||
|
||||
Phase 26: CC7/10/64 are defaults, configurable per channel through Audio → MIDI
|
||||
controller mapping. Disabled/unmapped CCs have no effect; CC120/123 stay panic.
|
||||
Decode accepts valid CC0..127 messages within the existing event budget. See
|
||||
CONTROL.md for the exact bindings, ramp, sustain and automation precedence rules.
|
||||
|
|
|
|||
|
|
@ -26,7 +26,8 @@ static control. There are at most 1024 points globally, with one per
|
|||
track/parameter/tick. Track deletion cascades to its automation.
|
||||
|
||||
A nonempty lane replaces that parameter's static value. Between points the C
|
||||
engine interpolates linearly at each sample, holding the first/last value outside
|
||||
engine interpolates linearly or holds each segment (Interpolation chooser),
|
||||
holding the first/last value outside
|
||||
their range. Preparation converts ticks to integer sample endpoints, sorts and
|
||||
indexes lanes. When several ticks quantize to one sample at very low sample
|
||||
rates, the last point wins at that sample. Rendering searches prepared bounded
|
||||
|
|
@ -137,3 +138,8 @@ project performance remain unverified; no new dependency was introduced.
|
|||
`test_buses` covers bus routing, exact taps, audio/MIDI cancellation, controls,
|
||||
automation, persistence, invalid routes, deletion/undo and dBFS ballistics. Backend
|
||||
tests cover consuming interval peaks; GUI tests cover routing undo and clipping.
|
||||
|
||||
Phase 26 adds Linear/Hold interpolation for each point added or replaced. The
|
||||
point's mode applies to its following segment. Static controls remain fallbacks
|
||||
while a lane exists; moving/splitting clips does not move absolute track/bus lanes.
|
||||
See CONTROL.md for common parameter IDs and controller/automation precedence.
|
||||
|
|
|
|||
|
|
@ -193,3 +193,14 @@ replacements with host allocation/free/dlopen/dlclose guards. Native ABI tests
|
|||
cover process-error silence/reset. The separately installed amp/inverter/sine
|
||||
modules remain the qualified LADSPA set. Human listening, arbitrary third-party
|
||||
editors/plugins and extended realtime endurance remain unverified.
|
||||
|
||||
## Phase 26 parameter targets
|
||||
|
||||
`xtc_control.h` supplies common stable owner/parameter IDs and control-thread
|
||||
metadata/edit APIs for track/bus gain/pan and LADSPA input ports. The GUI's plugin
|
||||
automation command uses this contract. Linear/hold LADSPA encoding and its
|
||||
integer/toggle restrictions remain unchanged; v10 adds mixer interpolation and
|
||||
live-sine CC maps without changing plugin state records. Direct static edits do
|
||||
not override existing lanes. Live CCs do not map to plugins; missing targets or
|
||||
modules fail without installing partial state. See CONTROL.md for timing,
|
||||
precedence, reset and backward-jump behavior.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Project format v9 (reads v1–v8)
|
||||
# Project format v10 (reads v1–v9)
|
||||
|
||||
Phases 5–15 use a bounded text format implemented in C99 without a parser library.
|
||||
Phases 5–26 use a bounded text format implemented in C99 without a parser library.
|
||||
The extension is `.xtc`. File operations run exclusively on the control thread.
|
||||
The project owns its graph, tracks and silent/audio arrangement regions. Audio samples remain in external WAV
|
||||
files; MIDI notes are stored inline.
|
||||
|
|
@ -12,7 +12,7 @@ Fields use ASCII spaces. Integers are unsigned decimal, without signs.
|
|||
Counts determine the number of subsequent records:
|
||||
|
||||
```text
|
||||
XTC_PROJECT 7
|
||||
XTC_PROJECT 10
|
||||
APP 0 1 0
|
||||
TEMPO 120000
|
||||
IDS 1 1
|
||||
|
|
@ -23,12 +23,31 @@ EDGE 0 1
|
|||
TRACKS 1
|
||||
TRACK 0 547261636b
|
||||
MIX 3f800000 00000000 0 0
|
||||
ROUTE 0 18446744073709551615
|
||||
CLIPS 1
|
||||
CLIP 0 0 3840 2880 960 3840 526567696f6e
|
||||
ASSET -
|
||||
MIDI 0
|
||||
AUDIO 3f800000 0 0
|
||||
NOTES 0 0
|
||||
AUTOMATION 0
|
||||
CONTROL_MAPS 16
|
||||
MAP 0 7 10 64
|
||||
MAP 1 7 10 64
|
||||
MAP 2 7 10 64
|
||||
MAP 3 7 10 64
|
||||
MAP 4 7 10 64
|
||||
MAP 5 7 10 64
|
||||
MAP 6 7 10 64
|
||||
MAP 7 7 10 64
|
||||
MAP 8 7 10 64
|
||||
MAP 9 7 10 64
|
||||
MAP 10 7 10 64
|
||||
MAP 11 7 10 64
|
||||
MAP 12 7 10 64
|
||||
MAP 13 7 10 64
|
||||
MAP 14 7 10 64
|
||||
MAP 15 7 10 64
|
||||
END
|
||||
```
|
||||
|
||||
|
|
@ -47,6 +66,8 @@ END
|
|||
- `TRACK`: ID and hex-encoded name bytes. In v4/v5 each is immediately followed
|
||||
by `MIX gain_bits pan_bits mute solo`: finite binary32 gain 0..4, pan -1..1
|
||||
encoded as eight hex digits, mute and solo unsigned 0/1.
|
||||
- `ROUTE`: since v9, required after MIX: bus flag and destination bus ID;
|
||||
UINT64_MAX denotes master. See Phase 24 constraints below.
|
||||
- `CLIP`: ID, track ID, start tick, length tick, source offset tick, source
|
||||
length tick, hex-encoded name bytes. Trimming
|
||||
preserves source bounds, so a region can re-extend only within its original
|
||||
|
|
@ -63,7 +84,8 @@ END
|
|||
within source bounds. Pitch is 0..127, velocity 1..127, channel 0..15.
|
||||
Note IDs are unique, monotonic uint64 IDs with UINT64_MAX reserved.
|
||||
- `AUTOMATION`: global point count, after the last NOTE and before END in v4/v5.
|
||||
Follow with `POINT track_id parameter tick value_bits` for each point.
|
||||
Follow with `POINT track_id parameter tick value_bits step` in v10 (v4–v9
|
||||
omit step and migrate to linear). Step is 0 linear or 1 hold for the next segment.
|
||||
Parameter 0 is gain (0..4), 1 pan (-1..1); values use finite binary32 hex.
|
||||
Track must exist; tick <= MAX_TICK; duplicate track/parameter/tick is invalid.
|
||||
Record order is preserved; rendering sorts a separate prepared copy.
|
||||
|
|
@ -227,3 +249,23 @@ Bus controls and automation use existing MIX and POINT records. Older readers
|
|||
reject v9 rather than discard routing. The public `xtc_track_info` grew fields;
|
||||
API consumers must rebuild. Fixtures cover v1–v8 migration and tests exercise
|
||||
v9 exact roundtrips and malformed routing.
|
||||
|
||||
## Phase 26: version 10 interpolation and controller bindings
|
||||
|
||||
The current writer emits v10 and reads v1–v9. Track/bus automation points are
|
||||
`POINT track_id parameter tick value_bits step`, where step is 0 linear or 1
|
||||
hold for the segment starting there. v1–v9 points migrate to step=0. LADSPA
|
||||
`PARAM` encoding remains unchanged (already has interpolation mode).
|
||||
|
||||
Immediately after all POINT records, before END, v10 requires `CONTROL_MAPS 16`
|
||||
and exactly 16 records in ascending channel order:
|
||||
`MAP channel volume_CC pan_CC sustain_CC`. Channels are 0..15. Controllers are
|
||||
0..127 or 128 (disabled); enabled numbers must be distinct within a row and may
|
||||
not be 120 or 123. Duplicate/missing/out-of-order channels, invalid CCs, reserved
|
||||
bindings and invalid interpolation modes reject the complete candidate. v1–v9
|
||||
supply default 7/10/64 bindings on every channel. No event history/current live
|
||||
controller values are serialized. Older readers reject v10.
|
||||
|
||||
Fixtures cover v1–v9 migration. Exact roundtrips, malformed metadata, step/linear
|
||||
renders and remapped live events cover the new writer/reader. Public clients
|
||||
must rebuild and initialize the appended `xtc_automation_point.step` field.
|
||||
|
|
|
|||
|
|
@ -672,10 +672,36 @@ Enable repeatable changes to mix and instrument parameters over time, with clear
|
|||
- Document precedence rules for automation, controller input, and direct user changes.
|
||||
|
||||
### Acceptance criteria
|
||||
- Supported parameters can be automated and saved in a project.
|
||||
- Playback produces deterministic automation values for a given project and transport position.
|
||||
- Missing targets fail safely and are reported to the user.
|
||||
- Automation processing meets the engine's real-time safety requirements.
|
||||
- [x] Supported parameters can be automated and saved in a project.
|
||||
- [x] Playback produces deterministic automation values for a given project and transport position.
|
||||
- [x] Missing targets fail safely and are reported to the user.
|
||||
- [x] Automation processing meets the engine's real-time safety requirements.
|
||||
|
||||
Implemented: common stable owner/parameter keys and copied metadata for
|
||||
track/bus gain/pan, LADSPA input controls and live sine controller targets;
|
||||
validated common static/lane edit APIs; per-point linear/hold mixer automation;
|
||||
per-channel saved volume/pan/sustain CC bindings with explicit disable and reserved
|
||||
panic controllers. GUI adds Interpolation and Audio/MIDI controller mapping;
|
||||
edits participate in undo/redo. Project v10 reads v1–v9 with linear/default-map
|
||||
migration. CONTROL.md documents target identity, clip boundaries, precedence,
|
||||
missing-target handling, controller ramps and real-time ownership.
|
||||
|
||||
Validation: warning-enabled core/GUI builds and full tests; common metadata,
|
||||
missing owner/port/module failures and retained state; exact step/ramp endpoints,
|
||||
low-rate collisions, odd blocks, seeks and explicit backward wraps; default/
|
||||
remapped/disabled/unmapped CCs and stereo pan, immutable maps after preparation;
|
||||
GUI map/interpolation/save/Open/undo/redo and invalid-edit rollback; v1–v9
|
||||
migration, v10 exact persistence and malformed records; fixture/installed plugin
|
||||
tests, callback-allocation guards, reliability/static analysis, performance and
|
||||
capacity tests; software JACK GUI/audio/MIDI and workflow; dependency-free build,
|
||||
installation/package relocation, core/GUI ASan+UBSan (existing fontconfig leak
|
||||
suppression only for GUI/system font allocations).
|
||||
|
||||
No loop transport, MIDI learn/capture, write/touch/latch modes, arbitrary MIDI
|
||||
mapping to arranged faders/plugins, timbre parameter for the built-in sine or
|
||||
opaque-plugin seek restoration is claimed. Live MIDI targets have reset-default
|
||||
metadata and controller bindings, not timeline lanes. Physical controllers,
|
||||
listening and extended third-party-plugin endurance remain unverified.
|
||||
|
||||
## Phase 27 — Editing Workflow, Undo/Redo, and Usability
|
||||
|
||||
|
|
|
|||
|
|
@ -138,3 +138,10 @@ reset and insertion of an effect on a selected wire. Graph wires determine
|
|||
processing order; Delete removes a selected plugin and its wires. Changes are
|
||||
undoable. Replacement keeps compatible audio wiring but resets plugin controls
|
||||
and automation. See PLUGIN_HOSTING.md for supported formats and failure behavior.
|
||||
|
||||
Phase 26: Mixer Interpolation selects Linear or Hold for each point added or
|
||||
replaced. Audio → MIDI controller mapping lists all channel bindings; enter
|
||||
`channel volume_CC pan_CC sustain_CC` (channels 0..15, 128 disables, enabled CCs
|
||||
must be distinct, 120/123 reserved). Maps are undoable and saved. Controllers
|
||||
modify live sine voices; arranged track/bus/plugin automation takes precedence
|
||||
over its static controls and is unaffected by those MIDI bindings. See CONTROL.md.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue