Skip to content

Releases: RustAudio/cpal

cpal 0.18.2

Choose a tag to compare

@roderickvd roderickvd released this 16 Aug 17:58

Added

  • AAudio: Xruns are now reported as ErrorKind::Xrun.
  • CoreAudio: Xruns are now reported as ErrorKind::Xrun.
  • PipeWire: Xruns are now reported as ErrorKind::Xrun.
  • WASAPI: Capture xruns are now reported as ErrorKind::Xrun.

Changed

  • BSD: Clarify that realtime-dbus has no effect there.
  • CoreAudio: Bump objc2-core-foundation dependency lower bound to 0.3.1.
  • iOS: Timestamps now include hardware latency and update when the audio route changes.
  • JACK: Timestamps now include port latency.
  • Linux: Clarify that realtime alone is a no-op without realtime-dbus.
  • PipeWire: Devices with multiple ports now get distinct, localized, per-port names.
  • WASAPI: The windows and windows-core dependencies are now both pinned to 0.62.

Fixed

  • Timestamps now stay monotonic across device and graph changes.
  • ALSA: A nonzero but sub-millisecond stream timeout is no longer treated as a non-blocking poll.
  • ALSA: Fix compilation on FreeBSD, DragonFly, and NetBSD.
  • ASIO: Fix duplex streams silently dropping audio when built from separate Device handles.
  • AudioWorklet: Fix Stream operations to work when called from any thread.
  • AudioWorklet: Fix stale audio output when a data callback wrote a partial buffer.
  • CoreAudio: Fix stale audio output when a data callback wrote a partial buffer.
  • CoreAudio: Default-output streams now report xrun status.
  • iOS: Streams now resume automatically when an audio session interruption ends.
  • JACK: Streams with more channels than physical system ports no longer fail to build.
  • JACK: Channel enumeration is no longer capped at the physical system port count.
  • JACK: Device::id no longer embeds the process ID, so DeviceId is now stable across application restarts.
  • PipeWire: Fix streams starting audio before play() is called.
  • PipeWire: Fix real-time promotion blocking the audio callback thread on Linux.
  • PipeWire: Fix rtkit burst limit errors from repeated real-time promotion on quantum jitter.
  • PipeWire: Fix 24-bit sample format mapping.
  • PipeWire: Nodes with an /Internal media class are now enumerated as devices.
  • PipeWire: Streams for a specific device no longer auto-reroute if it disappears.
  • PipeWire: Build on 32-bit targets without native 64-bit atomics.
  • PulseAudio: NoData errors are no longer misreported as buffer xruns.
  • PulseAudio: Build on 32-bit targets without native 64-bit atomics.
  • visionOS: The CoreAudio backend now builds.
  • WASAPI: Stream::drop, play, and pause no longer panic when the device is lost.
  • WASAPI: Output streams no longer reject formats that the built-in resampler can convert.
  • WASAPI: Fix 24-bit samples not being packed into the upper bits of their sample container.
  • WASAPI: Reported buffer sizes are no longer off by one frame.
  • WASAPI: Default device changes no longer report DeviceChanged, which wrongly implied the stream had rerouted automatically.
  • WebAudio: Fix stale audio output when a data callback wrote a partial buffer.
  • WebAudio: Fix unsound Send + Sync on Stream when compiled with +atomics.
  • WebAudio: Fix Host::is_available() always returning true, even in non-window contexts.

Thanks to Our Contributors

14 people contributed to this release, 9 of them for the first time: Andreas (@sandreas), Benoît Rouleau (@benface), @dheijl, Edwin Löffler (@edwloef), Erwan Legrand (@ErwanLegrand), @Jaxx497, Kpqi5858 (@kpqi5858), LastExceed (@LastExceed), Mat Silverstein (@silverstein), @MordechaiHadad, Nicola Vitale (@nivit), Nicolas Franco Gomez (@nico-franco-gomez), SkeletonGamer (@SkeletonGamer), and @the-drunk-coder. Welcome aboard, and thank you all!

asio-sys 0.4.0

Choose a tag to compare

@roderickvd roderickvd released this 16 Aug 17:51

