From 57b2f0c4764dc30ba91b4d1aad333ca15ddb454c Mon Sep 17 00:00:00 2001 From: Philpax Date: Wed, 1 Oct 2025 20:08:52 +0200 Subject: [PATCH 1/7] chore: update cpal to latest Git, replace `From for cpal::Device` with `into_inner` --- Cargo.lock | 142 +++++++++++++++++++++++++++++++++----- Cargo.toml | 2 +- examples/microphone.rs | 2 +- src/microphone.rs | 9 +-- src/microphone/builder.rs | 2 +- 5 files changed, 133 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d2c88ff6..321f0db9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,9 +13,9 @@ dependencies = [ [[package]] name = "alsa" -version = "0.9.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed7572b7ba83a31e20d1b48970ee402d2e3e0537dcfe0a3ff4d6eb7508617d43" +checksum = "7c88dbbce13b232b26250e1e2e6ac18b6a891a646b8148285036ebce260ac5c3" dependencies = [ "alsa-sys", "bitflags 2.9.1", @@ -78,6 +78,15 @@ version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +[[package]] +name = "block2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "340d2f0bdb2a43c1d3cd40513185b2bd7def0aa1052f956455114bc98f82dcf2" +dependencies = [ + "objc2", +] + [[package]] name = "bumpalo" version = "3.19.0" @@ -188,8 +197,7 @@ dependencies = [ [[package]] name = "cpal" version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbd307f43cc2a697e2d1f8bc7a1d824b5269e052209e28883e5bc04d095aaa3f" +source = "git+https://github.com/RustAudio/cpal?rev=c9d8e2e18789e305e2d087d65888f06db08bd2ba#c9d8e2e18789e305e2d087d65888f06db08bd2ba" dependencies = [ "alsa", "coreaudio-rs", @@ -197,14 +205,17 @@ dependencies = [ "jni", "js-sys", "libc", - "mach2", + "mach2 0.5.0", "ndk", "ndk-context", "num-derive", "num-traits", + "objc2", "objc2-audio-toolbox", "objc2-core-audio", "objc2-core-audio-types", + "objc2-core-foundation", + "objc2-foundation", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -560,6 +571,15 @@ dependencies = [ "libc", ] +[[package]] +name = "mach2" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a1b95cd5421ec55b445b5ae102f5ea0e768de1f82bd3001e11f426c269c3aea" +dependencies = [ + "libc", +] + [[package]] name = "memchr" version = "2.7.5" @@ -711,9 +731,9 @@ dependencies = [ [[package]] name = "objc2" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88c6597e14493ab2e44ce58f2fdecf095a51f12ca57bec060a11c57332520551" +checksum = "561f357ba7f3a2a61563a186a163d0a3a5247e1089524a3981d49adb775078bc" dependencies = [ "objc2-encode", ] @@ -743,6 +763,7 @@ dependencies = [ "objc2", "objc2-core-audio-types", "objc2-core-foundation", + "objc2-foundation", ] [[package]] @@ -762,7 +783,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166" dependencies = [ "bitflags 2.9.1", + "block2", "dispatch2", + "libc", "objc2", ] @@ -778,7 +801,11 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c" dependencies = [ + "bitflags 2.9.1", + "block2", + "libc", "objc2", + "objc2-core-foundation", ] [[package]] @@ -1181,7 +1208,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84ae312bda09b2368f79f985fdb4df4a0b5cbc75546b511303972d195f8c27d6" dependencies = [ "libc", - "mach2", + "mach2 0.4.3", "winapi", ] @@ -1676,31 +1703,103 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" -version = "0.54.0" +version = "0.62.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49" +checksum = "49e6c4a1f363c8210c6f77ba24f645c61c6fb941eccf013da691f7e09515b8ac" +dependencies = [ + "windows-collections", + "windows-core", + "windows-future", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "123e712f464a8a60ce1a13f4c446d2d43ab06464cb5842ff68f5c71b6fb7852e" dependencies = [ "windows-core", - "windows-targets 0.52.6", ] [[package]] name = "windows-core" -version = "0.54.0" +version = "0.62.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65" +checksum = "6844ee5416b285084d3d3fffd743b925a6c9385455f64f6d4fa3031c4c2749a9" dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", "windows-result", - "windows-targets 0.52.6", + "windows-strings", +] + +[[package]] +name = "windows-future" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f3db6b24b120200d649cd4811b4947188ed3a8d2626f7075146c5d178a9a4a" +dependencies = [ + "windows-core", + "windows-link", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.60.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edb307e42a74fb6de9bf3a02d9712678b22399c87e6fa869d6dfcd8c1b7754e0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0abd1ddbc6964ac14db11c7213d6532ef34bd9aa042c2e5935f59d7908b46a5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" + +[[package]] +name = "windows-numerics" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ce3498fe0aba81e62e477408383196b4b0363db5e0c27646f932676283b43d8" +dependencies = [ + "windows-core", + "windows-link", ] [[package]] name = "windows-result" -version = "0.1.2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +checksum = "7084dcc306f89883455a206237404d3eaf961e5bd7e0f312f7c91f57eb44167f" dependencies = [ - "windows-targets 0.52.6", + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7218c655a553b0bed4426cf54b20d7ba363ef543b52d515b3e48d7fd55318dda" +dependencies = [ + "windows-link", ] [[package]] @@ -1801,6 +1900,15 @@ dependencies = [ "windows_x86_64_msvc 0.53.0", ] +[[package]] +name = "windows-threading" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab47f085ad6932defa48855254c758cdd0e2f2d48e62a34118a268d8f345e118" +dependencies = [ + "windows-link", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" diff --git a/Cargo.toml b/Cargo.toml index bc53c68b..9b8286db 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -103,7 +103,7 @@ all-features = true rustdoc-args = ["--cfg", "docsrs"] [dependencies] -cpal = { version = "0.16", optional = true } +cpal = { git = "https://github.com/RustAudio/cpal", rev = "c9d8e2e18789e305e2d087d65888f06db08bd2ba", optional = true } dasp_sample = "0.11.0" claxon = { version = "0.4.2", optional = true } hound = { version = "3.5", optional = true } diff --git a/examples/microphone.rs b/examples/microphone.rs index c3e55918..97419327 100644 --- a/examples/microphone.rs +++ b/examples/microphone.rs @@ -13,7 +13,7 @@ fn main() -> Result<(), Box> { .prompt()?; let input = MicrophoneBuilder::new() - .device(input)? + .device(input.into_inner())? .default_config()? .open_stream()?; diff --git a/src/microphone.rs b/src/microphone.rs index eb98985d..12b769a1 100644 --- a/src/microphone.rs +++ b/src/microphone.rs @@ -91,7 +91,7 @@ //! //! // Use a specific device (e.g., the second one) //! let mic = MicrophoneBuilder::new() -//! .device(inputs[1].clone())? +//! .device(inputs[1].clone().into_inner())? //! .default_config()? //! .open_stream()?; //! # Ok(()) @@ -130,9 +130,10 @@ pub struct Input { inner: cpal::Device, } -impl From for cpal::Device { - fn from(val: Input) -> Self { - val.inner +impl Input { + /// Consumes the input and returns the inner device. + pub fn into_inner(self) -> cpal::Device { + self.inner } } diff --git a/src/microphone/builder.rs b/src/microphone/builder.rs index deac72da..b4687fad 100644 --- a/src/microphone/builder.rs +++ b/src/microphone/builder.rs @@ -128,7 +128,7 @@ where /// ```no_run /// # use rodio::microphone::{MicrophoneBuilder, available_inputs}; /// let input = available_inputs()?.remove(2); - /// let builder = MicrophoneBuilder::new().device(input)?; + /// let builder = MicrophoneBuilder::new().device(input.into_inner())?; /// # Ok::<(), Box>(()) /// ``` pub fn device( From 4f6de33383c71eb0f4354f2ccf2d7be3361e337e Mon Sep 17 00:00:00 2001 From: Philpax Date: Thu, 9 Oct 2025 01:31:46 +0200 Subject: [PATCH 2/7] chore: update cpal ref --- Cargo.lock | 13 ++++++++++++- Cargo.toml | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 321f0db9..8dd460c6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -197,7 +197,7 @@ dependencies = [ [[package]] name = "cpal" version = "0.16.0" -source = "git+https://github.com/RustAudio/cpal?rev=c9d8e2e18789e305e2d087d65888f06db08bd2ba#c9d8e2e18789e305e2d087d65888f06db08bd2ba" +source = "git+https://github.com/RustAudio/cpal?rev=b7c0eace84974780571a138bae2ae5c56fda783d#b7c0eace84974780571a138bae2ae5c56fda783d" dependencies = [ "alsa", "coreaudio-rs", @@ -212,6 +212,7 @@ dependencies = [ "num-traits", "objc2", "objc2-audio-toolbox", + "objc2-avf-audio", "objc2-core-audio", "objc2-core-audio-types", "objc2-core-foundation", @@ -753,6 +754,16 @@ dependencies = [ "objc2-foundation", ] +[[package]] +name = "objc2-avf-audio" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfc1d11521c211a7ebe17739fc806719da41f56c6b3f949d9861b459188ce910" +dependencies = [ + "objc2", + "objc2-foundation", +] + [[package]] name = "objc2-core-audio" version = "0.3.1" diff --git a/Cargo.toml b/Cargo.toml index 9b8286db..9bb30432 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -103,7 +103,7 @@ all-features = true rustdoc-args = ["--cfg", "docsrs"] [dependencies] -cpal = { git = "https://github.com/RustAudio/cpal", rev = "c9d8e2e18789e305e2d087d65888f06db08bd2ba", optional = true } +cpal = { git = "https://github.com/RustAudio/cpal", rev = "b7c0eace84974780571a138bae2ae5c56fda783d", optional = true } dasp_sample = "0.11.0" claxon = { version = "0.4.2", optional = true } hound = { version = "3.5", optional = true } From 929edd0134289bd733129eba39bc41177ee275e2 Mon Sep 17 00:00:00 2001 From: Philpax Date: Tue, 14 Oct 2025 14:21:30 +0200 Subject: [PATCH 3/7] feat: enable U24 support from cpal --- src/microphone.rs | 3 +-- src/stream.rs | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/microphone.rs b/src/microphone.rs index 12b769a1..12b4432c 100644 --- a/src/microphone.rs +++ b/src/microphone.rs @@ -272,8 +272,7 @@ impl Microphone { I64, i64; U8, u8; U16, u16; - // TODO: uncomment when https://github.com/RustAudio/cpal/pull/1011 is merged - // U24, cpal::U24; + U24, cpal::U24; U32, u32; U64, u64 ) diff --git a/src/stream.rs b/src/stream.rs index fc014b8f..d1df8012 100644 --- a/src/stream.rs +++ b/src/stream.rs @@ -515,8 +515,7 @@ impl OutputStream { I64, i64; U8, u8; U16, u16; - // TODO: uncomment when https://github.com/RustAudio/cpal/pull/1011 is merged - // U24, U24; + U24, cpal::U24; U32, u32; U64, u64 ); From bb397077449e7a01c1aac6b2d3979412f0fc5d67 Mon Sep 17 00:00:00 2001 From: Philpax Date: Tue, 14 Oct 2025 14:24:22 +0200 Subject: [PATCH 4/7] chore: update cpal ref, remove oboe backend support --- Cargo.lock | 2 +- Cargo.toml | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8dd460c6..f0429b3c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -197,7 +197,7 @@ dependencies = [ [[package]] name = "cpal" version = "0.16.0" -source = "git+https://github.com/RustAudio/cpal?rev=b7c0eace84974780571a138bae2ae5c56fda783d#b7c0eace84974780571a138bae2ae5c56fda783d" +source = "git+https://github.com/RustAudio/cpal?rev=a8269d3c993f7d375d4655b53d3437429d4f6bd8#a8269d3c993f7d375d4655b53d3437429d4f6bd8" dependencies = [ "alsa", "coreaudio-rs", diff --git a/Cargo.toml b/Cargo.toml index 9bb30432..174f6b23 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,8 +46,6 @@ noise = ["rand", "rand_distr"] # # Enable WebAssembly support for web browsers wasm-bindgen = ["cpal/wasm-bindgen"] -# Use shared C++ stdlib on Android (reduces APK size, fixes linking issues) -cpal-shared-stdcxx = ["cpal/oboe-shared-stdcxx"] # To decode an audio source with Rodio, you need to enable the appropriate features for *both* the # demuxer and the decoder. @@ -103,7 +101,7 @@ all-features = true rustdoc-args = ["--cfg", "docsrs"] [dependencies] -cpal = { git = "https://github.com/RustAudio/cpal", rev = "b7c0eace84974780571a138bae2ae5c56fda783d", optional = true } +cpal = { git = "https://github.com/RustAudio/cpal", rev = "a8269d3c993f7d375d4655b53d3437429d4f6bd8", optional = true } dasp_sample = "0.11.0" claxon = { version = "0.4.2", optional = true } hound = { version = "3.5", optional = true } From c2597edb0769d4dde007a79d02b26b6ff7e7fb92 Mon Sep 17 00:00:00 2001 From: Roderick van Domburg Date: Wed, 10 Dec 2025 15:42:32 +0100 Subject: [PATCH 5/7] chore: update cpal to new rev and adapt API changes --- Cargo.lock | 11 ++++------- Cargo.toml | 2 +- src/microphone.rs | 18 ++++++++++++++++-- src/microphone/builder.rs | 29 ++++++++++++++++++++--------- src/microphone/config.rs | 8 ++++---- src/stream.rs | 15 ++++++++++----- src/wav_output.rs | 2 +- 7 files changed, 56 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f0429b3c..ed4cc456 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -197,7 +197,7 @@ dependencies = [ [[package]] name = "cpal" version = "0.16.0" -source = "git+https://github.com/RustAudio/cpal?rev=a8269d3c993f7d375d4655b53d3437429d4f6bd8#a8269d3c993f7d375d4655b53d3437429d4f6bd8" +source = "git+https://github.com/RustAudio/cpal?rev=e32ee65a5335301553cc9650b949b868f922d748#e32ee65a5335301553cc9650b949b868f922d748" dependencies = [ "alsa", "coreaudio-rs", @@ -205,7 +205,7 @@ dependencies = [ "jni", "js-sys", "libc", - "mach2 0.5.0", + "mach2 0.6.0", "ndk", "ndk-context", "num-derive", @@ -574,12 +574,9 @@ dependencies = [ [[package]] name = "mach2" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a1b95cd5421ec55b445b5ae102f5ea0e768de1f82bd3001e11f426c269c3aea" -dependencies = [ - "libc", -] +checksum = "dae608c151f68243f2b000364e1f7b186d9c29845f7d2d85bd31b9ad77ad552b" [[package]] name = "memchr" diff --git a/Cargo.toml b/Cargo.toml index 174f6b23..82a48166 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -101,7 +101,7 @@ all-features = true rustdoc-args = ["--cfg", "docsrs"] [dependencies] -cpal = { git = "https://github.com/RustAudio/cpal", rev = "a8269d3c993f7d375d4655b53d3437429d4f6bd8", optional = true } +cpal = { git = "https://github.com/RustAudio/cpal", rev = "e32ee65a5335301553cc9650b949b868f922d748", optional = true } dasp_sample = "0.11.0" claxon = { version = "0.4.2", optional = true } hound = { version = "3.5", optional = true } diff --git a/src/microphone.rs b/src/microphone.rs index 12b4432c..8e0594ea 100644 --- a/src/microphone.rs +++ b/src/microphone.rs @@ -140,14 +140,28 @@ impl Input { impl fmt::Debug for Input { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("Device") - .field("inner", &self.inner.name().unwrap_or("unknown".to_string())) + .field( + "inner", + &self + .inner + .description() + .ok() + .map_or("unknown".to_string(), |d| d.name().to_string()), + ) .finish() } } impl fmt::Display for Input { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.inner.name().unwrap_or("unknown".to_string())) + write!( + f, + "{}", + self.inner + .description() + .ok() + .map_or("unknown".to_string(), |d| d.name().to_string()) + ) } } diff --git a/src/microphone/builder.rs b/src/microphone/builder.rs index b4687fad..cc10b383 100644 --- a/src/microphone/builder.rs +++ b/src/microphone/builder.rs @@ -76,10 +76,11 @@ where f.debug_struct("MicrophoneBuilder") .field( "device", - &self - .device - .as_ref() - .map(|d| d.0.name().unwrap_or("unknown".to_string())), + &self.device.as_ref().map(|d| { + d.0.description() + .ok() + .map_or("unknown".to_string(), |d| d.name().to_string()) + }), ) .field("config", &self.config) .finish() @@ -140,7 +141,10 @@ where .supported_input_configs() .map_err(|source| Error::InputConfigs { source, - device_name: device.name().unwrap_or_else(|_| "unknown".to_string()), + device_name: device + .description() + .ok() + .map_or("unknown".to_string(), |d| d.name().to_string()), })? .collect(); Ok(MicrophoneBuilder { @@ -169,8 +173,9 @@ where .map_err(|source| Error::InputConfigs { source, device_name: default_device - .name() - .unwrap_or_else(|_| "unknown".to_string()), + .description() + .ok() + .map_or("unknown".to_string(), |d| d.name().to_string()), })? .collect(); Ok(MicrophoneBuilder { @@ -203,7 +208,10 @@ where .default_input_config() .map_err(|source| Error::DefaultInputConfig { source, - device_name: device.name().unwrap_or_else(|_| "unknown".to_string()), + device_name: device + .description() + .ok() + .map_or("unknown".to_string(), |d| d.name().to_string()), })? .into(); @@ -266,7 +274,10 @@ where .any(|range| config.supported_given(range)) { Err(Error::UnsupportedByDevice { - device_name: device.name().unwrap_or_else(|_| "unknown".to_string()), + device_name: device + .description() + .ok() + .map_or("unknown".to_string(), |d| d.name().to_string()), }) } else { Ok(()) diff --git a/src/microphone/config.rs b/src/microphone/config.rs index 21c6d5c5..923a77d4 100644 --- a/src/microphone/config.rs +++ b/src/microphone/config.rs @@ -34,8 +34,8 @@ impl InputConfig { buffer_ok && self.channel_count.get() == supported.channels() && self.sample_format == supported.sample_format() - && self.sample_rate.get() <= supported.max_sample_rate().0 - && self.sample_rate.get() >= supported.min_sample_rate().0 + && self.sample_rate.get() <= supported.max_sample_rate() + && self.sample_rate.get() >= supported.min_sample_rate() } pub(crate) fn with_f32_samples(&self) -> Self { @@ -47,7 +47,7 @@ impl InputConfig { pub(crate) fn stream_config(&self) -> cpal::StreamConfig { cpal::StreamConfig { channels: self.channel_count.get(), - sample_rate: cpal::SampleRate(self.sample_rate.get()), + sample_rate: self.sample_rate.get(), buffer_size: self.buffer_size, } } @@ -62,7 +62,7 @@ impl From for InputConfig { Self { channel_count: NonZero::new(value.channels()) .expect("A supported config never has 0 channels"), - sample_rate: NonZero::new(value.sample_rate().0) + sample_rate: NonZero::new(value.sample_rate()) .expect("A supported config produces samples"), buffer_size, sample_format: value.sample_format(), diff --git a/src/stream.rs b/src/stream.rs index d1df8012..21b8756c 100644 --- a/src/stream.rs +++ b/src/stream.rs @@ -131,7 +131,12 @@ impl OutputStreamConfig { impl core::fmt::Debug for OutputStreamBuilder { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let device = if let Some(device) = &self.device { - "Some(".to_owned() + device.name().as_deref().unwrap_or("UnNamed") + ")" + "Some(".to_owned() + + &device + .description() + .ok() + .map_or("UnNamed".to_string(), |d| d.name().to_string()) + + ")" } else { "None".to_owned() }; @@ -307,7 +312,7 @@ where self.config = OutputStreamConfig { channel_count: NonZero::new(config.channels()) .expect("no valid cpal config has zero channels"), - sample_rate: NonZero::new(config.sample_rate().0) + sample_rate: NonZero::new(config.sample_rate()) .expect("no valid cpal config has zero sample rate"), sample_format: config.sample_format(), ..Default::default() @@ -320,7 +325,7 @@ where self.config = OutputStreamConfig { channel_count: NonZero::new(config.channels) .expect("no valid cpal config has zero channels"), - sample_rate: NonZero::new(config.sample_rate.0) + sample_rate: NonZero::new(config.sample_rate) .expect("no valid cpal config has zero sample rate"), buffer_size: config.buffer_size, ..self.config @@ -390,7 +395,7 @@ impl From<&OutputStreamConfig> for StreamConfig { fn from(config: &OutputStreamConfig) -> Self { cpal::StreamConfig { channels: config.channel_count.get() as cpal::ChannelCount, - sample_rate: cpal::SampleRate(config.sample_rate.get()), + sample_rate: config.sample_rate.get(), buffer_size: config.buffer_size, } } @@ -538,7 +543,7 @@ pub fn supported_output_configs( let max_rate = sf.max_sample_rate(); let min_rate = sf.min_sample_rate(); let mut formats = vec![sf.with_max_sample_rate()]; - let preferred_rate = cpal::SampleRate(HZ_44100.get()); + let preferred_rate = HZ_44100.get(); if preferred_rate < max_rate && preferred_rate > min_rate { formats.push(sf.with_sample_rate(preferred_rate)) } diff --git a/src/wav_output.rs b/src/wav_output.rs index ddf40f7b..bdf3bf03 100644 --- a/src/wav_output.rs +++ b/src/wav_output.rs @@ -46,7 +46,7 @@ pub fn wav_to_file( /// # Example /// ```rust /// # use rodio::static_buffer::StaticSamplesBuffer; -/// # use rodio::collect_to_wav; +/// # use rodio::wav_to_writer; /// # const SAMPLES: [rodio::Sample; 5] = [0.0, 1.0, 2.0, 3.0, 4.0]; /// # let source = StaticSamplesBuffer::new( /// # 1.try_into().unwrap(), From 1a66725ce9ecfd7a89ba780e249477cdd8c644e0 Mon Sep 17 00:00:00 2001 From: Roderick van Domburg Date: Wed, 10 Dec 2025 16:00:15 +0100 Subject: [PATCH 6/7] feat: filter actionable stream errors in example --- examples/error_callback.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/examples/error_callback.rs b/examples/error_callback.rs index 2e70d4eb..ab335583 100644 --- a/examples/error_callback.rs +++ b/examples/error_callback.rs @@ -14,8 +14,11 @@ fn main() -> Result<(), Box> { let stream_handle = rodio::OutputStreamBuilder::from_device(default_device)? .with_error_callback(move |err| { - // Filter for where err is a DeviceNotAvailable error. - if let cpal::StreamError::DeviceNotAvailable = err { + // Filter for where err is an actionable error. + if matches!( + err, + cpal::StreamError::DeviceNotAvailable | cpal::StreamError::StreamInvalidated + ) { if let Err(e) = tx.send(err) { eprintln!("Error emitting StreamError: {e}"); } @@ -31,9 +34,10 @@ fn main() -> Result<(), Box> { mixer.add(wave); if let Ok(err) = rx.recv_timeout(Duration::from_secs(30)) { - // Here we print the error that was emitted by the error callback. - // but in a real application we may want to destroy the stream and - // try to reopen it, either with the same device or a different one. + // Here we received an error that requires action from the error callback. + // In a real application you would destroy the stream and try to reopen it, + // either with the same device (for StreamInvalidated) or a different device + // (for DeviceNotAvailable). eprintln!("Error with stream {err}"); } From a031c6b71627f64d80f97f0abb303d5a452e0919 Mon Sep 17 00:00:00 2001 From: Roderick van Domburg Date: Sat, 20 Dec 2025 20:32:34 +0100 Subject: [PATCH 7/7] chore: upgrade cpal to released v0.17 --- CHANGELOG.md | 1 + Cargo.lock | 14 +++++++++----- Cargo.toml | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c9df654..48573720 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `Blue` noise generator uses uniform instead of Gaussian noise for better performance. - `Gaussian` noise generator has standard deviation of 0.6 for perceptual equivalence. - `Velvet` noise generator takes density in Hz as `usize` instead of `f32`. +- Upgrade `cpal` to v0.17. ## Version [0.21.1] (2025-07-14) diff --git a/Cargo.lock b/Cargo.lock index ed4cc456..e870c79a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -196,8 +196,9 @@ dependencies = [ [[package]] name = "cpal" -version = "0.16.0" -source = "git+https://github.com/RustAudio/cpal?rev=e32ee65a5335301553cc9650b949b868f922d748#e32ee65a5335301553cc9650b949b868f922d748" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58ceb96745bc9bbcf1f7eb1267ee03045275fa0cc82a4b34d8534ffdcaf657c3" dependencies = [ "alsa", "coreaudio-rs", @@ -205,7 +206,7 @@ dependencies = [ "jni", "js-sys", "libc", - "mach2 0.6.0", + "mach2 0.5.0", "ndk", "ndk-context", "num-derive", @@ -574,9 +575,12 @@ dependencies = [ [[package]] name = "mach2" -version = "0.6.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dae608c151f68243f2b000364e1f7b186d9c29845f7d2d85bd31b9ad77ad552b" +checksum = "6a1b95cd5421ec55b445b5ae102f5ea0e768de1f82bd3001e11f426c269c3aea" +dependencies = [ + "libc", +] [[package]] name = "memchr" diff --git a/Cargo.toml b/Cargo.toml index 82a48166..5c3cd2e0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -101,7 +101,7 @@ all-features = true rustdoc-args = ["--cfg", "docsrs"] [dependencies] -cpal = { git = "https://github.com/RustAudio/cpal", rev = "e32ee65a5335301553cc9650b949b868f922d748", optional = true } +cpal = { version = "0.17.0", optional = true } dasp_sample = "0.11.0" claxon = { version = "0.4.2", optional = true } hound = { version = "3.5", optional = true }