1
0
Fork 0
forked from hanez/xtc
xtc/docs/AUDIO_FILES.md

6.6 KiB

Audio clips and recording (Phase 6)

Import and playback

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 silent placeholder. Imported clips use the existing move/trim controls. Import stops playback, validates a candidate project, and commits only after successful backend preparation (or locally when disconnected).

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, WAVE_FORMAT_EXTENSIBLE, PCM8, other containers and multichannel files are unsupported. Nonfinite float data and malformed/truncated files are rejected. There is no new dependency: the bounded C decoder/writer is covered by known sample, truncation and invalid-codec tests. See decision 0005.

Audio is preloaded before playback: maximum 64 distinct paths per plan, 16777216 mono frames per asset (64 MiB), 67108864 total frames (256 MiB). Import rejects files over 256 MiB or over 4096 chunks. No streaming decoder, waveform cache, peak drawing or background load worker exists yet. Preloading can briefly block the GUI. Candidate compilation retains the old plan until success; temporary build memory can include both old and candidate buffers.

The callback renders only overlapping clip ranges from memory. Clips on all tracks are summed through their mix/automation settings into the graph's Audio clips source node. Import creates that source and connects it to an existing/new output if no audio source exists. Subsequent routing is explicit: disconnect it or route it through gain/meter nodes in Modular Graph. Removing the output silences editor graphs. This source does not monitor JACK input; unconnected ordinary graph inputs retain their earlier external-input behavior. Track faders/pan/mute are implemented by the Phase 8 track mixer (see MIXER.md); individual track graph routing remains deferred.

Linear interpolation converts source sample rate to backend rate. There is no antialiasing filter, time stretching, looping or fades. Musical durations round up to a tick on import; playback boundaries and trims use floor tick-to-sample conversion. A rounded tail pads with silence past the source, and a recording's placement can differ by less than one tick from the capture start sample. Changing tempo changes the musical span, not the source playback rate.

Arrange edits stop playback. Play preloads and adopts the current arrangement; Stop pauses the sample clock. Graph-only edits can still be submitted during playback. Graph recompilation can reset oscillator phase as before. Playback does not stop automatically at the arrangement end.

Assets and recovery

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 metadata path; it does not copy assets. Moving/deleting a WAV makes its regions silent, preserves their IDs/positions and reports the path and unique issue count on Open/Play. An already loaded plan keeps playing even if its file is removed; the next preparation detects it. Unreadable, malformed and unsupported assets are also reported, rather than substituted with unrelated files. Capacity/OOM is a preparation failure and retains the old plans.

Select the affected clip, then File/Relink selected audio to choose a replacement. Relinking retains its original timeline/source bounds. The replacement is validated on the next Play; a shorter replacement pads beyond its end with silence. Saving retains unresolved references for later repair. Missing assets are also checked on Open without a working backend, using a temporary plan. Automatic asset search, content hashes and portable project bundles are deferred.

Recording

Record (or Audio/Record WAV, Shift+F5) opens a destination chooser, stops playback, prepares the project, opens a temporary mono float32 WAV and starts JACK. Connect a source to xtc's JACK input using an external patchbay; no physical or software route is created automatically. Without a route the take 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 GUI/control thread, which drains it every 100 ms. The producer uses verified lock-free atomics and bounded copies only. It never allocates, logs, takes a mutex, opens/writes files or calls FLTK. A slow disk/blocked GUI can overflow the ring; capture then stops accepting input with a sticky, visible capacity error rather than hiding gaps or compressing time.

Stop first synchronizes the callback, detaches the recorder, drains remaining samples, writes the final WAV header, flushes/fsyncs/closes and renames the same-directory temporary over the destination. A successful nonempty take is imported at its capture position on the selected track (or a new Recording track), then the document becomes unsaved. Save the project after Stop. Seeking back to the take and pressing Play auditions it. Recording continues existing arrangement playback, 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 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 and is not automatically added. On import/preparation failure the completed take remains at its chosen path with an explicit recovery message. I/O errors are reported; an unfinished temporary is removed on destruction. Recordings are RIFF-limited to 1073741814 frames, but the smaller playback/import asset limit still applies: longer takes may need external splitting before import. There is no crash-recovery journal. The file is mode 0600; parent-directory fsync and preservation of previous permissions are not implemented.

Verification

make test includes deterministic WAV/graph samples, resampling/overlap/trim, malformed inputs, missing/relinked assets, SPSC concurrency/overflow/cleanup, and record -> save/reopen -> exact playback through the backend callback. make test-gui covers the workflow and rollback with a fake backend. make test-gui-jack records/reopens a silent take using real JACK callbacks. make test-jack-audio routes only two software clients: known source -> recorded WAV -> saved/reopened project -> graph playback -> capture assertion. Physical input/output, device latency, slow-disk endurance and server loss during a real recording remain unverified.