Offline rendering
Offline rendering is a host-neutral composition of the installed public interfaces. The SDK does not ship an IOfflineRenderer, an OfflineRenderJob, or an offline_renderer executable. The application owns the loop that moves completed audio blocks from transport output buffers to a background writer.
Use the supported composition
Section titled “Use the supported composition”Perform setup and file work on a control or background thread:
- Query
getAudioFileCapabilities()and callpreflightAudioFileWrite()for the exact output tuple before creating media objects. - Create an
IAudioFileWriterfor the output, or use an existing source file. - Call
probeAudioFile()and open anIAudioFileReaderfor each input. - Create a
TransportConfig, register and prepare each source, and route its group withsetGroupOutputBus(). - Allocate planar output buffers once. Call
processAudio()with no more than the configured maximum block size. - Interleave each completed block on the control/background side and call
writeSamples()there. Close the writer and inspect its metadata.
The render call is still an audio operation even when no device is involved. It must not perform file I/O, callback dispatch, sleeping, or hardware-driver work. A host may choose any offline block size accepted by its transport configuration; the routing implementation may internally chunk work.
Source: offline_renderer/README.md, transport_controller.h, and routing_matrix.h.
Preflight exact file tuples
Section titled “Preflight exact file tuples”getAudioFileCapabilities() reports policy and provider availability without probing a file. It documents WAV, AIFF, and FLAC read support; an individual file still needs probeAudioFile() for actual acceptance. preflightAudioFileWrite() validates the exact rate, channel count, container, and sample encoding without opening a destination.
For the required libsndfile provider, the writer supports WAV and AIFF as Int16, Int24, or Float32, and FLAC as Int16 or Int24. FLAC Float32 is rejected. Missing provider support is NotReady; invalid rate or channel values are InvalidParameter; unsupported containers are NotSupported; opening the destination can still fail with InternalError after a successful preflight. Keep those outcomes separate in diagnostics.
Source: audio_file_capabilities.h and audio_file_writer.h.
Keep reader and writer work off the callback
Section titled “Keep reader and writer work off the callback”Opening and closing readers and writers belongs on a background/UI thread. Reader reads and seeks are background operations unless a concrete implementation documents a stronger guarantee; writer writes perform blocking file I/O and must never run from an audio callback. A real-time capture path should feed a lock-free ring and let a background writer drain it.
The installed package example is the executable reference for this sequence. It links only the public transport and audio utility targets, uses no private implementation headers, and does not use a device driver. Its deterministic contract writes a stereo 48 kHz PCM16 source, renders fixed output frames across block sizes 256, 512, 1024, and 2048, verifies metadata and samples, checks trailing silence and EOF, and records a portable payload digest. That evidence scopes the recipe; it does not mean every codec or provider tuple has been executed.
Source: audio_file_reader.h, audio_file_writer.h, offline_renderer/README.md, and offline_render.cpp.
Verify the result, then clean up
Section titled “Verify the result, then clean up”Treat every operation as a checked result: preflight, writer open, each write, close, probe, reader open/read/close, transport status, and final metadata. Remove temporary source and output files only after the reader and writer have closed. If a writer or reader provider is absent, report a prerequisite failure; do not treat an empty or unrendered output as a passing offline result.