Docs file normalization.
This commit is contained in:
parent
dd32143bf8
commit
619c2d0808
46 changed files with 3587 additions and 2579 deletions
|
|
@ -1,39 +1,46 @@
|
||||||
# Architecture
|
# Architecture
|
||||||
|
|
||||||
## Decision: modular engine first
|
## Decision: Modular Engine First
|
||||||
|
|
||||||
The processing graph is the common model for audio sources, instruments,
|
The processing graph is the common model for audio sources, instruments,
|
||||||
effects, mixers, and outputs. The sequencer produces time-based content and
|
effects, mixers, and outputs. The sequencer produces time-based content and
|
||||||
events consumed by graph nodes. The default workspace remains sequencer-first;
|
events consumed by graph nodes. The default workspace remains sequencer-first;
|
||||||
the graph editor is an advanced view of the same project.
|
the graph editor is an advanced view of the same project.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Layers
|
## Layers
|
||||||
|
|
||||||
1. **FLTK/C++ GUI:** input, drawing, windows, view state.
|
1. **FLTK/C++ GUI:** input, drawing, windows, view state.
|
||||||
2. **C core:** project model, commands, parameters, persistence, validation.
|
2. **C core:** project model, commands, parameters, persistence, validation.
|
||||||
3. **C engine:** prepared processing graph, DSP, transport timing, event delivery.
|
3. **C engine:** prepared processing graph, DSP, transport timing, event
|
||||||
|
delivery.
|
||||||
4. **Backend:** hardware and system audio/MIDI integration.
|
4. **Backend:** hardware and system audio/MIDI integration.
|
||||||
|
|
||||||
The GUI must not directly modify engine internals. It calls a stable C API.
|
The GUI must not directly modify engine internals. It calls a stable C API.
|
||||||
|
|
||||||
## Graph execution
|
---
|
||||||
|
|
||||||
|
## Graph Execution
|
||||||
|
|
||||||
The first implementation should reject cycles. Compile a graph off the audio
|
The first implementation should reject cycles. Compile a graph off the audio
|
||||||
thread: validate, topologically sort, determine buffer requirements, allocate
|
thread: validate, topologically sort, determine buffer requirements, allocate
|
||||||
resources, and publish a prepared immutable execution plan. The audio thread
|
resources, and publish a prepared immutable execution plan. The audio thread
|
||||||
must not traverse a graph being edited.
|
must not traverse a graph being edited.
|
||||||
|
|
||||||
The offline engine now copies a validated graph into a prepared plan with
|
The offline engine now copies a validated graph into a prepared plan with stable
|
||||||
stable node IDs, topological order, precomputed input adjacency, per-node mono
|
node IDs, topological order, precomputed input adjacency, per-node mono buffers
|
||||||
buffers and oscillator/meter state. Each plan has one processing owner. Graph
|
and oscillator/meter state. Each plan has one processing owner. Graph edits and
|
||||||
edits and destruction cannot affect an existing plan. All nodes are scheduled,
|
destruction cannot affect an existing plan. All nodes are scheduled, including
|
||||||
including disconnected nodes; only explicit output nodes are rendered (or
|
disconnected nodes; only explicit output nodes are rendered (or terminal nodes
|
||||||
terminal nodes for legacy callers that do not require explicit outputs). See AUDIO_ENGINE.md for contracts.
|
for legacy callers that do not require explicit outputs). See AUDIO_ENGINE.md
|
||||||
`xtc_realtime` now provides a one-pending/one-retired handoff around an
|
for contracts. `xtc_realtime` now provides a one-pending/one-retired handoff
|
||||||
exclusively audio-owned active plan. `xtc_backend` is the C backend boundary;
|
around an exclusively audio-owned active plan. `xtc_backend` is the C backend
|
||||||
the optional JACK implementation drives that same realtime engine.
|
boundary; the optional JACK implementation drives that same realtime engine.
|
||||||
|
|
||||||
## Ownership and threads
|
---
|
||||||
|
|
||||||
|
## Ownership and Threads
|
||||||
|
|
||||||
- GUI thread owns FLTK widgets and view state.
|
- GUI thread owns FLTK widgets and view state.
|
||||||
- Project/control thread owns mutable project data and graph compilation.
|
- Project/control thread owns mutable project data and graph compilation.
|
||||||
|
|
@ -41,53 +48,59 @@ the optional JACK implementation drives that same realtime engine.
|
||||||
- Backend callbacks follow the backend's documented threading contract.
|
- Backend callbacks follow the backend's documented threading contract.
|
||||||
|
|
||||||
Only acknowledged retired plans are reclaimed during processing. Backend close
|
Only acknowledged retired plans are reclaimed during processing. Backend close
|
||||||
synchronizes callbacks before reclaiming remaining plans. See decision 0004
|
synchronizes callbacks before reclaiming remaining plans. See decision 0004 for
|
||||||
for the release/acquire protocol, bounded resource retention and recovery.
|
the release/acquire protocol, bounded resource retention and recovery.
|
||||||
|
|
||||||
## GUI backend ownership
|
---
|
||||||
|
|
||||||
The GUI window owns one C backend handle and serializes all control calls
|
## GUI Backend Ownership
|
||||||
on the GUI thread. A GUI timer reads snapshots and collects retired resources;
|
|
||||||
no audio callback calls FLTK. Successful window close first closes the JACK
|
|
||||||
client (synchronizing callbacks), then removes the GUI timer and hides the
|
|
||||||
window. Failed close leaves both handle and window available for retry. View
|
|
||||||
switching and node positions are GUI state only. Semantic edits use transactional
|
|
||||||
C commands and publish independent compiled snapshots. See GUI.md.
|
|
||||||
|
|
||||||
## Editable graph and canvas
|
The GUI window owns one C backend handle and serializes all control calls on the
|
||||||
|
GUI thread. A GUI timer reads snapshots and collects retired resources; no audio
|
||||||
|
callback calls FLTK. Successful window close first closes the JACK client
|
||||||
|
(synchronizing callbacks), then removes the GUI timer and hides the window.
|
||||||
|
Failed close leaves both handle and window available for retry. View switching
|
||||||
|
and node positions are GUI state only. Semantic edits use transactional C
|
||||||
|
commands and publish independent compiled snapshots. See GUI.md.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Editable Graph and Canvas
|
||||||
|
|
||||||
Read-only C snapshots, monotonic node IDs, and a small set of C edit commands
|
Read-only C snapshots, monotonic node IDs, and a small set of C edit commands
|
||||||
are provided. The GUI owns an opaque graph handle, never private arrays.
|
are provided. The GUI owns an opaque graph handle, never private arrays. An edit
|
||||||
An edit produces a candidate, and the GUI commits it only after backend submit
|
produces a candidate, and the GUI commits it only after backend submit succeeds
|
||||||
succeeds (or locally while offline). A busy pending slot or invalid edit leaves
|
(or locally while offline). A busy pending slot or invalid edit leaves the prior
|
||||||
the prior model/plan unchanged. Active/submitted revisions distinguish the
|
model/plan unchanged. Active/submitted revisions distinguish the queued drawing
|
||||||
queued drawing from the engine's acknowledged plan. Empty/output-less editor
|
from the engine's acknowledged plan. Empty/output-less editor graphs render
|
||||||
graphs render silence; legacy offline terminal fallback remains available.
|
silence; legacy offline terminal fallback remains available.
|
||||||
|
|
||||||
GraphWidget owns only selection, node positions, pointer gestures and drawing.
|
GraphWidget owns only selection, node positions, pointer gestures and drawing.
|
||||||
Its fixed canvas is hosted by FLTK scrolling. C owns nodes, ports, edges,
|
Its fixed canvas is hosted by FLTK scrolling. C owns nodes, ports, edges,
|
||||||
validation, ID assignment, compilation and rendering. No audio thread accesses
|
validation, ID assignment, compilation and rendering. No audio thread accesses
|
||||||
GUI-owned state. Reconnect republishes the same retained editable graph.
|
GUI-owned state. Reconnect republishes the same retained editable graph.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Project ownership and persistence
|
## Project Ownership and Persistence
|
||||||
|
|
||||||
A C-owned project contains the graph, bounded track/clip arrays, stable ID
|
A C-owned project contains the graph, bounded track/clip arrays, stable ID
|
||||||
allocators and constant tempo. Read APIs return copies;
|
allocators and constant tempo. Read APIs return copies; GUI canvases borrow the
|
||||||
GUI canvases borrow the opaque project/graph on the control thread. A graph
|
opaque project/graph on the control thread. A graph edit prepares a candidate
|
||||||
edit prepares a candidate project before submitting its graph, then commits
|
project before submitting its graph, then commits ownership only after
|
||||||
ownership only after acceptance. Arrangement edits currently change silent
|
acceptance. Arrangement edits currently change silent metadata and require no
|
||||||
metadata and require no audio publication.
|
audio publication.
|
||||||
|
|
||||||
Persistence is private C/POSIX code; loading validates an isolated candidate
|
Persistence is private C/POSIX code; loading validates an isolated candidate and
|
||||||
and swaps ownership only after a successful close. The GUI similarly prepares
|
swaps ownership only after a successful close. The GUI similarly prepares a
|
||||||
a loaded document before stopping/submitting audio. File operations never run
|
loaded document before stopping/submitting audio. File operations never run in
|
||||||
in the callback. See PROJECT_FORMAT.md for schema, bounds and durability.
|
the callback. See PROJECT_FORMAT.md for schema, bounds and durability.
|
||||||
SequencerWidget owns selection, zoom and gestures only; musical range checks,
|
SequencerWidget owns selection, zoom and gestures only; musical range checks,
|
||||||
source-preserving trims and ID allocation remain C responsibilities.
|
source-preserving trims and ID allocation remain C responsibilities.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Assets and recording
|
## Assets and Recording
|
||||||
|
|
||||||
Audio paths are C clip metadata. A stopped preparation copies range/offset
|
Audio paths are C clip metadata. A stopped preparation copies range/offset
|
||||||
information, deduplicates paths, validates and preloads bounded WAV assets into
|
information, deduplicates paths, validates and preloads bounded WAV assets into
|
||||||
|
|
@ -102,12 +115,14 @@ and render silence, with repair through a C path setter and GUI relinking.
|
||||||
Version 2 persistence stores references and explicitly migrates version 1 loads.
|
Version 2 persistence stores references and explicitly migrates version 1 loads.
|
||||||
|
|
||||||
Recording has one callback producer and one control-thread consumer. A bounded
|
Recording has one callback producer and one control-thread consumer. A bounded
|
||||||
SPSC ring publishes complete payload blocks through lock-free indices. Only
|
SPSC ring publishes complete payload blocks through lock-free indices. Only the
|
||||||
the consumer writes WAV bytes; finalization follows successful callback stop.
|
consumer writes WAV bytes; finalization follows successful callback stop. No
|
||||||
No editable project pointer, GUI object or FILE is accessed by the producer.
|
editable project pointer, GUI object or FILE is accessed by the producer. See
|
||||||
See decision 0005 and AUDIO_FILES.md for format, limits and recovery contracts.
|
decision 0005 and AUDIO_FILES.md for format, limits and recovery contracts.
|
||||||
|
|
||||||
## MIDI source
|
---
|
||||||
|
|
||||||
|
## MIDI Source
|
||||||
|
|
||||||
The C MIDI plan prepares bounded source-relative notes into sample spans and
|
The C MIDI plan prepares bounded source-relative notes into sample spans and
|
||||||
renders a separate instrument buffer. `xtc_plan_process_sources` and
|
renders a separate instrument buffer. `xtc_plan_process_sources` and
|
||||||
|
|
@ -116,10 +131,12 @@ instrument input; older wrappers supply silence for omitted sources. Graph
|
||||||
instrument nodes consume the shared mono instrument buffer. The backend owns
|
instrument nodes consume the shared mono instrument buffer. The backend owns
|
||||||
prepared MIDI runtime state exclusively while active, with lock-free panic
|
prepared MIDI runtime state exclusively while active, with lock-free panic
|
||||||
requests and no callback allocation/I/O. Stop/seek clear live voices; scheduled
|
requests and no callback allocation/I/O. Stop/seek clear live voices; scheduled
|
||||||
notes chase their absolute phase. See MIDI.md for event ordering, panic semantics,
|
notes chase their absolute phase. See MIDI.md for event ordering, panic
|
||||||
capacities and test coverage. No new dependency is required.
|
semantics, capacities and test coverage. No new dependency is required.
|
||||||
|
|
||||||
## Mix snapshots and history
|
---
|
||||||
|
|
||||||
|
## Mix Snapshots and History
|
||||||
|
|
||||||
`src/mixer` owns validated per-track settings and bounded gain/pan automation.
|
`src/mixer` owns validated per-track settings and bounded gain/pan automation.
|
||||||
Audio/MIDI preparation copies and indexes these into source snapshots; paired
|
Audio/MIDI preparation copies and indexes these into source snapshots; paired
|
||||||
|
|
@ -128,16 +145,19 @@ output-peak snapshots cross to the GUI without exposing DSP state. Mixer edits
|
||||||
stop transport before subsequent preparation. `src/project/history.c` provides
|
stop transport before subsequent preparation. `src/project/history.c` provides
|
||||||
32-edit C project snapshots; checkout clones a candidate and accept moves the
|
32-edit C project snapshots; checkout clones a candidate and accept moves the
|
||||||
cursor only after successful GUI/backend installation. No samples or FLTK state
|
cursor only after successful GUI/backend installation. No samples or FLTK state
|
||||||
are stored in history. `mixer_widget.cpp` is only controls/drawing/gestures.
|
are stored in history. `mixer_widget.cpp` is only controls/drawing/gestures. See
|
||||||
See MIXER.md and PROJECT_FORMAT.md for ownership, limits and v4 migration.
|
MIXER.md and PROJECT_FORMAT.md for ownership, limits and v4 migration.
|
||||||
|
|
||||||
## Native lifecycle and distribution
|
---
|
||||||
|
|
||||||
`xtc_native.h` defines copied versioned C descriptors and bounded block contexts.
|
## Native Lifecycle and Distribution
|
||||||
Native effect/source nodes prepare independent instances on control-thread graph
|
|
||||||
compilation and reclaim them only on compile failure, quiescent destruction or
|
`xtc_native.h` defines copied versioned C descriptors and bounded block
|
||||||
retirement collection. Event instruments can render into the public graph source
|
contexts. Native effect/source nodes prepare independent instances on
|
||||||
buffer. No descriptor/state pointers enter project files; unsupported native
|
control-thread graph compilation and reclaim them only on compile failure,
|
||||||
saves preserve files. See NATIVE_API.md and decision 0008. Release tooling lives
|
quiescent destruction or retirement collection. Event instruments can render
|
||||||
outside the runtime, with source manifests, deterministic exports and staged
|
into the public graph source buffer. No descriptor/state pointers enter project
|
||||||
installation/consumer checks. See RELEASING.md for reproducibility scope.
|
files; unsupported native saves preserve files. See NATIVE_API.md and decision
|
||||||
|
0008. Release tooling lives outside the runtime, with source manifests,
|
||||||
|
deterministic exports and staged installation/consumer checks. See RELEASING.md
|
||||||
|
for reproducibility scope.
|
||||||
|
|
|
||||||
|
|
@ -1,66 +1,146 @@
|
||||||
# Audio source editor workflows
|
# Audio Source Editor Workflows
|
||||||
|
|
||||||
The editor uses the existing bounded mono WAV reader. Stereo input is downmixed;
|
The editor uses the existing bounded mono WAV reader. Stereo input is downmixed;
|
||||||
these are offline control-thread tools, not stereo restoration or time stretching.
|
these are offline control-thread tools, not stereo restoration or time
|
||||||
The project format remains 16. No new dependencies are required.
|
stretching. The project format remains 16. No new dependencies are required.
|
||||||
|
|
||||||
## Source inspection
|
---
|
||||||
|
|
||||||
|
## Source Inspection
|
||||||
|
|
||||||
Select an audio clip and use View / Sample editor or double-click it. The modal
|
Select an audio clip and use View / Sample editor or double-click it. The modal
|
||||||
editor loads an independent snapshot of the complete source, up to 4,194,304 frames
|
editor loads an independent snapshot of the complete source, up to 4,194,304
|
||||||
(about 87 seconds at 48 kHz). Drag or enter half-open native frame bounds; zoom
|
frames (about 87 seconds at 48 kHz). Drag or enter half-open native frame
|
||||||
1..64 and View start control the visible region. Statistics show raw mono min/max,
|
bounds; zoom 1..64 and View start control the visible region. Statistics show
|
||||||
RMS and mean/DC before clip gain, fades or mixer processing. Display clamps to
|
raw mono min/max, RMS and mean/DC before clip gain, fades or mixer processing.
|
||||||
±1; sample statistics retain finite over-range values. Editing project MIDI still
|
Display clamps to ±1; sample statistics retain finite over-range values. Editing
|
||||||
opens the piano roll. This editor does not audition or stream long files.
|
project MIDI still opens the piano roll. This editor does not audition or stream
|
||||||
|
long files.
|
||||||
|
|
||||||
## Trim clip to selection
|
---
|
||||||
|
|
||||||
Trim clip to selection applies source-frame endpoints within the current audible clip. Start rounds up and end rounds down to musical ticks; empty sub-tick ranges reject. Leading removal moves the timeline start by the same amount, preserving alignment. Source content, reference and clip gain/fade settings remain intact; project Undo restores the prior trim.
|
## Trim Clip to Selection
|
||||||
|
|
||||||
## Export and relink
|
Trim clip to selection applies source-frame endpoints within the current audible
|
||||||
|
clip. Start rounds up and end rounds down to musical ticks; empty sub-tick
|
||||||
|
ranges reject. Leading removal moves the timeline start by the same amount,
|
||||||
|
preserving alignment. Source content, reference and clip gain/fade settings
|
||||||
|
remain intact; project Undo restores the prior trim.
|
||||||
|
|
||||||
Export selected frames writes a new mono float32 WAV of the half-open selection at native rate. Save full copy and relink writes the complete source and relinks only the selected clip after successful preparation. The original source is never overwritten. Full-copy adoption requires matching source frame count/rate. Project undo restores the reference but retains the new file, which may be referenced by redo/history or other projects. Failed adoption removes its owned new file. Export/copy runs synchronously outside audio callbacks.
|
---
|
||||||
|
|
||||||
## Reverse selection
|
## Export and Relink
|
||||||
|
|
||||||
Reverse selection changes only the chosen source frames in a new local snapshot. Undo / redo toggles the most recent processing step; selection and view are unchanged. Processing does not affect playback until Save full copy and relink. Close discards unsaved local processing. Sources are bounded to 16 MiB of float samples; preparing a new edit can temporarily retain three snapshots (48 MiB), then two (32 MiB).
|
Export selected frames writes a new mono float32 WAV of the half-open selection
|
||||||
|
at native rate. Save full copy and relink writes the complete source and relinks
|
||||||
|
only the selected clip after successful preparation. The original source is
|
||||||
|
never overwritten. Full-copy adoption requires matching source frame count/rate.
|
||||||
|
Project undo restores the reference but retains the new file, which may be
|
||||||
|
referenced by redo/history or other projects. Failed adoption removes its owned
|
||||||
|
new file. Export/copy runs synchronously outside audio callbacks.
|
||||||
|
|
||||||
## Invert polarity
|
---
|
||||||
|
|
||||||
Invert polarity negates selected float samples; it is not time reversal. Over-range finite samples remain over-range; no implicit limiting is performed. Outside-selection frames are bit-preserved in the copied snapshot.
|
## Reverse Selection
|
||||||
|
|
||||||
## Remove DC offset
|
Reverse selection changes only the chosen source frames in a new local snapshot.
|
||||||
|
Undo / redo toggles the most recent processing step; selection and view are
|
||||||
|
unchanged. Processing does not affect playback until Save full copy and relink.
|
||||||
|
Close discards unsaved local processing. Sources are bounded to 16 MiB of float
|
||||||
|
samples; preparing a new edit can temporarily retain three snapshots (48 MiB),
|
||||||
|
then two (32 MiB).
|
||||||
|
|
||||||
Remove DC offset subtracts the mean of the selected range from only that range. This is a constant offset correction, not a high-pass filter. Selection boundaries may acquire discontinuities; use fades or zero-crossing tools where appropriate. Finite over-range results are retained; float overflow rejects the edit.
|
---
|
||||||
|
|
||||||
## Sample fades
|
## Invert Polarity
|
||||||
|
|
||||||
Sample fades offers four offline curves: linear in/out and equal-power in/out (sinusoidal amplitude). The entire selection is the fade duration; both endpoints are included in the curve. Fewer than two frames reject. These curves change copied sample data and stack with existing playback clip fades after adoption; they do not form a linked clip crossfade.
|
Invert polarity negates selected float samples; it is not time reversal.
|
||||||
|
Over-range finite samples remain over-range; no implicit limiting is performed.
|
||||||
|
Outside-selection frames are bit-preserved in the copied snapshot.
|
||||||
|
|
||||||
## Gain and normalize
|
---
|
||||||
|
|
||||||
Gain / normalize processes only selected samples. Mode 0 accepts linear gain 0..16; mode 1 accepts a linear peak target above 0 and at most 1, rejecting silent selections or required gain above 16. Finite values above unity are not clipped; float overflow rejects atomically. This changes sample data in the local snapshot, unlike the existing clip-gain normalization command; it provides neither true-peak nor LUFS processing.
|
## Remove DC Offset
|
||||||
|
|
||||||
## Select audible bounds
|
Remove DC offset subtracts the mean of the selected range from only that range.
|
||||||
|
This is a constant offset correction, not a high-pass filter. Selection
|
||||||
|
boundaries may acquire discontinuities; use fades or zero-crossing tools where
|
||||||
|
appropriate. Finite over-range results are retained; float overflow rejects the
|
||||||
|
edit.
|
||||||
|
|
||||||
Select audible bounds finds the first and last sample strictly above the chosen dBFS threshold and pads within the existing selection. It only changes selection; use Trim clip to selection to apply a nondestructive timeline trim, or export the selection. Entirely silent/below-threshold ranges leave selection unchanged. This is boundary detection, not automatic removal of internal gaps or a noise gate.
|
---
|
||||||
|
|
||||||
## Snap to zero crossings
|
## Sample Fades
|
||||||
|
|
||||||
Snap to zero crossings searches each selected boundary within a source-frame radius up to 65,536. It uses the mono source, chooses earlier positions on equal distance and changes both endpoints only if both searches yield a nonempty range. Source edges qualify only when their adjacent sample is zero. This can reduce boundary discontinuities but does not guarantee click-free output; musical-tick trimming/slicing can move a boundary away from the exact crossing.
|
Sample fades offers four offline curves: linear in/out and equal-power in/out
|
||||||
|
(sinusoidal amplitude). The entire selection is the fade duration; both
|
||||||
|
endpoints are included in the curve. Fewer than two frames reject. These curves
|
||||||
|
change copied sample data and stack with existing playback clip fades after
|
||||||
|
adoption; they do not form a linked clip crossfade.
|
||||||
|
|
||||||
## Detect attacks
|
---
|
||||||
|
|
||||||
Detect attacks uses absolute sample amplitude, an initial armed state, rearming below one quarter of the threshold and a minimum frame gap between retained attacks. It marks up to 128 source positions in orange; hovering the statistics shows exact frame indices. This is a threshold detector, not spectral onset detection, beat detection or tempo estimation. Selection/processing changes invalidate the markers. Slice clip at attacks splits the current clip reference at those positions in one project undo step and closes the editor. Edits in the local buffer must be saved/relinked first if the slices should use processed audio. Source positions round to nearest musical ticks; out-of-trim, edge and coalesced cuts are skipped. No usable cuts rejects. Left ID, source references and outside fades remain; inner explicit fades clear. Long explicit fades and existing automatic region fades can sound different after splitting. Timeline/source rounding may differ by one sample, so this is not sample-accurate timeline slicing. The no-explicit-fade aligned regression fixture remains bit-identical across slicing. No media files are written by slicing.
|
## Gain and Normalize
|
||||||
|
|
||||||
## Validation and timing limits
|
Gain / normalize processes only selected samples. Mode 0 accepts linear gain
|
||||||
|
0..16; mode 1 accepts a linear peak target above 0 and at most 1, rejecting
|
||||||
|
silent selections or required gain above 16. Finite values above unity are not
|
||||||
|
clipped; float overflow rejects atomically. This changes sample data in the
|
||||||
|
local snapshot, unlike the existing clip-gain normalization command; it provides
|
||||||
|
neither true-peak nor LUFS processing.
|
||||||
|
|
||||||
Focused model and GUI checks pass for each operation.
|
---
|
||||||
The integrated checks add allocation failure/cleanup, oversized sources, overflow,
|
|
||||||
clip ID rollback, exact selected samples, persistence, no-fade render comparison,
|
## Select Audible Bounds
|
||||||
plugin fixtures, software JACK, Clang analysis, ASan/UBSan and install layouts.
|
|
||||||
The actual source editor and attack markers are shown in the
|
Select audible bounds finds the first and last sample strictly above the chosen
|
||||||
|
dBFS threshold and pads within the existing selection. It only changes
|
||||||
|
selection; use Trim clip to selection to apply a nondestructive timeline trim,
|
||||||
|
or export the selection. Entirely silent/below-threshold ranges leave selection
|
||||||
|
unchanged. This is boundary detection, not automatic removal of internal gaps or
|
||||||
|
a noise gate.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Snap to Zero Crossings
|
||||||
|
|
||||||
|
Snap to zero crossings searches each selected boundary within a source-frame
|
||||||
|
radius up to 65,536. It uses the mono source, chooses earlier positions on equal
|
||||||
|
distance and changes both endpoints only if both searches yield a nonempty
|
||||||
|
range. Source edges qualify only when their adjacent sample is zero. This can
|
||||||
|
reduce boundary discontinuities but does not guarantee click-free output;
|
||||||
|
musical-tick trimming/slicing can move a boundary away from the exact crossing.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Detect Attacks
|
||||||
|
|
||||||
|
Detect attacks uses absolute sample amplitude, an initial armed state, rearming
|
||||||
|
below one quarter of the threshold and a minimum frame gap between retained
|
||||||
|
attacks. It marks up to 128 source positions in orange; hovering the statistics
|
||||||
|
shows exact frame indices. This is a threshold detector, not spectral onset
|
||||||
|
detection, beat detection or tempo estimation. Selection/processing changes
|
||||||
|
invalidate the markers. Slice clip at attacks splits the current clip reference
|
||||||
|
at those positions in one project undo step and closes the editor. Edits in the
|
||||||
|
local buffer must be saved/relinked first if the slices should use processed
|
||||||
|
audio. Source positions round to nearest musical ticks; out-of-trim, edge and
|
||||||
|
coalesced cuts are skipped. No usable cuts rejects. Left ID, source references
|
||||||
|
and outside fades remain; inner explicit fades clear. Long explicit fades and
|
||||||
|
existing automatic region fades can sound different after splitting.
|
||||||
|
Timeline/source rounding may differ by one sample, so this is not
|
||||||
|
sample-accurate timeline slicing. The no-explicit-fade aligned regression
|
||||||
|
fixture remains bit-identical across slicing. No media files are written by
|
||||||
|
slicing.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Validation and Timing Limits
|
||||||
|
|
||||||
|
Focused model and GUI checks pass for each operation. The integrated checks add
|
||||||
|
allocation failure/cleanup, oversized sources, overflow, clip ID rollback, exact
|
||||||
|
selected samples, persistence, no-fade render comparison, plugin fixtures,
|
||||||
|
software JACK, Clang analysis, ASan/UBSan and install layouts. The actual source
|
||||||
|
editor and attack markers are shown in the
|
||||||
[screenshot gallery](../screenshots/README.md).
|
[screenshot gallery](../screenshots/README.md).
|
||||||
|
|
||||||
Trim placement preserves alignment in musical ticks; independent source/timeline
|
Trim placement preserves alignment in musical ticks; independent source/timeline
|
||||||
|
|
@ -69,5 +149,5 @@ click-free transitions are promised. Clip source data outside a local processing
|
||||||
selection remains intact; exported selections contain only their chosen frames.
|
selection remains intact; exported selections contain only their chosen frames.
|
||||||
Closing the editor discards unsaved local processing. Successful project Undo
|
Closing the editor discards unsaved local processing. Successful project Undo
|
||||||
keeps generated files for redo/history; only failed adoption removes its owned
|
keeps generated files for redo/history; only failed adoption removes its owned
|
||||||
new output. Rejecting sources above the editor's frame limit may temporarily
|
new output. Rejecting sources above the editor's frame limit may temporarily use
|
||||||
use the existing WAV reader's larger decode bound before rejecting them.
|
the existing WAV reader's larger decode bound before rejecting them.
|
||||||
|
|
|
||||||
|
|
@ -1,128 +1,142 @@
|
||||||
# Audio engine requirements
|
# Audio Engine Requirements
|
||||||
|
|
||||||
## Real-time callback rules
|
## Real-Time Callback Rules
|
||||||
|
|
||||||
The callback must not allocate/free memory, lock blocking mutexes, perform
|
The callback must not allocate/free memory, lock blocking mutexes, perform
|
||||||
filesystem/network/console I/O, log, load plugins or samples, call GUI APIs,
|
filesystem/network/console I/O, log, load plugins or samples, call GUI APIs, or
|
||||||
or wait for another thread.
|
wait for another thread.
|
||||||
|
|
||||||
Use preallocated buffers and bounded work. Publish parameter and graph changes
|
Use preallocated buffers and bounded work. Publish parameter and graph changes
|
||||||
through a documented real-time-safe mechanism. Verify atomics are lock-free
|
through a documented real-time-safe mechanism. Verify atomics are lock-free
|
||||||
where required on the target platform.
|
where required on the target platform.
|
||||||
|
|
||||||
## Processing model
|
---
|
||||||
|
|
||||||
|
## Processing Model
|
||||||
|
|
||||||
Process a bounded number of frames per block. Do not assume a fixed block size
|
Process a bounded number of frames per block. Do not assume a fixed block size
|
||||||
unless the backend guarantees it. Define maximum frame and event counts and
|
unless the backend guarantees it. Define maximum frame and event counts and safe
|
||||||
safe behavior when those limits are reached.
|
behavior when those limits are reached.
|
||||||
|
|
||||||
The initial milestone is offline processing, then a test oscillator -> gain ->
|
The initial milestone is offline processing, then a test oscillator -> gain ->
|
||||||
meter/output graph, then a hardware backend.
|
meter/output graph, then a hardware backend.
|
||||||
|
|
||||||
## Clock and transport
|
---
|
||||||
|
|
||||||
|
## Clock and Transport
|
||||||
|
|
||||||
Audio sample position is the authoritative playback clock. Use integer or
|
Audio sample position is the authoritative playback clock. Use integer or
|
||||||
rational timeline representations to avoid cumulative floating-point drift.
|
rational timeline representations to avoid cumulative floating-point drift.
|
||||||
Define tempo-map conversion and behavior at tempo changes before implementing
|
Define tempo-map conversion and behavior at tempo changes before implementing
|
||||||
tempo automation.
|
tempo automation.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Offline API
|
## Offline API
|
||||||
|
|
||||||
`xtc_graph_create` accepts 1..256 nodes; IDs are monotonic stable identifiers, never reused
|
`xtc_graph_create` accepts 1..256 nodes; IDs are monotonic stable identifiers,
|
||||||
within a graph's lifetime. Enumeration indexes are dense and distinct from IDs. Supported nodes are gain (any finite multiplier), sine
|
never reused within a graph's lifetime. Enumeration indexes are dense and
|
||||||
|
distinct from IDs. Supported nodes are gain (any finite multiplier), sine
|
||||||
oscillator (finite nonnegative Hz), pass-through peak meter and audio output.
|
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
|
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
|
output nodes have no output. Port lookup reports direction, signal type and
|
||||||
channel count. MIDI/control ports and channel conversion are not implemented;
|
channel count. MIDI/control ports and channel conversion are not implemented;
|
||||||
invalid ports/directions, duplicate edges and cycles are rejected before an
|
invalid ports/directions, duplicate edges and cycles are rejected before an edit
|
||||||
edit becomes visible. Fan-out copies a source to consumers; fan-in sums inputs
|
becomes visible. Fan-out copies a source to consumers; fan-in sums inputs
|
||||||
without normalization. Failed additions leave IDs and graph contents unchanged.
|
without normalization. Failed additions leave IDs and graph contents unchanged.
|
||||||
|
|
||||||
`xtc_graph_compile(graph, sample_rate, max_frames, &plan)` runs on the control
|
`xtc_graph_compile(graph, sample_rate, max_frames, &plan)` runs on the control
|
||||||
thread. Empty graphs compile to silence. Sample rate must be finite and positive,
|
thread. Empty graphs compile to silence. Sample rate must be finite and
|
||||||
oscillators must be at or below Nyquist, and max_frames is 1..65536. Compilation
|
positive, oscillators must be at or below Nyquist, and max_frames is 1..65536.
|
||||||
allocates and copies topology/parameters, builds a topological schedule and
|
Compilation allocates and copies topology/parameters, builds a topological
|
||||||
input adjacency, and allocates paired max_frames float buffers per node for stereo. The
|
schedule and input adjacency, and allocates paired max_frames float buffers per
|
||||||
maximum buffer storage is 128 MiB per plan (32 MiB for the GUI 64-node limit). Compilation may fail with an
|
node for stereo. The maximum buffer storage is 128 MiB per plan (32 MiB for the
|
||||||
allocation error; output plan is then NULL. Destroy a plan on the control thread.
|
GUI 64-node limit). 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,
|
`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
|
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
|
return capacity errors without modifying output or state. Output storage must
|
||||||
hold frame_count floats. NULL input means silence; input/output may alias.
|
hold frame_count floats. NULL input means silence; input/output may alias. Zero
|
||||||
Zero frames leaves all state unchanged. No plan operations may run concurrently
|
frames leaves all state unchanged. No plan operations may run concurrently with
|
||||||
with processing, including reset, meter reads or destruction.
|
processing, including reset, meter reads or destruction.
|
||||||
|
|
||||||
Unconnected non-oscillator nodes receive external input. Connected inputs
|
Unconnected non-oscillator nodes receive external input. Connected inputs
|
||||||
receive only the sum of their upstream buffers. Explicit output nodes are
|
receive only the sum of their upstream buffers. Explicit output nodes are summed
|
||||||
summed to the caller's output. If none exist, terminal nodes are summed for
|
to the caller's output. If none exist, terminal nodes are summed for
|
||||||
compatibility with the original gain-chain API, unless
|
compatibility with the original gain-chain API, unless
|
||||||
`xtc_graph_require_output_nodes(graph, 1)` is set. The GUI uses that policy;
|
`xtc_graph_require_output_nodes(graph, 1)` is set. The GUI uses that policy; no
|
||||||
no output nodes means silence. Disconnected components cannot
|
output nodes means silence. Disconnected components cannot contribute when
|
||||||
contribute when explicit outputs exist, but they are still processed. Floating
|
explicit outputs exist, but they are still processed. Floating point overflow
|
||||||
point overflow and nonfinite input become silence per sample. No clipping or
|
and nonfinite input become silence per sample. No clipping or normalization is
|
||||||
normalization is applied to finite samples.
|
applied to finite samples.
|
||||||
|
|
||||||
Oscillators start at phase zero and carry phase continuously across blocks;
|
Oscillators start at phase zero and carry phase continuously across blocks;
|
||||||
reset clears phases and meter peaks. Meter reads return the last nonempty
|
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
|
block's absolute peak. These are same-thread reads, not a thread-safe GUI meter
|
||||||
meter bridge. Rendering is deterministic on the same build/platform regardless
|
bridge. Rendering is deterministic on the same build/platform regardless of
|
||||||
of block partitioning; libm results need not be bit-identical across platforms.
|
block partitioning; libm results need not be bit-identical across platforms.
|
||||||
|
|
||||||
`xtc_graph_process_offline` remains a convenience helper, compiling at 48000 Hz
|
`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
|
and destroying the plan after one block. It accepts a finite external-input gain
|
||||||
gain and requires non-NULL input/output. It now follows routing rather than
|
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
|
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.
|
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
|
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
|
meter output, reset and partition equivalence, fan-out/fan-in, reverse insertion
|
||||||
order, disconnected nodes, in-place processing, nonfinite input, invalid ports,
|
order, disconnected nodes, in-place processing, nonfinite input, invalid ports,
|
||||||
cycles, capacity limits, plan lifetime and repeated compilation/cleanup.
|
cycles, capacity limits, plan lifetime and repeated compilation/cleanup. The
|
||||||
The offline API remains single-owner. The realtime/backend APIs below add
|
offline API remains single-owner. The realtime/backend APIs below add
|
||||||
publication and JACK processing; offline tests alone do not qualify hardware.
|
publication and JACK processing; offline tests alone do not qualify hardware.
|
||||||
|
|
||||||
## Backend and realtime bridge
|
---
|
||||||
|
|
||||||
|
## Backend and Realtime Bridge
|
||||||
|
|
||||||
Use `xtc_backend.h` on one serialized control thread:
|
Use `xtc_backend.h` on one serialized control thread:
|
||||||
|
|
||||||
1. Open a config with `XTC_BACKEND_JACK`, a client name, channel_count 1 (or 2 for stereo output), and
|
1. Open a config with `XTC_BACKEND_JACK`, a client name, channel_count 1 (or 2
|
||||||
max_frames 1..65536. It must accommodate the server's current buffer size.
|
for stereo output), and max_frames 1..65536. It must accommodate the server's
|
||||||
The actual rate and buffer size are returned through get_status. Open does
|
current buffer size. The actual rate and buffer size are returned through
|
||||||
not start the server or acquire devices directly. Invalid config returns
|
get_status. Open does not start the server or acquire devices directly.
|
||||||
invalid argument, missing build support returns unsupported, and JACK setup
|
Invalid config returns invalid argument, missing build support returns
|
||||||
failures return I/O error. If cleanup itself fails, a non-NULL output handle
|
unsupported, and JACK setup failures return I/O error. If cleanup itself
|
||||||
is preserved for close retry; no other operation is allowed on that handle.
|
fails, a non-NULL output handle is preserved for close retry; no other
|
||||||
2. Submit a graph (copied/compiled at the server rate), then start. Starting
|
operation is allowed on that handle.
|
||||||
an already running client is an invalid-state error; stopping a stopped
|
2. Submit a graph (copied/compiled at the server rate), then start. Starting an
|
||||||
client succeeds. With no submitted graph, callbacks produce silence.
|
already running client is an invalid-state error; stopping a stopped client
|
||||||
|
succeeds. With no submitted graph, callbacks produce silence.
|
||||||
3. Enumerate available audio ports with visit_ports. Names are borrowed only
|
3. Enumerate available audio ports with visit_ports. Names are borrowed only
|
||||||
during the visitor; do not reenter backend operations from the visitor.
|
during the visitor; do not reenter backend operations from the visitor.
|
||||||
Connect the client's input to a remote output or its output to a remote
|
Connect the client's input to a remote output or its output to a remote input
|
||||||
input explicitly. JACK maps device selection to server/device port routes;
|
explicitly. JACK maps device selection to server/device port routes; ALSA
|
||||||
ALSA device identifiers are not accepted here. The server controls rate,
|
device identifiers are not accepted here. The server controls rate, period
|
||||||
period and hardware configuration outside this API. Names/ports can disappear
|
and hardware configuration outside this API. Names/ports can disappear
|
||||||
between enumeration and connection; route failures are returned as I/O errors.
|
between enumeration and connection; route failures are returned as I/O
|
||||||
|
errors.
|
||||||
4. During playback, submit edited graphs and periodically collect retired
|
4. During playback, submit edited graphs and periodically collect retired
|
||||||
resources. Capacity means one pending graph is still awaiting adoption;
|
resources. Capacity means one pending graph is still awaiting adoption; keep
|
||||||
keep the current graph and retry later. Stopped submissions instead compile
|
the current graph and retry later. Stopped submissions instead compile a
|
||||||
a replacement engine off-thread and swap only after success, while callbacks
|
replacement engine off-thread and swap only after success, while callbacks
|
||||||
are quiescent. Its block/revision counters restart and oscillator phase resets;
|
are quiescent. Its block/revision counters restart and oscillator phase
|
||||||
no edit is blocked behind a plan that cannot be adopted until playback. get_status is a nonblocking snapshot
|
resets; no edit is blocked behind a plan that cannot be adopted until
|
||||||
of rate, frames, running/server-loss/rate-change flags, xruns, processed
|
playback. get_status is a nonblocking snapshot of rate, frames,
|
||||||
blocks and last process result. No active DSP memory is exposed.
|
running/server-loss/rate-change flags, xruns, processed blocks and last
|
||||||
|
process result. No active DSP memory is exposed.
|
||||||
5. Stop pauses the retained DSP state after deactivation. Restart resumes it.
|
5. Stop pauses the retained DSP state after deactivation. Restart resumes it.
|
||||||
Close removes the JACK client, synchronizes all callbacks, then destroys
|
Close removes the JACK client, synchronizes all callbacks, then destroys
|
||||||
plans. Stop/close failures preserve the handle for recovery/retry. No plan
|
plans. Stop/close failures preserve the handle for recovery/retry. No plan is
|
||||||
is freed on the audio thread. Sample-rate change or server loss requires
|
freed on the audio thread. Sample-rate change or server loss requires
|
||||||
close/reopen and a fresh submission; there is no automatic reconnect.
|
close/reopen and a fresh submission; there is no automatic reconnect.
|
||||||
|
|
||||||
Buffers can change size. In-limit changes process normally; oversized blocks
|
Buffers can change size. In-limit changes process normally; oversized blocks are
|
||||||
are silent and report capacity errors until the size is supported again.
|
silent and report capacity errors until the size is supported again. Rate
|
||||||
Rate changes latch silence and invalid-state processing results. A missing input
|
changes latch silence and invalid-state processing results. A missing input
|
||||||
buffer is treated as unavailable input (silence). A missing output buffer is
|
buffer is treated as unavailable input (silence). A missing output buffer is
|
||||||
reported as an I/O process error. Shutdown callbacks only set the loss flag;
|
reported as an I/O process error. Shutdown callbacks only set the loss flag; the
|
||||||
the control thread closes the client. No JACK or GUI types cross the C API.
|
control thread closes the client. No JACK or GUI types cross the C API.
|
||||||
|
|
||||||
The standalone `xtc_realtime.h` API allows hardware-independent consumers and
|
The standalone `xtc_realtime.h` API allows hardware-independent consumers and
|
||||||
stress tests. Submit compiles on the producer; process adopts at a block
|
stress tests. Submit compiles on the producer; process adopts at a block
|
||||||
|
|
@ -134,12 +148,15 @@ JACK notification callbacks were audited for prohibited operations; JACK's own
|
||||||
internal realtime guarantees depend on the installed implementation/server.
|
internal realtime guarantees depend on the installed implementation/server.
|
||||||
|
|
||||||
Validation commands and results are recorded in BUILD.md and the integration
|
Validation commands and results are recorded in BUILD.md and the integration
|
||||||
test README. Current limitations: mono input, no crossfaded graph changes, no automatic reconnect,
|
test README. Current limitations: mono input, no crossfaded graph changes, no
|
||||||
no physical-device or long-duration endurance qualification. The FLTK shell is
|
automatic reconnect, no physical-device or long-duration endurance
|
||||||
connected to backend controls and status; see GUI.md. Its editors remain
|
qualification. The FLTK shell is connected to backend controls and status; see
|
||||||
placeholders except the modular editor described below.
|
GUI.md. Its editors remain placeholders except the modular editor described
|
||||||
|
below.
|
||||||
|
|
||||||
## Graph snapshots and edits
|
---
|
||||||
|
|
||||||
|
## Graph Snapshots and Edits
|
||||||
|
|
||||||
The control-thread API exposes copies through get_counts, get_node(index) and
|
The control-thread API exposes copies through get_counts, get_node(index) and
|
||||||
get_connection(index), including node IDs/types/values and port endpoints. No
|
get_connection(index), including node IDs/types/values and port endpoints. No
|
||||||
|
|
@ -154,17 +171,17 @@ and returns a caller-owned candidate on success. On failure candidate is NULL,
|
||||||
source and added_id are unchanged. added_id is optional and written only for
|
source and added_id are unchanged. added_id is optional and written only for
|
||||||
ADD_NODE. ADD_NODE validates type and the used parameter (finite gain, or finite
|
ADD_NODE. ADD_NODE validates type and the used parameter (finite gain, or finite
|
||||||
nonnegative oscillator Hz). Meter/output do not use the value field. Compile
|
nonnegative oscillator Hz). Meter/output do not use the value field. Compile
|
||||||
additionally checks the oscillator against the actual sample rate. Removing
|
additionally checks the oscillator against the actual sample rate. Removing a
|
||||||
a node removes its incident connections; disconnecting a nonexistent edge
|
node removes its incident connections; disconnecting a nonexistent edge returns
|
||||||
returns not-found. Missing nodes/ports, reversed directions, duplicate edges,
|
not-found. Missing nodes/ports, reversed directions, duplicate edges, cycles and
|
||||||
cycles and unknown command/type values are rejected without visible edits.
|
unknown command/type values are rejected without visible edits.
|
||||||
|
|
||||||
The GUI keeps a 64-node graph requiring explicit output nodes. It creates a
|
The GUI keeps a 64-node graph requiring explicit output nodes. It creates a
|
||||||
candidate, submits that exact candidate to the backend, then swaps its owned
|
candidate, submits that exact candidate to the backend, then swaps its owned
|
||||||
graph and refreshes the canvas only if submission succeeds. Failed compile or
|
graph and refreshes the canvas only if submission succeeds. Failed compile or
|
||||||
pending-slot pressure destroys the candidate and retains both the displayed
|
pending-slot pressure destroys the candidate and retains both the displayed
|
||||||
graph and previously submitted engine plan. When disconnected at startup,
|
graph and previously submitted engine plan. When disconnected at startup, edits
|
||||||
edits can be stored locally and are submitted on reconnect. Lost/changed active
|
can be stored locally and are submitted on reconnect. Lost/changed active
|
||||||
backends reject edits until reconnect. Reconnect submits the retained graph.
|
backends reject edits until reconnect. Reconnect submits the retained graph.
|
||||||
|
|
||||||
Submitted/active revision counters expose adoption without exposing plan
|
Submitted/active revision counters expose adoption without exposing plan
|
||||||
|
|
@ -181,20 +198,21 @@ silent under the GUI policy. Terminal fallback remains the default for earlier
|
||||||
offline/standalone callers. Input on unconnected nodes retains the existing
|
offline/standalone callers. Input on unconnected nodes retains the existing
|
||||||
external-input contract; the GUI does not connect external JACK ports.
|
external-input contract; the GUI does not connect external JACK ports.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Transport
|
## Transport
|
||||||
|
|
||||||
Backend status includes a uint64 sample_position. Each successful processing
|
Backend status includes a uint64 sample_position. Each successful processing
|
||||||
callback advances it by its exact frame count (including silence); errors do
|
callback advances it by its exact frame count (including silence); errors do not
|
||||||
not advance it. The counter uses compiler atomics, verified always lock-free
|
advance it. The counter uses compiler atomics, verified always lock-free before
|
||||||
before backend setup, with overflow detected rather than wrapped. No extra
|
backend setup, with overflow detected rather than wrapped. No extra allocation,
|
||||||
allocation, I/O, mutex or GUI work occurs in callbacks. Fields remain individually
|
I/O, mutex or GUI work occurs in callbacks. Fields remain individually coherent
|
||||||
coherent snapshots.
|
snapshots.
|
||||||
|
|
||||||
Stop pauses the clock. Start resumes; stopped and running graph submissions
|
Stop pauses the clock. Start resumes; stopped and running graph submissions
|
||||||
preserve position even when plan/revision counters reset. Reopen starts at zero.
|
preserve position even when plan/revision counters reset. Reopen starts at zero.
|
||||||
xtc_backend_seek changes position only on a healthy stopped backend; it does
|
xtc_backend_seek changes position only on a healthy stopped backend; it does not
|
||||||
not rewind oscillator phase. Project tick/sample conversions use integer floor
|
rewind oscillator phase. Project tick/sample conversions use integer floor
|
||||||
arithmetic at constant tempo, with explicit capacity errors and rates 1..768000.
|
arithmetic at constant tempo, with explicit capacity errors and rates 1..768000.
|
||||||
The GUI observes the counter every 100 ms, so visual updates are block-quantized
|
The GUI observes the counter every 100 ms, so visual updates are block-quantized
|
||||||
and delayed by polling. No external JACK transport synchronization is provided.
|
and delayed by polling. No external JACK transport synchronization is provided.
|
||||||
|
|
@ -203,8 +221,9 @@ Silent clip metadata is control-thread data, never traversed by the callback.
|
||||||
Audio/MIDI scheduling uses compiled event/clip plans rather than direct callback
|
Audio/MIDI scheduling uses compiled event/clip plans rather than direct callback
|
||||||
access to the editable project.
|
access to the editable project.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Audio source and recording
|
## Audio Source and Recording
|
||||||
|
|
||||||
xtc_audio.h provides control-thread import and immutable preloaded clip plans.
|
xtc_audio.h provides control-thread import and immutable preloaded clip plans.
|
||||||
The backend prepares a project only while stopped: build audio candidate,
|
The backend prepares a project only while stopped: build audio candidate,
|
||||||
|
|
@ -214,31 +233,33 @@ assets produce explicit issue metadata and silence; OOM/capacity fails.
|
||||||
Graph-only edits still use the existing pending/retired mechanism while running.
|
Graph-only edits still use the existing pending/retired mechanism while running.
|
||||||
|
|
||||||
Each callback renders the plan into a preallocated mono timeline buffer using
|
Each callback renders the plan into a preallocated mono timeline buffer using
|
||||||
the authoritative sample position. xtc_realtime_process_audio passes that
|
the authoritative sample position. xtc_realtime_process_audio passes that buffer
|
||||||
buffer into the compiled graph; XTC_NODE_AUDIO (output port only) reads it,
|
into the compiled graph; XTC_NODE_AUDIO (output port only) reads it,
|
||||||
independently from external JACK input. The old process APIs remain wrappers
|
independently from external JACK input. The old process APIs remain wrappers
|
||||||
with a silent timeline. Import creates a source/output route if necessary.
|
with a silent timeline. Import creates a source/output route if necessary. No
|
||||||
No samples or GUI/project arrays are shared with editable state. Clip mixing,
|
samples or GUI/project arrays are shared with editable state. Clip mixing, rate
|
||||||
rate conversion and graph processing are bounded; see AUDIO_FILES.md for limits.
|
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
|
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
|
is copied to its SPSC ring before graph processing. Producer and consumer index
|
||||||
release/acquire operations protect payload ownership; all atomics are checked
|
release/acquire operations protect payload ownership; all atomics are checked
|
||||||
always lock-free. The control thread drains to a temporary float32 WAV, then
|
always lock-free. The control thread drains to a temporary float32 WAV, then
|
||||||
finalizes only after successful stop/close has synchronized the callback.
|
finalizes only after successful stop/close has synchronized the callback. An
|
||||||
An overflowing ring or unavailable input creates a sticky error; later input is
|
overflowing ring or unavailable input creates a sticky error; later input is
|
||||||
dropped, reported and never silently joined into a continuous-looking take.
|
dropped, reported and never silently joined into a continuous-looking take. A
|
||||||
A partial overflow take is finalized for manual recovery. File errors retain
|
partial overflow take is finalized for manual recovery. File errors retain the
|
||||||
the previous destination and remove unfinished temporaries.
|
previous destination and remove unfinished temporaries.
|
||||||
|
|
||||||
GUI recording uses a two-second ring and 100 ms control-thread draining, with
|
GUI recording uses a two-second ring and 100 ms control-thread draining, with no
|
||||||
no worker thread. A GUI stall can overflow it. No callback allocation/free, file
|
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
|
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.
|
borrowed recorder; the caller must not free it before successful quiescence.
|
||||||
Live software source/capture acceptance and concurrent ring tests pass; physical
|
Live software source/capture acceptance and concurrent ring tests pass; physical
|
||||||
recording, latency compensation and disk endurance remain unverified.
|
recording, latency compensation and disk endurance remain unverified.
|
||||||
|
|
||||||
## MIDI source
|
---
|
||||||
|
|
||||||
|
## MIDI Source
|
||||||
|
|
||||||
The C MIDI plan prepares bounded source-relative notes into sample spans and
|
The C MIDI plan prepares bounded source-relative notes into sample spans and
|
||||||
renders a separate instrument buffer. `xtc_plan_process_sources` and
|
renders a separate instrument buffer. `xtc_plan_process_sources` and
|
||||||
|
|
@ -247,10 +268,12 @@ instrument input; older wrappers supply silence for omitted sources. Graph
|
||||||
instrument nodes consume the shared mono instrument buffer. The backend owns
|
instrument nodes consume the shared mono instrument buffer. The backend owns
|
||||||
prepared MIDI runtime state exclusively while active, with lock-free panic
|
prepared MIDI runtime state exclusively while active, with lock-free panic
|
||||||
requests and no callback allocation/I/O. Stop/seek clear live voices; scheduled
|
requests and no callback allocation/I/O. Stop/seek clear live voices; scheduled
|
||||||
notes chase their absolute phase. See MIDI.md for event ordering, panic semantics,
|
notes chase their absolute phase. See MIDI.md for event ordering, panic
|
||||||
capacities and test coverage. No new dependency is required.
|
semantics, capacities and test coverage. No new dependency is required.
|
||||||
|
|
||||||
## Stereo mixing and automation
|
---
|
||||||
|
|
||||||
|
## Stereo Mixing and Automation
|
||||||
|
|
||||||
Track settings and automation are copied into immutable source-plan snapshots.
|
Track settings and automation are copied into immutable source-plan snapshots.
|
||||||
`xtc_audio_plan_render_stereo` and `xtc_midi_plan_render_stereo` pan track audio
|
`xtc_audio_plan_render_stereo` and `xtc_midi_plan_render_stereo` pan track audio
|
||||||
|
|
@ -260,11 +283,13 @@ retain gain/mute/solo/automation but ignore pan. `xtc_plan_process_stereo` and
|
||||||
with one oscillator phase advance, preserving mono APIs and graph publication.
|
with one oscillator phase advance, preserving mono APIs and graph publication.
|
||||||
The backend preallocates paired buffers, registers an optional output_right port
|
The backend preallocates paired buffers, registers an optional output_right port
|
||||||
and publishes independently atomic output peak snapshots. Callback work remains
|
and publishes independently atomic output peak snapshots. Callback work remains
|
||||||
bounded and allocation/I/O/lock free. Meter UI reads no active plan memory.
|
bounded and allocation/I/O/lock free. Meter UI reads no active plan memory. See
|
||||||
See MIXER.md for exact pan law, automation interpolation, event/source exceptions,
|
MIXER.md for exact pan law, automation interpolation, event/source exceptions,
|
||||||
memory/history bounds and verification. Input/recording remain mono.
|
memory/history bounds and verification. Input/recording remain mono.
|
||||||
|
|
||||||
## Native processing
|
---
|
||||||
|
|
||||||
|
## Native Processing
|
||||||
|
|
||||||
Graph-native effects/sources use copied versioned descriptors, two independently
|
Graph-native effects/sources use copied versioned descriptors, two independently
|
||||||
prepared mono instances and the existing plan ownership/retirement protocol.
|
prepared mono instances and the existing plan ownership/retirement protocol.
|
||||||
|
|
@ -274,19 +299,24 @@ without rolling back already advanced DSP. Native event instruments can render
|
||||||
explicitly into graph instrument buffers. See NATIVE_API.md for exact lifecycle
|
explicitly into graph instrument buffers. See NATIVE_API.md for exact lifecycle
|
||||||
and serialization limits and PERFORMANCE.md for measured workload and budgets.
|
and serialization limits and PERFORMANCE.md for measured workload and budgets.
|
||||||
|
|
||||||
## Ownership audit
|
---
|
||||||
|
|
||||||
|
## Ownership Audit
|
||||||
|
|
||||||
[RELIABILITY.md](RELIABILITY.md) records resource owners, publication and
|
[RELIABILITY.md](RELIABILITY.md) records resource owners, publication and
|
||||||
reclamation ordering, callback work bounds and repeatable diagnostic tests.
|
reclamation ordering, callback work bounds and repeatable diagnostic tests.
|
||||||
Graph stereo rendering completes both channels before writing caller outputs;
|
Graph stereo rendering completes both channels before writing caller outputs;
|
||||||
either output may equal a source, but the output buffers must not overlap.
|
either output may equal a source, but the output buffers must not overlap.
|
||||||
|
|
||||||
## Quality policy
|
---
|
||||||
|
|
||||||
[AUDIO_QUALITY.md](AUDIO_QUALITY.md) defines absolute musical timing, tempo snapshot
|
## Quality Policy
|
||||||
changes, scheduled source envelopes and configurable master transitions. The GUI
|
|
||||||
enables 5 ms fades; low-level defaults remain raw. `xtc_backend_request_stop` is
|
[AUDIO_QUALITY.md](AUDIO_QUALITY.md) defines absolute musical timing, tempo
|
||||||
asynchronous and does not establish quiescence; control-thread collection after
|
snapshot changes, scheduled source envelopes and configurable master
|
||||||
its callback acknowledgement deactivates JACK. Immediate stop/close remain
|
transitions. The GUI enables 5 ms fades; low-level defaults remain raw.
|
||||||
available. Sample rate and buffer frames are reported, but end-to-end latency
|
`xtc_backend_request_stop` is asynchronous and does not establish quiescence;
|
||||||
and native-node delay compensation are not implemented.
|
control-thread collection after its callback acknowledgement deactivates JACK.
|
||||||
|
Immediate stop/close remain available. Sample rate and buffer frames are
|
||||||
|
reported, but end-to-end latency and native-node delay compensation are not
|
||||||
|
implemented.
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
# Audio clips and recording
|
# Audio Clips and Recording
|
||||||
|
|
||||||
## Import and playback
|
## Import and Playback
|
||||||
|
|
||||||
File/Import WAV (Ctrl+I) loads a WAV into the selected track at the playhead.
|
File/Import WAV (Ctrl+I) loads a WAV into the selected track at the playhead.
|
||||||
With no selected track it creates an Audio track. Add region still creates a
|
With no selected track it creates an Audio track. Add region still creates a
|
||||||
silent placeholder. Imported clips use the existing move/trim controls.
|
silent placeholder. Imported clips use the existing move/trim controls. Import
|
||||||
Import stops playback, validates a candidate project, and commits only after
|
stops playback, validates a candidate project, and commits only after successful
|
||||||
successful backend preparation (or locally when disconnected).
|
backend preparation (or locally when disconnected).
|
||||||
|
|
||||||
Supported input: little-endian RIFF/WAVE, PCM16/24/32 and IEEE float32, one or
|
Supported input: little-endian RIFF/WAVE, PCM16/24/32 and IEEE float32, one or
|
||||||
two channels, 1..768000 Hz. Stereo is averaged to mono. Compressed WAV, RF64,
|
two channels, 1..768000 Hz. Stereo is averaged to mono. Compressed WAV, RF64,
|
||||||
|
|
@ -15,23 +15,22 @@ unsupported. Nonfinite float data and malformed/truncated files are rejected.
|
||||||
There is no new dependency: the bounded C decoder/writer is covered by known
|
There is no new dependency: the bounded C decoder/writer is covered by known
|
||||||
sample, truncation and invalid-codec tests. See decision 0005.
|
sample, truncation and invalid-codec tests. See decision 0005.
|
||||||
|
|
||||||
Audio is preloaded before playback: maximum 64 distinct paths per plan,
|
Audio is preloaded before playback: maximum 64 distinct paths per plan, 16777216
|
||||||
16777216 mono frames per asset (64 MiB), 67108864 total frames (256 MiB).
|
mono frames per asset (64 MiB), 67108864 total frames (256 MiB). Import rejects
|
||||||
Import rejects files over 256 MiB or over 4096 chunks. No streaming decoder,
|
files over 256 MiB or over 4096 chunks. No streaming decoder, waveform cache,
|
||||||
waveform cache, peak drawing or background load worker exists yet. Preloading
|
peak drawing or background load worker exists yet. Preloading can briefly block
|
||||||
can briefly block the GUI. Candidate compilation retains the old plan until
|
the GUI. Candidate compilation retains the old plan until success; temporary
|
||||||
success; temporary build memory can include both old and candidate buffers.
|
build memory can include both old and candidate buffers.
|
||||||
|
|
||||||
The callback renders only overlapping clip ranges from memory. Clips on all
|
The callback renders only overlapping clip ranges from memory. Clips on all
|
||||||
tracks are summed through their mix/automation settings into the graph's
|
tracks are summed through their mix/automation settings into the graph's **Audio
|
||||||
**Audio clips** source node.
|
clips** source node. Import creates that source and connects it to an
|
||||||
Import creates that source and connects it to an existing/new output if no
|
existing/new output if no audio source exists. Subsequent routing is explicit:
|
||||||
audio source exists. Subsequent routing is explicit: disconnect it or route it
|
disconnect it or route it through gain/meter nodes in Modular Graph. Removing
|
||||||
through gain/meter nodes in Modular Graph. Removing the output silences editor
|
the output silences editor graphs. This source does not monitor JACK input;
|
||||||
graphs. This source does not monitor JACK input; unconnected ordinary graph
|
unconnected ordinary graph inputs retain their earlier external-input behavior.
|
||||||
inputs retain their earlier external-input behavior. Track faders/pan/mute
|
Track faders/pan/mute are implemented by the track mixer (see MIXER.md);
|
||||||
are implemented by the track mixer (see MIXER.md); individual
|
individual track graph routing remains deferred.
|
||||||
track graph routing remains deferred.
|
|
||||||
|
|
||||||
Linear interpolation converts source sample rate to backend rate. There is no
|
Linear interpolation converts source sample rate to backend rate. There is no
|
||||||
antialiasing filter, time stretching, looping or fades. Musical durations round
|
antialiasing filter, time stretching, looping or fades. Musical durations round
|
||||||
|
|
@ -45,7 +44,9 @@ Stop pauses the sample clock. Graph-only edits can still be submitted during
|
||||||
playback. Graph recompilation can reset oscillator phase as before. Playback
|
playback. Graph recompilation can reset oscillator phase as before. Playback
|
||||||
does not stop automatically at the arrangement end.
|
does not stop automatically at the arrangement end.
|
||||||
|
|
||||||
## Assets and recovery
|
---
|
||||||
|
|
||||||
|
## Assets and Recovery
|
||||||
|
|
||||||
Version 2 projects store external absolute canonical paths, not sample data.
|
Version 2 projects store external absolute canonical paths, not sample data.
|
||||||
Save the project AND keep its referenced WAV files. Save As changes only the
|
Save the project AND keep its referenced WAV files. Save As changes only the
|
||||||
|
|
@ -56,20 +57,24 @@ removed; the next preparation detects it. Unreadable, malformed and unsupported
|
||||||
assets are also reported, rather than substituted with unrelated files.
|
assets are also reported, rather than substituted with unrelated files.
|
||||||
Capacity/OOM is a preparation failure and retains the old plans.
|
Capacity/OOM is a preparation failure and retains the old plans.
|
||||||
|
|
||||||
Select the affected clip, then File/Relink selected audio to choose a replacement.
|
Select the affected clip, then File/Relink selected audio to choose a
|
||||||
Relinking retains its original timeline/source bounds. The replacement is
|
replacement. Relinking retains its original timeline/source bounds. The
|
||||||
validated on the next Play; a shorter replacement pads beyond its end with
|
replacement is validated on the next Play; a shorter replacement pads beyond its
|
||||||
silence. Saving retains unresolved references for later repair. Missing assets
|
end with silence. Saving retains unresolved references for later repair. Missing
|
||||||
are also checked on Open without a working backend, using a temporary plan.
|
assets are also checked on Open without a working backend, using a temporary
|
||||||
Automatic asset search, content hashes and portable project bundles are deferred.
|
plan. Automatic asset search, content hashes and portable project bundles are
|
||||||
|
deferred.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Recording
|
## Recording
|
||||||
|
|
||||||
Record (or Audio/Record WAV, Shift+F5) opens a destination chooser, stops playback,
|
Record (or Audio/Record WAV, Shift+F5) opens a destination chooser, stops
|
||||||
prepares the project, opens a temporary mono float32 WAV and starts JACK.
|
playback, prepares the project, opens a temporary mono float32 WAV and starts
|
||||||
Connect a source to xtc's JACK input using an external patchbay; no physical or
|
JACK. Connect a source to xtc's JACK input using an external patchbay; no
|
||||||
software route is created automatically. Without a route the take contains
|
physical or software route is created automatically. Without a route the take
|
||||||
silence. Recording captures raw mono JACK input, not the output/effect mix.
|
contains silence. Recording captures raw mono JACK input, not the output/effect
|
||||||
|
mix.
|
||||||
|
|
||||||
A preallocated two-second SPSC ring transfers complete callback blocks to the
|
A preallocated two-second SPSC ring transfers complete callback blocks to the
|
||||||
GUI/control thread, which drains it every 100 ms. The producer uses verified
|
GUI/control thread, which drains it every 100 ms. The producer uses verified
|
||||||
|
|
@ -80,53 +85,59 @@ error rather than hiding gaps or compressing time.
|
||||||
|
|
||||||
Stop first synchronizes the callback, detaches the recorder, drains remaining
|
Stop first synchronizes the callback, detaches the recorder, drains remaining
|
||||||
samples, writes the final WAV header, flushes/fsyncs/closes and renames the
|
samples, writes the final WAV header, flushes/fsyncs/closes and renames the
|
||||||
same-directory temporary using an atomic no-clobber link; an existing destination is refused. A successful nonempty take is
|
same-directory temporary using an atomic no-clobber link; an existing
|
||||||
imported at its capture position on the selected track (or a new Recording
|
destination is refused. A successful nonempty take is imported at its capture
|
||||||
track), then the document becomes unsaved. Save the project after Stop. Seeking
|
position on the selected track (or a new Recording track), then the document
|
||||||
back to the take and pressing Play auditions it. Recording continues existing
|
becomes unsaved. Save the project after Stop. Seeking back to the take and
|
||||||
arrangement playback, but there is no automatic input monitoring, punch, loop,
|
pressing Play auditions it. Recording continues existing arrangement playback,
|
||||||
latency compensation, multitrack arming or overdub alignment compensation.
|
but there is no automatic input monitoring, punch, loop, latency compensation,
|
||||||
|
multitrack arming or overdub alignment compensation.
|
||||||
|
|
||||||
Graph/arrangement edits, project file actions, reconnect and close are blocked
|
Graph/arrangement edits, project file actions, reconnect and close are blocked
|
||||||
until Stop finishes the take. Deactivation failure retains the recorder for a
|
until Stop finishes the take. Deactivation failure retains the recorder for a
|
||||||
safe retry. On overflow a finalized partial WAV is retained for manual recovery
|
safe retry. On overflow a finalized partial WAV is retained for manual recovery
|
||||||
and is not automatically added. On import/preparation failure the completed
|
and is not automatically added. On import/preparation failure the completed take
|
||||||
take remains at its chosen path with an explicit recovery message. I/O errors
|
remains at its chosen path with an explicit recovery message. I/O errors are
|
||||||
are reported; failed temporary data is retained and its recovery path is reported. Recordings
|
reported; failed temporary data is retained and its recovery path is reported.
|
||||||
are RIFF-limited to 1073741814 frames, but the smaller playback/import asset
|
Recordings are RIFF-limited to 1073741814 frames, but the smaller
|
||||||
limit still applies: longer takes may need external splitting before import.
|
playback/import asset limit still applies: longer takes may need external
|
||||||
There is no crash-recovery journal. The file is mode 0600; parent-directory
|
splitting before import. There is no crash-recovery journal. The file is mode
|
||||||
fsync and preservation of previous permissions are not implemented.
|
0600; parent-directory fsync and preservation of previous permissions are not
|
||||||
|
implemented.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Verification
|
## Verification
|
||||||
|
|
||||||
make test includes deterministic WAV/graph samples, resampling/overlap/trim,
|
make test includes deterministic WAV/graph samples, resampling/overlap/trim,
|
||||||
malformed inputs, missing/relinked assets, SPSC concurrency/overflow/cleanup,
|
malformed inputs, missing/relinked assets, SPSC concurrency/overflow/cleanup,
|
||||||
and record -> save/reopen -> exact playback through the backend callback.
|
and record -> save/reopen -> exact playback through the backend callback. make
|
||||||
make test-gui covers the workflow and rollback with a fake backend.
|
test-gui covers the workflow and rollback with a fake backend. make
|
||||||
make test-gui-jack records/reopens a silent take using real JACK callbacks.
|
test-gui-jack records/reopens a silent take using real JACK callbacks. make
|
||||||
make test-jack-audio routes only two software clients: known source -> recorded
|
test-jack-audio routes only two software clients: known source -> recorded WAV
|
||||||
WAV -> saved/reopened project -> graph playback -> capture assertion.
|
-> saved/reopened project -> graph playback -> capture assertion. Physical
|
||||||
Physical input/output, device latency, slow-disk endurance and server loss
|
input/output, device latency, slow-disk endurance and server loss during a real
|
||||||
during a real recording remain unverified.
|
recording remain unverified.
|
||||||
|
|
||||||
## Recording protection
|
---
|
||||||
|
|
||||||
|
## Recording Protection
|
||||||
|
|
||||||
The default recorder and GUI require a new destination, including rejecting
|
The default recorder and GUI require a new destination, including rejecting
|
||||||
symlinks. Publication also refuses files created during recording. The explicit
|
symlinks. Publication also refuses files created during recording. The explicit
|
||||||
`xtc_recorder_create_replace` API retains authorized replacement for callers
|
`xtc_recorder_create_replace` API retains authorized replacement for callers
|
||||||
that deliberately need it; the GUI never uses it. After a failed finish, copy
|
that deliberately need it; the GUI never uses it. After a failed finish, copy
|
||||||
`xtc_recorder_recovery_path` before destruction. Disk-write/finalization failures
|
`xtc_recorder_recovery_path` before destruction. Disk-write/finalization
|
||||||
retain the temporary. Destruction after producer quiescence attempts to drain
|
failures retain the temporary. Destruction after producer quiescence attempts to
|
||||||
and finalize accepted data; normal code should call finish and inspect errors.
|
drain and finalize accepted data; normal code should call finish and inspect
|
||||||
The GUI refuses closure while recording and prints the retained/finalized path
|
errors. The GUI refuses closure while recording and prints the
|
||||||
on exceptional destruction.
|
retained/finalized path on exceptional destruction.
|
||||||
|
|
||||||
Use `xtc-check --recover-recording TEMP NEW.wav` to copy complete float32 frames
|
Use `xtc-check --recover-recording TEMP NEW.wav` to copy complete float32 frames
|
||||||
from an interrupted xtc WAV into a new WAV. Source and existing destinations are
|
from an interrupted xtc WAV into a new WAV. Source and existing destinations are
|
||||||
never modified. A trailing partial frame is ignored. This handles xtc's canonical
|
never modified. A trailing partial frame is ignored. This handles xtc's
|
||||||
44-byte mono float32 header only, not arbitrary damaged WAVs. Recovery is explicit
|
canonical 44-byte mono float32 header only, not arbitrary damaged WAVs. Recovery
|
||||||
and control-thread only; no orphan scan runs during playback.
|
is explicit and control-thread only; no orphan scan runs during playback.
|
||||||
|
|
||||||
`make test-recording` simulates 30 minutes at 8 kHz with repeated ring wrapping
|
`make test-recording` simulates 30 minutes at 8 kHz with repeated ring wrapping
|
||||||
and draining, destination races/symlinks, a child-local disk-size limit, prefix
|
and draining, destination races/symlinks, a child-local disk-size limit, prefix
|
||||||
|
|
@ -138,20 +149,22 @@ player still limits each asset to 16M frames. Longer valid takes may require
|
||||||
external splitting before import. No directory fsync/power-loss guarantee is
|
external splitting before import. No directory fsync/power-loss guarantee is
|
||||||
claimed. WAV destinations are chosen explicitly by the user.
|
claimed. WAV destinations are chosen explicitly by the user.
|
||||||
|
|
||||||
## Non-destructive clip editing
|
---
|
||||||
|
|
||||||
|
## Non-Destructive Clip Editing
|
||||||
|
|
||||||
Move clips by dragging their body; drag the left/right edge to trim within the
|
Move clips by dragging their body; drag the left/right edge to trim within the
|
||||||
existing source length. Ctrl+D duplicates adjacent to the selected clip. Delete
|
existing source length. Ctrl+D duplicates adjacent to the selected clip. Delete
|
||||||
removes the reference. With an audio clip selected, click the ruler while stopped
|
removes the reference. With an audio clip selected, click the ruler while
|
||||||
to position the cursor strictly inside it, then choose **Edit / Split audio at
|
stopped to position the cursor strictly inside it, then choose **Edit / Split
|
||||||
cursor**, press S with timeline focus, or use the clip context menu. The right
|
audio at cursor**, press S with timeline focus, or use the clip context menu.
|
||||||
piece becomes selected. The four-pixel minimum draw width is also selectable for
|
The right piece becomes selected. The four-pixel minimum draw width is also
|
||||||
very short clips; zoom in for precise edge gestures.
|
selectable for very short clips; zoom in for precise edge gestures.
|
||||||
|
|
||||||
**Edit / Audio clip gain and fades** (A with timeline focus, also in the context
|
**Edit / Audio clip gain and fades** (A with timeline focus, also in the context
|
||||||
menu) takes three numbers: linear gain 0..4, fade-in ticks, fade-out ticks.
|
menu) takes three numbers: linear gain 0..4, fade-in ticks, fade-out ticks.
|
||||||
Defaults are `1 0 0`; 0 fade disables that explicit fade. Each duration can be up
|
Defaults are `1 0 0`; 0 fade disables that explicit fade. Each duration can be
|
||||||
to the original source length, even after trimming; overlapping long fades
|
up to the original source length, even after trimming; overlapping long fades
|
||||||
attenuate a short clip without extending it. MIDI clips reject these operations;
|
attenuate a short clip without extending it. MIDI clips reject these operations;
|
||||||
silent metadata regions support them for later audio relinking.
|
silent metadata regions support them for later audio relinking.
|
||||||
|
|
||||||
|
|
@ -165,9 +178,9 @@ No destructive audio processing or file deletion command is supplied.
|
||||||
A split retains the original source length/path/name/gain on both pieces. Its
|
A split retains the original source length/path/name/gain on both pieces. Its
|
||||||
right offset advances by the left length, keeping trims reversible within the
|
right offset advances by the left length, keeping trims reversible within the
|
||||||
same source. Left keeps its ID and fade-in; right gets a fresh ID and fade-out.
|
same source. Left keeps its ID and fade-in; right gets a fresh ID and fade-out.
|
||||||
Inner explicit fades are cleared. Gain/fades are retained on duplication.
|
Inner explicit fades are cleared. Gain/fades are retained on duplication. Moving
|
||||||
Moving does not alter offsets; trimming changes only timeline/source bounds and
|
does not alter offsets; trimming changes only timeline/source bounds and makes
|
||||||
makes explicit fades follow the new audible boundaries.
|
explicit fades follow the new audible boundaries.
|
||||||
|
|
||||||
The renderer maps tick boundaries by the existing absolute floor conversion,
|
The renderer maps tick boundaries by the existing absolute floor conversion,
|
||||||
linearly resamples the source and never reads beyond its samples. Its audible
|
linearly resamples the source and never reads beyond its samples. Its audible
|
||||||
|
|
@ -177,27 +190,27 @@ length up to a tick). A fade uses `age / fade_in_frames` at the start and
|
||||||
use the smaller value. The first/last audible samples are zero when their
|
use the smaller value. The first/last audible samples are zero when their
|
||||||
respective fade has a positive sample duration. Durations rounding to zero
|
respective fade has a positive sample duration. Durations rounding to zero
|
||||||
samples are disabled. A one-sample clip with any active fade is silent. Explicit
|
samples are disabled. A one-sample clip with any active fade is silent. Explicit
|
||||||
fade gain multiplies the existing optional safety envelope, then clip gain,
|
fade gain multiplies the existing optional safety envelope, then clip gain, then
|
||||||
then track gain/pan/automation. No limiter is added; gains/overlaps may clip.
|
track gain/pan/automation. No limiter is added; gains/overlaps may clip.
|
||||||
|
|
||||||
The GUI retains its 5 ms boundary safety fades, including new split edges, so
|
The GUI retains its 5 ms boundary safety fades, including new split edges, so
|
||||||
cuts can introduce a brief dip rather than an abrupt discontinuity. The raw C
|
cuts can introduce a brief dip rather than an abrupt discontinuity. The raw C
|
||||||
plan still defaults to zero safety fade for exact-sample/offline consumers;
|
plan still defaults to zero safety fade for exact-sample/offline consumers;
|
||||||
callers requesting raw cuts accept possible clicks. Tick quantization can place
|
callers requesting raw cuts accept possible clicks. Tick quantization can place
|
||||||
an edit up to one output sample away from a separately rounded boundary; this
|
an edit up to one output sample away from a separately rounded boundary; this is
|
||||||
is not sample-resolution audio editing. Manual listening remains pending.
|
not sample-resolution audio editing. Manual listening remains pending.
|
||||||
Time-stretching, independent pitch shifting and crossfade tools are future work;
|
Time-stretching, independent pitch shifting and crossfade tools are future work;
|
||||||
no suitable algorithm/quality target or new dependency has been selected.
|
no suitable algorithm/quality target or new dependency has been selected.
|
||||||
|
|
||||||
### Cached waveform display
|
### Cached waveform display
|
||||||
|
|
||||||
Timeline audio clips show mono min/max peaks from an immutable C summary,
|
Timeline audio clips show mono min/max peaks from an immutable C summary, shared
|
||||||
shared by reference path across split/duplicated clips. Up to 64 paths each
|
by reference path across split/duplicated clips. Up to 64 paths each cache at
|
||||||
cache at most 1024 bins (fewer for short files). It uses playback's WAV parser,
|
most 1024 bins (fewer for short files). It uses playback's WAV parser, downmix
|
||||||
downmix and file/frame bounds; creation temporarily loads one WAV then frees
|
and file/frame bounds; creation temporarily loads one WAV then frees its sample
|
||||||
its sample storage. Bins cover every source sample, including a final partial
|
storage. Bins cover every source sample, including a final partial bin. The
|
||||||
bin. The display follows source offsets and current tempo; it shows **raw source
|
display follows source offsets and current tempo; it shows **raw source peaks
|
||||||
peaks before clip/track gain and fades**, clamped visually to +/-1. It is an
|
before clip/track gain and fades**, clamped visually to +/-1. It is an
|
||||||
arrangement aid, not a sample editor or loudness meter.
|
arrangement aid, not a sample editor or loudness meter.
|
||||||
|
|
||||||
Loading/rebuilding is synchronous on the GUI/control thread during project
|
Loading/rebuilding is synchronous on the GUI/control thread during project
|
||||||
|
|
@ -219,4 +232,5 @@ cover short-clip selection, shared previews, split/duplicate/delete and undo.
|
||||||
|
|
||||||
The modal audio source editor also provides frame selection, reversible
|
The modal audio source editor also provides frame selection, reversible
|
||||||
processing, selection export, copy adoption and transient slicing. See
|
processing, selection export, copy adoption and transient slicing. See
|
||||||
[AUDIO_EDITOR.md](AUDIO_EDITOR.md) for commands, undo behavior and mono/size limits.
|
[AUDIO_EDITOR.md](AUDIO_EDITOR.md) for commands, undo behavior and mono/size
|
||||||
|
limits.
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,21 @@
|
||||||
# Timing, transitions and audio quality
|
# Timing, Transitions and Audio Quality
|
||||||
|
|
||||||
Deterministic transition processing and tests are included. Musical time still
|
Deterministic transition processing and tests are included. Musical time still
|
||||||
uses a single constant tempo, 960 ticks per quarter note and fixed 4/4 meter;
|
uses a single constant tempo, 960 ticks per quarter note and fixed 4/4 meter; it
|
||||||
it does not introduce a tempo map, meter editor or JACK transport following.
|
does not introduce a tempo map, meter editor or JACK transport following.
|
||||||
Project format remains v4 (reads v1–v3).
|
Project format remains v4 (reads v1–v3).
|
||||||
|
|
||||||
## Timing policy
|
---
|
||||||
|
|
||||||
|
## Timing Policy
|
||||||
|
|
||||||
`xtc_project_set_tempo` accepts 20000–300000 milli-BPM and changes the editable
|
`xtc_project_set_tempo` accepts 20000–300000 milli-BPM and changes the editable
|
||||||
model only. Build new audio/MIDI/mixer plans while stopped to adopt it. Existing
|
model only. Build new audio/MIDI/mixer plans while stopped to adopt it. Existing
|
||||||
plans keep their prepared sample positions and mix snapshots. The backend retains
|
plans keep their prepared sample positions and mix snapshots. The backend
|
||||||
its absolute sample counter through preparation; explicitly seek if the caller
|
retains its absolute sample counter through preparation; explicitly seek if the
|
||||||
wants to preserve a particular musical tick after changing tempo. The GUI has no
|
caller wants to preserve a particular musical tick after changing tempo. The GUI
|
||||||
tempo-change command yet. Meter is always 4/4, has no setter and does not vary
|
has no tempo-change command yet. Meter is always 4/4, has no setter and does not
|
||||||
within a project.
|
vary within a project.
|
||||||
|
|
||||||
Every musical boundary is converted from its **absolute** tick:
|
Every musical boundary is converted from its **absolute** tick:
|
||||||
|
|
||||||
|
|
@ -25,10 +27,11 @@ Conversions use bounded unsigned integer arithmetic, not accumulated floating
|
||||||
beat durations. The inverse also floors; a sample-to-tick roundtrip can lose a
|
beat durations. The inverse also floors; a sample-to-tick roundtrip can lose a
|
||||||
tick because of quantization. At very low supported rates several ticks can map
|
tick because of quantization. At very low supported rates several ticks can map
|
||||||
to one sample. Collapsed note spans are silent. Automation uses the last point
|
to one sample. Collapsed note spans are silent. Automation uses the last point
|
||||||
in tick order at a shared sample. Clip/note intervals are half-open `[start,end)`;
|
in tick order at a shared sample. Clip/note intervals are half-open
|
||||||
a boundary exactly at the next block belongs to that next block. The MIDI input
|
`[start,end)`; a boundary exactly at the next block belongs to that next block.
|
||||||
array preserves caller order for equal offsets (for example on/off versus off/on).
|
The MIDI input array preserves caller order for equal offsets (for example
|
||||||
A discontinuous MIDI render position resets live voices before rendering.
|
on/off versus off/on). A discontinuous MIDI render position resets live voices
|
||||||
|
before rendering.
|
||||||
|
|
||||||
Changing tempo shifts musical boundaries, including source offsets, on newly
|
Changing tempo shifts musical boundaries, including source offsets, on newly
|
||||||
compiled plans. WAV samples keep their original playback speed with linear rate
|
compiled plans. WAV samples keep their original playback speed with linear rate
|
||||||
|
|
@ -36,14 +39,17 @@ conversion; this is not audio time stretching. Scheduled note phase comes from
|
||||||
absolute note age, so seeks and block partitions reproduce the same waveform.
|
absolute note age, so seeks and block partitions reproduce the same waveform.
|
||||||
The graph oscillator/native graph clock is plan-local, rather than project time.
|
The graph oscillator/native graph clock is plan-local, rather than project time.
|
||||||
|
|
||||||
## Boundary fades and smoothing
|
---
|
||||||
|
|
||||||
|
## Boundary Fades and Smoothing
|
||||||
|
|
||||||
The GUI configures `xtc_backend_set_transition_frames(rate/200)`: approximately
|
The GUI configures `xtc_backend_set_transition_frames(rate/200)`: approximately
|
||||||
5 ms at the current rate (integer frames, floor). Configuration is control-thread
|
5 ms at the current rate (integer frames, floor). Configuration is
|
||||||
only while stopped, before project preparation. The low-level backend and
|
control-thread only while stopped, before project preparation. The low-level
|
||||||
source-plan APIs default to zero transition frames for source compatibility.
|
backend and source-plan APIs default to zero transition frames for source
|
||||||
Call `xtc_audio_plan_set_fade_frames` and `xtc_midi_plan_set_fade_frames` before
|
compatibility. Call `xtc_audio_plan_set_fade_frames` and
|
||||||
publication to enable the same behavior in an offline/custom host.
|
`xtc_midi_plan_set_fade_frames` before publication to enable the same behavior
|
||||||
|
in an offline/custom host.
|
||||||
|
|
||||||
Each audio region and scheduled note gets an independent linear boundary
|
Each audio region and scheduled note gets an independent linear boundary
|
||||||
envelope. Its first and last audible samples are zero. At distance `d` from the
|
envelope. Its first and last audible samples are zero. At distance `d` from the
|
||||||
|
|
@ -60,33 +66,35 @@ per-clip editing metadata.
|
||||||
`xtc_gain_ramp` in `xtc_dsp.h` is a single-owner C primitive for smooth gain and
|
`xtc_gain_ramp` in `xtc_dsp.h` is a single-owner C primitive for smooth gain and
|
||||||
parameter changes. Initialize with reset, set a finite target and length, then
|
parameter changes. Initialize with reset, set a finite target and length, then
|
||||||
process preallocated mono/stereo buffers. It reaches the exact target on the Nth
|
process preallocated mono/stereo buffers. It reaches the exact target on the Nth
|
||||||
sample, with the first sample one step toward the target. Retargeting starts from
|
sample, with the first sample one step toward the target. Retargeting starts
|
||||||
the current gain; zero frames changes it immediately. Stereo shares one gain and
|
from the current gain; zero frames changes it immediately. Stereo shares one
|
||||||
advances once per frame. Invalid calls leave buffers/state intact. It allocates
|
gain and advances once per frame. Invalid calls leave buffers/state intact. It
|
||||||
nothing. Mixer automation already interpolates gain/pan per sample; the ramp
|
allocates nothing. Mixer automation already interpolates gain/pan per sample;
|
||||||
primitive does not add a second smoothing delay to that timeline. Static mixer
|
the ramp primitive does not add a second smoothing delay to that timeline.
|
||||||
edits stop playback and use the master ramp on restart. Live native parameter
|
Static mixer edits stop playback and use the master ramp on restart. Live native
|
||||||
updates and live graph replacements have no automatic crossfade.
|
parameter updates and live graph replacements have no automatic crossfade.
|
||||||
|
|
||||||
## Graceful and immediate stopping
|
---
|
||||||
|
|
||||||
|
## Graceful and Immediate Stopping
|
||||||
|
|
||||||
GUI Play fades the master from zero to unity. Ordinary GUI Pause/Stop request a
|
GUI Play fades the master from zero to unity. Ordinary GUI Pause/Stop request a
|
||||||
fade to zero using `xtc_backend_request_stop`; repeated requests do not restart
|
fade to zero using `xtc_backend_request_stop`; repeated requests do not restart
|
||||||
the fade. The callback publishes completion with a release atomic, then outputs
|
the fade. The callback publishes completion with a release atomic, then outputs
|
||||||
silence and holds the sample position. `xtc_backend_collect` on the control thread
|
silence and holds the sample position. `xtc_backend_collect` on the control
|
||||||
acquires completion and calls JACK deactivate, which establishes quiescence.
|
thread acquires completion and calls JACK deactivate, which establishes
|
||||||
Until then, status reports `running` and `stopping`, and the GUI displays that it
|
quiescence. Until then, status reports `running` and `stopping`, and the GUI
|
||||||
is fading. The 100 ms GUI timer completes deactivation; it does not control fade
|
displays that it is fading. The 100 ms GUI timer completes deactivation; it does
|
||||||
timing. If deactivation fails, context/ownership remains intact, silence
|
not control fade timing. If deactivation fails, context/ownership remains
|
||||||
continues, the error is reported and later collection retries.
|
intact, silence continues, the error is reported and later collection retries.
|
||||||
|
|
||||||
The ramp length is sample-counted, but the last callback processes a whole block
|
The ramp length is sample-counted, but the last callback processes a whole block
|
||||||
and advances the sample position by that block, including its zero-valued tail.
|
and advances the sample position by that block, including its zero-valued tail.
|
||||||
A stop request starts at the next observed block boundary. Therefore Pause/Stop
|
A stop request starts at the next observed block boundary. Therefore Pause/Stop
|
||||||
can consume up to approximately `fade_frames + block_frames` after the request,
|
can consume up to approximately `fade_frames + block_frames` after the request,
|
||||||
plus server scheduling; this is not an immediate sample-exact stop command.
|
plus server scheduling; this is not an immediate sample-exact stop command. Play
|
||||||
Play resumes at the retained block-end sample position with a fresh start ramp.
|
resumes at the retained block-end sample position with a fresh start ramp. No
|
||||||
No callback waits for control or performs deactivation/allocation/I/O.
|
callback waits for control or performs deactivation/allocation/I/O.
|
||||||
|
|
||||||
`xtc_backend_stop`/close remain synchronous immediate operations. Recording Stop
|
`xtc_backend_stop`/close remain synchronous immediate operations. Recording Stop
|
||||||
uses immediate deactivation before draining/finalizing the input take; recording
|
uses immediate deactivation before draining/finalizing the input take; recording
|
||||||
|
|
@ -97,31 +105,37 @@ material preservation take priority. If callbacks cease, use immediate stop or
|
||||||
close rather than waiting for fade acknowledgement. Live note-off/panic remains
|
close rather than waiting for fade acknowledgement. Live note-off/panic remains
|
||||||
immediate with no release tail; scheduled notes use the boundary envelope.
|
immediate with no release tail; scheduled notes use the boundary envelope.
|
||||||
|
|
||||||
## Numerical and channel policy
|
---
|
||||||
|
|
||||||
Core graph, native output, audio and MIDI rendering canonicalize nonfinite values
|
## Numerical and Channel Policy
|
||||||
and float subnormals to zero at output boundaries; graph node buffers also use
|
|
||||||
this policy. Native callbacks remain trusted and may have their own internal
|
|
||||||
denormal behavior. No process-wide FTZ/DAZ flags are modified. Normal values as
|
|
||||||
small as `FLT_MIN` are retained. The raw constant-gain helper is unchanged;
|
|
||||||
`xtc_gain_ramp_process` applies the canonical output policy.
|
|
||||||
|
|
||||||
Finite values above unity are preserved for mixing headroom. There is no limiter,
|
Core graph, native output, audio and MIDI rendering canonicalize nonfinite
|
||||||
soft clipping or dither. The physical device/downstream system may clip; lower
|
values and float subnormals to zero at output boundaries; graph node buffers
|
||||||
track gains if meters exceed unity. Ports remain mono with paired stereo passes;
|
also use this policy. Native callbacks remain trusted and may have their own
|
||||||
external mono input is duplicated. Audio assets are downmixed on import, so
|
internal denormal behavior. No process-wide FTZ/DAZ flags are modified. Normal
|
||||||
stereo assets do not retain stereo image. Output buffers must not overlap each
|
values as small as `FLT_MIN` are retained. The raw constant-gain helper is
|
||||||
other; graph sources may alias outputs because both source passes finish first.
|
unchanged; `xtc_gain_ramp_process` applies the canonical output policy.
|
||||||
Supported render sizes are 0–65536 frames within the prepared graph maximum.
|
|
||||||
|
|
||||||
## Latency and synchronization limits
|
Finite values above unity are preserved for mixing headroom. There is no
|
||||||
|
limiter, soft clipping or dither. The physical device/downstream system may
|
||||||
|
clip; lower track gains if meters exceed unity. Ports remain mono with paired
|
||||||
|
stereo passes; external mono input is duplicated. Audio assets are downmixed on
|
||||||
|
import, so stereo assets do not retain stereo image. Output buffers must not
|
||||||
|
overlap each other; graph sources may alias outputs because both source passes
|
||||||
|
finish first. Supported render sizes are 0–65536 frames within the prepared
|
||||||
|
graph maximum.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Latency and Synchronization Limits
|
||||||
|
|
||||||
Backend status reports sample rate and current buffer frames, not measured
|
Backend status reports sample rate and current buffer frames, not measured
|
||||||
end-to-end device latency. `buffer_frames/sample_rate` is one process quantum,
|
end-to-end device latency. `buffer_frames/sample_rate` is one process quantum,
|
||||||
not capture-to-speaker latency. JACK owns hardware/graph scheduling and external
|
not capture-to-speaker latency. JACK owns hardware/graph scheduling and external
|
||||||
port latencies; xtc currently does not query/display JACK latency ranges or
|
port latencies; xtc currently does not query/display JACK latency ranges or
|
||||||
publish an explicit per-node latency model. Fades shape amplitude without a
|
publish an explicit per-node latency model. Fades shape amplitude without a
|
||||||
lookahead/delay buffer, so they add no timeline delay; they do attenuate attacks.
|
lookahead/delay buffer, so they add no timeline delay; they do attenuate
|
||||||
|
attacks.
|
||||||
|
|
||||||
Built-in gain/meter/output, preloaded sources and the sine instrument have no
|
Built-in gain/meter/output, preloaded sources and the sine instrument have no
|
||||||
algorithmic delay to compensate between tracks. The graph has no delay inserts,
|
algorithmic delay to compensate between tracks. The graph has no delay inserts,
|
||||||
|
|
@ -131,7 +145,9 @@ tail contract and compensation are required before claiming synchronized delayed
|
||||||
inserts or external hosting. JACK transport sync, external MIDI clock, tempo
|
inserts or external hosting. JACK transport sync, external MIDI clock, tempo
|
||||||
maps and physical recording-offset calibration remain unsupported.
|
maps and physical recording-offset calibration remain unsupported.
|
||||||
|
|
||||||
## Verification and listening
|
---
|
||||||
|
|
||||||
|
## Verification and Listening
|
||||||
|
|
||||||
```
|
```
|
||||||
make all test gui test-reliability test-workflow test-gui test-gui-jack
|
make all test gui test-reliability test-workflow test-gui test-gui-jack
|
||||||
|
|
@ -140,21 +156,23 @@ make test-sanitize analyze
|
||||||
make quality-preview
|
make quality-preview
|
||||||
```
|
```
|
||||||
|
|
||||||
`test_quality` is part of `make test`. It covers a sample-rate/tempo matrix up to
|
`test_quality` is part of `make test`. It covers a sample-rate/tempo matrix up
|
||||||
768 kHz and the maximum project tick, conversion errors, old/new tempo snapshots
|
to 768 kHz and the maximum project tick, conversion errors, old/new tempo
|
||||||
for both audio and MIDI, exact offset/on/off order, sample boundary behavior,
|
snapshots for both audio and MIDI, exact offset/on/off order, sample boundary
|
||||||
raw versus faded endpoints, media ends shorter than rounded clip ends, split/
|
behavior, raw versus faded endpoints, media ends shorter than rounded clip ends,
|
||||||
whole equivalence, seeks, ramps, stereo parity, overload, NaN/infinity/subnormals
|
split/ whole equivalence, seeks, ramps, stereo parity, overload,
|
||||||
and block sizes 1, 2, 3, 17, 257, 4097, 65535 and 65536. Backend fault tests check
|
NaN/infinity/subnormals and block sizes 1, 2, 3, 17, 257, 4097, 65535 and 65536.
|
||||||
exact master ramps, repeated stop requests, held position/silence after completion,
|
Backend fault tests check exact master ramps, repeated stop requests, held
|
||||||
deactivation failure/retry, immediate escape and recording guards. The workflow
|
position/silence after completion, deactivation failure/retry, immediate escape
|
||||||
render comparison now enables the GUI source fade policy before/after reopening.
|
and recording guards. The workflow render comparison now enables the GUI source
|
||||||
|
fade policy before/after reopening.
|
||||||
|
|
||||||
Automated checks pass warning-enabled core/GUI and no-JACK builds,
|
Automated checks pass warning-enabled core/GUI and no-JACK builds,
|
||||||
ASan/UBSan/leak checks, static analysis, pthread TSan tests, mock and live GUI,
|
ASan/UBSan/leak checks, static analysis, pthread TSan tests, mock and live GUI,
|
||||||
software JACK audio/MIDI tests and staged installation. GUI leak checks retain
|
software JACK audio/MIDI tests and staged installation. GUI leak checks retain
|
||||||
the existing fontconfig-only suppression; core leak checks are unsuppressed.
|
the existing fontconfig-only suppression; core leak checks are unsuppressed.
|
||||||
Physical-device listening and human listening acceptance are **not yet verified**.
|
Physical-device listening and human listening acceptance are **not yet
|
||||||
|
verified**.
|
||||||
|
|
||||||
`make quality-preview` writes ignored build artifacts `quality-raw.wav` and
|
`make quality-preview` writes ignored build artifacts `quality-raw.wav` and
|
||||||
`quality-smooth.wav` in BUILD_DIR using `examples/quality_preview.c`. Compare at
|
`quality-smooth.wav` in BUILD_DIR using `examples/quality_preview.c`. Compare at
|
||||||
|
|
@ -162,7 +180,7 @@ moderate playback level: first listen to the three-note phrase endings, then the
|
||||||
constant clip at two seconds, then a mid-period tone stop near three seconds.
|
constant clip at two seconds, then a mid-period tone stop near three seconds.
|
||||||
Check that fades reduce edge clicks, do not add noise and do not unexpectedly
|
Check that fades reduce edge clicks, do not add noise and do not unexpectedly
|
||||||
change pitch/timing. Also listen to the saved MIDI/audio workflow project with
|
change pitch/timing. Also listen to the saved MIDI/audio workflow project with
|
||||||
repeated Play/Pause/Stop, Home/seek and representative gain/pan automation on the
|
repeated Play/Pause/Stop, Home/seek and representative gain/pan automation on
|
||||||
actual target device. Record device, rate, block size and observations before
|
the actual target device. Record device, rate, block size and observations
|
||||||
marking human listening acceptance complete. Generated previews are reproducible
|
before marking human listening acceptance complete. Generated previews are
|
||||||
test material, not a claim that anyone has listened to them.
|
reproducible test material, not a claim that anyone has listened to them.
|
||||||
|
|
|
||||||
233
docs/BUILD.md
233
docs/BUILD.md
|
|
@ -1,9 +1,11 @@
|
||||||
# Build baseline
|
# Build Baseline
|
||||||
|
|
||||||
The existing layout is retained: public C headers in `include/xtc`,
|
The existing layout is retained: public C headers in `include/xtc`, C
|
||||||
C implementation modules under `src`, optional C++ GUI under `src/gui`, and
|
implementation modules under `src`, optional C++ GUI under `src/gui`, and tests
|
||||||
tests under `tests`. `src/main.c` is a minimal headless startup/shutdown check;
|
under `tests`. `src/main.c` is a minimal headless startup/shutdown check; it
|
||||||
it does not initialize audio devices or open a GUI.
|
does not initialize audio devices or open a GUI.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
|
|
@ -15,14 +17,17 @@ make gui
|
||||||
```
|
```
|
||||||
|
|
||||||
`all` builds the static C library and startup check. `test` runs the existing
|
`all` builds the static C library and startup check. `test` runs the existing
|
||||||
core/offline tests, concurrent plan-handoff stress, JACK fault injection
|
core/offline tests, concurrent plan-handoff stress, JACK fault injection (when
|
||||||
(when JACK headers are available), and the startup check. `debug` builds and tests separately in
|
JACK headers are available), and the startup check. `debug` builds and tests
|
||||||
`build/debug`. `gui` builds the FLTK shell with backend controls and status.
|
separately in `build/debug`. `gui` builds the FLTK shell with backend controls
|
||||||
The shell starts with a silent graph and never connects physical ports. Generated files remain under `build` and header changes trigger rebuilds.
|
and status. The shell starts with a silent graph and never connects physical
|
||||||
|
ports. Generated files remain under `build` and header changes trigger rebuilds.
|
||||||
Compiler, flags, `BUILD_DIR`, `PKG_CONFIG`, `FLTK_CONFIG`, and installation
|
Compiler, flags, `BUILD_DIR`, `PKG_CONFIG`, `FLTK_CONFIG`, and installation
|
||||||
`PREFIX` can be overridden through Make variables. C uses C99; GUI uses C++17.
|
`PREFIX` can be overridden through Make variables. C uses C99; GUI uses C++17.
|
||||||
|
|
||||||
## Inspected Linux toolchain (2026-10-26)
|
---
|
||||||
|
|
||||||
|
## Inspected Linux Toolchain (2026-10-26)
|
||||||
|
|
||||||
| Component | Available version | Role |
|
| Component | Available version | Role |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
|
|
@ -35,24 +40,29 @@ Compiler, flags, `BUILD_DIR`, `PKG_CONFIG`, `FLTK_CONFIG`, and installation
|
||||||
| Clang | 23.1.3 | Alternative compiler / diagnostics |
|
| Clang | 23.1.3 | Alternative compiler / diagnostics |
|
||||||
|
|
||||||
Valgrind is also available. The core tests use a small in-tree C test harness
|
Valgrind is also available. The core tests use a small in-tree C test harness
|
||||||
and require no external test framework. FLTK has no `fltk.pc` on this host;
|
and require no external test framework. FLTK has no `fltk.pc` on this host; the
|
||||||
the Makefile tries pkg-config first, then `fltk-config`.
|
Makefile tries pkg-config first, then `fltk-config`.
|
||||||
|
|
||||||
## Dependencies and licensing
|
---
|
||||||
|
|
||||||
|
## Dependencies and Licensing
|
||||||
|
|
||||||
The offline core needs the C runtime and math library. Optional JACK support is
|
The offline core needs the C runtime and math library. Optional JACK support is
|
||||||
selected with pkg-config; missing JACK does not prevent core/tests
|
selected with pkg-config; missing JACK does not prevent core/tests from
|
||||||
from building. Realtime publication uses GCC/Clang lock-free atomic builtins in
|
building. Realtime publication uses GCC/Clang lock-free atomic builtins in C99.
|
||||||
C99. Tests also use POSIX threads. Backend consumers must link JACK explicitly;
|
Tests also use POSIX threads. Backend consumers must link JACK explicitly;
|
||||||
backend objects are pulled from the static library only when used. The repository is MIT licensed. The optional GUI uses maintained
|
backend objects are pulled from the static library only when used. The
|
||||||
FLTK 1.4 (LGPL with FLTK's static-linking exception); its platform link flags
|
repository is MIT licensed. The optional GUI uses maintained FLTK 1.4 (LGPL with
|
||||||
come from the installed package. Distribution still requires review of all
|
FLTK's static-linking exception); its platform link flags come from the
|
||||||
linked dependencies and notices. The installed PipeWire JACK library is MIT;
|
installed package. Distribution still requires review of all linked dependencies
|
||||||
traditional JACK client libraries use LGPL licensing. See decision 0004 for
|
and notices. The installed PipeWire JACK library is MIT; traditional JACK client
|
||||||
the dependency choice and caveats. ALSA remains a future MIDI candidate. No packages or system settings
|
libraries use LGPL licensing. See decision 0004 for the dependency choice and
|
||||||
|
caveats. ALSA remains a future MIDI candidate. No packages or system settings
|
||||||
are changed by these build commands.
|
are changed by these build commands.
|
||||||
|
|
||||||
## Backend verification
|
---
|
||||||
|
|
||||||
|
## Backend Verification
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
make all test gui debug
|
make all test gui debug
|
||||||
|
|
@ -72,11 +82,13 @@ Normal, sanitizer and no-JACK tests pass. ThreadSanitizer reports no race in
|
||||||
2,000 concurrent submissions. The 30-second live loopback test passed at 48 kHz
|
2,000 concurrent submissions. The 30-second live loopback test passed at 48 kHz
|
||||||
with zero xruns and ten restart cycles; see tests/integration/README.md. Live
|
with zero xruns and ten restart cycles; see tests/integration/README.md. Live
|
||||||
server termination/format changes were not performed on the shared server;
|
server termination/format changes were not performed on the shared server;
|
||||||
fault-injection tests cover those notification paths. No packages installed
|
fault-injection tests cover those notification paths. No packages installed or
|
||||||
or system/device configuration changed. Sanitizers are not enabled in the live
|
system/device configuration changed. Sanitizers are not enabled in the live
|
||||||
callback qualification run.
|
callback qualification run.
|
||||||
|
|
||||||
## GUI shell verification
|
---
|
||||||
|
|
||||||
|
## GUI Shell Verification
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
make clean all test gui debug test-gui test-gui-jack
|
make clean all test gui debug test-gui test-gui-jack
|
||||||
|
|
@ -92,7 +104,9 @@ exit-time font allocations; see tests/integration/README.md for the distinction
|
||||||
and command. No compiler warnings remain with GCC or Clang. Core/backend tests
|
and command. No compiler warnings remain with GCC or Clang. Core/backend tests
|
||||||
pass with unsuppressed ASan/UBSan. No packages or system configuration changed.
|
pass with unsuppressed ASan/UBSan. No packages or system configuration changed.
|
||||||
|
|
||||||
## Graph editor verification
|
---
|
||||||
|
|
||||||
|
## Graph Editor Verification
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
make clean all test gui debug test-gui test-gui-jack
|
make clean all test gui debug test-gui test-gui-jack
|
||||||
|
|
@ -106,10 +120,12 @@ ASan/UBSan; ThreadSanitizer passes the concurrent handoff test with revision-to-
|
||||||
gain checks. GUI ASan/UBSan tests pass with the existing fontconfig-only leak
|
gain checks. GUI ASan/UBSan tests pass with the existing fontconfig-only leak
|
||||||
suppression. Live GUI tests build a connected graph, adopt accepted edits during
|
suppression. Live GUI tests build a connected graph, adopt accepted edits during
|
||||||
playback, reject cycles, reconnect and close active clients. Mouse/visual smoke
|
playback, reject cycles, reconnect and close active clients. Mouse/visual smoke
|
||||||
checks cover node creation, wiring, cycle rejection, dragging and deletion.
|
checks cover node creation, wiring, cycle rejection, dragging and deletion. No
|
||||||
No physical routes, new dependencies or system changes are introduced.
|
physical routes, new dependencies or system changes are introduced.
|
||||||
|
|
||||||
## Project verification
|
---
|
||||||
|
|
||||||
|
## Project Verification
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
make clean all test gui debug test-gui test-gui-jack
|
make clean all test gui debug test-gui test-gui-jack
|
||||||
|
|
@ -118,10 +134,10 @@ make BUILD_DIR=build/nojack PKG_CONFIG=false all test gui test-gui
|
||||||
|
|
||||||
The suite adds test_project: track/clip limits, stable IDs, trims, integer
|
The suite adds test_project: track/clip limits, stable IDs, trims, integer
|
||||||
transport conversion, exact file roundtrip with graph rendering, exhaustive
|
transport conversion, exact file roundtrip with graph rendering, exhaustive
|
||||||
fixture truncations, byte mutations, failed saves and temporary cleanup.
|
fixture truncations, byte mutations, failed saves and temporary cleanup. GUI
|
||||||
GUI tests cover region gestures, zoom, save/load and backend rollback.
|
tests cover region gestures, zoom, save/load and backend rollback. Live JACK
|
||||||
Live JACK tests verify playhead advance, pause and resume without creating routes.
|
tests verify playhead advance, pause and resume without creating routes. The
|
||||||
The updated core and GUI tests pass Clang ASan/UBSan (the GUI uses the existing
|
updated core and GUI tests pass Clang ASan/UBSan (the GUI uses the existing
|
||||||
fontconfig-only LSan suppression). An Xvfb/xdotool visual check created a track
|
fontconfig-only LSan suppression). An Xvfb/xdotool visual check created a track
|
||||||
and region, moved it one bar and zoomed the canvas. No dependencies were added.
|
and region, moved it one bar and zoomed the canvas. No dependencies were added.
|
||||||
|
|
||||||
|
|
@ -129,8 +145,9 @@ Audio assets and recording are supported. Silent arrangement regions, fixed
|
||||||
tempo/4/4, no undo, no persisted GUI layout, and unverified physical-device
|
tempo/4/4, no undo, no persisted GUI layout, and unverified physical-device
|
||||||
playback/endurance remain explicit limits.
|
playback/endurance remain explicit limits.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Audio verification
|
## Audio Verification
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
make all test gui debug test-gui test-gui-jack test-jack-audio
|
make all test gui debug test-gui test-gui-jack test-jack-audio
|
||||||
|
|
@ -150,12 +167,15 @@ migration and 1024 maximum-length asset paths in a valid v2 file.
|
||||||
The live test-jack-audio target connects only its software clients and checks
|
The live test-jack-audio target connects only its software clients and checks
|
||||||
record -> WAV -> saved/reopened project -> graph playback. GUI/JACK tests also
|
record -> WAV -> saved/reopened project -> graph playback. GUI/JACK tests also
|
||||||
record, finalize, save and reopen a take without hardware routing. Clang
|
record, finalize, save and reopen a take without hardware routing. Clang
|
||||||
ASan/UBSan passes the core and GUI tests (GUI retains the existing fontconfig-only
|
ASan/UBSan passes the core and GUI tests (GUI retains the existing
|
||||||
LSan suppression). ThreadSanitizer passes the concurrent recorder and existing
|
fontconfig-only LSan suppression). ThreadSanitizer passes the concurrent
|
||||||
realtime handoff tests. Hardware capture/playback, disk endurance and real server
|
recorder and existing realtime handoff tests. Hardware capture/playback, disk
|
||||||
loss during recording remain unverified. See AUDIO_FILES.md.
|
endurance and real server loss during recording remain unverified. See
|
||||||
|
AUDIO_FILES.md.
|
||||||
|
|
||||||
## MIDI verification
|
---
|
||||||
|
|
||||||
|
## MIDI Verification
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
make all test gui debug test-gui test-gui-jack test-jack-audio test-jack-midi
|
make all test gui debug test-gui test-gui-jack test-jack-audio test-jack-midi
|
||||||
|
|
@ -166,17 +186,20 @@ make BUILD_DIR=build/nojack PKG_CONFIG=false all test gui test-gui
|
||||||
voice capacities, stable notes and v3 malformed-file/roundtrip/v2 migration
|
voice capacities, stable notes and v3 malformed-file/roundtrip/v2 migration
|
||||||
coverage. Backend fault injection checks event offsets, dropped/malformed input,
|
coverage. Backend fault injection checks event offsets, dropped/malformed input,
|
||||||
disconnection, xruns, missing output buffers and stop/restart cleanup. GUI tests
|
disconnection, xruns, missing output buffers and stop/restart cleanup. GUI tests
|
||||||
draw/move/resize notes, save/reopen and render them. The live MIDI target connects
|
draw/move/resize notes, save/reopen and render them. The live MIDI target
|
||||||
only software clients and checks on/off, panic, disconnect, and saved-note
|
connects only software clients and checks on/off, panic, disconnect, and
|
||||||
playback/seek. It needs an existing JACK-compatible server. No hardware routes
|
saved-note playback/seek. It needs an existing JACK-compatible server. No
|
||||||
or system changes are made. MIDI recording/SMF and physical devices are deferred.
|
hardware routes or system changes are made. MIDI recording/SMF and physical
|
||||||
|
devices are deferred.
|
||||||
|
|
||||||
A fresh `build/verify` build passed all targets above with no compiler warnings.
|
A fresh `build/verify` build passed all targets above with no compiler warnings.
|
||||||
The no-JACK core/GUI suite and Clang ASan/UBSan core/GUI suite also passed; GUI
|
The no-JACK core/GUI suite and Clang ASan/UBSan core/GUI suite also passed; GUI
|
||||||
leak checking uses only the existing fontconfig suppression documented in the
|
leak checking uses only the existing fontconfig suppression documented in the
|
||||||
integration README. Physical MIDI and audio devices remain unverified.
|
integration README. Physical MIDI and audio devices remain unverified.
|
||||||
|
|
||||||
## Mixer verification
|
---
|
||||||
|
|
||||||
|
## Mixer Verification
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
make all test gui debug test-gui test-gui-jack test-jack-audio test-jack-midi
|
make all test gui debug test-gui test-gui-jack test-jack-audio test-jack-midi
|
||||||
|
|
@ -184,20 +207,23 @@ make BUILD_DIR=build/nojack PKG_CONFIG=false all test gui test-gui
|
||||||
```
|
```
|
||||||
|
|
||||||
`test_mixer` covers stereo gain/pan, mute/solo, sample automation, block
|
`test_mixer` covers stereo gain/pan, mute/solo, sample automation, block
|
||||||
independence, WAV and graph routing, v4 persistence failures and bounded history.
|
independence, WAV and graph routing, v4 persistence failures and bounded
|
||||||
GUI tests add automation mouse edits, mixer keys, history rollback/branching and
|
history. GUI tests add automation mouse edits, mixer keys, history
|
||||||
save/reopen. The existing live MIDI test now uses two software capture ports and
|
rollback/branching and save/reopen. The existing live MIDI test now uses two
|
||||||
checks hard-right saved-note playback and output meter snapshots; mono audio
|
software capture ports and checks hard-right saved-note playback and output
|
||||||
record/play acceptance remains covered. A native Xvfb mouse smoke check confirms
|
meter snapshots; mono audio record/play acceptance remains covered. A native
|
||||||
sliders and automation drawing. See MIXER.md for capacities and deferred features.
|
Xvfb mouse smoke check confirms sliders and automation drawing. See MIXER.md for
|
||||||
|
capacities and deferred features.
|
||||||
|
|
||||||
The fresh verification build, no-JACK core/GUI suite and Clang
|
The fresh verification build, no-JACK core/GUI suite and Clang ASan/UBSan
|
||||||
ASan/UBSan core/GUI suite passed without compiler warnings. GUI leak checking
|
core/GUI suite passed without compiler warnings. GUI leak checking retains only
|
||||||
retains only the existing fontconfig suppression. ThreadSanitizer also passed
|
the existing fontconfig suppression. ThreadSanitizer also passed the recorder
|
||||||
the recorder concurrency and realtime publication tests. Physical devices and
|
concurrency and realtime publication tests. Physical devices and long-running
|
||||||
long-running stereo performance remain unverified.
|
stereo performance remain unverified.
|
||||||
|
|
||||||
## Release preparation
|
---
|
||||||
|
|
||||||
|
## Release Preparation
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
make all test gui debug test-gui test-gui-jack test-jack test-jack-audio test-jack-midi
|
make all test gui debug test-gui test-gui-jack test-jack test-jack-audio test-jack-midi
|
||||||
|
|
@ -205,54 +231,63 @@ make test-install test-recovery test-performance
|
||||||
make test-release
|
make test-release
|
||||||
```
|
```
|
||||||
|
|
||||||
Core test now includes native ABI/lifecycle/retirement and the native-gain example.
|
Core test now includes native ABI/lifecycle/retirement and the native-gain
|
||||||
Optional release tests use Python 3.12+ standard library, Git for indexed source
|
example. Optional release tests use Python 3.12+ standard library, Git for
|
||||||
exports, GNU/LLVM deterministic ar and temporary directories. No live prefix is
|
indexed source exports, GNU/LLVM deterministic ar and temporary directories. No
|
||||||
installed. test-install checks core/GUI files, a prefix containing spaces,
|
live prefix is installed. test-install checks core/GUI files, a prefix
|
||||||
headless CLI, pkg-config C/C++ consumers, exact/idempotent uninstall and preservation
|
containing spaces, headless CLI, pkg-config C/C++ consumers, exact/idempotent
|
||||||
of unrelated files. test-release compares two clean exported optimized builds and
|
uninstall and preservation of unrelated files. test-release compares two clean
|
||||||
repacked archives byte-for-byte. test-recovery kills private child writers and
|
exported optimized builds and repacked archives byte-for-byte. test-recovery
|
||||||
forces a child-local write limit, checking complete finalized destinations and
|
kills private child writers and forces a child-local write limit, checking
|
||||||
explicit orphan temporaries. Performance timings are reported, not used as a
|
complete finalized destinations and explicit orphan temporaries. Performance
|
||||||
universal realtime guarantee. See RELEASING.md, RECOVERY.md and PERFORMANCE.md.
|
timings are reported, not used as a universal realtime guarantee. See
|
||||||
|
RELEASING.md, RECOVERY.md and PERFORMANCE.md.
|
||||||
|
|
||||||
Verification passed a fresh warning-enabled core/debug/GUI build, all
|
Verification passed a fresh warning-enabled core/debug/GUI build, all software
|
||||||
software JACK targets, staged install/uninstall, recovery and performance tests.
|
JACK targets, staged install/uninstall, recovery and performance tests. No-JACK
|
||||||
No-JACK core/GUI/install checks and Clang ASan/UBSan core/GUI checks also passed
|
core/GUI/install checks and Clang ASan/UBSan core/GUI checks also passed (the
|
||||||
(the GUI retains only its existing fontconfig leak suppression). TSan recorder
|
GUI retains only its existing fontconfig leak suppression). TSan recorder and
|
||||||
and realtime-handoff checks passed. Two independent optimized source exports
|
realtime-handoff checks passed. Two independent optimized source exports and
|
||||||
and their repacked source archives were byte-identical on this toolchain.
|
their repacked source archives were byte-identical on this toolchain.
|
||||||
|
|
||||||
## Reliability audit
|
---
|
||||||
|
|
||||||
|
## Reliability Audit
|
||||||
|
|
||||||
Run `make test-reliability` for the core suites, allocation-failure sweep,
|
Run `make test-reliability` for the core suites, allocation-failure sweep,
|
||||||
callback allocation/free guard and native reclamation checks. Run
|
callback allocation/free guard and native reclamation checks. Run
|
||||||
`make test-sanitize` for Clang ASan/UBSan/leak checks and `make analyze` for
|
`make test-sanitize` for Clang ASan/UBSan/leak checks and `make analyze` for
|
||||||
Clang static analysis of all core sources. These need installed development
|
Clang static analysis of all core sources. These need installed development
|
||||||
tools; the allocation guard uses a GNU-compatible linker. See
|
tools; the allocation guard uses a GNU-compatible linker. See
|
||||||
[RELIABILITY.md](RELIABILITY.md) for ownership, audit findings,
|
[RELIABILITY.md](RELIABILITY.md) for ownership, audit findings, full
|
||||||
full verification commands and remaining limits.
|
verification commands and remaining limits.
|
||||||
|
|
||||||
## Workflow acceptance
|
---
|
||||||
|
|
||||||
|
## Workflow Acceptance
|
||||||
|
|
||||||
`make test-workflow` requires FLTK/JACK development files, Xvfb and an existing
|
`make test-workflow` requires FLTK/JACK development files, Xvfb and an existing
|
||||||
JACK-compatible server. It does not start/configure the server or connect
|
JACK-compatible server. It does not start/configure the server or connect
|
||||||
physical devices. See [WORKFLOW.md](WORKFLOW.md) for the full GUI composition
|
physical devices. See [WORKFLOW.md](WORKFLOW.md) for the full GUI composition
|
||||||
acceptance sequence and transport semantics.
|
acceptance sequence and transport semantics.
|
||||||
|
|
||||||
## Audio quality
|
---
|
||||||
|
|
||||||
|
## Audio Quality
|
||||||
|
|
||||||
`make test-quality` runs exact timing, source-boundary, gain-ramp, event-order
|
`make test-quality` runs exact timing, source-boundary, gain-ramp, event-order
|
||||||
and numeric/layout tests (also included in `make test`). `make quality-preview`
|
and numeric/layout tests (also included in `make test`). `make quality-preview`
|
||||||
builds the C example and writes raw/smoothed listening WAVs into BUILD_DIR without
|
builds the C example and writes raw/smoothed listening WAVs into BUILD_DIR
|
||||||
playing them or configuring devices. See [AUDIO_QUALITY.md](AUDIO_QUALITY.md).
|
without playing them or configuring devices. See
|
||||||
|
[AUDIO_QUALITY.md](AUDIO_QUALITY.md).
|
||||||
|
|
||||||
Parameter-processor and plugin checks: `make test-processor test-plugins test-gui-plugins`.
|
Parameter-processor and plugin checks:
|
||||||
The latter two need the system LADSPA development header; real-plugin acceptance
|
`make test-processor test-plugins test-gui-plugins`. The latter two need the
|
||||||
is separate (`make test-plugins-real`, paths listed in PLUGIN_HOSTING.md). With no
|
system LADSPA development header; real-plugin acceptance is separate
|
||||||
|
(`make test-plugins-real`, paths listed in PLUGIN_HOSTING.md). With no
|
||||||
`ladspa.h`, the ordinary core/GUI still builds and plugin operations return
|
`ladspa.h`, the ordinary core/GUI still builds and plugin operations return
|
||||||
UNSUPPORTED; existing plugin metadata can still be loaded/saved. To exercise that
|
UNSUPPORTED; existing plugin metadata can still be loaded/saved. To exercise
|
||||||
configuration explicitly, use a fresh BUILD_DIR with
|
that configuration explicitly, use a fresh BUILD_DIR with
|
||||||
`CPPFLAGS=-DXTC_DISABLE_LADSPA JACK_AVAILABLE=`. No dependency is downloaded.
|
`CPPFLAGS=-DXTC_DISABLE_LADSPA JACK_AVAILABLE=`. No dependency is downloaded.
|
||||||
Link static consumers with `-lm -ldl` plus the backend dependencies when used.
|
Link static consumers with `-lm -ldl` plus the backend dependencies when used.
|
||||||
See LICENSES.md for header/plugin licensing and decision 0009 for rationale.
|
See LICENSES.md for header/plugin licensing and decision 0009 for rationale.
|
||||||
|
|
@ -264,23 +299,27 @@ ASan/UBSan. Run `make benchmark benchmark-project` separately without contention
|
||||||
or sanitizers for timing reports. Optional `make test-stress-plugins` requires
|
or sanitizers for timing reports. Optional `make test-stress-plugins` requires
|
||||||
installed LADSPA headers; `make test-stress` supports minimal builds too.
|
installed LADSPA headers; `make test-stress` supports minimal builds too.
|
||||||
|
|
||||||
## Installation layouts
|
---
|
||||||
|
|
||||||
|
## Installation Layouts
|
||||||
|
|
||||||
`make test-install test-install-layout` verifies default and custom layouts in
|
`make test-install test-install-layout` verifies default and custom layouts in
|
||||||
throwaway staging directories, C/C++ installed consumers, examples and exact
|
throwaway staging directories, C/C++ installed consumers, examples and exact
|
||||||
removal. Override `PREFIX`, `exec_prefix`, `bindir`, `libdir`, `includedir`,
|
removal. Override `PREFIX`, `exec_prefix`, `bindir`, `libdir`, `includedir`,
|
||||||
`datarootdir`, `datadir`, `docdir`, `pkgconfigdir`, `licensedir`, `examplesdir` or
|
`datarootdir`, `datadir`, `docdir`, `pkgconfigdir`, `licensedir`, `examplesdir`
|
||||||
`desktopdir` as needed. `DESTDIR` adds staging separately; pass the same layout
|
or `desktopdir` as needed. `DESTDIR` adds staging separately; pass the same
|
||||||
to uninstall. See RELEASING.md for commands and RELEASE_NOTES.md for upgrades.
|
layout to uninstall. See RELEASING.md for commands and RELEASE_NOTES.md for
|
||||||
|
upgrades.
|
||||||
|
|
||||||
Modern plugin adapters build in C99 using the pinned header-only CLAP
|
Modern plugin adapters build in C99 using the pinned header-only CLAP and VST3 C
|
||||||
and VST3 C APIs under third_party; there is no network build or SDK runtime.
|
APIs under third_party; there is no network build or SDK runtime. VST2
|
||||||
VST2 compatibility uses original ABI declarations. `make test-modern-plugins`
|
compatibility uses original ABI declarations. `make test-modern-plugins` runs
|
||||||
runs original shared-library fixtures without a server; `make test-gui-modern-plugins`
|
original shared-library fixtures without a server;
|
||||||
adds GUI/browser/undo/reopen tests under Xvfb. The fixtures also run in `make test`
|
`make test-gui-modern-plugins` adds GUI/browser/undo/reopen tests under Xvfb.
|
||||||
and therefore in sanitizer/release builds. Notices are installed with LICENSE.
|
The fixtures also run in `make test` and therefore in sanitizer/release builds.
|
||||||
|
Notices are installed with LICENSE.
|
||||||
|
|
||||||
The GUI uses a header-only FLTK theme and existing drawing primitives; no new
|
The GUI uses a header-only FLTK theme and existing drawing primitives; no new
|
||||||
GUI dependency or generated asset is required. `make test-gui-instruments` also
|
GUI dependency or generated asset is required. `make test-gui-instruments` also
|
||||||
exercises sidebar track creation, rollback, undo/reopen and minimum/large layouts.
|
exercises sidebar track creation, rollback, undo/reopen and minimum/large
|
||||||
See WORKSPACE.md for the default size and manual visual verification.
|
layouts. See WORKSPACE.md for the default size and manual visual verification.
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,23 @@
|
||||||
# Internal instruments and effects
|
# Internal Instruments and Effects
|
||||||
|
|
||||||
No plugin downloads, search paths or external libraries are needed. The original
|
No plugin downloads, search paths or external libraries are needed. The original
|
||||||
built-in sine remains available for existing projects.
|
built-in sine remains available for existing projects.
|
||||||
|
|
||||||
Choose **Internal: Soft Keys** or **Internal: Sub Bass** in a MIDI track's
|
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
|
instrument dropdown. Soft Keys blends a sine with a third harmonic; Sub Bass
|
||||||
uses a pure sine. Both have 32 voices, velocity sensitivity,
|
uses a pure sine. Both have 32 voices, velocity sensitivity, short
|
||||||
short attack/release envelopes, sustain pedal, note-off and panic handling.
|
attack/release envelopes, sustain pedal, note-off and panic handling. High
|
||||||
High harmonics are omitted near Nyquist. The default sounds remain compatible with fixed presets from v13. See the
|
harmonics are omitted near Nyquist. The default sounds remain compatible with
|
||||||
instrument controls below. A sample library is not provided by these oscillators.
|
fixed presets from v13. See the instrument controls below. A sample library is
|
||||||
|
not provided by these oscillators.
|
||||||
|
|
||||||
In **Modular Graph**, select a wire and choose **Edit → Insert internal delay on
|
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
|
wire** or **Insert internal reverb on wire**. This preserves the route and
|
||||||
the effect into the signal path. **File → Add internal delay/reverb** creates an
|
inserts the effect into the signal path. **File → Add internal delay/reverb**
|
||||||
unconnected device for manual wiring. Select its node and use **Edit → Selected
|
creates an unconnected device for manual wiring. Select its node and use **Edit
|
||||||
plugin control** to edit it, or **Selected plugin automation** to automate it.
|
→ Selected plugin control** to edit it, or **Selected plugin automation** to
|
||||||
Changes use the existing stopped-engine preparation and undo workflow.
|
automate it. Changes use the existing stopped-engine preparation and undo
|
||||||
|
workflow.
|
||||||
|
|
||||||
- **Delay:** time (1–2000 ms), feedback (0–0.95), dry/wet mix (0–1).
|
- **Delay:** time (1–2000 ms), feedback (0–0.95), dry/wet mix (0–1).
|
||||||
- **Reverb:** four parallel damped feedback combs, with decay (0–0.95), damping
|
- **Reverb:** four parallel damped feedback combs, with decay (0–0.95), damping
|
||||||
|
|
@ -28,37 +30,43 @@ Internal effect history resets on transport discontinuities. Configurable export
|
||||||
tails and optional playback stopping after tails are described below.
|
tails and optional playback stopping after tails are described below.
|
||||||
|
|
||||||
Project format 13 stores internal devices as format 4 with reserved module path
|
Project format 13 stores internal devices as format 4 with reserved module path
|
||||||
`/xtc/internal`, stable numeric identity and index (0 keys, 1 bass, 2 delay,
|
`/xtc/internal`, stable numeric identity and index (0 keys, 1 bass, 2 delay, 3
|
||||||
3 reverb). This is a virtual identifier, never an external binary. Effect controls
|
reverb). This is a virtual identifier, never an external binary. Effect controls
|
||||||
and automation are saved using the existing plugin records; instruments are fixed
|
and automation are saved using the existing plugin records; instruments are
|
||||||
presets. Readers still accept formats 1–12. Older xtc builds reject format 13.
|
fixed presets. Readers still accept formats 1–12. Older xtc builds reject format
|
||||||
All buffers are allocated during preparation; processing performs no allocation,
|
13. All buffers are allocated during preparation; processing performs no
|
||||||
file access, library loading, locking or GUI calls.
|
allocation, file access, library loading, locking or GUI calls.
|
||||||
|
|
||||||
Validation: `make BUILD_DIR=build/builtins all gui test test-gui-instruments
|
Validation:
|
||||||
test-gui-modern-plugins test-gui-plugins analyze` (join onto one line).
|
`make BUILD_DIR=build/builtins all gui test test-gui-instruments test-gui-modern-plugins test-gui-plugins analyze`
|
||||||
`test-builtins` checks impulse tails, dry mix, feedback bounds, block partition
|
(join onto one line). `test-builtins` checks impulse tails, dry mix, feedback
|
||||||
consistency, note release/panic and instrument/effect project round trips.
|
bounds, block partition consistency, note release/panic and instrument/effect
|
||||||
|
project round trips.
|
||||||
|
|
||||||
## Acceptance checks
|
---
|
||||||
|
|
||||||
|
## Acceptance Checks
|
||||||
|
|
||||||
`make BUILD_DIR=build/builtin-acceptance all gui test test-reliability test-gui builtin-preview`
|
`make BUILD_DIR=build/builtin-acceptance all gui test test-reliability test-gui builtin-preview`
|
||||||
checks all four device identities and GUI paths without external plugin binaries.
|
checks all four device identities and GUI paths without external plugin
|
||||||
The reliability runner fails each internal preparation allocation in turn and
|
binaries. The reliability runner fails each internal preparation allocation in
|
||||||
forbids allocation/free, direct file I/O and blocking locks during processing.
|
turn and forbids allocation/free, direct file I/O and blocking locks during
|
||||||
Core tests compare persisted rendering for both instruments and both automated
|
processing. Core tests compare persisted rendering for both instruments and both
|
||||||
effects, corrupt an internal module identity transactionally, and cover voice
|
automated effects, corrupt an internal module identity transactionally, and
|
||||||
exhaustion, sustain, repeated notes, partitioning and transport reset/seek/panic.
|
cover voice exhaustion, sustain, repeated notes, partitioning and transport
|
||||||
The existing portability suite verifies older project migrations.
|
reset/seek/panic. The existing portability suite verifies older project
|
||||||
|
migrations.
|
||||||
|
|
||||||
For repeatable manual listening, run `make builtin-preview` and audition
|
For repeatable manual listening, run `make builtin-preview` and audition
|
||||||
`build/builtin-{0,1,2,3}.wav` at a conservative level: 0 is Soft Keys, 1 Sub Bass,
|
`build/builtin-{0,1,2,3}.wav` at a conservative level: 0 is Soft Keys, 1 Sub
|
||||||
2 Delay and 3 Reverb. Each six-second file includes held tones or two impulses
|
Bass, 2 Delay and 3 Reverb. Each six-second file includes held tones or two
|
||||||
followed by silence for tails. Check onset/release, unwanted discontinuities,
|
impulses followed by silence for tails. Check onset/release, unwanted
|
||||||
finite decay and the documented mono character. Generation is verified;
|
discontinuities, finite decay and the documented mono character. Generation is
|
||||||
human listening and physical-device qualification remain pending.
|
verified; human listening and physical-device qualification remain pending.
|
||||||
|
|
||||||
## Instrument controls and presets
|
---
|
||||||
|
|
||||||
|
## Instrument Controls and Presets
|
||||||
|
|
||||||
**Edit → Selected instrument controls** edits an assigned internal instrument.
|
**Edit → Selected instrument controls** edits an assigned internal instrument.
|
||||||
The five ports are harmonic amount (0..1), attack (0.1..2000 ms), release
|
The five ports are harmonic amount (0..1), attack (0.1..2000 ms), release
|
||||||
|
|
@ -77,8 +85,8 @@ with no parameters upgrade to defaults when opened in the editor.
|
||||||
are versioned single-instrument `.xtc` containers with no clips. Public C APIs
|
are versioned single-instrument `.xtc` containers with no clips. Public C APIs
|
||||||
`xtc_plugin_preset_save/load` provide atomic saving and transactional metadata
|
`xtc_plugin_preset_save/load` provide atomic saving and transactional metadata
|
||||||
loading; they never execute plugin code. Loading into a track is an undoable,
|
loading; they never execute plugin code. Loading into a track is an undoable,
|
||||||
prepared edit. Parameter automation is included. Preset paths are ordinary files;
|
prepared edit. Parameter automation is included. Preset paths are ordinary
|
||||||
saving uses the existing project replacement semantics.
|
files; saving uses the existing project replacement semantics.
|
||||||
|
|
||||||
Live MIDI pitch bend uses standard 14-bit messages (8192 center) and is applied
|
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
|
at the event's sample offset per channel. Panic clears the affected channel's
|
||||||
|
|
@ -91,7 +99,9 @@ old fixed internal assignments use their original defaults. Older builds reject
|
||||||
v14. Tests cover legacy-default sound equality, v13 migration, parameter/preset
|
v14. Tests cover legacy-default sound equality, v13 migration, parameter/preset
|
||||||
round trips, pitch-bend offsets, automated block partitions, undo and GUI edits.
|
round trips, pitch-bend offsets, automated block partitions, undo and GUI edits.
|
||||||
|
|
||||||
## Sample instrument
|
---
|
||||||
|
|
||||||
|
## Sample Instrument
|
||||||
|
|
||||||
**File → Load sampler WAV** assigns a Sample Player to the selected track or
|
**File → Load sampler WAV** assigns a Sample Player to the selected track or
|
||||||
relinks its existing sample while retaining its controls. Use the instrument
|
relinks its existing sample while retaining its controls. Use the instrument
|
||||||
|
|
@ -99,8 +109,8 @@ controls editor for root MIDI key (0..127), whole-sample loop (0/1), attack,
|
||||||
release and gain (0..4). One root mapping covers every MIDI key using linear
|
release and gain (0..4). One root mapping covers every MIDI key using linear
|
||||||
rate conversion, including source/output sample-rate differences. Loop and root
|
rate conversion, including source/output sample-rate differences. Loop and root
|
||||||
are integer controls and require hold automation. Live bend spans ±2 semitones.
|
are integer controls and require hold automation. Live bend spans ±2 semitones.
|
||||||
This initial sampler has no multisample zones, loop-point editor or time stretch.
|
This initial sampler has no multisample zones, loop-point editor or time
|
||||||
Extreme transposition can alias; use appropriate source material.
|
stretch. Extreme transposition can alias; use appropriate source material.
|
||||||
|
|
||||||
The existing WAV reader supports PCM16/24/32 and float32, mono/stereo downmixed
|
The existing WAV reader supports PCM16/24/32 and float32, mono/stereo downmixed
|
||||||
to mono. Each sample is at most 16M mono frames; the combined instrument plan
|
to mono. Each sample is at most 16M mono frames; the combined instrument plan
|
||||||
|
|
@ -122,15 +132,17 @@ Tests cover source-rate conversion, one-shot endpoint, looping, release,
|
||||||
partitioning, preset references, missing assets, GUI relinking/undo/reload and
|
partitioning, preset references, missing assets, GUI relinking/undo/reload and
|
||||||
preparation-allocation/callback guards.
|
preparation-allocation/callback guards.
|
||||||
|
|
||||||
## Stereo effects
|
---
|
||||||
|
|
||||||
|
## Stereo Effects
|
||||||
|
|
||||||
**File → Add stereo delay/reverb** and **Edit → Insert stereo delay/reverb on
|
**File → Add stereo delay/reverb** and **Edit → Insert stereo delay/reverb on
|
||||||
wire** add new devices (indices 5/6). Original Delay/Reverb (indices 2/3) retain
|
wire** add new devices (indices 5/6). Original Delay/Reverb (indices 2/3) retain
|
||||||
their original algorithms, values and saved identities. Existing control and
|
their original algorithms, values and saved identities. Existing control and
|
||||||
automation editors, undo and persistence support both generations.
|
automation editors, undo and persistence support both generations.
|
||||||
|
|
||||||
Stereo Delay adds integer **Sync**: 0 milliseconds, 1 quarter, 2 eighth,
|
Stereo Delay adds integer **Sync**: 0 milliseconds, 1 quarter, 2 eighth, 3
|
||||||
3 dotted eighth, 4 eighth triplet. Nonzero sync follows project tempo; changing
|
dotted eighth, 4 eighth triplet. Nonzero sync follows project tempo; changing
|
||||||
tempo uses ordinary stopped project preparation. Time changes crossfade two
|
tempo uses ordinary stopped project preparation. Time changes crossfade two
|
||||||
fractional read heads for 5 ms. A crossfade finishes before adopting the latest
|
fractional read heads for 5 ms. A crossfade finishes before adopting the latest
|
||||||
automated target, bounding transition work and avoiding read-head jumps.
|
automated target, bounding transition work and avoiding read-head jumps.
|
||||||
|
|
@ -139,29 +151,33 @@ Delay storage covers four seconds, sufficient for all divisions at 20..300 BPM.
|
||||||
|
|
||||||
Stereo Reverb adds **Room** (0..1, scales comb spacing) and **Diffusion** (0..1,
|
Stereo Reverb adds **Room** (0..1, scales comb spacing) and **Diffusion** (0..1,
|
||||||
cross-couples damped feedback). The right comb timings differ from the left.
|
cross-couples damped feedback). The right comb timings differ from the left.
|
||||||
Decay/damping retain 0..0.95 bounds. This is a simple algorithmic reverb, without
|
Decay/damping retain 0..0.95 bounds. This is a simple algorithmic reverb,
|
||||||
physical room simulation or a measured RT60. Room automation can alter coloration.
|
without physical room simulation or a measured RT60. Room automation can alter
|
||||||
|
coloration.
|
||||||
|
|
||||||
The graph evaluates both channels' inputs before calling a coupled internal
|
The graph evaluates both channels' inputs before calling a coupled internal
|
||||||
processor. Each stereo device has one prepared state, with no callback allocation.
|
processor. Each stereo device has one prepared state, with no callback
|
||||||
Mono processing excites both sides and folds the wet output to mono. External
|
allocation. Mono processing excites both sides and folds the wet output to mono.
|
||||||
plugins and the original effects retain independent mono instances.
|
External plugins and the original effects retain independent mono instances.
|
||||||
|
|
||||||
Tests compare whole/split blocks, tempo-synced impulse placement, left-to-right
|
Tests compare whole/split blocks, tempo-synced impulse placement, left-to-right
|
||||||
energy, bounded extreme feedback/diffusion and graph/direct stereo output
|
energy, bounded extreme feedback/diffusion and graph/direct stereo output
|
||||||
(including the engine's subnormal-to-zero policy). GUI tests save/reopen both
|
(including the engine's subnormal-to-zero policy). GUI tests save/reopen both
|
||||||
identities; callback guards and ASan/UBSan cover processing. `make builtin-preview`
|
identities; callback guards and ASan/UBSan cover processing.
|
||||||
also writes files 5/6 for repeatable listening; human listening remains pending.
|
`make builtin-preview` also writes files 5/6 for repeatable listening; human
|
||||||
|
listening remains pending.
|
||||||
|
|
||||||
## History and tails
|
---
|
||||||
|
|
||||||
|
## History and Tails
|
||||||
|
|
||||||
Internal effects reset on a transport discontinuity (seek/loop wrap), stopped
|
Internal effects reset on a transport discontinuity (seek/loop wrap), stopped
|
||||||
backend, or newly prepared plan. Pause uses backend Stop and therefore also
|
backend, or newly prepared plan. Pause uses backend Stop and therefore also
|
||||||
resets history. Continuous playback retains tails. Reset invalidates delay
|
resets history. Continuous playback retains tails. Reset invalidates delay
|
||||||
history with a valid-frame counter and clears only fixed-size filter/voice state;
|
history with a valid-frame counter and clears only fixed-size filter/voice
|
||||||
it neither allocates nor clears a large delay buffer in the callback. External
|
state; it neither allocates nor clears a large delay buffer in the callback.
|
||||||
plugins retain their existing history contract. MIDI discontinuities continue
|
External plugins retain their existing history contract. MIDI discontinuities
|
||||||
to chase notes with fresh envelopes.
|
continue to chase notes with fresh envelopes.
|
||||||
|
|
||||||
**File → Export WAV** renders the song plus the Preferences / transport
|
**File → Export WAV** renders the song plus the Preferences / transport
|
||||||
`tail_ms` duration (0..60000, default 3000). Output is stereo float32 WAV at the
|
`tail_ms` duration (0..60000, default 3000). Output is stereo float32 WAV at the
|
||||||
|
|
@ -169,9 +185,9 @@ offline sample rate. The destination must be a new absolute path. Rendering
|
||||||
prepares an independent snapshot, then advances in 256-frame control-thread
|
prepares an independent snapshot, then advances in 256-frame control-thread
|
||||||
steps with a Cancel button; the project and playback instance stay independent.
|
steps with a Cancel button; the project and playback instance stay independent.
|
||||||
Only a complete synced file is published, without replacing an existing file.
|
Only a complete synced file is published, without replacing an existing file.
|
||||||
Cancellation/errors remove the temporary. Missing media rejects export.
|
Cancellation/errors remove the temporary. Missing media rejects export. RIFF's
|
||||||
RIFF's 32-bit size limit is enforced before rendering. Rendering does not apply
|
32-bit size limit is enforced before rendering. Rendering does not apply loop
|
||||||
loop preferences, normalize, automatically detect silence or stop infinite
|
preferences, normalize, automatically detect silence or stop infinite
|
||||||
oscillator/feedback sources early: the configured endpoint always bounds work.
|
oscillator/feedback sources early: the configured endpoint always bounds work.
|
||||||
|
|
||||||
The public `xtc_export_create/step/progress/destroy` API supports incremental
|
The public `xtc_export_create/step/progress/destroy` API supports incremental
|
||||||
|
|
@ -181,8 +197,9 @@ destruction. `xtc_project_render_length` returns the exact sample endpoint.
|
||||||
Set `stop_after_tail=1` in Preferences to stop ordinary playback after the song
|
Set `stop_after_tail=1` in Preferences to stop ordinary playback after the song
|
||||||
and configured tail. Looping and recording disable this automatic stop. Playback
|
and configured tail. Looping and recording disable this automatic stop. Playback
|
||||||
stop is serviced by the GUI refresh timer and normal stop fade, so it can exceed
|
stop is serviced by the GUI refresh timer and normal stop fade, so it can exceed
|
||||||
the endpoint by a refresh interval plus fade; export has the exact sample length.
|
the endpoint by a refresh interval plus fade; export has the exact sample
|
||||||
Uncheck the setting to retain indefinite playback. Stop always remains available.
|
length. Uncheck the setting to retain indefinite playback. Stop always remains
|
||||||
|
available.
|
||||||
|
|
||||||
Tests compare stereo export against direct rendering in 31-frame blocks, verify
|
Tests compare stereo export against direct rendering in 31-frame blocks, verify
|
||||||
nonzero tails, exact length, cancellation, existing-file retention, tail bounds,
|
nonzero tails, exact length, cancellation, existing-file retention, tail bounds,
|
||||||
|
|
|
||||||
|
|
@ -1,48 +1,124 @@
|
||||||
# Arrangement and composition workflows
|
# Arrangement and Composition Workflows
|
||||||
|
|
||||||
All mutations run on the control thread through the existing stop, history and
|
All mutations run on the control thread through the existing stop, history and
|
||||||
prepared-plan workflow. No new dependencies are required.
|
prepared-plan workflow. No new dependencies are required.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Persistent Arrangement Markers
|
## Persistent Arrangement Markers
|
||||||
|
|
||||||
Edit/Markers/Set at cursor adds or renames a marker; Remove at cursor removes the exact tick key. Markers draw names and vertical guides in the arrangement and survive project save/load and undo. Up to 128 markers are supported. Names may overlap visually when markers are close; markers do not change playback by themselves.
|
Edit/Markers/Set at cursor adds or renames a marker; Remove at cursor removes
|
||||||
|
the exact tick key. Markers draw names and vertical guides in the arrangement
|
||||||
|
and survive project save/load and undo. Up to 128 markers are supported. Names
|
||||||
|
may overlap visually when markers are close; markers do not change playback by
|
||||||
|
themselves.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Section Navigation and Looping
|
## Section Navigation and Looping
|
||||||
|
|
||||||
View/Previous marker and Next marker navigate without wrapping and stop playback before seeking. Loop current section uses the last marker at or before the cursor through its successor; the final section ends at the final clip endpoint. Empty final sections reject. Loop ranges remain existing UI preferences rather than marker metadata.
|
View/Previous marker and Next marker navigate without wrapping and stop playback
|
||||||
|
before seeking. Loop current section uses the last marker at or before the
|
||||||
|
cursor through its successor; the final section ends at the final clip endpoint.
|
||||||
|
Empty final sections reject. Loop ranges remain existing UI preferences rather
|
||||||
|
than marker metadata.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Ripple Time Editing
|
## Ripple Time Editing
|
||||||
|
|
||||||
Edit/Time inserts a gap or removes a tick range beginning at the cursor. Clips crossing either edit boundary reject the entire operation; split them first. Contained clips and their notes are removed; later clips, markers and absolute automation points shift together. Source notes within retained clips do not move. No interpolation guard points are generated, so automation ramps across the boundary may change slope. Loop preferences are unchanged.
|
Edit/Time inserts a gap or removes a tick range beginning at the cursor. Clips
|
||||||
|
crossing either edit boundary reject the entire operation; split them first.
|
||||||
|
Contained clips and their notes are removed; later clips, markers and absolute
|
||||||
|
automation points shift together. Source notes within retained clips do not
|
||||||
|
move. No interpolation guard points are generated, so automation ramps across
|
||||||
|
the boundary may change slope. Loop preferences are unchanged.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Complete Track Duplication
|
## Complete Track Duplication
|
||||||
|
|
||||||
Edit/Duplicate complete track copies the selected non-bus track adjacent to its source. Clips, notes, instrument settings, static mix, bus routing and mixer automation are independent model copies with fresh IDs; WAV references remain shared. The modular graph and live-input target are unchanged. Bus duplication is rejected. Capacity errors leave the original document unchanged.
|
Edit/Duplicate complete track copies the selected non-bus track adjacent to its
|
||||||
|
source. Clips, notes, instrument settings, static mix, bus routing and mixer
|
||||||
|
automation are independent model copies with fresh IDs; WAV references remain
|
||||||
|
shared. The modular graph and live-input target are unchanged. Bus duplication
|
||||||
|
is rejected. Capacity errors leave the original document unchanged.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Nondestructive MIDI Clip Splitting
|
## Nondestructive MIDI Clip Splitting
|
||||||
|
|
||||||
The existing Split clip at cursor command (S) now handles MIDI as well as audio. Left retains its ID; right gets fresh IDs, the same source content and an adjusted source offset. Hidden notes remain editable. Split is nondestructive, but instrument note envelopes may retrigger at the new boundary; original sine rendering retains source phase. Capacity failures preserve the project.
|
The existing Split clip at cursor command (S) now handles MIDI as well as audio.
|
||||||
|
Left retains its ID; right gets fresh IDs, the same source content and an
|
||||||
|
adjusted source offset. Hidden notes remain editable. Split is nondestructive,
|
||||||
|
but instrument note envelopes may retrigger at the new boundary; original sine
|
||||||
|
rendering retains source phase. Capacity failures preserve the project.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## MIDI Clip Consolidation
|
## MIDI Clip Consolidation
|
||||||
|
|
||||||
Edit/Consolidate MIDI clips merges two or more selected MIDI clips on one track. The new clip spans their full bounding range; gaps and overlapping notes remain. Notes outside visible trims are discarded and crossing notes are cropped to audible boundaries. IDs are fresh. Cropped notes start anew, so envelope/phase behavior can change. Audio or cross-track selections reject atomically.
|
Edit/Consolidate MIDI clips merges two or more selected MIDI clips on one track.
|
||||||
|
The new clip spans their full bounding range; gaps and overlapping notes remain.
|
||||||
|
Notes outside visible trims are discarded and crossing notes are cropped to
|
||||||
|
audible boundaries. IDs are fresh. Cropped notes start anew, so envelope/phase
|
||||||
|
behavior can change. Audio or cross-track selections reject atomically.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Deterministic MIDI Humanization
|
## Deterministic MIDI Humanization
|
||||||
|
|
||||||
Edit/MIDI tools/Humanize applies timing variation up to 960 ticks and velocity variation up to 127, using a 32-bit seed and stable note IDs. Repeating from the same original state reproduces results; applying repeatedly accumulates edits. All source notes are affected, including hidden trimmed notes. Timing outside source bounds rejects the entire edit; velocities clamp to 1..127. This is offline editing, not live randomness.
|
Edit/MIDI tools/Humanize applies timing variation up to 960 ticks and velocity
|
||||||
|
variation up to 127, using a 32-bit seed and stable note IDs. Repeating from the
|
||||||
|
same original state reproduces results; applying repeatedly accumulates edits.
|
||||||
|
All source notes are affected, including hidden trimmed notes. Timing outside
|
||||||
|
source bounds rejects the entire edit; velocities clamp to 1..127. This is
|
||||||
|
offline editing, not live randomness.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Chord Construction
|
## Chord Construction
|
||||||
|
|
||||||
Edit/MIDI tools/Build chords accepts 1..8 unique nonzero semitone intervals, such as 4 7 for a major triad or 3 7 for minor. Originals remain; added notes copy timing, velocity and channel. Negative intervals support lower voicings. All source notes are processed, including hidden trimmed notes. Pitch overflow or capacity rejects the whole operation; existing unisons are not deduplicated.
|
Edit/MIDI tools/Build chords accepts 1..8 unique nonzero semitone intervals,
|
||||||
|
such as 4 7 for a major triad or 3 7 for minor. Originals remain; added notes
|
||||||
|
copy timing, velocity and channel. Negative intervals support lower voicings.
|
||||||
|
All source notes are processed, including hidden trimmed notes. Pitch overflow
|
||||||
|
or capacity rejects the whole operation; existing unisons are not deduplicated.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Offline Arpeggio Generation
|
## Offline Arpeggio Generation
|
||||||
|
|
||||||
Edit/MIDI tools/Generate arpeggio replaces source notes with a written pattern. Equal-onset notes on the same channel form a chord lasting until its longest note end. The pattern cycles sorted pitches upward or downward, with the selected step and gate. Each step inherits its chosen note velocity/channel. All source notes, including hidden trimmed notes, participate. This is offline generation with undo, not a live arpeggiator or tempo-synced MIDI effect.
|
Edit/MIDI tools/Generate arpeggio replaces source notes with a written pattern.
|
||||||
|
Equal-onset notes on the same channel form a chord lasting until its longest
|
||||||
|
note end. The pattern cycles sorted pitches upward or downward, with the
|
||||||
|
selected step and gate. Each step inherits its chosen note velocity/channel. All
|
||||||
|
source notes, including hidden trimmed notes, participate. This is offline
|
||||||
|
generation with undo, not a live arpeggiator or tempo-synced MIDI effect.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Audio Peak Normalization
|
## Audio Peak Normalization
|
||||||
|
|
||||||
Edit/Audio tools/Normalize source peak accepts a target from -60 to 0 dBFS. The C API accepts a linear target above 0 and at most 1. Analysis uses the audible native-rate source slice and the same mono downmix as playback, before fades or mixer controls. It replaces clip gain without writing WAV data. Silence, missing/invalid media, MIDI selections or required gain above 4 reject the entire batch. This is sample-peak normalization, not true-peak limiting or LUFS loudness normalization. Analysis runs synchronously on the control thread.
|
Edit/Audio tools/Normalize source peak accepts a target from -60 to 0 dBFS. The
|
||||||
|
C API accepts a linear target above 0 and at most 1. Analysis uses the audible
|
||||||
|
native-rate source slice and the same mono downmix as playback, before fades or
|
||||||
|
mixer controls. It replaces clip gain without writing WAV data. Silence,
|
||||||
|
missing/invalid media, MIDI selections or required gain above 4 reject the
|
||||||
|
entire batch. This is sample-peak normalization, not true-peak limiting or LUFS
|
||||||
|
loudness normalization. Analysis runs synchronously on the control thread.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Portable Project Collection
|
## Portable Project Collection
|
||||||
|
|
||||||
File/Collect project media... requires a new absolute folder. The original document and files remain unchanged; open project.xtc inside the new folder to use the copy. Referenced audio and track/graph sampler WAVs are deduplicated and copied byte-for-byte, with relative references. Limits are 128 distinct assets, 256 MiB per file, 1 GiB total and a canonical folder path shorter than 480 bytes. Existing destinations, missing media, nonregular files and native graph nodes reject. External plugin binaries/state are not collected; plugins must remain installed. Invalid WAV data is copied rather than repaired. The folder is visible during synchronous collection; failures remove owned outputs, and the project file is saved last.
|
File/Collect project media... requires a new absolute folder. The original
|
||||||
|
document and files remain unchanged; open project.xtc inside the new folder to
|
||||||
|
use the copy. Referenced audio and track/graph sampler WAVs are deduplicated and
|
||||||
|
copied byte-for-byte, with relative references. Limits are 128 distinct assets,
|
||||||
|
256 MiB per file, 1 GiB total and a canonical folder path shorter than 480
|
||||||
|
bytes. Existing destinations, missing media, nonregular files and native graph
|
||||||
|
nodes reject. External plugin binaries/state are not collected; plugins must
|
||||||
|
remain installed. Invalid WAV data is copied rather than repaired. The folder is
|
||||||
|
visible during synchronous collection; failures remove owned outputs, and the
|
||||||
|
project file is saved last.
|
||||||
|
|
|
||||||
183
docs/CONTROL.md
183
docs/CONTROL.md
|
|
@ -1,41 +1,45 @@
|
||||||
# Automation and expressive control
|
# Automation and Expressive Control
|
||||||
|
|
||||||
Track Gain/Pan lanes in the Mixer apply to audio and scheduled instrument voices.
|
Track Gain/Pan lanes in the Mixer apply to audio and scheduled instrument
|
||||||
They use absolute project ticks, linear or hold interpolation, hold-first/last outside
|
voices. They use absolute project ticks, linear or hold interpolation,
|
||||||
points and the constant project tempo snapshot. A clip trim/move does not move
|
hold-first/last outside points and the constant project tempo snapshot. A clip
|
||||||
track or effect automation: lanes belong to the project timeline. Instrument
|
trim/move does not move track or effect automation: lanes belong to the project
|
||||||
volume is controlled by its track Gain lane; the current sine has no timbre
|
timeline. Instrument volume is controlled by its track Gain lane; the current
|
||||||
parameter. Track gain ramps and boundary fades are described in AUDIO_QUALITY.md.
|
sine has no timbre parameter. Track gain ramps and boundary fades are described
|
||||||
|
in AUDIO_QUALITY.md.
|
||||||
|
|
||||||
Select a LADSPA node in Modular Graph and use Edit/Selected plugin automation.
|
Select a LADSPA node in Modular Graph and use Edit/Selected plugin automation.
|
||||||
Enter `port tick mode value`: mode 0 interpolates linearly, 1 holds until the next
|
Enter `port tick mode value`: mode 0 interpolates linearly, 1 holds until the
|
||||||
point, and -1 removes the point at that port/tick (value ignored). Port names,
|
next point, and -1 removes the point at that port/tick (value ignored). Port
|
||||||
ranges and current tick are displayed. There are at most 32 points per plugin;
|
names, ranges and current tick are displayed. There are at most 32 points per
|
||||||
setting an existing port/tick replaces it. Integer/toggle controls require step
|
plugin; setting an existing port/tick replaces it. Integer/toggle controls
|
||||||
mode. Invalid values, ticks, ports or duplicate persisted points reject the edit
|
require step mode. Invalid values, ticks, ports or duplicate persisted points
|
||||||
or file. Edits are undoable and rebuild on the control thread while stopped.
|
reject the edit or file. Edits are undoable and rebuild on the control thread
|
||||||
|
while stopped.
|
||||||
|
|
||||||
Effect lanes use the project tempo, hold first/last outside their range and
|
Effect lanes use the project tempo, hold first/last outside their range and
|
||||||
apply before run at each exact sample. Distinct ticks rounding to one sample
|
apply before run at each exact sample. Distinct ticks rounding to one sample
|
||||||
resolve to the later tick. Linear curves avoid stepping continuous controls;
|
resolve to the later tick. Linear curves avoid stepping continuous controls;
|
||||||
intentional step curves may click. The initial implementation calls run(1) while
|
intentional step curves may click. The initial implementation calls run(1) while
|
||||||
any lane exists, with connected preallocated buffers. CPU cost can be significant;
|
any lane exists, with connected preallocated buffers. CPU cost can be
|
||||||
only the documented LADSPA set is qualified. No worker, allocator, loader or
|
significant; only the documented LADSPA set is qualified. No worker, allocator,
|
||||||
clock is called from the host audio path. Native ABI 2 callers continue to use
|
loader or clock is called from the host audio path. Native ABI 2 callers
|
||||||
sample-offset parameter events, applied before equal-offset MIDI events.
|
continue to use sample-offset parameter events, applied before equal-offset MIDI
|
||||||
|
events.
|
||||||
|
|
||||||
Live MIDI input maps CC7 to per-channel volume (0..1), CC10 to pan (64 center),
|
Live MIDI input maps CC7 to per-channel volume (0..1), CC10 to pan (64 center),
|
||||||
and CC64 to sustain (>=64 down). Volume/pan ramp over 5 ms. These default mappings
|
and CC64 to sustain (>=64 down). Volume/pan ramp over 5 ms. These default
|
||||||
apply to live sine voices, not track faders or prerecorded clips; controller
|
mappings apply to live sine voices, not track faders or prerecorded clips;
|
||||||
capture, automatic learn and plugin MIDI are not supported. CC120/123 and
|
controller capture, automatic learn and plugin MIDI are not supported. CC120/123
|
||||||
Panic release all live voices and sustain and suppress already-started scheduled
|
and Panic release all live voices and sustain and suppress already-started
|
||||||
notes. Note-on velocity zero decodes to note-off. Repeated live note-on on one
|
scheduled notes. Note-on velocity zero decodes to note-off. Repeated live
|
||||||
channel/pitch retriggers one voice; note-off releases it or marks it pending while
|
note-on on one channel/pitch retriggers one voice; note-off releases it or marks
|
||||||
sustain is held. Sustain-up releases pending voices, never newer retriggers.
|
it pending while sustain is held. Sustain-up releases pending voices, never
|
||||||
Seek, stop, teardown and disconnect clear live voices; plan reset returns controller
|
newer retriggers. Seek, stop, teardown and disconnect clear live voices; plan
|
||||||
values to unity/center. Equal-offset live events execute in input order before
|
reset returns controller values to unity/center. Equal-offset live events
|
||||||
the sample; arrange note ends precede starts, and scheduled mixer values are
|
execute in input order before the sample; arrange note ends precede starts, and
|
||||||
evaluated at that sample. Overlapping arranged notes are independent.
|
scheduled mixer values are evaluated at that sample. Overlapping arranged notes
|
||||||
|
are independent.
|
||||||
|
|
||||||
Format v6 preserves v5 data plus effect lanes. A v5 plugin migrates with no lane
|
Format v6 preserves v5 data plus effect lanes. A v5 plugin migrates with no lane
|
||||||
and the project tempo. Repeated render/save/reopen, odd block partition, exact
|
and the project tempo. Repeated render/save/reopen, odd block partition, exact
|
||||||
|
|
@ -46,12 +50,16 @@ make test test-control test-plugins test-gui-plugins test-plugins-real
|
||||||
```
|
```
|
||||||
|
|
||||||
Physical controller devices and listening remain unqualified; no tempo map,
|
Physical controller devices and listening remain unqualified; no tempo map,
|
||||||
latency compensation, MIDI capture, pitch bend or plugin crash isolation is added.
|
latency compensation, MIDI capture, pitch bend or plugin crash isolation is
|
||||||
|
added.
|
||||||
|
|
||||||
## Common parameter targets
|
---
|
||||||
|
|
||||||
`xtc_control.h` identifies a parameter by `(kind, stable owner ID, parameter ID)`.
|
## Common Parameter Targets
|
||||||
IDs never mean a dense list index and are not DSP pointers:
|
|
||||||
|
`xtc_control.h` identifies a parameter by
|
||||||
|
`(kind, stable owner ID, parameter ID)`. IDs never mean a dense list index and
|
||||||
|
are not DSP pointers:
|
||||||
|
|
||||||
| Kind | Owner | Parameter IDs | Metadata/reset defaults |
|
| Kind | Owner | Parameter IDs | Metadata/reset defaults |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
|
|
@ -59,39 +67,44 @@ IDs never mean a dense list index and are not DSP pointers:
|
||||||
| PLUGIN | LADSPA graph node ID | Actual input-control port | Descriptor name, bounds, default and discrete/logarithmic hints; units unspecified |
|
| PLUGIN | LADSPA graph node ID | Actual input-control port | Descriptor name, bounds, default and discrete/logarithmic hints; units unspecified |
|
||||||
| LIVE | MIDI channel 0..15 | 0 volume, 1 pan, 2 sustain | Volume 0..1 default 1; pan -1..1 default 0; sustain boolean default 0 |
|
| LIVE | MIDI channel 0..15 | 0 volume, 1 pan, 2 sustain | Volume 0..1 default 1; pan -1..1 default 0; sustain boolean default 0 |
|
||||||
|
|
||||||
`xtc_project_parameter` returns copied metadata, static configuration and whether
|
`xtc_project_parameter` returns copied metadata, static configuration and
|
||||||
a lane exists. LIVE values are reset defaults, not callback-owned controller
|
whether a lane exists. LIVE values are reset defaults, not callback-owned
|
||||||
readbacks. `xtc_project_set_parameter` changes TRACK/PLUGIN static configuration
|
controller readbacks. `xtc_project_set_parameter` changes TRACK/PLUGIN static
|
||||||
without deleting automation. `xtc_project_automate` sets/replaces/removes points
|
configuration without deleting automation. `xtc_project_automate`
|
||||||
for TRACK/PLUGIN through one C contract. LIVE static setters and timeline lanes
|
sets/replaces/removes points for TRACK/PLUGIN through one C contract. LIVE
|
||||||
are unsupported: these controls belong to incoming MIDI events, not the arranged
|
static setters and timeline lanes are unsupported: these controls belong to
|
||||||
instrument. Plugin metadata/control edits execute trusted discovery on the
|
incoming MIDI events, not the arranged instrument. Plugin metadata/control edits
|
||||||
control thread; they never run inside audio. Model-only clients must compile and
|
execute trusted discovery on the control thread; they never run inside audio.
|
||||||
publish accepted snapshots before rendering; GUI edits do this transactionally.
|
Model-only clients must compile and publish accepted snapshots before rendering;
|
||||||
|
GUI edits do this transactionally.
|
||||||
|
|
||||||
Unknown owners/ports fail without touching the destination model/output. Missing
|
Unknown owners/ports fail without touching the destination model/output. Missing
|
||||||
plugin modules fail discovery rather than guessing ranges or installing a dummy.
|
plugin modules fail discovery rather than guessing ranges or installing a dummy.
|
||||||
Track deletion removes its lanes; plugin deletion removes its embedded lanes.
|
Track deletion removes its lanes; plugin deletion removes its embedded lanes.
|
||||||
Compatible plugin replacement resets controls/automation as described in
|
Compatible plugin replacement resets controls/automation as described in
|
||||||
PLUGIN_HOSTING.md. Persisted dangling references reject the complete load;
|
PLUGIN_HOSTING.md. Persisted dangling references reject the complete load; the
|
||||||
the current project remains intact. The GUI reports rejected edits/Open failures.
|
current project remains intact. The GUI reports rejected edits/Open failures.
|
||||||
|
|
||||||
## Interpolation and precedence
|
---
|
||||||
|
|
||||||
|
## Interpolation and Precedence
|
||||||
|
|
||||||
The Mixer Interpolation chooser selects Linear or Hold (step) for the point
|
The Mixer Interpolation chooser selects Linear or Hold (step) for the point
|
||||||
being added/replaced. A point owns the segment beginning there. At a hold point,
|
being added/replaced. A point owns the segment beginning there. At a hold point,
|
||||||
its value remains until the next point's exact sample. Linear segments interpolate
|
its value remains until the next point's exact sample. Linear segments
|
||||||
between endpoint values without an extra smoothing stage. Hold first/last before/
|
interpolate between endpoint values without an extra smoothing stage. Hold
|
||||||
after the lane. Gain/pan for tracks and buses support both; integer/toggle LADSPA
|
first/last before/ after the lane. Gain/pan for tracks and buses support both;
|
||||||
controls require hold. Existing files migrate mixer points to linear.
|
integer/toggle LADSPA controls require hold. Existing files migrate mixer points
|
||||||
|
to linear.
|
||||||
|
|
||||||
Automation is absolute project time, independent of clip starts, ends, trims,
|
Automation is absolute project time, independent of clip starts, ends, trims,
|
||||||
splits and moves; it neither restarts nor resets at a clip boundary. Tick-to-sample
|
splits and moves; it neither restarts nor resets at a clip boundary.
|
||||||
rounding uses the prepared constant tempo/rate; distinct ticks landing on the
|
Tick-to-sample rounding uses the prepared constant tempo/rate; distinct ticks
|
||||||
same sample choose the greatest tick. Empty lanes restore the static value.
|
landing on the same sample choose the greatest tick. Empty lanes restore the
|
||||||
Static edits while a lane exists change the fallback value, not the audible lane.
|
static value. Static edits while a lane exists change the fallback value, not
|
||||||
GUI changes stop/rebuild snapshots; live mutation of faders/plugin instances is
|
the audible lane. GUI changes stop/rebuild snapshots; live mutation of
|
||||||
not introduced. Plugin reset removes lanes only when explicitly applied.
|
faders/plugin instances is not introduced. Plugin reset removes lanes only when
|
||||||
|
explicitly applied.
|
||||||
|
|
||||||
At each sample, arranged track/bus and plugin lanes apply to their own targets.
|
At each sample, arranged track/bus and plugin lanes apply to their own targets.
|
||||||
Incoming MIDI volume/pan/sustain affect only live sine voices on that channel,
|
Incoming MIDI volume/pan/sustain affect only live sine voices on that channel,
|
||||||
|
|
@ -107,41 +120,47 @@ the new position. Backward jumps evaluate the earlier timeline again; tests
|
||||||
exercise explicit wraps. There is no loop transport feature or promise to
|
exercise explicit wraps. There is no loop transport feature or promise to
|
||||||
restore opaque LADSPA delay history across jumps (transport reset retains it).
|
restore opaque LADSPA delay history across jumps (transport reset retains it).
|
||||||
|
|
||||||
## Configurable live MIDI bindings
|
---
|
||||||
|
|
||||||
|
## Configurable Live MIDI Bindings
|
||||||
|
|
||||||
Audio → MIDI controller mapping lists the current 16 channels. Enter
|
Audio → MIDI controller mapping lists the current 16 channels. Enter
|
||||||
`channel volume_CC pan_CC sustain_CC`, for example `2 1 74 11`. Channels are
|
`channel volume_CC pan_CC sustain_CC`, for example `2 1 74 11`. Channels are
|
||||||
zero-based; CCs are 0..127, or 128 to disable a target. Enabled CCs must be distinct
|
zero-based; CCs are 0..127, or 128 to disable a target. Enabled CCs must be
|
||||||
within a channel; CC120 and CC123 cannot be rebound. All channels default to
|
distinct within a channel; CC120 and CC123 cannot be rebound. All channels
|
||||||
7/10/64. Rebinding replaces the old binding; it is not an additional route. An
|
default to 7/10/64. Rebinding replaces the old binding; it is not an additional
|
||||||
unmapped CC does nothing. Other channels remain independent. The same volume,
|
route. An unmapped CC does nothing. Other channels remain independent. The same
|
||||||
pan and sustain transfer functions apply regardless of the chosen CC number.
|
volume, pan and sustain transfer functions apply regardless of the chosen CC
|
||||||
Disabling a target leaves it at its runtime reset value until plan replacement.
|
number. Disabling a target leaves it at its runtime reset value until plan
|
||||||
Changing a map stops/rebuilds playback and is one undoable edit; maps survive
|
replacement. Changing a map stops/rebuilds playback and is one undoable edit;
|
||||||
save/Open and undo/redo. Cancel and invalid/duplicate/reserved bindings retain
|
maps survive save/Open and undo/redo. Cancel and invalid/duplicate/reserved
|
||||||
the prior configuration. There is no automatic learn, arbitrary plugin/track CC
|
bindings retain the prior configuration. There is no automatic learn, arbitrary
|
||||||
mapping, MIDI capture or write/touch/latch automation mode.
|
plugin/track CC mapping, MIDI capture or write/touch/latch automation mode.
|
||||||
|
|
||||||
Plans copy only 48 binding bytes on the control thread. The callback compares
|
Plans copy only 48 binding bytes on the control thread. The callback compares at
|
||||||
at most three CC numbers per control event, uses existing preallocated ramps/
|
most three CC numbers per control event, uses existing preallocated ramps/
|
||||||
voices and the existing 256-event block budget. Decode now accepts all valid
|
voices and the existing 256-event block budget. Decode now accepts all valid
|
||||||
three-byte CC messages; even unmapped CCs count against that event budget.
|
three-byte CC messages; even unmapped CCs count against that event budget. Mixer
|
||||||
Mixer points compile to bounded sorted arrays with binary lane lookup; processing
|
points compile to bounded sorted arrays with binary lane lookup; processing does
|
||||||
does no allocation, sort, file/module I/O, locking or GUI work. LADSPA automated
|
no allocation, sort, file/module I/O, locking or GUI work. LADSPA automated
|
||||||
run(1) cost and native plugin trust limits remain unchanged.
|
run(1) cost and native plugin trust limits remain unchanged.
|
||||||
|
|
||||||
## Persistence and verification
|
---
|
||||||
|
|
||||||
|
## Persistence and Verification
|
||||||
|
|
||||||
Project v10 appends a mixer interpolation field and 16 controller-map records;
|
Project v10 appends a mixer interpolation field and 16 controller-map records;
|
||||||
v1–v9 migrate to linear mixer lanes and default 7/10/64 maps. LADSPA point encoding
|
v1–v9 migrate to linear mixer lanes and default 7/10/64 maps. LADSPA point
|
||||||
is unchanged. Public `xtc_automation_point` gains `step`: rebuild clients and
|
encoding is unchanged. Public `xtc_automation_point` gains `step`: rebuild
|
||||||
initialize it to 0 (linear) or 1 (hold). See PROJECT_FORMAT.md for exact grammar.
|
clients and initialize it to 0 (linear) or 1 (hold). See PROJECT_FORMAT.md for
|
||||||
|
exact grammar.
|
||||||
|
|
||||||
`test_parameters` covers metadata, missing targets, static/automation precedence,
|
`test_parameters` covers metadata, missing targets, static/automation
|
||||||
exact hold/linear boundaries, save/reopen, malformed maps, low-rate sample
|
precedence, exact hold/linear boundaries, save/reopen, malformed maps, low-rate
|
||||||
collisions, odd blocks, seeks and backward jumps. `test_control` compares default
|
sample collisions, odd blocks, seeks and backward jumps. `test_control` compares
|
||||||
and remapped event streams, stereo pan, disabled/unmapped controls and immutable
|
default and remapped event streams, stereo pan, disabled/unmapped controls and
|
||||||
plan maps across resets. Plugin tests cover common-target edits and persistence;
|
immutable plan maps across resets. Plugin tests cover common-target edits and
|
||||||
GUI tests cover interpolation, map rollback, undo/redo and save/Open. Existing
|
persistence; GUI tests cover interpolation, map rollback, undo/redo and
|
||||||
callback guards and sanitizers verify host ownership constraints. Physical
|
save/Open. Existing callback guards and sanitizers verify host ownership
|
||||||
controller devices, listening and extended high-density endurance are pending.
|
constraints. Physical controller devices, listening and extended high-density
|
||||||
|
endurance are pending.
|
||||||
|
|
|
||||||
|
|
@ -1,42 +1,53 @@
|
||||||
# Creative workflow additions
|
# Creative Workflow Additions
|
||||||
|
|
||||||
These features prioritize fast musical experiments and retain the existing
|
These features prioritize fast musical experiments and retain the existing
|
||||||
control-thread preparation and project undo model. They introduce no dependency
|
control-thread preparation and project undo model. They introduce no dependency
|
||||||
or project-format change.
|
or project-format change.
|
||||||
|
|
||||||
## Selected track inserts
|
---
|
||||||
|
|
||||||
|
## Selected Track Inserts
|
||||||
|
|
||||||
**Track → Show selected track inserts** (Ctrl+5) opens the sequencer or active
|
**Track → Show selected track inserts** (Ctrl+5) opens the sequencer or active
|
||||||
mixer selection directly. Bus inserts are unsupported; no selection leaves the
|
mixer selection directly. Bus inserts are unsupported; no selection leaves the
|
||||||
workspace unchanged. **View → Track inserts** still opens the rack independently.
|
workspace unchanged. **View → Track inserts** still opens the rack
|
||||||
Ctrl+4 remains the piano-roll command, resolving the earlier shortcut collision.
|
independently. Ctrl+4 remains the piano-roll command, resolving the earlier
|
||||||
|
shortcut collision.
|
||||||
|
|
||||||
## Duplicate an effect
|
---
|
||||||
|
|
||||||
Select a slot, then **Rack actions → Duplicate effect**. The copy appears directly
|
## Duplicate an Effect
|
||||||
after it, retaining controls, automation, wet amount and bypass. It is an
|
|
||||||
independent instance with fresh processing history. Eight-slot capacity and
|
Select a slot, then **Rack actions → Duplicate effect**. The copy appears
|
||||||
|
directly after it, retaining controls, automation, wet amount and bypass. It is
|
||||||
|
an independent instance with fresh processing history. Eight-slot capacity and
|
||||||
plugin preparation errors preserve the old chain; Undo removes the copy.
|
plugin preparation errors preserve the old chain; Undo removes the copy.
|
||||||
|
|
||||||
## Copy a chain between tracks
|
---
|
||||||
|
|
||||||
|
## Copy A Chain Between Tracks
|
||||||
|
|
||||||
**Rack actions → Copy chain** stores an independent metadata snapshot. Select
|
**Rack actions → Copy chain** stores an independent metadata snapshot. Select
|
||||||
another track and use **Paste chain (replace)** to replace its complete chain,
|
another track and use **Paste chain (replace)** to replace its complete chain,
|
||||||
including output gain. Copying neither loads modules nor changes undo history;
|
including output gain. Copying neither loads modules nor changes undo history;
|
||||||
pasting prepares the candidate and is undoable. The clipboard is internal to
|
pasting prepares the candidate and is undoable. The clipboard is internal to
|
||||||
this session and clears on successful New/Open. Preparation errors keep both
|
this session and clears on successful New/Open. Preparation errors keep both the
|
||||||
the destination and clipboard intact.
|
destination and clipboard intact.
|
||||||
|
|
||||||
## Compare effect configurations
|
---
|
||||||
|
|
||||||
**Rack actions → Compare** captures or recalls A and B. Each slot is bound to the
|
## Compare Effect Configurations
|
||||||
track where it was captured; Recall is available only on that track. Capturing
|
|
||||||
copies metadata without affecting undo or loading modules. Recall prepares a
|
|
||||||
fresh chain and is undoable; histories and opaque plugin states are excluded.
|
|
||||||
The two comparison slots clear on successful New/Open. Comparisons stop
|
|
||||||
transport when recalled, following the existing safe insert-edit workflow.
|
|
||||||
|
|
||||||
## Creative starting points
|
**Rack actions → Compare** captures or recalls A and B. Each slot is bound to
|
||||||
|
the track where it was captured; Recall is available only on that track.
|
||||||
|
Capturing copies metadata without affecting undo or loading modules. Recall
|
||||||
|
prepares a fresh chain and is undoable; histories and opaque plugin states are
|
||||||
|
excluded. The two comparison slots clear on successful New/Open. Comparisons
|
||||||
|
stop transport when recalled, following the existing safe insert-edit workflow.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Creative Starting Points
|
||||||
|
|
||||||
**Add effect → Templates (replace)** offers Slapback (80 ms delay), Dub Echo
|
**Add effect → Templates (replace)** offers Slapback (80 ms delay), Dub Echo
|
||||||
(375 ms feedback delay into a short reverb), and Ambient Space (long reverb into
|
(375 ms feedback delay into a short reverb), and Ambient Space (long reverb into
|
||||||
|
|
@ -45,15 +56,19 @@ no external plugins. All controls remain editable. Times are milliseconds;
|
||||||
feedback and wet levels are deliberate starting points, without automatic
|
feedback and wet levels are deliberate starting points, without automatic
|
||||||
loudness matching or a claim that the presets suit every source.
|
loudness matching or a claim that the presets suit every source.
|
||||||
|
|
||||||
## Bulk rack actions
|
---
|
||||||
|
|
||||||
|
## Bulk Rack Actions
|
||||||
|
|
||||||
**Enable all effects**, **Bypass all effects**, and **Clear chain** each prepare
|
**Enable all effects**, **Bypass all effects**, and **Clear chain** each prepare
|
||||||
one undoable edit. Enabling all intentionally enables every slot, including
|
one undoable edit. Enabling all intentionally enables every slot, including
|
||||||
previously bypassed effects; Undo restores the previous mixed bypass state.
|
previously bypassed effects; Undo restores the previous mixed bypass state.
|
||||||
Clear removes slots while preserving chain output gain. No plugin resources
|
Clear removes slots while preserving chain output gain. No plugin resources are
|
||||||
are released in the audio callback. Empty racks return a no-result error.
|
released in the audio callback. Empty racks return a no-result error.
|
||||||
|
|
||||||
## Meter while editing effects
|
---
|
||||||
|
|
||||||
|
## Meter While Editing Effects
|
||||||
|
|
||||||
The insert workspace shows the selected track's stereo sample peaks after its
|
The insert workspace shows the selected track's stereo sample peaks after its
|
||||||
fader and before its bus, including the effects' output. Green bars release at
|
fader and before its bus, including the effects' output. Green bars release at
|
||||||
|
|
@ -62,34 +77,41 @@ it. Stopped, offline or missing-track readings show the -90 dBFS floor. Changing
|
||||||
tracks clears the indicator. These are sample peaks, not true-peak or loudness
|
tracks clears the indicator. These are sample peaks, not true-peak or loudness
|
||||||
measurements. The display shares the mixer's existing backend snapshot read.
|
measurements. The display shares the mixer's existing backend snapshot read.
|
||||||
|
|
||||||
## Tap tempo
|
---
|
||||||
|
|
||||||
|
## Tap Tempo
|
||||||
|
|
||||||
Tap the transport **Tap** button at a quarter-note pulse. The estimator averages
|
Tap the transport **Tap** button at a quarter-note pulse. The estimator averages
|
||||||
the last four valid intervals and accepts 20–300 BPM. The first tap primes it;
|
the last four valid intervals and accepts 20–300 BPM. The first tap primes it; a
|
||||||
a pause longer than three seconds restarts it. Too-fast or backward timestamps
|
pause longer than three seconds restarts it. Too-fast or backward timestamps are
|
||||||
are ignored. Each accepted tempo is an undoable edit and stops playback before
|
ignored. Each accepted tempo is an undoable edit and stops playback before
|
||||||
preparation; tapping is unavailable while recording. New/Open resets tap history.
|
preparation; tapping is unavailable while recording. New/Open resets tap
|
||||||
The estimator uses monotonic control-thread time, with no audio-callback clock
|
history. The estimator uses monotonic control-thread time, with no
|
||||||
access or allocation. Tap timing is not a beat detector or MIDI clock sync.
|
audio-callback clock access or allocation. Tap timing is not a beat detector or
|
||||||
|
MIDI clock sync.
|
||||||
|
|
||||||
## Audio crossfades
|
---
|
||||||
|
|
||||||
Select two partially overlapping audio clips on the same track and choose
|
## Audio Crossfades
|
||||||
**Edit → Audio tools → Crossfade two selected clips**. The earlier clip fades
|
|
||||||
out across the overlap while the later clip fades in. Gains, positions, source
|
|
||||||
files and the opposite fades are preserved. Equal boundaries, containment,
|
|
||||||
adjacency, cross-track selections and MIDI clips reject without partial edits.
|
|
||||||
This is a linear tick-based crossfade using existing clip envelopes; it does
|
|
||||||
not move clips, create overlaps or offer equal-power curves. Discrete sample
|
|
||||||
endpoints retain the engine's existing one-sample boundary convention.
|
|
||||||
|
|
||||||
## Chord strumming
|
Select two partially overlapping audio clips on the same track and choose **Edit
|
||||||
|
→ Audio tools → Crossfade two selected clips**. The earlier clip fades out
|
||||||
|
across the overlap while the later clip fades in. Gains, positions, source files
|
||||||
|
and the opposite fades are preserved. Equal boundaries, containment, adjacency,
|
||||||
|
cross-track selections and MIDI clips reject without partial edits. This is a
|
||||||
|
linear tick-based crossfade using existing clip envelopes; it does not move
|
||||||
|
clips, create overlaps or offer equal-power curves. Discrete sample endpoints
|
||||||
|
retain the engine's existing one-sample boundary convention.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chord Strumming
|
||||||
|
|
||||||
Select MIDI clips and use **Edit → MIDI tools → Strum chords...**. Enter spacing
|
Select MIDI clips and use **Edit → MIDI tools → Strum chords...**. Enter spacing
|
||||||
in ticks (1–960) and direction (0 ascending, 1 descending). Notes sharing a source
|
in ticks (1–960) and direction (0 ascending, 1 descending). Notes sharing a
|
||||||
onset and MIDI channel within each clip form a chord. Equal pitches use stable
|
source onset and MIDI channel within each clip form a chord. Equal pitches use
|
||||||
note-ID order. Each successive note starts one spacing later, while its end,
|
stable note-ID order. Each successive note starts one spacing later, while its
|
||||||
pitch, velocity and channel remain unchanged. Single notes remain unchanged.
|
end, pitch, velocity and channel remain unchanged. Single notes remain
|
||||||
Any resulting zero/negative duration rejects the entire edit; Undo restores the
|
unchanged. Any resulting zero/negative duration rejects the entire edit; Undo
|
||||||
whole selection. This edits source notes, including notes hidden by clip trims.
|
restores the whole selection. This edits source notes, including notes hidden by
|
||||||
It does not generate an arpeggiator or schedule live input.
|
clip trims. It does not generate an arpeggiator or schedule live input.
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
# Editing commands and undo audit
|
# Editing Commands and Undo Audit
|
||||||
|
|
||||||
The control thread owns project edits and history. Audio plans are immutable
|
The control thread owns project edits and history. Audio plans are immutable
|
||||||
snapshots; widgets never pass editable project pointers into the callback.
|
snapshots; widgets never pass editable project pointers into the callback. Graph
|
||||||
Graph commands and batch note commands use the existing public C command APIs.
|
commands and batch note commands use the existing public C command APIs. The GUI
|
||||||
The GUI groups a completed gesture or accepted dialog as one history step.
|
groups a completed gesture or accepted dialog as one history step.
|
||||||
|
|
||||||
## Operation audit
|
---
|
||||||
|
|
||||||
|
## Operation Audit
|
||||||
|
|
||||||
| Operation | History / grouping | Engine and external effects |
|
| Operation | History / grouping | Engine and external effects |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
|
|
@ -30,7 +32,9 @@ plus a baseline; new accepted edits discard redo, and eviction drops the oldest
|
||||||
baseline. Monotonic ID high-water marks survive undo and branches. History is
|
baseline. Monotonic ID high-water marks survive undo and branches. History is
|
||||||
session-only; restart/New/Open discards it.
|
session-only; restart/New/Open discards it.
|
||||||
|
|
||||||
## History ownership and failure boundary
|
---
|
||||||
|
|
||||||
|
## History Ownership and Failure Boundary
|
||||||
|
|
||||||
`xtc_history_reserve` allocates one empty fixed-capacity project/graph snapshot
|
`xtc_history_reserve` allocates one empty fixed-capacity project/graph snapshot
|
||||||
before an edit mutates the document or a candidate is submitted to the engine.
|
before an edit mutates the document or a candidate is submitted to the engine.
|
||||||
|
|
@ -47,8 +51,8 @@ The snapshot contains metadata/graph configuration only, never sample buffers,
|
||||||
DSP instances, module handles or GUI pointers. An unused reservation is freed
|
DSP instances, module handles or GUI pointers. An unused reservation is freed
|
||||||
with history. This adds at most one pending metadata snapshot to the 33 retained
|
with history. This adds at most one pending metadata snapshot to the 33 retained
|
||||||
states. C clients that call record without reserving retain the original
|
states. C clients that call record without reserving retain the original
|
||||||
clone-and-report-allocation-failure behavior; they must handle that result.
|
clone-and-report-allocation-failure behavior; they must handle that result. All
|
||||||
All history work is serialized on the control thread, never the audio callback.
|
history work is serialized on the control thread, never the audio callback.
|
||||||
|
|
||||||
Undo/redo checks out an owned candidate without moving the cursor, stops/resets
|
Undo/redo checks out an owned candidate without moving the cursor, stops/resets
|
||||||
transport and prepares its assets/plans, then accepts the adjacent history step
|
transport and prepares its assets/plans, then accepts the adjacent history step
|
||||||
|
|
@ -57,33 +61,38 @@ cursor/document, so retry is possible. Preparation failure may leave transport
|
||||||
stopped at zero; it does not resume playback automatically. Snapshot restoration
|
stopped at zero; it does not resume playback automatically. Snapshot restoration
|
||||||
marks the document dirty conservatively, even if it matches a saved file.
|
marks the document dirty conservatively, even if it matches a saved file.
|
||||||
|
|
||||||
## Selection, focus and menus
|
---
|
||||||
|
|
||||||
Ctrl+Z undoes; Ctrl+Shift+Z and Ctrl+Y redo. The main Edit menu disables unavailable
|
## Selection, Focus and Menus
|
||||||
steps and disables history while recording. Piano roll also has Edit/Undo/Redo
|
|
||||||
shortcuts. Undo preserves currently selected track/clip, mixer strip, graph node
|
|
||||||
and piano-roll clip/note when their stable IDs still exist (notes must remain
|
|
||||||
visible under the current filter). Clip selection follows its restored track. A removed selection
|
|
||||||
clears, with track fallback for a removed clip. A visible piano roll stays open
|
|
||||||
when its clip survives; missing clips hide it. Historical selections/layouts are
|
|
||||||
not saved in snapshots; undo does not resurrect a selection already cleared by
|
|
||||||
a deletion. Open/New retain their reset behavior.
|
|
||||||
|
|
||||||
Editor-local shortcuts act on focused editors. Text inputs retain Space and
|
Ctrl+Z undoes; Ctrl+Shift+Z and Ctrl+Y redo. The main Edit menu disables
|
||||||
text undo/editing keys; numeric mixer inputs do not invoke fader shortcuts.
|
unavailable steps and disables history while recording. Piano roll also has
|
||||||
Timeline Ctrl+D duplicates, F2 renames, Alt+Up/Down reorders tracks, S splits
|
Edit/Undo/Redo shortcuts. Undo preserves currently selected track/clip, mixer
|
||||||
audio at the cursor, A opens audio properties and Delete removes the selection.
|
strip, graph node and piano-roll clip/note when their stable IDs still exist
|
||||||
Graph Left/Right chooses a node, L arranges by flow, I inserts unity gain in the
|
(notes must remain visible under the current filter). Clip selection follows its
|
||||||
selected wire, Delete removes the selected node/wire and Escape cancels gestures.
|
restored track. A removed selection clears, with track fallback for a removed
|
||||||
Piano-roll commands are listed in its Notes menu. Escape cancels gestures;
|
clip. A visible piano roll stays open when its clip survives; missing clips hide
|
||||||
ordinary deletion is reversible and does not add a confirmation dialog.
|
it. Historical selections/layouts are not saved in snapshots; undo does not
|
||||||
|
resurrect a selection already cleared by a deletion. Open/New retain their reset
|
||||||
|
behavior.
|
||||||
|
|
||||||
|
Editor-local shortcuts act on focused editors. Text inputs retain Space and text
|
||||||
|
undo/editing keys; numeric mixer inputs do not invoke fader shortcuts. Timeline
|
||||||
|
Ctrl+D duplicates, F2 renames, Alt+Up/Down reorders tracks, S splits audio at
|
||||||
|
the cursor, A opens audio properties and Delete removes the selection. Graph
|
||||||
|
Left/Right chooses a node, L arranges by flow, I inserts unity gain in the
|
||||||
|
selected wire, Delete removes the selected node/wire and Escape cancels
|
||||||
|
gestures. Piano-roll commands are listed in its Notes menu. Escape cancels
|
||||||
|
gestures; ordinary deletion is reversible and does not add a confirmation
|
||||||
|
dialog.
|
||||||
|
|
||||||
Graph right-click now selects the node/wire under the pointer before showing
|
Graph right-click now selects the node/wire under the pointer before showing
|
||||||
Inspect/Arrange/Insert/Delete; empty space clears a stale selection. Piano-roll
|
Inspect/Arrange/Insert/Delete; empty space clears a stale selection. Piano-roll
|
||||||
right-click selects the clicked note and offers Properties/Quantize/Repeat/Delete.
|
right-click selects the clicked note and offers
|
||||||
It no longer immediately deletes the note. Timeline context menus retain their
|
Properties/Quantize/Repeat/Delete. It no longer immediately deletes the note.
|
||||||
selection and duplicate/rename/delete/audio commands. Dismissing a context menu
|
Timeline context menus retain their selection and duplicate/rename/delete/audio
|
||||||
does not edit the document. Context menus and widgets remain C++/FLTK UI code.
|
commands. Dismissing a context menu does not edit the document. Context menus
|
||||||
|
and widgets remain C++/FLTK UI code.
|
||||||
|
|
||||||
Open/import/plugin load/replacement paint a busy cursor and operation status
|
Open/import/plugin load/replacement paint a busy cursor and operation status
|
||||||
before synchronous work, flushing drawing without dispatching new input or
|
before synchronous work, flushing drawing without dispatching new input or
|
||||||
|
|
@ -93,13 +102,15 @@ optional-support and audio errors. Unsaved New/Open/Quit and Save As overwrite
|
||||||
keep their existing confirmations; undoable deletes and external-media reference
|
keep their existing confirmations; undoable deletes and external-media reference
|
||||||
edits do not request extra approval. No operation here deletes source media.
|
edits do not request extra approval. No operation here deletes source media.
|
||||||
|
|
||||||
## Evidence and manual procedure
|
---
|
||||||
|
|
||||||
`make all test gui test-gui-plugins test-reliability analyze test-workflow
|
## Evidence and Manual Procedure
|
||||||
test-gui-jack` covers core commands, grouped gestures/batches, backend rollback,
|
|
||||||
selection retention, take undo/redo and real software JACK state restoration.
|
`make all test gui test-gui-plugins test-reliability analyze test-workflow test-gui-jack`
|
||||||
The GUI fixture injects history-reservation failure before graph/map/import
|
covers core commands, grouped gestures/batches, backend rollback, selection
|
||||||
publication and verifies unchanged document, submission count and redo. The
|
retention, take undo/redo and real software JACK state restoration. The GUI
|
||||||
|
fixture injects history-reservation failure before graph/map/import publication
|
||||||
|
and verifies unchanged document, submission count and redo. The
|
||||||
allocation-interposed reliability suite fails each reservation allocation, then
|
allocation-interposed reliability suite fails each reservation allocation, then
|
||||||
fails all allocations while capturing a reserved edit; redo branching and
|
fails all allocations while capturing a reserved edit; redo branching and
|
||||||
snapshot restoration still succeed. ASan/UBSan cover the same ownership paths.
|
snapshot restoration still succeed. ASan/UBSan cover the same ownership paths.
|
||||||
|
|
|
||||||
225
docs/GUI.md
225
docs/GUI.md
|
|
@ -1,44 +1,51 @@
|
||||||
# GUI guidelines
|
# GUI Guidelines
|
||||||
|
|
||||||
Use FLTK/C++ for windows, menus, dialogs, and the event loop. Keep all audio
|
Use FLTK/C++ for windows, menus, dialogs, and the event loop. Keep all audio
|
||||||
engine and project-domain logic in C.
|
engine and project-domain logic in C.
|
||||||
|
|
||||||
Main views:
|
Main views:
|
||||||
|
|
||||||
- Sequencer: tracks, clips, ruler, playhead, selection, zoom and scrolling.
|
- Sequencer: tracks, clips, ruler, playhead, selection, zoom and scrolling.
|
||||||
- Mixer: channels, faders, pan, mute/solo and meters.
|
- Mixer: channels, faders, pan, mute/solo and meters.
|
||||||
- Modular graph: nodes, ports, connections, validation feedback.
|
- Modular graph: nodes, ports, connections, validation feedback.
|
||||||
- Transport: play/stop/record, tempo, meter, loop and position.
|
- Transport: play/stop/record, tempo, meter, loop and position.
|
||||||
|
|
||||||
Use custom-drawn widgets where ordinary controls are not a good fit: timeline,
|
Use custom-drawn widgets where ordinary controls are not a good fit: timeline,
|
||||||
waveforms, piano roll, mixer strips and graph canvas. Keep drawing separate
|
waveforms, piano roll, mixer strips and graph canvas. Keep drawing separate from
|
||||||
from project mutation. Never call FLTK from the audio thread.
|
project mutation. Never call FLTK from the audio thread.
|
||||||
|
|
||||||
Visual direction: compact, high-contrast, restrained dark interface. Avoid
|
Visual direction: compact, high-contrast, restrained dark interface. Avoid
|
||||||
excessive animation and modal configuration. Recreate broad usability ideas,
|
excessive animation and modal configuration. Recreate broad usability ideas, not
|
||||||
not energyXT's exact artwork or proprietary resources.
|
energyXT's exact artwork or proprietary resources.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Shell
|
## Shell
|
||||||
|
|
||||||
The shell opens JACK on startup through `xtc_backend.h`. It never accesses
|
The shell opens JACK on startup through `xtc_backend.h`. It never accesses
|
||||||
backend structures, processes samples, or calls JACK itself. Graph domain
|
backend structures, processes samples, or calls JACK itself. Graph domain data
|
||||||
data is owned by opaque C objects, manipulated only through the C API. All backend control calls run on the GUI thread; FLTK is never called
|
is owned by opaque C objects, manipulated only through the C API. All backend
|
||||||
from an audio callback. No server is started and no audio ports are connected
|
control calls run on the GUI thread; FLTK is never called from an audio
|
||||||
by the GUI. The initially empty graph produces silence.
|
callback. No server is started and no audio ports are connected by the GUI. The
|
||||||
|
initially empty graph produces silence.
|
||||||
|
|
||||||
- **Play / F5:** start the engine. **Stop / F8:** deactivate it. **Pause / F7:** hold playback. **Space:** toggle Play/Stop.
|
- **Play / F5:** start the engine. **Stop / F8:** deactivate it. **Pause / F7:**
|
||||||
**To start / Home:** stop and seek to zero. Pause/Home are disabled while recording.
|
hold playback. **Space:** toggle Play/Stop. **To start / Home:** stop and seek
|
||||||
These advance/pause the sample-counted playhead; imported audio clips play through their graph source.
|
to zero. Pause/Home are disabled while recording. These advance/pause the
|
||||||
- **Reconnect / F6:** close the old client and open a fresh stopped client.
|
sample-counted playhead; imported audio clips play through their graph source.
|
||||||
Use this after server loss or sample-rate changes. A failed close preserves
|
- **Reconnect / F6:** close the old client and open a fresh stopped client. Use
|
||||||
the handle and reports the failure instead of opening another client.
|
this after server loss or sample-rate changes. A failed close preserves the
|
||||||
|
handle and reports the failure instead of opening another client.
|
||||||
- **View menu / Ctrl+1, Ctrl+2, Ctrl+3:** switch between sequencer, mixer and
|
- **View menu / Ctrl+1, Ctrl+2, Ctrl+3:** switch between sequencer, mixer and
|
||||||
modular graph. Tabs provide the same view switching. Mixer, graph and sequencer editors are described below.
|
modular graph. Tabs provide the same view switching. Mixer, graph and
|
||||||
|
sequencer editors are described below.
|
||||||
- **File / Quit / Ctrl+Q** or the window close button: close the backend and
|
- **File / Quit / Ctrl+Q** or the window close button: close the backend and
|
||||||
synchronize audio callbacks before hiding/destroying widgets. A failed close
|
synchronize audio callbacks before hiding/destroying widgets. A failed close
|
||||||
leaves the window open for a retry. New/Open/Save actions are described below. About identifies the development milestone and version.
|
leaves the window open for a retry. New/Open/Save actions are described below.
|
||||||
|
About identifies the development milestone and version.
|
||||||
|
|
||||||
The indicator shows disconnected, ready, running, server lost, format changed
|
The indicator shows disconnected, ready, running, server lost, format changed or
|
||||||
or process-error states. The status line shows rate, actual block size, mono
|
process-error states. The status line shows rate, actual block size, mono
|
||||||
layout, processed block count, xruns and process result. Command errors remain
|
layout, processed block count, xruns and process result. Command errors remain
|
||||||
visible until a successful control action; periodic refresh does not erase them.
|
visible until a successful control action; periodic refresh does not erase them.
|
||||||
A GUI-owned 100 ms timer reads atomic snapshots and collects retired plans.
|
A GUI-owned 100 ms timer reads atomic snapshots and collects retired plans.
|
||||||
|
|
@ -54,41 +61,44 @@ process exit. Normal close/reconnect paths permit retry and release ownership
|
||||||
only after successful close. The entry point catches C++ exceptions before
|
only after successful close. The entry point catches C++ exceptions before
|
||||||
process exit. Backend operations return C error codes throughout.
|
process exit. Backend operations return C error codes throughout.
|
||||||
|
|
||||||
Tests: `make test-gui` runs real widgets/callbacks/timers against a fake C backend
|
Tests: `make test-gui` runs real widgets/callbacks/timers against a fake C
|
||||||
under Xvfb, including control errors, startup without JACK, partially initialized
|
backend under Xvfb, including control errors, startup without JACK, partially
|
||||||
handles, server/format notifications, view switching, retrying close, and timer
|
initialized handles, server/format notifications, view switching, retrying
|
||||||
removal. `make test-gui-jack` additionally requires a running JACK-compatible
|
close, and timer removal. `make test-gui-jack` additionally requires a running
|
||||||
server, tests repeated start/stop, reconnect and active-client close, and creates
|
JACK-compatible server, tests repeated start/stop, reconnect and active-client
|
||||||
no routes. Physical playback is outside this shell. See BUILD.md and the
|
close, and creates no routes. Physical playback is outside this shell. See
|
||||||
integration test README for sanitizer limitations and keyboard smoke results.
|
BUILD.md and the integration test README for sanitizer limitations and keyboard
|
||||||
|
smoke results.
|
||||||
|
|
||||||
## Modular editor
|
---
|
||||||
|
|
||||||
Open **Modular Graph** or press **Ctrl+3**. Add oscillator (440 Hz), gain (0.10),
|
## Modular Editor
|
||||||
pass-through meter or output nodes with the toolbar. Their parameters are fixed
|
|
||||||
presets in this milestone and are drawn on each node; parameter editing and
|
Open **Modular Graph** or press **Ctrl+3**. Add oscillator (440 Hz), gain
|
||||||
live meter display are not implemented. Connect oscillator → gain → meter →
|
(0.10), pass-through meter or output nodes with the toolbar. Their parameters
|
||||||
output for a simple test chain. No sound reaches hardware until ports are
|
are fixed presets in this milestone and are drawn on each node; parameter
|
||||||
explicitly connected outside the GUI. Output nodes are required to render;
|
editing and live meter display are not implemented. Connect oscillator → gain →
|
||||||
|
meter → output for a simple test chain. No sound reaches hardware until ports
|
||||||
|
are explicitly connected outside the GUI. Output nodes are required to render;
|
||||||
isolated sources and an empty graph produce silence.
|
isolated sources and an empty graph produce silence.
|
||||||
|
|
||||||
Drag a node body/title to move it. Drag a circular output port to an input port
|
Drag a node body/title to move it. Drag a circular output port to an input port
|
||||||
to connect. Click a node or wire to select it (yellow outline/wire), then press
|
to connect. Click a node or wire to select it (yellow outline/wire), then press
|
||||||
Delete/Backspace or **Delete selection**. Deleting a node deletes its incident
|
Delete/Backspace or **Delete selection**. Deleting a node deletes its incident
|
||||||
wires. Escape cancels a drag preview. Canvas scrollbars pan the view; positions
|
wires. Escape cancels a drag preview. Canvas scrollbars pan the view; positions
|
||||||
are retained across edits/reconnect but not across application restart. There
|
are retained across edits/reconnect but not across application restart. There is
|
||||||
is no graph zoom, multiselection or external hardware routing UI. Semantic
|
no graph zoom, multiselection or external hardware routing UI. Semantic graph
|
||||||
graph edits participate in project undo/redo; layout does not. The default
|
edits participate in project undo/redo; layout does not. The default project
|
||||||
project supports 64 nodes; auto-layout can grow the scrollable canvas.
|
supports 64 nodes; auto-layout can grow the scrollable canvas.
|
||||||
|
|
||||||
Every semantic action becomes a C graph command. The window owns a C project containing the graph
|
Every semantic action becomes a C graph command. The window owns a C project
|
||||||
handle and publishes the C-created candidate through the backend. Cycle,
|
containing the graph handle and publishes the C-created candidate through the
|
||||||
invalid-direction, duplicate connection, missing-port, capacity and backend
|
backend. Cycle, invalid-direction, duplicate connection, missing-port, capacity
|
||||||
failures are shown below the canvas; failed edits leave the graph unchanged.
|
and backend failures are shown below the canvas; failed edits leave the graph
|
||||||
Capacity feedback distinguishes the possible node limit/pending edit condition
|
unchanged. Capacity feedback distinguishes the possible node limit/pending edit
|
||||||
and allows retry. Editing while stopped replaces the prepared plan without
|
condition and allows retry. Editing while stopped replaces the prepared plan
|
||||||
starting playback. Editing with a disconnected startup backend stays local
|
without starting playback. Editing with a disconnected startup backend stays
|
||||||
until reconnect. A lost or changed live backend requires reconnect before
|
local until reconnect. A lost or changed live backend requires reconnect before
|
||||||
further semantic edits. Moving/selecting nodes does not touch the engine.
|
further semantic edits. Moving/selecting nodes does not touch the engine.
|
||||||
|
|
||||||
The graph state line distinguishes offline, prepared, queued and active states.
|
The graph state line distinguishes offline, prepared, queued and active states.
|
||||||
|
|
@ -100,54 +110,59 @@ rejected capacity edit. Plan replacement can reset oscillator phase and is not
|
||||||
crossfaded. Render validation and active replacement tests are described in
|
crossfaded. Render validation and active replacement tests are described in
|
||||||
tests/integration/README.md.
|
tests/integration/README.md.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Projects and sequencer
|
## Projects and Sequencer
|
||||||
|
|
||||||
File/New (Ctrl+N), Open (Ctrl+O), Save (Ctrl+S), and Save As
|
File/New (Ctrl+N), Open (Ctrl+O), Save (Ctrl+S), and Save As (Ctrl+Shift+S) use
|
||||||
(Ctrl+Shift+S) use native file dialogs and the C persistence API. New/Open/Quit
|
native file dialogs and the C persistence API. New/Open/Quit offer
|
||||||
offer Cancel/Discard when semantic edits are unsaved; save first to retain them.
|
Cancel/Discard when semantic edits are unsaved; save first to retain them. Save
|
||||||
Save As confirms overwrites. The title marks unsaved changes. Failed loads and
|
As confirms overwrites. The title marks unsaved changes. Failed loads and
|
||||||
backend submissions retain the old document. Loading parses before stopping
|
backend submissions retain the old document. Loading parses before stopping
|
||||||
audio; installing a valid candidate stops and resets transport before compiling
|
audio; installing a valid candidate stops and resets transport before compiling
|
||||||
and submitting. A later failure can leave the retained document stopped at zero.
|
and submitting. A later failure can leave the retained document stopped at zero.
|
||||||
Opening/New resets graph layout; graph positions are not saved. See PROJECT_FORMAT.md.
|
Opening/New resets graph layout; graph positions are not saved. See
|
||||||
|
PROJECT_FORMAT.md.
|
||||||
|
|
||||||
Sequencer offers Add track, Add region, Delete region/track, Zoom +/-. Select a
|
Sequencer offers Add track, Add region, Delete region/track, Zoom +/-. Select a
|
||||||
track header to add a one-bar region there at the cursor. Select a region to
|
track header to add a one-bar region there at the cursor. Select a region to
|
||||||
delete it; deleting a selected track cascades to its regions. Delete also works
|
delete it; deleting a selected track cascades to its regions. Delete also works
|
||||||
with canvas focus. Drag a region body to move it in time or between tracks;
|
with canvas focus. Drag a region body to move it in time or between tracks; drag
|
||||||
drag either edge to trim within its original source bounds. Edits commit on
|
either edge to trim within its original source bounds. Edits commit on release
|
||||||
release with the selected snap grid; Escape cancels. There is no drag preview.
|
with the selected snap grid; Escape cancels. There is no drag preview. Undo,
|
||||||
Undo, rename, tempo editing and additive clip selection are supported. Group
|
rename, tempo editing and additive clip selection are supported. Group commands,
|
||||||
commands, clipboard and musical transforms are described in
|
clipboard and musical transforms are described in
|
||||||
[MODERN_EDITING.md](MODERN_EDITING.md). Overlapping regions are permitted.
|
[MODERN_EDITING.md](MODERN_EDITING.md). Overlapping regions are permitted.
|
||||||
|
|
||||||
The scrollable canvas expands to cover the arrangement plus a margin; zoom
|
The scrollable canvas expands to cover the arrangement plus a margin; zoom
|
||||||
ranges from 24 to 384 pixels/quarter. Names, tempo and 4/4 meter are drawn.
|
ranges from 24 to 384 pixels/quarter. Names, tempo and 4/4 meter are drawn. A
|
||||||
A ruler click seeks while stopped (or positions the cursor when disconnected).
|
ruler click seeks while stopped (or positions the cursor when disconnected). The
|
||||||
The 100 ms GUI refresh converts the backend's actual sample counter to ticks;
|
100 ms GUI refresh converts the backend's actual sample counter to ticks; it
|
||||||
it never integrates wall-clock time. Play resumes and Stop pauses. Reconnect,
|
never integrates wall-clock time. Play resumes and Stop pauses. Reconnect, New
|
||||||
New and Open reset position. Add region creates silent metadata; imported WAV clips play through the
|
and Open reset position. Add region creates silent metadata; imported WAV clips
|
||||||
audio source node (see below). MIDI clips and notes are described below. The C model
|
play through the audio source node (see below). MIDI clips and notes are
|
||||||
supports a constant tempo; a tempo map and scheduler are future work.
|
described below. The C model supports a constant tempo; a tempo map and
|
||||||
|
scheduler are future work.
|
||||||
|
|
||||||
Tests cover C-model/persistence boundaries, GUI move/trim gestures and zoom,
|
Tests cover C-model/persistence boundaries, GUI move/trim gestures and zoom,
|
||||||
save/reopen, failed load/submission rollback, sample-derived cursor updates,
|
save/reopen, failed load/submission rollback, sample-derived cursor updates, and
|
||||||
and live JACK playhead advance/pause.
|
live JACK playhead advance/pause.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Audio workflow
|
## Audio Workflow
|
||||||
|
|
||||||
Use File/Import WAV (Ctrl+I) to add an audio clip at the playhead on the selected
|
Use File/Import WAV (Ctrl+I) to add an audio clip at the playhead on the
|
||||||
track, or on a new Audio track. Record (Shift+F5) chooses a WAV destination and
|
selected track, or on a new Audio track. Record (Shift+F5) chooses a WAV
|
||||||
captures JACK input until Stop finalizes and adds the take. No input routes are
|
destination and captures JACK input until Stop finalizes and adds the take. No
|
||||||
created automatically. Save after Stop; the project references the external WAV.
|
input routes are created automatically. Save after Stop; the project references
|
||||||
|
the external WAV.
|
||||||
|
|
||||||
Import creates an Audio clips graph source and output route if the source is
|
Import creates an Audio clips graph source and output route if the source is
|
||||||
absent. Modular Graph offers Add audio source for explicit routing through gain
|
absent. Modular Graph offers Add audio source for explicit routing through gain
|
||||||
or meter nodes. All tracks currently share one mono timeline mix. Arrangement
|
or meter nodes. All tracks currently share one mono timeline mix. Arrangement
|
||||||
edits stop playback; graph edits remain live outside recording. During recording,
|
edits stop playback; graph edits remain live outside recording. During
|
||||||
edits, file actions, reconnect and close require Stop first.
|
recording, edits, file actions, reconnect and close require Stop first.
|
||||||
|
|
||||||
Open/Play reports missing, unreadable or unsupported assets, preserving their
|
Open/Play reports missing, unreadable or unsupported assets, preserving their
|
||||||
regions as silence. The backend status shows the unique issue count. Select a
|
regions as silence. The backend status shows the unique issue count. Select a
|
||||||
|
|
@ -158,21 +173,26 @@ can block the GUI while reading, but never the audio callback.
|
||||||
See AUDIO_FILES.md for supported WAV formats, memory limits, musical placement,
|
See AUDIO_FILES.md for supported WAV formats, memory limits, musical placement,
|
||||||
recording overflow/partial-take recovery, external asset portability and the
|
recording overflow/partial-take recovery, external asset portability and the
|
||||||
software-only acceptance tests. Waveform drawing, input monitoring, recording
|
software-only acceptance tests. Waveform drawing, input monitoring, recording
|
||||||
latency compensation and per-track graph inserts are not implemented.
|
latency compensation and per-track graph inserts are not implemented. Per-track
|
||||||
Per-track gain/pan/mute/solo is available in the mixer below.
|
gain/pan/mute/solo is available in the mixer below.
|
||||||
|
|
||||||
## Piano roll
|
---
|
||||||
|
|
||||||
|
## Piano Roll
|
||||||
|
|
||||||
Add MIDI clip creates a one-bar clip on the selected/first existing track at the
|
Add MIDI clip creates a one-bar clip on the selected/first existing track at the
|
||||||
cursor. Select it and choose Piano roll (View/Piano roll, Ctrl+4). Click to draw,
|
cursor. Select it and choose Piano roll (View/Piano roll, Ctrl+4). Click to
|
||||||
drag a body to move pitch/time, drag its right edge to resize, and right-click
|
draw, drag a body to move pitch/time, drag its right edge to resize, and
|
||||||
or Delete to remove. Notes use source ticks with 1/16 snapping; trimmed source
|
right-click or Delete to remove. Notes use source ticks with 1/16 snapping;
|
||||||
content is retained. Edits stop transport and are blocked during audio recording.
|
trimmed source content is retained. Edits stop transport and are blocked during
|
||||||
Panic/F9 silences held notes; Record continues to mean WAV audio capture.
|
audio recording. Panic/F9 silences held notes; Record continues to mean WAV
|
||||||
Modular Graph offers Add instrument for explicit routing. Status includes MIDI
|
audio capture. Modular Graph offers Add instrument for explicit routing. Status
|
||||||
drops. See MIDI.md for voice limits, unsupported messages and live input routing.
|
includes MIDI drops. See MIDI.md for voice limits, unsupported messages and live
|
||||||
|
input routing.
|
||||||
|
|
||||||
## Mixer and editing
|
---
|
||||||
|
|
||||||
|
## Mixer and Editing
|
||||||
|
|
||||||
Mixer (Ctrl+2) now has a selectable track strip, gain/pan controls, mute/solo,
|
Mixer (Ctrl+2) now has a selectable track strip, gain/pan controls, mute/solo,
|
||||||
Output L/R peaks and editable gain/pan automation lanes. Mixer edits stop
|
Output L/R peaks and editable gain/pan automation lanes. Mixer edits stop
|
||||||
|
|
@ -182,35 +202,42 @@ and redo up to 32 project edits; New/Open resets history. M/S and arrow keys
|
||||||
provide mixer shortcuts. See MIXER.md for exact controls, history rollback,
|
provide mixer shortcuts. See MIXER.md for exact controls, history rollback,
|
||||||
stereo port routing, automation semantics and prototype limits.
|
stereo port routing, automation semantics and prototype limits.
|
||||||
|
|
||||||
## Minimal composition workflow
|
---
|
||||||
|
|
||||||
|
## Minimal Composition Workflow
|
||||||
|
|
||||||
[WORKFLOW.md](WORKFLOW.md) walks through creating, arranging, saving, closing,
|
[WORKFLOW.md](WORKFLOW.md) walks through creating, arranging, saving, closing,
|
||||||
reopening and playing MIDI/audio with the GUI. New/Open select Sequencer;
|
reopening and playing MIDI/audio with the GUI. New/Open select Sequencer; Ctrl+3
|
||||||
Ctrl+3 still opens the modular graph. Stop retains its established position-hold
|
still opens the modular graph. Stop retains its established position-hold
|
||||||
behavior and finalizes recording; explicit Pause retains position without
|
behavior and finalizes recording; explicit Pause retains position without
|
||||||
finalizing a take (and is refused during recording). Home stops and returns to
|
finalizing a take (and is refused during recording). Home stops and returns to
|
||||||
zero. Failed candidate installation now refreshes the actual backend state
|
zero. Failed candidate installation now refreshes the actual backend state even
|
||||||
even when the previous document is retained.
|
when the previous document is retained.
|
||||||
|
|
||||||
`make test-workflow` uses a live JACK-compatible backend and Xvfb, with exact
|
`make test-workflow` uses a live JACK-compatible backend and Xvfb, with exact
|
||||||
stereo render comparisons across destruction/recreation of the GUI and live
|
stereo render comparisons across destruction/recreation of the GUI and live
|
||||||
playhead/meter/transport checks. `test-gui` covers stop/seek failure and recording
|
playhead/meter/transport checks. `test-gui` covers stop/seek failure and
|
||||||
guards. No project files need manual editing for this workflow.
|
recording guards. No project files need manual editing for this workflow.
|
||||||
|
|
||||||
## Timing and transitions
|
---
|
||||||
|
|
||||||
|
## Timing and Transitions
|
||||||
|
|
||||||
The GUI enables 5 ms source boundaries and master start/stop ramps. Ordinary
|
The GUI enables 5 ms source boundaries and master start/stop ramps. Ordinary
|
||||||
Pause/Stop now request a fade and show “stopping” until the timer collects its
|
Pause/Stop now request a fade and show “stopping” until the timer collects its
|
||||||
acknowledgement and deactivates JACK. Recording Stop, Home, fault handling and
|
acknowledgement and deactivates JACK. Recording Stop, Home, fault handling and
|
||||||
project installation retain immediate semantics. See
|
project installation retain immediate semantics. See
|
||||||
[AUDIO_QUALITY.md](AUDIO_QUALITY.md) for timing, overload/denormal behavior, latency
|
[AUDIO_QUALITY.md](AUDIO_QUALITY.md) for timing, overload/denormal behavior,
|
||||||
limits, test commands and the pending human-listening checklist.
|
latency limits, test commands and the pending human-listening checklist.
|
||||||
|
|
||||||
## Routing refinement
|
---
|
||||||
|
|
||||||
|
## Routing Refinement
|
||||||
|
|
||||||
Graph selection now reports edge counts, output reachability and external-input
|
Graph selection now reports edge counts, output reachability and external-input
|
||||||
fallback. Direction arrows, role colors, incident-wire highlighting and no-output
|
fallback. Direction arrows, role colors, incident-wire highlighting and
|
||||||
badges help inspect routes. View / Arrange graph by signal flow (L) is a layout
|
no-output badges help inspect routes. View / Arrange graph by signal flow (L) is
|
||||||
command; Edit / Insert unity gain in selected wire (I) is one undoable graph edit.
|
a layout command; Edit / Insert unity gain in selected wire (I) is one undoable
|
||||||
Left/Right selects nodes; Tab retains ordinary focus navigation. See [ROUTING.md](ROUTING.md) for summing, stereo-lane,
|
graph edit. Left/Right selects nodes; Tab retains ordinary focus navigation. See
|
||||||
cycle, live publication and deferred grouping/template semantics.
|
[ROUTING.md](ROUTING.md) for summing, stereo-lane, cycle, live publication and
|
||||||
|
deferred grouping/template semantics.
|
||||||
|
|
|
||||||
399
docs/IDEA.md
399
docs/IDEA.md
|
|
@ -1,48 +1,78 @@
|
||||||
# Project Brief: A Modern, Lightweight, energyXT-Inspired DAW
|
# Project Brief: A Modern, Lightweight, energyXT-Inspired DAW
|
||||||
|
|
||||||
**Document purpose:** This file is the authoritative project brief and implementation guide for an AI coding agent working inside an IDE.
|
**Document purpose:** This file is the authoritative project brief and
|
||||||
|
implementation guide for an AI coding agent working inside an IDE.
|
||||||
|
|
||||||
**Working project name:** `xtc` (temporary; keep the project name configurable and do not hard-code it into public APIs).
|
**Working project name:** `xtc` (temporary; keep the project name configurable
|
||||||
|
and do not hard-code it into public APIs).
|
||||||
|
|
||||||
**Primary goal:** Build a modern, reliable, lightweight digital audio workstation inspired by the workflow and modular philosophy of energyXT. This is a new implementation, not a clone of energyXT's proprietary code or assets.
|
**Primary goal:** Build a modern, reliable, lightweight digital audio
|
||||||
|
workstation inspired by the workflow and modular philosophy of energyXT. This is
|
||||||
|
a new implementation, not a clone of energyXT's proprietary code or assets.
|
||||||
|
|
||||||
**Architecture decision:** **B — Modular engine first.** The sequencer, instruments, effects, mixers, audio inputs, and outputs are components in one unified processing graph. The default user experience should still be a simple sequencer-first workspace; users can open the modular view when they need to inspect or edit signal flow.
|
**Architecture decision:** **B — Modular engine first.** The sequencer,
|
||||||
|
instruments, effects, mixers, audio inputs, and outputs are components in one
|
||||||
|
unified processing graph. The default user experience should still be a simple
|
||||||
|
sequencer-first workspace; users can open the modular view when they need to
|
||||||
|
inspect or edit signal flow.
|
||||||
|
|
||||||
**Language decision:**
|
**Language decision:**
|
||||||
|
|
||||||
- **100% C for the audio engine and core domain logic.**
|
- **100% C for the audio engine and core domain logic.**
|
||||||
- **FLTK with C++ for the graphical user interface only.**
|
- **FLTK with C++ for the graphical user interface only.**
|
||||||
- The GUI talks to the core through a small, documented C API.
|
- The GUI talks to the core through a small, documented C API.
|
||||||
- Do not introduce C++ into the audio engine or core library.
|
- Do not introduce C++ into the audio engine or core library.
|
||||||
- Keep dependencies small, prefer open-source components, and avoid unnecessary frameworks.
|
- Keep dependencies small, prefer open-source components, and avoid unnecessary
|
||||||
|
frameworks.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 1. Instructions to the AI coding agent
|
## 1. Instructions to the AI Coding Agent
|
||||||
|
|
||||||
Treat this document as the project contract. Follow it in every implementation task.
|
Treat this document as the project contract. Follow it in every implementation
|
||||||
|
task.
|
||||||
|
|
||||||
1. Read this file and the existing project before making changes.
|
1. Read this file and the existing project before making changes.
|
||||||
2. Inspect the current build system, source tree, and tests. Do not assume the repository is empty.
|
2. Inspect the current build system, source tree, and tests. Do not assume the
|
||||||
3. Implement work in small, buildable increments. Each increment must compile and have relevant tests before proceeding.
|
repository is empty.
|
||||||
4. Prefer complete, coherent file updates over partial snippets. Do not silently remove existing functionality.
|
3. Implement work in small, buildable increments. Each increment must compile
|
||||||
5. Before editing, state briefly what you intend to change and which files are affected. Then make the changes.
|
and have relevant tests before proceeding.
|
||||||
6. Do not invent APIs, FLTK features, audio backend capabilities, or dependency behavior. Check installed headers and official documentation when uncertain.
|
4. Prefer complete, coherent file updates over partial snippets. Do not silently
|
||||||
7. Keep C source compatible with **C99** initially. Use C11 features only when explicitly justified and supported by the selected compiler/toolchain.
|
remove existing functionality.
|
||||||
8. Use C snake_case identifiers. Use clear names; avoid cryptic one-letter names except conventional loop counters.
|
5. Before editing, state briefly what you intend to change and which files are
|
||||||
9. Validate external input, lengths, indexes, counts, enum values, and allocation sizes. Handle errors explicitly.
|
affected. Then make the changes.
|
||||||
10. Do not hide failures, silently clamp invalid data, or continue with partially initialized objects.
|
6. Do not invent APIs, FLTK features, audio backend capabilities, or dependency
|
||||||
11. Avoid unnecessary dependencies, generated-code systems, global mutable state, and elaborate abstractions.
|
behavior. Check installed headers and official documentation when uncertain.
|
||||||
12. Never perform audio-thread-unsafe operations from the real-time callback. See the real-time rules below.
|
7. Keep C source compatible with **C99** initially. Use C11 features only when
|
||||||
13. Keep the project usable on Linux first. Do not make Linux-specific details leak into the public core API.
|
explicitly justified and supported by the selected compiler/toolchain.
|
||||||
|
8. Use C snake_case identifiers. Use clear names; avoid cryptic one-letter names
|
||||||
|
except conventional loop counters.
|
||||||
|
9. Validate external input, lengths, indexes, counts, enum values, and
|
||||||
|
allocation sizes. Handle errors explicitly.
|
||||||
|
10. Do not hide failures, silently clamp invalid data, or continue with
|
||||||
|
partially initialized objects.
|
||||||
|
11. Avoid unnecessary dependencies, generated-code systems, global mutable
|
||||||
|
state, and elaborate abstractions.
|
||||||
|
12. Never perform audio-thread-unsafe operations from the real-time callback.
|
||||||
|
See the real-time rules below.
|
||||||
|
13. Keep the project usable on Linux first. Do not make Linux-specific details
|
||||||
|
leak into the public core API.
|
||||||
14. Add or update tests and documentation with each feature.
|
14. Add or update tests and documentation with each feature.
|
||||||
15. At the end of a task, report: files changed, behavior added, build/test commands run, results, known limitations, and the next sensible step.
|
15. At the end of a task, report: files changed, behavior added, build/test
|
||||||
16. If a requirement is ambiguous, choose the smallest safe implementation consistent with this document and explain the assumption. Ask a question only if the ambiguity blocks safe progress.
|
commands run, results, known limitations, and the next sensible step.
|
||||||
17. Do not claim that a feature works unless it has been implemented and tested. Clearly distinguish a prototype, stub, and finished feature.
|
16. If a requirement is ambiguous, choose the smallest safe implementation
|
||||||
18. Never copy energyXT source code, proprietary resources, UI artwork, or undocumented internal implementation. Use energyXT only as inspiration for high-level workflow ideas.
|
consistent with this document and explain the assumption. Ask a question
|
||||||
|
only if the ambiguity blocks safe progress.
|
||||||
|
17. Do not claim that a feature works unless it has been implemented and tested.
|
||||||
|
Clearly distinguish a prototype, stub, and finished feature.
|
||||||
|
18. Never copy energyXT source code, proprietary resources, UI artwork, or
|
||||||
|
undocumented internal implementation. Use energyXT only as inspiration for
|
||||||
|
high-level workflow ideas.
|
||||||
|
|
||||||
### Definition of done for every task
|
### Definition of done for every task
|
||||||
|
|
||||||
A task is complete only when:
|
A task is complete only when:
|
||||||
|
|
||||||
- the code builds with warnings enabled;
|
- the code builds with warnings enabled;
|
||||||
- relevant tests pass;
|
- relevant tests pass;
|
||||||
- error paths are considered;
|
- error paths are considered;
|
||||||
|
|
@ -53,16 +83,19 @@ A task is complete only when:
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 2. Product principles
|
## 2. Product Principles
|
||||||
|
|
||||||
The application should feel like a small, responsive music instrument rather than a general-purpose content-creation suite.
|
The application should feel like a small, responsive music instrument rather
|
||||||
|
than a general-purpose content-creation suite.
|
||||||
|
|
||||||
### Core principles
|
### Core principles
|
||||||
|
|
||||||
- **Simple by default, powerful when opened up.**
|
- **Simple by default, powerful when opened up.**
|
||||||
- A single unified component graph underlies the application.
|
- A single unified component graph underlies the application.
|
||||||
- The sequencer, mixer, instruments, effects, audio I/O, and utility processors use a common node model.
|
- The sequencer, mixer, instruments, effects, audio I/O, and utility processors
|
||||||
- Common operations should require few clicks and avoid modal dialogs when practical.
|
use a common node model.
|
||||||
|
- Common operations should require few clicks and avoid modal dialogs when
|
||||||
|
practical.
|
||||||
- The modular graph should expose real signal flow, not be a decorative diagram.
|
- The modular graph should expose real signal flow, not be a decorative diagram.
|
||||||
- The project must remain understandable to a human developer.
|
- The project must remain understandable to a human developer.
|
||||||
- Audio reliability is more important than visual effects or feature count.
|
- Audio reliability is more important than visual effects or feature count.
|
||||||
|
|
@ -75,6 +108,7 @@ The application should feel like a small, responsive music instrument rather tha
|
||||||
### Explicit non-goals for the first release
|
### Explicit non-goals for the first release
|
||||||
|
|
||||||
Do not initially implement:
|
Do not initially implement:
|
||||||
|
|
||||||
- video, notation, collaboration, cloud accounts, or online services;
|
- video, notation, collaboration, cloud accounts, or online services;
|
||||||
- an integrated marketplace;
|
- an integrated marketplace;
|
||||||
- scripting as a requirement for basic operation;
|
- scripting as a requirement for basic operation;
|
||||||
|
|
@ -86,11 +120,12 @@ Do not initially implement:
|
||||||
- automatic online update services;
|
- automatic online update services;
|
||||||
- a proprietary project format that cannot be inspected or migrated.
|
- a proprietary project format that cannot be inspected or migrated.
|
||||||
|
|
||||||
These may be considered later, but they must not delay the first reliable recording and playback workflow.
|
These may be considered later, but they must not delay the first reliable
|
||||||
|
recording and playback workflow.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3. High-level architecture
|
## 3. High-Level Architecture
|
||||||
|
|
||||||
Use distinct layers with narrow interfaces.
|
Use distinct layers with narrow interfaces.
|
||||||
|
|
||||||
|
|
@ -125,7 +160,9 @@ Use distinct layers with narrow interfaces.
|
||||||
+------------------------------------------------------------+
|
+------------------------------------------------------------+
|
||||||
```
|
```
|
||||||
|
|
||||||
The C core and audio engine may be separate libraries or clearly separated modules within one C library. Keep their interfaces explicit even if they initially compile into one library.
|
The C core and audio engine may be separate libraries or clearly separated
|
||||||
|
modules within one C library. Keep their interfaces explicit even if they
|
||||||
|
initially compile into one library.
|
||||||
|
|
||||||
### Suggested repository layout
|
### Suggested repository layout
|
||||||
|
|
||||||
|
|
@ -179,13 +216,14 @@ xtc/
|
||||||
└── build/ # generated; do not commit
|
└── build/ # generated; do not commit
|
||||||
```
|
```
|
||||||
|
|
||||||
Keep C and C++ files clearly separated. C headers exposed to C++ must use `extern "C"` guards.
|
Keep C and C++ files clearly separated. C headers exposed to C++ must use
|
||||||
|
`extern "C"` guards.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 4. Language and API boundary
|
## 4. Language and API Boundary
|
||||||
|
|
||||||
### C code owns
|
### C Code owns
|
||||||
|
|
||||||
- project and track data;
|
- project and track data;
|
||||||
- graph nodes, ports, and connections;
|
- graph nodes, ports, and connections;
|
||||||
|
|
@ -198,7 +236,7 @@ Keep C and C++ files clearly separated. C headers exposed to C++ must use `exter
|
||||||
- backend-independent engine state;
|
- backend-independent engine state;
|
||||||
- error codes and diagnostic messages.
|
- error codes and diagnostic messages.
|
||||||
|
|
||||||
### C++/FLTK code owns
|
### C++/FLTK Code owns
|
||||||
|
|
||||||
- windows and widgets;
|
- windows and widgets;
|
||||||
- layout and drawing;
|
- layout and drawing;
|
||||||
|
|
@ -211,15 +249,19 @@ Keep C and C++ files clearly separated. C headers exposed to C++ must use `exter
|
||||||
### Boundary rules
|
### Boundary rules
|
||||||
|
|
||||||
- Public C headers must compile from both C and C++.
|
- Public C headers must compile from both C and C++.
|
||||||
- Do not expose C++ classes, STL containers, exceptions, or FLTK types through the C API.
|
- Do not expose C++ classes, STL containers, exceptions, or FLTK types through
|
||||||
|
the C API.
|
||||||
- Prefer opaque handles for objects whose internal layout must remain private.
|
- Prefer opaque handles for objects whose internal layout must remain private.
|
||||||
- Use explicit integer error codes and documented output parameters.
|
- Use explicit integer error codes and documented output parameters.
|
||||||
- Define ownership for every pointer: borrowed, caller-owned, or transferred.
|
- Define ownership for every pointer: borrowed, caller-owned, or transferred.
|
||||||
- Do not return pointers into mutable engine memory unless their lifetime is guaranteed.
|
- Do not return pointers into mutable engine memory unless their lifetime is
|
||||||
|
guaranteed.
|
||||||
- Do not let GUI widgets mutate internal engine structures directly.
|
- Do not let GUI widgets mutate internal engine structures directly.
|
||||||
- Avoid a public API that mirrors every internal struct field. Provide stable operations instead.
|
- Avoid a public API that mirrors every internal struct field. Provide stable
|
||||||
|
operations instead.
|
||||||
|
|
||||||
Example API shape (illustrative only; refine after reviewing the actual codebase):
|
Example API shape (illustrative only; refine after reviewing the actual
|
||||||
|
codebase):
|
||||||
|
|
||||||
```c
|
```c
|
||||||
#ifndef XTC_H
|
#ifndef XTC_H
|
||||||
|
|
@ -254,17 +296,21 @@ xtc_result xtc_transport_stop(xtc_app *app);
|
||||||
#endif
|
#endif
|
||||||
```
|
```
|
||||||
|
|
||||||
Do not implement this exact API blindly if the existing design calls for a better interface. Keep it small and consistent.
|
Do not implement this exact API blindly if the existing design calls for a
|
||||||
|
better interface. Keep it small and consistent.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 5. Modular processing graph — primary design decision
|
## 5. Modular Processing Graph — Primary Design Decision
|
||||||
|
|
||||||
**Decision B: Modular engine first.** The graph is the common representation of signal processing and routing. The sequencer is a source of time-based events and clips, not a separate audio system disconnected from the graph.
|
**Decision B: Modular engine first.** The graph is the common representation of
|
||||||
|
signal processing and routing. The sequencer is a source of time-based events
|
||||||
|
and clips, not a separate audio system disconnected from the graph.
|
||||||
|
|
||||||
### Node categories
|
### Node categories
|
||||||
|
|
||||||
Start with a small set:
|
Start with a small set:
|
||||||
|
|
||||||
- audio input;
|
- audio input;
|
||||||
- audio output;
|
- audio output;
|
||||||
- audio clip player;
|
- audio clip player;
|
||||||
|
|
@ -277,11 +323,13 @@ Start with a small set:
|
||||||
- metering/analyzer;
|
- metering/analyzer;
|
||||||
- utility nodes such as channel mapping.
|
- utility nodes such as channel mapping.
|
||||||
|
|
||||||
Do not build every node at once. First prove the graph with a test tone, gain node, and output node.
|
Do not build every node at once. First prove the graph with a test tone, gain
|
||||||
|
node, and output node.
|
||||||
|
|
||||||
### Ports and connections
|
### Ports and connections
|
||||||
|
|
||||||
Each node has a stable identifier, a node type, and declared ports. A port has:
|
Each node has a stable identifier, a node type, and declared ports. A port has:
|
||||||
|
|
||||||
- a unique identifier within its node;
|
- a unique identifier within its node;
|
||||||
- a direction (input or output);
|
- a direction (input or output);
|
||||||
- a signal/data type (audio, MIDI/event, or control);
|
- a signal/data type (audio, MIDI/event, or control);
|
||||||
|
|
@ -289,6 +337,7 @@ Each node has a stable identifier, a node type, and declared ports. A port has:
|
||||||
- a documented sample/block processing contract.
|
- a documented sample/block processing contract.
|
||||||
|
|
||||||
Validate connections before accepting them:
|
Validate connections before accepting them:
|
||||||
|
|
||||||
- source and destination exist;
|
- source and destination exist;
|
||||||
- source port is an output and destination is an input;
|
- source port is an output and destination is an input;
|
||||||
- signal types are compatible;
|
- signal types are compatible;
|
||||||
|
|
@ -298,13 +347,18 @@ Validate connections before accepting them:
|
||||||
|
|
||||||
### Cycles and feedback
|
### Cycles and feedback
|
||||||
|
|
||||||
For the first working engine, reject cycles in the audio-processing graph. A directed acyclic graph is easier to schedule safely and predictably. Report a useful error to the user. Do not silently break a cycle.
|
For the first working engine, reject cycles in the audio-processing graph. A
|
||||||
|
directed acyclic graph is easier to schedule safely and predictably. Report a
|
||||||
|
useful error to the user. Do not silently break a cycle.
|
||||||
|
|
||||||
Feedback support can be considered later using explicit delay/feedback nodes and a defined block-boundary model. Never introduce arbitrary graph cycles without a correct scheduling design.
|
Feedback support can be considered later using explicit delay/feedback nodes and
|
||||||
|
a defined block-boundary model. Never introduce arbitrary graph cycles without a
|
||||||
|
correct scheduling design.
|
||||||
|
|
||||||
### Graph compilation
|
### Graph compilation
|
||||||
|
|
||||||
Compile the editable graph into an execution plan outside the real-time thread:
|
Compile the editable graph into an execution plan outside the real-time thread:
|
||||||
|
|
||||||
1. validate nodes, ports, and edges;
|
1. validate nodes, ports, and edges;
|
||||||
2. identify source nodes and reachable output nodes;
|
2. identify source nodes and reachable output nodes;
|
||||||
3. detect cycles;
|
3. detect cycles;
|
||||||
|
|
@ -313,21 +367,31 @@ Compile the editable graph into an execution plan outside the real-time thread:
|
||||||
6. allocate buffers and prepare node state;
|
6. allocate buffers and prepare node state;
|
||||||
7. publish an immutable, ready-to-run plan.
|
7. publish an immutable, ready-to-run plan.
|
||||||
|
|
||||||
The audio callback processes the prepared plan. It must not perform graph discovery, sorting, dynamic allocation, file loading, or plugin creation.
|
The audio callback processes the prepared plan. It must not perform graph
|
||||||
|
discovery, sorting, dynamic allocation, file loading, or plugin creation.
|
||||||
|
|
||||||
### Graph replacement during playback
|
### Graph replacement during playback
|
||||||
|
|
||||||
The editor must not modify the graph currently being traversed by the audio thread. Prepare a new plan off-thread and publish it through a bounded real-time-safe mechanism. Define how the old plan is retired only after the audio thread can no longer access it. Do not use a naive pointer swap followed by immediate free.
|
The editor must not modify the graph currently being traversed by the audio
|
||||||
|
thread. Prepare a new plan off-thread and publish it through a bounded
|
||||||
|
real-time-safe mechanism. Define how the old plan is retired only after the
|
||||||
|
audio thread can no longer access it. Do not use a naive pointer swap followed
|
||||||
|
by immediate free.
|
||||||
|
|
||||||
Possible approaches include a carefully designed single-producer/single-consumer handoff, epochs, or another proven reclamation scheme. Choose one, document it, and test it under stress. Keep the initial design as simple as safety allows.
|
Possible approaches include a carefully designed single-producer/single-consumer
|
||||||
|
handoff, epochs, or another proven reclamation scheme. Choose one, document it,
|
||||||
|
and test it under stress. Keep the initial design as simple as safety allows.
|
||||||
|
|
||||||
### Sequencer integration
|
### Sequencer integration
|
||||||
|
|
||||||
The sequencer stores timeline content and emits events to the graph at the correct sample positions. A clip player or instrument node consumes those events. The GUI timeline is a view/editor for project data; it is not the audio scheduler.
|
The sequencer stores timeline content and emits events to the graph at the
|
||||||
|
correct sample positions. A clip player or instrument node consumes those
|
||||||
|
events. The GUI timeline is a view/editor for project data; it is not the audio
|
||||||
|
scheduler.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 6. Real-time audio requirements
|
## 6. Real-Time Audio Requirements
|
||||||
|
|
||||||
These rules are mandatory.
|
These rules are mandatory.
|
||||||
|
|
||||||
|
|
@ -354,54 +418,75 @@ These rules are mandatory.
|
||||||
- process silence safely when a source is unavailable;
|
- process silence safely when a source is unavailable;
|
||||||
- handle backend buffer sizes and channel counts within documented limits.
|
- handle backend buffer sizes and channel counts within documented limits.
|
||||||
|
|
||||||
Do not assume all backends use a fixed block size unless the backend contract guarantees it. Establish maximum supported frame/event counts and define what happens when limits are exceeded.
|
Do not assume all backends use a fixed block size unless the backend contract
|
||||||
|
guarantees it. Establish maximum supported frame/event counts and define what
|
||||||
|
happens when limits are exceeded.
|
||||||
|
|
||||||
### Thread ownership
|
### Thread ownership
|
||||||
|
|
||||||
Document which thread owns each mutable resource:
|
Document which thread owns each mutable resource:
|
||||||
|
|
||||||
- GUI thread: widgets and GUI state;
|
- GUI thread: widgets and GUI state;
|
||||||
- control/project thread: editable project state, file operations, graph compilation;
|
- control/project thread: editable project state, file operations, graph
|
||||||
|
compilation;
|
||||||
- audio thread: active processing plan and real-time DSP state;
|
- audio thread: active processing plan and real-time DSP state;
|
||||||
- backend callbacks: follow the backend's documented threading model.
|
- backend callbacks: follow the backend's documented threading model.
|
||||||
|
|
||||||
Avoid sharing mutable structs across threads without an explicit synchronization strategy. Atomics are not automatically safe for every use: verify that the selected atomic operations are lock-free where required and use correct memory ordering.
|
Avoid sharing mutable structs across threads without an explicit synchronization
|
||||||
|
strategy. Atomics are not automatically safe for every use: verify that the
|
||||||
|
selected atomic operations are lock-free where required and use correct memory
|
||||||
|
ordering.
|
||||||
|
|
||||||
### Timing
|
### Timing
|
||||||
|
|
||||||
Use audio sample position as the authoritative playback clock. Represent timeline positions with an integer or rational scheme that avoids accumulated floating-point drift. Convert musical time (bars/beats/ticks) to sample positions using tempo and meter maps. Define behavior at tempo changes before implementing advanced tempo automation.
|
Use audio sample position as the authoritative playback clock. Represent
|
||||||
|
timeline positions with an integer or rational scheme that avoids accumulated
|
||||||
|
floating-point drift. Convert musical time (bars/beats/ticks) to sample
|
||||||
|
positions using tempo and meter maps. Define behavior at tempo changes before
|
||||||
|
implementing advanced tempo automation.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 7. Audio backend strategy
|
## 7. Audio Backend Strategy
|
||||||
|
|
||||||
Start on Linux and keep the backend replaceable.
|
Start on Linux and keep the backend replaceable.
|
||||||
|
|
||||||
1. Define a small backend interface in C.
|
1. Define a small backend interface in C.
|
||||||
2. Implement one backend first, selected after checking the target system and installed development packages. JACK-compatible audio is a reasonable first target on Linux.
|
2. Implement one backend first, selected after checking the target system and
|
||||||
3. Test device enumeration, start/stop, sample rate, buffer size, channel count, disconnects, and shutdown.
|
installed development packages. JACK-compatible audio is a reasonable first
|
||||||
|
target on Linux.
|
||||||
|
3. Test device enumeration, start/stop, sample rate, buffer size, channel count,
|
||||||
|
disconnects, and shutdown.
|
||||||
4. Keep backend-specific headers out of the public API.
|
4. Keep backend-specific headers out of the public API.
|
||||||
5. Add another backend only after the engine works and tests pass.
|
5. Add another backend only after the engine works and tests pass.
|
||||||
|
|
||||||
Do not assume PipeWire-native, JACK compatibility, ALSA PCM, and desktop audio routing are interchangeable. Document the chosen backend's setup and limitations.
|
Do not assume PipeWire-native, JACK compatibility, ALSA PCM, and desktop audio
|
||||||
|
routing are interchangeable. Document the chosen backend's setup and
|
||||||
|
limitations.
|
||||||
|
|
||||||
The engine should also have an offline/test mode that processes buffers without physical audio hardware. This makes unit and integration testing repeatable.
|
The engine should also have an offline/test mode that processes buffers without
|
||||||
|
physical audio hardware. This makes unit and integration testing repeatable.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 8. MIDI, parameters, automation, and DSP
|
## 8. MIDI, Parameters, Automation, and DSP
|
||||||
|
|
||||||
### MIDI/events
|
### MIDI/Events
|
||||||
|
|
||||||
- Use a compact, well-defined event representation.
|
- Use a compact, well-defined event representation.
|
||||||
- Store event time relative to a project timeline and convert it to sample offsets for a processing block.
|
- Store event time relative to a project timeline and convert it to sample
|
||||||
|
offsets for a processing block.
|
||||||
- Validate event sizes and event counts.
|
- Validate event sizes and event counts.
|
||||||
- Handle note-on, note-off, velocity, channel, controller, pitch bend, and tempo/transport events as needed.
|
- Handle note-on, note-off, velocity, channel, controller, pitch bend, and
|
||||||
- Ensure all held notes can be released on stop, panic, seek, device loss, or project teardown.
|
tempo/transport events as needed.
|
||||||
|
- Ensure all held notes can be released on stop, panic, seek, device loss, or
|
||||||
|
project teardown.
|
||||||
- Avoid unbounded event queues.
|
- Avoid unbounded event queues.
|
||||||
|
|
||||||
### Parameters
|
### Parameters
|
||||||
|
|
||||||
Every automatable control should have:
|
Every automatable control should have:
|
||||||
|
|
||||||
- a stable parameter ID;
|
- a stable parameter ID;
|
||||||
- a type and valid range;
|
- a type and valid range;
|
||||||
- a default value;
|
- a default value;
|
||||||
|
|
@ -409,85 +494,115 @@ Every automatable control should have:
|
||||||
- a safe update mechanism;
|
- a safe update mechanism;
|
||||||
- optional automation and MIDI mapping.
|
- optional automation and MIDI mapping.
|
||||||
|
|
||||||
Do not silently clamp invalid serialized values. Validate project data and return an error or apply a clearly documented migration rule. UI controls may constrain user input, but core validation must remain authoritative.
|
Do not silently clamp invalid serialized values. Validate project data and
|
||||||
|
return an error or apply a clearly documented migration rule. UI controls may
|
||||||
|
constrain user input, but core validation must remain authoritative.
|
||||||
|
|
||||||
### Automation
|
### Automation
|
||||||
|
|
||||||
Implement automation only after transport, graph processing, and basic parameter updates work. Define interpolation types explicitly (initially step and linear are enough). Automation evaluation must be deterministic and bounded.
|
Implement automation only after transport, graph processing, and basic parameter
|
||||||
|
updates work. Define interpolation types explicitly (initially step and linear
|
||||||
|
are enough). Automation evaluation must be deterministic and bounded.
|
||||||
|
|
||||||
### DSP
|
### DSP
|
||||||
|
|
||||||
Start with a few well-tested processors:
|
Start with a few well-tested processors:
|
||||||
|
|
||||||
- gain;
|
- gain;
|
||||||
- pan;
|
- pan;
|
||||||
- simple meter/peak detector;
|
- simple meter/peak detector;
|
||||||
- test oscillator;
|
- test oscillator;
|
||||||
- basic delay only after buffer/lifetime handling is sound.
|
- basic delay only after buffer/lifetime handling is sound.
|
||||||
|
|
||||||
Keep DSP algorithms in C and independently testable. Use appropriate numerical safeguards, including finite-value checks where needed. Avoid premature SIMD optimization until profiling shows a real bottleneck.
|
Keep DSP algorithms in C and independently testable. Use appropriate numerical
|
||||||
|
safeguards, including finite-value checks where needed. Avoid premature SIMD
|
||||||
|
optimization until profiling shows a real bottleneck.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 9. FLTK/C++ GUI guidelines
|
## 9. FLTK/C++ GUI Guidelines
|
||||||
|
|
||||||
The GUI is a thin client of the C API, not the owner of the engine.
|
The GUI is a thin client of the C API, not the owner of the engine.
|
||||||
|
|
||||||
### Main views
|
### Main views
|
||||||
|
|
||||||
1. **Sequencer:** tracks, audio/MIDI clips, timeline ruler, playhead, selection, zoom and horizontal scrolling.
|
1. **Sequencer:** tracks, audio/MIDI clips, timeline ruler, playhead, selection,
|
||||||
2. **Mixer:** channels, faders, pan, mute/solo, inserts/sends when supported, and meters.
|
zoom and horizontal scrolling.
|
||||||
3. **Modular graph:** nodes, ports, connections, zoom/pan, selection, and connection validation feedback.
|
2. **Mixer:** channels, faders, pan, mute/solo, inserts/sends when supported,
|
||||||
4. **Transport:** play, stop, record, tempo, meter, loop range, and current position.
|
and meters.
|
||||||
5. **Project/file dialogs:** create, open, save, import audio, and manage missing assets.
|
3. **Modular graph:** nodes, ports, connections, zoom/pan, selection, and
|
||||||
|
connection validation feedback.
|
||||||
|
4. **Transport:** play, stop, record, tempo, meter, loop range, and current
|
||||||
|
position.
|
||||||
|
5. **Project/file dialogs:** create, open, save, import audio, and manage
|
||||||
|
missing assets.
|
||||||
|
|
||||||
The default workspace should emphasize the sequencer and transport. The graph view is an advanced but first-class view of the same underlying project.
|
The default workspace should emphasize the sequencer and transport. The graph
|
||||||
|
view is an advanced but first-class view of the same underlying project.
|
||||||
|
|
||||||
### GUI implementation
|
### GUI Implementation
|
||||||
|
|
||||||
- Use FLTK for conventional widgets and application windows.
|
- Use FLTK for conventional widgets and application windows.
|
||||||
- Use custom-drawn widgets for the timeline, piano roll, mixer strips, waveform display, and graph canvas where needed.
|
- Use custom-drawn widgets for the timeline, piano roll, mixer strips, waveform
|
||||||
|
display, and graph canvas where needed.
|
||||||
- Keep drawing code separate from project mutation.
|
- Keep drawing code separate from project mutation.
|
||||||
- Use GUI timers or the toolkit's appropriate event mechanism for refreshing meters; never poll from the audio callback or block the GUI waiting for audio.
|
- Use GUI timers or the toolkit's appropriate event mechanism for refreshing
|
||||||
|
meters; never poll from the audio callback or block the GUI waiting for audio.
|
||||||
- Avoid redrawing the entire application when only a small region changes.
|
- Avoid redrawing the entire application when only a small region changes.
|
||||||
- Support keyboard shortcuts and predictable focus behavior.
|
- Support keyboard shortcuts and predictable focus behavior.
|
||||||
- Make selection, dragging, snapping, zooming, and scrolling consistent across editors.
|
- Make selection, dragging, snapping, zooming, and scrolling consistent across
|
||||||
|
editors.
|
||||||
- Never call FLTK APIs from the audio thread.
|
- Never call FLTK APIs from the audio thread.
|
||||||
- Do not hold GUI locks while calling potentially blocking engine operations.
|
- Do not hold GUI locks while calling potentially blocking engine operations.
|
||||||
- Keep C++ simple: use RAII for GUI resources, clear ownership, and small classes. Do not force the C core into C++ abstractions.
|
- Keep C++ simple: use RAII for GUI resources, clear ownership, and small
|
||||||
|
classes. Do not force the C core into C++ abstractions.
|
||||||
|
|
||||||
### Visual direction
|
### Visual direction
|
||||||
|
|
||||||
Aim for a compact, dark, high-contrast interface with restrained decoration. Prioritize legible waveforms, clip boundaries, transport state, and meter levels. Avoid excessive gradients, animations, nested panels, and modal configuration windows.
|
Aim for a compact, dark, high-contrast interface with restrained decoration.
|
||||||
|
Prioritize legible waveforms, clip boundaries, transport state, and meter
|
||||||
|
levels. Avoid excessive gradients, animations, nested panels, and modal
|
||||||
|
configuration windows.
|
||||||
|
|
||||||
Do not copy energyXT's artwork, exact visual assets, or proprietary UI resources. Recreate the general principles of compactness, direct manipulation, and modular routing in an original design.
|
Do not copy energyXT's artwork, exact visual assets, or proprietary UI
|
||||||
|
resources. Recreate the general principles of compactness, direct manipulation,
|
||||||
|
and modular routing in an original design.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 10. Project format and persistence
|
## 10. Project Format and Persistence
|
||||||
|
|
||||||
The project format must be versioned from its first release.
|
The project format must be versioned from its first release.
|
||||||
|
|
||||||
### Requirements
|
### Requirements
|
||||||
|
|
||||||
- Include a format version and application version.
|
- Include a format version and application version.
|
||||||
- Store stable IDs for tracks, nodes, ports where necessary, clips, parameters, and connections.
|
- Store stable IDs for tracks, nodes, ports where necessary, clips, parameters,
|
||||||
|
and connections.
|
||||||
- Save relative asset paths when possible.
|
- Save relative asset paths when possible.
|
||||||
- Define behavior for missing audio files.
|
- Define behavior for missing audio files.
|
||||||
- Validate every field before allocating large amounts of memory.
|
- Validate every field before allocating large amounts of memory.
|
||||||
- Handle truncated, malformed, unsupported, or corrupted files gracefully.
|
- Handle truncated, malformed, unsupported, or corrupted files gracefully.
|
||||||
- Never execute code while loading a project.
|
- Never execute code while loading a project.
|
||||||
- Save atomically: write a temporary file, flush as appropriate, and rename it into place when safe.
|
- Save atomically: write a temporary file, flush as appropriate, and rename it
|
||||||
- Preserve unknown optional fields when practical, or explicitly document when they are discarded.
|
into place when safe.
|
||||||
|
- Preserve unknown optional fields when practical, or explicitly document when
|
||||||
|
they are discarded.
|
||||||
- Include migration functions when the format changes.
|
- Include migration functions when the format changes.
|
||||||
- Keep project serialization outside the real-time thread.
|
- Keep project serialization outside the real-time thread.
|
||||||
|
|
||||||
Choose a simple, well-supported format after considering the dependency and robustness trade-offs. A small, documented text format can help inspect projects, but large binary audio data should generally live in separate assets rather than be embedded in a text document. Do not add a serialization dependency without a clear reason.
|
Choose a simple, well-supported format after considering the dependency and
|
||||||
|
robustness trade-offs. A small, documented text format can help inspect
|
||||||
|
projects, but large binary audio data should generally live in separate assets
|
||||||
|
rather than be embedded in a text document. Do not add a serialization
|
||||||
|
dependency without a clear reason.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 11. Undo/redo and editing commands
|
## 11. Undo/Redo and Editing Commands
|
||||||
|
|
||||||
Use explicit commands for user-visible edits, such as:
|
Use explicit commands for user-visible edits, such as:
|
||||||
|
|
||||||
- create/delete/move/resize clip;
|
- create/delete/move/resize clip;
|
||||||
- create/delete/rename track;
|
- create/delete/rename track;
|
||||||
- change parameter;
|
- change parameter;
|
||||||
|
|
@ -495,21 +610,28 @@ Use explicit commands for user-visible edits, such as:
|
||||||
- connect/disconnect ports;
|
- connect/disconnect ports;
|
||||||
- change tempo or meter.
|
- change tempo or meter.
|
||||||
|
|
||||||
A command should validate its inputs and have a well-defined inverse or stored previous state. Avoid designing a generic event-sourcing framework before it is needed.
|
A command should validate its inputs and have a well-defined inverse or stored
|
||||||
|
previous state. Avoid designing a generic event-sourcing framework before it is
|
||||||
|
needed.
|
||||||
|
|
||||||
The initial implementation may begin without a complete undo stack, but design edit operations so undo/redo can be added without rewriting all editors. Never make an edit partially visible if it fails validation.
|
The initial implementation may begin without a complete undo stack, but design
|
||||||
|
edit operations so undo/redo can be added without rewriting all editors. Never
|
||||||
|
make an edit partially visible if it fails validation.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 12. Build, coding standards, and dependencies
|
## 12. Build, Coding Standards, and Dependencies
|
||||||
|
|
||||||
### Build system
|
### Build system
|
||||||
|
|
||||||
Use a straightforward Makefile unless the existing repository has a sound reason to use another build system.
|
Use a straightforward Makefile unless the existing repository has a sound reason
|
||||||
|
to use another build system.
|
||||||
|
|
||||||
The build must:
|
The build must:
|
||||||
|
|
||||||
- compile C with the selected C standard and warnings enabled;
|
- compile C with the selected C standard and warnings enabled;
|
||||||
- compile C++ GUI sources with the standard supported by the chosen FLTK version;
|
- compile C++ GUI sources with the standard supported by the chosen FLTK
|
||||||
|
version;
|
||||||
- link the GUI with FLTK and the C core;
|
- link the GUI with FLTK and the C core;
|
||||||
- link the required audio backend;
|
- link the required audio backend;
|
||||||
- provide `all`, `clean`, `test`, and a debug build target;
|
- provide `all`, `clean`, `test`, and a debug build target;
|
||||||
|
|
@ -517,9 +639,11 @@ The build must:
|
||||||
- avoid embedding machine-specific paths;
|
- avoid embedding machine-specific paths;
|
||||||
- separate generated objects and binaries into a build directory.
|
- separate generated objects and binaries into a build directory.
|
||||||
|
|
||||||
Use `pkg-config` where supported by the installed dependencies. Check actual package names on the target distribution rather than hard-coding unverified names.
|
Use `pkg-config` where supported by the installed dependencies. Check actual
|
||||||
|
package names on the target distribution rather than hard-coding unverified
|
||||||
|
names.
|
||||||
|
|
||||||
### C style
|
### C Style
|
||||||
|
|
||||||
- Use C99 initially.
|
- Use C99 initially.
|
||||||
- Use `snake_case`.
|
- Use `snake_case`.
|
||||||
|
|
@ -532,7 +656,7 @@ Use `pkg-config` where supported by the installed dependencies. Check actual pac
|
||||||
- Use `const` where appropriate.
|
- Use `const` where appropriate.
|
||||||
- Do not suppress warnings merely to get a clean build.
|
- Do not suppress warnings merely to get a clean build.
|
||||||
|
|
||||||
### C++ GUI style
|
### C++ GUI Style
|
||||||
|
|
||||||
- Keep C++ confined to the GUI and any unavoidable C++-only third-party wrapper.
|
- Keep C++ confined to the GUI and any unavoidable C++-only third-party wrapper.
|
||||||
- Prefer small classes with explicit ownership.
|
- Prefer small classes with explicit ownership.
|
||||||
|
|
@ -544,21 +668,26 @@ Use `pkg-config` where supported by the installed dependencies. Check actual pac
|
||||||
### Dependencies
|
### Dependencies
|
||||||
|
|
||||||
Before adding a dependency:
|
Before adding a dependency:
|
||||||
|
|
||||||
1. identify the exact feature it provides;
|
1. identify the exact feature it provides;
|
||||||
2. check license and maintenance status;
|
2. check license and maintenance status;
|
||||||
3. determine whether the existing code can provide the functionality simply and safely;
|
3. determine whether the existing code can provide the functionality simply and
|
||||||
|
safely;
|
||||||
4. document the dependency and its version constraints;
|
4. document the dependency and its version constraints;
|
||||||
5. keep it optional if the feature is optional.
|
5. keep it optional if the feature is optional.
|
||||||
|
|
||||||
Prefer open-source dependencies with clear licensing. Do not claim the whole application is license-compatible until all direct and bundled dependencies have been reviewed.
|
Prefer open-source dependencies with clear licensing. Do not claim the whole
|
||||||
|
application is license-compatible until all direct and bundled dependencies have
|
||||||
|
been reviewed.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 13. Testing and diagnostics
|
## 13. Testing and Diagnostics
|
||||||
|
|
||||||
### Unit tests
|
### Unit tests
|
||||||
|
|
||||||
Test at least:
|
Test at least:
|
||||||
|
|
||||||
- graph validation and topological sorting;
|
- graph validation and topological sorting;
|
||||||
- invalid ports and incompatible connections;
|
- invalid ports and incompatible connections;
|
||||||
- cycle detection;
|
- cycle detection;
|
||||||
|
|
@ -573,6 +702,7 @@ Test at least:
|
||||||
### Integration tests
|
### Integration tests
|
||||||
|
|
||||||
Test:
|
Test:
|
||||||
|
|
||||||
- test oscillator → gain → output processing;
|
- test oscillator → gain → output processing;
|
||||||
- offline rendering with deterministic output;
|
- offline rendering with deterministic output;
|
||||||
- graph replacement during active processing;
|
- graph replacement during active processing;
|
||||||
|
|
@ -585,6 +715,7 @@ Test:
|
||||||
### Tools
|
### Tools
|
||||||
|
|
||||||
Where available, use:
|
Where available, use:
|
||||||
|
|
||||||
- compiler warnings;
|
- compiler warnings;
|
||||||
- AddressSanitizer and UndefinedBehaviorSanitizer in non-real-time test builds;
|
- AddressSanitizer and UndefinedBehaviorSanitizer in non-real-time test builds;
|
||||||
- static analysis;
|
- static analysis;
|
||||||
|
|
@ -592,25 +723,29 @@ Where available, use:
|
||||||
- stress tests for graph edits and shutdown;
|
- stress tests for graph edits and shutdown;
|
||||||
- audio loopback or offline render comparisons.
|
- audio loopback or offline render comparisons.
|
||||||
|
|
||||||
Sanitizers and diagnostic logging should not be enabled in production real-time callbacks unless their real-time implications have been specifically evaluated.
|
Sanitizers and diagnostic logging should not be enabled in production real-time
|
||||||
|
callbacks unless their real-time implications have been specifically evaluated.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 14. Development roadmap and acceptance criteria
|
## 14. Development Roadmap and Acceptance Criteria
|
||||||
|
|
||||||
Implement these milestones in order. Do not jump ahead merely because a later feature is exciting.
|
Implement these milestones in order. Do not jump ahead merely because a later
|
||||||
|
feature is exciting.
|
||||||
|
|
||||||
### Repository and design baseline
|
### Repository and design baseline
|
||||||
|
|
||||||
- Inspect the repository and available toolchain.
|
- Inspect the repository and available toolchain.
|
||||||
- Create or update architecture documentation and the Makefile.
|
- Create or update architecture documentation and the Makefile.
|
||||||
- Verify C compiler, C++ compiler, FLTK, audio development headers, and test tools.
|
- Verify C compiler, C++ compiler, FLTK, audio development headers, and test
|
||||||
|
tools.
|
||||||
- Record dependency and licensing decisions.
|
- Record dependency and licensing decisions.
|
||||||
- Add a minimal application that starts and exits cleanly.
|
- Add a minimal application that starts and exits cleanly.
|
||||||
|
|
||||||
**Acceptance:** clean build on the target Linux environment; no audio engine assumptions hidden in GUI code.
|
**Acceptance:** clean build on the target Linux environment; no audio engine
|
||||||
|
assumptions hidden in GUI code.
|
||||||
|
|
||||||
### C core and offline processing
|
### C Core and offline processing
|
||||||
|
|
||||||
- Create the C library/API.
|
- Create the C library/API.
|
||||||
- Define node, port, connection, and graph data structures.
|
- Define node, port, connection, and graph data structures.
|
||||||
|
|
@ -619,7 +754,8 @@ Implement these milestones in order. Do not jump ahead merely because a later fe
|
||||||
- Add oscillator, gain, meter, and output test nodes.
|
- Add oscillator, gain, meter, and output test nodes.
|
||||||
- Implement deterministic offline block processing.
|
- Implement deterministic offline block processing.
|
||||||
|
|
||||||
**Acceptance:** automated test proves oscillator → gain → meter/output produces expected samples without hardware.
|
**Acceptance:** automated test proves oscillator → gain → meter/output produces
|
||||||
|
expected samples without hardware.
|
||||||
|
|
||||||
### Real-time backend
|
### Real-time backend
|
||||||
|
|
||||||
|
|
@ -629,16 +765,18 @@ Implement these milestones in order. Do not jump ahead merely because a later fe
|
||||||
- Add safe control-to-audio communication.
|
- Add safe control-to-audio communication.
|
||||||
- Stress-test shutdown and graph replacement.
|
- Stress-test shutdown and graph replacement.
|
||||||
|
|
||||||
**Acceptance:** stable playback for a sustained test; no known callback allocations or blocking calls; failures are reported clearly.
|
**Acceptance:** stable playback for a sustained test; no known callback
|
||||||
|
allocations or blocking calls; failures are reported clearly.
|
||||||
|
|
||||||
### FLTK shell
|
### FLTK Shell
|
||||||
|
|
||||||
- Create main window, menus, transport, status area, and view switching.
|
- Create main window, menus, transport, status area, and view switching.
|
||||||
- Call the C API through the public header.
|
- Call the C API through the public header.
|
||||||
- Add an audio engine status indicator.
|
- Add an audio engine status indicator.
|
||||||
- Implement clean startup and shutdown.
|
- Implement clean startup and shutdown.
|
||||||
|
|
||||||
**Acceptance:** GUI can start/stop the engine, report backend errors, and close without leaks or hangs.
|
**Acceptance:** GUI can start/stop the engine, report backend errors, and close
|
||||||
|
without leaks or hangs.
|
||||||
|
|
||||||
### Modular graph editor
|
### Modular graph editor
|
||||||
|
|
||||||
|
|
@ -648,16 +786,19 @@ Implement these milestones in order. Do not jump ahead merely because a later fe
|
||||||
- Display invalid connection feedback.
|
- Display invalid connection feedback.
|
||||||
- Submit graph edits through validated C API commands.
|
- Submit graph edits through validated C API commands.
|
||||||
|
|
||||||
**Acceptance:** graph shown by the GUI matches the graph used by the engine; invalid connections are rejected without corrupting active playback.
|
**Acceptance:** graph shown by the GUI matches the graph used by the engine;
|
||||||
|
invalid connections are rejected without corrupting active playback.
|
||||||
|
|
||||||
### Project and sequencer foundation
|
### Project and sequencer foundation
|
||||||
|
|
||||||
- Add project persistence and stable IDs.
|
- Add project persistence and stable IDs.
|
||||||
- Add tracks and clip objects.
|
- Add tracks and clip objects.
|
||||||
- Implement timeline rendering, selection, moving, trimming, zoom, and scrolling.
|
- Implement timeline rendering, selection, moving, trimming, zoom, and
|
||||||
|
scrolling.
|
||||||
- Add transport/sample-position synchronization.
|
- Add transport/sample-position synchronization.
|
||||||
|
|
||||||
**Acceptance:** save/load a project with clips and reproduce the same arrangement.
|
**Acceptance:** save/load a project with clips and reproduce the same
|
||||||
|
arrangement.
|
||||||
|
|
||||||
### Audio clips and recording
|
### Audio clips and recording
|
||||||
|
|
||||||
|
|
@ -666,16 +807,18 @@ Implement these milestones in order. Do not jump ahead merely because a later fe
|
||||||
- Keep file I/O outside the audio callback.
|
- Keep file I/O outside the audio callback.
|
||||||
- Add missing-asset reporting.
|
- Add missing-asset reporting.
|
||||||
|
|
||||||
**Acceptance:** record, save, reopen, and play a basic audio project without callback file I/O.
|
**Acceptance:** record, save, reopen, and play a basic audio project without
|
||||||
|
callback file I/O.
|
||||||
|
|
||||||
### MIDI and a simple instrument
|
### MIDI And a simple instrument
|
||||||
|
|
||||||
- Add MIDI input and clip events.
|
- Add MIDI input and clip events.
|
||||||
- Add a basic internal synthesizer or test instrument.
|
- Add a basic internal synthesizer or test instrument.
|
||||||
- Handle note-off, panic, seeking, and stop correctly.
|
- Handle note-off, panic, seeking, and stop correctly.
|
||||||
- Add a minimal piano-roll editor only after event scheduling works.
|
- Add a minimal piano-roll editor only after event scheduling works.
|
||||||
|
|
||||||
**Acceptance:** record or draw MIDI notes, play them in time, save the project, and reopen it.
|
**Acceptance:** record or draw MIDI notes, play them in time, save the project,
|
||||||
|
and reopen it.
|
||||||
|
|
||||||
### Mixer, automation, and editing polish
|
### Mixer, automation, and editing polish
|
||||||
|
|
||||||
|
|
@ -684,7 +827,8 @@ Implement these milestones in order. Do not jump ahead merely because a later fe
|
||||||
- Add a bounded undo/redo system for common edits.
|
- Add a bounded undo/redo system for common edits.
|
||||||
- Improve keyboard interaction and workflow.
|
- Improve keyboard interaction and workflow.
|
||||||
|
|
||||||
**Acceptance:** basic composition and mixing can be completed without editing project files manually.
|
**Acceptance:** basic composition and mixing can be completed without editing
|
||||||
|
project files manually.
|
||||||
|
|
||||||
### Extensibility and release preparation
|
### Extensibility and release preparation
|
||||||
|
|
||||||
|
|
@ -693,31 +837,40 @@ Implement these milestones in order. Do not jump ahead merely because a later fe
|
||||||
- Review project format migration, crash behavior, performance, and licensing.
|
- Review project format migration, crash behavior, performance, and licensing.
|
||||||
- Package the application and document Linux setup.
|
- Package the application and document Linux setup.
|
||||||
|
|
||||||
**Acceptance:** reproducible release build, tested install/uninstall, clear limitations, and complete user/developer documentation.
|
**Acceptance:** reproducible release build, tested install/uninstall, clear
|
||||||
|
limitations, and complete user/developer documentation.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 15. Initial implementation task for the agent
|
## 15. Initial Implementation Task for the Agent
|
||||||
|
|
||||||
Start with the **repository and design baseline** only.
|
Start with the **repository and design baseline** only.
|
||||||
|
|
||||||
1. Inspect the current repository and report its state.
|
1. Inspect the current repository and report its state.
|
||||||
2. Identify the available C/C++ compilers, FLTK version, audio backend development packages, `pkg-config`, and test tools.
|
2. Identify the available C/C++ compilers, FLTK version, audio backend
|
||||||
|
development packages, `pkg-config`, and test tools.
|
||||||
3. Do not install packages or modify system configuration without permission.
|
3. Do not install packages or modify system configuration without permission.
|
||||||
4. Propose the smallest initial source tree compatible with this brief.
|
4. Propose the smallest initial source tree compatible with this brief.
|
||||||
5. Add or update the Makefile and documentation only as needed.
|
5. Add or update the Makefile and documentation only as needed.
|
||||||
6. Create a minimal program that builds and exits cleanly; do not yet implement a full audio engine or GUI.
|
6. Create a minimal program that builds and exits cleanly; do not yet implement
|
||||||
|
a full audio engine or GUI.
|
||||||
7. Build it and run its tests.
|
7. Build it and run its tests.
|
||||||
8. Report exact commands, results, assumptions, and any missing dependencies.
|
8. Report exact commands, results, assumptions, and any missing dependencies.
|
||||||
|
|
||||||
After the baseline is reviewed, continue with the C core and offline processing. Keep each milestone independently buildable and testable.
|
After the baseline is reviewed, continue with the C core and offline processing.
|
||||||
|
Keep each milestone independently buildable and testable.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 16. Long-term quality bar
|
## 16. Long-Term Quality Bar
|
||||||
|
|
||||||
The project succeeds if a musician can open it quickly, connect components without fighting the interface, record and arrange audio/MIDI, and make music without needing to understand every detail of the engine.
|
The project succeeds if a musician can open it quickly, connect components
|
||||||
|
without fighting the interface, record and arrange audio/MIDI, and make music
|
||||||
|
without needing to understand every detail of the engine.
|
||||||
|
|
||||||
The implementation succeeds if a developer can read the C code, understand ownership and thread boundaries, test components independently, and add functionality without turning the application into an unmaintainable framework.
|
The implementation succeeds if a developer can read the C code, understand
|
||||||
|
ownership and thread boundaries, test components independently, and add
|
||||||
|
functionality without turning the application into an unmaintainable framework.
|
||||||
|
|
||||||
**Guiding rule:** build a small, coherent system whose components compose well. Do not build a large DAW and then attempt to simplify it afterward.
|
**Guiding rule:** build a small, coherent system whose components compose well.
|
||||||
|
Do not build a large DAW and then attempt to simplify it afterward.
|
||||||
|
|
|
||||||
|
|
@ -1,36 +1,42 @@
|
||||||
# Known limitations and qualification boundaries
|
# Known Limitations and Qualification Boundaries
|
||||||
|
|
||||||
- Development version 0.1.0, Linux C99/C++17/FLTK, optional JACK. Physical-device
|
- Development version 0.1.0, Linux C99/C++17/FLTK, optional JACK.
|
||||||
playback/capture, human transition listening, independent user acceptance and
|
Physical-device playback/capture, human transition listening, independent user
|
||||||
long-duration device qualification are pending.
|
acceptance and long-duration device qualification are pending.
|
||||||
- Fixed 4/4 and constant tempo snapshots; no tempo map, loop transport, plugin
|
- Fixed 4/4 and constant tempo snapshots; no tempo map, loop transport, plugin
|
||||||
latency compensation, limiter, background streaming or multichannel mixer buses.
|
latency compensation, limiter, background streaming or multichannel mixer
|
||||||
|
buses.
|
||||||
- Mono capture/import downmix; stereo track output. Graph ports are mono with
|
- Mono capture/import downmix; stereo track output. Graph ports are mono with
|
||||||
independent paired processing. Maximum 64 project graph nodes (256 standalone),
|
independent paired processing. Maximum 64 project graph nodes (256
|
||||||
64 tracks, 1024 clips/automation points, 4096 scheduled notes, 256 live MIDI
|
standalone), 64 tracks, 1024 clips/automation points, 4096 scheduled notes,
|
||||||
events/block, 32 voices, 65536 frames/block. See API headers for exact bounds.
|
256 live MIDI events/block, 32 voices, 65536 frames/block. See API headers for
|
||||||
|
exact bounds.
|
||||||
- WAV samples preload with the memory/format limits in AUDIO_FILES.md. Callback
|
- WAV samples preload with the memory/format limits in AUDIO_FILES.md. Callback
|
||||||
overflow reports/silences; there is no CPU preemption or expensive-plugin rescue.
|
overflow reports/silences; there is no CPU preemption or expensive-plugin
|
||||||
- Live MIDI configurable per-channel volume/pan/sustain CC mapping; no controller learn, capture, SMF
|
rescue.
|
||||||
import, pitch bend, custom-instrument chooser or instrument timbre controls.
|
- Live MIDI configurable per-channel volume/pan/sustain CC mapping; no
|
||||||
- Native ABI 1 graph nodes are session-only. ABI 2 state is parameter-only. LADSPA
|
controller learn, capture, SMF import, pitch bend, custom-instrument chooser
|
||||||
supports the documented mono amp/inverter/sine set; no opaque state, native
|
or instrument timbre controls.
|
||||||
editor, MIDI, true multichannel layout, latency compensation or crash isolation.
|
- Native ABI 1 graph nodes are session-only. ABI 2 state is parameter-only.
|
||||||
Automated LADSPA controls use run(1) and can be expensive.
|
LADSPA supports the documented mono amp/inverter/sine set; no opaque state,
|
||||||
|
native editor, MIDI, true multichannel layout, latency compensation or crash
|
||||||
|
isolation. Automated LADSPA controls use run(1) and can be expensive.
|
||||||
- GUI loading/compilation is synchronous on the control thread. Timeline grid/
|
- GUI loading/compilation is synchronous on the control thread. Timeline grid/
|
||||||
zoom/selection and graph positions are session UI state. Undo retains 32 edits
|
zoom/selection and graph positions are session UI state. Undo retains 32 edits
|
||||||
plus baseline and at most one reserved metadata snapshot; GUI edits reserve
|
plus baseline and at most one reserved metadata snapshot; GUI edits reserve
|
||||||
history before mutation/publication. Media is
|
history before mutation/publication. Media is never removed by undo/delete.
|
||||||
never removed by undo/delete. Broad screen-reader/accessibility testing is pending.
|
Broad screen-reader/accessibility testing is pending.
|
||||||
- Format v12 reads v1–v11 and uses relative local media references. External absolute
|
- Format v12 reads v1–v11 and uses relative local media references. External
|
||||||
media/module paths need manual repair after relocation. Saving does not bundle
|
absolute media/module paths need manual repair after relocation. Saving does
|
||||||
media; missing media stays referenced, missing plugins reject GUI installation.
|
not bundle media; missing media stays referenced, missing plugins reject GUI
|
||||||
Unknown data is rejected rather than stripped. Post-rename directory-sync errors
|
installation. Unknown data is rejected rather than stripped. Post-rename
|
||||||
can report failure even though the complete new document was published.
|
directory-sync errors can report failure even though the complete new document
|
||||||
- No autosave/session crash restoration, RF64, system service, automatic dependency
|
was published.
|
||||||
installation or public signed release. Source/binary archives are local artifacts;
|
- No autosave/session crash restoration, RF64, system service, automatic
|
||||||
binary packages require compatible system libraries. No third-party plugin or
|
dependency installation or public signed release. Source/binary archives are
|
||||||
dependency binary is bundled. Power-cut durability depends on the filesystem.
|
local artifacts; binary packages require compatible system libraries. No
|
||||||
|
third-party plugin or dependency binary is bundled. Power-cut durability
|
||||||
|
depends on the filesystem.
|
||||||
|
|
||||||
See ROADMAP.md, AUDIO_QUALITY.md, CONTROL.md, WORKFLOW.md, PROJECT_FORMAT.md,
|
See ROADMAP.md, AUDIO_QUALITY.md, CONTROL.md, WORKFLOW.md, PROJECT_FORMAT.md,
|
||||||
PERFORMANCE.md, PLUGIN_HOSTING.md and RECOVERY.md for tested contracts/evidence.
|
PERFORMANCE.md, PLUGIN_HOSTING.md and RECOVERY.md for tested contracts/evidence.
|
||||||
|
|
@ -46,43 +52,49 @@ PERFORMANCE.md, PLUGIN_HOSTING.md and RECOVERY.md for tested contracts/evidence.
|
||||||
|
|
||||||
- Stereo one-level mix buses share the 64-track limit. Nested buses, independent
|
- Stereo one-level mix buses share the 64-track limit. Nested buses, independent
|
||||||
bus plugin inserts, per-track aux sends and sidechains remain deferred. Track
|
bus plugin inserts, per-track aux sends and sidechains remain deferred. Track
|
||||||
meters are pre-bus; bus meters are pre-graph; master is post-graph. Sample peaks
|
meters are pre-bus; bus meters are pre-graph; master is post-graph. Sample
|
||||||
and sticky clipping do not provide loudness, true-peak analysis or limiting.
|
peaks and sticky clipping do not provide loudness, true-peak analysis or
|
||||||
|
limiting.
|
||||||
|
|
||||||
- Plugin discovery is an explicit-file descriptor browser, not a directory scan.
|
- Plugin discovery is an explicit-file descriptor browser, not a directory scan.
|
||||||
Generic parameter dialogs own copied metadata; no native plugin editors or
|
Generic parameter dialogs own copied metadata; no native plugin editors or
|
||||||
custom MIDI instrument chooser. LADSPA units are unspecified. Replacement
|
custom MIDI instrument chooser. LADSPA units are unspecified. Replacement
|
||||||
requires the same mono audio layout and resets controls/automation. Missing
|
requires the same mono audio layout and resets controls/automation. Missing
|
||||||
modules reject Open while retaining the current project; GUI module relink for
|
modules reject Open while retaining the current project; GUI module relink for
|
||||||
unopened documents is deferred. In-process plugin crashes/hangs are uncontained.
|
unopened documents is deferred. In-process plugin crashes/hangs are
|
||||||
|
uncontained.
|
||||||
|
|
||||||
- Common parameter targets cover track/bus gain/pan, LADSPA controls and metadata
|
- Common parameter targets cover track/bus gain/pan, LADSPA controls and
|
||||||
for live sine volume/pan/sustain. Live mappings do not drive arranged lanes,
|
metadata for live sine volume/pan/sustain. Live mappings do not drive arranged
|
||||||
faders or plugins. No automation capture, touch/latch/write modes or loop
|
lanes, faders or plugins. No automation capture, touch/latch/write modes or
|
||||||
transport. Backward jumps are deterministic for lanes, not opaque plugin tails.
|
loop transport. Backward jumps are deterministic for lanes, not opaque plugin
|
||||||
|
tails.
|
||||||
|
|
||||||
- Editing feedback remains synchronous; busy cursors are not background loading
|
- Editing feedback remains synchronous; busy cursors are not background loading
|
||||||
or cancellable progress. Surviving selections are retained across undo but
|
or cancellable progress. Surviving selections are retained across undo but
|
||||||
historical selection/layout is not stored. Native context-menu/focus manual
|
historical selection/layout is not stored. Native context-menu/focus manual
|
||||||
qualification and broad accessibility testing remain pending. See EDITING.md.
|
qualification and broad accessibility testing remain pending. See EDITING.md.
|
||||||
|
|
||||||
Project diagnostics use syntax-line locations; semantic cross-reference
|
Project diagnostics use syntax-line locations; semantic cross-reference failures
|
||||||
failures identify the MODEL stage without a source line. `xtc-check --inspect`
|
identify the MODEL stage without a source line. `xtc-check --inspect` checks
|
||||||
checks dependency file availability only, without loading code or WAV contents.
|
dependency file availability only, without loading code or WAV contents. The
|
||||||
The project format is Linux/POSIX oriented; absolute plugin paths, architecture,
|
project format is Linux/POSIX oriented; absolute plugin paths, architecture, ABI
|
||||||
ABI and JACK/device configuration must be supplied on another system. Unknown
|
and JACK/device configuration must be supplied on another system. Unknown fields
|
||||||
fields are rejected, not preserved. See PROJECT_FORMAT.md for versions 1–10 and
|
are rejected, not preserved. See PROJECT_FORMAT.md for versions 1–10 and
|
||||||
RECOVERY.md for save failures after rename.
|
RECOVERY.md for save failures after rename.
|
||||||
|
|
||||||
CLAP/VST2/VST3 loading supports Linux binary modules, one-input mono
|
CLAP/VST2/VST3 loading supports Linux binary modules, one-input mono float32
|
||||||
float32 zero-latency effects at default configuration. No modern parameter edit,
|
zero-latency effects at default configuration. No modern parameter edit,
|
||||||
automation, programs, opaque state, MIDI/instruments, transport, custom editor,
|
automation, programs, opaque state, MIDI/instruments, transport, custom editor,
|
||||||
workers, sidechains or true stereo/multichannel buses are implemented. Plugin
|
workers, sidechains or true stereo/multichannel buses are implemented. Plugin
|
||||||
bundles must be opened at their actual Linux shared-library binary. Only original
|
bundles must be opened at their actual Linux shared-library binary. Only
|
||||||
ABI fixtures are qualified; arbitrary third-party modern plugins remain untested.
|
original ABI fixtures are qualified; arbitrary third-party modern plugins remain
|
||||||
See PLUGIN_HOSTING.md and decision 0010 for lifecycle and licensing boundaries.
|
untested. See PLUGIN_HOSTING.md and decision 0010 for lifecycle and licensing
|
||||||
|
boundaries.
|
||||||
|
|
||||||
## Instrument support
|
---
|
||||||
|
|
||||||
|
## Instrument Support
|
||||||
|
|
||||||
MIDI tracks can bind CLAP, VST2 and VST3 instruments. In the Track menu, select
|
MIDI tracks can bind CLAP, VST2 and VST3 instruments. In the Track menu, select
|
||||||
**Load instrument plugin** for the selected sequencer track; **Use built-in
|
**Load instrument plugin** for the selected sequencer track; **Use built-in
|
||||||
|
|
@ -93,9 +105,9 @@ their own track's instrument. Independent instances feed track gain/pan,
|
||||||
mute/solo, bus routing and automation. Bindings/live target save in v12.
|
mute/solo, bus routing and automation. Bindings/live target save in v12.
|
||||||
|
|
||||||
Supply the actual trusted Linux binary (including the inner .so of a VST3
|
Supply the actual trusted Linux binary (including the inner .so of a VST3
|
||||||
bundle). Supported instruments have zero audio inputs, one mono output,
|
bundle). Supported instruments have zero audio inputs, one mono output, float32
|
||||||
float32 processing, zero latency and one note/event input. Default configuration
|
processing, zero latency and one note/event input. Default configuration only:
|
||||||
only: no custom editor, opaque state/preset restoration, modern parameter
|
no custom editor, opaque state/preset restoration, modern parameter
|
||||||
editing/automation, stereo/multichannel instruments or MIDI output. No arbitrary
|
editing/automation, stereo/multichannel instruments or MIDI output. No arbitrary
|
||||||
third-party instrument is qualified by the original ABI fixture tests.
|
third-party instrument is qualified by the original ABI fixture tests.
|
||||||
|
|
||||||
|
|
@ -113,19 +125,18 @@ the callback and old instances are reclaimed on the control thread. Missing
|
||||||
references remain inspectable without loading; failed GUI preparation retains
|
references remain inspectable without loading; failed GUI preparation retains
|
||||||
the current project. Save a backup for applications limited to v11 or earlier.
|
the current project. Save a backup for applications limited to v11 or earlier.
|
||||||
|
|
||||||
|
|
||||||
### Track insert chains
|
### Track insert chains
|
||||||
|
|
||||||
Track chains contain at most eight mono effects. Modern adapters require zero
|
Track chains contain at most eight mono effects. Modern adapters require zero
|
||||||
reported latency, use default configuration and do not provide native plugin
|
reported latency, use default configuration and do not provide native plugin
|
||||||
windows, parameter editing or opaque state persistence. A bounded VST3 output
|
windows, parameter editing or opaque state persistence. A bounded VST3 output
|
||||||
parameter sink retains the final notification per parameter per block (64
|
parameter sink retains the final notification per parameter per block (64
|
||||||
parameters); these notifications are not recorded or exposed as controls.
|
parameters); these notifications are not recorded or exposed as controls. Track
|
||||||
Track edits stop transport before candidate preparation. Bus inserts and tracks
|
edits stop transport before candidate preparation. Bus inserts and tracks with
|
||||||
with both audio assets and MIDI reject preparation. Unassigned live sine
|
both audio assets and MIDI reject preparation. Unassigned live sine monitoring
|
||||||
monitoring stays on the master input. Stereo insert layouts, latency
|
stays on the master input. Stereo insert layouts, latency compensation,
|
||||||
compensation, sandboxed scanning and gapless live insert edits remain future
|
sandboxed scanning and gapless live insert edits remain future work. Internal
|
||||||
work. Internal history resets on discontinuities; third-party history follows
|
history resets on discontinuities; third-party history follows the existing host
|
||||||
the existing host contract. Presets retain absolute plugin references, so
|
contract. Presets retain absolute plugin references, so compatible binaries must
|
||||||
compatible binaries must be installed at the same paths on another machine.
|
be installed at the same paths on another machine. The smaller optional
|
||||||
The smaller optional inspector's visibility is session-local.
|
inspector's visibility is session-local.
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,14 @@
|
||||||
# Licensing and dependency review
|
# Licensing and Dependency Review
|
||||||
|
|
||||||
The repository's original code, example and documentation are under the MIT
|
The repository's original code, example and documentation are under the MIT
|
||||||
license in LICENSE (copyright Johannes Findeisen). No energyXT source, artwork,
|
license in LICENSE (copyright Johannes Findeisen). No energyXT source, artwork,
|
||||||
proprietary SDK, vendored DSP or plugin binary is included. Permissively licensed
|
proprietary SDK, vendored DSP or plugin binary is included. Permissively
|
||||||
ABI headers are vendored with their own notices. The source archive
|
licensed ABI headers are vendored with their own notices. The source archive
|
||||||
contains repository files and an export manifest; it does not bundle system
|
contains repository files and an export manifest; it does not bundle system
|
||||||
libraries. Installation includes LICENSE and these documents.
|
libraries. Installation includes LICENSE and these documents.
|
||||||
|
|
||||||
The host review inspected installed package metadata and local license files. Package-level license sets can include utilities/docs that differ from the
|
The host review inspected installed package metadata and local license files.
|
||||||
|
Package-level license sets can include utilities/docs that differ from the
|
||||||
specific library being linked; retain the relevant upstream notices when
|
specific library being linked; retain the relevant upstream notices when
|
||||||
redistributing dependencies. The default install uses system shared libraries.
|
redistributing dependencies. The default install uses system shared libraries.
|
||||||
|
|
||||||
|
|
@ -27,10 +28,10 @@ redistributing dependencies. The default install uses system shared libraries.
|
||||||
| D-Bus | AFL-2.1 OR GPL-2.0-or-later. |
|
| D-Bus | AFL-2.1 OR GPL-2.0-or-later. |
|
||||||
| Python 3 | PSF-2.0; optional build/test/package scripts use only the standard library. Not an application runtime dependency. |
|
| Python 3 | PSF-2.0; optional build/test/package scripts use only the standard library. Not an application runtime dependency. |
|
||||||
|
|
||||||
GNU Make, GCC/Clang, binutils, pkg-config and optional Xvfb/xdotool/sanitizers are
|
GNU Make, GCC/Clang, binutils, pkg-config and optional Xvfb/xdotool/sanitizers
|
||||||
build/test tools, not shipped dependencies. New Python tooling needs Python 3.12+
|
are build/test tools, not shipped dependencies. New Python tooling needs Python
|
||||||
for safe tar extraction in release tests; this host has Python 3.14.8. No packages
|
3.12+ for safe tar extraction in release tests; this host has Python 3.14.8. No
|
||||||
were installed and no application dependency was added.
|
packages were installed and no application dependency was added.
|
||||||
|
|
||||||
Binary redistributors must inspect their own `readelf -d`/`ldd` dependency set
|
Binary redistributors must inspect their own `readelf -d`/`ldd` dependency set
|
||||||
and supply the notices/source/relinking facilities required by those exact
|
and supply the notices/source/relinking facilities required by those exact
|
||||||
|
|
@ -38,7 +39,9 @@ licenses and linking choices. FLTK's exception does not remove obligations of
|
||||||
other linked libraries. This review covers the current unmodified system-linked
|
other linked libraries. This review covers the current unmodified system-linked
|
||||||
build; static all-in-one bundles and external plugins need a separate review.
|
build; static all-in-one bundles and external plugins need a separate review.
|
||||||
|
|
||||||
## LADSPA review
|
---
|
||||||
|
|
||||||
|
## LADSPA Review
|
||||||
|
|
||||||
The optional external host includes the system LADSPA 1.1 header (`ladspa`
|
The optional external host includes the system LADSPA 1.1 header (`ladspa`
|
||||||
1.17-7), copyright Richard W.E. Furse, Paul Barton-Davis and Stefan Westerfeld,
|
1.17-7), copyright Richard W.E. Furse, Paul Barton-Davis and Stefan Westerfeld,
|
||||||
|
|
@ -50,12 +53,15 @@ The original fixture in tests/plugins is MIT repository code.
|
||||||
|
|
||||||
Acceptance dynamically loads the user's installed LADSPA sample amp/sine modules
|
Acceptance dynamically loads the user's installed LADSPA sample amp/sine modules
|
||||||
(package metadata LGPL-2.1-or-later) and SWH inverter (swh-plugins 0.4.17-7,
|
(package metadata LGPL-2.1-or-later) and SWH inverter (swh-plugins 0.4.17-7,
|
||||||
GPL-2.0-or-later). Testing/loading a user-installed module does not grant the right
|
GPL-2.0-or-later). Testing/loading a user-installed module does not grant the
|
||||||
to bundle or relicense it. Redistributors must review each chosen module and the
|
right to bundle or relicense it. Redistributors must review each chosen module
|
||||||
combined distribution's obligations separately; xtc's MIT grant covers only its
|
and the combined distribution's obligations separately; xtc's MIT grant covers
|
||||||
original code. No third-party plugin is included in source archives or installs.
|
only its original code. No third-party plugin is included in source archives or
|
||||||
|
installs.
|
||||||
|
|
||||||
## Pinned header dependencies
|
---
|
||||||
|
|
||||||
|
## Pinned Header Dependencies
|
||||||
|
|
||||||
CLAP headers are MIT, copyright Alexandre BIQUE, from upstream commit
|
CLAP headers are MIT, copyright Alexandre BIQUE, from upstream commit
|
||||||
`a47f6badb49d948fd009998f28309cdab78979c9`. The generated VST3 C ABI header is
|
`a47f6badb49d948fd009998f28309cdab78979c9`. The generated VST3 C ABI header is
|
||||||
|
|
@ -63,7 +69,8 @@ BSD-3-Clause, copyright Steinberg Media Technologies GmbH, from commit
|
||||||
`93a116f7c6c52a317ec3aaee9b13789068b5234e`. Exact licenses are retained under
|
`93a116f7c6c52a317ec3aaee9b13789068b5234e`. Exact licenses are retained under
|
||||||
third_party and installed as CLAP-LICENSE / VST3-C-API-LICENSE. These are header
|
third_party and installed as CLAP-LICENSE / VST3-C-API-LICENSE. These are header
|
||||||
specifications only: no external runtime SDK or network build step was added.
|
specifications only: no external runtime SDK or network build step was added.
|
||||||
Review updates explicitly; do not assume future revisions share the same license.
|
Review updates explicitly; do not assume future revisions share the same
|
||||||
|
license.
|
||||||
|
|
||||||
The VST2 compatibility declarations and all three ABI fixtures are original MIT
|
The VST2 compatibility declarations and all three ABI fixtures are original MIT
|
||||||
repository code; no Steinberg VST2 SDK or third-party plugin is bundled. Hosting
|
repository code; no Steinberg VST2 SDK or third-party plugin is bundled. Hosting
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
# Linux setup and installation
|
# Linux Setup and Installation
|
||||||
|
|
||||||
Use a C99 compiler, C++17 compiler for the GUI, GNU Make, binutils and pkg-config.
|
Use a C99 compiler, C++17 compiler for the GUI, GNU Make, binutils and
|
||||||
The core needs only the C/math runtime. FLTK 1.4 development files enable the GUI;
|
pkg-config. The core needs only the C/math runtime. FLTK 1.4 development files
|
||||||
JACK-compatible development files enable the optional audio/MIDI backend.
|
enable the GUI; JACK-compatible development files enable the optional audio/MIDI
|
||||||
Packaging/install tests additionally use Python 3.12+ (standard library only).
|
backend. Packaging/install tests additionally use Python 3.12+ (standard library
|
||||||
No command starts a server, installs dependencies or changes system settings.
|
only). No command starts a server, installs dependencies or changes system
|
||||||
|
settings.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
make all test
|
make all test
|
||||||
|
|
@ -15,20 +16,24 @@ make gui
|
||||||
Start/configure a JACK or PipeWire JACK-compatible server through your existing
|
Start/configure a JACK or PipeWire JACK-compatible server through your existing
|
||||||
system setup first. xtc opens without starting one and requires reconnect after
|
system setup first. xtc opens without starting one and requires reconnect after
|
||||||
server loss/rate changes. In a separate JACK routing tool connect desired MIDI
|
server loss/rate changes. In a separate JACK routing tool connect desired MIDI
|
||||||
to `midi_in`, audio capture to `input`, and `output`/`output_right` to left/right
|
to `midi_in`, audio capture to `input`, and `output`/`output_right` to
|
||||||
playback ports. No physical routes are automatic. Input/recording remain mono.
|
left/right playback ports. No physical routes are automatic. Input/recording
|
||||||
See GUI.md, AUDIO_FILES.md, MIDI.md and MIXER.md for composing/recording/editing.
|
remain mono. See GUI.md, AUDIO_FILES.md, MIDI.md and MIXER.md for
|
||||||
|
composing/recording/editing.
|
||||||
|
|
||||||
`xtc --help` and `xtc --version` work without a display/server. `xtc project.xtc`
|
`xtc --help` and `xtc --version` work without a display/server.
|
||||||
opens one project; no-file startup retains FLTK options such as `-display`.
|
`xtc project.xtc` opens one project; no-file startup retains FLTK options such
|
||||||
`xtc-check --validate project.xtc` validates metadata only; native graphs cannot
|
as `-display`. `xtc-check --validate project.xtc` validates metadata only;
|
||||||
be serialized. See RECOVERY.md before replacing damaged files.
|
native graphs cannot be serialized. See RECOVERY.md before replacing damaged
|
||||||
|
files.
|
||||||
|
|
||||||
## Staged installation
|
---
|
||||||
|
|
||||||
Core-only installation retains the original `make install` behavior and now
|
## Staged Installation
|
||||||
adds xtc-check, pkg-config metadata, license and documentation. install-gui adds
|
|
||||||
the GUI executable and desktop launcher. Defaults to PREFIX=/usr/local:
|
Core-only installation retains the original `make install` behavior and now adds
|
||||||
|
xtc-check, pkg-config metadata, license and documentation. install-gui adds the
|
||||||
|
GUI executable and desktop launcher. Defaults to PREFIX=/usr/local:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
make install-gui DESTDIR="$PWD/build/stage" PREFIX=/usr
|
make install-gui DESTDIR="$PWD/build/stage" PREFIX=/usr
|
||||||
|
|
@ -57,28 +62,33 @@ file records its private dependency. Public headers contain no JACK/FLTK types.
|
||||||
To build without optional libraries, set PKG_CONFIG=false FLTK_CONFIG=false.
|
To build without optional libraries, set PKG_CONFIG=false FLTK_CONFIG=false.
|
||||||
Python is not needed to run the installed executables or library.
|
Python is not needed to run the installed executables or library.
|
||||||
|
|
||||||
## Binary/development archive
|
---
|
||||||
|
|
||||||
|
## Binary/Development Archive
|
||||||
|
|
||||||
`make package` creates a system-linked Linux archive plus SHA-256 sidecar below
|
`make package` creates a system-linked Linux archive plus SHA-256 sidecar below
|
||||||
BUILD_DIR; `make test-package` verifies its contents. It includes usr/bin,
|
BUILD_DIR; `make test-package` verifies its contents. It includes usr/bin,
|
||||||
headers/static library/pkg-config metadata, desktop file (when FLTK is present),
|
headers/static library/pkg-config metadata, desktop file (when FLTK is present),
|
||||||
manuals, baseline and MIT license. No shared library, third-party plugin, media,
|
manuals, baseline and MIT license. No shared library, third-party plugin, media,
|
||||||
service or dependency installer is bundled. `BINARY_MANIFEST.json` lists file
|
service or dependency installer is bundled. `BINARY_MANIFEST.json` lists file
|
||||||
hashes/sizes, architecture/libc and ELF NEEDED libraries. The entire archive's hash
|
hashes/sizes, architecture/libc and ELF NEEDED libraries. The entire archive's
|
||||||
covers the manifest too. Do not assume compatibility with another distribution.
|
hash covers the manifest too. Do not assume compatibility with another
|
||||||
|
distribution.
|
||||||
|
|
||||||
Inspect/test under a temporary directory first. For a writable user prefix,
|
Inspect/test under a temporary directory first. For a writable user prefix,
|
||||||
extract the archive with two leading path components stripped (`xtc-VERSION-linux-
|
extract the archive with two leading path components stripped
|
||||||
ARCH/usr`), placing bin/include/lib/share directly under that prefix. Put its bin
|
(`xtc-VERSION-linux- ARCH/usr`), placing bin/include/lib/share directly under
|
||||||
on PATH and lib/pkgconfig on PKG_CONFIG_PATH. The archive's pkg-config prefix is
|
that prefix. Put its bin on PATH and lib/pkgconfig on PKG_CONFIG_PATH. The
|
||||||
relative to its installed location; normal `make install` retains explicit PREFIX.
|
archive's pkg-config prefix is relative to its installed location; normal
|
||||||
Use the matching source's uninstall with that PREFIX, or review the manifest
|
`make install` retains explicit PREFIX. Use the matching source's uninstall with
|
||||||
before removing its files. Unknown/unrelated files are retained by source uninstall.
|
that PREFIX, or review the manifest before removing its files. Unknown/unrelated
|
||||||
This local tar package is not a pacman/RPM/deb registration or public distribution.
|
files are retained by source uninstall. This local tar package is not a
|
||||||
|
pacman/RPM/deb registration or public distribution.
|
||||||
|
|
||||||
`xtc-check --diagnose` reports build capabilities and format/engine limits without
|
`xtc-check --diagnose` reports build capabilities and format/engine limits
|
||||||
opening a server or executing a plugin. `xtc --diagnose` works headlessly as well.
|
without opening a server or executing a plugin. `xtc --diagnose` works
|
||||||
Missing runtime GUI libraries are loader errors: install the distribution's
|
headlessly as well. Missing runtime GUI libraries are loader errors: install the
|
||||||
compatible dependencies or rebuild the core-only configuration. Build without
|
distribution's compatible dependencies or rebuild the core-only configuration.
|
||||||
optional libraries using a fresh directory, `PKG_CONFIG=false FLTK_CONFIG=false
|
Build without optional libraries using a fresh directory,
|
||||||
CPPFLAGS=-DXTC_DISABLE_LADSPA`. No system setting or package is changed by tests.
|
`PKG_CONFIG=false FLTK_CONFIG=false CPPFLAGS=-DXTC_DISABLE_LADSPA`. No system
|
||||||
|
setting or package is changed by tests.
|
||||||
|
|
|
||||||
|
|
@ -1,45 +1,53 @@
|
||||||
# Release and maintenance policy
|
# Release and Maintenance Policy
|
||||||
|
|
||||||
## Supported development target
|
## Supported Development Target
|
||||||
|
|
||||||
Initial target: x86_64 Artix/Arch-family Linux with glibc, GNU Make, GCC/Clang,
|
Initial target: x86_64 Artix/Arch-family Linux with glibc, GNU Make, GCC/Clang,
|
||||||
FLTK 1.4 and a JACK-compatible client/server. The inspected host uses GCC 16.2.1,
|
FLTK 1.4 and a JACK-compatible client/server. The inspected host uses GCC
|
||||||
FLTK 1.4.5 and the dependencies in LICENSES.md. Core-only/no-JACK/no-LADSPA builds
|
16.2.1, FLTK 1.4.5 and the dependencies in LICENSES.md.
|
||||||
are checked too. Build on the destination distribution for different library ABIs;
|
Core-only/no-JACK/no-LADSPA builds are checked too. Build on the destination
|
||||||
there is no cross-distribution static-binary promise. Python 3.12+ and binutils
|
distribution for different library ABIs; there is no cross-distribution
|
||||||
are build/package/test tools only. No dependency is fetched automatically.
|
static-binary promise. Python 3.12+ and binutils are build/package/test tools
|
||||||
|
only. No dependency is fetched automatically.
|
||||||
|
|
||||||
## Release checklist
|
---
|
||||||
|
|
||||||
|
## Release Checklist
|
||||||
|
|
||||||
1. Work from a clean reviewed commit. Record `git rev-parse HEAD`, compiler,
|
1. Work from a clean reviewed commit. Record `git rev-parse HEAD`, compiler,
|
||||||
libc/FLTK/JACK versions and `xtc-check --diagnose`. No automatic version bump,
|
libc/FLTK/JACK versions and `xtc-check --diagnose`. No automatic version
|
||||||
Git tag, public upload or external release is performed by local targets.
|
bump, Git tag, public upload or external release is performed by local
|
||||||
2. Run warning-enabled `make all test gui test-plugins test-plugins-real
|
targets.
|
||||||
test-gui-plugins test-workflow test-gui-jack test-jack-midi test-recording
|
2. Run warning-enabled
|
||||||
test-recovery test-reliability test-scale analyze` where dependencies exist.
|
`make all test gui test-plugins test-plugins-real test-gui-plugins test-workflow test-gui-jack test-jack-midi test-recording test-recovery test-reliability test-scale analyze`
|
||||||
|
where dependencies exist.
|
||||||
3. Use a separate BUILD_DIR for ASan/UBSan/leak runs and another for optional-
|
3. Use a separate BUILD_DIR for ASan/UBSan/leak runs and another for optional-
|
||||||
dependency builds. GUI leak checks use only the documented fontconfig
|
dependency builds. GUI leak checks use only the documented fontconfig
|
||||||
suppression; core tests use none. Run publication/recording race tests as
|
suppression; core tests use none. Run publication/recording race tests as
|
||||||
described in RELIABILITY.md. Sanitizers are not latency qualification.
|
described in RELIABILITY.md. Sanitizers are not latency qualification.
|
||||||
4. Run `make benchmark test-performance test-stress`; compare on matching
|
4. Run `make benchmark test-performance test-stress`; compare on matching
|
||||||
host/compiler/flags against a reviewed baseline. Investigate regressions;
|
host/compiler/flags against a reviewed baseline. Investigate regressions; do
|
||||||
do not weaken thresholds or replace evidence without explanation.
|
not weaken thresholds or replace evidence without explanation.
|
||||||
5. Run `make test-install test-release test-package`. Inspect archive manifests,
|
5. Run `make test-install test-release test-package`. Inspect archive manifests,
|
||||||
hashes, dynamic dependency names and licenses. Source exports rebuild twice
|
hashes, dynamic dependency names and licenses. Source exports rebuild twice
|
||||||
with identical artifacts on this host. Repeat binary packaging compares bytes.
|
with identical artifacts on this host. Repeat binary packaging compares
|
||||||
6. Complete physical listening, recording/device/endurance, and independent human
|
bytes.
|
||||||
install/workflow checks before claiming production qualification. They remain
|
6. Complete physical listening, recording/device/endurance, and independent
|
||||||
pending for this prototype, even when all automated checks pass.
|
human install/workflow checks before claiming production qualification. They
|
||||||
|
remain pending for this prototype, even when all automated checks pass.
|
||||||
7. Save checksums/test logs/conditions with the proposed release. Review known
|
7. Save checksums/test logs/conditions with the proposed release. Review known
|
||||||
limitations and format compatibility and update user/developer docs. Publishing
|
limitations and format compatibility and update user/developer docs.
|
||||||
or distro repository submission is a separate action.
|
Publishing or distro repository submission is a separate action.
|
||||||
|
|
||||||
## Regressions and compatibility
|
---
|
||||||
|
|
||||||
|
## Regressions and Compatibility
|
||||||
|
|
||||||
Report the exact version/commit, OS/toolchain, compiled features, reproduction,
|
Report the exact version/commit, OS/toolchain, compiled features, reproduction,
|
||||||
expected/actual output, GUI errors/xruns and whether plugins are involved. Keep a
|
expected/actual output, GUI errors/xruns and whether plugins are involved. Keep
|
||||||
minimal project/media fixture when redistribution is permitted; do not attach
|
a minimal project/media fixture when redistribution is permitted; do not attach
|
||||||
private recordings or full memory dumps inadvertently. No telemetry/upload occurs.
|
private recordings or full memory dumps inadvertently. No telemetry/upload
|
||||||
|
occurs.
|
||||||
|
|
||||||
A confirmed defect gets a focused deterministic regression or repeatable runtime
|
A confirmed defect gets a focused deterministic regression or repeatable runtime
|
||||||
check before its fix. Memory/thread/file-loss defects take priority; disable the
|
check before its fix. Memory/thread/file-loss defects take priority; disable the
|
||||||
|
|
@ -47,22 +55,25 @@ unsafe path rather than silently dropping media or unknown project records. Keep
|
||||||
candidate preparation/plan publication transactional and callbacks bounded.
|
candidate preparation/plan publication transactional and callbacks bounded.
|
||||||
|
|
||||||
Format changes increment XTC_PROJECT_FORMAT_VERSION, retain explicit bounded
|
Format changes increment XTC_PROJECT_FORMAT_VERSION, retain explicit bounded
|
||||||
migrations/fixtures for all supported older versions, and add malformed/roundtrip
|
migrations/fixtures for all supported older versions, and add
|
||||||
checks. Unknown versions/types/records fail with actionable errors. Never rewrite
|
malformed/roundtrip checks. Unknown versions/types/records fail with actionable
|
||||||
an unsupported source file during failed Open. Keep the original when diagnosing
|
errors. Never rewrite an unsupported source file during failed Open. Keep the
|
||||||
post-publication sync errors. Native descriptor ABI compatibility is distinct from
|
original when diagnosing post-publication sync errors. Native descriptor ABI
|
||||||
project format and is documented in NATIVE_API.md; opaque DSP state is not promised.
|
compatibility is distinct from project format and is documented in
|
||||||
No public stability guarantee or support SLA is implied by development version 0.1.0.
|
NATIVE_API.md; opaque DSP state is not promised. No public stability guarantee
|
||||||
|
or support SLA is implied by development version 0.1.0.
|
||||||
|
|
||||||
## Support and triage record
|
---
|
||||||
|
|
||||||
|
## Support and Triage Record
|
||||||
|
|
||||||
Verified compilers are GCC/G++ 16.2.1 and Clang/Clang++ 23.1.3 on x86_64 Linux;
|
Verified compilers are GCC/G++ 16.2.1 and Clang/Clang++ 23.1.3 on x86_64 Linux;
|
||||||
these are tested versions, not a promise that arbitrary older/newer versions work.
|
these are tested versions, not a promise that arbitrary older/newer versions
|
||||||
The code requires C99 plus GCC/Clang lock-free atomics, C++17 for the GUI, FLTK
|
work. The code requires C99 plus GCC/Clang lock-free atomics, C++17 for the GUI,
|
||||||
1.4 and POSIX/glibc APIs. JACK (including PipeWire's JACK compatibility) is the
|
FLTK 1.4 and POSIX/glibc APIs. JACK (including PipeWire's JACK compatibility) is
|
||||||
only live backend. Native Windows/macOS, other architectures and direct ALSA
|
the only live backend. Native Windows/macOS, other architectures and direct ALSA
|
||||||
backends are not qualified. Core builds can disable JACK, FLTK and LADSPA.
|
backends are not qualified. Core builds can disable JACK, FLTK and LADSPA. See
|
||||||
See BUILD.md and LICENSES.md for dependency roles and versions.
|
BUILD.md and LICENSES.md for dependency roles and versions.
|
||||||
|
|
||||||
Release qualification adds `test-install-layout`, installed example inspection,
|
Release qualification adds `test-install-layout`, installed example inspection,
|
||||||
all performance report resources, source checksum verification and the current
|
all performance report resources, source checksum verification and the current
|
||||||
|
|
@ -70,11 +81,12 @@ RELEASE_NOTES.md. Retain the original graph benchmark alert in release records;
|
||||||
a successful compile does not clear timing qualification gaps.
|
a successful compile does not clear timing qualification gaps.
|
||||||
|
|
||||||
File reproducible bugs with the repository maintainers using the source commit
|
File reproducible bugs with the repository maintainers using the source commit
|
||||||
and archive SHA-256, `xtc-check --version`/`--diagnose`, distro/kernel and toolchain,
|
and archive SHA-256, `xtc-check --version`/`--diagnose`, distro/kernel and
|
||||||
exact commands or GUI steps, expected versus observed behavior and frequency.
|
toolchain, exact commands or GUI steps, expected versus observed behavior and
|
||||||
Reduce to a redistributable project and state whether it reproduces without
|
frequency. Reduce to a redistributable project and state whether it reproduces
|
||||||
external plugins and with the offline/core tools. Include relevant stderr and
|
without external plugins and with the offline/core tools. Include relevant
|
||||||
sanitizer traces; preserve original recovery files before experimenting.
|
stderr and sanitizer traces; preserve original recovery files before
|
||||||
|
experimenting.
|
||||||
|
|
||||||
Maintainers should first confirm version/features and reproduce in an isolated
|
Maintainers should first confirm version/features and reproduce in an isolated
|
||||||
build. Prioritize data loss/security/memory/thread defects, then crashes and
|
build. Prioritize data loss/security/memory/thread defects, then crashes and
|
||||||
|
|
|
||||||
154
docs/MIDI.md
154
docs/MIDI.md
|
|
@ -1,49 +1,57 @@
|
||||||
# MIDI clips and instrument
|
# MIDI Clips and Instrument
|
||||||
|
|
||||||
Drawing persisted notes and live JACK MIDI input are supported. Record still
|
Drawing persisted notes and live JACK MIDI input are supported. Record still
|
||||||
captures audio to WAV: MIDI capture and Standard MIDI File import are deferred.
|
captures audio to WAV: MIDI capture and Standard MIDI File import are deferred.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Workflow
|
## Workflow
|
||||||
|
|
||||||
Add/select a track in Sequencer, choose Add MIDI clip, then Piano roll (Ctrl+4).
|
Add/select a track in Sequencer, choose Add MIDI clip, then Piano roll (Ctrl+4).
|
||||||
Creation adds an instrument-to-output route if no instrument exists. Existing
|
Creation adds an instrument-to-output route if no instrument exists. Existing
|
||||||
instruments retain their routes; use Modular Graph to connect them as needed.
|
instruments retain their routes; use Modular Graph to connect them as needed.
|
||||||
Scheduled MIDI clips now apply their track mix/automation before summing to
|
Scheduled MIDI clips now apply their track mix/automation before summing to
|
||||||
paired stereo instrument buffers; live input stays centered and unassigned. No hardware ports
|
paired stereo instrument buffers; live input stays centered and unassigned. No
|
||||||
are connected automatically. Connect a MIDI source to the backend's `midi_in`
|
hardware ports are connected automatically. Connect a MIDI source to the
|
||||||
JACK port, and route audio output explicitly to hear it while Play is running.
|
backend's `midi_in` JACK port, and route audio output explicitly to hear it
|
||||||
|
while Play is running.
|
||||||
|
|
||||||
The piano roll shows all 128 pitches and edits clip-source time. Click blank
|
The piano roll shows all 128 pitches and edits clip-source time. Click blank
|
||||||
space to draw a one-beat note (velocity 100, filtered channel or channel 0); drag its body to move
|
space to draw a one-beat note (velocity 100, filtered channel or channel 0);
|
||||||
it, drag the right edge to resize, or right-click/Delete to remove it. Edits
|
drag its body to move it, drag the right edge to resize, or right-click/Delete
|
||||||
snap to the configured grid (default 1/16). Escape cancels a drag. Trimmed-out source notes remain editable
|
to remove it. Edits snap to the configured grid (default 1/16). Escape cancels a
|
||||||
and are preserved. Arrangement/note edits stop playback and are blocked during
|
drag. Trimmed-out source notes remain editable and are preserved.
|
||||||
audio recording. Save/Open preserves MIDI flags, notes and stable IDs.
|
Arrangement/note edits stop playback and are blocked during audio recording.
|
||||||
|
Save/Open preserves MIDI flags, notes and stable IDs.
|
||||||
|
|
||||||
## Timing and ownership
|
---
|
||||||
|
|
||||||
The C model owns up to 4096 notes per project, with source-relative ticks at
|
## Timing and Ownership
|
||||||
960 ticks/quarter and constant tempo. Control-thread preparation intersects
|
|
||||||
notes with clip trims and converts boundaries to integer sample positions.
|
The C model owns up to 4096 notes per project, with source-relative ticks at 960
|
||||||
Scheduled rendering uses absolute note age: block partitions do not change
|
ticks/quarter and constant tempo. Control-thread preparation intersects notes
|
||||||
samples, and seeking into a note chases its phase. Clip ends cut notes off.
|
with clip trims and converts boundaries to integer sample positions. Scheduled
|
||||||
The instrument source has its own buffer, separate from external audio input
|
rendering uses absolute note age: block partitions do not change samples, and
|
||||||
and WAV timeline playback, and routes through the ordinary graph.
|
seeking into a note chases its phase. Clip ends cut notes off. The instrument
|
||||||
|
source has its own buffer, separate from external audio input and WAV timeline
|
||||||
|
playback, and routes through the ordinary graph.
|
||||||
|
|
||||||
Prepared ranges are immutable; only their audio owner changes voice/panic state.
|
Prepared ranges are immutable; only their audio owner changes voice/panic state.
|
||||||
Preparation allocates; rendering uses bounded preallocated storage and performs
|
Preparation allocates; rendering uses bounded preallocated storage and performs
|
||||||
no allocation, freeing, I/O, locks, logging or GUI calls. Project preparation
|
no allocation, freeing, I/O, locks, logging or GUI calls. Project preparation
|
||||||
builds audio and MIDI candidates before committing the stopped backend state.
|
builds audio and MIDI candidates before committing the stopped backend state.
|
||||||
|
|
||||||
JACK events have sample offsets within the current block. Supported messages
|
JACK events have sample offsets within the current block. Supported messages are
|
||||||
are complete note on/off (including velocity-zero note on) and CC120/123 on
|
complete note on/off (including velocity-zero note on) and CC120/123 on channels
|
||||||
channels 0..15, plus CC7 volume, CC10 pan and CC64 sustain (see CONTROL.md).
|
0..15, plus CC7 volume, CC10 pan and CC64 sustain (see CONTROL.md). Equal-offset
|
||||||
Equal-offset events retain input order. Bend, program changes, running status
|
events retain input order. Bend, program changes, running status and SysEx are
|
||||||
and SysEx are unsupported.
|
unsupported. At most 256 events are accepted per block. Malformed/overflowed
|
||||||
At most 256 events are accepted per block. Malformed/overflowed input discards
|
input discards that block's events and triggers panic, with a MIDI-drop status
|
||||||
that block's events and triggers panic, with a MIDI-drop status counter.
|
counter.
|
||||||
|
|
||||||
## Recovery and limits
|
---
|
||||||
|
|
||||||
|
## Recovery and Limits
|
||||||
|
|
||||||
Panic/F9 clears live voices and suppresses scheduled notes already started;
|
Panic/F9 clears live voices and suppresses scheduled notes already started;
|
||||||
future timeline notes can still start. CC120/123 does this for its channel.
|
future timeline notes can still start. CC120/123 does this for its channel.
|
||||||
|
|
@ -52,15 +60,17 @@ notes to be chased again. MIDI port disconnection, xruns and callback processing
|
||||||
failures request panic. Control requests use lock-free generation counters;
|
failures request panic. Control requests use lock-free generation counters;
|
||||||
voice state changes on the audio thread, or while stopped.
|
voice state changes on the audio thread, or while stopped.
|
||||||
|
|
||||||
The sine instrument scales amplitude by 0.1 times velocity/127. It supports
|
The sine instrument scales amplitude by 0.1 times velocity/127. It supports 32
|
||||||
32 simultaneous scheduled notes and a separate 32 live voices; live overflow
|
simultaneous scheduled notes and a separate 32 live voices; live overflow steals
|
||||||
steals the oldest voice, and repeated channel/pitch retriggers it. Preparation
|
the oldest voice, and repeated channel/pitch retriggers it. Preparation rejects
|
||||||
rejects more than 32 overlapping scheduled notes with CAPACITY. Such metadata
|
more than 32 overlapping scheduled notes with CAPACITY. Such metadata can be
|
||||||
can be saved by the C model, but GUI Open/Play rejects it until overlap is
|
saved by the C model, but GUI Open/Play rejects it until overlap is reduced.
|
||||||
reduced. Immediate note-off/stealing can click; there is no envelope or limiter,
|
Immediate note-off/stealing can click; there is no envelope or limiter, and
|
||||||
and summed voices can exceed unity. Above-Nyquist pitches are silent.
|
summed voices can exceed unity. Above-Nyquist pitches are silent. There is no
|
||||||
There is no per-track/channel instrument routing, MIDI recording, SMF import
|
per-track/channel instrument routing, MIDI recording, SMF import or piano-roll
|
||||||
or piano-roll zoom yet. Note edits participate in project snapshot undo/redo.
|
zoom yet. Note edits participate in project snapshot undo/redo.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Verification
|
## Verification
|
||||||
|
|
||||||
|
|
@ -70,13 +80,15 @@ malformed files, plus callback fault recovery. `make test-gui` draws, moves and
|
||||||
resizes notes with FLTK events, then saves/reopens and renders them.
|
resizes notes with FLTK events, then saves/reopens and renders them.
|
||||||
`make test-jack-midi` uses only software MIDI/audio ports to verify live on/off,
|
`make test-jack-midi` uses only software MIDI/audio ports to verify live on/off,
|
||||||
panic, disconnection and saved/reopened scheduled playback. JACK port discovery
|
panic, disconnection and saved/reopened scheduled playback. JACK port discovery
|
||||||
may lag activation under PipeWire; the test waits before connecting.
|
may lag activation under PipeWire; the test waits before connecting. Physical
|
||||||
Physical MIDI devices, bridge/device loss behind an unchanged port, latency and
|
MIDI devices, bridge/device loss behind an unchanged port, latency and
|
||||||
long-running performance remain unverified. Panic/Stop provides manual recovery.
|
long-running performance remain unverified. Panic/Stop provides manual recovery.
|
||||||
|
|
||||||
Track mixing, automation and project undo/redo are available; see MIXER.md.
|
Track mixing, automation and project undo/redo are available; see MIXER.md.
|
||||||
|
|
||||||
## Composition commands
|
---
|
||||||
|
|
||||||
|
## Composition Commands
|
||||||
|
|
||||||
The piano-roll **Notes** menu exposes these commands. Shortcuts apply while the
|
The piano-roll **Notes** menu exposes these commands. Shortcuts apply while the
|
||||||
piano roll has focus; use the main window Edit menu for undo/redo.
|
piano roll has focus; use the main window Edit menu for undo/redo.
|
||||||
|
|
@ -92,22 +104,22 @@ piano roll has focus; use the main window Edit menu for undo/redo.
|
||||||
| Select filtered | Ctrl+A | Select every note matching the current clip filter |
|
| Select filtered | Ctrl+A | Select every note matching the current clip filter |
|
||||||
| Delete | Delete | Remove the single selected note or all filtered notes |
|
| Delete | Delete | Remove the single selected note or all filtered notes |
|
||||||
|
|
||||||
160 ticks is a sixteenth-note triplet; 320 is an eighth-note triplet.
|
160 ticks is a sixteenth-note triplet; 320 is an eighth-note triplet. The grid
|
||||||
The grid governs drawing, drag movement and minimum resize duration. At 1-tick
|
governs drawing, drag movement and minimum resize duration. At 1-tick snap the
|
||||||
snap the visual grid remains 120 ticks to stay legible at the fixed zoom.
|
visual grid remains 120 ticks to stay legible at the fixed zoom. The header
|
||||||
The header shows current grid, channel/pitch filter and selection scope.
|
shows current grid, channel/pitch filter and selection scope. Velocity also
|
||||||
Velocity also affects unselected note brightness. Preferences are session-only.
|
affects unselected note brightness. Preferences are session-only.
|
||||||
|
|
||||||
Click selects one visible note; Ctrl+A selects the whole filtered set. A click
|
Click selects one visible note; Ctrl+A selects the whole filtered set. A click
|
||||||
or filter change clears that set selection. Hidden notes cannot be mouse-edited.
|
or filter change clears that set selection. Hidden notes cannot be mouse-edited.
|
||||||
A channel filter also sets the channel for newly drawn notes. No lasso or
|
A channel filter also sets the channel for newly drawn notes. No lasso or
|
||||||
arbitrary disjoint multi-selection is provided. Moving/resizing uses the mouse;
|
arbitrary disjoint multi-selection is provided. Moving/resizing uses the mouse;
|
||||||
V edits velocity/channel without changing timing, pitch or IDs. Quantization
|
V edits velocity/channel without changing timing, pitch or IDs. Quantization
|
||||||
changes starts only, preserving durations and other properties. Repetition
|
changes starts only, preserving durations and other properties. Repetition keeps
|
||||||
keeps originals and gives every copy a fresh stable ID; spacing need not equal
|
originals and gives every copy a fresh stable ID; spacing need not equal note
|
||||||
note length, so both overlapping patterns and rests are possible. The existing
|
length, so both overlapping patterns and rests are possible. The existing clip
|
||||||
clip source must have room for every result; extend it in Sequencer first if
|
source must have room for every result; extend it in Sequencer first if needed.
|
||||||
needed. Source notes outside the visible arrangement trim remain editable.
|
Source notes outside the visible arrangement trim remain editable.
|
||||||
|
|
||||||
All batch edits validate before mutation. Invalid pitch/range, copy counts,
|
All batch edits validate before mutation. Invalid pitch/range, copy counts,
|
||||||
capacity overflow or a note crossing the source boundary rejects the entire
|
capacity overflow or a note crossing the source boundary rejects the entire
|
||||||
|
|
@ -120,24 +132,27 @@ These edits use the existing persisted note fields; format remains v7.
|
||||||
Scheduled notes occupy [start,end), with ends counted before starts at an equal
|
Scheduled notes occupy [start,end), with ends counted before starts at an equal
|
||||||
sample for the 32-voice limit. Overlapping same-channel/pitch scheduled notes
|
sample for the 32-voice limit. Overlapping same-channel/pitch scheduled notes
|
||||||
are independent sine voices; adjacent repetitions restart phase. Live repeated
|
are independent sine voices; adjacent repetitions restart phase. Live repeated
|
||||||
notes instead retrigger the matching channel/pitch voice, and a note-off releases
|
notes instead retrigger the matching channel/pitch voice, and a note-off
|
||||||
that voice (or defers release under sustain). Equal-sample live on/off/control
|
releases that voice (or defers release under sustain). Equal-sample live
|
||||||
messages execute in caller/JACK order, with no implicit priority reordering.
|
on/off/control messages execute in caller/JACK order, with no implicit priority
|
||||||
The renderer rejects malformed/unsorted/out-of-range events before touching
|
reordering. The renderer rejects malformed/unsorted/out-of-range events before
|
||||||
output or runtime; raw velocity-zero note-ons decode to note-off.
|
touching output or runtime; raw velocity-zero note-ons decode to note-off.
|
||||||
|
|
||||||
`make test-composition` covers filters, property preservation, triplet rounding,
|
`make test-composition` covers filters, property preservation, triplet rounding,
|
||||||
repeats/fresh IDs, rejected batch rollback, capacity, undo snapshots, equal-offset
|
repeats/fresh IDs, rejected batch rollback, capacity, undo snapshots,
|
||||||
live order, adjacent/overlapping notes, exact block partitions and seek chase.
|
equal-offset live order, adjacent/overlapping notes, exact block partitions and
|
||||||
`make test-gui` covers mouse edits and the new commands with undo/redo and engine
|
seek chase. `make test-gui` covers mouse edits and the new commands with
|
||||||
reinstallation. Listening and physical MIDI-device validation remain pending.
|
undo/redo and engine reinstallation. Listening and physical MIDI-device
|
||||||
|
validation remain pending.
|
||||||
|
|
||||||
CC7/10/64 are defaults, configurable per channel through Audio → MIDI controller
|
CC7/10/64 are defaults, configurable per channel through Audio → MIDI controller
|
||||||
mapping. Disabled/unmapped CCs have no effect; CC120/123 stay panic.
|
mapping. Disabled/unmapped CCs have no effect; CC120/123 stay panic. Decode
|
||||||
Decode accepts valid CC0..127 messages within the existing event budget. See
|
accepts valid CC0..127 messages within the existing event budget. See CONTROL.md
|
||||||
CONTROL.md for the exact bindings, ramp, sustain and automation precedence rules.
|
for the exact bindings, ramp, sustain and automation precedence rules.
|
||||||
|
|
||||||
## Instrument support
|
---
|
||||||
|
|
||||||
|
## Instrument Support
|
||||||
|
|
||||||
MIDI tracks can bind CLAP, VST2 and VST3 instruments. In the Track menu, select
|
MIDI tracks can bind CLAP, VST2 and VST3 instruments. In the Track menu, select
|
||||||
**Load instrument plugin** for the selected sequencer track; **Use built-in
|
**Load instrument plugin** for the selected sequencer track; **Use built-in
|
||||||
|
|
@ -148,9 +163,9 @@ their own track's instrument. Independent instances feed track gain/pan,
|
||||||
mute/solo, bus routing and automation. Bindings/live target save in v12.
|
mute/solo, bus routing and automation. Bindings/live target save in v12.
|
||||||
|
|
||||||
Supply the actual trusted Linux binary (including the inner .so of a VST3
|
Supply the actual trusted Linux binary (including the inner .so of a VST3
|
||||||
bundle). Supported instruments have zero audio inputs, one mono output,
|
bundle). Supported instruments have zero audio inputs, one mono output, float32
|
||||||
float32 processing, zero latency and one note/event input. Default configuration
|
processing, zero latency and one note/event input. Default configuration only:
|
||||||
only: no custom editor, opaque state/preset restoration, modern parameter
|
no custom editor, opaque state/preset restoration, modern parameter
|
||||||
editing/automation, stereo/multichannel instruments or MIDI output. No arbitrary
|
editing/automation, stereo/multichannel instruments or MIDI output. No arbitrary
|
||||||
third-party instrument is qualified by the original ABI fixture tests.
|
third-party instrument is qualified by the original ABI fixture tests.
|
||||||
|
|
||||||
|
|
@ -168,14 +183,17 @@ the callback and old instances are reclaimed on the control thread. Missing
|
||||||
references remain inspectable without loading; failed GUI preparation retains
|
references remain inspectable without loading; failed GUI preparation retains
|
||||||
the current project. Save a backup for applications limited to v11 or earlier.
|
the current project. Save a backup for applications limited to v11 or earlier.
|
||||||
|
|
||||||
## Note dynamics and clip editing
|
---
|
||||||
|
|
||||||
|
## Note Dynamics and Clip Editing
|
||||||
|
|
||||||
Double-click a MIDI clip to open its piano roll. The Note velocity slider and
|
Double-click a MIDI clip to open its piano roll. The Note velocity slider and
|
||||||
fixed Velocity lane edit individual notes from 1 to 127, preserving timing,
|
fixed Velocity lane edit individual notes from 1 to 127, preserving timing,
|
||||||
pitch and channel. Chord notes at the same start can be selected individually in
|
pitch and channel. Chord notes at the same start can be selected individually in
|
||||||
the keys before editing their highlighted bar. Completed gestures are undoable
|
the keys before editing their highlighted bar. Completed gestures are undoable
|
||||||
and save in the existing note velocity field. Velocity is not a separate dB
|
and save in the existing note velocity field. Velocity is not a separate dB
|
||||||
volume stage: the built-in sine scales amplitude, while plugins choose their
|
volume stage: the built-in sine scales amplitude, while plugins choose their own
|
||||||
own patch-dependent response. The track header instrument dropdown reuses saved
|
patch-dependent response. The track header instrument dropdown reuses saved
|
||||||
project instruments or opens explicit loading; bus tracks cannot host instruments.
|
project instruments or opens explicit loading; bus tracks cannot host
|
||||||
See WORKSPACE.md for grid/snap divisions, filters and control behavior.
|
instruments. See WORKSPACE.md for grid/snap divisions, filters and control
|
||||||
|
behavior.
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,23 @@
|
||||||
# Application configuration and MIDI workflows
|
# Application Configuration and MIDI Workflows
|
||||||
|
|
||||||
`~/.xtc.conf` is the application's base configuration. It is read before creating
|
`~/.xtc.conf` is the application's base configuration. It is read before
|
||||||
its first project and backend. Missing keys use compiled defaults. Preferences
|
creating its first project and backend. Missing keys use compiled defaults.
|
||||||
Apply writes every tab atomically with owner-only permissions; clean exit also
|
Preferences Apply writes every tab atomically with owner-only permissions; clean
|
||||||
collects workspace, snap/zoom, loop, piano filters and note defaults. A missing
|
exit also collects workspace, snap/zoom, loop, piano filters and note defaults.
|
||||||
file is created on Apply or clean exit. Invalid files produce a visible startup
|
A missing file is created on Apply or clean exit. Invalid files produce a
|
||||||
error and are preserved until an explicit successful Apply replaces them. A save
|
visible startup error and are preserved until an explicit successful Apply
|
||||||
failure keeps the window open for retry. Project contents, plugin states and
|
replaces them. A save failure keeps the window open for retry. Project contents,
|
||||||
session clipboards are project/session data, not application preferences.
|
plugin states and session clipboards are project/session data, not application
|
||||||
|
preferences.
|
||||||
|
|
||||||
All persistent preference fields are listed by the shared C schema and available
|
All persistent preference fields are listed by the shared C schema and available
|
||||||
in Preferences. Existing project tempo/controller maps remain project data;
|
in Preferences. Existing project tempo/controller maps remain project data;
|
||||||
Preferences project defaults apply to New. No configuration I/O runs in an audio
|
Preferences project defaults apply to New. No configuration I/O runs in an audio
|
||||||
callback. Tests and screenshot captures use isolated configuration paths.
|
callback. Tests and screenshot captures use isolated configuration paths.
|
||||||
|
|
||||||
## MIDI backend
|
---
|
||||||
|
|
||||||
|
## MIDI Backend
|
||||||
|
|
||||||
xtc exposes `midi_in` and `midi_out` JACK ports. The output sends scheduled MIDI
|
xtc exposes `midi_in` and `midi_out` JACK ports. The output sends scheduled MIDI
|
||||||
clip notes from unmuted, solo-eligible tracks, retaining source channels and
|
clip notes from unmuted, solo-eligible tracks, retaining source channels and
|
||||||
|
|
@ -27,13 +30,16 @@ are outside this note-output workflow.
|
||||||
Input can filter a single channel, and output can preserve or force a channel.
|
Input can filter a single channel, and output can preserve or force a channel.
|
||||||
Optional thru forwards supported live notes, controllers and pitch bend while
|
Optional thru forwards supported live notes, controllers and pitch bend while
|
||||||
transport is active. Thru defaults off to avoid accidental feedback. Callback
|
transport is active. Thru defaults off to avoid accidental feedback. Callback
|
||||||
work and event buffers are bounded; overflow requests all-notes-off and increments
|
work and event buffers are bounded; overflow requests all-notes-off and
|
||||||
the MIDI-drop counter. Panic and stop send CC123 on all channels. Immediate stop
|
increments the MIDI-drop counter. Panic and stop send CC123 on all channels.
|
||||||
waits up to 100 ms for callback acknowledgement before deactivation; delivery
|
Immediate stop waits up to 100 ms for callback acknowledgement before
|
||||||
cannot be guaranteed after server/device loss or to devices ignoring CC123.
|
deactivation; delivery cannot be guaranteed after server/device loss or to
|
||||||
No device is connected unless a user chooses it or an external patchbay routes it.
|
devices ignoring CC123. No device is connected unless a user chooses it or an
|
||||||
|
external patchbay routes it.
|
||||||
|
|
||||||
## MIDI preferences
|
---
|
||||||
|
|
||||||
|
## MIDI Preferences
|
||||||
|
|
||||||
Preferences → midi has editable dropdowns for a default input source and output
|
Preferences → midi has editable dropdowns for a default input source and output
|
||||||
destination, plus a Refresh MIDI devices button. Names are enumerated from the
|
destination, plus a Refresh MIDI devices button. Names are enumerated from the
|
||||||
|
|
@ -42,26 +48,31 @@ field for no automatic connection. Typed offline names remain saved. Hardware
|
||||||
ports are visible only when the host exposes them through its MIDI bridge.
|
ports are visible only when the host exposes them through its MIDI bridge.
|
||||||
|
|
||||||
Input channel `-1` accepts all channels; `0..15` selects MIDI channel 1..16.
|
Input channel `-1` accepts all channels; `0..15` selects MIDI channel 1..16.
|
||||||
Output channel `-1` preserves note channels; `0..15` forces a channel. Thru defaults
|
Output channel `-1` preserves note channels; `0..15` forces a channel. Thru
|
||||||
off. Apply saves these choices; the next Play/Record restores the selected routes.
|
defaults off. Apply saves these choices; the next Play/Record restores the
|
||||||
A missing port rejects that start and stops the backend, preserving the saved
|
selected routes. A missing port rejects that start and stops the backend,
|
||||||
choice for retry. Reconnect audio after server loss, then retry Play. Defaults
|
preserving the saved choice for retry. Reconnect audio after server loss, then
|
||||||
also apply when playback resumes after a loop edit. MIDI input/thru currently
|
retry Play. Defaults also apply when playback resumes after a loop edit. MIDI
|
||||||
requires active transport. Existing editing and project_defaults tabs contain
|
input/thru currently requires active transport. Existing editing and
|
||||||
note length, velocity, channel, filters and new-project controller mappings.
|
project_defaults tabs contain note length, velocity, channel, filters and
|
||||||
|
new-project controller mappings.
|
||||||
|
|
||||||
## Export a selected clip
|
---
|
||||||
|
|
||||||
Select exactly one MIDI clip and choose File → Export selected clip as MIDI.
|
## Export A Selected Clip
|
||||||
The save chooser confirms overwrites. Export writes an atomic Standard MIDI File
|
|
||||||
(type 0, 960 PPQN) with project tempo, clip name and audible notes relative to the
|
|
||||||
clip start, retaining channels and velocities. Notes crossing trimmed boundaries
|
|
||||||
are cropped and notes outside the trim are omitted. Trailing silence remains.
|
|
||||||
Export does not edit the project or undo history. Audio clips reject. Only note
|
|
||||||
messages are exported: instruments, opaque plugin data, controller maps,
|
|
||||||
automation and audio are excluded. Export is unavailable during recording.
|
|
||||||
|
|
||||||
## Import MIDI files
|
Select exactly one MIDI clip and choose File → Export selected clip as MIDI. The
|
||||||
|
save chooser confirms overwrites. Export writes an atomic Standard MIDI File
|
||||||
|
(type 0, 960 PPQN) with project tempo, clip name and audible notes relative to
|
||||||
|
the clip start, retaining channels and velocities. Notes crossing trimmed
|
||||||
|
boundaries are cropped and notes outside the trim are omitted. Trailing silence
|
||||||
|
remains. Export does not edit the project or undo history. Audio clips reject.
|
||||||
|
Only note messages are exported: instruments, opaque plugin data, controller
|
||||||
|
maps, automation and audio are excluded. Export is unavailable during recording.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Import MIDI Files
|
||||||
|
|
||||||
File → Import MIDI (also in the sequencer Create menu) adds a clip at the cursor
|
File → Import MIDI (also in the sequencer Create menu) adds a clip at the cursor
|
||||||
on the selected non-bus track, or creates a track when none is selected. Import
|
on the selected non-bus track, or creates a track when none is selected. Import
|
||||||
|
|
@ -71,17 +82,18 @@ backend preparation retain the old project and IDs.
|
||||||
The reader supports Standard MIDI File types 0 and 1 with PPQN timing, including
|
The reader supports Standard MIDI File types 0 and 1 with PPQN timing, including
|
||||||
running status and velocity-zero note-offs. File tracks merge into one clip;
|
running status and velocity-zero note-offs. File tracks merge into one clip;
|
||||||
channels and velocities remain. Timing rounds to 960 ticks per quarter note,
|
channels and velocities remain. Timing rounds to 960 ticks per quarter note,
|
||||||
with positive sub-tick notes given one tick. Trailing silence remains. The project
|
with positive sub-tick notes given one tick. Trailing silence remains. The
|
||||||
tempo is retained: tempo maps, time signatures, CC/sustain, program changes,
|
project tempo is retained: tempo maps, time signatures, CC/sustain, program
|
||||||
pitch bend, SysEx and other metadata are not imported. This is a notes workflow,
|
changes, pitch bend, SysEx and other metadata are not imported. This is a notes
|
||||||
not full-song or instrument reconstruction.
|
workflow, not full-song or instrument reconstruction.
|
||||||
|
|
||||||
Limits are 1 MiB per file, 64 file tracks, 65,536 parsed events and 4,096 notes
|
Limits are 1 MiB per file, 64 file tracks, 65,536 parsed events and 4,096 notes
|
||||||
within the project's total note capacity. SMPTE timing and type 2 reject explicitly.
|
within the project's total note capacity. SMPTE timing and type 2 reject
|
||||||
Unterminated notes, zero source duration and malformed events reject rather than
|
explicitly. Unterminated notes, zero source duration and malformed events reject
|
||||||
silently dropping notes. Unmatched note-offs are harmless and ignored. Overlapping
|
rather than silently dropping notes. Unmatched note-offs are harmless and
|
||||||
same-pitch notes pair FIFO within each file track/channel. Project save/reload
|
ignored. Overlapping same-pitch notes pair FIFO within each file track/channel.
|
||||||
uses the existing format; no format migration or extra dependency is required.
|
Project save/reload uses the existing format; no format migration or extra
|
||||||
|
dependency is required.
|
||||||
|
|
||||||
Configured startup holds the transport clock and emits silence until selected
|
Configured startup holds the transport clock and emits silence until selected
|
||||||
MIDI ports are connected, so notes at the song start are not consumed before
|
MIDI ports are connected, so notes at the song start are not consumed before
|
||||||
|
|
|
||||||
225
docs/MIXER.md
225
docs/MIXER.md
|
|
@ -1,42 +1,46 @@
|
||||||
# Studio mixer
|
# Studio Mixer
|
||||||
|
|
||||||
Open **View / Mixer** (Ctrl+2) to see a channel strip for every track and bus.
|
Open **View / Mixer** (Ctrl+2) to see a channel strip for every track and bus.
|
||||||
The horizontal scrollbar reveals additional channels; the master output monitor
|
The horizontal scrollbar reveals additional channels; the master output monitor
|
||||||
stays pinned on the right. The bank supports the full 64-track/bus project limit.
|
stays pinned on the right. The bank supports the full 64-track/bus project
|
||||||
Channel order follows the sequencer, and colors match the track headers.
|
limit. Channel order follows the sequencer, and colors match the track headers.
|
||||||
|
|
||||||
Each strip offers:
|
Each strip offers:
|
||||||
|
|
||||||
- A name button that selects its track for automation below the bank.
|
- A name button that selects its track for automation below the bank.
|
||||||
- **Mute** and **Solo** switches using the existing inclusive track/bus solo rules.
|
- **Mute** and **Solo** switches using the existing inclusive track/bus solo
|
||||||
|
rules.
|
||||||
- A flat **Pan** knob: left -1, center 0, right +1. Drag to turn it;
|
- A flat **Pan** knob: left -1, center 0, right +1. Drag to turn it;
|
||||||
double-click to center. The text shows direction and percentage.
|
double-click to center. The text shows direction and percentage.
|
||||||
- An output dropdown for **Master** or a project bus. Bus outputs stay at Master;
|
- An output dropdown for **Master** or a project bus. Bus outputs stay at
|
||||||
nested bus routing remains unsupported. **Add bus** creates a new bus strip.
|
Master; nested bus routing remains unsupported. **Add bus** creates a new bus
|
||||||
- A vertical level fader, displayed in dB. Zero dB is unity gain. The upper limit
|
strip.
|
||||||
is approximately +12.04 dB (linear gain 4); the -60 dB bottom position is silence.
|
- A vertical level fader, displayed in dB. Zero dB is unity gain. The upper
|
||||||
|
limit is approximately +12.04 dB (linear gain 4); the -60 dB bottom position
|
||||||
|
is silence.
|
||||||
- Independent stereo sample-peak meters, numeric dBFS readouts and sticky clip
|
- Independent stereo sample-peak meters, numeric dBFS readouts and sticky clip
|
||||||
indications. **Reset peaks** clears all strip and master clip latches.
|
indications. **Reset peaks** clears all strip and master clip latches.
|
||||||
|
|
||||||
Changing a fader or knob commits on release, so a completed gesture is one undo
|
Changing a fader or knob commits on release, so a completed gesture is one undo
|
||||||
step. The existing preparation guard stops playback before model edits and
|
step. The existing preparation guard stops playback before model edits and
|
||||||
rejects changes while recording. Failed edits restore the displayed model values.
|
rejects changes while recording. Failed edits restore the displayed model
|
||||||
Selections are UI state and create no undo step. Track IDs keep controls attached
|
values. Selections are UI state and create no undo step. Track IDs keep controls
|
||||||
to the correct channel after reordering, undo, deletion or project replacement.
|
attached to the correct channel after reordering, undo, deletion or project
|
||||||
|
replacement.
|
||||||
|
|
||||||
The top Track selector provides another way to select automation targets; the
|
The top Track selector provides another way to select automation targets; the
|
||||||
bank scrolls to reveal the selection. M/S toggle the selected track's mute/solo,
|
bank scrolls to reveal the selection. M/S toggle the selected track's mute/solo,
|
||||||
Left/Right adjust its linear gain, Shift+Left/Right adjust pan, and Up/Down select
|
Left/Right adjust its linear gain, Shift+Left/Right adjust pan, and Up/Down
|
||||||
adjacent tracks. The existing automation controls below the bank retain Gain/Pan,
|
select adjacent tracks. The existing automation controls below the bank retain
|
||||||
First tick and Linear/Hold interpolation. Click to add a point and right-click
|
Gain/Pan, First tick and Linear/Hold interpolation. Click to add a point and
|
||||||
near a point to remove it.
|
right-click near a point to remove it.
|
||||||
|
|
||||||
Faders and knobs display **static** mix values. Automation replaces those values
|
Faders and knobs display **static** mix values. Automation replaces those values
|
||||||
during playback; the controls are not motorized automation displays. Automation
|
during playback; the controls are not motorized automation displays. Automation
|
||||||
values retain their existing linear gain and pan units. Existing project files
|
values retain their existing linear gain and pan units. Existing project files
|
||||||
store mix values and automation without a format change. Very small nonzero
|
store mix values and automation without a format change. Very small nonzero
|
||||||
gains display at the fader floor; pan/mute/solo edits preserve their actual value.
|
gains display at the fader floor; pan/mute/solo edits preserve their actual
|
||||||
Moving the fader to its bottom explicitly sets silence.
|
value. Moving the fader to its bottom explicitly sets silence.
|
||||||
|
|
||||||
Meters use the backend's consumed peak snapshot for every track and bus,
|
Meters use the backend's consumed peak snapshot for every track and bus,
|
||||||
including offscreen channels. Track taps are after track controls and before the
|
including offscreen channels. Track taps are after track controls and before the
|
||||||
|
|
@ -44,41 +48,49 @@ bus, bus taps follow bus controls, and the master follows the modular graph and
|
||||||
transport envelope. Missing taps decay to silence. Displays use instant attack,
|
transport envelope. Missing taps decay to silence. Displays use instant attack,
|
||||||
20 dB/s release and sticky clipping at a linear sample peak of 1 or more.
|
20 dB/s release and sticky clipping at a linear sample peak of 1 or more.
|
||||||
Numeric displays have a -90 dBFS floor, channel bars a -60 dBFS floor; master
|
Numeric displays have a -90 dBFS floor, channel bars a -60 dBFS floor; master
|
||||||
bars cover -90 to +6 dBFS. These are sample-peak meters, not loudness or true-peak
|
bars cover -90 to +6 dBFS. These are sample-peak meters, not loudness or
|
||||||
meters. The master strip is an output monitor, not a new gain control.
|
true-peak meters. The master strip is an output monitor, not a new gain control.
|
||||||
|
|
||||||
## Engine mixing behavior
|
---
|
||||||
|
|
||||||
Gain is a linear multiplier from 0 to 4. Pan ranges from -1 (left) to +1 (right):
|
## Engine Mixing Behavior
|
||||||
center has unity on both sides and moving away attenuates the opposite side
|
|
||||||
linearly. This preserves existing centered mono levels; it is not an equal-power
|
|
||||||
pan law. Mute wins over Solo. Solo behavior across tracks and buses is defined below. WAV clips and scheduled MIDI use their containing track's settings before
|
|
||||||
summing into the audio/instrument graph sources. Live MIDI input and independent
|
|
||||||
graph oscillators/external input are unassigned sources and bypass track mixing.
|
|
||||||
Stereo WAV files are still downmixed at import; stereo output comes from panning
|
|
||||||
those mono sources. Separate per-track graph inserts/sends are deferred.
|
|
||||||
|
|
||||||
## Automation lanes
|
Gain is a linear multiplier from 0 to 4. Pan ranges from -1 (left) to +1
|
||||||
|
(right): center has unity on both sides and moving away attenuates the opposite
|
||||||
|
side linearly. This preserves existing centered mono levels; it is not an
|
||||||
|
equal-power pan law. Mute wins over Solo. Solo behavior across tracks and buses
|
||||||
|
is defined below. WAV clips and scheduled MIDI use their containing track's
|
||||||
|
settings before summing into the audio/instrument graph sources. Live MIDI input
|
||||||
|
and independent graph oscillators/external input are unassigned sources and
|
||||||
|
bypass track mixing. Stereo WAV files are still downmixed at import; stereo
|
||||||
|
output comes from panning those mono sources. Separate per-track graph
|
||||||
|
inserts/sends are deferred.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Automation Lanes
|
||||||
|
|
||||||
Choose Gain or Pan under Automation. The lane shows four bars (15360 ticks);
|
Choose Gain or Pan under Automation. The lane shows four bars (15360 ticks);
|
||||||
First tick moves its viewport across the project. Grid labels are absolute ticks.
|
First tick moves its viewport across the project. Grid labels are absolute
|
||||||
Click to add a point or replace the point at that snapped time (1/16 note, 240
|
ticks. Click to add a point or replace the point at that snapped time (1/16
|
||||||
ticks). Vertical position maps to gain 0..4 or pan -1..1, top to bottom descending.
|
note, 240 ticks). Vertical position maps to gain 0..4 or pan -1..1, top to
|
||||||
Right-click near a point's time to remove it. Removing every point restores the
|
bottom descending. Right-click near a point's time to remove it. Removing every
|
||||||
static control. There are at most 1024 points globally, with one per
|
point restores the static control. There are at most 1024 points globally, with
|
||||||
track/parameter/tick. Track deletion cascades to its automation.
|
one per track/parameter/tick. Track deletion cascades to its automation.
|
||||||
|
|
||||||
A nonempty lane replaces that parameter's static value. Between points the C
|
A nonempty lane replaces that parameter's static value. Between points the C
|
||||||
engine interpolates linearly or holds each segment (Interpolation chooser),
|
engine interpolates linearly or holds each segment (Interpolation chooser),
|
||||||
holding the first/last value outside
|
holding the first/last value outside their range. Preparation converts ticks to
|
||||||
their range. Preparation converts ticks to integer sample endpoints, sorts and
|
integer sample endpoints, sorts and indexes lanes. When several ticks quantize
|
||||||
indexes lanes. When several ticks quantize to one sample at very low sample
|
to one sample at very low sample rates, the last point wins at that sample.
|
||||||
rates, the last point wins at that sample. Rendering searches prepared bounded
|
Rendering searches prepared bounded arrays; it never sorts, allocates, accesses
|
||||||
arrays; it never sorts, allocates, accesses project data, or calls the GUI.
|
project data, or calls the GUI. Seeking and block partitioning give the same
|
||||||
Seeking and block partitioning give the same timeline values. Mute/solo are
|
timeline values. Mute/solo are static; automation capture, modes, curves and
|
||||||
static; automation capture, modes, curves and tempo automation are deferred.
|
tempo automation are deferred.
|
||||||
|
|
||||||
## Stereo output and meters
|
---
|
||||||
|
|
||||||
|
## Stereo Output and Meters
|
||||||
|
|
||||||
The GUI opens the JACK backend with two audio output ports: `output` (left) and
|
The GUI opens the JACK backend with two audio output ports: `output` (left) and
|
||||||
`output_right`. Input and raw WAV recording remain mono. Connect both outputs
|
`output_right`. Input and raw WAV recording remain mono. Connect both outputs
|
||||||
|
|
@ -89,30 +101,34 @@ port. Old mono audio/MIDI render functions apply gain/mute/solo and gain
|
||||||
automation while ignoring pan; the stereo variants apply both lanes.
|
automation while ignoring pan; the stereo variants apply both lanes.
|
||||||
|
|
||||||
The graph executes the same topology separately on left and right buses;
|
The graph executes the same topology separately on left and right buses;
|
||||||
oscillators advance once per frame and are centered on both sides. Existing
|
oscillators advance once per frame and are centered on both sides. Existing port
|
||||||
port metadata and validation describe the mono graph topology. Stereo processing
|
metadata and validation describe the mono graph topology. Stereo processing uses
|
||||||
uses explicit paired buffers, not new port IDs. Output buffers must be distinct;
|
explicit paired buffers, not new port IDs. Output buffers must be distinct;
|
||||||
stereo callers must not alias them with source buffers. Graph-node meter reads
|
stereo callers must not alias them with source buffers. Graph-node meter reads
|
||||||
report the maximum of both sides on the processing owner only.
|
report the maximum of both sides on the processing owner only.
|
||||||
|
|
||||||
Track and bus meters measure coherent audio plus scheduled MIDI sums, after their
|
Track and bus meters measure coherent audio plus scheduled MIDI sums, after
|
||||||
own gain/pan/mute/solo controls, before the shared modular graph. A track tap is
|
their own gain/pan/mute/solo controls, before the shared modular graph. A track
|
||||||
before its parent bus: a muted bus can have active member-track meters. Bus taps
|
tap is before its parent bus: a muted bus can have active member-track meters.
|
||||||
are after bus controls. Master L/R measure the final graph output after transport
|
Bus taps are after bus controls. Master L/R measure the final graph output after
|
||||||
fades; downstream effects and graph routing can change its level independently.
|
transport fades; downstream effects and graph routing can change its level
|
||||||
|
independently.
|
||||||
|
|
||||||
The backend retains interval sample-peak maxima until one serialized control
|
The backend retains interval sample-peak maxima until one serialized control
|
||||||
reader consumes them with `xtc_backend_read_meters`. The GUI polls about every
|
reader consumes them with `xtc_backend_read_meters`. The GUI polls about every
|
||||||
100 ms. Atomic channels are independent (not a simultaneous waveform snapshot);
|
100 ms. Atomic channels are independent (not a simultaneous waveform snapshot);
|
||||||
peaks are quantized to 0.000001 linear and capped at 1000. Legacy backend status
|
peaks are quantized to 0.000001 linear and capped at 1000. Legacy backend status
|
||||||
peaks remain last-block linear values. GUI readouts display 20*log10(peak) dBFS, floor -90, with instantaneous
|
peaks remain last-block linear values. GUI readouts display 20*log10(peak) dBFS,
|
||||||
attack and 20 dB/second release. Channel bars cover -60 to +6 dBFS; master
|
floor -90, with instantaneous attack and 20 dB/second release. Channel bars
|
||||||
bars cover -90 to +6 dBFS.
|
cover -60 to +6 dBFS; master bars cover -90 to +6 dBFS. Each channel latches red
|
||||||
Each channel latches red CLIP at linear peak >=1 (0 dBFS) until Reset peaks.
|
CLIP at linear peak >=1 (0 dBFS) until Reset peaks. Reset is session state, not
|
||||||
Reset is session state, not an audio edit. Selection changes preserve every strip's meter history. These are sample-peak meters, not RMS, LUFS or true-peak measurements.
|
an audio edit. Selection changes preserve every strip's meter history. These are
|
||||||
There is no limiter; summed levels can exceed unity.
|
sample-peak meters, not RMS, LUFS or true-peak measurements. There is no
|
||||||
|
limiter; summed levels can exceed unity.
|
||||||
|
|
||||||
## Mix buses and gain staging
|
---
|
||||||
|
|
||||||
|
## Mix Buses and Gain Staging
|
||||||
|
|
||||||
Use Add bus in Mixer, select an ordinary track, then choose its Route: Master or
|
Use Add bus in Mixer, select an ordinary track, then choose its Route: Master or
|
||||||
an existing bus. Buses share the 64-track capacity and gain/pan automation APIs.
|
an existing bus. Buses share the 64-track capacity and gain/pan automation APIs.
|
||||||
|
|
@ -123,42 +139,45 @@ routing. Editing uses the existing stopped-transport preparation workflow.
|
||||||
Track controls apply first, then parent bus controls, then the shared graph.
|
Track controls apply first, then parent bus controls, then the shared graph.
|
||||||
Gain multiplies (track 2 times bus 2 gives 4); pan uses the same center-unity
|
Gain multiplies (track 2 times bus 2 gives 4); pan uses the same center-unity
|
||||||
balance law at both stages. There is no normalization or automatic attenuation.
|
balance law at both stages. There is no normalization or automatic attenuation.
|
||||||
Solo is one inclusive domain: a soloed track passes through its bus, a soloed bus
|
Solo is one inclusive domain: a soloed track passes through its bus, a soloed
|
||||||
admits all its members, and unrelated tracks are silent. Track mute silences
|
bus admits all its members, and unrelated tracks are silent. Track mute silences
|
||||||
that member; bus mute silences its entire output even when a member is soloed.
|
that member; bus mute silences its entire output even when a member is soloed.
|
||||||
Live MIDI, external audio inputs and independent graph oscillators remain
|
Live MIDI, external audio inputs and independent graph oscillators remain
|
||||||
unassigned and outside this solo domain.
|
unassigned and outside this solo domain.
|
||||||
|
|
||||||
Master here means the source mix feeding the shared graph, not independent
|
Master here means the source mix feeding the shared graph, not independent
|
||||||
per-bus effect chains. Graph fan-out and gain branches permit parallel processing
|
per-bus effect chains. Graph fan-out and gain branches permit parallel
|
||||||
of shared sources. Independent per-track aux sends, sidechains, bus plugin
|
processing of shared sources. Independent per-track aux sends, sidechains, bus
|
||||||
inserts and nested buses are not represented and remain deferred.
|
plugin inserts and nested buses are not represented and remain deferred.
|
||||||
|
|
||||||
Preparation allocates shared stereo monitor scratch on the control thread:
|
Preparation allocates shared stereo monitor scratch on the control thread: 2 *
|
||||||
2 * track_count * max_frames * sizeof(float), at most 32 MiB at current limits.
|
track_count * max_frames * sizeof(float), at most 32 MiB at current limits. The
|
||||||
The callback clears, accumulates and scans bounded buffers, with no allocation,
|
callback clears, accumulates and scans bounded buffers, with no allocation, I/O,
|
||||||
I/O, locks or GUI calls. Immutable audio/MIDI snapshots borrow this scratch until
|
locks or GUI calls. Immutable audio/MIDI snapshots borrow this scratch until
|
||||||
stopped replacement or backend destruction.
|
stopped replacement or backend destruction.
|
||||||
|
|
||||||
## Undo and keyboard workflow
|
---
|
||||||
|
|
||||||
Ctrl+Z undoes; Ctrl+Shift+Z or Ctrl+Y redoes. The C history keeps 32 project edits
|
## Undo and Keyboard Workflow
|
||||||
plus a baseline, cloning metadata and graph, never audio samples. Common graph,
|
|
||||||
track, clip, note, mixer, import/relink and automation edits are included. One
|
Ctrl+Z undoes; Ctrl+Shift+Z or Ctrl+Y redoes. The C history keeps 32 project
|
||||||
accepted gesture is one step; selection, scrolling and graph-node placement are
|
edits plus a baseline, cloning metadata and graph, never audio samples. Common
|
||||||
GUI state and are not undoable. New/Open resets history; Save retains it.
|
graph, track, clip, note, mixer, import/relink and automation edits are
|
||||||
Undo/redo stops and resets transport; surviving selections are preserved by
|
included. One accepted gesture is one step; selection, scrolling and graph-node
|
||||||
stable ID (layout remains session state). The
|
placement are GUI state and are not undoable. New/Open resets history; Save
|
||||||
candidate is installed before moving the history cursor: validation, asset-plan
|
retains it. Undo/redo stops and resets transport; surviving selections are
|
||||||
or backend failure retains the current document and history position. Missing
|
preserved by stable ID (layout remains session state). The candidate is
|
||||||
assets retain the existing silent/reporting behavior. A new edit after Undo
|
installed before moving the history cursor: validation, asset-plan or backend
|
||||||
removes the redo branch; the oldest state is evicted at capacity. Allocation
|
failure retains the current document and history position. Missing assets retain
|
||||||
ID high-water marks survive Undo/branching so abandoned IDs are not reused. History is
|
the existing silent/reporting behavior. A new edit after Undo removes the redo
|
||||||
session-only and Undo marks the document dirty even if it matches a saved state.
|
branch; the oldest state is evicted at capacity. Allocation ID high-water marks
|
||||||
External WAV files are never deleted or restored by Undo; recording itself cannot
|
survive Undo/branching so abandoned IDs are not reused. History is session-only
|
||||||
be undone while active. Snapshot storage is reserved before GUI commands mutate/publish, so an
|
and Undo marks the document dirty even if it matches a saved state. External WAV
|
||||||
allocation failure rejects the command before adoption; reserved capture itself
|
files are never deleted or restored by Undo; recording itself cannot be undone
|
||||||
does not allocate. C clients using unreserved history record must handle errors.
|
while active. Snapshot storage is reserved before GUI commands mutate/publish,
|
||||||
|
so an allocation failure rejects the command before adoption; reserved capture
|
||||||
|
itself does not allocate. C clients using unreserved history record must handle
|
||||||
|
errors.
|
||||||
|
|
||||||
With mixer focus, M/S toggles mute/solo, Left/Right changes gain by 0.05,
|
With mixer focus, M/S toggles mute/solo, Left/Right changes gain by 0.05,
|
||||||
Shift+Left/Right changes pan, and Up/Down selects a track. Native sliders also
|
Shift+Left/Right changes pan, and Up/Down selects a track. Native sliders also
|
||||||
|
|
@ -168,30 +187,34 @@ singly selected; automation-point dragging is not implemented. Track rename and
|
||||||
arrangement clipboard editing are available. See MODERN_EDITING.md for static
|
arrangement clipboard editing are available. See MODERN_EDITING.md for static
|
||||||
mixer A/B comparison and its automation limits.
|
mixer A/B comparison and its automation limits.
|
||||||
|
|
||||||
## Verification and limits
|
---
|
||||||
|
|
||||||
|
## Verification and Limits
|
||||||
|
|
||||||
`test_mixer` verifies exact stereo gain/pan, mute/solo precedence, automation
|
`test_mixer` verifies exact stereo gain/pan, mute/solo precedence, automation
|
||||||
samples and block equivalence, stereo graph phase/routing, WAV mixing, v4 exact
|
samples and block equivalence, stereo graph phase/routing, WAV mixing, v4 exact
|
||||||
roundtrip/truncations/malformed records, lane capacities and history eviction and
|
roundtrip/truncations/malformed records, lane capacities and history eviction
|
||||||
branching. Backend fault injection verifies stereo registration failure, output
|
and branching. Backend fault injection verifies stereo registration failure,
|
||||||
names, output separation and atomic meters. GUI tests edit lanes with mouse
|
output names, output separation and atomic meters. GUI tests edit lanes with
|
||||||
events, use mixer keys and exercise undo/redo, failed installation rollback,
|
mouse events, use mixer keys and exercise undo/redo, failed installation
|
||||||
branching, save/reopen and history reset. Live JACK MIDI acceptance verifies
|
rollback, branching, save/reopen and history reset. Live JACK MIDI acceptance
|
||||||
saved/reopened hard-right playback and stereo peaks using only software clients.
|
verifies saved/reopened hard-right playback and stereo peaks using only software
|
||||||
A native Xvfb mouse smoke check covers sliders and automation drawing.
|
clients. A native Xvfb mouse smoke check covers sliders and automation drawing.
|
||||||
Checks cover independent strip callbacks/meters, fader gestures, pan
|
Checks cover independent strip callbacks/meters, fader gestures, pan centering,
|
||||||
centering, failed-edit restoration, routing, undo/reload, duplicate names and
|
failed-edit restoration, routing, undo/reload, duplicate names and stable IDs
|
||||||
stable IDs across reorder/removal. A 64-channel GUI session verifies scrolling
|
across reorder/removal. A 64-channel GUI session verifies scrolling and
|
||||||
and minimum/large layouts. Screenshots include live JACK meters and a bus strip.
|
minimum/large layouts. Screenshots include live JACK meters and a bus strip.
|
||||||
|
|
||||||
Physical stereo devices, listening quality, realtime endurance and high-density
|
Physical stereo devices, listening quality, realtime endurance and high-density
|
||||||
project performance remain unverified; no new dependency was introduced.
|
project performance remain unverified; no new dependency was introduced.
|
||||||
|
|
||||||
`test_buses` covers bus routing, exact taps, audio/MIDI cancellation, controls,
|
`test_buses` covers bus routing, exact taps, audio/MIDI cancellation, controls,
|
||||||
automation, persistence, invalid routes, deletion/undo and dBFS ballistics. Backend
|
automation, persistence, invalid routes, deletion/undo and dBFS ballistics.
|
||||||
tests cover consuming interval peaks; GUI tests cover routing undo and clipping.
|
Backend tests cover consuming interval peaks; GUI tests cover routing undo and
|
||||||
|
clipping.
|
||||||
|
|
||||||
Linear/Hold interpolation is available for each point added or replaced. The
|
Linear/Hold interpolation is available for each point added or replaced. The
|
||||||
point's mode applies to its following segment. Static controls remain fallbacks
|
point's mode applies to its following segment. Static controls remain fallbacks
|
||||||
while a lane exists; moving/splitting clips does not move absolute track/bus lanes.
|
while a lane exists; moving/splitting clips does not move absolute track/bus
|
||||||
See CONTROL.md for common parameter IDs and controller/automation precedence.
|
lanes. See CONTROL.md for common parameter IDs and controller/automation
|
||||||
|
precedence.
|
||||||
|
|
|
||||||
|
|
@ -1,57 +1,127 @@
|
||||||
# Modern editing workflows
|
# Modern Editing Workflows
|
||||||
|
|
||||||
These control-thread edits were introduced without changing format 15.
|
These control-thread edits were introduced without changing format 15. The
|
||||||
The current writer uses format 16 for arrangement markers and still reads older projects. Session selections,
|
current writer uses format 16 for arrangement markers and still reads older
|
||||||
clipboard and comparison snapshots are not saved in projects. Audio callbacks
|
projects. Session selections, clipboard and comparison snapshots are not saved
|
||||||
continue to consume prepared plans; edits use the existing stop/history workflow.
|
in projects. Audio callbacks continue to consume prepared plans; edits use the
|
||||||
|
existing stop/history workflow.
|
||||||
|
|
||||||
## Arrangement Multi-selection
|
---
|
||||||
|
|
||||||
Shift-click clips to toggle selection; Ctrl+A in the sequencer or Edit/Select all clips selects every clip. Plain clicking replaces the selection. Selection is session UI state; no marquee selection yet.
|
## Arrangement Multi-Selection
|
||||||
|
|
||||||
|
Shift-click clips to toggle selection; Ctrl+A in the sequencer or Edit/Select
|
||||||
|
all clips selects every clip. Plain clicking replaces the selection. Selection
|
||||||
|
is session UI state; no marquee selection yet.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Transactional Group Editing
|
## Transactional Group Editing
|
||||||
|
|
||||||
Use Left/Right in the sequencer (or Edit/Nudge selection) to move the selected phrase by the current snap step. Ctrl+D duplicates after its complete bounding span; Delete removes selected clips. Edits are atomic and undoable. Mouse dragging remains a single-clip gesture.
|
Use Left/Right in the sequencer (or Edit/Nudge selection) to move the selected
|
||||||
|
phrase by the current snap step. Ctrl+D duplicates after its complete bounding
|
||||||
|
span; Delete removes selected clips. Edits are atomic and undoable. Mouse
|
||||||
|
dragging remains a single-clip gesture.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Arrangement Clipboard
|
## Arrangement Clipboard
|
||||||
|
|
||||||
Ctrl+C/Ctrl+V in the sequencer, or Edit/Copy clips and Paste clips at cursor, copy/paste the selection. Earliest clip lands on the cursor. The earliest source track maps to the currently selected destination track; intervening track spacing is retained. All required tracks must already exist and must not be buses. Instruments, automation and media bytes are not copied. The clipboard survives document changes within the window but is not the OS clipboard.
|
Ctrl+C/Ctrl+V in the sequencer, or Edit/Copy clips and Paste clips at cursor,
|
||||||
|
copy/paste the selection. Earliest clip lands on the cursor. The earliest source
|
||||||
|
track maps to the currently selected destination track; intervening track
|
||||||
|
spacing is retained. All required tracks must already exist and must not be
|
||||||
|
buses. Instruments, automation and media bytes are not copied. The clipboard
|
||||||
|
survives document changes within the window but is not the OS clipboard.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Repeat Arrangement Patterns
|
## Repeat Arrangement Patterns
|
||||||
|
|
||||||
Edit/Repeat selected phrase asks for 1..1024 additional copies. The bounding span includes gaps and overlaps; copies remain on their original tracks. The entire repeat is one undo step. Clip/note capacity and timeline endpoints can limit the requested count.
|
Edit/Repeat selected phrase asks for 1..1024 additional copies. The bounding
|
||||||
|
span includes gaps and overlaps; copies remain on their original tracks. The
|
||||||
|
entire repeat is one undo step. Clip/note capacity and timeline endpoints can
|
||||||
|
limit the requested count.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Align and Slip Editing
|
## Align and Slip Editing
|
||||||
|
|
||||||
Edit/Align clip starts to cursor places every selected start at the cursor. Slip sources earlier/later changes source offsets by the snap step while retaining timeline positions and durations. Trimming must leave source material available; an invalid slip rejects the whole selection. No time stretching or destructive media edits are performed.
|
Edit/Align clip starts to cursor places every selected start at the cursor. Slip
|
||||||
|
sources earlier/later changes source offsets by the snap step while retaining
|
||||||
|
timeline positions and durations. Trimming must leave source material available;
|
||||||
|
an invalid slip rejects the whole selection. No time stretching or destructive
|
||||||
|
media edits are performed.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## MIDI Swing Quantization
|
## MIDI Swing Quantization
|
||||||
|
|
||||||
Select MIDI clips and use Edit/MIDI tools/Swing quantize. Grid is in source ticks; swing delays alternate subdivisions by 0..half a grid step, while strength blends the old start toward the nearest swung point. Durations stay fixed. All source notes are affected, including notes outside visible trims. Mixed audio/MIDI selections and notes that would exceed source bounds reject the entire edit. This is destructive note editing with undo, not a live groove engine.
|
Select MIDI clips and use Edit/MIDI tools/Swing quantize. Grid is in source
|
||||||
|
ticks; swing delays alternate subdivisions by 0..half a grid step, while
|
||||||
|
strength blends the old start toward the nearest swung point. Durations stay
|
||||||
|
fixed. All source notes are affected, including notes outside visible trims.
|
||||||
|
Mixed audio/MIDI selections and notes that would exceed source bounds reject the
|
||||||
|
entire edit. This is destructive note editing with undo, not a live groove
|
||||||
|
engine.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## MIDI Legato and Gate Tools
|
## MIDI Legato and Gate Tools
|
||||||
|
|
||||||
Edit/MIDI tools/Note gate scales lengths from 1 to 400 percent, rounded to at least one tick. Legato ends notes at the next strictly later onset in the same clip and channel; notes in a chord end together. The final onset extends to source end. Gate expansion beyond the source rejects the whole edit. Undo restores original durations.
|
Edit/MIDI tools/Note gate scales lengths from 1 to 400 percent, rounded to at
|
||||||
|
least one tick. Legato ends notes at the next strictly later onset in the same
|
||||||
|
clip and channel; notes in a chord end together. The final onset extends to
|
||||||
|
source end. Gate expansion beyond the source rejects the whole edit. Undo
|
||||||
|
restores original durations.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## MIDI Scale Correction
|
## MIDI Scale Correction
|
||||||
|
|
||||||
Edit/MIDI tools/Correct to scale takes a root (0=C through 11=B) and chromatic, major or natural minor. Each pitch moves to the nearest permitted MIDI note; ties choose the lower pitch. Timing, channel and velocity remain unchanged. Corrections can produce unison notes; notes are not merged. This changes MIDI notes, not audio pitch or a live scale filter.
|
Edit/MIDI tools/Correct to scale takes a root (0=C through 11=B) and chromatic,
|
||||||
|
major or natural minor. Each pitch moves to the nearest permitted MIDI note;
|
||||||
|
ties choose the lower pitch. Timing, channel and velocity remain unchanged.
|
||||||
|
Corrections can produce unison notes; notes are not merged. This changes MIDI
|
||||||
|
notes, not audio pitch or a live scale filter.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## MIDI Velocity Shaping
|
## MIDI Velocity Shaping
|
||||||
|
|
||||||
Edit/MIDI tools/Shape velocities scales from 0 to 400 percent, rounds, then applies an offset from -127 to 127. Results clamp to 1..127, keeping every note audible rather than introducing velocity-zero note-offs. Use 0 percent with a positive offset for a fixed velocity. No randomization is applied.
|
Edit/MIDI tools/Shape velocities scales from 0 to 400 percent, rounds, then
|
||||||
|
applies an offset from -127 to 127. Results clamp to 1..127, keeping every note
|
||||||
|
audible rather than introducing velocity-zero note-offs. Use 0 percent with a
|
||||||
|
positive offset for a fixed velocity. No randomization is applied.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Batch Audio Fade Tools
|
## Batch Audio Fade Tools
|
||||||
|
|
||||||
Edit/Audio tools/Set boundary fades sets linear fade-in and fade-out lengths in ticks; 0 or Remove boundary fades clears them. Each fade must fit within half of every selected clip duration. Gain and source offsets stay unchanged. These are boundary envelopes, not overlap-aware crossfades, equal-power curves or destructive WAV processing.
|
Edit/Audio tools/Set boundary fades sets linear fade-in and fade-out lengths in
|
||||||
|
ticks; 0 or Remove boundary fades clears them. Each fade must fit within half of
|
||||||
|
every selected clip duration. Gain and source offsets stay unchanged. These are
|
||||||
|
boundary envelopes, not overlap-aware crossfades, equal-power curves or
|
||||||
|
destructive WAV processing.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Mixer A/B Comparison
|
## Mixer A/B Comparison
|
||||||
|
|
||||||
Edit/Mixer comparison captures or recalls A and B. Capture stores static gain, pan, mute and solo for every track and bus without changing the document. Recall requires the same stable track IDs, stops playback through the normal edit guard and creates one undo step. Track order may change. Routing, plugins and automation are excluded; automation still overrides static gain and pan. Slots are session-only and clear on New/Open. This is static mix comparison, not seamless live scene morphing.
|
Edit/Mixer comparison captures or recalls A and B. Capture stores static gain,
|
||||||
|
pan, mute and solo for every track and bus without changing the document. Recall
|
||||||
|
requires the same stable track IDs, stops playback through the normal edit guard
|
||||||
|
and creates one undo step. Track order may change. Routing, plugins and
|
||||||
|
automation are excluded; automation still overrides static gain and pan. Slots
|
||||||
|
are session-only and clear on New/Open. This is static mix comparison, not
|
||||||
|
seamless live scene morphing.
|
||||||
|
|
||||||
## Validation and remaining scope
|
---
|
||||||
|
|
||||||
The code is built with warnings enabled and tested. Reproduce the core, transaction and allocation-failure checks with:
|
## Validation and Remaining Scope
|
||||||
|
|
||||||
|
The code is built with warnings enabled and tested. Reproduce the core,
|
||||||
|
transaction and allocation-failure checks with:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
make BUILD_DIR=build/roadmap-audit all gui test-reliability
|
make BUILD_DIR=build/roadmap-audit all gui test-reliability
|
||||||
|
|
@ -65,7 +135,7 @@ system Fontconfig suppression. Save/reload comparisons render identical nonzero
|
||||||
MIDI output after musical transforms; no project format migration is required.
|
MIDI output after musical transforms; no project format migration is required.
|
||||||
|
|
||||||
These workflows improve arrangement and musical editing workflows. They do not
|
These workflows improve arrangement and musical editing workflows. They do not
|
||||||
provide DAW feature parity: time stretching, comping, a clip launcher, tempo maps,
|
provide DAW feature parity: time stretching, comping, a clip launcher, tempo
|
||||||
track insert chains and customizable shortcuts need separate designs. No new
|
maps, track insert chains and customizable shortcuts need separate designs. No
|
||||||
dependencies or audio-callback operations are introduced. Human listening,
|
new dependencies or audio-callback operations are introduced. Human listening,
|
||||||
physical devices and arbitrary third-party plugins remain unqualified.
|
physical devices and arbitrary third-party plugins remain unqualified.
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,15 @@
|
||||||
# Native C processor API, version 1
|
# Native C Processor API, Version 1
|
||||||
|
|
||||||
`xtc_native.h` defines a small compile-time extension boundary for trusted C99
|
`xtc_native.h` defines a small compile-time extension boundary for trusted C99
|
||||||
sources, effects and instruments. Build `make build/native-gain` and run it for a
|
sources, effects and instruments. Build `make build/native-gain` and run it for
|
||||||
complete graph-effect example in `examples/native_gain.c`. This is a source API
|
a complete graph-effect example in `examples/native_gain.c`. This is a source
|
||||||
for this release, not a promise of binary compatibility across builds/platforms.
|
API for this release, not a promise of binary compatibility across
|
||||||
There is no module scanner, dynamic loader, SDK dependency or sandbox.
|
builds/platforms. There is no module scanner, dynamic loader, SDK dependency or
|
||||||
|
sandbox.
|
||||||
|
|
||||||
## Descriptor and ownership
|
---
|
||||||
|
|
||||||
|
## Descriptor and Ownership
|
||||||
|
|
||||||
Set `abi_version = XTC_NATIVE_ABI_VERSION`, `struct_size = sizeof(descriptor)`,
|
Set `abi_version = XTC_NATIVE_ABI_VERSION`, `struct_size = sizeof(descriptor)`,
|
||||||
a terminated printable non-space ASCII identifier (1..63 bytes), kind and all
|
a terminated printable non-space ASCII identifier (1..63 bytes), kind and all
|
||||||
|
|
@ -30,59 +33,68 @@ inside callbacks is trusted: xtc cannot enforce its realtime behavior or protect
|
||||||
against memory corruption. C++ processors must use C linkage and never throw
|
against memory corruption. C++ processors must use C linkage and never throw
|
||||||
across this boundary; domain/DSP code in this repository remains C.
|
across this boundary; domain/DSP code in this repository remains C.
|
||||||
|
|
||||||
## Block contract
|
---
|
||||||
|
|
||||||
A block contains mono input/output, frames, absolute sample position and optional
|
## Block Contract
|
||||||
MIDI events. Input NULL means silence; exact input/output aliasing is allowed and
|
|
||||||
processors must support it. Output is writable for every frame, including silent
|
A block contains mono input/output, frames, absolute sample position and
|
||||||
frames; do not retain any borrowed block pointers. Other overlapping buffers are
|
optional MIDI events. Input NULL means silence; exact input/output aliasing is
|
||||||
not supported. Only instruments receive events; event count <=256, offsets are
|
allowed and processors must support it. Output is writable for every frame,
|
||||||
sorted and strictly less than frames, with equal offsets retaining caller order.
|
including silent frames; do not retain any borrowed block pointers. Other
|
||||||
Pitch/velocity/channel/type bounds follow xtc_midi.h. Zero frames is a no-op.
|
overlapping buffers are not supported. Only instruments receive events; event
|
||||||
|
count <=256, offsets are sorted and strictly less than frames, with equal
|
||||||
|
offsets retaining caller order. Pitch/velocity/channel/type bounds follow
|
||||||
|
xtc_midi.h. Zero frames is a no-op.
|
||||||
|
|
||||||
The host rejects invalid blocks before changing state/output, and reports
|
The host rejects invalid blocks before changing state/output, and reports
|
||||||
CAPACITY above the prepared block limit. Position arithmetic cannot overflow.
|
CAPACITY above the prepared block limit. Position arithmetic cannot overflow. A
|
||||||
A discontinuous position resets held voices/state before processing. Call reset
|
discontinuous position resets held voices/state before processing. Call reset
|
||||||
for Stop/panic when hosting instruments yourself; send channel ALL_OFF for
|
for Stop/panic when hosting instruments yourself; send channel ALL_OFF for
|
||||||
channel-specific panic. The native host does not implement sustain or routing.
|
channel-specific panic. The native host does not implement sustain or routing.
|
||||||
|
|
||||||
On successful processing, nonfinite samples become silence. Callback failure
|
On successful processing, nonfinite samples become silence. Callback failure
|
||||||
silences the block, resets that processor and returns its error. Already advanced
|
silences the block, resets that processor and returns its error. Already
|
||||||
processors in a graph are not rolled back. Never rely on failure to transactionally
|
advanced processors in a graph are not rolled back. Never rely on failure to
|
||||||
rewind DSP; prepare fallible resources before publication. There is no latency
|
transactionally rewind DSP; prepare fallible resources before publication. There
|
||||||
compensation, tail protocol, parameter ramp or dynamic port negotiation in ABI 1.
|
is no latency compensation, tail protocol, parameter ramp or dynamic port
|
||||||
|
negotiation in ABI 1.
|
||||||
|
|
||||||
## Graph and instrument integration
|
---
|
||||||
|
|
||||||
`xtc_graph_add_native` adds effects (input 0/output 1) or sources (output 1), with
|
## Graph and Instrument Integration
|
||||||
a scalar immutable parameter. Compilation creates two independent mono instances
|
|
||||||
for stereo; no mutable state is shared between sides. Graph-only edits retain
|
`xtc_graph_add_native` adds effects (input 0/output 1) or sources (output 1),
|
||||||
the existing pending/retired publication contract. Reset clears native state and
|
with a scalar immutable parameter. Compilation creates two independent mono
|
||||||
its graph-local frame clock; graph positions count successfully rendered frames
|
instances for stereo; no mutable state is shared between sides. Graph-only edits
|
||||||
since compilation/reset, independently of backend seek/transport. Sources needing
|
retain the existing pending/retired publication contract. Reset clears native
|
||||||
transport time should be hosted explicitly with a block position.
|
state and its graph-local frame clock; graph positions count successfully
|
||||||
|
rendered frames since compilation/reset, independently of backend
|
||||||
|
seek/transport. Sources needing transport time should be hosted explicitly with
|
||||||
|
a block position.
|
||||||
|
|
||||||
For an instrument, use create/process directly with sample-offset events, then
|
For an instrument, use create/process directly with sample-offset events, then
|
||||||
feed its output to an existing XTC_NODE_INSTRUMENT through process_sources or
|
feed its output to an existing XTC_NODE_INSTRUMENT through process_sources or
|
||||||
process_stereo. The host owns event routing and panic/reset delivery. Graph-native
|
process_stereo. The host owns event routing and panic/reset delivery.
|
||||||
instrument addition returns UNSUPPORTED because current graph ports carry audio,
|
Graph-native instrument addition returns UNSUPPORTED because current graph ports
|
||||||
not MIDI. This separation avoids silently dropping instrument events. The built-in
|
carry audio, not MIDI. This separation avoids silently dropping instrument
|
||||||
JACK MIDI sine instrument remains the GUI's instrument; custom instrument selection
|
events. The built-in JACK MIDI sine instrument remains the GUI's instrument;
|
||||||
and event graph ports are future work.
|
custom instrument selection and event graph ports are future work.
|
||||||
|
|
||||||
Descriptors survive graph/project cloning and transactional remove/connect edits;
|
Descriptors survive graph/project cloning and transactional remove/connect
|
||||||
custom ADD_NODE commands use the dedicated constructor rather than a GUI menu.
|
edits; custom ADD_NODE commands use the dedicated constructor rather than a GUI
|
||||||
Native nodes have no project-file representation: Save returns UNSUPPORTED and
|
menu. Native nodes have no project-file representation: Save returns UNSUPPORTED
|
||||||
preserves the destination. Format v4 still accepts only builtin types 1..6.
|
and preserves the destination. Format v4 still accepts only builtin types 1..6.
|
||||||
A durable identifier/registry, versioned processor state and missing-module policy
|
A durable identifier/registry, versioned processor state and missing-module
|
||||||
must precede serialized native extensions or external plugin hosting.
|
policy must precede serialized native extensions or external plugin hosting.
|
||||||
|
|
||||||
Tests cover ABI/size/field rejection, descriptor copying, aliased buffers,
|
Tests cover ABI/size/field rejection, descriptor copying, aliased buffers,
|
||||||
prepare/process failures, stereo compile cleanup, retirement/destruction outside
|
prepare/process failures, stereo compile cleanup, retirement/destruction outside
|
||||||
processing, event offsets, seek note reset, source ports, instrument-buffer graph
|
processing, event offsets, seek note reset, source ports, instrument-buffer
|
||||||
routing and unsupported-save preservation. Run `make test`.
|
graph routing and unsupported-save preservation. Run `make test`.
|
||||||
|
|
||||||
## Structured parameter processors
|
---
|
||||||
|
|
||||||
|
## Structured Parameter Processors
|
||||||
|
|
||||||
`xtc_processor.h` is the public C99 parameter-only extension interface (ABI 2).
|
`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.
|
It complements the ABI 1 graph adapter without changing its layout or behavior.
|
||||||
|
|
@ -90,27 +102,28 @@ It complements the ABI 1 graph adapter without changing its layout or behavior.
|
||||||
instrument using only public headers; `make test-processor` builds and exercises
|
instrument using only public headers; `make test-processor` builds and exercises
|
||||||
both. The instrument has immediate note-off and no voice stealing/release tail.
|
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,
|
Descriptors have an exact ABI version and structure size, a persistent
|
||||||
and up to 16 parameters with unique unsigned IDs, names, units, finite ranges and
|
identifier, and up to 16 parameters with unique unsigned IDs, names, units,
|
||||||
defaults. Unsupported ABI versions/sizes are rejected before initialization.
|
finite ranges and defaults. Unsupported ABI versions/sizes are rejected before
|
||||||
Changing identifier, parameter order, IDs or ranges requires an explicit migration
|
initialization. Changing identifier, parameter order, IDs or ranges requires an
|
||||||
by the extension author. There is no promise of binary compatibility across
|
explicit migration by the extension author. There is no promise of binary
|
||||||
compiler architectures, and no C++/FLTK types in either API.
|
compatibility across compiler architectures, and no C++/FLTK types in either
|
||||||
|
API.
|
||||||
|
|
||||||
Create prepares a copied descriptor on the control thread. Failed preparation
|
Create prepares a copied descriptor on the control thread. Failed preparation
|
||||||
calls destroy, including with NULL: callbacks must implement partial cleanup.
|
calls destroy, including with NULL: callbacks must implement partial cleanup.
|
||||||
Reset/process/parameter have one audio owner and must never allocate, free, block,
|
Reset/process/parameter have one audio owner and must never allocate, free,
|
||||||
perform I/O or call GUI functions. Destroy is control-thread only after callback
|
block, perform I/O or call GUI functions. Destroy is control-thread only after
|
||||||
quiescence. Reconfiguration prepares a new independent instance; publish it with
|
callback quiescence. Reconfiguration prepares a new independent instance;
|
||||||
an appropriate owner handoff and retire the old instance after quiescence. The
|
publish it with an appropriate owner handoff and retire the old instance after
|
||||||
callback code must remain loaded throughout that lifetime.
|
quiescence. The callback code must remain loaded throughout that lifetime.
|
||||||
|
|
||||||
Each instance has one mono output and either one optional input (effect) or no
|
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
|
input (source/instrument). NULL input means silence. Stereo effects use two
|
||||||
independent instances; multichannel interdependent effects have no adapter.
|
independent instances; multichannel interdependent effects have no adapter.
|
||||||
Instruments receive at most 256 sorted sample-offset MIDI events per block.
|
Instruments receive at most 256 sorted sample-offset MIDI events per block. The
|
||||||
The API intentionally has no channel-count argument: unsupported layouts cannot
|
API intentionally has no channel-count argument: unsupported layouts cannot be
|
||||||
be represented. Graph ABI 1 rejects instrument descriptors; explicitly render
|
represented. Graph ABI 1 rejects instrument descriptors; explicitly render
|
||||||
instrument output and feed the existing instrument source buffers.
|
instrument output and feed the existing instrument source buffers.
|
||||||
|
|
||||||
Up to 256 sorted parameter events split the process block at exact sample
|
Up to 256 sorted parameter events split the process block at exact sample
|
||||||
|
|
@ -122,13 +135,14 @@ reset retains current parameters. Callback errors silence the whole output and
|
||||||
reset voices/history; already applied parameters persist. Nonfinite/subnormal
|
reset voices/history; already applied parameters persist. Nonfinite/subnormal
|
||||||
successful samples become zero. Input/output may alias exactly.
|
successful samples become zero. Input/output may alias exactly.
|
||||||
|
|
||||||
`xtc_processor_save`/`restore` run only while quiescent and serialize configuration,
|
`xtc_processor_save`/`restore` run only while quiescent and serialize
|
||||||
not DSP history. Format: `XTCN`, little-endian uint32 version 2, zero-padded
|
configuration, not DSP history. Format: `XTCN`, little-endian uint32 version 2,
|
||||||
64-byte identifier, uint32 parameter count, zero uint32 reserved, then ordered
|
zero-padded 64-byte identifier, uint32 parameter count, zero uint32 reserved,
|
||||||
pairs of uint32 ID and IEEE float32 bits. Header is 80 bytes, pairs 8 bytes.
|
then ordered pairs of uint32 ID and IEEE float32 bits. Header is 80 bytes, pairs
|
||||||
Restore validates exact length, identity, IDs, ranges and defaults/descriptor
|
8 bytes. Restore validates exact length, identity, IDs, ranges and
|
||||||
compatibility before preparing a new instance; failure leaves existing handles
|
defaults/descriptor compatibility before preparing a new instance; failure
|
||||||
intact. Opaque assets and hidden state are outside this ABI. ABI 1 graph nodes
|
leaves existing handles intact. Opaque assets and hidden state are outside this
|
||||||
remain session-only and fail project saves explicitly; ABI 2 configuration blobs
|
ABI. ABI 1 graph nodes remain session-only and fail project saves explicitly;
|
||||||
are a separate public facility, not automatically embedded in project files.
|
ABI 2 configuration blobs are a separate public facility, not automatically
|
||||||
GUI graph access continues through public C APIs only.
|
embedded in project files. GUI graph access continues through public C APIs
|
||||||
|
only.
|
||||||
|
|
|
||||||
|
|
@ -1,48 +1,54 @@
|
||||||
# Performance and realtime qualification
|
# Performance and Realtime Qualification
|
||||||
|
|
||||||
The original `test-performance` ran a hardware-independent 48 kHz, 128-frame stereo
|
The original `test-performance` ran a hardware-independent 48 kHz, 128-frame
|
||||||
workload: 64 graph nodes, 4096 MIDI notes (32 simultaneous), 16 tracks and gain
|
stereo workload: 64 graph nodes, 4096 MIDI notes (32 simultaneous), 16 tracks
|
||||||
automation. Preparation and block timing use CLOCK_MONOTONIC outside the engine;
|
and gain automation. Preparation and block timing use CLOCK_MONOTONIC outside
|
||||||
callback code itself does not clock or log. The test checks finite output and
|
the engine; callback code itself does not clock or log. The test checks finite
|
||||||
reports mean, p99, maximum and CPU-time/audio-duration ratio. A run is a workload
|
output and reports mean, p99, maximum and CPU-time/audio-duration ratio. A run
|
||||||
measurement, not a universal realtime threshold. Run more blocks with:
|
is a workload measurement, not a universal realtime threshold. Run more blocks
|
||||||
|
with:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
./build/test_performance 10000
|
./build/test_performance 10000
|
||||||
```
|
```
|
||||||
|
|
||||||
Initial measurement on an AMD Ryzen Threadripper 1920X, GCC 16.2.1, -O2,
|
Initial measurement on an AMD Ryzen Threadripper 1920X, GCC 16.2.1, -O2, 2000
|
||||||
2000 blocks: preparation 3.045 ms, mean 308.301 us, p99 422.153 us, maximum
|
blocks: preparation 3.045 ms, mean 308.301 us, p99 422.153 us, maximum 665.096
|
||||||
665.096 us, versus a 2666.667 us block deadline; CPU/audio ratio 0.1156. These are
|
us, versus a 2666.667 us block deadline; CPU/audio ratio 0.1156. These are one
|
||||||
one host/run's observed values and depend on scheduling/load/compiler. The test
|
host/run's observed values and depend on scheduling/load/compiler. The test
|
||||||
excludes WAV disk preparation, external/native plugin complexity, GUI redraw,
|
excludes WAV disk preparation, external/native plugin complexity, GUI redraw,
|
||||||
server scheduling and actual hardware latency. Native callbacks must provide
|
server scheduling and actual hardware latency. Native callbacks must provide
|
||||||
their own bounded realtime implementation.
|
their own bounded realtime implementation.
|
||||||
|
|
||||||
Existing software JACK loopback, stereo MIDI/save/reopen, record/reopen,
|
Existing software JACK loopback, stereo MIDI/save/reopen, record/reopen,
|
||||||
restart/close and concurrent graph handoff tests remain available. Runtime
|
restart/close and concurrent graph handoff tests remain available. Runtime fault
|
||||||
fault injection covers loss/rate/xrun/null-buffer and lifecycle failures without
|
injection covers loss/rate/xrun/null-buffer and lifecycle failures without
|
||||||
altering the shared server. ASan/UBSan validate memory/error paths; TSan checks
|
altering the shared server. ASan/UBSan validate memory/error paths; TSan checks
|
||||||
recorder/handoff races, not timing. Sanitized runs are not latency qualification.
|
recorder/handoff races, not timing. Sanitized runs are not latency
|
||||||
|
qualification.
|
||||||
|
|
||||||
Current worst-case storage includes up to 256 MiB preloaded mono WAV samples,
|
Current worst-case storage includes up to 256 MiB preloaded mono WAV samples,
|
||||||
paired graph buffers (128 MiB at 256 nodes/65536 frames; GUI limit 32 MiB), bounded
|
paired graph buffers (128 MiB at 256 nodes/65536 frames; GUI limit 32 MiB),
|
||||||
MIDI/mix metadata and up to 33 metadata/graph history snapshots. Pending/retired
|
bounded MIDI/mix metadata and up to 33 metadata/graph history snapshots.
|
||||||
plans can retain additional graph memory. Native preparation can allocate more;
|
Pending/retired plans can retain additional graph memory. Native preparation can
|
||||||
the API cannot enforce an extension's memory budget. There is no CPU overload
|
allocate more; the API cannot enforce an extension's memory budget. There is no
|
||||||
scheduler, disk streaming, latency compensation or callback allocator audit of
|
CPU overload scheduler, disk streaming, latency compensation or callback
|
||||||
arbitrary third-party code. High-density interactive projects, physical devices,
|
allocator audit of arbitrary third-party code. High-density interactive
|
||||||
long-duration stereo/recording and live server termination remain unqualified.
|
projects, physical devices, long-duration stereo/recording and live server
|
||||||
|
termination remain unqualified.
|
||||||
|
|
||||||
## Matrix, capacity and contention checks
|
---
|
||||||
|
|
||||||
|
## Matrix, Capacity and Contention Checks
|
||||||
|
|
||||||
`make benchmark` records 24 warmed graph cases: 2/16/64/256 nodes, mono/stereo,
|
`make benchmark` records 24 warmed graph cases: 2/16/64/256 nodes, mono/stereo,
|
||||||
44.1k/31, 48k/128 and 96k/1024. Each reports control-thread compile time separately
|
44.1k/31, 48k/128 and 96k/1024. Each reports control-thread compile time
|
||||||
from 300 process calls, mean/p99/max, block deadline, mean load, and paired graph
|
separately from 300 process calls, mean/p99/max, block deadline, mean load, and
|
||||||
buffer bytes. Timing, sorting, allocation and logging happen outside processing.
|
paired graph buffer bytes. Timing, sorting, allocation and logging happen
|
||||||
Metered gain chains test graph scaling; they do not represent expensive plugins.
|
outside processing. Metered gain chains test graph scaling; they do not
|
||||||
The checked-in `performance-baseline.json` records CPU/compiler/flags/kernel and
|
represent expensive plugins. The checked-in `performance-baseline.json` records
|
||||||
all measurements. Copy a new run only after reviewing changes and conditions.
|
CPU/compiler/flags/kernel and all measurements. Copy a new run only after
|
||||||
|
reviewing changes and conditions.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
make benchmark test-performance test-scale test-stress
|
make benchmark test-performance test-scale test-stress
|
||||||
|
|
@ -60,37 +66,42 @@ shared-machine contention still affect results. No real-time scheduling/pinning
|
||||||
or external profiler is required. CPU-pressure runs are correctness checks, not
|
or external profiler is required. CPU-pressure runs are correctness checks, not
|
||||||
comparable timing baselines. Tests/benchmark outputs live below BUILD_DIR.
|
comparable timing baselines. Tests/benchmark outputs live below BUILD_DIR.
|
||||||
|
|
||||||
Initial matrix (Threadripper 1920X, GCC 16.2.1, -O2, 300 blocks): 256-node stereo
|
Initial matrix (Threadripper 1920X, GCC 16.2.1, -O2, 300 blocks): 256-node
|
||||||
48k/128 mean 353.214 us, p99 396.495 us, load .132; 96k/1024 mean 2478.520 us,
|
stereo 48k/128 mean 353.214 us, p99 396.495 us, load .132; 96k/1024 mean
|
||||||
p99 3092.434 us, load .232. The full JSON is the evidence. These met the local
|
2478.520 us, p99 3092.434 us, load .232. The full JSON is the evidence. These
|
||||||
investigation target of mean load <.5 for ordinary graph chains; this is a
|
met the local investigation target of mean load <.5 for ordinary graph chains;
|
||||||
host-specific development target, not a supported maximum CPU or latency promise.
|
this is a host-specific development target, not a supported maximum CPU or
|
||||||
|
latency promise.
|
||||||
|
|
||||||
The mixed 64-node/4096-note workload measured 340–357 us before removing unused
|
The mixed 64-node/4096-note workload measured 340–357 us before removing unused
|
||||||
live-controller processing and 313 us after (mean over 2000 blocks); p99 varied
|
live-controller processing and 313 us after (mean over 2000 blocks); p99 varied
|
||||||
with system load. The measured hot-path change skips live voices/controller ramps
|
with system load. The measured hot-path change skips live voices/controller
|
||||||
when neither is active and avoids finished-ramp calls. Exact CC/odd-block tests
|
ramps when neither is active and avoids finished-ramp calls. Exact CC/odd-block
|
||||||
continue to pass. No other graph optimization was justified by this measurement.
|
tests continue to pass. No other graph optimization was justified by this
|
||||||
|
measurement.
|
||||||
|
|
||||||
`test-scale` constructs all 64 tracks, 1024 clips, 1024 automation points and
|
`test-scale` constructs all 64 tracks, 1024 clips, 1024 automation points and
|
||||||
4096 notes, compiles a standalone 256-node metered graph, renders stereo odd-sized
|
4096 notes, compiles a standalone 256-node metered graph, renders stereo
|
||||||
blocks and rejects capacity excesses. Project/GUI graphs remain capped at 64
|
odd-sized blocks and rejects capacity excesses. Project/GUI graphs remain capped
|
||||||
nodes. `test-stress` runs publication, allocation/retirement, capacity and optional
|
at 64 nodes. `test-stress` runs publication, allocation/retirement, capacity and
|
||||||
GUI/timer/redraw tests while two ordinary CPU workers compete; subprocesses have
|
optional GUI/timer/redraw tests while two ordinary CPU workers compete;
|
||||||
timeouts and workers are always terminated. Existing callback guards verify no
|
subprocesses have timeouts and workers are always terminated. Existing callback
|
||||||
host allocation/free/loading/unloading. This does not qualify arbitrary plugins.
|
guards verify no host allocation/free/loading/unloading. This does not qualify
|
||||||
|
arbitrary plugins.
|
||||||
|
|
||||||
Callback work is bounded by documented node/frame/clip/note/event/point capacities.
|
Callback work is bounded by documented node/frame/clip/note/event/point
|
||||||
Exceeding model/plan/mailbox capacities returns CAPACITY transactionally; invalid
|
capacities. Exceeding model/plan/mailbox capacities returns CAPACITY
|
||||||
or overlarge processing buffers are silenced and reported, JACK xruns are counted.
|
transactionally; invalid or overlarge processing buffers are silenced and
|
||||||
There is no CPU scheduler or preemption inside a DSP callback: an expensive trusted
|
reported, JACK xruns are counted. There is no CPU scheduler or preemption inside
|
||||||
plugin can miss a deadline or hang. Automated LADSPA lanes currently use run(1)
|
a DSP callback: an expensive trusted plugin can miss a deadline or hang.
|
||||||
and bounded per-sample lane searches and may be costly; they are excluded from
|
Automated LADSPA lanes currently use run(1) and bounded per-sample lane searches
|
||||||
the gain-chain baseline. Large WAV memory limits remain those in AUDIO_FILES.md.
|
and may be costly; they are excluded from the gain-chain baseline. Large WAV
|
||||||
Physical-device endurance, CPU-overload sound quality and a full GUI latency
|
memory limits remain those in AUDIO_FILES.md. Physical-device endurance,
|
||||||
benchmark remain unqualified.
|
CPU-overload sound quality and a full GUI latency benchmark remain unqualified.
|
||||||
|
|
||||||
## Qualification workloads
|
---
|
||||||
|
|
||||||
|
## Qualification Workloads
|
||||||
|
|
||||||
The current `test-performance` emits one JSON record (the old prose output is
|
The current `test-performance` emits one JSON record (the old prose output is
|
||||||
retired). Default: 2,000 stereo blocks at 48 kHz/128, 64 graph nodes, 16 tracks,
|
retired). Default: 2,000 stereo blocks at 48 kHz/128, 64 graph nodes, 16 tracks,
|
||||||
|
|
@ -101,10 +112,10 @@ for this revision. `benchmark-project` runs nine cases: 1/16/64 tracks,
|
||||||
Two long notes per first 16 tracks remain audible. Other notes are scheduled
|
Two long notes per first 16 tracks remain audible. Other notes are scheduled
|
||||||
later to remain within the 32-voice plan limit. The position wraps every 96,000
|
later to remain within the 32-voice plan limit. The position wraps every 96,000
|
||||||
samples to keep long runs active. Future notes exercise storage/preparation and
|
samples to keep long runs active. Future notes exercise storage/preparation and
|
||||||
bounded scans rather than additional simultaneous synthesis. Each track has
|
bounded scans rather than additional simultaneous synthesis. Each track has 16
|
||||||
16 gain points; graph processing uses the same 64-node chain in every case.
|
gain points; graph processing uses the same 64-node chain in every case. The
|
||||||
The graph matrix separately scales nodes and chain connections from 2 to 256.
|
graph matrix separately scales nodes and chain connections from 2 to 256. These
|
||||||
These synthetic cases do not qualify every possible dense graph or plugin chain.
|
synthetic cases do not qualify every possible dense graph or plugin chain.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
make benchmark benchmark-project
|
make benchmark benchmark-project
|
||||||
|
|
@ -122,22 +133,25 @@ exceedances, not actual JACK xruns: there is no server scheduling in the timing
|
||||||
loop. Graph compilation or project construction/preparation is timed separately.
|
loop. Graph compilation or project construction/preparation is timed separately.
|
||||||
`process_cpu_ms` measures CLOCK_PROCESS_CPUTIME_ID over the complete measured
|
`process_cpu_ms` measures CLOCK_PROCESS_CPUTIME_ID over the complete measured
|
||||||
loop, including timing and finite-output checks; it excludes preparation and
|
loop, including timing and finite-output checks; it excludes preparation and
|
||||||
sorting. Project `cpu_audio_ratio` divides that CPU time by simulated audio time.
|
sorting. Project `cpu_audio_ratio` divides that CPU time by simulated audio
|
||||||
`peak_rss_kib` is Linux getrusage process high-water RSS, including model, plans,
|
time. `peak_rss_kib` is Linux getrusage process high-water RSS, including model,
|
||||||
measurement storage and executable/runtime overhead; it is not current heap size
|
plans, measurement storage and executable/runtime overhead; it is not current
|
||||||
or a leak test. Graph buffer bytes remain a separate exact buffer-size estimate.
|
heap size or a leak test. Graph buffer bytes remain a separate exact buffer-size
|
||||||
Timing probes, memory queries, sorting and output occur outside engine calls.
|
estimate. Timing probes, memory queries, sorting and output occur outside engine
|
||||||
|
calls.
|
||||||
|
|
||||||
Checked-in `project-performance-baseline.json` provides initial project cases;
|
Checked-in `project-performance-baseline.json` provides initial project cases;
|
||||||
the original graph baseline is retained. `graph-performance-baseline.json` adds
|
the original graph baseline is retained. `graph-performance-baseline.json` adds
|
||||||
a current graph report with CPU/RSS/deadline fields. Gates use the existing
|
a current graph report with CPU/RSS/deadline fields. Gates use the existing 1.5x
|
||||||
1.5x mean-time budget and 1 us noise allowance, with p99/max/misses and memory
|
mean-time budget and 1 us noise allowance, with p99/max/misses and memory
|
||||||
reported for investigation. There is no universal hardware-independent deadline
|
reported for investigation. There is no universal hardware-independent deadline
|
||||||
or RSS pass threshold. `test-benchmark-tools` verifies same-context success,
|
or RSS pass threshold. `test-benchmark-tools` verifies same-context success,
|
||||||
regression rejection, missing cases and host/workload mismatch without relying
|
regression rejection, missing cases and host/workload mismatch without relying
|
||||||
on machine timing. Do not replace a failing baseline without investigating.
|
on machine timing. Do not replace a failing baseline without investigating.
|
||||||
|
|
||||||
## Endurance, faults and callback audit
|
---
|
||||||
|
|
||||||
|
## Endurance, Faults and Callback Audit
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
make test-soak test-stress test-stress-plugins
|
make test-soak test-stress test-stress-plugins
|
||||||
|
|
@ -153,24 +167,26 @@ quiescent position/rebuild cycles. It runs faster than wall time and models
|
||||||
position wrap/seek and restart publication; it is not a real device start/stop
|
position wrap/seek and restart publication; it is not a real device start/stop
|
||||||
or hardware endurance test. The project benchmark separately wraps active MIDI.
|
or hardware endurance test. The project benchmark separately wraps active MIDI.
|
||||||
|
|
||||||
`test-stress` defaults to three rounds under two ordinary CPU workers. Each round
|
`test-stress` defaults to three rounds under two ordinary CPU workers. Each
|
||||||
runs concurrent publication, allocation/lifetime guards, maximum model capacity,
|
round runs concurrent publication, allocation/lifetime guards, maximum model
|
||||||
project relocation/reload and missing-media retention, save-fault diagnostics,
|
capacity, project relocation/reload and missing-media retention, save-fault
|
||||||
and the soak test. With JACK headers present it also repeats the deterministic
|
diagnostics, and the soak test. With JACK headers present it also repeats the
|
||||||
backend fake's start/stop/seek, rate/buffer/server-loss and failure/retry cases.
|
deterministic backend fake's start/stop/seek, rate/buffer/server-loss and
|
||||||
Optional GUI tests run after those rounds under the same CPU load.
|
failure/retry cases. Optional GUI tests run after those rounds under the same
|
||||||
`test-stress-plugins` adds the original LADSPA fixture's identity/layout/range,
|
CPU load. `test-stress-plugins` adds the original LADSPA fixture's
|
||||||
instantiation-error and invalid-metadata cases each round; it needs LADSPA headers.
|
identity/layout/range, instantiation-error and invalid-metadata cases each
|
||||||
No command changes a physical device, kills the shared server or loads unknown
|
round; it needs LADSPA headers. No command changes a physical device, kills the
|
||||||
plugins. Subprocess deadlines bound each test and workers are cleaned up on exit.
|
shared server or loads unknown plugins. Subprocess deadlines bound each test and
|
||||||
|
workers are cleaned up on exit.
|
||||||
|
|
||||||
The reliability executable now interposes fopen/fread/fwrite/read/write,
|
The reliability executable now interposes fopen/fread/fwrite/read/write,
|
||||||
pthread_mutex_lock and pthread_cond_wait in addition to malloc/calloc/realloc/free.
|
pthread_mutex_lock and pthread_cond_wait in addition to
|
||||||
Guarded host graph/realtime render calls fail immediately on these operations.
|
malloc/calloc/realloc/free. Guarded host graph/realtime render calls fail
|
||||||
This complements the existing native lifetime and plugin callback guards and
|
immediately on these operations. This complements the existing native lifetime
|
||||||
control/callback ownership review in RELIABILITY.md. It does not intercept every
|
and plugin callback guards and control/callback ownership review in
|
||||||
libc entry point, raw syscalls, hidden dynamic-module calls, or GUI code by magic;
|
RELIABILITY.md. It does not intercept every libc entry point, raw syscalls,
|
||||||
third-party DSP remains trusted. No known host callback safety violation was found.
|
hidden dynamic-module calls, or GUI code by magic; third-party DSP remains
|
||||||
|
trusted. No known host callback safety violation was found.
|
||||||
|
|
||||||
`check-development` combines the ordinary build/tests, capacity/soak checks,
|
`check-development` combines the ordinary build/tests, capacity/soak checks,
|
||||||
benchmark gate tests, static analysis and ASan/UBSan. The sanitizer target now
|
benchmark gate tests, static analysis and ASan/UBSan. The sanitizer target now
|
||||||
|
|
@ -178,16 +194,18 @@ includes maximum capacity and virtual endurance. These are opt-in developer
|
||||||
checks requiring installed Clang/Python; no runtime dependency was added.
|
checks requiring installed Clang/Python; no runtime dependency was added.
|
||||||
Sanitized/contended/profiled runs must not become timing baselines.
|
Sanitized/contended/profiled runs must not become timing baselines.
|
||||||
|
|
||||||
## Profiling evidence and remaining costs
|
---
|
||||||
|
|
||||||
|
## Profiling Evidence and Remaining Costs
|
||||||
|
|
||||||
Before considering DSP changes, a 10,000-block, 64-track/128-frame project was
|
Before considering DSP changes, a 10,000-block, 64-track/128-frame project was
|
||||||
sampled with GCC `-O2 -g -pg` and GNU gprof on the documented baseline host.
|
sampled with GCC `-O2 -g -pg` and GNU gprof on the documented baseline host.
|
||||||
Flat samples attributed about 30% to mixer automation `value`, 29% to MIDI
|
Flat samples attributed about 30% to mixer automation `value`, 29% to MIDI
|
||||||
`segment`, and 11% to finite-value handling. Instrumentation and inlining affect
|
`segment`, and 11% to finite-value handling. Instrumentation and inlining affect
|
||||||
attribution; this identifies investigation candidates, not exact production
|
attribution; this identifies investigation candidates, not exact production cost
|
||||||
cost or evidence that checks should be removed. MIDI scans bounded stored-note
|
or evidence that checks should be removed. MIDI scans bounded stored-note arrays
|
||||||
arrays and evaluates per-voice, per-sample gain/pan lanes. No DSP optimization
|
and evaluates per-voice, per-sample gain/pan lanes. No DSP optimization was
|
||||||
was introduced without a separate correctness/performance justification.
|
introduced without a separate correctness/performance justification.
|
||||||
|
|
||||||
Reproduce in an isolated build (GNU gprof must already be installed):
|
Reproduce in an isolated build (GNU gprof must already be installed):
|
||||||
|
|
||||||
|
|
@ -209,10 +227,10 @@ CPU/audio .142 and peak process RSS 19,296 KiB. The 256-node stereo/128 graph
|
||||||
mean was 286.398 us, p99 484.712 us, compile .300 ms. These case runs observed
|
mean was 286.398 us, p99 484.712 us, compile .300 ms. These case runs observed
|
||||||
zero deadline exceedances. See JSON for all cases and host metadata.
|
zero deadline exceedances. See JSON for all cases and host metadata.
|
||||||
|
|
||||||
The project comparison passed. Repeated graph comparisons flagged variable
|
The project comparison passed. Repeated graph comparisons flagged variable small
|
||||||
small cases despite unchanged graph processing code; a 3,000-block run against
|
cases despite unchanged graph processing code; a 3,000-block run against the
|
||||||
the retained baseline still flagged 16-node mono/31-frame mean 5.089 us
|
retained baseline still flagged 16-node mono/31-frame mean 5.089 us above its
|
||||||
above its 1.5x budget. The new graph report is evidence, not a replacement chosen
|
1.5x budget. The new graph report is evidence, not a replacement chosen to make
|
||||||
to make that comparison pass. This shared-host timing alert remains an
|
that comparison pass. This shared-host timing alert remains an investigation
|
||||||
investigation item; no CPU/latency guarantee is inferred from the correctness
|
item; no CPU/latency guarantee is inferred from the correctness suite. Longer
|
||||||
suite. Longer comparisons can use `BENCHMARK_BLOCKS=3000`.
|
comparisons can use `BENCHMARK_BLOCKS=3000`.
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# External plugin hosting evaluation
|
# External Plugin Hosting Evaluation
|
||||||
|
|
||||||
The original decision deferred external hosting. The native source API is useful
|
The original decision deferred external hosting. The native source API is useful
|
||||||
for proving processor contracts without adding an SDK or scanning/loading code.
|
for proving processor contracts without adding an SDK or scanning/loading code.
|
||||||
|
|
@ -9,27 +9,32 @@ for proving processor contracts without adding an SDK or scanning/loading code.
|
||||||
| CLAP | C ABI, explicit lifecycle and event model | Extension negotiation, parameter/state persistence, host callbacks, main/audio-thread scheduling and UI integration |
|
| CLAP | C ABI, explicit lifecycle and event model | Extension negotiation, parameter/state persistence, host callbacks, main/audio-thread scheduling and UI integration |
|
||||||
| VST3 | Broad plugin availability | SDK/license review for the selected SDK release, C++ adapter outside the C core, component/controller and editor lifecycle, state and event translation |
|
| VST3 | Broad plugin availability | SDK/license review for the selected SDK release, C++ adapter outside the C core, component/controller and editor lifecycle, state and event translation |
|
||||||
|
|
||||||
No candidate was linked, scanned or loaded. API/SDK and plugin
|
No candidate was linked, scanned or loaded. API/SDK and plugin licenses must be
|
||||||
licenses must be checked at the revision actually adopted; they are separate
|
checked at the revision actually adopted; they are separate from xtc's MIT
|
||||||
from xtc's MIT license. Supporting a format does not grant redistribution rights
|
license. Supporting a format does not grant redistribution rights to individual
|
||||||
to individual plugins. Do not search user plugin directories from the callback.
|
plugins. Do not search user plugin directories from the callback.
|
||||||
|
|
||||||
Before implementation, require versioned module identity and state, a missing-
|
Before implementation, require versioned module identity and state, a missing-
|
||||||
plugin recovery policy, preparation failure/partial cleanup tests, bounded events
|
plugin recovery policy, preparation failure/partial cleanup tests, bounded
|
||||||
and parameter publication, latency/tail handling, callback-safe unload after
|
events and parameter publication, latency/tail handling, callback-safe unload
|
||||||
retirement, a GUI/main-thread boundary and an explicit crash-containment decision.
|
after retirement, a GUI/main-thread boundary and an explicit crash-containment
|
||||||
Native ABI tests cover some ownership mechanics but do not prove third-party
|
decision. Native ABI tests cover some ownership mechanics but do not prove
|
||||||
code safe. Event graph ports remain a gap; track instrument selection is described below.
|
third-party code safe. Event graph ports remain a gap; track instrument
|
||||||
Choose one format with concrete user needs after those contracts are specified;
|
selection is described below. Choose one format with concrete user needs after
|
||||||
do not introduce a general multi-format framework now. See decision 0008.
|
those contracts are specified; do not introduce a general multi-format framework
|
||||||
|
now. See decision 0008.
|
||||||
|
|
||||||
## LADSPA implementation (supersedes the earlier deferral)
|
---
|
||||||
|
|
||||||
Decision [0009](decisions/0009-parameter-processors-and-ladspa.md) selects a bounded
|
## LADSPA Implementation (Supersedes the Earlier Deferral)
|
||||||
LADSPA 1.1 host. `xtc_plugin.h` is the C API; no C++ engine or FLTK type is needed.
|
|
||||||
|
|
||||||
1. Choose **File → Load LADSPA plugin** and a trusted absolute `.so` path. Loading
|
Decision [0009](decisions/0009-parameter-processors-and-ladspa.md) selects a
|
||||||
executes native code immediately, including constructors during discovery.
|
bounded LADSPA 1.1 host. `xtc_plugin.h` is the C API; no C++ engine or FLTK type
|
||||||
|
is needed.
|
||||||
|
|
||||||
|
1. Choose **File → Load LADSPA plugin** and a trusted absolute `.so` path.
|
||||||
|
Loading executes native code immediately, including constructors during
|
||||||
|
discovery.
|
||||||
2. The descriptor browser lists names, labels, makers and source/effect roles.
|
2. The descriptor browser lists names, labels, makers and source/effect roles.
|
||||||
Select a row and Choose. Counts report compatible and skipped descriptors.
|
Select a row and Choose. Counts report compatible and skipped descriptors.
|
||||||
3. In the Modular Graph, connect the new source/effect output to an output or
|
3. In the Modular Graph, connect the new source/effect output to an output or
|
||||||
|
|
@ -37,18 +42,19 @@ LADSPA 1.1 host. `xtc_plugin.h` is the C API; no C++ engine or FLTK type is need
|
||||||
receive external input, as other graph processors do.
|
receive external input, as other graph processors do.
|
||||||
4. Select its node and use **Edit → Selected plugin control**. The editor shows
|
4. Select its node and use **Edit → Selected plugin control**. The editor shows
|
||||||
name, maker, copyright, module path, descriptor index and unique ID, then
|
name, maker, copyright, module path, descriptor index and unique ID, then
|
||||||
actual port IDs, editable values, rate-adjusted bounds, defaults and discrete/
|
actual port IDs, editable values, rate-adjusted bounds, defaults and
|
||||||
logarithmic hints. Apply validates all values and candidate initialization;
|
discrete/ logarithmic hints. Apply validates all values and candidate
|
||||||
Cancel and window close preserve the document. Toggled controls require 0/1
|
initialization; Cancel and window close preserve the document. Toggled
|
||||||
and integer controls require integral values.
|
controls require 0/1 and integer controls require integral values.
|
||||||
5. Save normally, reopen, reconnect external JACK playback if needed, and Play.
|
5. Save normally, reopen, reconnect external JACK playback if needed, and Play.
|
||||||
Plugin changes stop/rebuild playback and participate in ordinary undo/redo.
|
Plugin changes stop/rebuild playback and participate in ordinary undo/redo.
|
||||||
|
|
||||||
The GUI uses only public graph/model/plugin APIs. Discovery probes explicit module
|
The GUI uses only public graph/model/plugin APIs. Discovery probes explicit
|
||||||
files by descriptor index, bounded to 1024 descriptors. It never recursively scans
|
module files by descriptor index, bounded to 1024 descriptors. It never
|
||||||
system directories. The C API exposes probe, parameter metadata, instance
|
recursively scans system directories. The C API exposes probe, parameter
|
||||||
create/process/destroy, and add/get/set graph configuration. Missing header means
|
metadata, instance create/process/destroy, and add/get/set graph configuration.
|
||||||
hosting returns UNSUPPORTED; metadata persistence continues to work.
|
Missing header means hosting returns UNSUPPORTED; metadata persistence continues
|
||||||
|
to work.
|
||||||
|
|
||||||
Supported: 0/1 audio input, 1 output, <=64 total ports and <=16 input controls.
|
Supported: 0/1 audio input, 1 output, <=64 total ports and <=16 input controls.
|
||||||
Stereo graph channels are two independent mono instances. Stereo/multichannel
|
Stereo graph channels are two independent mono instances. Stereo/multichannel
|
||||||
|
|
@ -65,22 +71,25 @@ incompatible identity/range/layout, or instantiate returning NULL unwinds the
|
||||||
candidate and leaves active/pending plans intact. Only run and bounded host
|
candidate and leaves active/pending plans intact. Only run and bounded host
|
||||||
buffer copies execute in audio. Destruction and unloading happen after callback
|
buffer copies execute in audio. Destruction and unloading happen after callback
|
||||||
quiescence or retirement acknowledgement on the control thread. Transport reset
|
quiescence or retirement acknowledgement on the control thread. Transport reset
|
||||||
retains LADSPA history; compile/reopen starts fresh. A LADSPA run callback has no
|
retains LADSPA history; compile/reopen starts fresh. A LADSPA run callback has
|
||||||
error return. Nonfinite/subnormal samples become zero, but native crashes,
|
no error return. Nonfinite/subnormal samples become zero, but native crashes,
|
||||||
corruption, runaway CPU, allocations or I/O inside a plugin cannot be contained
|
corruption, runaway CPU, allocations or I/O inside a plugin cannot be contained
|
||||||
or prevented. Use trusted plugins; hard-realtime properties are declarations,
|
or prevented. Use trusted plugins; hard-realtime properties are declarations,
|
||||||
not proof. This is an in-process host, not a crash-isolation service.
|
not proof. This is an in-process host, not a crash-isolation service.
|
||||||
|
|
||||||
Project v5 stores absolute module path, index, label, LADSPA unique ID, mono input
|
Project v5 stores absolute module path, index, label, LADSPA unique ID, mono
|
||||||
count and ordered input-control port/value pairs. Restore verifies identity,
|
input count and ordered input-control port/value pairs. Restore verifies
|
||||||
layout, parameter ports and ranges against the loaded module. No pointers are
|
identity, layout, parameter ports and ranges against the loaded module. No
|
||||||
serialized. Relocating a module requires restoring it at its saved absolute path
|
pointers are serialized. Relocating a module requires restoring it at its saved
|
||||||
or deliberately modifying its metadata through a C client. GUI Open reports the
|
absolute path or deliberately modifying its metadata through a C client. GUI
|
||||||
missing/incompatible identity/path and retains the current document. Metadata
|
Open reports the missing/incompatible identity/path and retains the current
|
||||||
load/save and `xtc-check --validate` do not execute plugin code and do not certify
|
document. Metadata load/save and `xtc-check --validate` do not execute plugin
|
||||||
module availability. LADSPA IDs are not cryptographic binary/version identities.
|
code and do not certify module availability. LADSPA IDs are not cryptographic
|
||||||
|
binary/version identities.
|
||||||
|
|
||||||
## Repeatable acceptance
|
---
|
||||||
|
|
||||||
|
## Repeatable Acceptance
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
make all test gui test-plugins test-gui-plugins analyze
|
make all test gui test-plugins test-gui-plugins analyze
|
||||||
|
|
@ -91,9 +100,10 @@ The first plugin target builds an original MIT shared-library fixture with gain,
|
||||||
source, unsupported stereo and failed-initialization descriptors. Tests exercise
|
source, unsupported stereo and failed-initialization descriptors. Tests exercise
|
||||||
identity/range errors, exact in-place gain, save/reopen/exact rendering, missing
|
identity/range errors, exact in-place gain, save/reopen/exact rendering, missing
|
||||||
module metadata preservation and 100 plan replacements with callback guards
|
module metadata preservation and 100 plan replacements with callback guards
|
||||||
against host allocation/free/dlopen/dlclose. GUI commands cover add, control edit,
|
against host allocation/free/dlopen/dlclose. GUI commands cover add, control
|
||||||
invalid-value rollback, undo/redo and save/New/reopen. ASan/UBSan/leak checks cover
|
edit, invalid-value rollback, undo/redo and save/New/reopen. ASan/UBSan/leak
|
||||||
host/fixture lifetimes; plugin code from system packages is not instrumented.
|
checks cover host/fixture lifetimes; plugin code from system packages is not
|
||||||
|
instrumented.
|
||||||
|
|
||||||
`test-plugins-real` requires these separately installed modules (nothing is
|
`test-plugins-real` requires these separately installed modules (nothing is
|
||||||
bundled or installed by the target):
|
bundled or installed by the target):
|
||||||
|
|
@ -108,32 +118,35 @@ Tested packages: ladspa 1.17-7 and swh-plugins 0.4.17-7. These zero-latency
|
||||||
processors define the initial compatible set; other plugins remain unqualified.
|
processors define the initial compatible set; other plugins remain unqualified.
|
||||||
Physical listening and plugin CPU/endurance qualification remain pending.
|
Physical listening and plugin CPU/endurance qualification remain pending.
|
||||||
|
|
||||||
## Discovery, editing and graph lifecycle
|
---
|
||||||
|
|
||||||
|
## Discovery, Editing and Graph Lifecycle
|
||||||
|
|
||||||
Discovery remains explicit-file only, bounded to 1024 descriptor indices; no
|
Discovery remains explicit-file only, bounded to 1024 descriptor indices; no
|
||||||
recursive scan, plugin database or new dependency is introduced. Unsupported
|
recursive scan, plugin database or new dependency is introduced. Unsupported
|
||||||
layouts are skipped with counts; source/effect roles describe audio ports, not
|
layouts are skipped with counts; source/effect roles describe audio ports, not
|
||||||
MIDI instrument capabilities. Modern track instruments are described below. LADSPA sources can be identified, edited, replaced and removed in
|
MIDI instrument capabilities. Modern track instruments are described below.
|
||||||
the graph but cannot receive MIDI events.
|
LADSPA sources can be identified, edited, replaced and removed in the graph but
|
||||||
|
cannot receive MIDI events.
|
||||||
|
|
||||||
**Edit → Insert LADSPA on selected wire** replaces one existing connection with
|
**Edit → Insert LADSPA on selected wire** replaces one existing connection with
|
||||||
`source -> effect -> destination`, as one undo step. Only one-input effects are
|
`source -> effect -> destination`, as one undo step. Only one-input effects are
|
||||||
accepted; stale wires, capacity failures and initialization failures retain the
|
accepted; stale wires, capacity failures and initialization failures retain the
|
||||||
original graph. **Edit → Replace selected plugin** accepts the same audio input
|
original graph. **Edit → Replace selected plugin** accepts the same audio input
|
||||||
layout, keeps the node ID and all wires, and installs the new descriptor's default
|
layout, keeps the node ID and all wires, and installs the new descriptor's
|
||||||
controls with no inherited automation. It can replace from another module.
|
default controls with no inherited automation. It can replace from another
|
||||||
A source/effect layout mismatch is rejected. Undo restores the old identity,
|
module. A source/effect layout mismatch is rejected. Undo restores the old
|
||||||
values and automation. Every candidate is compiled before adoption even when
|
identity, values and automation. Every candidate is compiled before adoption
|
||||||
the backend is disconnected; no intermediate graph is published.
|
even when the backend is disconnected; no intermediate graph is published.
|
||||||
|
|
||||||
Ordering is graph signal flow, not descriptor order, creation order or a flat
|
Ordering is graph signal flow, not descriptor order, creation order or a flat
|
||||||
rack. Use the graph's connection/disconnection tools to place effects in series
|
rack. Use the graph's connection/disconnection tools to place effects in series
|
||||||
or parallel. Insertion on a wire preserves its endpoints and changes only that
|
or parallel. Insertion on a wire preserves its endpoints and changes only that
|
||||||
stage. Select a plugin and Delete to remove it and incident wires, then reconnect
|
stage. Select a plugin and Delete to remove it and incident wires, then
|
||||||
as desired; deletion does not automatically bridge or sum routes. A now-unwired
|
reconnect as desired; deletion does not automatically bridge or sum routes. A
|
||||||
effect receives external audio, following existing graph semantics. Undo/redo
|
now-unwired effect receives external audio, following existing graph semantics.
|
||||||
restores removal and routing. Independent bus inserts are still outside the
|
Undo/redo restores removal and routing. Independent bus inserts are still
|
||||||
shared-source graph model.
|
outside the shared-source graph model.
|
||||||
|
|
||||||
Reset defaults in the editor previews every control's declared/default-derived
|
Reset defaults in the editor previews every control's declared/default-derived
|
||||||
value. Apply also clears that plugin's automation; Cancel preserves it. The
|
value. Apply also clears that plugin's automation; Cancel preserves it. The
|
||||||
|
|
@ -156,8 +169,8 @@ validated; impossible defaults fail discovery rather than reaching the engine.
|
||||||
The generic modal editor owns copied metadata and temporary widget values only.
|
The generic modal editor owns copied metadata and temporary widget values only.
|
||||||
It never owns or retains module handles, descriptors or audio instance pointers.
|
It never owns or retains module handles, descriptors or audio instance pointers.
|
||||||
Closing it cannot unload active DSP; Apply builds a new immutable plan before
|
Closing it cannot unload active DSP; Apply builds a new immutable plan before
|
||||||
installation and existing retirement/quiescence rules release old instances.
|
installation and existing retirement/quiescence rules release old instances. No
|
||||||
No embedded third-party editor UI is supported.
|
embedded third-party editor UI is supported.
|
||||||
|
|
||||||
### Compatibility and recovery
|
### Compatibility and recovery
|
||||||
|
|
||||||
|
|
@ -174,8 +187,8 @@ Missing/incompatible modules reject GUI Open with the offending label/path and
|
||||||
leave the current project intact. Restore a compatible module at that path and
|
leave the current project intact. Restore a compatible module at that path and
|
||||||
retry; use metadata-only validation/save to preserve an unavailable module's
|
retry; use metadata-only validation/save to preserve an unavailable module's
|
||||||
records. No dummy replacement silently removes its controls. Failed discovery,
|
records. No dummy replacement silently removes its controls. Failed discovery,
|
||||||
replacement or instantiate reports an error and retains the current document.
|
replacement or instantiate reports an error and retains the current document. A
|
||||||
A LADSPA `run` callback has no error return; finite-sample sanitation does not
|
LADSPA `run` callback has no error return; finite-sample sanitation does not
|
||||||
contain crashes, hangs, memory corruption or prohibited work inside a plugin.
|
contain crashes, hangs, memory corruption or prohibited work inside a plugin.
|
||||||
Only trusted in-process plugins are supported. See RECOVERY.md.
|
Only trusted in-process plugins are supported. See RECOVERY.md.
|
||||||
|
|
||||||
|
|
@ -193,71 +206,83 @@ cover process-error silence/reset. The separately installed amp/inverter/sine
|
||||||
modules remain the qualified LADSPA set. Human listening, arbitrary third-party
|
modules remain the qualified LADSPA set. Human listening, arbitrary third-party
|
||||||
editors/plugins and extended realtime endurance remain unverified.
|
editors/plugins and extended realtime endurance remain unverified.
|
||||||
|
|
||||||
## Parameter targets
|
---
|
||||||
|
|
||||||
|
## Parameter Targets
|
||||||
|
|
||||||
`xtc_control.h` supplies common stable owner/parameter IDs and control-thread
|
`xtc_control.h` supplies common stable owner/parameter IDs and control-thread
|
||||||
metadata/edit APIs for track/bus gain/pan and LADSPA input ports. The GUI's plugin
|
metadata/edit APIs for track/bus gain/pan and LADSPA input ports. The GUI's
|
||||||
automation command uses this contract. Linear/hold LADSPA encoding and its
|
plugin automation command uses this contract. Linear/hold LADSPA encoding and
|
||||||
integer/toggle restrictions remain unchanged; v10 adds mixer interpolation and
|
its integer/toggle restrictions remain unchanged; v10 adds mixer interpolation
|
||||||
live-sine CC maps without changing plugin state records. Direct static edits do
|
and live-sine CC maps without changing plugin state records. Direct static edits
|
||||||
not override existing lanes. Live CCs do not map to plugins; missing targets or
|
do not override existing lanes. Live CCs do not map to plugins; missing targets
|
||||||
modules fail without installing partial state. See CONTROL.md for timing,
|
or modules fail without installing partial state. See CONTROL.md for timing,
|
||||||
precedence, reset and backward-jump behavior.
|
precedence, reset and backward-jump behavior.
|
||||||
|
|
||||||
## CLAP, VST2 and VST3 effect loaders
|
---
|
||||||
|
|
||||||
**File → Load plugin** now detects LADSPA, CLAP, VST2 and VST3 entry points in an
|
## CLAP, VST2 and VST3 Effect Loaders
|
||||||
explicit trusted Linux module. **Insert plugin on selected wire** and **Replace
|
|
||||||
selected plugin** use the same browser and transactional graph preparation. The
|
|
||||||
identity/editor dialog names the format and stable ID. Existing LADSPA controls
|
|
||||||
and automation continue to work. Modern effects currently use their default
|
|
||||||
configuration: the editor shows identity but no editable parameters.
|
|
||||||
|
|
||||||
Choose the actual binary: `.clap` for CLAP, a VST2 `.so` exporting `VSTPluginMain`,
|
**File → Load plugin** now detects LADSPA, CLAP, VST2 and VST3 entry points in
|
||||||
or a VST3 bundle's `Contents/<architecture>-linux/<module>.so` exporting
|
an explicit trusted Linux module. **Insert plugin on selected wire** and
|
||||||
`ModuleEntry`, `ModuleExit` and `GetPluginFactory`. The chooser does not resolve
|
**Replace selected plugin** use the same browser and transactional graph
|
||||||
bundle directories or recursively scan plugin folders. On Linux this avoids
|
preparation. The identity/editor dialog names the format and stable ID. Existing
|
||||||
executing unrelated plugins just to discover one selected module. Auto-detection
|
LADSPA controls and automation continue to work. Modern effects currently use
|
||||||
prefers CLAP, then VST2, then VST3, otherwise LADSPA; the C API also provides
|
their default configuration: the editor shows identity but no editable
|
||||||
`xtc_plugin_probe_format` for an explicit format.
|
parameters.
|
||||||
|
|
||||||
The modern subset is **one mono audio input and one mono output, float32, default
|
Choose the actual binary: `.clap` for CLAP, a VST2 `.so` exporting
|
||||||
configuration, zero reported latency**. Stereo graph playback uses independent
|
`VSTPluginMain`, or a VST3 bundle's `Contents/<architecture>-linux/<module>.so`
|
||||||
instances. For the modern effect subset, true stereo/multichannel/sidechain buses, instruments, MIDI/events,
|
exporting `ModuleEntry`, `ModuleExit` and `GetPluginFactory`. The chooser does
|
||||||
custom editors, parameter changes/automation, programs/presets, opaque state,
|
not resolve bundle directories or recursively scan plugin folders. On Linux this
|
||||||
transport/time information, workers and latency compensation are not implemented
|
avoids executing unrelated plugins just to discover one selected module.
|
||||||
for these three formats. Modern metadata with controls/automation is rejected,
|
Auto-detection prefers CLAP, then VST2, then VST3, otherwise LADSPA; the C API
|
||||||
not silently ignored. VST3 event buses and CLAP note ports are rejected. Plugins
|
also provides `xtc_plugin_probe_format` for an explicit format.
|
||||||
|
|
||||||
|
The modern subset is **one mono audio input and one mono output, float32,
|
||||||
|
default configuration, zero reported latency**. Stereo graph playback uses
|
||||||
|
independent instances. For the modern effect subset, true
|
||||||
|
stereo/multichannel/sidechain buses, instruments, MIDI/events, custom editors,
|
||||||
|
parameter changes/automation, programs/presets, opaque state, transport/time
|
||||||
|
information, workers and latency compensation are not implemented for these
|
||||||
|
three formats. Modern metadata with controls/automation is rejected, not
|
||||||
|
silently ignored. VST3 event buses and CLAP note ports are rejected. Plugins
|
||||||
requiring unsupported host extensions may refuse initialization. This is not a
|
requiring unsupported host extensions may refuse initialization. This is not a
|
||||||
claim that all CLAP/VST2/VST3 plugins will load or sound identically after updates.
|
claim that all CLAP/VST2/VST3 plugins will load or sound identically after
|
||||||
|
updates.
|
||||||
|
|
||||||
Only original effect fixtures have been qualified for the new formats. Trusted
|
Only original effect fixtures have been qualified for the new formats. Trusted
|
||||||
plugin code is in-process and can crash/hang or violate realtime rules. No plugin
|
plugin code is in-process and can crash/hang or violate realtime rules. No
|
||||||
binary is included in packages. A VST2 ABI adapter does not provide rights to the
|
plugin binary is included in packages. A VST2 ABI adapter does not provide
|
||||||
discontinued SDK or plugin redistribution. See decision 0010 and LICENSES.md.
|
rights to the discontinued SDK or plugin redistribution. See decision 0010 and
|
||||||
|
LICENSES.md.
|
||||||
|
|
||||||
The control/main thread owns discovery, activation, module reference accounting,
|
The control/main thread owns discovery, activation, module reference accounting,
|
||||||
retirement and unloading. CLAP's start-processing call runs on the audio owner;
|
retirement and unloading. CLAP's start-processing call runs on the audio owner;
|
||||||
main-thread callbacks are coalesced and serviced via `xtc_plugin_idle` (GUI timer,
|
main-thread callbacks are coalesced and serviced via `xtc_plugin_idle` (GUI
|
||||||
currently 100 ms). C hosts using CLAP must pump that API on their serialized main
|
timer, currently 100 ms). C hosts using CLAP must pump that API on their
|
||||||
thread while instances live, and stop/join audio before destruction. Restart and
|
serialized main thread while instances live, and stop/join audio before
|
||||||
VST2 I/O-change requests make subsequent blocks fail/silence; stop and rebuild or
|
destruction. Restart and VST2 I/O-change requests make subsequent blocks
|
||||||
reload the plugin rather than reconfiguring inside the callback. CLAP process
|
fail/silence; stop and rebuild or reload the plugin rather than reconfiguring
|
||||||
errors and VST3 failure results silence a block. VST2 has no process error return.
|
inside the callback. CLAP process errors and VST3 failure results silence a
|
||||||
|
block. VST2 has no process error return.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
make all test gui test-modern-plugins test-gui-modern-plugins
|
make all test gui test-modern-plugins test-gui-modern-plugins
|
||||||
make test-sanitize analyze
|
make test-sanitize analyze
|
||||||
```
|
```
|
||||||
|
|
||||||
Original CLAP/VST2/VST3 shared-library fixtures exercise exact in-place and stereo
|
Original CLAP/VST2/VST3 shared-library fixtures exercise exact in-place and
|
||||||
processing, entry/instance lifetimes, rejected layouts, partial initialization,
|
stereo processing, entry/instance lifetimes, rejected layouts, partial
|
||||||
CLAP start/process failures, graph replacement rollback, 50 plan retirements per
|
initialization, CLAP start/process failures, graph replacement rollback, 50 plan
|
||||||
format, missing modules, v11 save/reopen and GUI add/browser/undo/reopen. Host
|
retirements per format, missing modules, v11 save/reopen and GUI
|
||||||
allocation/loading/unloading guards remain active while rendering. This evidence
|
add/browser/undo/reopen. Host allocation/loading/unloading guards remain active
|
||||||
qualifies the subset above, not arbitrary external plugins or physical audio.
|
while rendering. This evidence qualifies the subset above, not arbitrary
|
||||||
|
external plugins or physical audio.
|
||||||
|
|
||||||
## Instrument support
|
---
|
||||||
|
|
||||||
|
## Instrument Support
|
||||||
|
|
||||||
MIDI tracks can bind CLAP, VST2 and VST3 instruments. In the Track menu, select
|
MIDI tracks can bind CLAP, VST2 and VST3 instruments. In the Track menu, select
|
||||||
**Load instrument plugin** for the selected sequencer track; **Use built-in
|
**Load instrument plugin** for the selected sequencer track; **Use built-in
|
||||||
|
|
@ -268,9 +293,9 @@ their own track's instrument. Independent instances feed track gain/pan,
|
||||||
mute/solo, bus routing and automation. Bindings/live target save in v12.
|
mute/solo, bus routing and automation. Bindings/live target save in v12.
|
||||||
|
|
||||||
Supply the actual trusted Linux binary (including the inner .so of a VST3
|
Supply the actual trusted Linux binary (including the inner .so of a VST3
|
||||||
bundle). Supported instruments have zero audio inputs, one mono output,
|
bundle). Supported instruments have zero audio inputs, one mono output, float32
|
||||||
float32 processing, zero latency and one note/event input. Default configuration
|
processing, zero latency and one note/event input. Default configuration only:
|
||||||
only: no custom editor, opaque state/preset restoration, modern parameter
|
no custom editor, opaque state/preset restoration, modern parameter
|
||||||
editing/automation, stereo/multichannel instruments or MIDI output. No arbitrary
|
editing/automation, stereo/multichannel instruments or MIDI output. No arbitrary
|
||||||
third-party instrument is qualified by the original ABI fixture tests.
|
third-party instrument is qualified by the original ABI fixture tests.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,21 @@
|
||||||
# Application preferences and looping
|
# Application Preferences and Looping
|
||||||
|
|
||||||
Open **Edit / Preferences** (Ctrl+,). Each tab edits application settings.
|
Open **Edit / Preferences** (Ctrl+,). Each tab edits application settings.
|
||||||
**Apply** validates every tab, saves `~/.xtc.conf`, and applies the values.
|
**Apply** validates every tab, saves `~/.xtc.conf`, and applies the values.
|
||||||
**Close** discards edits made since the last Apply. Apply stops playback; stop
|
**Close** discards edits made since the last Apply. Apply stops playback; stop
|
||||||
recording before opening Preferences. Clean exit also saves collected application settings.
|
recording before opening Preferences. Clean exit also saves collected
|
||||||
Startup reads `~/.xtc.conf` before project/backend creation; missing keys use defaults.
|
application settings. Startup reads `~/.xtc.conf` before project/backend
|
||||||
Malformed configuration reports an error and uses defaults without overwriting
|
creation; missing keys use defaults. Malformed configuration reports an error
|
||||||
it. Invalid input or failed writes preserve the previous saved configuration.
|
and uses defaults without overwriting it. Invalid input or failed writes
|
||||||
|
preserve the previous saved configuration.
|
||||||
|
|
||||||
The file is INI with `[audio]`, `[plugins]`, `[midi]`, `[interface]`, `[editing]`,
|
The file is INI with `[audio]`, `[plugins]`, `[midi]`, `[interface]`,
|
||||||
`[project_defaults]` and `[transport]` sections. Save uses a mode-0600 temporary
|
`[editing]`, `[project_defaults]` and `[transport]` sections. Save uses a
|
||||||
file, flushes and fsyncs it, then atomically renames it. Unknown keys/sections,
|
mode-0600 temporary file, flushes and fsyncs it, then atomically renames it.
|
||||||
duplicate keys, invalid ranges, embedded NULs and files larger than 64 KiB are
|
Unknown keys/sections, duplicate keys, invalid ranges, embedded NULs and files
|
||||||
rejected. Blank lines and full-line `;` / `#` comments are supported. Strings
|
larger than 64 KiB are rejected. Blank lines and full-line `;` / `#` comments
|
||||||
may be quoted, with `\\` and `\"` escapes. Apply rewrites comments and formatting.
|
are supported. Strings may be quoted, with `\\` and `\"` escapes. Apply rewrites
|
||||||
|
comments and formatting.
|
||||||
|
|
||||||
| Section | Settings and defaults |
|
| Section | Settings and defaults |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
|
|
@ -30,37 +32,41 @@ Audio client name, block capacity, output channels and fades take effect on
|
||||||
these remain JACK server settings. Offline rate is used when disconnected.
|
these remain JACK server settings. Offline rate is used when disconnected.
|
||||||
Recording capacity applies to the next take. Tempo and CC maps apply to **New**
|
Recording capacity applies to the next take. Tempo and CC maps apply to **New**
|
||||||
projects. Track mix, routing, instruments, plugin parameters, automation and
|
projects. Track mix, routing, instruments, plugin parameters, automation and
|
||||||
musical content remain project data, saved through Save Project. Internal
|
musical content remain project data, saved through Save Project. Internal safety
|
||||||
safety limits and plugin ABI requirements are not runtime preferences.
|
limits and plugin ABI requirements are not runtime preferences.
|
||||||
|
|
||||||
Snap accepts 1 (Off), 120, 160, 240, 320, 480, 960, 1920 or 3840 ticks.
|
Snap accepts 1 (Off), 120, 160, 240, 320, 480, 960, 1920 or 3840 ticks. Zoom
|
||||||
Zoom accepts 24, 48, 96, 192 or 384 pixels per beat. MIDI channels are zero-based;
|
accepts 24, 48, 96, 192 or 384 pixels per beat. MIDI channels are zero-based;
|
||||||
filter channel -1 shows all channels. Window sizes, grids and filters currently
|
filter channel -1 shows all channels. Window sizes, grids and filters currently
|
||||||
in use populate Preferences when it opens; Apply or a clean application exit persists them.
|
in use populate Preferences when it opens; Apply or a clean application exit
|
||||||
|
persists them.
|
||||||
|
|
||||||
Plugin selection now opens a library of `.clap` and `.so` files from the search
|
Plugin selection now opens a library of `.clap` and `.so` files from the search
|
||||||
paths. `~/` expands to the home directory; empty/nonabsolute roots are skipped.
|
paths. `~/` expands to the home directory; empty/nonabsolute roots are skipped.
|
||||||
Traversal does not follow directory symlinks and stops at depth six, 4096 entries
|
Traversal does not follow directory symlinks and stops at depth six, 4096
|
||||||
or 512 files. Linux VST3 bundle binaries are found inside bundle directories.
|
entries or 512 files. Linux VST3 bundle binaries are found inside bundle
|
||||||
Listing reads filenames only. **Inspect plugin** explicitly loads the selected
|
directories. Listing reads filenames only. **Inspect plugin** explicitly loads
|
||||||
trusted binary through the existing descriptor chooser; **Browse files** allows
|
the selected trusted binary through the existing descriptor chooser; **Browse
|
||||||
other locations. It is not a plugin certification or isolation service.
|
files** allows other locations. It is not a plugin certification or isolation
|
||||||
|
service.
|
||||||
|
|
||||||
## Loop playback
|
---
|
||||||
|
|
||||||
|
## Loop Playback
|
||||||
|
|
||||||
**Shift-drag the sequencer ruler** to select a region using the selected Snap.
|
**Shift-drag the sequencer ruler** to select a region using the selected Snap.
|
||||||
Dragging in either direction works. A band shows the region; **Loop** enables
|
Dragging in either direction works. A band shows the region; **Loop** enables or
|
||||||
or disables it. **Loop range...** also accepts start and end in ticks. Selection
|
disables it. **Loop range...** also accepts start and end in ticks. Selection
|
||||||
and toggling take effect immediately; Apply or clean exit persists the region.
|
and toggling take effect immediately; Apply or clean exit persists the region.
|
||||||
The region is global application configuration and is not stored in `.xtc`
|
The region is global application configuration and is not stored in `.xtc`
|
||||||
projects. Changing a region during playback stops, reconfigures and restarts the
|
projects. Changing a region during playback stops, reconfigures and restarts the
|
||||||
backend. Selecting a region does not itself enable looping.
|
backend. Selecting a region does not itself enable looping.
|
||||||
|
|
||||||
Playback wraps at the exclusive end sample, including inside an audio block,
|
Playback wraps at the exclusive end sample, including inside an audio block, and
|
||||||
and starts at the region beginning when the transport lies outside the region.
|
starts at the region beginning when the transport lies outside the region. The
|
||||||
The region follows the current project's tempo. Enabled regions must span at
|
region follows the current project's tempo. Enabled regions must span at least
|
||||||
least 64 samples at the active rate. Scheduled MIDI uses the existing seek/reset
|
64 samples at the active rate. Scheduled MIDI uses the existing seek/reset and
|
||||||
and note-chase behavior at a wrap. Effects retain tails/state. No loop-boundary
|
note-chase behavior at a wrap. Effects retain tails/state. No loop-boundary
|
||||||
crossfade is added, so discontinuous audio can click. Recording requires looping
|
crossfade is added, so discontinuous audio can click. Recording requires looping
|
||||||
to be disabled. Export retains its explicit linear range.
|
to be disabled. Export retains its explicit linear range.
|
||||||
|
|
||||||
|
|
@ -70,24 +76,25 @@ plus JACK callback wrap positions and existing GUI/core regressions. Tests use
|
||||||
temporary configuration paths and do not write the user's configuration.
|
temporary configuration paths and do not write the user's configuration.
|
||||||
|
|
||||||
`[transport] tail_ms=3000` (0..60000) and `stop_after_tail=0` (0/1) are
|
`[transport] tail_ms=3000` (0..60000) and `stop_after_tail=0` (0/1) are
|
||||||
supported. Export always includes the configured tail; optional
|
supported. Export always includes the configured tail; optional playback
|
||||||
playback stopping uses the GUI timer and is disabled during looping/recording.
|
stopping uses the GUI timer and is disabled during looping/recording. See
|
||||||
See BUILTIN_DEVICES.md for endpoint, cancellation and reset semantics.
|
BUILTIN_DEVICES.md for endpoint, cancellation and reset semantics.
|
||||||
|
|
||||||
`[interface]` provides `transport_detached`, `mixer_detached`, and each panel's
|
`[interface]` provides `transport_detached`, `mixer_detached`, and each panel's
|
||||||
`_x`, `_y`, `_width`, `_height` rectangle. Use Preferences / Apply or close the application cleanly after
|
`_x`, `_y`, `_width`, `_height` rectangle. Use Preferences / Apply or close the
|
||||||
moving panels to save the captured layout. Restoration clamps rectangles to the
|
application cleanly after moving panels to save the captured layout. Restoration
|
||||||
current display; the floating transport wraps at narrow widths.
|
clamps rectangles to the current display; the floating transport wraps at narrow
|
||||||
|
widths.
|
||||||
|
|
||||||
`[interface]` also includes `sequencer_detached`, `graph_detached`,
|
`[interface]` also includes `sequencer_detached`, `graph_detached`,
|
||||||
`piano_detached`, editor window geometry and `track_header_width` (180..360).
|
`piano_detached`, editor window geometry and `track_header_width` (180..360).
|
||||||
Piano retains `piano_width`/`piano_height` and adds `piano_x`/`piano_y`.
|
Piano retains `piano_width`/`piano_height` and adds `piano_x`/`piano_y`. Reset
|
||||||
Reset workspace layout changes the session; Preferences / Apply or clean exit persists it.
|
workspace layout changes the session; Preferences / Apply or clean exit persists
|
||||||
Only original-tab docking and floating windows are supported.
|
it. Only original-tab docking and floating windows are supported.
|
||||||
|
|
||||||
Configuration also includes complete workspace collection and MIDI
|
Configuration also includes complete workspace collection and MIDI
|
||||||
ports/channels/thru. Invalid startup files are preserved on exit; explicit Apply
|
ports/channels/thru. Invalid startup files are preserved on exit; explicit Apply
|
||||||
can replace them after validation. If saving fails, the window stays open for
|
can replace them after validation. If saving fails, the window stays open for
|
||||||
retry. See [MIDI_WORKFLOWS.md](MIDI_WORKFLOWS.md) for device setup and notes-only
|
retry. See [MIDI_WORKFLOWS.md](MIDI_WORKFLOWS.md) for device setup and
|
||||||
Standard MIDI File import/export. JACK server hardware settings and musical
|
notes-only Standard MIDI File import/export. JACK server hardware settings and
|
||||||
project contents remain owned by the server and project respectively.
|
musical project contents remain owned by the server and project respectively.
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,17 @@
|
||||||
# Project format v17 (reads v1–v17)
|
# Project Format v17 (Reads v1–v17)
|
||||||
|
|
||||||
The project uses a bounded text format implemented in C99 without a parser library.
|
The project uses a bounded text format implemented in C99 without a parser
|
||||||
The extension is `.xtc`. File operations run exclusively on the control thread.
|
library. The extension is `.xtc`. File operations run exclusively on the control
|
||||||
The project owns its graph, tracks and silent/audio arrangement regions. Audio samples remain in external WAV
|
thread. The project owns its graph, tracks and silent/audio arrangement regions.
|
||||||
files; MIDI notes are stored inline.
|
Audio samples remain in external WAV files; MIDI notes are stored inline.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Schema
|
## Schema
|
||||||
|
|
||||||
Records occur in this exact order, separated by LF, including the final record.
|
Records occur in this exact order, separated by LF, including the final record.
|
||||||
Fields use ASCII spaces. Integers are unsigned decimal, without signs.
|
Fields use ASCII spaces. Integers are unsigned decimal, without signs. Counts
|
||||||
Counts determine the number of subsequent records:
|
determine the number of subsequent records:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
XTC_PROJECT 11
|
XTC_PROJECT 11
|
||||||
|
|
@ -55,37 +57,38 @@ END
|
||||||
- `TEMPO`: constant milli-BPM (20000..300000, default 120000), fixed 4/4.
|
- `TEMPO`: constant milli-BPM (20000..300000, default 120000), fixed 4/4.
|
||||||
- `IDS`: next track ID and next clip ID. IDs are uint64, monotonic and never
|
- `IDS`: next track ID and next clip ID. IDs are uint64, monotonic and never
|
||||||
reused; UINT64_MAX is reserved. Track and clip ID namespaces are separate.
|
reused; UINT64_MAX is reserved. Track and clip ID namespaces are separate.
|
||||||
- `GRAPH`: output-node policy (0/1), next node ID, node count, edge count.
|
- `GRAPH`: output-node policy (0/1), next node ID, node count, edge count. Nodes
|
||||||
Nodes retain stable IDs (limited to the host's size_t range). No pointers or
|
retain stable IDs (limited to the host's size_t range). No pointers or
|
||||||
compiled state are serialized.
|
compiled state are serialized.
|
||||||
- `NODE`: ID, type (1 gain, 2 oscillator, 3 meter, 4 output, 5 audio source, 6 instrument, 8 LADSPA plugin), and exactly eight
|
- `NODE`: ID, type (1 gain, 2 oscillator, 3 meter, 4 output, 5 audio source, 6
|
||||||
hexadecimal digits encoding the IEEE binary32 parameter bits, independent
|
instrument, 8 LADSPA plugin), and exactly eight hexadecimal digits encoding
|
||||||
of locale and host byte order. Nonfinite values are rejected.
|
the IEEE binary32 parameter bits, independent of locale and host byte order.
|
||||||
- `EDGE`: source and destination node IDs. Port directions are implied
|
Nonfinite values are rejected.
|
||||||
by node type; endpoints, duplicates and cycles are validated by the graph API.
|
- `EDGE`: source and destination node IDs. Port directions are implied by node
|
||||||
|
type; endpoints, duplicates and cycles are validated by the graph API.
|
||||||
- `TRACK`: ID and hex-encoded name bytes. In v4/v5 each is immediately followed
|
- `TRACK`: ID and hex-encoded name bytes. In v4/v5 each is immediately followed
|
||||||
by `MIX gain_bits pan_bits mute solo`: finite binary32 gain 0..4, pan -1..1
|
by `MIX gain_bits pan_bits mute solo`: finite binary32 gain 0..4, pan -1..1
|
||||||
encoded as eight hex digits, mute and solo unsigned 0/1.
|
encoded as eight hex digits, mute and solo unsigned 0/1.
|
||||||
- `ROUTE`: since v9, required after MIX: bus flag and destination bus ID;
|
- `ROUTE`: since v9, required after MIX: bus flag and destination bus ID;
|
||||||
UINT64_MAX denotes master. See the mix routing constraints below.
|
UINT64_MAX denotes master. See the mix routing constraints below.
|
||||||
- `CLIP`: ID, track ID, start tick, length tick, source offset tick, source
|
- `CLIP`: ID, track ID, start tick, length tick, source offset tick, source
|
||||||
length tick, hex-encoded name bytes. Trimming
|
length tick, hex-encoded name bytes. Trimming preserves source bounds, so a
|
||||||
preserves source bounds, so a region can re-extend only within its original
|
region can re-extend only within its original length. Overlaps are allowed and
|
||||||
length. Overlaps are allowed and audio clips mix through the audio source node.
|
audio clips mix through the audio source node.
|
||||||
- `ASSET`: required after each CLIP in v2/v3/v4/v5; "-" means no audio asset, otherwise
|
- `ASSET`: required after each CLIP in v2/v3/v4/v5; "-" means no audio asset,
|
||||||
hex-encoded absolute path bytes, <=511 bytes after decoding, no embedded NUL
|
otherwise hex-encoded absolute path bytes, <=511 bytes after decoding, no
|
||||||
or ASCII control characters. Each clip directly references a WAV; no sample
|
embedded NUL or ASCII control characters. Each clip directly references a WAV;
|
||||||
data, pointers or DSP state are embedded. Paths can contain spaces.
|
no sample data, pointers or DSP state are embedded. Paths can contain spaces.
|
||||||
- `MIDI`: required after each ASSET in v3/v4/v5; 0 for silent/audio regions, 1 for
|
- `MIDI`: required after each ASSET in v3/v4/v5; 0 for silent/audio regions, 1
|
||||||
MIDI clips. MIDI clips must have no asset.
|
for MIDI clips. MIDI clips must have no asset.
|
||||||
- `NOTES`: next stable note ID and global note count, followed by that many
|
- `NOTES`: next stable note ID and global note count, followed by that many
|
||||||
`NOTE id clip_id start_tick length_tick pitch velocity channel` records.
|
`NOTE id clip_id start_tick length_tick pitch velocity channel` records. Notes
|
||||||
Notes reference MIDI clips; start/length are source-relative, positive length
|
reference MIDI clips; start/length are source-relative, positive length within
|
||||||
within source bounds. Pitch is 0..127, velocity 1..127, channel 0..15.
|
source bounds. Pitch is 0..127, velocity 1..127, channel 0..15. Note IDs are
|
||||||
Note IDs are unique, monotonic uint64 IDs with UINT64_MAX reserved.
|
unique, monotonic uint64 IDs with UINT64_MAX reserved.
|
||||||
- `AUTOMATION`: global point count, after the last NOTE and before END in v4/v5.
|
- `AUTOMATION`: global point count, after the last NOTE and before END in v4/v5.
|
||||||
Follow with `POINT track_id parameter tick value_bits step` in v10 (v4–v9
|
Follow with `POINT track_id parameter tick value_bits step` in v10 (v4–v9 omit
|
||||||
omit step and migrate to linear). Step is 0 linear or 1 hold for the next segment.
|
step and migrate to linear). Step is 0 linear or 1 hold for the next segment.
|
||||||
Parameter 0 is gain (0..4), 1 pan (-1..1); values use finite binary32 hex.
|
Parameter 0 is gain (0..4), 1 pan (-1..1); values use finite binary32 hex.
|
||||||
Track must exist; tick <= MAX_TICK; duplicate track/parameter/tick is invalid.
|
Track must exist; tick <= MAX_TICK; duplicate track/parameter/tick is invalid.
|
||||||
Record order is preserved; rendering sorts a separate prepared copy.
|
Record order is preserved; rendering sorts a separate prepared copy.
|
||||||
|
|
@ -94,20 +97,24 @@ END
|
||||||
|
|
||||||
Ticks use 960 per quarter note, 3840 per bar. All region endpoints are bounded
|
Ticks use 960 per quarter note, 3840 per bar. All region endpoints are bounded
|
||||||
by 38400000 ticks (10000 bars). Limits: 64 tracks, 1024 clips, 64 graph nodes,
|
by 38400000 ticks (10000 bars). Limits: 64 tracks, 1024 clips, 64 graph nodes,
|
||||||
4096 edges, 4096 notes, 1024 automation points, 4 MiB input, 1535 bytes per record, 12 tokens per record. The reader
|
4096 edges, 4096 notes, 1024 automation points, 4 MiB input, 1535 bytes per
|
||||||
rejects invalid references, duplicate IDs, inconsistent next IDs, ranges,
|
record, 12 tokens per record. The reader rejects invalid references, duplicate
|
||||||
truncated records, raw control/non-ASCII bytes, and trailing data.
|
IDs, inconsistent next IDs, ranges, truncated records, raw control/non-ASCII
|
||||||
|
bytes, and trailing data.
|
||||||
|
|
||||||
Unsupported format versions return UNSUPPORTED. Other malformed data returns
|
Unsupported format versions return UNSUPPORTED. Other malformed data returns
|
||||||
FORMAT. The reader explicitly accepts v1 records without ASSET lines, with
|
FORMAT. The reader explicitly accepts v1 records without ASSET lines, with node
|
||||||
node types 1..4, migrating their clips to empty asset paths. Version 2 accepts
|
types 1..4, migrating their clips to empty asset paths. Version 2 accepts node
|
||||||
node types 1..5 and ASSET records. Both migrate to MIDI=0 and no notes.
|
types 1..5 and ASSET records. Both migrate to MIDI=0 and no notes. Version 3
|
||||||
Version 3 accepts instrument nodes and MIDI/NOTES records. Versions 1–3 migrate
|
accepts instrument nodes and MIDI/NOTES records. Versions 1–3 migrate all tracks
|
||||||
all tracks to unity gain, centered pan, mute/solo off and no automation.
|
to unity gain, centered pan, mute/solo off and no automation. Saving always
|
||||||
Saving always writes v15. Unknown versions are rejected without replacing the destination; older
|
writes v15. Unknown versions are rejected without replacing the destination;
|
||||||
applications without v12 support cannot read current saves. Migration and maximum-path roundtrips are tested.
|
older applications without v12 support cannot read current saves. Migration and
|
||||||
|
maximum-path roundtrips are tested.
|
||||||
|
|
||||||
## Ownership and failures
|
---
|
||||||
|
|
||||||
|
## Ownership and Failures
|
||||||
|
|
||||||
Load builds and validates a separate candidate, closes the input, then replaces
|
Load builds and validates a separate candidate, closes the input, then replaces
|
||||||
the destination. Any failure retains the complete previous project. Saving
|
the destination. Any failure retains the complete previous project. Saving
|
||||||
|
|
@ -116,35 +123,42 @@ directory, writes, flushes, fsyncs, closes and renames over the destination.
|
||||||
Failures before rename retain the previous destination and remove the temporary.
|
Failures before rename retain the previous destination and remove the temporary.
|
||||||
After rename, the parent directory is fsynced. A directory-sync failure reports
|
After rename, the parent directory is fsynced. A directory-sync failure reports
|
||||||
I/O error even though the new complete destination may already be present.
|
I/O error even though the new complete destination may already be present.
|
||||||
Storage and filesystem behavior still determine power-loss durability. Save replaces symlinks themselves and does not preserve
|
Storage and filesystem behavior still determine power-loss durability. Save
|
||||||
existing file permissions. POSIX I/O is private to the Linux-first persistence
|
replaces symlinks themselves and does not preserve existing file permissions.
|
||||||
module; public headers contain no POSIX types.
|
POSIX I/O is private to the Linux-first persistence module; public headers
|
||||||
|
contain no POSIX types.
|
||||||
|
|
||||||
Saved data reproduces the arrangement, graph, track mix and automation, including
|
Saved data reproduces the arrangement, graph, track mix and automation,
|
||||||
ID allocation state. Undo history is not saved. See MIXER.md for pan/interpolation.
|
including ID allocation state. Undo history is not saved. See MIXER.md for
|
||||||
Graph node positions, timeline zoom/scroll/selection, transport position and DSP
|
pan/interpolation. Graph node positions, timeline zoom/scroll/selection,
|
||||||
oscillator phase are GUI/session state and are not saved. Asset references are
|
transport position and DSP oscillator phase are GUI/session state and are not
|
||||||
absolute in memory; saves use relative paths for media inside the project folder,
|
saved. Asset references are absolute in memory; saves use relative paths for
|
||||||
otherwise absolute paths. Media are not copied on Save As. Metadata loading preserves
|
media inside the project folder, otherwise absolute paths. Media are not copied
|
||||||
missing references; audio-plan preparation reports unreadable/invalid assets
|
on Save As. Metadata loading preserves missing references; audio-plan
|
||||||
and renders them silently. Relinking replaces a selected clip's path without
|
preparation reports unreadable/invalid assets and renders them silently.
|
||||||
changing its IDs or arrangement. See AUDIO_FILES.md for recovery and limitations.
|
Relinking replaces a selected clip's path without changing its IDs or
|
||||||
|
arrangement. See AUDIO_FILES.md for recovery and limitations.
|
||||||
|
|
||||||
## Extension and recovery policy
|
---
|
||||||
|
|
||||||
Format v4 was retained. Native processor descriptors are process-local and have no
|
## Extension and Recovery Policy
|
||||||
serialized representation; saving a native graph returns UNSUPPORTED and retains
|
|
||||||
the existing destination. Unknown file versions/types remain rejected. See
|
|
||||||
NATIVE_API.md for the extension boundary and RECOVERY.md for write-failure, killed
|
|
||||||
writer and unfinished-recording behavior. Metadata validation is available via
|
|
||||||
`xtc-check --validate PROJECT` without a GUI or server; it does not load assets.
|
|
||||||
|
|
||||||
## Version 5: plugin metadata
|
Format v4 was retained. Native processor descriptors are process-local and have
|
||||||
|
no serialized representation; saving a native graph returns UNSUPPORTED and
|
||||||
|
retains the existing destination. Unknown file versions/types remain rejected.
|
||||||
|
See NATIVE_API.md for the extension boundary and RECOVERY.md for write-failure,
|
||||||
|
killed writer and unfinished-recording behavior. Metadata validation is
|
||||||
|
available via `xtc-check --validate PROJECT` without a GUI or server; it does
|
||||||
|
not load assets.
|
||||||
|
|
||||||
`XTC_PROJECT 5` was introduced; its reader also supported versions 1–4. All v4 records and
|
---
|
||||||
order remain the same. Node type 8 is a LADSPA plugin; native pointer-bearing type
|
|
||||||
7 is still unsupported in files. Immediately after each type-8 `NODE id 8
|
## Version 5: Plugin Metadata
|
||||||
00000000` record come:
|
|
||||||
|
`XTC_PROJECT 5` was introduced; its reader also supported versions 1–4. All v4
|
||||||
|
records and order remain the same. Node type 8 is a LADSPA plugin; native
|
||||||
|
pointer-bearing type 7 is still unsupported in files. Immediately after each
|
||||||
|
type-8 `NODE id 8 00000000` record come:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
PLUGIN unique_id descriptor_index mono_inputs control_count hex_label
|
PLUGIN unique_id descriptor_index mono_inputs control_count hex_label
|
||||||
|
|
@ -155,130 +169,153 @@ CONTROL port_index float32_hex_bits
|
||||||
There are exactly `control_count` CONTROL records. Label length is 1–63 bytes,
|
There are exactly `control_count` CONTROL records. Label length is 1–63 bytes,
|
||||||
module path 1–511 bytes (absolute), both hex-encoded with no embedded NUL. Index
|
module path 1–511 bytes (absolute), both hex-encoded with no embedded NUL. Index
|
||||||
is <1024, mono_inputs 0/1, controls <=16, control port indices <64 strictly
|
is <1024, mono_inputs 0/1, controls <=16, control port indices <64 strictly
|
||||||
increasing, and values finite. Unique ID fits uint32. The one output is implicit.
|
increasing, and values finite. Unique ID fits uint32. The one output is
|
||||||
Structural validation never opens libraries. On graph compilation the host checks
|
implicit. Structural validation never opens libraries. On graph compilation the
|
||||||
identity, layout, input control port IDs and rate-adjusted legal ranges against
|
host checks identity, layout, input control port IDs and rate-adjusted legal
|
||||||
the module. Unknown nodes/versions fail without mutating the current project.
|
ranges against the module. Unknown nodes/versions fail without mutating the
|
||||||
Missing modules remain preserved by metadata load/save; GUI installation rejects
|
current project. Missing modules remain preserved by metadata load/save; GUI
|
||||||
them with a repair message. No transient DSP state, pointer or plugin binary is
|
installation rejects them with a repair message. No transient DSP state, pointer
|
||||||
stored. See PLUGIN_HOSTING.md and decision 0009 for supported processors/limits.
|
or plugin binary is stored. See PLUGIN_HOSTING.md and decision 0009 for
|
||||||
|
supported processors/limits.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Version 6
|
## Version 6
|
||||||
|
|
||||||
Version 6 was introduced and its reader accepted v1–v6. After each plugin's CONTROL records,
|
Version 6 was introduced and its reader accepted v1–v6. After each plugin's
|
||||||
`PLUGIN_AUTOMATION count` is followed by exactly count (<=32) records:
|
CONTROL records, `PLUGIN_AUTOMATION count` is followed by exactly count (<=32)
|
||||||
`PARAM tick port mode float32_hex_bits`. Mode is 0 linear or 1 step. Duplicate
|
records: `PARAM tick port mode float32_hex_bits`. Mode is 0 linear or 1 step.
|
||||||
port/tick pairs, nonfinite values, unknown control ports and ticks beyond the
|
Duplicate port/tick pairs, nonfinite values, unknown control ports and ticks
|
||||||
project limit are rejected. Loaded plugin tempo comes from TEMPO. Range and
|
beyond the project limit are rejected. Loaded plugin tempo comes from TEMPO.
|
||||||
discrete-mode compatibility are checked on control-thread compilation. Versions
|
Range and discrete-mode compatibility are checked on control-thread compilation.
|
||||||
1–5 migrate with empty plugin lanes. See CONTROL.md for timing/ordering.
|
Versions 1–5 migrate with empty plugin lanes. See CONTROL.md for
|
||||||
|
timing/ordering.
|
||||||
|
|
||||||
## Version 7 and project folders
|
---
|
||||||
|
|
||||||
Version 7 was introduced; its readers migrated v1–v6. Record ordering and field bounds
|
## Version 7 and Project Folders
|
||||||
are otherwise unchanged from v6. v7 ASSET may contain a relative path, interpreted
|
|
||||||
against the actual containing directory of the named project file (resolved on
|
Version 7 was introduced; its readers migrated v1–v6. Record ordering and field
|
||||||
the control thread), never the launch working directory. Opening a symlink to a project uses the
|
bounds are otherwise unchanged from v6. v7 ASSET may contain a relative path,
|
||||||
resolved target project directory; Save replaces the named entry as before. After loading, all core
|
interpreted against the actual containing directory of the named project file
|
||||||
asset references are absolute, including missing media. Media inside the save
|
(resolved on the control thread), never the launch working directory. Opening a
|
||||||
folder are written relative; references outside remain absolute. Save As resolves
|
symlink to a project uses the resolved target project directory; Save replaces
|
||||||
against its new folder and preserves media identity rather than rebasing it by
|
the named entry as before. After loading, all core asset references are
|
||||||
accident. Copy/move a project folder together with its referenced media to retain
|
absolute, including missing media. Media inside the save folder are written
|
||||||
|
relative; references outside remain absolute. Save As resolves against its new
|
||||||
|
folder and preserves media identity rather than rebasing it by accident.
|
||||||
|
Copy/move a project folder together with its referenced media to retain
|
||||||
portability. Saving does not copy assets: import/record into that folder first.
|
portability. Saving does not copy assets: import/record into that folder first.
|
||||||
Plugin binaries remain trusted absolute module references, not bundled resources.
|
Plugin binaries remain trusted absolute module references, not bundled
|
||||||
|
resources.
|
||||||
|
|
||||||
Empty assets still use `-`. Paths exclude embedded NUL/control bytes and must fit
|
Empty assets still use `-`. Paths exclude embedded NUL/control bytes and must
|
||||||
511 bytes after resolution; overly long resolved references fail transactionally.
|
fit 511 bytes after resolution; overly long resolved references fail
|
||||||
Relative references can name outside the folder using ordinary POSIX semantics;
|
transactionally. Relative references can name outside the folder using ordinary
|
||||||
this is not a sandbox. Symlinks follow filesystem behavior, so portability requires
|
POSIX semantics; this is not a sandbox. Symlinks follow filesystem behavior, so
|
||||||
moving their targets too. Old formats continue to require absolute media paths.
|
portability requires moving their targets too. Old formats continue to require
|
||||||
No unknown version/node/record is silently discarded; unsupported versions/types
|
absolute media paths. No unknown version/node/record is silently discarded;
|
||||||
or malformed/trailing data reject the candidate and retain the current project.
|
unsupported versions/types or malformed/trailing data reject the candidate and
|
||||||
Parsing never opens media/plugins or constructs an audio engine.
|
retain the current project. Parsing never opens media/plugins or constructs an
|
||||||
|
audio engine.
|
||||||
|
|
||||||
Save validates the complete model, writes/fsyncs a same-folder temporary, closes
|
Save validates the complete model, writes/fsyncs a same-folder temporary, closes
|
||||||
it, atomically renames it, then fsyncs the containing directory. Failures before
|
it, atomically renames it, then fsyncs the containing directory. Failures before
|
||||||
rename retain the old destination. A directory sync failure *after* rename reports
|
rename retain the old destination. A directory sync failure *after* rename
|
||||||
I/O error but the new complete file may already be present: inspect/reopen it;
|
reports I/O error but the new complete file may already be present:
|
||||||
there is no rollback across that durability boundary. Filesystem/hardware power
|
inspect/reopen it; there is no rollback across that durability boundary.
|
||||||
loss guarantees still depend on the underlying storage. Recording destinations
|
Filesystem/hardware power loss guarantees still depend on the underlying
|
||||||
have their separate no-clobber policy; ordinary project Save intentionally replaces
|
storage. Recording destinations have their separate no-clobber policy; ordinary
|
||||||
the selected document. In-memory models and the existing destination are preserved
|
project Save intentionally replaces the selected document. In-memory models and
|
||||||
on load failure. No automatic unknown-field stripping or media deletion occurs.
|
the existing destination are preserved on load failure. No automatic
|
||||||
|
unknown-field stripping or media deletion occurs.
|
||||||
|
|
||||||
`make test-portability test test-plugins test-recovery test-recording` covers checked-in
|
`make test-portability test test-plugins test-recovery test-recording` covers
|
||||||
v1–v10 fixtures (including missing v5/v6 plugins), current exact roundtrips, moved-folder
|
checked-in v1–v10 fixtures (including missing v5/v6 plugins), current exact
|
||||||
playback from a different cwd, missing media retention, unknown records, every
|
roundtrips, moved-folder playback from a different cwd, missing media retention,
|
||||||
truncation and deterministic byte mutations, malformed plugin metadata, interrupted
|
unknown records, every truncation and deterministic byte mutations, malformed
|
||||||
writers and write-limit failures. ASan/UBSan/static analysis additionally audit the
|
plugin metadata, interrupted writers and write-limit failures. ASan/UBSan/static
|
||||||
bounded parser. This is regression/fault-injection coverage, not exhaustive fuzzing
|
analysis additionally audit the bounded parser. This is
|
||||||
or a claim of power-cut qualification.
|
regression/fault-injection coverage, not exhaustive fuzzing or a claim of
|
||||||
|
power-cut qualification.
|
||||||
|
|
||||||
## Version 8: audio clip settings
|
---
|
||||||
|
|
||||||
|
## Version 8: Audio Clip Settings
|
||||||
|
|
||||||
Version 8 adds audio clip gain/fade settings and reads v1–v7 with unity clip
|
Version 8 adds audio clip gain/fade settings and reads v1–v7 with unity clip
|
||||||
gain and no explicit clip fades. After **every** clip's `MIDI` record (including silent and MIDI
|
gain and no explicit clip fades. After **every** clip's `MIDI` record (including
|
||||||
clips), v8 requires:
|
silent and MIDI clips), v8 requires:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
AUDIO gain_float32_hex_bits fade_in_ticks fade_out_ticks
|
AUDIO gain_float32_hex_bits fade_in_ticks fade_out_ticks
|
||||||
```
|
```
|
||||||
|
|
||||||
Gain is finite, linear and within 0..4. Fade durations are unsigned decimal,
|
Gain is finite, linear and within 0..4. Fade durations are unsigned decimal,
|
||||||
0..source_length_tick; zero disables that explicit fade. MIDI clips require
|
0..source_length_tick; zero disables that explicit fade. MIDI clips require gain
|
||||||
gain exactly 1 and both fades zero. Invalid or missing AUDIO records reject the
|
exactly 1 and both fades zero. Invalid or missing AUDIO records reject the whole
|
||||||
whole candidate. All v7 media-folder rules and atomic-save guarantees remain.
|
candidate. All v7 media-folder rules and atomic-save guarantees remain. Older
|
||||||
Older applications reject v8 rather than silently stripping clip settings.
|
applications reject v8 rather than silently stripping clip settings. Rebuild
|
||||||
Rebuild C/C++ consumers against the extended `xtc_clip_info` public struct;
|
C/C++ consumers against the extended `xtc_clip_info` public struct; this
|
||||||
this development release does not promise an unchanged struct binary layout.
|
development release does not promise an unchanged struct binary layout.
|
||||||
|
|
||||||
Fades follow the audible trimmed clip boundaries, in current-tempo ticks, with
|
Fades follow the audible trimmed clip boundaries, in current-tempo ticks, with
|
||||||
sample endpoints defined in AUDIO_FILES.md. Duplicating retains settings and
|
sample endpoints defined in AUDIO_FILES.md. Duplicating retains settings and
|
||||||
source references; splitting keeps the original ID on the left, gives the right
|
source references; splitting keeps the original ID on the left, gives the right
|
||||||
a fresh ID/source offset, retains outer explicit fades and clears inner ones.
|
a fresh ID/source offset, retains outer explicit fades and clears inner ones. No
|
||||||
No waveform cache or source audio is serialized. Checked-in v1–v7 migrations,
|
waveform cache or source audio is serialized. Checked-in v1–v7 migrations, v8
|
||||||
v8 exact roundtrips, malformed new metadata and byte-mutation tests cover the
|
exact roundtrips, malformed new metadata and byte-mutation tests cover the
|
||||||
format change (`make test test-portability test-audio-editing`).
|
format change (`make test test-portability test-audio-editing`).
|
||||||
|
|
||||||
## Version 9: mix routing
|
---
|
||||||
|
|
||||||
Version 9 adds `ROUTE is_bus bus_id` immediately after each TRACK's MIX record. `is_bus` is 0 or 1; `bus_id` is an existing bus track ID,
|
## Version 9: Mix Routing
|
||||||
or decimal UINT64_MAX (18446744073709551615) for master. Buses must route to
|
|
||||||
master and cannot contain clips. Invalid destinations, flags and nested routing
|
|
||||||
are rejected. v1–v8 migrate all tracks to ordinary direct-to-master tracks.
|
|
||||||
Bus controls and automation use existing MIX and POINT records. Older readers
|
|
||||||
reject v9 rather than discard routing. The public `xtc_track_info` grew fields;
|
|
||||||
API consumers must rebuild. Fixtures cover v1–v8 migration and tests exercise
|
|
||||||
v9 exact roundtrips and malformed routing.
|
|
||||||
|
|
||||||
## Version 10: interpolation and controller bindings
|
Version 9 adds `ROUTE is_bus bus_id` immediately after each TRACK's MIX record.
|
||||||
|
`is_bus` is 0 or 1; `bus_id` is an existing bus track ID, or decimal UINT64_MAX
|
||||||
|
(18446744073709551615) for master. Buses must route to master and cannot contain
|
||||||
|
clips. Invalid destinations, flags and nested routing are rejected. v1–v8
|
||||||
|
migrate all tracks to ordinary direct-to-master tracks. Bus controls and
|
||||||
|
automation use existing MIX and POINT records. Older readers reject v9 rather
|
||||||
|
than discard routing. The public `xtc_track_info` grew fields; API consumers
|
||||||
|
must rebuild. Fixtures cover v1–v8 migration and tests exercise v9 exact
|
||||||
|
roundtrips and malformed routing.
|
||||||
|
|
||||||
Version 10 adds interpolation modes and 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
|
## Version 10: Interpolation and Controller Bindings
|
||||||
`PARAM` encoding remains unchanged (already has interpolation mode).
|
|
||||||
|
Version 10 adds interpolation modes and 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).
|
||||||
|
|
||||||
Immediately after all POINT records, before END, v10 requires `CONTROL_MAPS 16`
|
Immediately after all POINT records, before END, v10 requires `CONTROL_MAPS 16`
|
||||||
and exactly 16 records in ascending channel order:
|
and exactly 16 records in ascending channel order:
|
||||||
`MAP channel volume_CC pan_CC sustain_CC`. Channels are 0..15. Controllers are
|
`MAP channel volume_CC pan_CC sustain_CC`. Channels are 0..15. Controllers are
|
||||||
0..127 or 128 (disabled); enabled numbers must be distinct within a row and may
|
0..127 or 128 (disabled); enabled numbers must be distinct within a row and may
|
||||||
not be 120 or 123. Duplicate/missing/out-of-order channels, invalid CCs, reserved
|
not be 120 or 123. Duplicate/missing/out-of-order channels, invalid CCs,
|
||||||
bindings and invalid interpolation modes reject the complete candidate. v1–v9
|
reserved bindings and invalid interpolation modes reject the complete candidate.
|
||||||
supply default 7/10/64 bindings on every channel. No event history/current live
|
v1–v9 supply default 7/10/64 bindings on every channel. No event history/current
|
||||||
controller values are serialized. Older readers reject v10.
|
live controller values are serialized. Older readers reject v10.
|
||||||
|
|
||||||
Fixtures cover v1–v10 loading and migration. Exact roundtrips, malformed metadata, step/linear
|
Fixtures cover v1–v10 loading and migration. Exact roundtrips, malformed
|
||||||
renders and remapped live events cover the new writer/reader. Public clients
|
metadata, step/linear renders and remapped live events cover the new
|
||||||
must rebuild and initialize the appended `xtc_automation_point.step` field.
|
writer/reader. Public clients must rebuild and initialize the appended
|
||||||
|
`xtc_automation_point.step` field.
|
||||||
|
|
||||||
## Compatibility and diagnostic contract
|
---
|
||||||
|
|
||||||
|
## Compatibility and Diagnostic Contract
|
||||||
|
|
||||||
The current reader accepts versions 1–15 and the writer always emits version 15.
|
The current reader accepts versions 1–15 and the writer always emits version 15.
|
||||||
Compatibility diagnostics made no format change; plugin format identity is added in v11. Saving an older document upgrades it;
|
Compatibility diagnostics made no format change; plugin format identity is added
|
||||||
retain an original backup if an older application must still open it. APP is
|
in v11. Saving an older document upgrades it; retain an original backup if an
|
||||||
informational; compatibility depends on the format version, not the producer's
|
older application must still open it. APP is informational; compatibility
|
||||||
application version. A future incompatible schema requires a new format number.
|
depends on the format version, not the producer's application version. A future
|
||||||
Public C/C++ consumers must rebuild when public structs change.
|
incompatible schema requires a new format number. Public C/C++ consumers must
|
||||||
|
rebuild when public structs change.
|
||||||
|
|
||||||
| Version | Added representation | Defaults when loading earlier versions |
|
| Version | Added representation | Defaults when loading earlier versions |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
|
|
@ -303,41 +340,47 @@ incompatible plugins retain the current document and identify the module.
|
||||||
Missing media references remain available for relinking and render silently.
|
Missing media references remain available for relinking and render silently.
|
||||||
|
|
||||||
`xtc_project_load_diagnostic` adds a copied result, parsed format version (zero
|
`xtc_project_load_diagnostic` adds a copied result, parsed format version (zero
|
||||||
if unavailable), expected record/stage and message. Syntax locations are 1-based;
|
if unavailable), expected record/stage and message. Syntax locations are
|
||||||
line zero denotes I/O, size, path resolution or whole-model validation. MODEL
|
1-based; line zero denotes I/O, size, path resolution or whole-model validation.
|
||||||
errors do not identify the original line of a cross-reference. The original
|
MODEL errors do not identify the original line of a cross-reference. The
|
||||||
`xtc_project_load` remains available with identical transactional semantics.
|
original `xtc_project_load` remains available with identical transactional
|
||||||
|
semantics.
|
||||||
|
|
||||||
`xtc-check --validate PROJECT` checks bounded metadata without loading dependencies.
|
`xtc-check --validate PROJECT` checks bounded metadata without loading
|
||||||
`xtc-check --inspect PROJECT` additionally lists resolved media and module paths,
|
dependencies. `xtc-check --inspect PROJECT` additionally lists resolved media
|
||||||
plugin labels, unique IDs and descriptor indices. It checks readable regular-file
|
and module paths, plugin labels, unique IDs and descriptor indices. It checks
|
||||||
availability only. Exit status is 0 when references are available, 2 when valid
|
readable regular-file availability only. Exit status is 0 when references are
|
||||||
metadata has missing/unreadable references, and 1 for invalid metadata or I/O.
|
available, 2 when valid metadata has missing/unreadable references, and 1 for
|
||||||
Neither command executes plugin code, decodes WAV data, connects JACK or verifies
|
invalid metadata or I/O. Neither command executes plugin code, decodes WAV data,
|
||||||
hardware. A readable file can still be an invalid WAV or incompatible plugin;
|
connects JACK or verifies hardware. A readable file can still be an invalid WAV
|
||||||
actual preparation performs those checks. Paths and labels are escaped for
|
or incompatible plugin; actual preparation performs those checks. Paths and
|
||||||
terminal output. There is no search-path substitution or automatic plugin relink.
|
labels are escaped for terminal output. There is no search-path substitution or
|
||||||
|
automatic plugin relink.
|
||||||
|
|
||||||
Portability currently targets Linux/POSIX. The text representation is independent
|
Portability currently targets Linux/POSIX. The text representation is
|
||||||
of byte order and locale and requires IEEE binary32 floats. IDs used by the graph
|
independent of byte order and locale and requires IEEE binary32 floats. IDs used
|
||||||
must fit the receiving host's size_t; a 64-bit file is not guaranteed to fit a
|
by the graph must fit the receiving host's size_t; a 64-bit file is not
|
||||||
32-bit build. Paths follow POSIX semantics; Windows drive letters and separators
|
guaranteed to fit a 32-bit build. Paths follow POSIX semantics; Windows drive
|
||||||
are not translated. Relative media can travel with their project folder, while
|
letters and separators are not translated. Relative media can travel with their
|
||||||
absolute references and symlink targets must be restored separately. LADSPA
|
project folder, while absolute references and symlink targets must be restored
|
||||||
modules are absolute installed references: match architecture, ABI, descriptor
|
separately. LADSPA modules are absolute installed references: match
|
||||||
identity, ports and legal controls on the destination. Plugin binaries and state
|
architecture, ABI, descriptor identity, ports and legal controls on the
|
||||||
are not bundled. JACK availability, sample rate, block limits and device routing
|
destination. Plugin binaries and state are not bundled. JACK availability,
|
||||||
are runtime dependencies; loading metadata does not restore device connections.
|
sample rate, block limits and device routing are runtime dependencies; loading
|
||||||
|
metadata does not restore device connections.
|
||||||
|
|
||||||
`make test` includes v1–v10 migration, malformed/truncated/mutated/oversized input,
|
`make test` includes v1–v10 migration, malformed/truncated/mutated/oversized
|
||||||
retained-state diagnostics, CLI dependency inspection, and deterministic save
|
input, retained-state diagnostics, CLI dependency inspection, and deterministic
|
||||||
faults at flush, file sync, close, rename and directory sync. Pre-rename faults
|
save faults at flush, file sync, close, rename and directory sync. Pre-rename
|
||||||
preserve the old bytes and remove the temporary. After rename, a sync failure
|
faults preserve the old bytes and remove the temporary. After rename, a sync
|
||||||
reports I/O while leaving a complete new document; inspect it before retrying.
|
failure reports I/O while leaving a complete new document; inspect it before
|
||||||
Fault wrappers are linked into tests only. These tests complement killed-writer
|
retrying. Fault wrappers are linked into tests only. These tests complement
|
||||||
coverage in `make test-recovery`; they do not qualify power-cut behavior.
|
killed-writer coverage in `make test-recovery`; they do not qualify power-cut
|
||||||
|
behavior.
|
||||||
|
|
||||||
## Version 11: plugin format identity
|
---
|
||||||
|
|
||||||
|
## Version 11: Plugin Format Identity
|
||||||
|
|
||||||
Immediately after every plugin MODULE record, v11 requires:
|
Immediately after every plugin MODULE record, v11 requires:
|
||||||
|
|
||||||
|
|
@ -345,29 +388,34 @@ Immediately after every plugin MODULE record, v11 requires:
|
||||||
FORMAT format_number hex_identity_or_dash
|
FORMAT format_number hex_identity_or_dash
|
||||||
```
|
```
|
||||||
|
|
||||||
0 = LADSPA, 1 = CLAP, 2 = VST2, 3 = VST3. Identity is `-` for LADSPA/VST2;
|
0 = LADSPA, 1 = CLAP, 2 = VST2, 3 = VST3. Identity is `-` for LADSPA/VST2; CLAP
|
||||||
CLAP uses its stable plugin ID (1–127 non-NUL bytes); VST3 uses the 32-character lowercase
|
uses its stable plugin ID (1–127 non-NUL bytes); VST3 uses the 32-character
|
||||||
hex class ID string, itself hex-encoded like other byte strings. PLUGIN's unique
|
lowercase hex class ID string, itself hex-encoded like other byte strings.
|
||||||
ID remains the VST2/LADSPA integer ID (zero for CLAP/VST3), descriptor index and
|
PLUGIN's unique ID remains the VST2/LADSPA integer ID (zero for CLAP/VST3),
|
||||||
label. MODULE is still the actual absolute binary path. Versions 1–10 migrate
|
descriptor index and label. MODULE is still the actual absolute binary path.
|
||||||
to format 0 and empty extra identity. Older readers reject v11. The public plugin
|
Versions 1–10 migrate to format 0 and empty extra identity. Older readers reject
|
||||||
struct has grown; C/C++ consumers must rebuild and initialize it to zero.
|
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
|
Modern adapters accept one-input mono effects, default configuration only, with
|
||||||
zero controls and automation points. Unsupported modern control metadata is
|
zero controls and automation points. Unsupported modern control metadata is
|
||||||
rejected, not discarded. State/editor/preset changes are not exposed, so no opaque
|
rejected, not discarded. State/editor/preset changes are not exposed, so no
|
||||||
state is serialized. Reloading recreates plugin defaults, which can change after
|
opaque state is serialized. Reloading recreates plugin defaults, which can
|
||||||
a plugin update or with its external configuration. Matching ID/name/layout is
|
change after a plugin update or with its external configuration. Matching
|
||||||
not a binary hash or sound-reproducibility guarantee. See PLUGIN_HOSTING.md.
|
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
|
Metadata validation and inspection never initialize modules. Actual graph
|
||||||
preparation verifies format, descriptor, stable identity, name and layout before
|
preparation verifies format, descriptor, stable identity, name and layout before
|
||||||
publishing. Missing module metadata survives C load/save; GUI preparation retains
|
publishing. Missing module metadata survives C load/save; GUI preparation
|
||||||
the existing document on failure. No automatic path search or plugin substitution
|
retains the existing document on failure. No automatic path search or plugin
|
||||||
occurs. Current and historical migration fixtures, malformed fields, identity
|
substitution occurs. Current and historical migration fixtures, malformed
|
||||||
mismatch, missing-module and exact-render roundtrips cover this extension.
|
fields, identity mismatch, missing-module and exact-render roundtrips cover this
|
||||||
|
extension.
|
||||||
|
|
||||||
## Version 12: track instruments
|
---
|
||||||
|
|
||||||
|
## Version 12: Track Instruments
|
||||||
|
|
||||||
After CONTROL_MAPS/MAP records and before END:
|
After CONTROL_MAPS/MAP records and before END:
|
||||||
|
|
||||||
|
|
@ -389,25 +437,32 @@ modules; preparing playback verifies binary identity and configuration. Deleting
|
||||||
tracks removes bindings; reordering preserves stable track identities. Undo
|
tracks removes bindings; reordering preserves stable track identities. Undo
|
||||||
snapshots include bindings. Public clients must rebuild for the new spec field.
|
snapshots include bindings. Public clients must rebuild for the new spec field.
|
||||||
|
|
||||||
## Version 13 internal devices
|
---
|
||||||
|
|
||||||
|
## Version 13 Internal Devices
|
||||||
|
|
||||||
Format value 4 identifies dependency-free internal devices at `/xtc/internal`.
|
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
|
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
|
effects with three controls and existing automation records. Identity and
|
||||||
ranges are validated without loading libraries. See [BUILTIN_DEVICES.md](BUILTIN_DEVICES.md).
|
control ranges are validated without loading libraries. See
|
||||||
|
[BUILTIN_DEVICES.md](BUILTIN_DEVICES.md).
|
||||||
|
|
||||||
## Version 14 instrument parameters
|
---
|
||||||
|
|
||||||
|
## Version 14 Instrument Parameters
|
||||||
|
|
||||||
Each track INSTRUMENT identity is followed by `INSTRUMENT_CONTROLS count`,
|
Each track INSTRUMENT identity is followed by `INSTRUMENT_CONTROLS count`,
|
||||||
`CONTROL port value_bits` records, `INSTRUMENT_AUTOMATION count` and
|
`CONTROL port value_bits` records, `INSTRUMENT_AUTOMATION count` and
|
||||||
`PARAM tick port mode value_bits` records. Bounds, duplicate points and metadata
|
`PARAM tick port mode value_bits` records. Bounds, duplicate points and metadata
|
||||||
are validated before destination replacement, just as for graph effects.
|
are validated before destination replacement, just as for graph effects. Earlier
|
||||||
Earlier bindings have no controls/automation; v13 internal instruments retain
|
bindings have no controls/automation; v13 internal instruments retain fixed
|
||||||
fixed default sounds. Modern external instruments still require zero controls.
|
default sounds. Modern external instruments still require zero controls.
|
||||||
Instrument tempo follows project tempo. Instrument preset files use this same
|
Instrument tempo follows project tempo. Instrument preset files use this same
|
||||||
schema with exactly one instrument track and no clips; they are metadata only.
|
schema with exactly one instrument track and no clips; they are metadata only.
|
||||||
|
|
||||||
## Version 15 sample references
|
---
|
||||||
|
|
||||||
|
## Version 15 Sample References
|
||||||
|
|
||||||
Each instrument parameter block ends with `SAMPLE hex_path_or_dash`. Only the
|
Each instrument parameter block ends with `SAMPLE hex_path_or_dash`. Only the
|
||||||
internal Sample Player (index 4) may carry a nonempty sample path. Paths within
|
internal Sample Player (index 4) may carry a nonempty sample path. Paths within
|
||||||
|
|
@ -415,19 +470,23 @@ the project directory are relative on disk and resolve against the project
|
||||||
file's directory; other paths are absolute. Metadata loading does not read WAVs.
|
file's directory; other paths are absolute. Metadata loading does not read WAVs.
|
||||||
Missing/invalid samples remain references and become reported silence during
|
Missing/invalid samples remain references and become reported silence during
|
||||||
preparation. Controls describe root key, whole-file loop, attack, release and
|
preparation. Controls describe root key, whole-file loop, attack, release and
|
||||||
gain. Earlier projects have empty sample paths. Rebuild public API consumers
|
gain. Earlier projects have empty sample paths. Rebuild public API consumers for
|
||||||
for the additional copied `sample_path` field in `xtc_plugin_spec`.
|
the additional copied `sample_path` field in `xtc_plugin_spec`.
|
||||||
|
|
||||||
## Version 16: arrangement markers
|
---
|
||||||
|
|
||||||
|
## Version 16: Arrangement Markers
|
||||||
|
|
||||||
After `LIVE_INSTRUMENT` and before `END`, version 16 writes `MARKERS count`
|
After `LIVE_INSTRUMENT` and before `END`, version 16 writes `MARKERS count`
|
||||||
followed by `MARKER tick hex_name` records. Count is 0..128; ticks must be strictly
|
followed by `MARKER tick hex_name` records. Count is 0..128; ticks must be
|
||||||
increasing and at most MAX_TICK. Names use the existing bounded UTF-8 hex encoding.
|
strictly increasing and at most MAX_TICK. Names use the existing bounded UTF-8
|
||||||
Versions 1–15 migrate to an empty marker list. Older builds reject version 16.
|
hex encoding. Versions 1–15 migrate to an empty marker list. Older builds reject
|
||||||
Markers are copied by snapshots and history; the tick is their stable key.
|
version 16. Markers are copied by snapshots and history; the tick is their
|
||||||
|
stable key.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Version 17: per-track insert chains
|
## Version 17: per-Track Insert Chains
|
||||||
|
|
||||||
After MARKERS/MARKER and before END, the writer emits a chain for every track,
|
After MARKERS/MARKER and before END, the writer emits a chain for every track,
|
||||||
in dense track order. Earlier versions migrate to empty chains with unity gain.
|
in dense track order. Earlier versions migrate to empty chains with unity gain.
|
||||||
|
|
@ -448,16 +507,16 @@ PARAM tick port step value_bits
|
||||||
|
|
||||||
Each CHAIN has exactly slot_count INSERT blocks. CONTROLS/PARAMETERS determine
|
Each CHAIN has exactly slot_count INSERT blocks. CONTROLS/PARAMETERS determine
|
||||||
the subsequent CONTROL/PARAM record counts, including zero. Slots are ordered,
|
the subsequent CONTROL/PARAM record counts, including zero. Slots are ordered,
|
||||||
at most eight, and accept mono non-instrument effects only. Enabled is 0/1,
|
at most eight, and accept mono non-instrument effects only. Enabled is 0/1, wet
|
||||||
wet is finite 0–1, output gain finite 0–4; inputs must be 1. The format values
|
is finite 0–1, output gain finite 0–4; inputs must be 1. The format values are
|
||||||
are LADSPA=0, CLAP=1, VST2=2, VST3=3 and Internal=4. Existing plugin specification
|
LADSPA=0, CLAP=1, VST2=2, VST3=3 and Internal=4. Existing plugin specification
|
||||||
validation applies, including descriptor/identity/port/automation bounds and
|
validation applies, including descriptor/identity/port/automation bounds and
|
||||||
20,000–300,000 milli-BPM. Bus chains must be empty. No sample reference is
|
20,000–300,000 milli-BPM. Bus chains must be empty. No sample reference is
|
||||||
permitted on an effect. Duplicate, missing, reordered or excessive chain
|
permitted on an effect. Duplicate, missing, reordered or excessive chain
|
||||||
records, malformed strings and nonfinite values reject the whole load.
|
records, malformed strings and nonfinite values reject the whole load.
|
||||||
|
|
||||||
Loading and dependency inspection only validate metadata; no plugin module
|
Loading and dependency inspection only validate metadata; no plugin module is
|
||||||
is opened. Enabled plugins are verified when a render plan is prepared. Chain
|
opened. Enabled plugins are verified when a render plan is prepared. Chain
|
||||||
preset files reuse this schema with exactly one non-bus track and no clips or
|
preset files reuse this schema with exactly one non-bus track and no clips or
|
||||||
instrument. Track insert APIs are declared in `xtc_plugin.h`; see
|
instrument. Track insert APIs are declared in `xtc_plugin.h`; see
|
||||||
[TRACK_INSERTS.md](TRACK_INSERTS.md) for playback restrictions and workflows.
|
[TRACK_INSERTS.md](TRACK_INSERTS.md) for playback restrictions and workflows.
|
||||||
|
|
|
||||||
108
docs/RECOVERY.md
108
docs/RECOVERY.md
|
|
@ -1,44 +1,51 @@
|
||||||
# Persistence and failure recovery
|
# Persistence and Failure Recovery
|
||||||
|
|
||||||
The project format is v12. Readers migrate v1–v11, validate bounded input
|
The project format is v12. Readers migrate v1–v11, validate bounded input and
|
||||||
and atomically install a candidate only after complete success. Existing tests
|
atomically install a candidate only after complete success. Existing tests cover
|
||||||
cover exact migration/roundtrip, truncations, malformed references, counts,
|
exact migration/roundtrip, truncations, malformed references, counts, IDs,
|
||||||
IDs, nonfinite values and failed GUI/backend installation. Native processors
|
nonfinite values and failed GUI/backend installation. Native processors are
|
||||||
are session-only; saving their graph returns UNSUPPORTED rather than writing
|
session-only; saving their graph returns UNSUPPORTED rather than writing process
|
||||||
process addresses or an unreadable project. See PROJECT_FORMAT.md.
|
addresses or an unreadable project. See PROJECT_FORMAT.md.
|
||||||
|
|
||||||
Project Save writes a mode-0600 same-directory `NAME.tmp.XXXXXX`, flushes and
|
Project Save writes a mode-0600 same-directory `NAME.tmp.XXXXXX`, flushes and
|
||||||
fsyncs it, closes and renames it over the destination. Before rename, handled
|
fsyncs it, closes and renames it over the destination. Before rename, handled
|
||||||
failures remove the temporary and retain the destination. POSIX rename gives
|
failures remove the temporary and retain the destination. POSIX rename gives
|
||||||
complete old-or-new destination contents during process failure. The containing directory is fsynced after rename. If that sync fails, Save
|
complete old-or-new destination contents during process failure. The containing
|
||||||
reports I/O failure but the complete new file may already be present. Preserve
|
directory is fsynced after rename. If that sync fails, Save reports I/O failure
|
||||||
and validate it before retrying; filesystem/hardware durability still varies. Symlinks are
|
but the complete new file may already be present. Preserve and validate it
|
||||||
|
before retrying; filesystem/hardware durability still varies. Symlinks are
|
||||||
replaced rather than followed at rename; original file permissions are not kept.
|
replaced rather than followed at rename; original file permissions are not kept.
|
||||||
|
|
||||||
Recording similarly writes/finalizes a same-directory temporary, then renames
|
Recording similarly writes/finalizes a same-directory temporary, then renames
|
||||||
it. Stop must synchronize callbacks before draining/finalizing. Ring overflow
|
it. Stop must synchronize callbacks before draining/finalizing. Ring overflow
|
||||||
returns an explicit error and may finalize a partial take for manual recovery;
|
returns an explicit error and may finalize a partial take for manual recovery;
|
||||||
I/O failure retains the previous destination. A killed recorder does not finish
|
I/O failure retains the previous destination. A killed recorder does not finish
|
||||||
its WAV header. Source WAV files remain external; references inside the project folder are
|
its WAV header. Source WAV files remain external; references inside the project
|
||||||
saved relative to it. Save As does not collect them. Back up the project and assets together.
|
folder are saved relative to it. Save As does not collect them. Back up the
|
||||||
|
project and assets together.
|
||||||
|
|
||||||
## After a crash
|
---
|
||||||
|
|
||||||
|
## After A Crash
|
||||||
|
|
||||||
1. Preserve the destination and any `.tmp.*` files before attempting repair.
|
1. Preserve the destination and any `.tmp.*` files before attempting repair.
|
||||||
2. Run `xtc-check --validate project.xtc` for metadata validation without a GUI,
|
2. Run `xtc-check --validate project.xtc` for metadata validation without a GUI,
|
||||||
display or audio server. Run `xtc-check --inspect project.xtc` to list resolved
|
display or audio server. Run `xtc-check --inspect project.xtc` to list
|
||||||
media/module paths and plugin identities: status 2 means missing/unreadable
|
resolved media/module paths and plugin identities: status 2 means
|
||||||
references, 1 means invalid metadata/I/O, 0 means files are available. Neither
|
missing/unreadable references, 1 means invalid metadata/I/O, 0 means files
|
||||||
command verifies file contents, plugin initialization or realtime preparation.
|
are available. Neither command verifies file contents, plugin initialization
|
||||||
3. A valid destination can be opened normally. If only a temporary contains useful
|
or realtime preparation.
|
||||||
data, copy it to a separate candidate and validate that copy before replacing
|
3. A valid destination can be opened normally. If only a temporary contains
|
||||||
anything. Partial project files are rejected; there is no salvage parser.
|
useful data, copy it to a separate candidate and validate that copy before
|
||||||
4. An unfinished WAV temporary may have a zero/incorrect data length and needs
|
replacing anything. Partial project files are rejected; there is no salvage
|
||||||
a separate recovery tool or manual header repair on a copy. xtc does not guess
|
parser.
|
||||||
|
4. An unfinished WAV temporary may have a zero/incorrect data length and needs a
|
||||||
|
separate recovery tool or manual header repair on a copy. xtc does not guess
|
||||||
its intended length or automatically rename orphan temporaries.
|
its intended length or automatically rename orphan temporaries.
|
||||||
5. Missing assets preserve silent clips. Use Relink selected audio, then Play to
|
5. Missing assets preserve silent clips. Use Relink selected audio, then Play to
|
||||||
revalidate. For server loss/format changes, Stop/Reconnect and explicit routing
|
revalidate. For server loss/format changes, Stop/Reconnect and explicit
|
||||||
are required. Panic/F9 clears held notes. Failed close retains ownership for retry.
|
routing are required. Panic/F9 clears held notes. Failed close retains
|
||||||
|
ownership for retry.
|
||||||
|
|
||||||
There is no autosave, crash journal, automatic orphan recovery or persisted Undo
|
There is no autosave, crash journal, automatic orphan recovery or persisted Undo
|
||||||
history. Existing finalized files are protected against the tested process-level
|
history. Existing finalized files are protected against the tested process-level
|
||||||
|
|
@ -51,18 +58,22 @@ draining but before finalization. Complete old/new destinations and explicit
|
||||||
orphan temporaries are verified. It does not cut power, terminate the shared
|
orphan temporaries are verified. It does not cut power, terminate the shared
|
||||||
audio server, simulate a failing filesystem, or qualify disk/device endurance.
|
audio server, simulate a failing filesystem, or qualify disk/device endurance.
|
||||||
|
|
||||||
## Retained recording prefixes
|
---
|
||||||
|
|
||||||
|
## Retained Recording Prefixes
|
||||||
|
|
||||||
Recording now defaults to no-clobber publication; the GUI requires an unused
|
Recording now defaults to no-clobber publication; the GUI requires an unused
|
||||||
path. Failed nonempty temporary recordings survive destruction. Query the
|
path. Failed nonempty temporary recordings survive destruction. Query the
|
||||||
recorder recovery path before destruction, or use the GUI's reported path.
|
recorder recovery path before destruction, or use the GUI's reported path.
|
||||||
`xtc-check --recover-recording TEMP NEW.wav` reconstructs a canonical mono
|
`xtc-check --recover-recording TEMP NEW.wav` reconstructs a canonical mono
|
||||||
float32 WAV from complete on-disk frames, ignoring a trailing partial frame.
|
float32 WAV from complete on-disk frames, ignoring a trailing partial frame. It
|
||||||
It never changes the source or overwrites an existing destination. This
|
never changes the source or overwrites an existing destination. This supersedes
|
||||||
supersedes the earlier lack of a WAV recovery tool described above. See
|
the earlier lack of a WAV recovery tool described above. See AUDIO_FILES.md for
|
||||||
AUDIO_FILES.md for format/ownership/size limits and `make test-recording`.
|
format/ownership/size limits and `make test-recording`.
|
||||||
|
|
||||||
## Plugin load and replacement failures
|
---
|
||||||
|
|
||||||
|
## Plugin Load and Replacement Failures
|
||||||
|
|
||||||
GUI Open reports an unavailable/incompatible plugin's label and absolute module
|
GUI Open reports an unavailable/incompatible plugin's label and absolute module
|
||||||
path and retains the current document. Preserve the saved file; restore a
|
path and retains the current document. Preserve the saved file; restore a
|
||||||
|
|
@ -77,27 +88,32 @@ ID only for the same audio layout. New defaults replace controls/automation;
|
||||||
Undo restores the original configuration. Failed discovery/compile/instantiate
|
Undo restores the original configuration. Failed discovery/compile/instantiate
|
||||||
retains the original graph, controls and history position. Cancel in the generic
|
retains the original graph, controls and history position. Cancel in the generic
|
||||||
parameter editor discards its temporary values. Reset defaults clears automation
|
parameter editor discards its temporary values. Reset defaults clears automation
|
||||||
only when applied. No host recovery can contain a crash or hang in trusted native
|
only when applied. No host recovery can contain a crash or hang in trusted
|
||||||
plugin code; LADSPA has no runtime error-return channel.
|
native plugin code; LADSPA has no runtime error-return channel.
|
||||||
|
|
||||||
## Save diagnostics
|
---
|
||||||
|
|
||||||
`make test-project-diagnostics` deterministically injects flush, file-sync, close,
|
## Save Diagnostics
|
||||||
rename and directory-sync errors. Pre-rename failures retain the previous bytes
|
|
||||||
and clean temporary files. Post-rename sync errors leave a complete new file and
|
`make test-project-diagnostics` deterministically injects flush, file-sync,
|
||||||
return failure; there is no rollback after replacement. Load diagnostics identify
|
close, rename and directory-sync errors. Pre-rename failures retain the previous
|
||||||
the expected record and syntax line, or line zero for whole-model/I/O stages.
|
bytes and clean temporary files. Post-rename sync errors leave a complete new
|
||||||
Unknown versions report the supported range (1–12); unknown records/fields are
|
file and return failure; there is no rollback after replacement. Load
|
||||||
rejected without partially changing the current project.
|
diagnostics identify the expected record and syntax line, or line zero for
|
||||||
|
whole-model/I/O stages. Unknown versions report the supported range (1–12);
|
||||||
|
unknown records/fields are rejected without partially changing the current
|
||||||
|
project.
|
||||||
|
|
||||||
Modern CLAP/VST2/VST3 module identity is preserved in v11 metadata even when the
|
Modern CLAP/VST2/VST3 module identity is preserved in v11 metadata even when the
|
||||||
binary is unavailable. Restore the compatible saved binary path and retry Open.
|
binary is unavailable. Restore the compatible saved binary path and retry Open.
|
||||||
CLAP restart and VST2 I/O-change requests fail/silence subsequent blocks; stop
|
CLAP restart and VST2 I/O-change requests fail/silence subsequent blocks; stop
|
||||||
and rebuild/reload rather than attempting callback-time reconfiguration. Modern
|
and rebuild/reload rather than attempting callback-time reconfiguration. Modern
|
||||||
instances restart at default configuration; no edited opaque state is exposed
|
instances restart at default configuration; no edited opaque state is exposed or
|
||||||
or saved by the initial adapters. Trusted plugin crashes cannot be contained.
|
saved by the initial adapters. Trusted plugin crashes cannot be contained.
|
||||||
|
|
||||||
## Instrument support
|
---
|
||||||
|
|
||||||
|
## Instrument Support
|
||||||
|
|
||||||
MIDI tracks can bind CLAP, VST2 and VST3 instruments. In the Track menu, select
|
MIDI tracks can bind CLAP, VST2 and VST3 instruments. In the Track menu, select
|
||||||
**Load instrument plugin** for the selected sequencer track; **Use built-in
|
**Load instrument plugin** for the selected sequencer track; **Use built-in
|
||||||
|
|
@ -108,9 +124,9 @@ their own track's instrument. Independent instances feed track gain/pan,
|
||||||
mute/solo, bus routing and automation. Bindings/live target save in v12.
|
mute/solo, bus routing and automation. Bindings/live target save in v12.
|
||||||
|
|
||||||
Supply the actual trusted Linux binary (including the inner .so of a VST3
|
Supply the actual trusted Linux binary (including the inner .so of a VST3
|
||||||
bundle). Supported instruments have zero audio inputs, one mono output,
|
bundle). Supported instruments have zero audio inputs, one mono output, float32
|
||||||
float32 processing, zero latency and one note/event input. Default configuration
|
processing, zero latency and one note/event input. Default configuration only:
|
||||||
only: no custom editor, opaque state/preset restoration, modern parameter
|
no custom editor, opaque state/preset restoration, modern parameter
|
||||||
editing/automation, stereo/multichannel instruments or MIDI output. No arbitrary
|
editing/automation, stereo/multichannel instruments or MIDI output. No arbitrary
|
||||||
third-party instrument is qualified by the original ABI fixture tests.
|
third-party instrument is qualified by the original ABI fixture tests.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,50 +1,60 @@
|
||||||
# 0.1.0 development release notes
|
# 0.1.0 Development Release Notes
|
||||||
|
|
||||||
This remains a development prototype, not a production-qualified DAW. The local
|
This remains a development prototype, not a production-qualified DAW. The local
|
||||||
release workflow is complete without bumping the application version, creating a
|
release workflow is complete without bumping the application version, creating a
|
||||||
tag or publishing artifacts. The exact source archive SHA-256 and
|
tag or publishing artifacts. The exact source archive SHA-256 and reviewed Git
|
||||||
reviewed Git commit identify a build; version 0.1.0 alone does not identify all
|
commit identify a build; version 0.1.0 alone does not identify all of the
|
||||||
of the development revisions that used that version.
|
development revisions that used that version.
|
||||||
|
|
||||||
## Included functionality
|
---
|
||||||
|
|
||||||
The C99 engine provides bounded graphs, immutable plan publication, stereo audio,
|
## Included Functionality
|
||||||
MIDI instruments and controller bindings, track/bus mixing, automation and inline
|
|
||||||
MIDI editing. The C++17 FLTK application adds arrangement, routing, recording,
|
|
||||||
undo/redo and a generic LADSPA editor. JACK is the only live audio/MIDI backend;
|
|
||||||
core validation and offline rendering work without it. Native/LADSPA processors
|
|
||||||
are trusted in-process code. No proprietary energyXT resources are included.
|
|
||||||
|
|
||||||
Project format v13 reads versions 1–13 transactionally. Syntax diagnostics identify
|
The C99 engine provides bounded graphs, immutable plan publication, stereo
|
||||||
records and lines. `xtc-check --inspect` lists dependency paths without executing
|
audio, MIDI instruments and controller bindings, track/bus mixing, automation
|
||||||
plugins. Timing/CPU/RSS reports, repeatable stress runs and virtual endurance are
|
and inline MIDI editing. The C++17 FLTK application adds arrangement, routing,
|
||||||
available. Configurable install directories, shared install/remove inventory,
|
recording, undo/redo and a generic LADSPA editor. JACK is the only live
|
||||||
installed MIDI examples and source archive checksum sidecars are also included.
|
audio/MIDI backend; core validation and offline rendering work without it.
|
||||||
|
Native/LADSPA processors are trusted in-process code. No proprietary energyXT
|
||||||
|
resources are included.
|
||||||
|
|
||||||
## Upgrading and removal
|
Project format v13 reads versions 1–13 transactionally. Syntax diagnostics
|
||||||
|
identify records and lines. `xtc-check --inspect` lists dependency paths without
|
||||||
|
executing plugins. Timing/CPU/RSS reports, repeatable stress runs and virtual
|
||||||
|
endurance are available. Configurable install directories, shared install/remove
|
||||||
|
inventory, installed MIDI examples and source archive checksum sidecars are also
|
||||||
|
included.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Upgrading and Removal
|
||||||
|
|
||||||
Back up documents and external media before upgrading. Opening an older project
|
Back up documents and external media before upgrading. Opening an older project
|
||||||
does not rewrite it; saving upgrades it to v12, which older readers may reject.
|
does not rewrite it; saving upgrades it to v12, which older readers may reject.
|
||||||
Use Save As for a separate migrated copy. Moving a project folder preserves media
|
Use Save As for a separate migrated copy. Moving a project folder preserves
|
||||||
stored inside it via relative references. Absolute media and plugin module paths
|
media stored inside it via relative references. Absolute media and plugin module
|
||||||
must be restored separately. There is no bundled plugin/media migration or saved
|
paths must be restored separately. There is no bundled plugin/media migration or
|
||||||
JACK port configuration. See PROJECT_FORMAT.md and RECOVERY.md for exact policies.
|
saved JACK port configuration. See PROJECT_FORMAT.md and RECOVERY.md for exact
|
||||||
|
policies.
|
||||||
|
|
||||||
Install to the same layout to repair owned files. Only documented owned filenames
|
Install to the same layout to repair owned files. Only documented owned
|
||||||
are replaced; unrelated files with other names remain. Use the same source
|
filenames are replaced; unrelated files with other names remain. Use the same
|
||||||
version and directory variables for uninstall. It removes owned files and empty
|
source version and directory variables for uninstall. It removes owned files and
|
||||||
owned directories, never recordings or recursively deleting a prefix. A changed
|
empty owned directories, never recordings or recursively deleting a prefix. A
|
||||||
layout or an older release with a different inventory may require removing that
|
changed layout or an older release with a different inventory may require
|
||||||
old version before installing the new one. No database/package-manager registration
|
removing that old version before installing the new one. No
|
||||||
or automatic cleanup of historical inventories is performed.
|
database/package-manager registration or automatic cleanup of historical
|
||||||
|
inventories is performed.
|
||||||
|
|
||||||
## Known qualification limits
|
---
|
||||||
|
|
||||||
|
## Known Qualification Limits
|
||||||
|
|
||||||
Physical devices, multi-hour wall-clock endurance, power-cut behavior and other
|
Physical devices, multi-hour wall-clock endurance, power-cut behavior and other
|
||||||
Linux distributions remain unqualified. There is no disk streaming, crash autosave,
|
Linux distributions remain unqualified. There is no disk streaming, crash
|
||||||
plugin sandbox, latency compensation or stable shared-library ABI. A trusted
|
autosave, plugin sandbox, latency compensation or stable shared-library ABI. A
|
||||||
plugin can allocate, block or crash the process. Metadata inspection checks file
|
trusted plugin can allocate, block or crash the process. Metadata inspection
|
||||||
availability only. See KNOWN_LIMITATIONS.md for the complete list.
|
checks file availability only. See KNOWN_LIMITATIONS.md for the complete list.
|
||||||
|
|
||||||
The retained graph performance gate has a documented small-case timing alert on
|
The retained graph performance gate has a documented small-case timing alert on
|
||||||
the shared development host; the project timing comparison passed. This alert
|
the shared development host; the project timing comparison passed. This alert
|
||||||
|
|
@ -53,56 +63,60 @@ measurements as latency expectations. Sanitizers and virtual endurance qualify
|
||||||
software paths, not hardware timing.
|
software paths, not hardware timing.
|
||||||
|
|
||||||
Default-configuration CLAP/VST2/VST3 mono effect loaders, common GUI
|
Default-configuration CLAP/VST2/VST3 mono effect loaders, common GUI
|
||||||
discovery/insertion/replacement and v11 format identity are supported. Pinned MIT CLAP and
|
discovery/insertion/replacement and v11 format identity are supported. Pinned
|
||||||
BSD-3-Clause VST3 C headers ship with notices; VST2 uses original compatibility
|
MIT CLAP and BSD-3-Clause VST3 C headers ship with notices; VST2 uses original
|
||||||
declarations. Modern instruments, parameters/state/editors and multichannel
|
compatibility declarations. Modern instruments, parameters/state/editors and
|
||||||
layouts remain unsupported. No third-party modern plugin has been qualified.
|
multichannel layouts remain unsupported. No third-party modern plugin has been
|
||||||
|
qualified.
|
||||||
|
|
||||||
CLAP/VST2/VST3 mono instruments are supported, bound to MIDI tracks, with
|
CLAP/VST2/VST3 mono instruments are supported, bound to MIDI tracks, with
|
||||||
sample-offset notes, a saved live target, track mixing, GUI assignment/undo and
|
sample-offset notes, a saved live target, track mixing, GUI assignment/undo and
|
||||||
v12 persistence.
|
v12 persistence. See PLUGIN_HOSTING.md for compatibility and controller/state
|
||||||
See PLUGIN_HOSTING.md for compatibility and controller/state limits.
|
limits.
|
||||||
|
|
||||||
A flat DAW workspace, shared dark theme, track-creation sidebar, read-only
|
A flat DAW workspace, shared dark theme, track-creation sidebar, read-only
|
||||||
musical transport/track inspector, colored track clips and real MIDI previews are
|
musical transport/track inspector, colored track clips and real MIDI previews
|
||||||
included. New MIDI/audio track commands are undoable and prepare candidates
|
are included. New MIDI/audio track commands are undoable and prepare candidates
|
||||||
before adoption. The default window is 1280 × 800, minimum 1220 × 720.
|
before adoption. The default window is 1280 × 800, minimum 1220 × 720. No
|
||||||
No dependency or project-format change. See WORKSPACE.md and the new
|
dependency or project-format change. See WORKSPACE.md and the new
|
||||||
`modern-session.xtc` example; existing engine/plugin limitations still apply.
|
`modern-session.xtc` example; existing engine/plugin limitations still apply.
|
||||||
|
|
||||||
A sequencer grid/Snap dropdown, absolute grid snapping for moves and trims,
|
A sequencer grid/Snap dropdown, absolute grid snapping for moves and trims, MIDI
|
||||||
MIDI double-click editing, a piano velocity lane/slider and per-track instrument
|
double-click editing, a piano velocity lane/slider and per-track instrument
|
||||||
dropdowns are included. Snap preferences are UI state; velocity and instrument
|
dropdowns are included. Snap preferences are UI state; velocity and instrument
|
||||||
bindings use the existing v12 format. No new dependency or engine feature is
|
bindings use the existing v12 format. No new dependency or engine feature is
|
||||||
required. See WORKSPACE.md for supported divisions, controller semantics and limits.
|
required. See WORKSPACE.md for supported divisions, controller semantics and
|
||||||
|
limits.
|
||||||
|
|
||||||
Edit / Preferences provides an Apply button and `~/.xtc.conf` INI persistence,
|
Edit / Preferences provides an Apply button and `~/.xtc.conf` INI persistence,
|
||||||
configurable plugin search paths and a file library, plus sequencer ruler loop
|
configurable plugin search paths and a file library, plus sequencer ruler loop
|
||||||
selection and sample-boundary playback wrapping. See PREFERENCES.md
|
selection and sample-boundary playback wrapping. See PREFERENCES.md for
|
||||||
for settings, reconnect behavior and looping limits.
|
settings, reconnect behavior and looping limits.
|
||||||
|
|
||||||
The single-track mixer panel is replaced by a scrolling studio mixer: vertical
|
The single-track mixer panel is replaced by a scrolling studio mixer: vertical
|
||||||
dB faders, flat pan knobs, mute/solo, routing and stereo meters on every track and
|
dB faders, flat pan knobs, mute/solo, routing and stereo meters on every track
|
||||||
bus, plus a pinned master monitor. Selected-track automation remains
|
and bus, plus a pinned master monitor. Selected-track automation remains below
|
||||||
below the strips. No project format or engine changes. Screenshots are refreshed;
|
the strips. No project format or engine changes. Screenshots are refreshed; see
|
||||||
see MIXER.md and screenshots/README.md.
|
MIXER.md and screenshots/README.md.
|
||||||
|
|
||||||
|
|
||||||
Searchable Commands (Ctrl+P), editable project BPM, a live track inspector,
|
Searchable Commands (Ctrl+P), editable project BPM, a live track inspector,
|
||||||
session statistics, Fit song and an optional persistent Follow playhead control
|
session statistics, Fit song and an optional persistent Follow playhead control
|
||||||
are included. Numeric input remains intact during display refreshes.
|
are included. Numeric input remains intact during display refreshes. Screenshots
|
||||||
Screenshots are refreshed, including the command palette. See WORKSPACE.md.
|
are refreshed, including the command palette. See WORKSPACE.md.
|
||||||
|
|
||||||
Dependency-free Soft Keys/Sub Bass instruments and Delay/Reverb effects are
|
Dependency-free Soft Keys/Sub Bass instruments and Delay/Reverb effects are
|
||||||
included, with saved controls and automation. Choose instruments in track headers;
|
included, with saved controls and automation. Choose instruments in track
|
||||||
insert effects on selected graph wires from Edit. See [BUILTIN_DEVICES.md](BUILTIN_DEVICES.md).
|
headers; insert effects on selected graph wires from Edit. See
|
||||||
|
[BUILTIN_DEVICES.md](BUILTIN_DEVICES.md).
|
||||||
|
|
||||||
## Audio source editing
|
---
|
||||||
|
|
||||||
Audio clips now open a modal waveform editor with native frame selection,
|
## Audio Source Editing
|
||||||
zoom, source statistics, nondestructive timeline trims, selection export and
|
|
||||||
save-copy adoption. Local one-step undo supports reverse, polarity inversion,
|
Audio clips now open a modal waveform editor with native frame selection, zoom,
|
||||||
DC removal, linear/equal-power fades and gain/normalization. Silence boundaries,
|
source statistics, nondestructive timeline trims, selection export and save-copy
|
||||||
|
adoption. Local one-step undo supports reverse, polarity inversion, DC removal,
|
||||||
|
linear/equal-power fades and gain/normalization. Silence boundaries,
|
||||||
zero-crossing snapping and amplitude attack markers support transactional clip
|
zero-crossing snapping and amplitude attack markers support transactional clip
|
||||||
slicing. Originals are never overwritten; exported media remains available to
|
slicing. Originals are never overwritten; exported media remains available to
|
||||||
project undo/redo. Source editing uses the existing mono downmix and bounded
|
project undo/redo. Source editing uses the existing mono downmix and bounded
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,13 @@
|
||||||
# Release preparation (0.1.0 development prototype)
|
# Release Preparation (0.1.0 Development Prototype)
|
||||||
|
|
||||||
Source packaging, staged install/uninstall and repeatable builds are testable. It does not turn the prototype into a production-qualified DAW. The
|
Source packaging, staged install/uninstall and repeatable builds are testable.
|
||||||
version remains 0.1.0; no tag, external release or binary publication is created
|
It does not turn the prototype into a production-qualified DAW. The version
|
||||||
by `make dist` or `make release`.
|
remains 0.1.0; no tag, external release or binary publication is created by
|
||||||
|
`make dist` or `make release`.
|
||||||
|
|
||||||
## Build and package
|
---
|
||||||
|
|
||||||
|
## Build and Package
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
make release
|
make release
|
||||||
|
|
@ -24,63 +27,75 @@ a source manifest; stage intended files first and check `git diff --cached`.
|
||||||
Untracked files, ignored build output and .git are excluded. Exported archives
|
Untracked files, ignored build output and .git are excluded. Exported archives
|
||||||
can reproduce themselves without Git using SOURCE_MANIFEST.json.
|
can reproduce themselves without Git using SOURCE_MANIFEST.json.
|
||||||
|
|
||||||
Archive order, permissions, ownership, gzip filename and timestamps are normalized.
|
Archive order, permissions, ownership, gzip filename and timestamps are
|
||||||
SOURCE_DATE_EPOCH defaults to 0; set an unsigned 32-bit epoch explicitly if desired.
|
normalized. SOURCE_DATE_EPOCH defaults to 0; set an unsigned 32-bit epoch
|
||||||
The archive does not claim to identify a commit: release from a clean checkout
|
explicitly if desired. The archive does not claim to identify a commit: release
|
||||||
and record its commit/hash externally. Do not treat a dirty-tree archive as an
|
from a clean checkout and record its commit/hash externally. Do not treat a
|
||||||
attested release. No artifact is uploaded by these targets.
|
dirty-tree archive as an attested release. No artifact is uploaded by these
|
||||||
|
targets.
|
||||||
|
|
||||||
test-release unpacks the source into two different temporary paths, runs release
|
test-release unpacks the source into two different temporary paths, runs release
|
||||||
in each, compares libxtc.a/xtc-check/optional xtc SHA-256 values, and repacks each
|
in each, compares libxtc.a/xtc-check/optional xtc SHA-256 values, and repacks
|
||||||
export to compare archive bytes. This verifies reproducibility for the same host,
|
each export to compare archive bytes. This verifies reproducibility for the same
|
||||||
compiler, flags and dependency versions. It does not promise bit-identical output
|
host, compiler, flags and dependency versions. It does not promise bit-identical
|
||||||
across distributions, compilers or library updates. Compiler/debug/sanitizer
|
output across distributions, compilers or library updates.
|
||||||
build directories are intentionally separate; changing toolchain/flags in place
|
Compiler/debug/sanitizer build directories are intentionally separate; changing
|
||||||
requires a clean directory. Python release tests require version 3.12+.
|
toolchain/flags in place requires a clean directory. Python release tests
|
||||||
|
require version 3.12+.
|
||||||
|
|
||||||
## Qualification record
|
---
|
||||||
|
|
||||||
|
## Qualification Record
|
||||||
|
|
||||||
Run normal core/GUI and live software JACK tests, no-JACK builds and ASan/UBSan.
|
Run normal core/GUI and live software JACK tests, no-JACK builds and ASan/UBSan.
|
||||||
GUI leak tests retain the narrow fontconfig suppression; core tests do not.
|
GUI leak tests retain the narrow fontconfig suppression; core tests do not. TSan
|
||||||
TSan recorder/publication tests complement lifecycle tests. Native API tests
|
recorder/publication tests complement lifecycle tests. Native API tests verify
|
||||||
verify callback failures, cleanup and retirement; they cannot certify arbitrary
|
callback failures, cleanup and retirement; they cannot certify arbitrary
|
||||||
extensions. See BUILD.md and tests/integration/README.md for commands.
|
extensions. See BUILD.md and tests/integration/README.md for commands.
|
||||||
|
|
||||||
Record versions, archive hashes, installation/consumer checks and measured timing.
|
Record versions, archive hashes, installation/consumer checks and measured
|
||||||
Use LICENSES.md for dependency/license review and PLUGIN_HOSTING.md for the
|
timing. Use LICENSES.md for dependency/license review and PLUGIN_HOSTING.md for
|
||||||
external-hosting decision. Review RECOVERY.md for migration and process-crash
|
the external-hosting decision. Review RECOVERY.md for migration and
|
||||||
semantics. Physical devices, power loss, sustained recording/performance, user
|
process-crash semantics. Physical devices, power loss, sustained
|
||||||
acceptance on other distributions and binary redistribution are still separate
|
recording/performance, user acceptance on other distributions and binary
|
||||||
qualification work. There is no DEB/RPM/AppImage, bundled runtime, autosave,
|
redistribution are still separate qualification work. There is no
|
||||||
external plugin host or stable shared-library extension ABI in this release.
|
DEB/RPM/AppImage, bundled runtime, autosave, external plugin host or stable
|
||||||
|
shared-library extension ABI in this release.
|
||||||
|
|
||||||
## Local binary packaging and installed workflow
|
---
|
||||||
|
|
||||||
|
## Local Binary Packaging and Installed Workflow
|
||||||
|
|
||||||
`make test-package` builds the release, stages installation only in a temporary
|
`make test-package` builds the release, stages installation only in a temporary
|
||||||
DESTDIR, writes a normalized Linux binary/development archive, checks its SHA-256
|
DESTDIR, writes a normalized Linux binary/development archive, checks its
|
||||||
sidecar and per-file manifest, relocatable pkg-config paths and headless commands.
|
SHA-256 sidecar and per-file manifest, relocatable pkg-config paths and headless
|
||||||
Same-host repeated packaging is byte-identical; dependency versions and toolchain
|
commands. Same-host repeated packaging is byte-identical; dependency versions
|
||||||
still determine binary compatibility. `make test-install` now repeats installation
|
and toolchain still determine binary compatibility. `make test-install` now
|
||||||
to verify repair/upgrade of owned files while preserving an unrelated sentinel,
|
repeats installation to verify repair/upgrade of owned files while preserving an
|
||||||
then compiles both C99 and C++17 installed consumers that create MIDI, save/reopen
|
unrelated sentinel, then compiles both C99 and C++17 installed consumers that
|
||||||
and compare nonzero exact rendering. Removal remains exact and idempotent.
|
create MIDI, save/reopen and compare nonzero exact rendering. Removal remains
|
||||||
|
exact and idempotent.
|
||||||
|
|
||||||
USER_MANUAL.md consolidates operation; KNOWN_LIMITATIONS.md lists qualification
|
USER_MANUAL.md consolidates operation; KNOWN_LIMITATIONS.md lists qualification
|
||||||
gaps; MAINTENANCE.md defines the release checklist, regression and compatibility
|
gaps; MAINTENANCE.md defines the release checklist, regression and compatibility
|
||||||
policy. Build diagnostics make no server/plugin calls. There is no asynchronous
|
policy. Build diagnostics make no server/plugin calls. There is no asynchronous
|
||||||
crash uploader or signal-handler cleanup: inspect OS core/debugger evidence on
|
crash uploader or signal-handler cleanup: inspect OS core/debugger evidence on
|
||||||
the control side, preserving project/media recovery paths. No release is publicly
|
the control side, preserving project/media recovery paths. No release is
|
||||||
published by these commands, and human/device/listening checks remain pending.
|
publicly published by these commands, and human/device/listening checks remain
|
||||||
|
pending.
|
||||||
|
|
||||||
## Release workflow
|
---
|
||||||
|
|
||||||
Installation now shares one explicit file inventory with uninstallation. GNU-style
|
## Release Workflow
|
||||||
`exec_prefix`, `bindir`, `libdir`, `includedir`, `datarootdir`, `datadir`, `docdir`,
|
|
||||||
`pkgconfigdir` and the xtc-specific `licensedir`, `examplesdir`, `desktopdir` can be
|
Installation now shares one explicit file inventory with uninstallation.
|
||||||
overridden alongside `PREFIX`/`DESTDIR`. Paths must be absolute POSIX paths;
|
GNU-style `exec_prefix`, `bindir`, `libdir`, `includedir`, `datarootdir`,
|
||||||
spaces are supported. Do not include DESTDIR in a directory variable: staging is
|
`datadir`, `docdir`, `pkgconfigdir` and the xtc-specific `licensedir`,
|
||||||
applied separately and never embedded in pkg-config metadata. Staging refuses
|
`examplesdir`, `desktopdir` can be overridden alongside `PREFIX`/`DESTDIR`.
|
||||||
parent symlinks that escape DESTDIR. Use exactly the same variables for removal.
|
Paths must be absolute POSIX paths; spaces are supported. Do not include DESTDIR
|
||||||
|
in a directory variable: staging is applied separately and never embedded in
|
||||||
|
pkg-config metadata. Staging refuses parent symlinks that escape DESTDIR. Use
|
||||||
|
exactly the same variables for removal.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
make BUILD_DIR=build/release-check all test gui
|
make BUILD_DIR=build/release-check all test gui
|
||||||
|
|
@ -90,18 +105,20 @@ make PREFIX=/usr DESTDIR=/tmp/xtc-stage libdir=/usr/lib64 uninstall
|
||||||
make test-release test-package
|
make test-release test-package
|
||||||
```
|
```
|
||||||
|
|
||||||
Core install includes the static library, public headers, `xtc-check`, pkg-config
|
Core install includes the static library, public headers, `xtc-check`,
|
||||||
metadata, Markdown documentation, all checked-in performance reports, license and
|
pkg-config metadata, Markdown documentation, all checked-in performance reports,
|
||||||
`share/xtc/examples` (a media/plugin-free MIDI demo). GUI install adds the desktop
|
license and `share/xtc/examples` (a media/plugin-free MIDI demo). GUI install
|
||||||
entry and `xtc`. No desktop MIME association is claimed. Package archives keep
|
adds the desktop entry and `xtc`. No desktop MIME association is claimed.
|
||||||
their fixed `/usr` layout and relocatable pkg-config metadata; custom live layouts
|
Package archives keep their fixed `/usr` layout and relocatable pkg-config
|
||||||
are tested separately. Existing owned file symlinks are replaced, not followed;
|
metadata; custom live layouts are tested separately. Existing owned file
|
||||||
installation is atomic per file, not a transaction over the entire prefix.
|
symlinks are replaced, not followed; installation is atomic per file, not a
|
||||||
|
transaction over the entire prefix.
|
||||||
|
|
||||||
`make dist` now writes a `.sha256` sidecar as well as the normalized source archive.
|
`make dist` now writes a `.sha256` sidecar as well as the normalized source
|
||||||
Record that hash, the reviewed commit, version and build/dependency conditions
|
archive. Record that hash, the reviewed commit, version and build/dependency
|
||||||
with release logs. `test-release` verifies the hash, builds/tests two fresh source
|
conditions with release logs. `test-release` verifies the hash, builds/tests two
|
||||||
exports and compares artifacts and repacks. It validates exported tracked content,
|
fresh source exports and compares artifacts and repacks. It validates exported
|
||||||
including staged work; it does not attest that the caller's Git tree is clean.
|
tracked content, including staged work; it does not attest that the caller's Git
|
||||||
For public release use a clean reviewed checkout and inspect `git status` first.
|
tree is clean. For public release use a clean reviewed checkout and inspect
|
||||||
RELEASE_NOTES.md supplies upgrade guidance and remaining qualification limits.
|
`git status` first. RELEASE_NOTES.md supplies upgrade guidance and remaining
|
||||||
|
qualification limits.
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
# Engine correctness and reliability
|
# Engine Correctness and Reliability
|
||||||
|
|
||||||
The existing engine was audited rather than extended with musical features. The
|
The existing engine was audited rather than extended with musical features. The
|
||||||
review covers graph edits/compilation, offline DSP, plan publication, JACK
|
review covers graph edits/compilation, offline DSP, plan publication, JACK
|
||||||
callbacks/lifecycle, audio/MIDI source plans and the recorder handoff.
|
callbacks/lifecycle, audio/MIDI source plans and the recorder handoff.
|
||||||
|
|
||||||
## Ownership and synchronization
|
---
|
||||||
|
|
||||||
|
## Ownership and Synchronization
|
||||||
|
|
||||||
| Resource | Owner and lifetime |
|
| Resource | Owner and lifetime |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
|
|
@ -24,7 +26,9 @@ The public realtime API is SPSC: multiple producers, simultaneous process calls,
|
||||||
collection from arbitrary threads, and destruction during processing are not
|
collection from arbitrary threads, and destruction during processing are not
|
||||||
supported. Atomics do not remove those ownership requirements.
|
supported. Atomics do not remove those ownership requirements.
|
||||||
|
|
||||||
## Bounded callback work
|
---
|
||||||
|
|
||||||
|
## Bounded Callback Work
|
||||||
|
|
||||||
Compilation, topological sorting, asset I/O, allocation and native preparation
|
Compilation, topological sorting, asset I/O, allocation and native preparation
|
||||||
are control-thread operations. Graph processing traverses at most 256 nodes,
|
are control-thread operations. Graph processing traverses at most 256 nodes,
|
||||||
|
|
@ -50,13 +54,15 @@ callbacks are trusted: the host cannot prevent their allocation, blocking,
|
||||||
crashes or excessive runtime. Maximum supported capacities are safety bounds,
|
crashes or excessive runtime. Maximum supported capacities are safety bounds,
|
||||||
not a promise that every workload meets its audio deadline.
|
not a promise that every workload meets its audio deadline.
|
||||||
|
|
||||||
## Findings and regression coverage
|
---
|
||||||
|
|
||||||
|
## Findings and Regression Coverage
|
||||||
|
|
||||||
Graph rendering previously mixed the left output before reading right-channel
|
Graph rendering previously mixed the left output before reading right-channel
|
||||||
sources. With external input equal to the left output, the right pass could
|
sources. With external input equal to the left output, the right pass could read
|
||||||
read already processed samples (gain applied twice). Both passes now finish
|
already processed samples (gain applied twice). Both passes now finish source
|
||||||
source reads before either output is written. Tests check mono input aliasing
|
reads before either output is written. Tests check mono input aliasing and
|
||||||
and cross-channel source aliasing against exact expected samples. Output buffers
|
cross-channel source aliasing against exact expected samples. Output buffers
|
||||||
must not overlap each other. A redundant assignment in missing-asset preparation
|
must not overlap each other. A redundant assignment in missing-asset preparation
|
||||||
was also removed after Clang's dead-store diagnostic; behavior is unchanged.
|
was also removed after Clang's dead-store diagnostic; behavior is unchanged.
|
||||||
|
|
||||||
|
|
@ -67,20 +73,23 @@ that failed replacement preserves output and revisions, and counts both stereo
|
||||||
native instances through retirement, collection and destruction of a pending
|
native instances through retirement, collection and destruction of a pending
|
||||||
plan. It repeats this lifecycle 100 times. A maximum 256-node reverse-insertion
|
plan. It repeats this lifecycle 100 times. A maximum 256-node reverse-insertion
|
||||||
chain checks dependency scheduling, long-cycle rejection/rollback and compiled
|
chain checks dependency scheduling, long-cycle rejection/rollback and compiled
|
||||||
snapshot independence. The pthread handoff test submits 2000 native graphs
|
snapshot independence. The pthread handoff test submits 2000 native graphs while
|
||||||
while processing, checks whole-block output/revision consistency, asserts that
|
processing, checks whole-block output/revision consistency, asserts that
|
||||||
prepare/destruction run on the control thread, and balances all native lifetimes
|
prepare/destruction run on the control thread, and balances all native lifetimes
|
||||||
after joining the consumer.
|
after joining the consumer.
|
||||||
|
|
||||||
Existing backend fault tests cover repeated start/stop, partial registration,
|
Existing backend fault tests cover repeated start/stop, partial registration,
|
||||||
callback setup, open/activate/deactivate/close failures and retries, server loss,
|
callback setup, open/activate/deactivate/close failures and retries, server
|
||||||
rate/buffer changes, missing buffers, MIDI disconnect/panic, and recorder detach.
|
loss, rate/buffer changes, missing buffers, MIDI disconnect/panic, and recorder
|
||||||
Other suites cover deterministic variable-block DSP, finite-output handling,
|
detach. Other suites cover deterministic variable-block DSP, finite-output
|
||||||
project errors, record-ring saturation and concurrent draining, and crash/write
|
handling, project errors, record-ring saturation and concurrent draining, and
|
||||||
failure preservation. No critical realtime safety defect remains known within
|
crash/write failure preservation. No critical realtime safety defect remains
|
||||||
these contracts; these tests are evidence for tested paths, not a formal proof.
|
known within these contracts; these tests are evidence for tested paths, not a
|
||||||
|
formal proof.
|
||||||
|
|
||||||
## Reproducing the audit
|
---
|
||||||
|
|
||||||
|
## Reproducing the Audit
|
||||||
|
|
||||||
From the repository root:
|
From the repository root:
|
||||||
|
|
||||||
|
|
@ -92,22 +101,22 @@ make BUILD_DIR=build/audit test-gui test-gui-jack test-jack test-jack-audio test
|
||||||
make BUILD_DIR=build/nojack PKG_CONFIG=false all test-reliability gui
|
make BUILD_DIR=build/nojack PKG_CONFIG=false all test-reliability gui
|
||||||
```
|
```
|
||||||
|
|
||||||
`test-sanitize` needs installed Clang and runs core, allocation-failure and recovery
|
`test-sanitize` needs installed Clang and runs core, allocation-failure and
|
||||||
tests with ASan/UBSan and Linux's default ASan leak checking. `analyze` uses
|
recovery tests with ASan/UBSan and Linux's default ASan leak checking. `analyze`
|
||||||
Clang's path-sensitive analyzer on every core translation unit, including JACK
|
uses Clang's path-sensitive analyzer on every core translation unit, including
|
||||||
when its development files are available, and fails on diagnostics. Python and
|
JACK when its development files are available, and fails on diagnostics. Python
|
||||||
Clang are development tools, not new runtime dependencies. The allocation guard
|
and Clang are development tools, not new runtime dependencies. The allocation
|
||||||
requires a GNU-compatible linker. Live tests require an existing JACK-compatible
|
guard requires a GNU-compatible linker. Live tests require an existing
|
||||||
server; GUI tests use installed FLTK and Xvfb. No target installs dependencies or
|
JACK-compatible server; GUI tests use installed FLTK and Xvfb. No target
|
||||||
changes server/system configuration.
|
installs dependencies or changes server/system configuration.
|
||||||
|
|
||||||
Verification on GCC 16.2.1 / Clang 23.1.3 passed normal and no-JACK builds,
|
Verification on GCC 16.2.1 / Clang 23.1.3 passed normal and no-JACK builds, all
|
||||||
all core tests, ASan/UBSan/leak checks, Clang static analysis, GUI/mock and live
|
core tests, ASan/UBSan/leak checks, Clang static analysis, GUI/mock and live
|
||||||
JACK integrations, plus GCC TSan on the pthread native-publication and recorder
|
JACK integrations, plus GCC TSan on the pthread native-publication and recorder
|
||||||
concurrency tests. The GUI also passed ASan/UBSan with the existing
|
concurrency tests. The GUI also passed ASan/UBSan with the existing
|
||||||
`tests/integration/lsan.supp` fontconfig-only suppression; core tests use no leak
|
`tests/integration/lsan.supp` fontconfig-only suppression; core tests use no
|
||||||
suppression. The live graph test observed both replacement gains, ten restart
|
leak suppression. The live graph test observed both replacement gains, ten
|
||||||
cycles and zero xruns during its five-second software run.
|
restart cycles and zero xruns during its five-second software run.
|
||||||
|
|
||||||
Physical audio devices, hard realtime scheduling, multi-hour endurance and
|
Physical audio devices, hard realtime scheduling, multi-hour endurance and
|
||||||
arbitrary third-party native callbacks remain unqualified. Sanitizers change
|
arbitrary third-party native callbacks remain unqualified. Sanitizers change
|
||||||
|
|
@ -115,7 +124,9 @@ timing and should not be used to measure production realtime performance. See
|
||||||
PERFORMANCE.md for workload measurements, RECOVERY.md for process-crash limits,
|
PERFORMANCE.md for workload measurements, RECOVERY.md for process-crash limits,
|
||||||
and NATIVE_API.md for the trusted extension boundary.
|
and NATIVE_API.md for the trusted extension boundary.
|
||||||
|
|
||||||
## Transition ownership
|
---
|
||||||
|
|
||||||
|
## Transition Ownership
|
||||||
|
|
||||||
Source fade configuration is written before publication and immutable during
|
Source fade configuration is written before publication and immutable during
|
||||||
rendering. The master ramp and stop-observed flag belong to the audio consumer
|
rendering. The master ramp and stop-observed flag belong to the audio consumer
|
||||||
|
|
@ -126,12 +137,15 @@ voices/flags. A completed callback continues silence/holds position until that
|
||||||
deactivation. No callback waits or calls JACK control functions. Immediate
|
deactivation. No callback waits or calls JACK control functions. Immediate
|
||||||
stop/close handles faults or missing callbacks. See AUDIO_QUALITY.md.
|
stop/close handles faults or missing callbacks. See AUDIO_QUALITY.md.
|
||||||
|
|
||||||
## Repeatable development checks
|
---
|
||||||
|
|
||||||
`make check-development` combines normal tests, capacity/endurance, deterministic
|
## Repeatable Development Checks
|
||||||
benchmark-gate tests, static analysis and ASan/UBSan (including scale and soak).
|
|
||||||
`make test-stress` repeats project/backend/publication faults under CPU contention;
|
`make check-development` combines normal tests, capacity/endurance,
|
||||||
`make test-stress-plugins` adds the original LADSPA failure fixture. The reliability
|
deterministic benchmark-gate tests, static analysis and ASan/UBSan (including
|
||||||
callback guard now also rejects common host file I/O and blocking mutex/condition
|
scale and soak). `make test-stress` repeats project/backend/publication faults
|
||||||
calls. It audits directly linked host code, not arbitrary dynamic-plugin internals.
|
under CPU contention; `make test-stress-plugins` adds the original LADSPA
|
||||||
See PERFORMANCE.md for exact workloads, metrics, profiles and qualification limits.
|
failure fixture. The reliability callback guard now also rejects common host
|
||||||
|
file I/O and blocking mutex/condition calls. It audits directly linked host
|
||||||
|
code, not arbitrary dynamic-plugin internals. See PERFORMANCE.md for exact
|
||||||
|
workloads, metrics, profiles and qualification limits.
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
# Modular routing workflow
|
# Modular Routing Workflow
|
||||||
|
|
||||||
Open Modular Graph (Ctrl+3). Select a node or wire to inspect it in the feedback
|
Open Modular Graph (Ctrl+3). Select a node or wire to inspect it in the feedback
|
||||||
line. Nodes have stable IDs, role labels and distinct colors: teal sources,
|
line. Nodes have stable IDs, role labels and distinct colors: teal sources,
|
||||||
purple gain/bus nodes, blue processors/meters and red output sums. LADSPA nodes
|
purple gain/bus nodes, blue processors/meters and red output sums. LADSPA nodes
|
||||||
also show the saved plugin label. Track names remain in Sequencer/Mixer; the
|
also show the saved plugin label. Track names remain in Sequencer/Mixer; the
|
||||||
Audio mix and MIDI mix graph sources represent their shared mix buffers, not
|
Audio mix and MIDI mix graph sources represent their shared mix buffers, not
|
||||||
individual tracks. MIDI mix is the internal sine-instrument mix; its graph
|
individual tracks. MIDI mix is the internal sine-instrument mix; its graph ports
|
||||||
ports carry audio, not MIDI events. Native nodes are trusted extensions.
|
carry audio, not MIDI events. Native nodes are trusted extensions.
|
||||||
|
|
||||||
Wires show arrows from right-hand audio outputs to left-hand inputs. Selecting
|
Wires show arrows from right-hand audio outputs to left-hand inputs. Selecting a
|
||||||
a node highlights all its incoming/outgoing wires; selecting a wire shows its
|
node highlights all its incoming/outgoing wires; selecting a wire shows its
|
||||||
endpoint IDs. Inputs sum all connected signals without normalization; fan-out
|
endpoint IDs. Inputs sum all connected signals without normalization; fan-out
|
||||||
sends the same signal to each destination. Multiple output nodes sum into the
|
sends the same signal to each destination. Multiple output nodes sum into the
|
||||||
engine output. Gain/bus nodes are ordinary summing gain processors, not a new
|
engine output. Gain/bus nodes are ordinary summing gain processors, not a new
|
||||||
|
|
@ -31,6 +31,8 @@ path is not a substitute for stopping playback or muting a track. The graph
|
||||||
models one audio lane per port; stereo compilation processes paired independent
|
models one audio lane per port; stereo compilation processes paired independent
|
||||||
lanes. It does not expose separate left/right, MIDI or control wires.
|
lanes. It does not expose separate left/right, MIDI or control wires.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
| Action | Operation |
|
| Action | Operation |
|
||||||
|
|
@ -58,11 +60,13 @@ allocates a fresh stable node ID and is **one** semantic edit/undo step. It
|
||||||
preserves all other edges. Failure (including capacity, a missing/stale wire or
|
preserves all other edges. Failure (including capacity, a missing/stale wire or
|
||||||
backend refusal) keeps the previous graph and plan. It introduces no new node
|
backend refusal) keeps the previous graph and plan. It introduces no new node
|
||||||
type or project record: v8 persistence already represents the resulting graph.
|
type or project record: v8 persistence already represents the resulting graph.
|
||||||
One-level stereo mix buses are added before shared graph sources (see
|
One-level stereo mix buses are added before shared graph sources (see MIXER.md).
|
||||||
MIXER.md). Track templates, folders and independent per-track/bus graph inserts
|
Track templates, folders and independent per-track/bus graph inserts remain
|
||||||
remain deferred because graph sources still expose shared mixes.
|
deferred because graph sources still expose shared mixes.
|
||||||
|
|
||||||
## Transactions, cycles and realtime ownership
|
---
|
||||||
|
|
||||||
|
## Transactions, Cycles and Realtime Ownership
|
||||||
|
|
||||||
The public C `xtc_graph_apply_edit` command constructs a private candidate.
|
The public C `xtc_graph_apply_edit` command constructs a private candidate.
|
||||||
`XTC_EDIT_INSERT_GAIN` uses `data.connection` and returns the fresh ID through
|
`XTC_EDIT_INSERT_GAIN` uses `data.connection` and returns the fresh ID through
|
||||||
|
|
@ -77,34 +81,37 @@ The GUI clones its project and compiles/publishes the exact candidate through
|
||||||
the existing backend before replacing the displayed model/history. When running,
|
the existing backend before replacing the displayed model/history. When running,
|
||||||
a complete immutable plan is adopted at a block boundary; the control thread
|
a complete immutable plan is adopted at a block boundary; the control thread
|
||||||
collects acknowledged retired plans. The feedback line distinguishes prepared,
|
collects acknowledged retired plans. The feedback line distinguishes prepared,
|
||||||
queued and active revisions. A queued graph can appear before it becomes audible.
|
queued and active revisions. A queued graph can appear before it becomes
|
||||||
The single pending slot can reject a busy edit with CAPACITY: wait for adoption
|
audible. The single pending slot can reject a busy edit with CAPACITY: wait for
|
||||||
and retry. There is no hidden unbounded edit queue or callback mutation. Normal
|
adoption and retry. There is no hidden unbounded edit queue or callback
|
||||||
graph edits can run during playback; undo/redo uses the existing stopped-plan
|
mutation. Normal graph edits can run during playback; undo/redo uses the
|
||||||
installation contract. Recording still blocks semantic graph edits. Plan swaps
|
existing stopped-plan installation contract. Recording still blocks semantic
|
||||||
may reset oscillator/plugin state and are not crossfaded.
|
graph edits. Plan swaps may reset oscillator/plugin state and are not
|
||||||
|
crossfaded.
|
||||||
|
|
||||||
`xtc_graph_analyze` computes input/output edge counts, longest-path level,
|
`xtc_graph_analyze` computes input/output edge counts, longest-path level,
|
||||||
rendered-output reachability and external-input fallback in dense-node order.
|
rendered-output reachability and external-input fallback in dense-node order. It
|
||||||
It is a bounded, allocation-free **control-thread** API, not a callback service.
|
is a bounded, allocation-free **control-thread** API, not a callback service. It
|
||||||
It never loads plugins. It honors explicit outputs; legacy terminal fallback
|
never loads plugins. It honors explicit outputs; legacy terminal fallback
|
||||||
applies only when there are no explicit output nodes and the caller has not
|
applies only when there are no explicit output nodes and the caller has not
|
||||||
required them. Errors leave result storage/count unchanged. The GUI caches this
|
required them. Errors leave result storage/count unchanged. The GUI caches this
|
||||||
analysis when binding a graph; drawing reads cached metadata only. It uses
|
analysis when binding a graph; drawing reads cached metadata only. It uses
|
||||||
public C snapshots/commands and never engine internals or callback storage.
|
public C snapshots/commands and never engine internals or callback storage.
|
||||||
|
|
||||||
## Verification and limits
|
---
|
||||||
|
|
||||||
|
## Verification and Limits
|
||||||
|
|
||||||
`make test-routing` checks branch reachability, external input, levels, capacity
|
`make test-routing` checks branch reachability, external input, levels, capacity
|
||||||
rollback, exact unity-insertion rendering and complete plan handoff. `make test`
|
rollback, exact unity-insertion rendering and complete plan handoff. `make test`
|
||||||
also retains concurrent publication/lifecycle tests.
|
also retains concurrent publication/lifecycle tests. `make test-reliability`
|
||||||
`make test-reliability` retains the callback-allocation guards.
|
retains the callback-allocation guards. `make test-gui-plugins` checks selection
|
||||||
`make test-gui-plugins` checks selection diagnostics, unique placement/layout,
|
diagnostics, unique placement/layout, failed backend publication, atomic
|
||||||
failed backend publication, atomic insertion undo/redo and keyboard focus.
|
insertion undo/redo and keyboard focus. `make test-gui-jack`
|
||||||
`make test-gui-jack` inserts/disconnects/restores real routes during live software
|
inserts/disconnects/restores real routes during live software playback and
|
||||||
playback and checks engine revision acknowledgements and cycle rejection.
|
checks engine revision acknowledgements and cycle rejection.
|
||||||
|
|
||||||
Physical routing/listening and hardware endurance remain unqualified. This is
|
Physical routing/listening and hardware endurance remain unqualified. This is an
|
||||||
an audio-lane DAG editor with a default 64-node project capacity (standalone
|
audio-lane DAG editor with a default 64-node project capacity (standalone C
|
||||||
C graphs up to 256), no zoom/lasso or persisted layout, no latency compensation
|
graphs up to 256), no zoom/lasso or persisted layout, no latency compensation
|
||||||
and no plugin crash isolation. Unconnected branches are diagnosed, not pruned.
|
and no plugin crash isolation. Unconnected branches are diagnosed, not pruned.
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
# Track inserts
|
# Track Inserts
|
||||||
|
|
||||||
The sequencer's **Create** dropdown groups track creation, WAV import and
|
The sequencer's **Create** dropdown groups track creation, WAV import and
|
||||||
instrument loading. **View → Track inspector** opens the optional inspector;
|
instrument loading. **View → Track inspector** opens the optional inspector; it
|
||||||
it is hidden when the application starts to leave more room for editing.
|
is hidden when the application starts to leave more room for editing.
|
||||||
|
|
||||||
Project format 17 stores up to eight effect slots per track, their order,
|
Project format 17 stores up to eight effect slots per track, their order,
|
||||||
bypass, wet amount and chain output gain. Formats 1–16 read with empty chains.
|
bypass, wet amount and chain output gain. Formats 1–16 read with empty chains.
|
||||||
|
|
@ -17,39 +17,41 @@ chain; plugin identity and layout are checked when preparing playback.
|
||||||
|
|
||||||
Playback prepares an independent serial graph for each affected track. Audio
|
Playback prepares an independent serial graph for each affected track. Audio
|
||||||
clips on the same track sum before its effects; instrument and scheduled MIDI
|
clips on the same track sum before its effects; instrument and scheduled MIDI
|
||||||
contributions also pass through their track graph. Effects run before track
|
contributions also pass through their track graph. Effects run before track and
|
||||||
and bus gain/pan, and meters observe their output. Wet/dry uses parallel gain
|
bus gain/pan, and meters observe their output. Wet/dry uses parallel gain
|
||||||
branches. Internal effect history resets at timeline discontinuities.
|
branches. Internal effect history resets at timeline discontinuities.
|
||||||
|
|
||||||
Each renderer owns its plans and preallocated raw buffers (up to 256 KiB per
|
Each renderer owns its plans and preallocated raw buffers (up to 256 KiB per
|
||||||
affected track); processing uses blocks of at most 256 frames, with no host
|
affected track); processing uses blocks of at most 256 frames, with no host
|
||||||
allocation or I/O. Mono effect adapters require zero reported latency. External
|
allocation or I/O. Mono effect adapters require zero reported latency. External
|
||||||
plugin state on seeks follows the existing host contract. Bus inserts and
|
plugin state on seeks follows the existing host contract. Bus inserts and tracks
|
||||||
tracks containing both audio assets and MIDI reject preparation explicitly.
|
containing both audio assets and MIDI reject preparation explicitly. Live
|
||||||
Live unassigned sine monitoring remains a separate master input.
|
unassigned sine monitoring remains a separate master input.
|
||||||
|
|
||||||
Open **View → Track inserts** (or Ctrl+5 for the selected track) and choose a track. **Add effect** offers
|
Open **View → Track inserts** (or Ctrl+5 for the selected track) and choose a
|
||||||
internal Delay/Reverb and the plugin library. The left rack shows signal order;
|
track. **Add effect** offers internal Delay/Reverb and the plugin library. The
|
||||||
the graph displays the actual generated graph compiled by playback. Wiring in
|
left rack shows signal order; the graph displays the actual generated graph
|
||||||
this view is read-only: edit the rack to preserve the serial chain. The global
|
compiled by playback. Wiring in this view is read-only: edit the rack to
|
||||||
Modular Graph remains independent. A failed plugin probe or playback preparation
|
preserve the serial chain. The global Modular Graph remains independent. A
|
||||||
preserves the current project; successful additions are undoable.
|
failed plugin probe or playback preparation preserves the current project;
|
||||||
|
successful additions are undoable.
|
||||||
|
|
||||||
The library searches configured Preferences paths recursively (including VST3
|
The library searches configured Preferences paths recursively (including VST3
|
||||||
bundle contents), with case-insensitive search and format filters. LADSPA and
|
bundle contents), with case-insensitive search and format filters. LADSPA and
|
||||||
VST2 both use `.so`, so those filters share candidates until inspection identifies
|
VST2 both use `.so`, so those filters share candidates until inspection
|
||||||
the ABI. Listing files executes no plugin code. Only inspect trusted binaries.
|
identifies the ABI. Listing files executes no plugin code. Only inspect trusted
|
||||||
|
binaries.
|
||||||
|
|
||||||
Select a slot in the rack, then use **Up**, **Down**, **Bypass** or **Remove**.
|
Select a slot in the rack, then use **Up**, **Down**, **Bypass** or **Remove**.
|
||||||
The selection follows reordered effects. Bypassed slots retain their settings
|
The selection follows reordered effects. Bypassed slots retain their settings
|
||||||
and appear marked in the rack; their nodes are omitted from the compiled graph.
|
and appear marked in the rack; their nodes are omitted from the compiled graph.
|
||||||
Each successful operation creates one project undo step.
|
Each successful operation creates one project undo step.
|
||||||
|
|
||||||
**Inspect / edit** verifies the selected plugin and opens its identity and generic
|
**Inspect / edit** verifies the selected plugin and opens its identity and
|
||||||
controls. Reset defaults clears parameter automation on Apply. Cancel leaves the
|
generic controls. Reset defaults clears parameter automation on Apply. Cancel
|
||||||
project unchanged. Internal effects and LADSPA expose controls; modern adapters
|
leaves the project unchanged. Internal effects and LADSPA expose controls;
|
||||||
currently expose none and run default configurations. Native plugin editor
|
modern adapters currently expose none and run default configurations. Native
|
||||||
windows and opaque plugin-state chunks are not implemented.
|
plugin editor windows and opaque plugin-state chunks are not implemented.
|
||||||
|
|
||||||
**Preset → Save chain / Load chain** reuses the atomic versioned project file
|
**Preset → Save chain / Load chain** reuses the atomic versioned project file
|
||||||
container with one track. Order, bypass, wet amounts, output gain and exposed
|
container with one track. Order, bypass, wet amounts, output gain and exposed
|
||||||
|
|
@ -67,19 +69,19 @@ insert layouts, latency compensation and gapless live insert edits are future
|
||||||
work. Editing stops transport before preparing the replacement plan.
|
work. Editing stops transport before preparing the replacement plan.
|
||||||
|
|
||||||
The CLI `xtc-check --inspect project.xtc` lists insert format, slot order,
|
The CLI `xtc-check --inspect project.xtc` lists insert format, slot order,
|
||||||
bypass/wet settings and missing binary references without loading plugins.
|
bypass/wet settings and missing binary references without loading plugins. VST3
|
||||||
VST3 processing supplies a fixed output-parameter sink (64 IDs, final point per
|
processing supplies a fixed output-parameter sink (64 IDs, final point per
|
||||||
ID/block) for plugins that emit meter/parameter notifications; notifications are
|
ID/block) for plugins that emit meter/parameter notifications; notifications are
|
||||||
not recorded or exposed as controls.
|
not recorded or exposed as controls.
|
||||||
|
|
||||||
Host qualification on 2026-11-06 used the installed Linux x86_64 ZamEQ2,
|
Host qualification on 2026-11-06 used the installed Linux x86_64 ZamEQ2,
|
||||||
ZamAutoSat and ZamDelay VST3 binaries under `/usr/lib/vst3`. All three were
|
ZamAutoSat and ZamDelay VST3 binaries under `/usr/lib/vst3`. All three were
|
||||||
prepared together, rendered with nonzero finite output and exported to WAV.
|
prepared together, rendered with nonzero finite output and exported to WAV. This
|
||||||
This verifies those default mono configurations, not arbitrary plugins or
|
verifies those default mono configurations, not arbitrary plugins or physical
|
||||||
physical hardware. The repository fixtures cover LADSPA, CLAP, VST2 and VST3
|
hardware. The repository fixtures cover LADSPA, CLAP, VST2 and VST3 insert
|
||||||
insert adoption and VST3 output notification bounds. Internal-plan allocation
|
adoption and VST3 output notification bounds. Internal-plan allocation failure
|
||||||
failure and callback guards, sanitizers, GUI/JACK lifecycle and install checks
|
and callback guards, sanitizers, GUI/JACK lifecycle and install checks cover
|
||||||
cover host ownership and cleanup.
|
host ownership and cleanup.
|
||||||
|
|
||||||
Reproduce focused verification with:
|
Reproduce focused verification with:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,36 +1,44 @@
|
||||||
# xtc user manual (0.1.0 development build)
|
# xtc User Manual (0.1.0 Development Build)
|
||||||
|
|
||||||
xtc is a bounded Linux music-making prototype. Start with a copy of an important
|
xtc is a bounded Linux music-making prototype. Start with a copy of an important
|
||||||
project and keep backups of its WAV media. Supported limits and unfinished areas
|
project and keep backups of its WAV media. Supported limits and unfinished areas
|
||||||
are listed in KNOWN_LIMITATIONS.md; no production/device qualification is implied.
|
are listed in KNOWN_LIMITATIONS.md; no production/device qualification is
|
||||||
|
implied.
|
||||||
|
|
||||||
## Build or install
|
---
|
||||||
|
|
||||||
|
## Build or Install
|
||||||
|
|
||||||
Follow BUILD.md and LINUX.md. Core: `make all test`; GUI: `make gui`, then
|
Follow BUILD.md and LINUX.md. Core: `make all test`; GUI: `make gui`, then
|
||||||
`./build/xtc`. Use an existing JACK-compatible server and reconnect with F6.
|
`./build/xtc`. Use an existing JACK-compatible server and reconnect with F6.
|
||||||
Connect `midi_in` to a controller, `input` to mono capture and `output` /
|
Connect `midi_in` to a controller, `input` to mono capture and `output` /
|
||||||
`output_right` to left/right playback using your JACK routing application.
|
`output_right` to left/right playback using your JACK routing application. No
|
||||||
No server, physical routing or system configuration is changed automatically.
|
server, physical routing or system configuration is changed automatically.
|
||||||
`xtc --version`, `xtc --help` and `xtc --diagnose` need no display/server.
|
`xtc --version`, `xtc --help` and `xtc --diagnose` need no display/server.
|
||||||
|
|
||||||
For a source install stage with `make install-gui DESTDIR="$PWD/build/stage"
|
For a source install stage with
|
||||||
PREFIX=/usr`, inspect the stage, and use your normal deployment process. A user
|
`make install-gui DESTDIR="$PWD/build/stage" PREFIX=/usr`, inspect the stage,
|
||||||
prefix is supported (for example an absolute path to your `.local` folder).
|
and use your normal deployment process. A user prefix is supported (for example
|
||||||
`make uninstall` with the same DESTDIR/PREFIX removes only that version's known
|
an absolute path to your `.local` folder). `make uninstall` with the same
|
||||||
files. See LINUX.md for package extraction, dependencies and removal. Never use
|
DESTDIR/PREFIX removes only that version's known files. See LINUX.md for package
|
||||||
a release built for a different system ABI without rebuilding/testing it.
|
extraction, dependencies and removal. Never use a release built for a different
|
||||||
|
system ABI without rebuilding/testing it.
|
||||||
|
|
||||||
## Make a short project
|
---
|
||||||
|
|
||||||
|
## Make A Short Project
|
||||||
|
|
||||||
1. New/Open starts in Sequencer. Add track; use F2 to name it.
|
1. New/Open starts in Sequencer. Add track; use F2 to name it.
|
||||||
2. Add MIDI clip, select it and open Piano roll (Ctrl+4). Left-click to draw
|
2. Add MIDI clip, select it and open Piano roll (Ctrl+4). Left-click to draw
|
||||||
notes, drag to move, drag a right edge to resize, Delete/right-click to remove.
|
notes, drag to move, drag a right edge to resize, Delete/right-click to
|
||||||
|
remove.
|
||||||
3. Alternatively Import WAV (Ctrl+I). It creates/routes an Audio clips source;
|
3. Alternatively Import WAV (Ctrl+I). It creates/routes an Audio clips source;
|
||||||
supported WAV formats and preload limits are in AUDIO_FILES.md.
|
supported WAV formats and preload limits are in AUDIO_FILES.md.
|
||||||
4. Drag clips to arrange them and edges to trim. View/Snap sets the timeline
|
4. Drag clips to arrange them and edges to trim. View/Snap sets the timeline
|
||||||
grid; +/- zoom buttons and scrollbars navigate. Ctrl+D duplicates a clip after
|
grid; +/- zoom buttons and scrollbars navigate. Ctrl+D duplicates a clip
|
||||||
its end, retaining its complete source. F2 names clips; right-click offers
|
after its end, retaining its complete source. F2 names clips; right-click
|
||||||
duplicate/rename/delete. Alt+Up/Down with timeline focus reorders tracks.
|
offers duplicate/rename/delete. Alt+Up/Down with timeline focus reorders
|
||||||
|
tracks.
|
||||||
5. Play/F5 starts; Pause/F7 or Stop/F8 leaves the position for resuming. Home
|
5. Play/F5 starts; Pause/F7 or Stop/F8 leaves the position for resuming. Home
|
||||||
returns to start while stopped (or stops first); click the ruler to seek.
|
returns to start while stopped (or stops first); click the ruler to seek.
|
||||||
Recording uses Stop, not Pause. F9 Panic releases the instrument.
|
Recording uses Stop, not Pause. F9 Panic releases the instrument.
|
||||||
|
|
@ -38,22 +46,27 @@ a release built for a different system ABI without rebuilding/testing it.
|
||||||
Click to add points, right-click to remove. CONTROL.md explains timing and
|
Click to add points, right-click to remove. CONTROL.md explains timing and
|
||||||
live CC7 volume, CC10 pan and CC64 sustain.
|
live CC7 volume, CC10 pan and CC64 sustain.
|
||||||
7. Save (Ctrl+S), close, reopen and continue editing. Ctrl+Z undoes and
|
7. Save (Ctrl+S), close, reopen and continue editing. Ctrl+Z undoes and
|
||||||
Ctrl+Shift+Z/Ctrl+Y redoes. New/Open resets history after unsaved-change handling.
|
Ctrl+Shift+Z/Ctrl+Y redoes. New/Open resets history after unsaved-change
|
||||||
|
handling.
|
||||||
|
|
||||||
Modular Graph (Ctrl+3) exposes routing. Drag output to input to connect, select a
|
Modular Graph (Ctrl+3) exposes routing. Drag output to input to connect, select
|
||||||
wire/node and Delete to remove; cycles and invalid ports are rejected. Keep an
|
a wire/node and Delete to remove; cycles and invalid ports are rejected. Keep an
|
||||||
Output route for playback. GUI changes show queued/active graph status. Graph
|
Output route for playback. GUI changes show queued/active graph status. Graph
|
||||||
positions are session-only; music/routing/automation are saved. Edits that prepare
|
positions are session-only; music/routing/automation are saved. Edits that
|
||||||
new plans stop playback; disk/compilation may pause the GUI, never run in audio.
|
prepare new plans stop playback; disk/compilation may pause the GUI, never run
|
||||||
|
in audio.
|
||||||
|
|
||||||
## Record and retain media
|
---
|
||||||
|
|
||||||
Choose a project folder and save the project there first. Record/Shift+F5 asks for
|
## Record and Retain Media
|
||||||
an unused WAV path. Stop finalizes the take and inserts it. Existing destinations
|
|
||||||
are protected, including a file created while recording. Undo/removing a take
|
Choose a project folder and save the project there first. Record/Shift+F5 asks
|
||||||
removes its reference, never the recorded file. Imported external files are also
|
for an unused WAV path. Stop finalizes the take and inserts it. Existing
|
||||||
never deleted. WAVs inside the save folder become relative references; move the
|
destinations are protected, including a file created while recording.
|
||||||
folder and media together. Save As preserves the same source media, not a copy.
|
Undo/removing a take removes its reference, never the recorded file. Imported
|
||||||
|
external files are also never deleted. WAVs inside the save folder become
|
||||||
|
relative references; move the folder and media together. Save As preserves the
|
||||||
|
same source media, not a copy.
|
||||||
|
|
||||||
On write failure the GUI reports a retained path. Keep it and recover complete
|
On write failure the GUI reports a retained path. Keep it and recover complete
|
||||||
frames to a different, unused destination:
|
frames to a different, unused destination:
|
||||||
|
|
@ -62,62 +75,74 @@ frames to a different, unused destination:
|
||||||
xtc-check --recover-recording take.wav.tmp.XXXXXX recovered.wav
|
xtc-check --recover-recording take.wav.tmp.XXXXXX recovered.wav
|
||||||
```
|
```
|
||||||
|
|
||||||
Only xtc's canonical float32 mono temporary format is salvaged. Incomplete trailing
|
Only xtc's canonical float32 mono temporary format is salvaged. Incomplete
|
||||||
frames are omitted. The source is retained. Import/relink the recovered WAV.
|
trailing frames are omitted. The source is retained. Import/relink the recovered
|
||||||
Missing/unreadable media is silent and reported; select the clip and use File/
|
WAV. Missing/unreadable media is silent and reported; select the clip and use
|
||||||
Relink selected audio. See RECOVERY.md for interruption, disk-full and power-loss
|
File/ Relink selected audio. See RECOVERY.md for interruption, disk-full and
|
||||||
limits. Close/project operations are refused while recording; finish the take first.
|
power-loss limits. Close/project operations are refused while recording; finish
|
||||||
|
the take first.
|
||||||
|
|
||||||
## Trusted effects and sources
|
---
|
||||||
|
|
||||||
File/Load LADSPA plugin lists compatible descriptor indices from the chosen `.so`.
|
## Trusted Effects and Sources
|
||||||
Loading executes native code. Select a documented compatible mono plugin, connect
|
|
||||||
its graph ports, then use Edit/Selected plugin control. Edit/Selected plugin
|
|
||||||
automation adds/removes tick-based linear or step points. Control names/ranges
|
|
||||||
appear in the dialogs. Module identity/control values/lanes save with the project;
|
|
||||||
module binaries and DSP history do not. The initial amp/inverter/sine set and
|
|
||||||
unsupported layouts are listed in PLUGIN_HOSTING.md. Missing plugins reject GUI
|
|
||||||
Open with identity/path information and preserve the saved/current documents.
|
|
||||||
Restore the compatible module at that path and retry. Plugins are not sandboxed.
|
|
||||||
|
|
||||||
## Diagnose a problem
|
File/Load LADSPA plugin lists compatible descriptor indices from the chosen
|
||||||
|
`.so`. Loading executes native code. Select a documented compatible mono plugin,
|
||||||
|
connect its graph ports, then use Edit/Selected plugin control. Edit/Selected
|
||||||
|
plugin automation adds/removes tick-based linear or step points. Control
|
||||||
|
names/ranges appear in the dialogs. Module identity/control values/lanes save
|
||||||
|
with the project; module binaries and DSP history do not. The initial
|
||||||
|
amp/inverter/sine set and unsupported layouts are listed in PLUGIN_HOSTING.md.
|
||||||
|
Missing plugins reject GUI Open with identity/path information and preserve the
|
||||||
|
saved/current documents. Restore the compatible module at that path and retry.
|
||||||
|
Plugins are not sandboxed.
|
||||||
|
|
||||||
Run `xtc-check --diagnose` and capture the version, architecture, compiled features,
|
---
|
||||||
GUI error text and steps to reproduce. `xtc-check --validate song.xtc` checks
|
|
||||||
metadata without opening plugins/media; it does not certify playback resources.
|
|
||||||
Check JACK routing, sample rate/format and xrun/process status in the GUI. After
|
|
||||||
server loss/rate change stop/reconnect and retry. Keep the original project,
|
|
||||||
media and retained temporary files before recovery attempts.
|
|
||||||
|
|
||||||
A native plugin can crash/hang the process. There is no crash-isolation guarantee.
|
## Diagnose A Problem
|
||||||
Use the operating system's core-dump/debugger tools if available; xtc does not
|
|
||||||
install signal handlers, change core limits or upload crash reports. Debugger/
|
|
||||||
core files may contain media paths and audio memory; share only what you intend.
|
|
||||||
Report bugs following MAINTENANCE.md, including whether the issue reproduces
|
|
||||||
without plugins. Physical listening and independent human install/usability
|
|
||||||
acceptance remain pending.
|
|
||||||
|
|
||||||
## MIDI composition
|
Run `xtc-check --diagnose` and capture the version, architecture, compiled
|
||||||
|
features, GUI error text and steps to reproduce. `xtc-check --validate song.xtc`
|
||||||
|
checks metadata without opening plugins/media; it does not certify playback
|
||||||
|
resources. Check JACK routing, sample rate/format and xrun/process status in the
|
||||||
|
GUI. After server loss/rate change stop/reconnect and retry. Keep the original
|
||||||
|
project, media and retained temporary files before recovery attempts.
|
||||||
|
|
||||||
|
A native plugin can crash/hang the process. There is no crash-isolation
|
||||||
|
guarantee. Use the operating system's core-dump/debugger tools if available; xtc
|
||||||
|
does not install signal handlers, change core limits or upload crash reports.
|
||||||
|
Debugger/ core files may contain media paths and audio memory; share only what
|
||||||
|
you intend. Report bugs following MAINTENANCE.md, including whether the issue
|
||||||
|
reproduces without plugins. Physical listening and independent human
|
||||||
|
install/usability acceptance remain pending.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## MIDI Composition
|
||||||
|
|
||||||
In Piano roll, use the Notes menu for grid (including triplets), channel/pitch
|
In Piano roll, use the Notes menu for grid (including triplets), channel/pitch
|
||||||
filters, velocity/channel, quantization, transposition and pattern repetition.
|
filters, velocity/channel, quantization, transposition and pattern repetition.
|
||||||
Click selects a single note; Ctrl+A selects all filtered notes. Ctrl+D repeats
|
Click selects a single note; Ctrl+A selects all filtered notes. Ctrl+D repeats
|
||||||
that selection at a chosen spacing within the existing clip source. Up/Down
|
that selection at a chosen spacing within the existing clip source. Up/Down
|
||||||
transposes by a semitone. Commands are undoable through the main Edit menu.
|
transposes by a semitone. Commands are undoable through the main Edit menu. See
|
||||||
See [MIDI.md](MIDI.md#composition-commands) for shortcuts, timing and limits.
|
[MIDI.md](MIDI.md#composition-commands) for shortcuts, timing and limits.
|
||||||
|
|
||||||
## Audio clip tools
|
---
|
||||||
|
|
||||||
|
## Audio Clip Tools
|
||||||
|
|
||||||
Select an audio clip, click the ruler at the desired cut while stopped, then
|
Select an audio clip, click the ruler at the desired cut while stopped, then
|
||||||
choose Edit / Split clip at cursor (S with timeline focus). Ctrl+D duplicates;
|
choose Edit / Split clip at cursor (S with timeline focus). Ctrl+D duplicates;
|
||||||
Delete removes the clip reference. Drag the body to move and edges to trim.
|
Delete removes the clip reference. Drag the body to move and edges to trim. Edit
|
||||||
Edit / Audio clip gain and fades (A) sets linear gain and fade durations in ticks.
|
/ Audio clip gain and fades (A) sets linear gain and fade durations in ticks.
|
||||||
All are undoable and preserve the WAV file. Waveforms show cached raw source
|
All are undoable and preserve the WAV file. Waveforms show cached raw source
|
||||||
peaks, before gain/fades; large media can take time to load on Open/import.
|
peaks, before gain/fades; large media can take time to load on Open/import. See
|
||||||
See [AUDIO_FILES.md](AUDIO_FILES.md#non-destructive-clip-editing) for
|
[AUDIO_FILES.md](AUDIO_FILES.md#non-destructive-clip-editing) for boundary
|
||||||
boundary behavior, preview limits and the deferred stretch/pitch tools.
|
behavior, preview limits and the deferred stretch/pitch tools.
|
||||||
|
|
||||||
## Inspecting and organizing routing
|
---
|
||||||
|
|
||||||
|
## Inspecting and Organizing Routing
|
||||||
|
|
||||||
In Modular Graph, select a node or wire to inspect its routing in the feedback
|
In Modular Graph, select a node or wire to inspect its routing in the feedback
|
||||||
line. Arrows show direction; yellow no-output badges identify disconnected
|
line. Arrows show direction; yellow no-output badges identify disconnected
|
||||||
|
|
@ -126,48 +151,54 @@ unity gain/bus node as one undoable edit. These commands are also in View/Edit
|
||||||
and the graph context menu. Unwired effect inputs use external audio, as shown
|
and the graph context menu. Unwired effect inputs use external audio, as shown
|
||||||
by “ext in”; they do not imply silence. See [ROUTING.md](ROUTING.md).
|
by “ext in”; they do not imply silence. See [ROUTING.md](ROUTING.md).
|
||||||
|
|
||||||
The Mixer also offers Add bus and a Route choice for ordinary tracks.
|
The Mixer also offers Add bus and a Route choice for ordinary tracks. Select
|
||||||
Select Track/Bus strips to edit their controls and automation. Master and selected
|
Track/Bus strips to edit their controls and automation. Master and selected
|
||||||
strip meters show dBFS with 20 dB/s release; Reset peaks clears latched clipping.
|
strip meters show dBFS with 20 dB/s release; Reset peaks clears latched
|
||||||
See MIXER.md for solo rules, gain staging and meter taps.
|
clipping. See MIXER.md for solo rules, gain staging and meter taps.
|
||||||
|
|
||||||
File → Load LADSPA plugin offers a descriptor browser. Select a graph
|
File → Load LADSPA plugin offers a descriptor browser. Select a graph plugin and
|
||||||
plugin and Edit → Selected plugin control for identity, values, ranges and
|
Edit → Selected plugin control for identity, values, ranges and Reset defaults;
|
||||||
Reset defaults; Apply commits, Cancel discards. Edit also offers replacement,
|
Apply commits, Cancel discards. Edit also offers replacement, reset and
|
||||||
reset and insertion of an effect on a selected wire. Graph wires determine
|
insertion of an effect on a selected wire. Graph wires determine processing
|
||||||
processing order; Delete removes a selected plugin and its wires. Changes are
|
order; Delete removes a selected plugin and its wires. Changes are undoable.
|
||||||
undoable. Replacement keeps compatible audio wiring but resets plugin controls
|
Replacement keeps compatible audio wiring but resets plugin controls and
|
||||||
and automation. See PLUGIN_HOSTING.md for supported formats and failure behavior.
|
automation. See PLUGIN_HOSTING.md for supported formats and failure behavior.
|
||||||
|
|
||||||
Mixer Interpolation selects Linear or Hold for each point added or replaced. Audio → MIDI controller mapping lists all channel bindings; enter
|
Mixer Interpolation selects Linear or Hold for each point added or replaced.
|
||||||
|
Audio → MIDI controller mapping lists all channel bindings; enter
|
||||||
`channel volume_CC pan_CC sustain_CC` (channels 0..15, 128 disables, enabled CCs
|
`channel volume_CC pan_CC sustain_CC` (channels 0..15, 128 disables, enabled CCs
|
||||||
must be distinct, 120/123 reserved). Maps are undoable and saved. Controllers
|
must be distinct, 120/123 reserved). Maps are undoable and saved. Controllers
|
||||||
modify live sine voices; arranged track/bus/plugin automation takes precedence
|
modify live sine voices; arranged track/bus/plugin automation takes precedence
|
||||||
over its static controls and is unaffected by those MIDI bindings. See CONTROL.md.
|
over its static controls and is unaffected by those MIDI bindings. See
|
||||||
|
CONTROL.md.
|
||||||
|
|
||||||
Unavailable main-menu undo/redo actions are disabled, including while recording. Piano roll has Edit/Undo/Redo shortcuts and a right-click note menu;
|
Unavailable main-menu undo/redo actions are disabled, including while recording.
|
||||||
right-click no longer immediately deletes notes. Graph right-click targets the
|
Piano roll has Edit/Undo/Redo shortcuts and a right-click note menu; right-click
|
||||||
node/wire under the pointer. Undo preserves surviving selections. Completed
|
no longer immediately deletes notes. Graph right-click targets the node/wire
|
||||||
takes add one undo step; undo removes references and keeps WAV files. See
|
under the pointer. Undo preserves surviving selections. Completed takes add one
|
||||||
EDITING.md for grouped commands, failure handling and keyboard/focus behavior.
|
undo step; undo removes references and keeps WAV files. See EDITING.md for
|
||||||
|
grouped commands, failure handling and keyboard/focus behavior.
|
||||||
|
|
||||||
Project troubleshooting: `xtc-check --validate PROJECT.xtc` reports metadata
|
Project troubleshooting: `xtc-check --validate PROJECT.xtc` reports metadata
|
||||||
errors with the expected record and syntax line. `xtc-check --inspect PROJECT.xtc`
|
errors with the expected record and syntax line.
|
||||||
lists resolved media/module paths and plugin identities without executing plugins
|
`xtc-check --inspect PROJECT.xtc` lists resolved media/module paths and plugin
|
||||||
or starting JACK. Exit codes: 0 = valid metadata and available files, 2 = missing
|
identities without executing plugins or starting JACK. Exit codes: 0 = valid
|
||||||
or unreadable references, 1 = metadata/I/O error. File availability does not
|
metadata and available files, 2 = missing or unreadable references, 1 =
|
||||||
certify WAV contents or plugin compatibility. See [PROJECT_FORMAT.md](PROJECT_FORMAT.md)
|
metadata/I/O error. File availability does not certify WAV contents or plugin
|
||||||
for the compatibility and relocation policy.
|
compatibility. See [PROJECT_FORMAT.md](PROJECT_FORMAT.md) for the compatibility
|
||||||
|
and relocation policy.
|
||||||
|
|
||||||
**File → Load plugin** supports LADSPA plus an initial Linux
|
**File → Load plugin** supports LADSPA plus an initial Linux CLAP/VST2/VST3
|
||||||
CLAP/VST2/VST3 effect subset. Select the actual module binary (`.clap` or `.so`,
|
effect subset. Select the actual module binary (`.clap` or `.so`, including a
|
||||||
including a VST3 bundle's inner binary). Modern effects require one mono input
|
VST3 bundle's inner binary). Modern effects require one mono input and output,
|
||||||
and output, float32 and zero latency; they use default configuration. Instruments,
|
float32 and zero latency; they use default configuration. Instruments, modern
|
||||||
modern parameter editing/automation, opaque state and custom editors are not
|
parameter editing/automation, opaque state and custom editors are not
|
||||||
implemented. Projects now save v12 and read v1–v12. See PLUGIN_HOSTING.md for the
|
implemented. Projects now save v12 and read v1–v12. See PLUGIN_HOSTING.md for
|
||||||
full contract and test/qualification limits.
|
the full contract and test/qualification limits.
|
||||||
|
|
||||||
## Instrument support
|
---
|
||||||
|
|
||||||
|
## Instrument Support
|
||||||
|
|
||||||
MIDI tracks can bind CLAP, VST2 and VST3 instruments. In the Track menu, select
|
MIDI tracks can bind CLAP, VST2 and VST3 instruments. In the Track menu, select
|
||||||
**Load instrument plugin** for the selected sequencer track; **Use built-in
|
**Load instrument plugin** for the selected sequencer track; **Use built-in
|
||||||
|
|
@ -178,9 +209,9 @@ their own track's instrument. Independent instances feed track gain/pan,
|
||||||
mute/solo, bus routing and automation. Bindings/live target save in v12.
|
mute/solo, bus routing and automation. Bindings/live target save in v12.
|
||||||
|
|
||||||
Supply the actual trusted Linux binary (including the inner .so of a VST3
|
Supply the actual trusted Linux binary (including the inner .so of a VST3
|
||||||
bundle). Supported instruments have zero audio inputs, one mono output,
|
bundle). Supported instruments have zero audio inputs, one mono output, float32
|
||||||
float32 processing, zero latency and one note/event input. Default configuration
|
processing, zero latency and one note/event input. Default configuration only:
|
||||||
only: no custom editor, opaque state/preset restoration, modern parameter
|
no custom editor, opaque state/preset restoration, modern parameter
|
||||||
editing/automation, stereo/multichannel instruments or MIDI output. No arbitrary
|
editing/automation, stereo/multichannel instruments or MIDI output. No arbitrary
|
||||||
third-party instrument is qualified by the original ABI fixture tests.
|
third-party instrument is qualified by the original ABI fixture tests.
|
||||||
|
|
||||||
|
|
@ -198,27 +229,32 @@ the callback and old instances are reclaimed on the control thread. Missing
|
||||||
references remain inspectable without loading; failed GUI preparation retains
|
references remain inspectable without loading; failed GUI preparation retains
|
||||||
the current project. Save a backup for applications limited to v11 or earlier.
|
the current project. Save a backup for applications limited to v11 or earlier.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Workspace
|
## Workspace
|
||||||
|
|
||||||
The flat workspace puts New MIDI/audio track, WAV import and instrument loading
|
The flat workspace puts New MIDI/audio track, WAV import and instrument loading
|
||||||
in a persistent sidebar, with a musical transport display and selected-track
|
in a persistent sidebar, with a musical transport display and selected-track
|
||||||
overview. See [WORKSPACE.md](WORKSPACE.md) for shortcuts and workflow. Open
|
overview. See [WORKSPACE.md](WORKSPACE.md) for shortcuts and workflow. Open
|
||||||
`modern-session.xtc` in the installed examples for an original four-track arrangement.
|
`modern-session.xtc` in the installed examples for an original four-track
|
||||||
|
arrangement.
|
||||||
|
|
||||||
Use the sequencer Snap dropdown for straight/triplet/bar grids or Off.
|
Use the sequencer Snap dropdown for straight/triplet/bar grids or Off.
|
||||||
Double-click MIDI clips to edit notes, then use the Velocity lane or selected-note
|
Double-click MIDI clips to edit notes, then use the Velocity lane or
|
||||||
slider for dynamics. Each non-bus track header has an instrument dropdown offering
|
selected-note slider for dynamics. Each non-bus track header has an instrument
|
||||||
built-in sine, project instruments and explicit plugin loading. See WORKSPACE.md.
|
dropdown offering built-in sine, project instruments and explicit plugin
|
||||||
|
loading. See WORKSPACE.md.
|
||||||
|
|
||||||
Additive clip selection, atomic group commands, phrase clipboard and repeat,
|
Additive clip selection, atomic group commands, phrase clipboard and repeat,
|
||||||
alignment/slip tools, MIDI swing/gate/legato/scale/velocity transforms, batch
|
alignment/slip tools, MIDI swing/gate/legato/scale/velocity transforms, batch
|
||||||
audio fades and static mixer A/B recall are also available. See
|
audio fades and static mixer A/B recall are also available. See
|
||||||
[MODERN_EDITING.md](MODERN_EDITING.md) for commands, scope and limitations.
|
[MODERN_EDITING.md](MODERN_EDITING.md) for commands, scope and limitations.
|
||||||
|
|
||||||
See [arrangement and composition workflows](COMPOSITION_WORKFLOWS.md) for markers, MIDI composition, normalization and portable media collection.
|
See [arrangement and composition workflows](COMPOSITION_WORKFLOWS.md) for
|
||||||
|
markers, MIDI composition, normalization and portable media collection.
|
||||||
|
|
||||||
Select an audio clip and open View / Sample editor (or double-click it) to inspect
|
Select an audio clip and open View / Sample editor (or double-click it) to
|
||||||
source samples, choose native frame ranges, trim the clip or export a new WAV.
|
inspect source samples, choose native frame ranges, trim the clip or export a
|
||||||
Processing and one-level local undo remain in the editor until Save full copy and
|
new WAV. Processing and one-level local undo remain in the editor until Save
|
||||||
relink. See [AUDIO_EDITOR.md](AUDIO_EDITOR.md) for all sample tools, transient
|
full copy and relink. See [AUDIO_EDITOR.md](AUDIO_EDITOR.md) for all sample
|
||||||
slicing, musical-tick rounding and source preservation limits.
|
tools, transient slicing, musical-tick rounding and source preservation limits.
|
||||||
|
|
|
||||||
139
docs/WORKFLOW.md
139
docs/WORKFLOW.md
|
|
@ -1,14 +1,17 @@
|
||||||
# Make and reopen a small project
|
# Make and Reopen A Small Project
|
||||||
|
|
||||||
The default workspace is Sequencer. New and Open return to this workspace;
|
The default workspace is Sequencer. New and Open return to this workspace; Mixer
|
||||||
Mixer and Modular Graph remain available with Ctrl+2 and Ctrl+3. Start with an
|
and Modular Graph remain available with Ctrl+2 and Ctrl+3. Start with an empty
|
||||||
empty project at 120 BPM, 4/4. Clips default to one bar and piano-roll notes use
|
project at 120 BPM, 4/4. Clips default to one bar and piano-roll notes use
|
||||||
velocity 100; no notes or test oscillators are inserted automatically.
|
velocity 100; no notes or test oscillators are inserted automatically.
|
||||||
|
|
||||||
## Create music
|
---
|
||||||
|
|
||||||
1. Start your existing JACK-compatible server, launch `xtc`, and check that audio
|
## Create Music
|
||||||
says ready/stopped. If disconnected, start the server and use Reconnect/F6.
|
|
||||||
|
1. Start your existing JACK-compatible server, launch `xtc`, and check that
|
||||||
|
audio says ready/stopped. If disconnected, start the server and use
|
||||||
|
Reconnect/F6.
|
||||||
2. Click Add track, then Add MIDI clip. Click Piano roll (Ctrl+4) and click the
|
2. Click Add track, then Add MIDI clip. Click Piano roll (Ctrl+4) and click the
|
||||||
grid to draw notes. Drag notes to move them or their right edges to resize.
|
grid to draw notes. Drag notes to move them or their right edges to resize.
|
||||||
Close the piano-roll window to return to the arrangement.
|
Close the piano-roll window to return to the arrangement.
|
||||||
|
|
@ -21,14 +24,16 @@ velocity 100; no notes or test oscillators are inserted automatically.
|
||||||
5. MIDI creation supplies an instrument-to-output route, and audio import
|
5. MIDI creation supplies an instrument-to-output route, and audio import
|
||||||
supplies an audio-to-output route for a new project. No graph editing or
|
supplies an audio-to-output route for a new project. No graph editing or
|
||||||
project-file editing is required. Ctrl+3 shows these routes if you want to
|
project-file editing is required. Ctrl+3 shows these routes if you want to
|
||||||
inspect or change them. Existing custom routes are respected; see MIDI.md
|
inspect or change them. Existing custom routes are respected; see MIDI.md and
|
||||||
and AUDIO_FILES.md for routing limits.
|
AUDIO_FILES.md for routing limits.
|
||||||
6. In your existing JACK routing tool, connect xtc's `output` and `output_right`
|
6. In your existing JACK routing tool, connect xtc's `output` and `output_right`
|
||||||
ports to left/right playback inputs. Press Play/F5. Mixer/Ctrl+2 shows output
|
ports to left/right playback inputs. Press Play/F5. Mixer/Ctrl+2 shows output
|
||||||
meters and track gain/pan/mute/solo. If meters move but nothing is audible,
|
meters and track gain/pan/mute/solo. If meters move but nothing is audible,
|
||||||
check external playback routing and device levels. xtc does not connect
|
check external playback routing and device levels. xtc does not connect
|
||||||
physical ports automatically or start/configure the server.
|
physical ports automatically or start/configure the server.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Transport
|
## Transport
|
||||||
|
|
||||||
| Command | Behavior |
|
| Command | Behavior |
|
||||||
|
|
@ -41,27 +46,30 @@ velocity 100; no notes or test oscillators are inserted automatically.
|
||||||
| Click timeline ruler | Seek on the sixteenth-note grid while stopped; during playback the seek is refused. |
|
| Click timeline ruler | Seek on the sixteenth-note grid while stopped; during playback the seek is refused. |
|
||||||
| New / Open / Reconnect | Stop and reset the position. New/Open show Sequencer; Reconnect leaves the document intact. |
|
| New / Open / Reconnect | Stop and reset the position. New/Open show Sequencer; Reconnect leaves the document intact. |
|
||||||
|
|
||||||
Pause/Stop completion is asynchronous: the GUI briefly shows “stopping”. Recording
|
Pause/Stop completion is asynchronous: the GUI briefly shows “stopping”.
|
||||||
Stop and Home retain immediate deactivation. See [AUDIO_QUALITY.md](AUDIO_QUALITY.md)
|
Recording Stop and Home retain immediate deactivation. See
|
||||||
for the 5 ms fade policy and timing bounds.
|
[AUDIO_QUALITY.md](AUDIO_QUALITY.md) for the 5 ms fade policy and timing bounds.
|
||||||
|
|
||||||
The backend sample count drives the playhead; its display refreshes every 100 ms.
|
The backend sample count drives the playhead; its display refreshes every 100
|
||||||
Pause/Stop retain the exact sample position even though the ruler displays ticks.
|
ms. Pause/Stop retain the exact sample position even though the ruler displays
|
||||||
Arrangement, note and mixer edits stop playback; graph edits can be adopted live.
|
ticks. Arrangement, note and mixer edits stop playback; graph edits can be
|
||||||
A failed stop leaves playback running and the controls reflect that. A failed
|
adopted live. A failed stop leaves playback running and the controls reflect
|
||||||
return-to-start seek does not set the cursor to zero. If candidate project
|
that. A failed return-to-start seek does not set the cursor to zero. If
|
||||||
preparation fails after stopping/seeking, the old document stays loaded and the
|
candidate project preparation fails after stopping/seeking, the old document
|
||||||
GUI refreshes to its actual stopped position (which may be zero). A parse failure
|
stays loaded and the GUI refreshes to its actual stopped position (which may be
|
||||||
occurs before installation and leaves playback alone.
|
zero). A parse failure occurs before installation and leaves playback alone.
|
||||||
|
|
||||||
## Save, close and continue
|
---
|
||||||
|
|
||||||
|
## Save, Close and Continue
|
||||||
|
|
||||||
Use File/Save (Ctrl+S), choose a `.xtc` path and retain external WAV files. The
|
Use File/Save (Ctrl+S), choose a `.xtc` path and retain external WAV files. The
|
||||||
unsaved title marker clears on success. File/Save As confirms overwrites.
|
unsaved title marker clears on success. File/Save As confirms overwrites. Close
|
||||||
Close the window, launch xtc again and use File/Open (Ctrl+O), or run
|
the window, launch xtc again and use File/Open (Ctrl+O), or run
|
||||||
`xtc /path/to/song.xtc`. The arrangement, stable IDs, routing, notes, mixing and
|
`xtc /path/to/song.xtc`. The arrangement, stable IDs, routing, notes, mixing and
|
||||||
automation are restored; the transport starts stopped at zero. Continue drawing,
|
automation are restored; the transport starts stopped at zero. Continue drawing,
|
||||||
importing or moving clips, use Ctrl+Z/Ctrl+Shift+Z for undo/redo, and save again.
|
importing or moving clips, use Ctrl+Z/Ctrl+Shift+Z for undo/redo, and save
|
||||||
|
again.
|
||||||
|
|
||||||
New/Open/Quit ask before discarding unsaved edits. They are refused while
|
New/Open/Quit ask before discarding unsaved edits. They are refused while
|
||||||
recording: use Stop to finalize the take, then save. Missing media stays silent
|
recording: use Stop to finalize the take, then save. Missing media stays silent
|
||||||
|
|
@ -70,7 +78,9 @@ selected audio. Failed file operations retain the document and show an error;
|
||||||
check the path, format and permissions. Server loss or rate changes require
|
check the path, format and permissions. Server loss or rate changes require
|
||||||
Reconnect; this resets position, so seek again before resuming.
|
Reconnect; this resets position, so seek again before resuming.
|
||||||
|
|
||||||
## Repeatable acceptance test
|
---
|
||||||
|
|
||||||
|
## Repeatable Acceptance Test
|
||||||
|
|
||||||
With installed FLTK/JACK development files, Xvfb and an already running
|
With installed FLTK/JACK development files, Xvfb and an already running
|
||||||
JACK-compatible server:
|
JACK-compatible server:
|
||||||
|
|
@ -80,14 +90,15 @@ make all test gui test-gui test-workflow test-gui-jack test-jack-midi
|
||||||
```
|
```
|
||||||
|
|
||||||
`test-workflow` drives real GUI commands and timeline gestures under Xvfb. It
|
`test-workflow` drives real GUI commands and timeline gestures under Xvfb. It
|
||||||
creates a track, draws two notes, arranges the MIDI clip two beats later, imports
|
creates a track, draws two notes, arranges the MIDI clip two beats later,
|
||||||
a generated WAV and verifies both automatic source routes. It saves and closes,
|
imports a generated WAV and verifies both automatic source routes. It saves and
|
||||||
destroys the first window, reopens in a fresh window and compares the complete
|
closes, destroys the first window, reopens in a fresh window and compares the
|
||||||
stereo offline render exactly (including silence, imported audio and notes).
|
complete stereo offline render exactly (including silence, imported audio and
|
||||||
It checks stable clip IDs/positions and graph counts, seeks through the ruler,
|
notes). It checks stable clip IDs/positions and graph counts, seeks through the
|
||||||
plays on the real backend, observes nonzero stereo output meters and advancing
|
ruler, plays on the real backend, observes nonzero stereo output meters and
|
||||||
playhead, pauses/resumes, stops, returns to start, edits/undoes/redoes, saves and
|
advancing playhead, pauses/resumes, stops, returns to start,
|
||||||
reopens again. It uses temporary files only and cleans them on success.
|
edits/undoes/redoes, saves and reopens again. It uses temporary files only and
|
||||||
|
cleans them on success.
|
||||||
|
|
||||||
`test-gui` injects stop/seek/prepare failures to verify controls, position and
|
`test-gui` injects stop/seek/prepare failures to verify controls, position and
|
||||||
retained document state, plus recording guards. `test-gui-jack` exercises live
|
retained document state, plus recording guards. `test-gui-jack` exercises live
|
||||||
|
|
@ -98,34 +109,40 @@ JACK support. Core tests use no GUI leak suppression.
|
||||||
|
|
||||||
These checks cover a minimal composition workflow, not physical listening or
|
These checks cover a minimal composition workflow, not physical listening or
|
||||||
endurance qualification. No new dependency, project-format change, plugin host,
|
endurance qualification. No new dependency, project-format change, plugin host,
|
||||||
MIDI capture, tempo editor, loop playback, device-routing GUI, or persisted editor
|
MIDI capture, tempo editor, loop playback, device-routing GUI, or persisted
|
||||||
layout was introduced. See GUI.md, MIDI.md, MIXER.md and LINUX.md for details.
|
editor layout was introduced. See GUI.md, MIDI.md, MIXER.md and LINUX.md for
|
||||||
|
details.
|
||||||
|
|
||||||
## Editing workflow
|
---
|
||||||
|
|
||||||
Select a clip and press Ctrl+D (or Edit/Duplicate clip) to duplicate it immediately
|
## Editing Workflow
|
||||||
after its end. Complete source notes, trim offsets and media references are
|
|
||||||
retained with fresh stable IDs. No audio file is copied or overwritten. F2 or
|
|
||||||
Edit/Rename clip or track names the selection. Clip labels show both kind and
|
|
||||||
user name. Alt+Up/Down with timeline focus reorders its selected track without
|
|
||||||
changing IDs, clip membership or routing. Right-click a timeline clip/track for
|
|
||||||
Duplicate, Rename and Delete. Invalid/capacity edits retain the existing model.
|
|
||||||
|
|
||||||
View/Snap selects 1, 120, 240 (default), 480 or 960 ticks. It affects ruler seeks,
|
Select a clip and press Ctrl+D (or Edit/Duplicate clip) to duplicate it
|
||||||
clip moves and trims; 1 tick is the finest grid. Existing +/- zoom and scrollbars
|
immediately after its end. Complete source notes, trim offsets and media
|
||||||
retain their behavior. Piano roll has its own configurable grid (see MIDI.md); mixer lanes retain their 240-tick
|
references are retained with fresh stable IDs. No audio file is copied or
|
||||||
grid. Grid and zoom are application preferences saved on Apply/clean exit;
|
overwritten. F2 or Edit/Rename clip or track names the selection. Clip labels
|
||||||
selection is session state. These controls are not undoable music edits.
|
show both kind and user name. Alt+Up/Down with timeline focus reorders its
|
||||||
Escape cancels a drag; Delete affects the focused editor; text fields keep their
|
selected track without changing IDs, clip membership or routing. Right-click a
|
||||||
own editing keys. Commands are named in menus/tooltips and timeline focus accepts
|
timeline clip/track for Duplicate, Rename and Delete. Invalid/capacity edits
|
||||||
keyboard editing; screen-reader and broad accessibility qualification are pending.
|
retain the existing model.
|
||||||
|
|
||||||
|
View/Snap selects 1, 120, 240 (default), 480 or 960 ticks. It affects ruler
|
||||||
|
seeks, clip moves and trims; 1 tick is the finest grid. Existing +/- zoom and
|
||||||
|
scrollbars retain their behavior. Piano roll has its own configurable grid (see
|
||||||
|
MIDI.md); mixer lanes retain their 240-tick grid. Grid and zoom are application
|
||||||
|
preferences saved on Apply/clean exit; selection is session state. These
|
||||||
|
controls are not undoable music edits. Escape cancels a drag; Delete affects the
|
||||||
|
focused editor; text fields keep their own editing keys. Commands are named in
|
||||||
|
menus/tooltips and timeline focus accepts keyboard editing; screen-reader and
|
||||||
|
broad accessibility qualification are pending.
|
||||||
|
|
||||||
Create/delete/move/trim/duplicate, names/order, graph connects/deletes, notes,
|
Create/delete/move/trim/duplicate, names/order, graph connects/deletes, notes,
|
||||||
mixer/automation and plugin edits use the 32-edit snapshot history. Ctrl+Z undoes;
|
mixer/automation and plugin edits use the 32-edit snapshot history. Ctrl+Z
|
||||||
Ctrl+Shift+Z or Ctrl+Y redoes. Backend preparation precedes accepting an undo/redo
|
undoes; Ctrl+Shift+Z or Ctrl+Y redoes. Backend preparation precedes accepting an
|
||||||
snapshot; failure retains its cursor/document. Model edits stop playback before
|
undo/redo snapshot; failure retains its cursor/document. Model edits stop
|
||||||
mutation; compilation/file work occurs on the control thread and may pause the
|
playback before mutation; compilation/file work occurs on the control thread and
|
||||||
GUI, never block the audio callback. This is not a background-loading editor.
|
may pause the GUI, never block the audio callback. This is not a
|
||||||
|
background-loading editor.
|
||||||
|
|
||||||
A successful recorded take adds a reference as one undoable edit. Undo/removing
|
A successful recorded take adds a reference as one undoable edit. Undo/removing
|
||||||
its region never deletes the WAV; recording failures retain their recovery path.
|
its region never deletes the WAV; recording failures retain their recovery path.
|
||||||
|
|
@ -133,14 +150,16 @@ There is no destructive media-delete operation. New/Open reset history after
|
||||||
unsaved-change handling. The capacity limit and allocation-error reporting in
|
unsaved-change handling. The capacity limit and allocation-error reporting in
|
||||||
MIXER.md still apply. Tests: `make test-editing test-gui-plugins test-workflow`.
|
MIXER.md still apply. Tests: `make test-editing test-gui-plugins test-workflow`.
|
||||||
|
|
||||||
## Editing audit
|
---
|
||||||
|
|
||||||
|
## Editing Audit
|
||||||
|
|
||||||
See [EDITING.md](EDITING.md) for the operation-by-operation undo matrix, command
|
See [EDITING.md](EDITING.md) for the operation-by-operation undo matrix, command
|
||||||
ownership, allocation-failure boundary, external-media behavior and manual
|
ownership, allocation-failure boundary, external-media behavior and manual
|
||||||
context-menu/focus procedure. History now reserves storage before edits and
|
context-menu/focus procedure. History now reserves storage before edits and
|
||||||
publication, preserving redo when commands fail. Recording start has no empty
|
publication, preserving redo when commands fail. Recording start has no empty
|
||||||
undo entry; a completed take is one step and undo never deletes its WAV.
|
undo entry; a completed take is one step and undo never deletes its WAV. Undo
|
||||||
Undo preserves surviving selections and an open piano roll; the piano window
|
preserves surviving selections and an open piano roll; the piano window also
|
||||||
also offers Edit/Undo/Redo. Graph context menus select under the pointer and
|
offers Edit/Undo/Redo. Graph context menus select under the pointer and
|
||||||
piano-roll right-click now opens a menu instead of immediately deleting a note.
|
piano-roll right-click now opens a menu instead of immediately deleting a note.
|
||||||
Load/import/plugin work paints busy feedback while remaining synchronous.
|
Load/import/plugin work paints busy feedback while remaining synchronous.
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,24 @@
|
||||||
# Flat DAW workspace
|
# Flat DAW Workspace
|
||||||
|
|
||||||
The workspace presents the existing xtc editors in a consistent flat layout. It uses
|
The workspace presents the existing xtc editors in a consistent flat layout. It
|
||||||
FLTK vector drawing and system fonts: no images, shadows, bevels, 3D rendering,
|
uses FLTK vector drawing and system fonts: no images, shadows, bevels, 3D
|
||||||
external theme packages or new runtime dependencies.
|
rendering, external theme packages or new runtime dependencies.
|
||||||
|
|
||||||
The default window is 1280 × 800; the supported minimum is 1220 × 720. The main
|
The default window is 1280 × 800; the supported minimum is 1220 × 720. The main
|
||||||
editor grows with the window. Use the scrollbars for longer arrangements and
|
editor grows with the window. Use the scrollbars for longer arrangements and
|
||||||
larger track counts. The sidebar stays available across Sequencer, Mixer and
|
larger track counts. The sidebar stays available across Sequencer, Mixer and
|
||||||
Modular Graph views. Ctrl+1/2/3 switches those views; Ctrl+4 opens the piano roll.
|
Modular Graph views. Ctrl+1/2/3 switches those views; Ctrl+4 opens the piano
|
||||||
|
roll.
|
||||||
|
|
||||||
## Create and arrange
|
---
|
||||||
|
|
||||||
- **New MIDI track** (Ctrl+Shift+M) creates a named track and a one-bar MIDI clip
|
## Create and Arrange
|
||||||
at the cursor. The new clip and mixer track are selected together. **Edit MIDI
|
|
||||||
notes** opens its piano roll. Creation is one undo step.
|
- **New MIDI track** (Ctrl+Shift+M) creates a named track and a one-bar MIDI
|
||||||
- **New audio track** (Ctrl+Shift+A) creates an empty named track. **Import WAV**
|
clip at the cursor. The new clip and mixer track are selected together. **Edit
|
||||||
imports into the selected track, or creates one when none is selected.
|
MIDI notes** opens its piano roll. Creation is one undo step.
|
||||||
|
- **New audio track** (Ctrl+Shift+A) creates an empty named track. **Import
|
||||||
|
WAV** imports into the selected track, or creates one when none is selected.
|
||||||
- **Load instrument plugin** opens the instrument browser for the selected
|
- **Load instrument plugin** opens the instrument browser for the selected
|
||||||
sequencer track. Unassigned MIDI tracks retain the built-in sine instrument.
|
sequencer track. Unassigned MIDI tracks retain the built-in sine instrument.
|
||||||
- Existing Add track/region/MIDI clip, duplication, trimming, split, rename and
|
- Existing Add track/region/MIDI clip, duplication, trimming, split, rename and
|
||||||
|
|
@ -36,16 +39,18 @@ time visible. The transport display reads **bar : beat : tick** (4/4, 960 ticks
|
||||||
per beat); BPM follows the project tempo. These displays are read-only.
|
per beat); BPM follows the project tempo. These displays are read-only.
|
||||||
|
|
||||||
The sidebar inspector follows the sequencer selection, showing track name,
|
The sidebar inspector follows the sequencer selection, showing track name,
|
||||||
gain/pan, mute/solo and assigned instrument. Use the Mixer for controls, routing,
|
gain/pan, mute/solo and assigned instrument. Use the Mixer for controls,
|
||||||
meters and automation; the sidebar is an overview, not another mixer. Status and
|
routing, meters and automation; the sidebar is an overview, not another mixer.
|
||||||
errors remain visible below the editor. Existing engine connection, transport,
|
Status and errors remain visible below the editor. Existing engine connection,
|
||||||
recording and keyboard safety behavior is retained.
|
transport, recording and keyboard safety behavior is retained.
|
||||||
|
|
||||||
## Example and verification
|
---
|
||||||
|
|
||||||
|
## Example and Verification
|
||||||
|
|
||||||
Open `examples/projects/modern-session.xtc` for an original four-track, four-bar
|
Open `examples/projects/modern-session.xtc` for an original four-track, four-bar
|
||||||
MIDI arrangement with 16 clips and 128 notes. It needs no media or plugins. It is
|
MIDI arrangement with 16 clips and 128 notes. It needs no media or plugins. It
|
||||||
also installed with the project examples. Connect JACK playback ports before
|
is also installed with the project examples. Connect JACK playback ports before
|
||||||
listening. Work on a copy if the installed examples are read-only.
|
listening. Work on a copy if the installed examples are read-only.
|
||||||
|
|
||||||
GUI tests exercise sidebar creation, selected clip/editor access, undo/redo,
|
GUI tests exercise sidebar creation, selected clip/editor access, undo/redo,
|
||||||
|
|
@ -56,22 +61,24 @@ add commercial-DAW features: detachable/resizable docks, mixer channel strips,
|
||||||
automatic plugin scanning, custom plugin editors and new audio/MIDI features
|
automatic plugin scanning, custom plugin editors and new audio/MIDI features
|
||||||
remain outside this workspace. Existing plugin and engine limits still apply.
|
remain outside this workspace. Existing plugin and engine limits still apply.
|
||||||
|
|
||||||
## Editing controls
|
---
|
||||||
|
|
||||||
The **Snap** dropdown above the sequencer selects Off, 1/32, 1/16 triplet,
|
## Editing Controls
|
||||||
1/16, 1/8 triplet, 1/8, 1/4, 1/2 or one bar. Existing View/Snap commands update
|
|
||||||
the same preference. Bar lines are strongest, beats medium, subdivisions subtle.
|
The **Snap** dropdown above the sequencer selects Off, 1/32, 1/16 triplet, 1/16,
|
||||||
At low zoom closely spaced lines are coarsened to at least six pixels; snapping
|
1/8 triplet, 1/8, 1/4, 1/2 or one bar. Existing View/Snap commands update the
|
||||||
|
same preference. Bar lines are strongest, beats medium, subdivisions subtle. At
|
||||||
|
low zoom closely spaced lines are coarsened to at least six pixels; snapping
|
||||||
still uses the selected division. Clip moves and trim boundaries snap to the
|
still uses the selected division. Clip moves and trim boundaries snap to the
|
||||||
nearest absolute grid position (halfway rounds forward), including clips that
|
nearest absolute grid position (halfway rounds forward), including clips that
|
||||||
start off the grid. Off removes musical quantization; pointer resolution and
|
start off the grid. Off removes musical quantization; pointer resolution and
|
||||||
integer model ticks still apply. Invalid trims retain the original clip.
|
integer model ticks still apply. Invalid trims retain the original clip. Snap is
|
||||||
Snap is a UI preference, not a project edit or a saved project setting.
|
a UI preference, not a project edit or a saved project setting.
|
||||||
|
|
||||||
Double-click a MIDI clip with the left mouse button to open its piano roll.
|
Double-click a MIDI clip with the left mouse button to open its piano roll. The
|
||||||
The clip is selected and the click does not move/trim it. Audio/silent clips
|
clip is selected and the click does not move/trim it. Audio/silent clips retain
|
||||||
retain their existing selection/drag behavior. The piano roll also has a Snap
|
their existing selection/drag behavior. The piano roll also has a Snap dropdown
|
||||||
dropdown for its existing note grid; sequencer and piano snap remain independent.
|
for its existing note grid; sequencer and piano snap remain independent.
|
||||||
|
|
||||||
The piano roll has a fixed **Velocity** lane beneath the keys and a **Note
|
The piano roll has a fixed **Velocity** lane beneath the keys and a **Note
|
||||||
velocity** slider. Select a note, then drag its bar vertically or release the
|
velocity** slider. Select a note, then drag its bar vertically or release the
|
||||||
|
|
@ -82,25 +89,29 @@ the desired note in the keys first; its highlighted velocity bar and slider
|
||||||
remain individually editable. Horizontal scrolling aligns the lane with note
|
remain individually editable. Horizontal scrolling aligns the lane with note
|
||||||
starts; vertical scrolling moves the keys while the lane stays available.
|
starts; vertical scrolling moves the keys while the lane stays available.
|
||||||
Filters apply to lane visibility and selection. Values save with existing note
|
Filters apply to lane visibility and selection. Values save with existing note
|
||||||
metadata and affect built-in synthesis; plugin patches determine velocity response.
|
metadata and affect built-in synthesis; plugin patches determine velocity
|
||||||
This is MIDI velocity, not a per-note audio gain or loudness meter.
|
response. This is MIDI velocity, not a per-note audio gain or loudness meter.
|
||||||
|
|
||||||
Every ordinary track header has an instrument dropdown. Choose **Built-in sine**,
|
Every ordinary track header has an instrument dropdown. Choose **Built-in
|
||||||
an instrument already assigned elsewhere in the project, or **Load plugin...**
|
sine**, an instrument already assigned elsewhere in the project, or **Load
|
||||||
for a trusted CLAP/VST2/VST3 binary. Entries show the format and plugin label.
|
plugin...** for a trusted CLAP/VST2/VST3 binary. Entries show the format and
|
||||||
Each assignment creates an independent track instance, selects that track for
|
plugin label. Each assignment creates an independent track instance, selects
|
||||||
live MIDI and remains undoable; clear/reorder/reopen use stable track IDs. Bus
|
that track for live MIDI and remains undoable; clear/reorder/reopen use stable
|
||||||
tracks show their bus label instead. Cancel or failed preparation restores the
|
track IDs. Bus tracks show their bus label instead. Cancel or failed preparation
|
||||||
model's selection in the dropdown. The list is project-local, not a scanner or
|
restores the model's selection in the dropdown. The list is project-local, not a
|
||||||
installed-plugin database. Existing mono/default-configuration host limits apply.
|
scanner or installed-plugin database. Existing mono/default-configuration host
|
||||||
Instrument changes stop/reprepare playback and are refused while recording.
|
limits apply. Instrument changes stop/reprepare playback and are refused while
|
||||||
|
recording.
|
||||||
|
|
||||||
Verification includes off-grid move/trim, snap Off, dropdown labels, double-click,
|
Verification includes off-grid move/trim, snap Off, dropdown labels,
|
||||||
coincident notes, per-note slider/lane edits, invalid velocities, undo/reload and
|
double-click, coincident notes, per-note slider/lane edits, invalid velocities,
|
||||||
instrument reuse/clear/reorder for all three fixture formats. Manual checks use
|
undo/reload and instrument reuse/clear/reorder for all three fixture formats.
|
||||||
the original modern-session example and the flat sequencer/piano windows.
|
Manual checks use the original modern-session example and the flat
|
||||||
|
sequencer/piano windows.
|
||||||
|
|
||||||
## Studio mixer
|
---
|
||||||
|
|
||||||
|
## Studio Mixer
|
||||||
|
|
||||||
The Mixer tab now presents all tracks and buses as channel strips with vertical
|
The Mixer tab now presents all tracks and buses as channel strips with vertical
|
||||||
dB faders, flat pan knobs, mute/solo, output routing and stereo meters. Scroll
|
dB faders, flat pan knobs, mute/solo, output routing and stereo meters. Scroll
|
||||||
|
|
@ -109,63 +120,68 @@ Select a channel name to edit its gain/pan automation below the bank. Existing
|
||||||
undo, keyboard controls and project persistence remain available. See
|
undo, keyboard controls and project persistence remain available. See
|
||||||
[MIXER.md](MIXER.md) for fader units, metering, automation and limits.
|
[MIXER.md](MIXER.md) for fader units, metering, automation and limits.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Direct editing and navigation
|
## Direct Editing and Navigation
|
||||||
|
|
||||||
**Commands** (Ctrl+P) searches active menu actions by case-insensitive substring.
|
**Commands** (Ctrl+P) searches active menu actions by case-insensitive
|
||||||
Type part of an action path such as `mixer`, `import` or `preferences`, use
|
substring. Type part of an action path such as `mixer`, `import` or
|
||||||
Up/Down to select, then Enter or **Run command**. Double-click also runs an
|
`preferences`, use Up/Down to select, then Enter or **Run command**.
|
||||||
entry. Escape or Cancel leaves the project unchanged. The palette closes before
|
Double-click also runs an entry. Escape or Cancel leaves the project unchanged.
|
||||||
executing the existing menu callback; context and recording guards still apply.
|
The palette closes before executing the existing menu callback; context and
|
||||||
|
recording guards still apply.
|
||||||
|
|
||||||
The transport **BPM** field edits project tempo from 20 to 300 BPM, stored in
|
The transport **BPM** field edits project tempo from 20 to 300 BPM, stored in
|
||||||
milli-BPM. Enter or release commits one undoable change. It stops and rewinds
|
milli-BPM. Enter or release commits one undoable change. It stops and rewinds
|
||||||
transport and prepares the project, including converting loop ticks to samples
|
transport and prepares the project, including converting loop ticks to samples
|
||||||
at the new tempo. Failed validation/preparation retains the previous project;
|
at the new tempo. Failed validation/preparation retains the previous project;
|
||||||
the field returns to its actual value. Existing track/clip and piano-roll
|
the field returns to its actual value. Existing track/clip and piano-roll
|
||||||
selection survives. This is project tempo, separate from Preferences' new-project
|
selection survives. This is project tempo, separate from Preferences'
|
||||||
default. Tempo automation is not added.
|
new-project default. Tempo automation is not added.
|
||||||
|
|
||||||
The **Track inspector** now edits the selected track's linear Gain (0..4), Pan
|
The **Track inspector** now edits the selected track's linear Gain (0..4), Pan
|
||||||
(-1..1), Mute and Solo. In Mixer it follows the selected channel; in Sequencer
|
(-1..1), Mute and Solo. In Mixer it follows the selected channel; in Sequencer
|
||||||
and Graph it follows arrangement selection. Controls synchronize with model
|
and Graph it follows arrangement selection. Controls synchronize with model
|
||||||
changes and undo, while typing is protected from the display refresh timer.
|
changes and undo, while typing is protected from the display refresh timer. Only
|
||||||
Only the edited field is committed. Unchanged values create no history entry.
|
the edited field is committed. Unchanged values create no history entry. These
|
||||||
These are static values; automation still overrides gain and pan. Recording
|
are static values; automation still overrides gain and pan. Recording prevents
|
||||||
prevents edits. Track instruments and routing retain their existing selectors.
|
edits. Track instruments and routing retain their existing selectors.
|
||||||
|
|
||||||
The session row shows track/bus count, clip count and the arrangement's bar span.
|
The session row shows track/bus count, clip count and the arrangement's bar
|
||||||
**Fit song** (Ctrl+0) returns to the start and selects the largest supported zoom
|
span. **Fit song** (Ctrl+0) returns to the start and selects the largest
|
||||||
that fits the arrangement plus a beat of padding. Supported zoom remains
|
supported zoom that fits the arrangement plus a beat of padding. Supported zoom
|
||||||
24, 48, 96, 192 or 384 pixels per beat; a sufficiently long arrangement requires
|
remains 24, 48, 96, 192 or 384 pixels per beat; a sufficiently long arrangement
|
||||||
scrolling even at the minimum. Empty projects fit one bar.
|
requires scrolling even at the minimum. Empty projects fit one bar.
|
||||||
|
|
||||||
**Follow playhead** pages the arrangement horizontally during playback, retaining
|
**Follow playhead** pages the arrangement horizontally during playback,
|
||||||
vertical scroll. It operates only in Sequencer and waits while a mouse drag is
|
retaining vertical scroll. It operates only in Sequencer and waits while a mouse
|
||||||
active. It is off by default; Preferences / Apply persists it in
|
drag is active. It is off by default; Preferences / Apply persists it in
|
||||||
`[transport] follow_playhead=0` or `1`. Manual scrolling remains available and
|
`[transport] follow_playhead=0` or `1`. Manual scrolling remains available and
|
||||||
Fit song resets the viewport without editing the project.
|
Fit song resets the viewport without editing the project.
|
||||||
|
|
||||||
Verification covers real FLTK palette filtering, empty searches and cancellation,
|
Verification covers real FLTK palette filtering, empty searches and
|
||||||
tempo callbacks/undo/failed adoption, inspector edits and in-progress numeric
|
cancellation, tempo callbacks/undo/failed adoption, inspector edits and
|
||||||
input, fit and follow navigation, and existing core/GUI/live JACK workflows.
|
in-progress numeric input, fit and follow navigation, and existing core/GUI/live
|
||||||
|
JACK workflows.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Detachable transport and mixer
|
## Detachable Transport and Mixer
|
||||||
|
|
||||||
Use **View → Detach transport** or **View → Detach mixer** to move either panel
|
Use **View → Detach transport** or **View → Detach mixer** to move either panel
|
||||||
into a separate window. Toggle the same menu action, use the floating panel's
|
into a separate window. Toggle the same menu action, use the floating panel's
|
||||||
**Dock** button, or close its window to return it to the main workspace.
|
**Dock** button, or close its window to return it to the main workspace. **View
|
||||||
**View → Dock all panels** restores both. **View → Mixer** (Ctrl+2) also raises
|
→ Dock all panels** restores both. **View → Mixer** (Ctrl+2) also raises the
|
||||||
the floating mixer. The main arrangement expands when the transport is detached.
|
floating mixer. The main arrangement expands when the transport is detached. The
|
||||||
The mixer remains the same live view, with its channel selection, faders, routing
|
mixer remains the same live view, with its channel selection, faders, routing
|
||||||
and meters; the main Mixer tab offers Show and Dock actions while it is floating.
|
and meters; the main Mixer tab offers Show and Dock actions while it is
|
||||||
|
floating.
|
||||||
|
|
||||||
The transport owns the playback buttons, position, **BPM**, **Loop** toggle and
|
The transport owns the playback buttons, position, **BPM**, **Loop** toggle and
|
||||||
**Loop range...** settings in both layouts. Shift-drag on the sequencer ruler
|
**Loop range...** settings in both layouts. Shift-drag on the sequencer ruler
|
||||||
still updates the same loop region. BPM remains an undoable project edit;
|
still updates the same loop region. BPM remains an undoable project edit; loop
|
||||||
loop preferences persist through Preferences / Apply or clean application exit.
|
preferences persist through Preferences / Apply or clean application exit. Space
|
||||||
Space and menu playback shortcuts work from either floating panel, with normal
|
and menu playback shortcuts work from either floating panel, with normal
|
||||||
numeric/text editing protection. Closing the main window closes all panels only
|
numeric/text editing protection. Closing the main window closes all panels only
|
||||||
after the existing unsaved/recording/backend shutdown checks succeed.
|
after the existing unsaved/recording/backend shutdown checks succeed.
|
||||||
|
|
||||||
|
|
@ -174,12 +190,15 @@ The initial layout used session-only positions and a transport minimum width of
|
||||||
described below. The floating mixer resizes down to 600 × 420 and retains
|
described below. The floating mixer resizes down to 600 × 420 and retains
|
||||||
horizontal track scrolling.
|
horizontal track scrolling.
|
||||||
|
|
||||||
Verified with `make BUILD_DIR=build/workspace-detach gui test-gui test-gui-instruments
|
Verified with
|
||||||
test-gui-jack` (one line), plus the GUI suite under AddressSanitizer/UBSan.
|
`make BUILD_DIR=build/workspace-detach gui test-gui test-gui-instruments test-gui-jack`
|
||||||
Tests cover repeated reparenting, close-to-dock, resize, shared BPM/loop state,
|
(one line), plus the GUI suite under AddressSanitizer/UBSan. Tests cover
|
||||||
playback shortcuts, failed shutdown and cleanup.
|
repeated reparenting, close-to-dock, resize, shared BPM/loop state, playback
|
||||||
|
shortcuts, failed shutdown and cleanup.
|
||||||
|
|
||||||
## Saved panel layouts
|
---
|
||||||
|
|
||||||
|
## Saved Panel Layouts
|
||||||
|
|
||||||
Preferences / Apply now saves transport/mixer dock state and window rectangles.
|
Preferences / Apply now saves transport/mixer dock state and window rectangles.
|
||||||
Clean application exit also saves their current positions. Startup restores the
|
Clean application exit also saves their current positions. Startup restores the
|
||||||
|
|
@ -194,41 +213,46 @@ Existing close-to-dock, Dock all and shortcuts retain their shared widget state.
|
||||||
Tests cover narrow control bounds, save/restart, off-screen restoration, invalid
|
Tests cover narrow control bounds, save/restart, off-screen restoration, invalid
|
||||||
geometry, repeated docking/resizing and shared transport state.
|
geometry, repeated docking/resizing and shared transport state.
|
||||||
|
|
||||||
## Editor panels and pinned track headers
|
---
|
||||||
|
|
||||||
|
## Editor Panels and Pinned Track Headers
|
||||||
|
|
||||||
**View → Detach sequencer** and **Detach modular graph** float each complete
|
**View → Detach sequencer** and **Detach modular graph** float each complete
|
||||||
editor, including its toolbar and scroll area. Its main tab offers Show and Dock
|
editor, including its toolbar and scroll area. Its main tab offers Show and Dock
|
||||||
buttons. Closing the floating window docks it; View shortcuts also raise floating
|
buttons. Closing the floating window docks it; View shortcuts also raise
|
||||||
editors. Supported dock locations are their original main-window tabs; arbitrary
|
floating editors. Supported dock locations are their original main-window tabs;
|
||||||
split regions, tab reordering and drag-to-dock are not implemented. Sequencer
|
arbitrary split regions, tab reordering and drag-to-dock are not implemented.
|
||||||
minimum floating size is 1100 × 420; Graph is 1000 × 420.
|
Sequencer minimum floating size is 1100 × 420; Graph is 1000 × 420.
|
||||||
|
|
||||||
The Piano roll now also has a main-window tab. Select a MIDI clip and open it as
|
The Piano roll now also has a main-window tab. Select a MIDI clip and open it as
|
||||||
before. **View → Float piano roll** switches its existing widgets between the tab
|
before. **View → Float piano roll** switches its existing widgets between the
|
||||||
and a floating window; closing the floating window docks it. The tab's Open
|
tab and a floating window; closing the floating window docks it. The tab's Open
|
||||||
selected MIDI clip button opens the current selection. Default floating behavior
|
selected MIDI clip button opens the current selection. Default floating behavior
|
||||||
is retained for older preferences. A missing/invalid MIDI selection is reported.
|
is retained for older preferences. A missing/invalid MIDI selection is reported.
|
||||||
All panels share project/history, preserve editor selections and scroll offsets,
|
All panels share project/history, preserve editor selections and scroll offsets,
|
||||||
and retain playback shortcuts and text-input protection.
|
and retain playback shortcuts and text-input protection.
|
||||||
|
|
||||||
**View → Dock all panels** includes all editors. **Reset workspace layout** docks
|
**View → Dock all panels** includes all editors. **Reset workspace layout**
|
||||||
all panels, restores default floating rectangles and resets header width. Use
|
docks all panels, restores default floating rectangles and resets header width.
|
||||||
Preferences / Apply to persist either result. Editor dock state, floating window
|
Use Preferences / Apply to persist either result. Editor dock state, floating
|
||||||
rectangles and header width use the same validated settings/restore path as the
|
window rectangles and header width use the same validated settings/restore path
|
||||||
transport/mixer. Piano content opens lazily for the selected MIDI clip; startup
|
as the transport/mixer. Piano content opens lazily for the selected MIDI clip;
|
||||||
does not invent a clip or save a project-specific selection in application settings.
|
startup does not invent a clip or save a project-specific selection in
|
||||||
|
application settings.
|
||||||
|
|
||||||
Arrangement track headers and instrument selectors now stay pinned during
|
Arrangement track headers and instrument selectors now stay pinned during
|
||||||
horizontal scrolling. Drag the divider within the header's final five pixels to
|
horizontal scrolling. Drag the divider within the header's final five pixels to
|
||||||
resize from 180 to 360 pixels; Escape cancels the drag. Clip timing coordinates,
|
resize from 180 to 360 pixels; Escape cancels the drag. Clip timing coordinates,
|
||||||
snap and horizontal scrolling use the resized origin. Header layout is a UI
|
snap and horizontal scrolling use the resized origin. Header layout is a UI
|
||||||
preference, not an undoable project edit. Vertical scrolling remains shared with
|
preference, not an undoable project edit. Vertical scrolling remains shared with
|
||||||
the track rows. Clips covered by the pinned header cannot be selected through it.
|
the track rows. Clips covered by the pinned header cannot be selected through
|
||||||
|
it.
|
||||||
|
|
||||||
GUI regressions cover repeated detach/dock and close-to-dock, toolbar ownership,
|
GUI regressions cover repeated detach/dock and close-to-dock, toolbar ownership,
|
||||||
minimum/large resize, shared model/note/clip selection, scrolling, header dragging,
|
minimum/large resize, shared model/note/clip selection, scrolling, header
|
||||||
short-clip hit tests, Apply/restart, reset layout and failed/successful shutdown.
|
dragging, short-clip hit tests, Apply/restart, reset layout and
|
||||||
ASan/UBSan checks retain only the existing system Fontconfig leak suppression.
|
failed/successful shutdown. ASan/UBSan checks retain only the existing system
|
||||||
|
Fontconfig leak suppression.
|
||||||
|
|
||||||
Additive clip selection, atomic group commands, phrase clipboard and repeat,
|
Additive clip selection, atomic group commands, phrase clipboard and repeat,
|
||||||
alignment/slip tools, MIDI swing/gate/legato/scale/velocity transforms, batch
|
alignment/slip tools, MIDI swing/gate/legato/scale/velocity transforms, batch
|
||||||
|
|
@ -237,8 +261,10 @@ audio fades and static mixer A/B recall are also available. See
|
||||||
|
|
||||||
Arrangement markers and sections, ripple edits, complete track duplication, MIDI
|
Arrangement markers and sections, ripple edits, complete track duplication, MIDI
|
||||||
splitting/consolidation and composition tools, peak normalization and portable
|
splitting/consolidation and composition tools, peak normalization and portable
|
||||||
media collection are also available. See [COMPOSITION_WORKFLOWS.md](COMPOSITION_WORKFLOWS.md).
|
media collection are also available. See
|
||||||
|
[COMPOSITION_WORKFLOWS.md](COMPOSITION_WORKFLOWS.md).
|
||||||
|
|
||||||
A modal audio source editor provides frame selection, reversible processing,
|
A modal audio source editor provides frame selection, reversible processing,
|
||||||
selection export, copy adoption and transient slicing. See
|
selection export, copy adoption and transient slicing. See
|
||||||
[AUDIO_EDITOR.md](AUDIO_EDITOR.md) for commands, undo behavior and mono/size limits.
|
[AUDIO_EDITOR.md](AUDIO_EDITOR.md) for commands, undo behavior and mono/size
|
||||||
|
limits.
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,24 @@
|
||||||
# Decision 0001: Modular engine first
|
# Decision 0001: Modular Engine First
|
||||||
|
|
||||||
**Status:** Accepted
|
**Status:** Accepted
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Context
|
## Context
|
||||||
|
|
||||||
The project aims to preserve energyXT's combination of a simple workflow and a
|
The project aims to preserve energyXT's combination of a simple workflow and a
|
||||||
flexible modular routing model.
|
flexible modular routing model.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Decision
|
## Decision
|
||||||
|
|
||||||
Use one unified processing graph for sources, instruments, effects, mixers,
|
Use one unified processing graph for sources, instruments, effects, mixers, and
|
||||||
and outputs. The sequencer is a timeline/event source integrated with that
|
outputs. The sequencer is a timeline/event source integrated with that graph.
|
||||||
graph. The default GUI is simple and sequencer-oriented, while a graph editor
|
The default GUI is simple and sequencer-oriented, while a graph editor exposes
|
||||||
exposes routing when needed.
|
routing when needed.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Consequences
|
## Consequences
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,15 @@
|
||||||
# Decision 0002: C core with FLTK/C++ GUI
|
# Decision 0002: C Core with FLTK/C++ GUI
|
||||||
|
|
||||||
**Status:** Accepted
|
**Status:** Accepted
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Context
|
## Context
|
||||||
|
|
||||||
The project prioritizes a readable, small C implementation while using FLTK
|
The project prioritizes a readable, small C implementation while using FLTK for
|
||||||
for a lightweight desktop GUI.
|
a lightweight desktop GUI.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Decision
|
## Decision
|
||||||
|
|
||||||
|
|
@ -13,6 +17,8 @@ Keep the engine, DSP, project model, graph, and public core API in C (C99
|
||||||
baseline). Use C++ only for FLTK windows and widgets. Communicate through
|
baseline). Use C++ only for FLTK windows and widgets. Communicate through
|
||||||
documented C headers with `extern "C"` guards.
|
documented C headers with `extern "C"` guards.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Consequences
|
## Consequences
|
||||||
|
|
||||||
- No C++ classes, STL containers, exceptions, or FLTK types cross the C API.
|
- No C++ classes, STL containers, exceptions, or FLTK types cross the C API.
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,25 @@
|
||||||
# Decision 0003: Real-time thread rules
|
# Decision 0003: Real-Time Thread Rules
|
||||||
|
|
||||||
**Status:** Accepted
|
**Status:** Accepted
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Context
|
## Context
|
||||||
|
|
||||||
Audio glitches and unsafe graph changes can undermine the whole application.
|
Audio glitches and unsafe graph changes can undermine the whole application.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Decision
|
## Decision
|
||||||
|
|
||||||
The audio callback performs bounded processing using preallocated resources.
|
The audio callback performs bounded processing using preallocated resources. It
|
||||||
It performs no allocation/free, blocking locks, file I/O, logging, GUI calls,
|
performs no allocation/free, blocking locks, file I/O, logging, GUI calls,
|
||||||
plugin loading, or waits. Graphs are prepared outside the callback and active
|
plugin loading, or waits. Graphs are prepared outside the callback and active
|
||||||
graph resources are retired only after safe reclamation.
|
graph resources are retired only after safe reclamation.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Consequences
|
## Consequences
|
||||||
|
|
||||||
Thread ownership and publication mechanisms must be documented and tested.
|
Thread ownership and publication mechanisms must be documented and tested. Any
|
||||||
Any exception to these rules requires explicit evidence and review.
|
exception to these rules requires explicit evidence and review.
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
# Decision 0004: JACK backend and bounded plan handoff
|
# Decision 0004: JACK Backend and Bounded Plan Handoff
|
||||||
|
|
||||||
**Status:** Accepted
|
**Status:** Accepted
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Backend
|
## Backend
|
||||||
|
|
||||||
Use the JACK C client API. The inspected system provides PipeWire's maintained
|
Use the JACK C client API. The inspected system provides PipeWire's maintained
|
||||||
|
|
@ -22,10 +24,12 @@ framework or second driver implementation.
|
||||||
The optional dependency provides actual audio callbacks and port routing.
|
The optional dependency provides actual audio callbacks and port routing.
|
||||||
PipeWire's installed JACK library is MIT licensed (`pipewire-jack/COPYING`).
|
PipeWire's installed JACK library is MIT licensed (`pipewire-jack/COPYING`).
|
||||||
Traditional JACK client libraries use LGPL licensing; review the actual linked
|
Traditional JACK client libraries use LGPL licensing; review the actual linked
|
||||||
implementation, transitive libraries and notices when distributing. Nothing
|
implementation, transitive libraries and notices when distributing. Nothing is
|
||||||
is bundled or installed here. ALSA is still a future MIDI candidate.
|
bundled or installed here. ALSA is still a future MIDI candidate.
|
||||||
|
|
||||||
## C99 and atomic operations
|
---
|
||||||
|
|
||||||
|
## C99 and Atomic Operations
|
||||||
|
|
||||||
Retain C99 and use GCC/Clang `__atomic` builtins. This is a documented compiler
|
Retain C99 and use GCC/Clang `__atomic` builtins. This is a documented compiler
|
||||||
extension, avoiding a language-standard change and keeping the existing core
|
extension, avoiding a language-standard change and keeping the existing core
|
||||||
|
|
@ -34,12 +38,15 @@ unsigned-int atomics to be always lock-free, or returns unsupported before
|
||||||
callbacks are installed. Naturally aligned fields reside in calloc-allocated
|
callbacks are installed. Naturally aligned fields reside in calloc-allocated
|
||||||
objects. There is no mutex or libatomic fallback in the callback path.
|
objects. There is no mutex or libatomic fallback in the callback path.
|
||||||
|
|
||||||
## Ownership and publication
|
---
|
||||||
|
|
||||||
|
## Ownership and Publication
|
||||||
|
|
||||||
One serialized control producer and one audio consumer share two pointer slots:
|
One serialized control producer and one audio consumer share two pointer slots:
|
||||||
|
|
||||||
- `pending`: producer publishes a fully compiled plan with release; consumer
|
- `pending`: producer publishes a fully compiled plan with release; consumer
|
||||||
exchanges it for NULL with acquire/release at the next eligible block boundary.
|
exchanges it for NULL with acquire/release at the next eligible block
|
||||||
|
boundary.
|
||||||
- `retired`: consumer releases its previous active plan into this slot only
|
- `retired`: consumer releases its previous active plan into this slot only
|
||||||
after its final access. Producer exchanges with NULL using acquire/release,
|
after its final access. Producer exchanges with NULL using acquire/release,
|
||||||
then destroys that acknowledged plan on the control thread.
|
then destroys that acknowledged plan on the control thread.
|
||||||
|
|
@ -50,40 +57,47 @@ callers never receive plan pointers through the realtime/backend API.
|
||||||
|
|
||||||
A full pending slot returns capacity without replacing anything. A full retired
|
A full pending slot returns capacity without replacing anything. A full retired
|
||||||
slot defers adoption while the current plan continues processing. The consumer
|
slot defers adoption while the current plan continues processing. The consumer
|
||||||
performs at most one adoption per block and never loops waiting for the producer.
|
performs at most one adoption per block and never loops waiting for the
|
||||||
Producer collection can overlap processing because the retired plan is no
|
producer. Producer collection can overlap processing because the retired plan is
|
||||||
longer reachable from the consumer. Collection clears the slot before freeing;
|
no longer reachable from the consumer. Collection clears the slot before
|
||||||
consumer may then retire another, distinct plan. Publication never immediately
|
freeing; consumer may then retire another, distinct plan. Publication never
|
||||||
frees the previously active plan.
|
immediately frees the previously active plan.
|
||||||
|
|
||||||
Submitting collects any already retired plan, so a producer repeatedly submitting
|
Submitting collects any already retired plan, so a producer repeatedly
|
||||||
also reclaims memory. If it becomes idle, one pending, one active, and one retired
|
submitting also reclaims memory. If it becomes idle, one pending, one active,
|
||||||
plan bound retained resources (at most three plans, each with up to 64 MiB of
|
and one retired plan bound retained resources (at most three plans, each with up
|
||||||
sample buffers). Periodic collect is recommended. Shutdown closes the JACK client
|
to 64 MiB of sample buffers). Periodic collect is recommended. Shutdown closes
|
||||||
and synchronizes its callbacks before destroying any active/pending/retired plan.
|
the JACK client and synchronizes its callbacks before destroying any
|
||||||
Standalone realtime-engine callers must stop and join their consumer themselves.
|
active/pending/retired plan. Standalone realtime-engine callers must stop and
|
||||||
|
join their consumer themselves.
|
||||||
|
|
||||||
## Status, errors and recovery
|
---
|
||||||
|
|
||||||
Unsigned-int status fields use lock-free atomics. Values are individual snapshots,
|
## Status, Errors and Recovery
|
||||||
not one transactional state. Counters wrap naturally; no string formatting,
|
|
||||||
logging, allocation, GUI operation or blocking synchronization occurs in project
|
Unsigned-int status fields use lock-free atomics. Values are individual
|
||||||
callbacks. JACK's shutdown notification only stores a flag and leaves cleanup to
|
snapshots, not one transactional state. Counters wrap naturally; no string
|
||||||
the control thread. Other notifications store the current format and xrun count.
|
formatting, logging, allocation, GUI operation or blocking synchronization
|
||||||
|
occurs in project callbacks. JACK's shutdown notification only stores a flag and
|
||||||
|
leaves cleanup to the control thread. Other notifications store the current
|
||||||
|
format and xrun count.
|
||||||
|
|
||||||
Buffer changes within the configured maximum require no allocation. Larger
|
Buffer changes within the configured maximum require no allocation. Larger
|
||||||
blocks are fully silenced and reported as capacity errors; smaller blocks can
|
blocks are fully silenced and reported as capacity errors; smaller blocks can
|
||||||
resume processing. Sample-rate changes latch a flag and silence processing
|
resume processing. Sample-rate changes latch a flag and silence processing
|
||||||
rather than replaying an oscillator compiled for a different rate. Close/reopen
|
rather than replaying an oscillator compiled for a different rate. Close/reopen
|
||||||
and resubmit after a rate change or server loss. There is no automatic reconnect.
|
and resubmit after a rate change or server loss. There is no automatic
|
||||||
JACK-deactivate pauses the retained plan; restart continues its oscillator phase.
|
reconnect. JACK-deactivate pauses the retained plan; restart continues its
|
||||||
Plan replacement starts the newly compiled oscillator at phase zero, without
|
oscillator phase. Plan replacement starts the newly compiled oscillator at phase
|
||||||
crossfade. Smooth parameter ramps and click-free graph transitions are future work.
|
zero, without crossfade. Smooth parameter ramps and click-free graph transitions
|
||||||
|
are future work.
|
||||||
|
|
||||||
No stereo, recording, MIDI, native PipeWire API, GUI engine controls or hardware
|
No stereo, recording, MIDI, native PipeWire API, GUI engine controls or hardware
|
||||||
configuration dialogs are included.
|
configuration dialogs are included.
|
||||||
|
|
||||||
## Adoption acknowledgement and stopped editing
|
---
|
||||||
|
|
||||||
|
## Adoption Acknowledgement and Stopped Editing
|
||||||
|
|
||||||
The pending pointer has an associated atomic revision. Producer stores the
|
The pending pointer has an associated atomic revision. Producer stores the
|
||||||
revision before release-publishing the pointer. Consumer acquire-loads a
|
revision before release-publishing the pointer. Consumer acquire-loads a
|
||||||
|
|
@ -97,10 +111,10 @@ snapshots, not plan pointers or a multi-field transactional snapshot.
|
||||||
While JACK is stopped, a backend submission builds a separate realtime engine,
|
While JACK is stopped, a backend submission builds a separate realtime engine,
|
||||||
submits/compiles the graph there, and replaces the retained engine only on
|
submits/compiles the graph there, and replaces the retained engine only on
|
||||||
success. Process callbacks cannot run on an inactive client or after successful
|
success. Process callbacks cannot run on an inactive client or after successful
|
||||||
deactivation, and notification callbacks do not access the engine pointer.
|
deactivation, and notification callbacks do not access the engine pointer. The
|
||||||
The control thread can therefore reclaim all old state safely. Counters and
|
control thread can therefore reclaim all old state safely. Counters and
|
||||||
oscillator phases restart for that new engine epoch. The standalone realtime
|
oscillator phases restart for that new engine epoch. The standalone realtime API
|
||||||
API keeps its one-pending-slot contract regardless of external stop state.
|
keeps its one-pending-slot contract regardless of external stop state.
|
||||||
|
|
||||||
The callback still adopts at most one plan and never allocates/frees. Revision
|
The callback still adopts at most one plan and never allocates/frees. Revision
|
||||||
ordering is tested alongside the plan's rendered gain under 2,000 concurrent
|
ordering is tested alongside the plan's rendered gain under 2,000 concurrent
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# 0005: Preloaded WAV clips and control-thread recording consumer
|
# 0005: Preloaded WAV Clips and Control-Thread Recording Consumer
|
||||||
|
|
||||||
Status: accepted.
|
Status: accepted.
|
||||||
|
|
||||||
|
|
@ -11,16 +11,19 @@ codec library needs its own dependency and licensing review.
|
||||||
Compile musical clip ranges and decoded, shared-per-path mono buffers while
|
Compile musical clip ranges and decoded, shared-per-path mono buffers while
|
||||||
stopped. The callback renders the timeline into a preallocated buffer consumed
|
stopped. The callback renders the timeline into a preallocated buffer consumed
|
||||||
by an explicit graph source node, preserving graph routing rather than mixing
|
by an explicit graph source node, preserving graph routing rather than mixing
|
||||||
outside the graph. The old snapshot remains until candidate preparation succeeds.
|
outside the graph. The old snapshot remains until candidate preparation
|
||||||
All track clips currently share one source; per-track routing/mixing is deferred.
|
succeeds. All track clips currently share one source; per-track routing/mixing
|
||||||
|
is deferred.
|
||||||
|
|
||||||
Use a bounded SPSC ring for callback input capture, with release/acquire index
|
Use a bounded SPSC ring for callback input capture, with release/acquire index
|
||||||
publication and a GUI/control-thread consumer. This adds no worker-thread
|
publication and a GUI/control-thread consumer. This adds no worker-thread
|
||||||
dependency; a two-second ring tolerates normal 100 ms polling but exposes
|
dependency; a two-second ring tolerates normal 100 ms polling but exposes
|
||||||
overflow if the GUI or disk stalls. Sticky errors prevent silent time compression.
|
overflow if the GUI or disk stalls. Sticky errors prevent silent time
|
||||||
Finalization requires callback quiescence. Future long-session/background I/O
|
compression. Finalization requires callback quiescence. Future
|
||||||
work can reuse the ring contract with a dedicated consumer.
|
long-session/background I/O work can reuse the ring contract with a dedicated
|
||||||
|
consumer.
|
||||||
|
|
||||||
Store external absolute paths in version 2 metadata and retain version 1 loads.
|
Store external absolute paths in version 2 metadata and retain version 1 loads.
|
||||||
Missing/unreadable assets are reported silence, with explicit relinking; portable
|
Missing/unreadable assets are reported silence, with explicit relinking;
|
||||||
bundles and content-addressed assets are deferred. See AUDIO_FILES.md for limits.
|
portable bundles and content-addressed assets are deferred. See AUDIO_FILES.md
|
||||||
|
for limits.
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
# 0006 — Bounded MIDI notes and internal instrument
|
# 0006 — Bounded MIDI Notes and Internal Instrument
|
||||||
|
|
||||||
Status: accepted.
|
Status: accepted.
|
||||||
|
|
||||||
Use the existing JACK backend for timestamped MIDI input, avoiding another
|
Use the existing JACK backend for timestamped MIDI input, avoiding another
|
||||||
backend/dependency. Store source-relative notes in the C project and v3 format;
|
backend/dependency. Store source-relative notes in the C project and v3 format;
|
||||||
read v1/v2 without MIDI. Prepare sample spans on the control thread and render
|
read v1/v2 without MIDI. Prepare sample spans on the control thread and render a
|
||||||
a small sine instrument into its own graph source buffer. Use a piano roll to
|
small sine instrument into its own graph source buffer. Use a piano roll to meet
|
||||||
meet draw/play/save/reopen acceptance before adding MIDI capture or SMF import.
|
draw/play/save/reopen acceptance before adding MIDI capture or SMF import.
|
||||||
|
|
||||||
Keep explicit bounds: 4096 project notes, 32 overlapping scheduled notes, 32 live
|
Keep explicit bounds: 4096 project notes, 32 overlapping scheduled notes, 32
|
||||||
voices and 256 events/block. Reject scheduled overcapacity at preparation; steal
|
live voices and 256 events/block. Reject scheduled overcapacity at preparation;
|
||||||
oldest live voices. Panic handles event loss, disconnects and callback failures;
|
steal oldest live voices. Panic handles event loss, disconnects and callback
|
||||||
Stop/seek resets live state. Immediate note-off and a fixed sine voice keep this
|
failures; Stop/seek resets live state. Immediate note-off and a fixed sine voice
|
||||||
prototype small, at the cost of possible clicks and no expressive controllers.
|
keep this prototype small, at the cost of possible clicks and no expressive
|
||||||
See ../MIDI.md for ownership, detailed limits and validation.
|
controllers. See ../MIDI.md for ownership, detailed limits and validation.
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# 0007 — Track mixing, paired stereo buses and snapshot history
|
# 0007 — Track Mixing, Paired Stereo Buses and Snapshot History
|
||||||
|
|
||||||
Status: accepted.
|
Status: accepted.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,19 @@
|
||||||
# 0008 — Native processors and source release preparation
|
# 0008 — Native Processors and Source Release Preparation
|
||||||
|
|
||||||
Status: accepted.
|
Status: accepted.
|
||||||
|
|
||||||
Add a versioned copied C descriptor with control-thread prepare/destroy and
|
Add a versioned copied C descriptor with control-thread prepare/destroy and
|
||||||
single-owner realtime reset/process. Prove effects/sources in the existing graph,
|
single-owner realtime reset/process. Prove effects/sources in the existing
|
||||||
with two independent mono instances for stereo, and event instruments rendered
|
graph, with two independent mono instances for stereo, and event instruments
|
||||||
through the public instrument-source buffer boundary. Keep trusted code statically
|
rendered through the public instrument-source buffer boundary. Keep trusted code
|
||||||
linked. Native project serialization and graph event ports need more contracts;
|
statically linked. Native project serialization and graph event ports need more
|
||||||
reject unsupported saves without replacing files. Defer LV2/CLAP/VST3 after a
|
contracts; reject unsupported saves without replacing files. Defer LV2/CLAP/VST3
|
||||||
concrete evaluation rather than linking SDKs speculatively.
|
after a concrete evaluation rather than linking SDKs speculatively.
|
||||||
|
|
||||||
Keep format v4 and test migration plus process-crash/write-failure behavior.
|
Keep format v4 and test migration plus process-crash/write-failure behavior.
|
||||||
Provide deterministic source exports and optimized release builds, staged
|
Provide deterministic source exports and optimized release builds, staged
|
||||||
core/GUI installation, exact uninstall and installed C/C++ consumer tests. Use
|
core/GUI installation, exact uninstall and installed C/C++ consumer tests. Use
|
||||||
Python standard-library tools only for packaging/testing; no application runtime
|
Python standard-library tools only for packaging/testing; no application runtime
|
||||||
dependency or system changes. Document dependency licenses, Linux routing and
|
dependency or system changes. Document dependency licenses, Linux routing and
|
||||||
measured offline performance separately from unverified hardware/endurance.
|
measured offline performance separately from unverified hardware/endurance. See
|
||||||
See NATIVE_API.md, PLUGIN_HOSTING.md, RELEASING.md and RECOVERY.md.
|
NATIVE_API.md, PLUGIN_HOSTING.md, RELEASING.md and RECOVERY.md.
|
||||||
|
|
|
||||||
|
|
@ -1,52 +1,55 @@
|
||||||
# 0009 — Parameter processors and bounded LADSPA hosting
|
# 0009 — Parameter Processors and Bounded LADSPA Hosting
|
||||||
|
|
||||||
Status: accepted (2026-10-27).
|
Status: accepted (2026-10-27).
|
||||||
|
|
||||||
Native ABI 1 remains compatible. ABI 2 adds explicitly parameter-only configuration,
|
Native ABI 1 remains compatible. ABI 2 adds explicitly parameter-only
|
||||||
metadata, validation and sample-offset parameter/MIDI ordering. It is a public C
|
configuration, metadata, validation and sample-offset parameter/MIDI ordering.
|
||||||
facility; opaque state and automatic native descriptor registration in project
|
It is a public C facility; opaque state and automatic native descriptor
|
||||||
files remain unsupported. Native instrument and gain examples exercise the
|
registration in project files remain unsupported. Native instrument and gain
|
||||||
interface before adding a dynamically loaded module lifetime.
|
examples exercise the interface before adding a dynamically loaded module
|
||||||
|
lifetime.
|
||||||
|
|
||||||
Select LADSPA 1.1 for the first external host. Reconsidering earlier candidates,
|
Select LADSPA 1.1 for the first external host. Reconsidering earlier candidates,
|
||||||
LV2 needs RDF/features/URIDs/workers, CLAP needs host scheduling/extension
|
LV2 needs RDF/features/URIDs/workers, CLAP needs host scheduling/extension
|
||||||
negotiation, and VST3 needs a separate C++ SDK adapter and release-specific license
|
negotiation, and VST3 needs a separate C++ SDK adapter and release-specific
|
||||||
review. LADSPA adds a mature Linux C ABI, installed real plugins, straightforward
|
license review. LADSPA adds a mature Linux C ABI, installed real plugins,
|
||||||
port negotiation and no RDF/SDK runtime library. Its specification is old and
|
straightforward port negotiation and no RDF/SDK runtime library. Its
|
||||||
stable, not an actively expanding instrument/event ecosystem. This trades MIDI,
|
specification is old and stable, not an actively expanding instrument/event
|
||||||
editors, opaque state and modern automation for a small testable first host.
|
ecosystem. This trades MIDI, editors, opaque state and modern automation for a
|
||||||
No general multi-format abstraction is introduced.
|
small testable first host. No general multi-format abstraction is introduced.
|
||||||
|
|
||||||
Use the installed LGPL-2.1-or-later header, system dynamic loader (`-ldl`), and
|
Use the installed LGPL-2.1-or-later header, system dynamic loader (`-ldl`), and
|
||||||
user-selected, trusted module files. Neither the header nor plugin binaries are
|
user-selected, trusted module files. Neither the header nor plugin binaries are
|
||||||
vendored. Header absence or `XTC_DISABLE_LADSPA` yields unsupported hosting stubs;
|
vendored. Header absence or `XTC_DISABLE_LADSPA` yields unsupported hosting
|
||||||
metadata can still be loaded/saved. Plugin licenses are independent of the host
|
stubs; metadata can still be loaded/saved. Plugin licenses are independent of
|
||||||
and require review before distribution. See LICENSES.md.
|
the host and require review before distribution. See LICENSES.md.
|
||||||
|
|
||||||
Support zero/one mono audio input and exactly one mono output, at most 64 ports
|
Support zero/one mono audio input and exactly one mono output, at most 64 ports
|
||||||
and 16 input controls. Graph stereo consists of independent instances, not a
|
and 16 input controls. Graph stereo consists of independent instances, not a
|
||||||
stereo LADSPA layout. Reject incompatible layouts and identities explicitly.
|
stereo LADSPA layout. Reject incompatible layouts and identities explicitly.
|
||||||
Control outputs are connected to private storage, not exposed as graph events.
|
Control outputs are connected to private storage, not exposed as graph events.
|
||||||
LADSPA has no MIDI or opaque state API: save control values only. Parameter
|
LADSPA has no MIDI or opaque state API: save control values only. Parameter
|
||||||
changes rebuild plans on the control thread; sample automation is provided through
|
changes rebuild plans on the control thread; sample automation is provided
|
||||||
parameter processors. Rate-scaled bounds are recalculated at compile. Instance history/tails
|
through parameter processors. Rate-scaled bounds are recalculated at compile.
|
||||||
reset on recompile, not every transport seek (LADSPA has no realtime reset rule).
|
Instance history/tails reset on recompile, not every transport seek (LADSPA has
|
||||||
Latency compensation is unsupported: the supported set is zero-latency amp,
|
no realtime reset rule). Latency compensation is unsupported: the supported set
|
||||||
inverter and sine source, not arbitrary lookahead/delay/routing plugins.
|
is zero-latency amp, inverter and sine source, not arbitrary
|
||||||
|
lookahead/delay/routing plugins.
|
||||||
|
|
||||||
Discovery, dlopen, descriptor calls, instantiate, connect, activate, deactivate,
|
Discovery, dlopen, descriptor calls, instantiate, connect, activate, deactivate,
|
||||||
cleanup and dlclose are control-thread operations. Only preallocated copies and
|
cleanup and dlclose are control-thread operations. Only preallocated copies and
|
||||||
run execute in audio; the usual pending/retired plan handoff owns module handles.
|
run execute in audio; the usual pending/retired plan handoff owns module
|
||||||
Partial initialization unwinds on the control thread. The host cannot enforce
|
handles. Partial initialization unwinds on the control thread. The host cannot
|
||||||
third-party callback behavior, bound CPU time, catch native crashes/hangs, or
|
enforce third-party callback behavior, bound CPU time, catch native
|
||||||
undo memory corruption. There is no sandbox or crash recovery inside the audio
|
crashes/hangs, or undo memory corruption. There is no sandbox or crash recovery
|
||||||
process. A fault may kill xtc; previously saved documents/recording recovery files
|
inside the audio process. A fault may kill xtc; previously saved
|
||||||
remain subject to their ordinary durability guarantees. Test only trusted modules.
|
documents/recording recovery files remain subject to their ordinary durability
|
||||||
|
guarantees. Test only trusted modules.
|
||||||
|
|
||||||
Project v5 stores plain identity/layout/control metadata. Parsing never opens
|
Project v5 stores plain identity/layout/control metadata. Parsing never opens
|
||||||
modules. Compile failure preserves the source document and active plan. GUI Open
|
modules. Compile failure preserves the source document and active plan. GUI Open
|
||||||
rejects missing/incompatible modules, retains its current document, and reports
|
rejects missing/incompatible modules, retains its current document, and reports
|
||||||
saved module identity/path. Restore the compatible module at that path and retry;
|
saved module identity/path. Restore the compatible module at that path and
|
||||||
a metadata-only C client can preserve/save the document without the module.
|
retry; a metadata-only C client can preserve/save the document without the
|
||||||
No silent replacement or deletion occurs. Same-ID/label/ports do not authenticate
|
module. No silent replacement or deletion occurs. Same-ID/label/ports do not
|
||||||
binaries or guarantee unchanged sound across plugin upgrades.
|
authenticate binaries or guarantee unchanged sound across plugin upgrades.
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,14 @@
|
||||||
# 0010 — Bounded CLAP, VST2 and VST3 effect loading
|
# 0010 — Bounded CLAP, VST2 and VST3 Effect Loading
|
||||||
|
|
||||||
Accepted. The user's request to support these three formats
|
Accepted. The user's request to support these three formats supersedes the
|
||||||
supersedes the earlier recommendation to choose only one external format.
|
earlier recommendation to choose only one external format.
|
||||||
|
|
||||||
Keep the engine/model/host adapters in C99. CLAP uses pinned MIT headers and VST3
|
Keep the engine/model/host adapters in C99. CLAP uses pinned MIT headers and
|
||||||
uses the upstream BSD-3-Clause generated C ABI. No SDK runtime library is needed;
|
VST3 uses the upstream BSD-3-Clause generated C ABI. No SDK runtime library is
|
||||||
Linux dynamic loading and POSIX thread identity are existing platform facilities.
|
needed; Linux dynamic loading and POSIX thread identity are existing platform
|
||||||
VST2 uses original minimal compatibility declarations, not the discontinued SDK.
|
facilities. VST2 uses original minimal compatibility declarations, not the
|
||||||
See third_party/README.md and LICENSES.md for exact revisions and notices.
|
discontinued SDK. See third_party/README.md and LICENSES.md for exact revisions
|
||||||
|
and notices.
|
||||||
|
|
||||||
Reuse the existing plugin graph node, paired mono instances and immutable plan
|
Reuse the existing plugin graph node, paired mono instances and immutable plan
|
||||||
ownership. The common facade routes LADSPA to its existing implementation and
|
ownership. The common facade routes LADSPA to its existing implementation and
|
||||||
|
|
@ -18,25 +19,27 @@ configuration is used; no parameter/controller/editor or opaque-state access is
|
||||||
exposed. These are usable effect loaders, not complete implementations of every
|
exposed. These are usable effect loaders, not complete implementations of every
|
||||||
extension in the formats. Unsupported layouts fail explicitly.
|
extension in the formats. Unsupported layouts fail explicitly.
|
||||||
|
|
||||||
Project v11 adds format plus CLAP stable ID or VST3 class ID to each saved plugin.
|
Project v11 adds format plus CLAP stable ID or VST3 class ID to each saved
|
||||||
Older plugins migrate to LADSPA with an empty extra ID. VST2 retains its integer
|
plugin. Older plugins migrate to LADSPA with an empty extra ID. VST2 retains its
|
||||||
unique ID. Reopening checks format/index/identity/name/layout; metadata operations
|
integer unique ID. Reopening checks format/index/identity/name/layout; metadata
|
||||||
never open modules. This does not authenticate a binary or freeze defaults across
|
operations never open modules. This does not authenticate a binary or freeze
|
||||||
plugin releases. No modified opaque state exists in this initial API to persist.
|
defaults across plugin releases. No modified opaque state exists in this initial
|
||||||
|
API to persist.
|
||||||
|
|
||||||
Discovery and instance creation execute trusted module code on one serialized
|
Discovery and instance creation execute trusted module code on one serialized
|
||||||
main/control thread. A module cache balances CLAP entry init/deinit and Linux
|
main/control thread. A module cache balances CLAP entry init/deinit and Linux
|
||||||
VST3 ModuleEntry/ModuleExit across overlapping graph instances and retired plans.
|
VST3 ModuleEntry/ModuleExit across overlapping graph instances and retired
|
||||||
CLAP start_processing runs on the processing owner; stop_processing runs after
|
plans. CLAP start_processing runs on the processing owner; stop_processing runs
|
||||||
quiescence with the symbolic audio-thread context. CLAP callback requests use
|
after quiescence with the symbolic audio-thread context. CLAP callback requests
|
||||||
lock-free flags and are serviced by xtc_plugin_idle on main/control (the GUI timer
|
use lock-free flags and are serviced by xtc_plugin_idle on main/control (the GUI
|
||||||
calls it). Restart/I/O-change requests latch an error for re-preparation; the audio
|
timer calls it). Restart/I/O-change requests latch an error for re-preparation;
|
||||||
callback does not reconfigure or wait for GUI work. CLAP process wakeups need no
|
the audio callback does not reconfigure or wait for GUI work. CLAP process
|
||||||
queue because playback processes every block, including silence.
|
wakeups need no queue because playback processes every block, including silence.
|
||||||
|
|
||||||
Only preallocated buffers and plugin processing occur in audio. Error status
|
Only preallocated buffers and plugin processing occur in audio. Error status
|
||||||
silences the failed block; nonfinite/subnormal samples are sanitized. Plugin code
|
silences the failed block; nonfinite/subnormal samples are sanitized. Plugin
|
||||||
can still allocate, block, corrupt memory or crash; there is no sandbox, scanner
|
code can still allocate, block, corrupt memory or crash; there is no sandbox,
|
||||||
subprocess or recoverable crash boundary. Modules unload only after destruction
|
scanner subprocess or recoverable crash boundary. Modules unload only after
|
||||||
on a quiescent/control owner. Real third-party plugins and hardware timing remain
|
destruction on a quiescent/control owner. Real third-party plugins and hardware
|
||||||
unqualified; original ABI fixtures demonstrate the bounded contracts.
|
timing remain unqualified; original ABI fixtures demonstrate the bounded
|
||||||
|
contracts.
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,31 @@
|
||||||
# 0011 — Prepared MIDI track instruments
|
# 0011 — Prepared MIDI Track Instruments
|
||||||
|
|
||||||
Accepted. Extend the modern C99 adapters with zero-audio-input,
|
Accepted. Extend the modern C99 adapters with zero-audio-input, mono-output
|
||||||
mono-output instruments and one event input. Keep graph effects separate from
|
instruments and one event input. Keep graph effects separate from track
|
||||||
track bindings. Each assigned track owns one prepared instance; the existing
|
bindings. Each assigned track owns one prepared instance; the existing
|
||||||
instrument source sums their mixed output and the sine output of unassigned
|
instrument source sums their mixed output and the sine output of unassigned
|
||||||
tracks. A stable saved live target prevents accidental broadcast/double playback.
|
tracks. A stable saved live target prevents accidental broadcast/double
|
||||||
|
playback.
|
||||||
|
|
||||||
Bindings are copied metadata in the project/history model, serialized in v12.
|
Bindings are copied metadata in the project/history model, serialized in v12.
|
||||||
Loading metadata never executes modules. GUI edits prepare a candidate before
|
Loading metadata never executes modules. GUI edits prepare a candidate before
|
||||||
publication, preserving the previous project on missing/invalid binaries. Existing
|
publication, preserving the previous project on missing/invalid binaries.
|
||||||
quiescent plan retirement owns destruction; no module operation belongs in audio.
|
Existing quiescent plan retirement owns destruction; no module operation belongs
|
||||||
|
in audio.
|
||||||
|
|
||||||
Preallocate 256-frame audio scratch and 256 incoming events per chunk. Stable
|
Preallocate 256-frame audio scratch and 256 incoming events per chunk. Stable
|
||||||
insertion orders reset, scheduled off/on and live events without callback sort or
|
insertion orders reset, scheduled off/on and live events without callback sort
|
||||||
allocation. VST3 translates into a bounded 2304-event IEventList (2048 possible
|
or allocation. VST3 translates into a bounded 2304-event IEventList (2048
|
||||||
held keys plus 256 incoming events); panic expands held keys to note-offs. CLAP
|
possible held keys plus 256 incoming events); panic expands held keys to
|
||||||
prefers MIDI where supported, otherwise native note events; VST2 uses MIDI ABI
|
note-offs. CLAP prefers MIDI where supported, otherwise native note events; VST2
|
||||||
messages. Native CLAP and VST3 currently omit controller mapping. Existing
|
uses MIDI ABI messages. Native CLAP and VST3 currently omit controller mapping.
|
||||||
32 simultaneous scheduled notes and 4096 stored notes remain validation bounds.
|
Existing 32 simultaneous scheduled notes and 4096 stored notes remain validation
|
||||||
|
bounds.
|
||||||
|
|
||||||
Discontinuities send all-off and chase spanning notes with fresh note-ons.
|
Discontinuities send all-off and chase spanning notes with fresh note-ons. Panic
|
||||||
Panic suppresses already-started scheduled notes. Neither operation promises
|
suppresses already-started scheduled notes. Neither operation promises opaque
|
||||||
opaque DSP reconstruction or removal of release tails. Overflow/process errors
|
DSP reconstruction or removal of release tails. Overflow/process errors silence
|
||||||
silence the block and arm reset for the following render. Hosts cannot guarantee
|
the block and arm reset for the following render. Hosts cannot guarantee that
|
||||||
that third-party processing is realtime safe. Qualification covers original ABI
|
third-party processing is realtime safe. Qualification covers original ABI
|
||||||
fixtures; arbitrary third-party plugins, physical audio and MIDI remain unverified.
|
fixtures; arbitrary third-party plugins, physical audio and MIDI remain
|
||||||
|
unverified.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue