1
0
Fork 0
forked from hanez/xtc

Phase 14: define parameterized native processors and portable configuration state

This commit is contained in:
Johannes Findeisen 2026-10-27 03:48:46 +01:00
commit c3eadee891
8 changed files with 419 additions and 1 deletions

View file

@ -81,3 +81,54 @@ Tests cover ABI/size/field rejection, descriptor copying, aliased buffers,
prepare/process failures, stereo compile cleanup, retirement/destruction outside
processing, event offsets, seek note reset, source ports, instrument-buffer graph
routing and unsupported-save preservation. Run `make test`.
## Phase 14: structured parameter processors
`xtc_processor.h` is the public C99 parameter-only extension interface (ABI 2).
It complements the ABI 1 graph adapter without changing its layout or behavior.
`examples/processors.c` implements a mono gain effect and a monophonic MIDI sine
instrument using only public headers; `make test-processor` builds and exercises
both. The instrument has immediate note-off and no voice stealing/release tail.
Descriptors have an exact ABI version and structure size, a persistent identifier,
and up to 16 parameters with unique unsigned IDs, names, units, finite ranges and
defaults. Unsupported ABI versions/sizes are rejected before initialization.
Changing identifier, parameter order, IDs or ranges requires an explicit migration
by the extension author. There is no promise of binary compatibility across
compiler architectures, and no C++/FLTK types in either API.
Create prepares a copied descriptor on the control thread. Failed preparation
calls destroy, including with NULL: callbacks must implement partial cleanup.
Reset/process/parameter have one audio owner and must never allocate, free, block,
perform I/O or call GUI functions. Destroy is control-thread only after callback
quiescence. Reconfiguration prepares a new independent instance; publish it with
an appropriate owner handoff and retire the old instance after quiescence. The
callback code must remain loaded throughout that lifetime.
Each instance has one mono output and either one optional input (effect) or no
input (source/instrument). NULL input means silence. Stereo effects use two
independent instances; multichannel interdependent effects have no adapter.
Instruments receive at most 256 sorted sample-offset MIDI events per block.
The API intentionally has no channel-count argument: unsupported layouts cannot
be represented. Graph ABI 1 rejects instrument descriptors; explicitly render
instrument output and feed the existing instrument source buffers.
Up to 256 sorted parameter events split the process block at exact sample
positions. Equal-offset parameters execute in array order, then MIDI at that
sample. Values outside the descriptor range, bad IDs and malformed events reject
the entire call before touching state/output. Values are stepped; extension
callbacks own any smoothing. Transport discontinuities reset transient state;
reset retains current parameters. Callback errors silence the whole output and
reset voices/history; already applied parameters persist. Nonfinite/subnormal
successful samples become zero. Input/output may alias exactly.
`xtc_processor_save`/`restore` run only while quiescent and serialize configuration,
not DSP history. Format: `XTCN`, little-endian uint32 version 2, zero-padded
64-byte identifier, uint32 parameter count, zero uint32 reserved, then ordered
pairs of uint32 ID and IEEE float32 bits. Header is 80 bytes, pairs 8 bytes.
Restore validates exact length, identity, IDs, ranges and defaults/descriptor
compatibility before preparing a new instance; failure leaves existing handles
intact. Opaque assets and hidden state are outside this ABI. ABI 1 graph nodes
remain session-only and fail project saves explicitly; ABI 2 configuration blobs
are a separate public facility, not automatically embedded in project files.
GUI graph access continues through public C APIs only.