Phase 1 plus some refactoring.
This commit is contained in:
parent
71f7b4d96b
commit
8075e1b79d
17 changed files with 465 additions and 266 deletions
|
|
@ -23,9 +23,13 @@ thread: validate, topologically sort, determine buffer requirements, allocate
|
|||
resources, and publish a prepared immutable execution plan. The audio thread
|
||||
must not traverse a graph being edited.
|
||||
|
||||
The current scaffold is deliberately incomplete: `xt_graph_process_offline()`
|
||||
validates the graph and applies gain nodes in insertion order. It is a test
|
||||
placeholder, not the final graph execution algorithm.
|
||||
The offline engine now copies a validated graph into a prepared plan with
|
||||
stable node IDs, topological order, precomputed input adjacency, per-node mono
|
||||
buffers and oscillator/meter state. Each plan has one processing owner. Graph
|
||||
edits and destruction cannot affect an existing plan. All nodes are scheduled,
|
||||
including disconnected nodes; only explicit output nodes are rendered (or
|
||||
terminal nodes when no output node exists). See AUDIO_ENGINE.md for contracts.
|
||||
Plan publication across threads and retirement remain Phase 2 work.
|
||||
|
||||
## Ownership and threads
|
||||
|
||||
|
|
|
|||
|
|
@ -25,3 +25,57 @@ Audio sample position is the authoritative playback clock. Use integer or
|
|||
rational timeline representations to avoid cumulative floating-point drift.
|
||||
Define tempo-map conversion and behavior at tempo changes before implementing
|
||||
tempo automation.
|
||||
|
||||
## Phase 1 offline API
|
||||
|
||||
`xtc_graph_create` accepts 1..256 nodes; IDs are insertion indexes, stable for
|
||||
that graph's lifetime. Supported nodes are gain (any finite multiplier), sine
|
||||
oscillator (finite nonnegative Hz), pass-through peak meter and audio output.
|
||||
Ports carry mono float audio: input 0, output 1. Oscillators have no input and
|
||||
output nodes have no output. Port lookup reports direction, signal type and
|
||||
channel count. MIDI/control ports and channel conversion are not implemented;
|
||||
invalid ports/directions, duplicate edges and cycles are rejected before an
|
||||
edit becomes visible. Fan-out copies a source to consumers; fan-in sums inputs
|
||||
without normalization. Failed additions leave IDs and graph contents unchanged.
|
||||
|
||||
`xtc_graph_compile(graph, sample_rate, max_frames, &plan)` runs on the control
|
||||
thread. Empty graphs are rejected. Sample rate must be finite and positive,
|
||||
oscillators must be at or below Nyquist, and max_frames is 1..65536. Compilation
|
||||
allocates and copies topology/parameters, builds a topological schedule and
|
||||
input adjacency, and allocates one max_frames float buffer per node. The
|
||||
maximum buffer storage is 64 MiB per plan. Compilation may fail with an
|
||||
allocation error; output plan is then NULL. Destroy a plan on the control thread.
|
||||
|
||||
`xtc_plan_process` uses only prepared state: no allocation/free, sorting,
|
||||
logging, I/O or locks. Each call accepts up to max_frames; oversized calls
|
||||
return capacity errors without modifying output or state. Output storage must
|
||||
hold frame_count floats. NULL input means silence; input/output may alias.
|
||||
Zero frames leaves all state unchanged. No plan operations may run concurrently
|
||||
with processing, including reset, meter reads or destruction.
|
||||
|
||||
Unconnected non-oscillator nodes receive external input. Connected inputs
|
||||
receive only the sum of their upstream buffers. Explicit output nodes are
|
||||
summed to the caller's output. If none exist, terminal nodes are summed for
|
||||
compatibility with the original gain-chain API. Disconnected components cannot
|
||||
contribute when explicit outputs exist, but they are still processed. Floating
|
||||
point overflow and nonfinite input become silence per sample. No clipping or
|
||||
normalization is applied to finite samples.
|
||||
|
||||
Oscillators start at phase zero and carry phase continuously across blocks;
|
||||
reset clears phases and meter peaks. Meter reads return the last nonempty
|
||||
block's absolute peak. These are same-thread reads, not a thread-safe GUI
|
||||
meter bridge. Rendering is deterministic on the same build/platform regardless
|
||||
of block partitioning; libm results need not be bit-identical across platforms.
|
||||
|
||||
`xtc_graph_process_offline` remains a convenience helper, compiling at 48000 Hz
|
||||
and destroying the plan after one block. It accepts a finite external-input
|
||||
gain and requires non-NULL input/output. It now follows routing rather than
|
||||
multiplying every gain in insertion order. It allocates and is not suitable for
|
||||
an audio callback. Use a persistent plan for phase continuity and repeated blocks.
|
||||
|
||||
Tests in `tests/unit/test_offline.c` cover known oscillator samples, gain and
|
||||
meter output, reset and partition equivalence, fan-out/fan-in, reverse insertion
|
||||
order, disconnected nodes, in-place processing, nonfinite input, invalid ports,
|
||||
cycles, capacity limits, plan lifetime and repeated compilation/cleanup.
|
||||
Hardware playback, concurrent graph publication and backend stress tests remain
|
||||
Phase 2 work; this offline API does not claim hardware real-time qualification.
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ make gui
|
|||
```
|
||||
|
||||
`all` builds the static C library and startup check. `test` runs the existing
|
||||
core test and startup check. `debug` builds and tests separately in
|
||||
core and offline graph tests plus the startup check. `debug` builds and tests separately in
|
||||
`build/debug`. `gui` builds the existing placeholder shell; it does not produce
|
||||
audio. Generated files remain under `build` and header changes trigger rebuilds.
|
||||
Compiler, flags, `BUILD_DIR`, `PKG_CONFIG`, `FLTK_CONFIG`, and installation
|
||||
|
|
@ -49,9 +49,8 @@ are changed by these build commands.
|
|||
|
||||
## Next milestone
|
||||
|
||||
Phase 1 must replace insertion-order gain processing with a validated,
|
||||
topologically scheduled offline plan, preallocated buffers, oscillator, gain,
|
||||
meter and output nodes, and deterministic routing tests. The current gain
|
||||
prototype is not a real-time engine. Public project persistence declarations
|
||||
also remain unimplemented. Hardware playback and interactive GUI behavior are
|
||||
outside this baseline.
|
||||
Phase 1 implements compiled offline plans, preallocated buffers, oscillator,
|
||||
gain, meter/output nodes and routing tests; see AUDIO_ENGINE.md. Phase 2 adds
|
||||
a hardware backend and safe cross-thread plan publication/retirement. Public
|
||||
project persistence declarations remain unimplemented. Hardware playback and
|
||||
interactive GUI behavior are not verified by the offline tests.
|
||||
|
|
|
|||
26
docs/IDEA.md
26
docs/IDEA.md
|
|
@ -229,23 +229,23 @@ Example API shape (illustrative only; refine after reviewing the actual codebase
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct xt_app xt_app;
|
||||
typedef struct xtc_app xtc_app;
|
||||
|
||||
typedef enum {
|
||||
XT_OK = 0,
|
||||
XT_ERR_INVALID_ARGUMENT,
|
||||
XT_ERR_OUT_OF_MEMORY,
|
||||
XT_ERR_NOT_FOUND,
|
||||
XT_ERR_INVALID_STATE,
|
||||
XT_ERR_IO,
|
||||
XT_ERR_UNSUPPORTED
|
||||
} xt_result;
|
||||
XTC_OK = 0,
|
||||
XTC_ERR_INVALID_ARGUMENT,
|
||||
XTC_ERR_OUT_OF_MEMORY,
|
||||
XTC_ERR_NOT_FOUND,
|
||||
XTC_ERR_INVALID_STATE,
|
||||
XTC_ERR_IO,
|
||||
XTC_ERR_UNSUPPORTED
|
||||
} xtc_result;
|
||||
|
||||
xt_result xt_app_create(xt_app **out_app);
|
||||
void xt_app_destroy(xt_app *app);
|
||||
xtc_result xtc_app_create(xtc_app **out_app);
|
||||
void xtc_app_destroy(xtc_app *app);
|
||||
|
||||
xt_result xt_transport_play(xt_app *app);
|
||||
xt_result xt_transport_stop(xt_app *app);
|
||||
xtc_result xtc_transport_play(xtc_app *app);
|
||||
xtc_result xtc_transport_stop(xtc_app *app);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,11 @@ See [BUILD.md](BUILD.md) for toolchain, commands, licensing and limitations.
|
|||
Graph data structures, validation, cycle detection, topological ordering,
|
||||
preallocated buffers, test oscillator, gain and offline render tests.
|
||||
|
||||
Implemented: mono ports, transactional cycle rejection, independent compiled
|
||||
plans, precomputed input routing, oscillator/gain/meter/output, deterministic
|
||||
variable-block tests and lifecycle/error coverage. See AUDIO_ENGINE.md for API
|
||||
limits and compatibility behavior. Cross-thread publication remains Phase 2.
|
||||
|
||||
## Phase 2 — Real-time backend
|
||||
Choose and implement a Linux backend. Document callback semantics, start/stop,
|
||||
device errors, shutdown, and safe graph publication.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue