xtc/docs/CONTROL.md

166 lines
9.3 KiB
Markdown
Raw Normal View History

2026-11-06 15:20:20 +01:00
# Automation and Expressive Control
2026-11-06 15:20:20 +01:00
Track Gain/Pan lanes in the Mixer apply to audio and scheduled instrument
voices. 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 parameter. Track gain ramps and boundary fades are described
in AUDIO_QUALITY.md.
Select a LADSPA node in Modular Graph and use Edit/Selected plugin automation.
2026-11-06 15:20:20 +01:00
Enter `port tick mode value`: mode 0 interpolates linearly, 1 holds until the
next point, and -1 removes the point at that port/tick (value ignored). Port
names, ranges and current tick are displayed. There are at most 32 points per
plugin; setting an existing port/tick replaces it. Integer/toggle controls
require step mode. Invalid values, ticks, ports or duplicate persisted points
reject the edit or file. Edits are undoable and rebuild on the control thread
while stopped.
Effect lanes use the project tempo, hold first/last outside their range and
apply before run at each exact sample. Distinct ticks rounding to one sample
resolve to the later tick. Linear curves avoid stepping continuous controls;
intentional step curves may click. The initial implementation calls run(1) while
2026-11-06 15:20:20 +01:00
any lane exists, with connected preallocated buffers. CPU cost can be
significant; only the documented LADSPA set is qualified. No worker, allocator,
loader or 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),
2026-11-06 15:20:20 +01:00
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, 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 sustain is held. Sustain-up releases pending voices, never
newer retriggers. Seek, stop, teardown and disconnect clear live voices; plan
reset returns controller values to unity/center. Equal-offset live events
execute in input order before the sample; arrange note ends precede starts, and
scheduled mixer values are evaluated at that sample. Overlapping arranged notes
are independent.
Format v6 preserves v5 data plus effect lanes. A v5 plugin migrates with no lane
and the project tempo. Repeated render/save/reopen, odd block partition, exact
endpoints, seek/plan replacement, sustain/retrigger and controller ramp tests:
```sh
make test test-control test-plugins test-gui-plugins test-plugins-real
```
Physical controller devices and listening remain unqualified; no tempo map,
2026-11-06 15:20:20 +01:00
latency compensation, MIDI capture, pitch bend or plugin crash isolation is
added.
2026-11-06 15:20:20 +01:00
---
2026-11-06 15:20:20 +01:00
## 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 |
2026-11-06 15:20:20 +01:00
`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
2026-11-06 15:20:20 +01:00
PLUGIN_HOSTING.md. Persisted dangling references reject the complete load; the
current project remains intact. The GUI reports rejected edits/Open failures.
2026-11-06 15:20:20 +01:00
---
## 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,
2026-11-06 15:20:20 +01:00
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,
2026-11-06 15:20:20 +01:00
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).
2026-11-06 15:20:20 +01:00
---
## 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
2026-11-06 15:20:20 +01:00
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.
2026-11-06 15:20:20 +01:00
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
2026-11-06 15:20:20 +01:00
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.
2026-11-06 15:20:20 +01:00
---
## Persistence and Verification
Project v10 appends a mixer interpolation field and 16 controller-map records;
2026-11-06 15:20:20 +01:00
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.
2026-11-06 15:20:20 +01:00
`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.