Phase 31: add CLAP, VST2 and VST3 mono effect hosting

This commit is contained in:
Johannes Findeisen 2026-10-27 17:34:46 +01:00
commit 9e0e4562d7
114 changed files with 10369 additions and 75 deletions

View file

@ -1,6 +1,6 @@
# Project format v10 (reads v1–v9)
# Project format v11 (reads v1–v10)
Phases 5–28 use a bounded text format implemented in C99 without a parser library.
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.
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 10
XTC_PROJECT 11
APP 0 1 0
TEMPO 120000
IDS 1 1
@ -104,8 +104,8 @@ 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 v10. Unknown versions are rejected without replacing the destination; older
applications without v10 support cannot read current saves. Migration and maximum-path roundtrips are tested.
Saving always writes v11. Unknown versions are rejected without replacing the destination; older
applications without v11 support cannot read current saves. Migration and maximum-path roundtrips are tested.
## Ownership and failures
@ -254,7 +254,7 @@ 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
Phase 26 introduced v10 with migration from 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).
@ -274,8 +274,8 @@ must rebuild and initialize the appended `xtc_automation_point.step` field.
## Phase 28 compatibility and diagnostic contract
The current reader accepts versions 1–10 and the writer always emits version 10.
There is no format change in Phase 28. Saving an older document upgrades it;
The current reader accepts versions 1–11 and the writer always emits version 11.
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
application version. A future incompatible schema requires a new format number.
@ -337,3 +337,33 @@ preserve the old bytes and remove the temporary. After rename, a sync failure
reports I/O while leaving a complete new document; inspect it before retrying.
Fault wrappers are linked into tests only. These tests complement killed-writer
coverage in `make test-recovery`; they do not qualify power-cut behavior.
## Phase 31: version 11 plugin format identity
Immediately after every plugin MODULE record, v11 requires:
```text
FORMAT format_number hex_identity_or_dash
```
0 = LADSPA, 1 = CLAP, 2 = VST2, 3 = VST3. Identity is `-` for LADSPA/VST2;
CLAP uses its stable plugin ID (1–127 non-NUL bytes); VST3 uses the 32-character lowercase
hex class ID string, itself hex-encoded like other byte strings. PLUGIN's unique
ID remains the VST2/LADSPA integer ID (zero for CLAP/VST3), descriptor index and
label. MODULE is still the actual absolute binary path. Versions 1–10 migrate
to format 0 and empty extra identity. Older readers reject v11. The public plugin
struct has grown; C/C++ consumers must rebuild and initialize it to zero.
Modern adapters accept one-input mono effects, default configuration only, with
zero controls and automation points. Unsupported modern control metadata is
rejected, not discarded. State/editor/preset changes are not exposed, so no opaque
state is serialized. Reloading recreates plugin defaults, which can change after
a plugin update or with its external configuration. Matching ID/name/layout is
not a binary hash or sound-reproducibility guarantee. See PLUGIN_HOSTING.md.
Metadata validation and inspection never initialize modules. Actual graph
preparation verifies format, descriptor, stable identity, name and layout before
publishing. Missing module metadata survives C load/save; GUI preparation retains
the existing document on failure. No automatic path search or plugin substitution
occurs. Current and historical migration fixtures, malformed fields, identity
mismatch, missing-module and exact-render roundtrips cover this extension.