Added

  • Added Driver::streams() to access a driver's shared input/output buffer state
  • Derived Debug on AsioStreams and AsioStream

Thanks to Our Contributors

Thanks to MordechaiHadad (@MordechaiHadad), who reported the duplex-stream bug (#1287) that Driver::streams() fixes in this release.

cpal 0.18.1

Choose a tag to compare

@roderickvd roderickvd released this 07 Jun 14:53
94ecb6e

A quick follow-up to 0.18.0 primarily to fix the docs.rs build failure.

  • docs.rs: Excluded pipewire, whose system dependency isn't available in that sandboxed build environment.
  • WASM: Fixed the audioworklet feature failing to compile on wasm32-wasip1 and other non-browser wasm32 targets.

No API or behavioral changes.

Links

cpal 0.18.0

Choose a tag to compare

@roderickvd roderickvd released this 06 Jun 21:07
45fe976

Hey everyone! cpal 0.18.0 is out, bringing two long-requested native Linux backends, a unified error API, and accurate timestamps across every platform.

What's New

Native PipeWire and PulseAudio

Two new first-class backends join the Linux and BSD lineup:

  • PipeWire
  • PulseAudio

Enable them with the pipewire and pulseaudio Cargo features. When multiple backends are compiled in, cpal selects the best available one at runtime: PipeWire > PulseAudio > ALSA.

Unified Error API

All per-operation error enums (DevicesError, BuildStreamError, StreamError, etc.) are replaced by a single cpal::Error with a kind() getter:

match device.default_output_config() {
    Err(e) => match e.kind() {
        cpal::ErrorKind::DeviceNotAvailable => { /* ... */ }
        cpal::ErrorKind::DeviceBusy => { /* retry */ }
        _ => { /* ... */ }
    }
}

Two new error kinds make previously indistinguishable cases actionable: DeviceBusy (EBUSY/EAGAIN is retryable) and PermissionDenied for OS-level access denials. See the upgrading guide for the mapping table.

Accurate Timestamps and A/V Sync

Timestamps previously reflected when the callback fired rather than when audio would actually reach hardware. This release corrects that across every backend:

  • AAudio: pipeline buffer depth accounted for; fallback to zero on error fixed
  • ALSA: LinkSynchronized hardware cross-timestamps for reduced jitter on supported devices
  • ASIO: driver-reported hardware latency included; re-queried on kAsioLatenciesChanged
  • CoreAudio: device latency and safety offset included
  • JACK: precise hardware cycle deadline; input capture timestamps were previously using callback execution time
  • WASAPI: hardware pipeline latency included
  • WebAudio: base and output latency included

A new StreamTrait::now() method lets you query the stream's clock from outside the callback for A/V sync: read the audio clock at any point and correlate it with your video timeline.

48 kHz is the New Default

default_input_config() and default_output_config() now prefer 48 kHz, then 44.1 kHz, on all backends. Defaulting to 44.1 kHz meant cpal's chosen rate often didn't match the hardware's preferred rate. Pin it explicitly if you need 44.1 kHz.

New API

  • StreamTrait::buffer_size() queries the stream's current buffer size
  • SupportedStreamConfigRange::try_with_standard_sample_rate() / with_standard_sample_rate() snaps to 48 kHz or 44.1 kHz from a supported range

Platform Improvements

  • ALSA: device_by_id() now accepts PCM shorthand names like hw:0,0 and plughw:foo; streams attempt to recover after system suspend; capture streams no longer hang on overruns; backward-stepping timestamps during startup and xrun recovery are fixed.

  • ASIO: collect() on the device iterator no longer stops after the first device; device enumeration and stream creation now work correctly when called from spawned threads; distortion from drivers that fire the buffer callback multiple times per cycle is fixed.

  • CoreAudio: the physical stream format is now set directly on the hardware device rather than relying on the HAL mixer; user-specified timeouts are now respected when building a stream.

  • JACK: buffer size changes no longer fire an error callback but resizes internal buffers, avoiding unnecessary stream rebuilds; server shutdown now surfaces as ErrorKind::DeviceNotAvailable.

  • WASAPI: device names now prefer FriendlyName over DeviceDesc, so you see the readable name from system settings; default streams automatically reroute when the system default device changes.

...and a lot more. The changelog has the full picture.

Breaking Changes

  • Streams now require an explicit play() call: ALSA, CoreAudio, and JACK previously auto-started streams on creation. If you never called play(), your callback will never fire after upgrading.
  • Error types unified: match on e.kind() instead of per-operation error enums.
  • StreamConfig passed by value: StreamConfig now implements Copy; drop the & at build_*_stream call sites.
  • StreamInstant API overhauled: aligns with std::time::Instant. Change add/sub to checked_add/checked_sub (or +/-); duration_since returns Duration (saturating), secs/nanos are now u64.
  • Default sample rate is now 48 kHz: pin explicitly if you need 44.1 kHz.
  • Default sample format heuristics now fully ranked: floats before integers, higher bit-depth before lower; pin F32 explicitly if you were relying on it as the default.
  • Emscripten host removed: migrate to wasm32-unknown-unknown with the wasm-bindgen feature.

Full details and migration examples in the upgrading guide.

Looking Ahead to v0.19

The design goals are tracked in #1220. Highlights:

  • Extension traits: clean access to platform-specific functionality like RAW mode on WASAPI, control panel on ASIO, identifying stream properties on PipeWire, etc.
  • Exclusive mode on CoreAudio and WASAPI
  • Duplex stream API
  • Input streams on WASM: microphone access from the browser
  • Stream lifecycle normalization: play/pause to start/pause/stop with a draining stop
  • Native DSD on WASAPI
  • BufferSize refactor with range support

The feature set may change.

Thanks to Our Contributors

25 people contributed to this release, 19 of them for the first time: Access (@Decodetalkers), atlv (@atlv24), Chandler Newman (@csnewman), Colin Marc (@colinmarc), @DanielHabenicht, @dheijl, Edwin Löffler (@edwloef), GorTech (@gortech), Jerry.Wang (@wangjia184), kibaa (@d3d9), Louis Beaumont (@louis030195), Marin (@marin-m), Mat Silverstein (@silverstein), Mike Hilgendorf (@m-hilgendorf), Mikey (@ahdinosaur), Nicolas Franco Gomez (@nico-franco-gomez), osoftware (@osoftware), Raphael Poss (@knz), Seto Elkahfi (@setoelkahfi), Sintel (@Sin-tel), thewh1teagle (@thewh1teagle), Umer Haider (@umerhd), Worik Stanton (@worikgh), and 时光回忆 (@mikai233). Welcome aboard, and thank you all!

A handful of longstanding reports, some dating back to 2019, also got closed out along the way as fixes elsewhere in this release happened to resolve them too. Thanks to the original reporters for filing them and sticking around: @bspot, @JustAnotherCodemonkey, @knappador, Marc-Antoine ARNAUD (@MarcAntoine-Arnaud), @mitchmindtree, MOZGIII (@MOZGIII), Philippe GASSMANN (@zenria), Przemysław Węgrzyn (@codepainters), TG (@tGrothmannFluffy), @the-drunk-coder, and Will (@will3942).

Support the Project

If you find value in cpal, sponsorships are a heartfelt token of appreciation and help cover the costs of building it: music service subscriptions, hardware for cross-platform compatibility, and tooling. Every contribution helps: sponsor me at GitHub.

Links

Huge thanks to everyone who contributed to this release!

asio-sys 0.3.0

Choose a tag to compare

@roderickvd roderickvd released this 06 Jun 20:41
baa3678

Added

  • Added Driver::latencies() to query input and output stream latencies
  • Added BufferPreference enum with the driver's preferred buffer size and valid-size constraints

Changed

  • Driver::add_message_callback and Driver::remove_message_callback replaced by Driver::add_event_callback and Driver::remove_event_callback
  • MessageCallback renamed to DriverEventCallback, and MessageCallbackId renamed to DriverEventCallbackId. DriverEventCallback wraps Fn(AsioDriverEvent) -> bool whereAsioDriverEvent is a new enum covering both asioMessage selector events and sampleRateDidChange notifications
  • CallbackId renamed to BufferCallbackId
  • Public-facing c_long fields and return types replaced with i32
  • Public-facing c_double parameters and return types replaced with f64
  • CallbackInfo::system_time is now u64 nanoseconds
  • AsioError::ASE_NoMemory renamed to AsioError::NoMemory
  • Extended BufferSizeRange with a preferred: BufferPreference field
  • AsioTime::reserved, AsioTimeInfo::reserved, AsioTimeCode::future fields made private.
  • asio_import module is now pub(crate); raw bindgen types are no longer public API
  • asio_message now dispatches kAsioResyncRequest and kAsioLatenciesChanged to callbacks
  • asio_message delegates kAsioSelectorSupported for unknown selectors to registered callbacks, so each host decides which capabilities it opts into
  • sample_rate_did_change now dispatches AsioDriverEvent::SampleRateChanged to registered callbacks when the reported rate differs from the last known rate

Fixed

  • Fixed TOCTOU race condition when creating streams concurrently
  • Fixed data race where channels, latencies, sample_rate, and related query methods could call ASIO concurrently during set_sample_rate's teardown/reload
  • Fixed Asio::load_driver to return LoadDriverError::LoadDriverFailed instead of panicking when the driver name contains a null byte
  • Fixed Driver::set_sample_rate to perform a dummy buffer cycle and driver reload when the driver does not apply the rate change immediately, as required by some drivers (e.g. Steinberg)
  • Fixed asio_message not advertising kAsioSelectorSupported itself as a supported selector
  • Fixed rust-analyzer errors on non-Windows targets by using stub instead of ASIO bindings

Removed

  • Removed unused SampleRate struct
  • Removed DriverState from the public API

Thanks to Our Contributors

Thanks to Jerry.Wang (@wangjia184), who fixed the rust-analyzer build on non-Windows targets (#1140).

cpal 0.17.3

Choose a tag to compare

@roderickvd roderickvd released this 18 Feb 20:57
fd3b945

Changed

  • Reverted SemVer-breaking DeviceBusy error variant addition.

Fixed

  • ASIO: Fix linker errors.

asio-sys 0.2.6

Choose a tag to compare

@roderickvd roderickvd released this 18 Feb 20:49
fd3b945

Fixed

  • Link advapi32 to resolve Windows Registry API symbols.

cpal 0.17.2

Choose a tag to compare

@roderickvd roderickvd released this 08 Feb 21:59

This release was yanked.

Added

  • DeviceBusy error variant for retriable device access errors (EBUSY, EAGAIN).
  • ALSA: Debug implementations for Host, Device, Stream, and internal types.
  • ALSA: Example demonstrating ALSA error suppression during enumeration.
  • WASAPI: Enable as-necessary resampling in the WASAPI server process.

Changed

  • Bump overall MSRV to 1.78.
  • ALSA: Update alsa dependency to 0.11.
  • ALSA: Bump MSRV to 1.82.
  • CoreAudio: Update core-audio-rs dependency to 0.14.

Fixed

  • ALSA: Enumerating input and output devices no longer interferes with each other.
  • ALSA: Device handles are no longer exclusively held between operations.
  • ALSA: Reduce Valgrind memory leak reports from ALSA global configuration cache.
  • ALSA: Fix possible race condition on drop.
  • ALSA: Fix audio callback stalling when start threshold is not met.

cpal 0.17.1

Choose a tag to compare

@roderickvd roderickvd released this 04 Jan 14:45
ddad8bc

Added

  • ALSA: Default implementation for Device (returns the ALSA "default" device).
  • CI: Checks default/no-default/all feature sets with platform-dependent MSRV for JACK.

Fixed

  • ALSA: Device enumeration now includes both hints and physical cards.
  • JACK: No longer builds on iOS.
  • WASM: WasmBindgen no longer crashes (regression from 0.17.0).

Changed

  • ALSA: Devices now report direction from hint metadata and physical hardware probing.

asio-sys 0.2.5

Choose a tag to compare

@roderickvd roderickvd released this 04 Jan 14:32
ddad8bc

Fixed

  • Fixed ASIO SDK discovery on case sensitive filesystems.