feat: add editable internal instruments, automation and versioned presets

This commit is contained in:
Johannes Findeisen 2026-11-05 23:47:54 +01:00
commit 159fa939a1
21 changed files with 295 additions and 52 deletions

View file

@ -5,10 +5,10 @@ built-in sine remains available for existing projects.
Choose **Internal: Soft Keys** or **Internal: Sub Bass** in a MIDI track's
instrument dropdown. Soft Keys blends a sine with a third harmonic; Sub Bass
uses a pure sine. Both are fixed presets with 32 voices, velocity sensitivity,
uses a pure sine. Both have 32 voices, velocity sensitivity,
short attack/release envelopes, sustain pedal, note-off and panic handling.
High harmonics are omitted near Nyquist. These basic instruments have no preset
editor, pitch bend, sample library or oscillator/filter controls.
High harmonics are omitted near Nyquist. The default sounds remain compatible with fixed presets from v13. See the
Phase 41 controls below. A sample library is not provided by these oscillators.
In **Modular Graph**, select a wire and choose **Edit → Insert internal delay on
wire** or **Insert internal reverb on wire**. This preserves the route and inserts
@ -57,3 +57,36 @@ For repeatable manual listening, run `make builtin-preview` and audition
followed by silence for tails. Check onset/release, unwanted discontinuities,
finite decay and the documented mono character. Generation is verified;
human listening and physical-device qualification remain pending.
## Phase 41 instrument controls and presets
**Edit → Selected instrument controls** edits an assigned internal instrument.
The five ports are harmonic amount (0..1), attack (0.1..2000 ms), release
(1..5000 ms), low-pass cutoff (20..24000 Hz; 24000 bypasses the filter) and
pitch-bend range (0..24 semitones, default 2). The harmonic is a third harmonic;
it is suppressed before crossing Nyquist. Attack/release are exponential time
constants, not times to absolute silence. Defaults preserve the original sounds.
**Selected instrument automation** accepts `port tick mode value`, with absolute
project ticks, linear mode 0, hold mode 1, or -1 to remove a point. Automation
uses absolute sample positions, including seeks and 256-frame instrument chunks.
Static edits stop/reprepare playback and are undoable. Existing v13 assignments
with no parameters upgrade to defaults when opened in the editor.
**File → Save/Load instrument preset** uses an explicit absolute path. Presets
are versioned single-instrument `.xtc` containers with no clips. Public C APIs
`xtc_plugin_preset_save/load` provide atomic saving and transactional metadata
loading; they never execute plugin code. Loading into a track is an undoable,
prepared edit. Parameter automation is included. Preset paths are ordinary files;
saving uses the existing project replacement semantics.
Live MIDI pitch bend uses standard 14-bit messages (8192 center) and is applied
at the event's sample offset per channel. Panic clears the affected channel's
bend and sustain. The original unassigned sine ignores bend; CLAP MIDI/VST2
receive raw bend, while native-note CLAP/VST3 do not yet map it to expressions.
No external-plugin parameter support is implied.
Format 14 adds instrument controls and automation. Readers still accept v1–v13;
old fixed internal assignments use their original defaults. Older builds reject
v14. Tests cover legacy-default sound equality, v13 migration, parameter/preset
round trips, pitch-bend offsets, automated block partitions, undo and GUI edits.

View file

@ -1,4 +1,4 @@
# Project format v13 (reads v1–v12)
# Project format v14 (reads v1–v13)
Phases 5–31 use a bounded text format implemented in C99 without a parser library.
The extension is `.xtc`. File operations run exclusively on the control thread.
@ -104,7 +104,7 @@ node types 1..4, migrating their clips to empty asset paths. Version 2 accepts
node types 1..5 and ASSET records. Both migrate to MIDI=0 and no notes.
Version 3 accepts instrument nodes and MIDI/NOTES records. Versions 1–3 migrate
all tracks to unity gain, centered pan, mute/solo off and no automation.
Saving always writes v12. Unknown versions are rejected without replacing the destination; older
Saving always writes v14. Unknown versions are rejected without replacing the destination; older
applications without v12 support cannot read current saves. Migration and maximum-path roundtrips are tested.
## Ownership and failures
@ -274,7 +274,7 @@ must rebuild and initialize the appended `xtc_automation_point.step` field.
## Phase 28 compatibility and diagnostic contract
The current reader accepts versions 1–12 and the writer always emits version 12.
The current reader accepts versions 1–14 and the writer always emits version 14.
Phase 28 made no format change; Phase 31 adds plugin format identity in v11. Saving an older document upgrades it;
retain an original backup if an older application must still open it. APP is
informational; compatibility depends on the format version, not the producer's
@ -396,3 +396,14 @@ Format value 4 identifies dependency-free internal devices at `/xtc/internal`.
Indices 0/1 bind fixed Soft Keys/Sub Bass instruments; 2/3 are Delay/Reverb
effects with three controls and existing automation records. Identity and control
ranges are validated without loading libraries. See [BUILTIN_DEVICES.md](BUILTIN_DEVICES.md).
## Version 14 instrument parameters
Each track INSTRUMENT identity is followed by `INSTRUMENT_CONTROLS count`,
`CONTROL port value_bits` records, `INSTRUMENT_AUTOMATION count` and
`PARAM tick port mode value_bits` records. Bounds, duplicate points and metadata
are validated before destination replacement, just as for graph effects.
Earlier bindings have no controls/automation; v13 internal instruments retain
fixed default sounds. Modern external instruments still require zero controls.
Instrument tempo follows project tempo. Instrument preset files use this same
schema with exactly one instrument track and no clips; they are metadata only.

View file

@ -1174,14 +1174,18 @@ manual checks; human listening and physical hardware remain unverified.
Extend the fixed Soft Keys/Sub Bass presets into editable instruments.
### Tasks and acceptance criteria
- [ ] Define bounded oscillator, envelope and filter controls with metadata and defaults that preserve existing preset sounds.
- [ ] Provide instrument parameter editing, automation and reusable preset save/load through public C APIs.
- [ ] Support channel pitch bend with a documented range and sustain/note lifecycle behavior.
- [ ] Persist parameters and presets with explicit version migration, undo and failed-preparation rollback.
- [ ] Verify sample timing, block partition consistency, bounds, aliasing behavior and callback safety.
- [x] Define bounded oscillator, envelope and filter controls with metadata and defaults that preserve existing preset sounds.
- [x] Provide instrument parameter editing, automation and reusable preset save/load through public C APIs.
- [x] Support channel pitch bend with a documented range and sustain/note lifecycle behavior.
- [x] Persist parameters and presets with explicit version migration, undo and failed-preparation rollback.
- [x] Verify sample timing, block partition consistency, bounds, aliasing behavior and callback safety.
### Implementation status
Planned. The current instruments expose no editable parameters or pitch bend.
Implemented: five bounded oscillator/envelope/filter/bend controls, absolute-time
automation, instrument editor and reusable preset C APIs/GUI commands. Format 14
persists bindings and reads v1–v13, preserving legacy default sounds. Core,
reliability and GUI tests pass, including preset/migration, exact partition and
pitch-bend offset regressions. See BUILTIN_DEVICES.md and PROJECT_FORMAT.md.
---