Skip to main content

Offline audio engine

This page describes aidj-platform's offline renderer. The separate aidj-club-emulator now has a four-CDJ distributed runtime and an optional native CPAL path; see shared B2B mixer. The emulator uses basic mixer DSP, while bosai-dsp is evaluated for a future adapter. No Beat FX or measured A9 transfer-function compatibility is currently claimed.

The audible demo decodes through Symphonia, resamples through Rubato to interleaved stereo 48 kHz, and uses Signalsmith Stretch for independent tempo/key processing within a deliberately bounded 0.85–1.15 tempo ratio. Signalsmith's exact offline path compensates algorithm latency and renders the requested length.

The render path is decoded track → key-locked tempo → complementary three-band EQ → low-pass filter → channel fader → master sum/gain → 16-bit stereo WAV. Transitions use equal-power fader envelopes, a complementary low-band swap and a late outgoing low-pass sweep. A fixed master gain leaves headroom; clipping is counted before final integer saturation. This is not a modeled DJM circuit, mastering limiter or loudness normalization system.

Timing is in integer output frames. AI decisions select prevalidated transitions; the renderer executes them without network calls. Pause and cancellation are cooperative worker controls. A partial WAV is not offered as a completed recording. Startup/shutdown fades suppress abrupt session boundaries.

Offline processing allocates and performs file I/O. It is not yet a realtime-safe callback. CPAL, preallocated rtrb queues and realtime underrun handling are a later output milestone. The future callback must avoid locks, allocation, filesystem work, logging and model calls.

Tests cover stereo unity EQ, tempo duration/pitch, scheduling and replay. Identical WAV hashes are required for replay on the same pinned engine build and unchanged PCM assets; cross-platform bit identity is not promised. Listening to real music is a separate acceptance gate.

Selected dependencies: Symphonia 0.6, Rubato 5, Signalsmith Rust wrapper. Building the wrapper requires a C++ compiler and libclang.