Phase 6: Add WAV clips, graph playback and bounded recording

This commit is contained in:
Johannes Findeisen 2026-10-27 00:31:03 +01:00
commit 8a37090b81
40 changed files with 1450 additions and 69 deletions

View file

@ -203,3 +203,38 @@ and delayed by polling. No external JACK transport synchronization is provided.
Silent clip metadata is control-thread data, never traversed by the callback.
Audio/MIDI scheduling will be added in later phases through compiled event/clip
plans rather than direct callback access to the editable project.
## Phase 6 audio source and recording
xtc_audio.h provides control-thread import and immutable preloaded clip plans.
The backend prepares a project only while stopped: build audio candidate,
compile/submit its graph, then replace the old audio plan without a later
fallible step. Preparation failures retain both old plans. Missing/invalid
assets produce explicit issue metadata and silence; OOM/capacity fails.
Graph-only edits still use the existing pending/retired mechanism while running.
Each callback renders the plan into a preallocated mono timeline buffer using
the authoritative sample position. xtc_realtime_process_audio passes that
buffer into the compiled graph; XTC_NODE_AUDIO (output port only) reads it,
independently from external JACK input. The old process APIs remain wrappers
with a silent timeline. Import creates a source/output route if necessary.
No samples or GUI/project arrays are shared with editable state. Clip mixing,
rate conversion and graph processing are bounded; see AUDIO_FILES.md for limits.
A borrowed recorder can be attached/detached only while stopped. Raw JACK input
is copied to its SPSC ring before graph processing. Producer and consumer index
release/acquire operations protect payload ownership; all atomics are checked
always lock-free. The control thread drains to a temporary float32 WAV, then
finalizes only after successful stop/close has synchronized the callback.
An overflowing ring or unavailable input creates a sticky error; later input is
dropped, reported and never silently joined into a continuous-looking take.
A partial overflow take is finalized for manual recovery. File errors retain
the previous destination and remove unfinished temporaries.
GUI recording uses a two-second ring and 100 ms control-thread draining, with
no worker thread. A GUI stall can overflow it. No callback allocation/free, file
I/O, logging, locks or FLTK calls were added. Backend stop failure preserves the
borrowed recorder; the caller must not free it before successful quiescence.
Live software source/capture acceptance and concurrent ring tests pass; physical
recording, latency compensation and disk endurance remain unverified.