Skip to content

Audio and underruns

Start with capability discovery and the active route state. Keep endpoint selection explicit: when a chosen route fails, report that failure and reinitialize with host-selected configuration. Never silently fall back to a different endpoint.

Call enumerateEndpointCapabilities() or enumerateDevices() on a control/message thread and inspect direction-specific availability, channel descriptors, and supported rates. An empty output selection means the backend’s current default output; a nonempty identifier is never defaulted. Confirm supports_output, the requested channel count, and the active route state before starting.

The Dummy driver is available for hardware-independent integration and offline processing. It does not prove physical-device support. CoreAudio is the shipped production device backend on Apple platforms. Linux has no production device backend; WASAPI is source/fake-test capable on Windows but not release-supported. ASIO, ALSA, JACK, and PipeWire are unavailable in this release preview (ASIO is optional source-only when separately supplied).

Use a stable backend endpoint identifier, not a presentation name. Check probeRoute() before changing a route and handle InputUnavailable, OutputUnavailable, PermissionDenied, SampleRateUnsupported, InvalidChannelMap, and BackendFailure distinctly. A requested output channel count must be honored; do not replace it with a “closest” count unless that is an explicit host policy supported by the selected backend.

A terminal route outcome stops rendering and requires an explicit initialize() call. Preserve the current route when a transactional device change fails. Re-enumerate after an endpoint-change notification, then let the host choose whether and how to reinitialize.

A transport underrun means a prepared or streaming source could not provide the requested page at the render boundary. The callback emits bounded silence and reports BufferUnderrun; it does not read a file, sleep, allocate, or wait for a worker. Check that the source was registered and prepared before startClip(), and inspect worker/cache telemetry on the control side. For long sources, ensure the preparation worker has enough opportunity to fill its page ring before playback.

An underrun is different from a failed control operation. If prepareClipAudio() or a seek cannot reserve its working set, the control call returns an error and publishes no command. A seek refusal does not synthesize an underrun event or alter the cursor. Correct the preparation or capacity problem, then issue a new control operation.

Keep processAudio() input shape exact: provide the configured number of writable planar buffers and no more than the configured maximum frame count. Invalid shapes are no-touch returns. Drain transport callbacks and realtime telemetry from a message/control thread; callback diagnostics are opt-in and counters saturate instead of wrapping.