-
Notifications
You must be signed in to change notification settings - Fork 470
Description
Hello, thanks for creating 'cpal'. I have an issue with v0.13.4 on Fedora 34.
Here is what happens when I run the feedback.rs example, from the v0.13.4 tag:
> cargo run --example feedback -- 'sysdefault:CARD=PCH' 'sysdefault:CARD=PCH'
Using input device: "sysdefault:CARD=PCH"
Using output device: "sysdefault:CARD=PCH"
Attempting to build both streams with f32 samples and `StreamConfig { channels: 2, sample_rate: SampleRate(44100), buffer_size: Default }`.
Error: A backend-specific error has occurred: ALSA function 'snd_pcm_sw_params' failed with error 'EINVAL: Invalid argument'
Caused by:
A backend-specific error has occurred: ALSA function 'snd_pcm_sw_params' failed with error 'EINVAL: Invalid argument'
If I use the default audio outputs, then the 'feedback' example works as expected. It breaks when I specify a device.
I can recreate the 'feedback' example with this ALSA command, and it successfully connects the two devices I used above:
> arecord -D 'sysdefault:CARD=PCH' --disable-softvol --rate 48000 --format S32_LE --verbose | aplay -D 'sysdefault:CARD=PCH' --disable-softvol
Recording WAVE 'stdin' : Signed 32 bit Little Endian, Rate 48000 Hz, Mono
Plug PCM: Route conversion PCM (sformat=S32_LE)
Transformation table:
0 <- 0
Its setup is:
stream : CAPTURE
access : RW_INTERLEAVED
format : S32_LE
subformat : STD
channels : 1
rate : 48000
exact rate : 48000 (48000/1)
msbits : 32
buffer_size : 16384
period_size : 1024
period_time : 21333
tstamp_mode : NONE
tstamp_type : MONOTONIC
period_step : 1
avail_min : 1024
period_event : 0
start_threshold : 1
stop_threshold : 16384
silence_threshold: 0
silence_size : 0
boundary : 4611686018427387904
<... snip long log...>
Playing WAVE 'stdin' : Signed 32 bit Little Endian, Rate 48000 Hz, Mono
The problem looks related to the struct we pass to the snd_pcm_sw_params() function. I am running Linux 5.11.20-300.fc34; here's that function in Linux v5.11: https://github.com/torvalds/linux/blob/v5.11/sound/core/pcm_native.c
I can see a few ways to trigger EINVAL. I added some debug prints to cpal:
diff --git a/src/host/alsa/mod.rs b/src/host/alsa/mod.rs
index 908d63c..29c78a9 100644
--- a/src/host/alsa/mod.rs
+++ b/src/host/alsa/mod.rs
@@ -1017,6 +1017,7 @@ fn set_sw_params_from_format(
let period_len = {
let (buffer, period) = pcm_handle.get_params()?;
+ println!("buffer {}, period {}", buffer, period);
if buffer == 0 {
return Err(BackendSpecificError {
description: "initialization resulted in a null buffer".to_string(),
@@ -1036,6 +1037,10 @@ fn set_sw_params_from_format(
sw_params.set_tstamp_mode(true)?;
sw_params.set_tstamp_type(alsa::pcm::TstampType::MonotonicRaw)?;
+ println!("{:?}", sw_params);
+ let mut output = alsa::Output::buffer_open().unwrap();
+ sw_params.dump(&mut output).unwrap();
+ println!("{}", output);
pcm_handle.sw_params(&sw_params)?;
Ok(period_len)
Here's the output:
> cargo run --example feedback -- 'sysdefault:CARD=PCH' 'sysdefault:CARD=PCH'
Finished dev [unoptimized + debuginfo] target(s) in 1.55s
Running `target/debug/examples/feedback 'sysdefault:CARD=PCH' 'sysdefault:CARD=PCH'`
Using input device: "sysdefault:CARD=PCH"
Using output device: "sysdefault:CARD=PCH"
Attempting to build both streams with f32 samples and `StreamConfig { channels: 2, sample_rate: SampleRate(44100), buffer_size: Default }`.
buffer 4704, period 940
SwParams(avail_min: Ok(940) frames, start_threshold: Ok(1) frames, stop_threshold: Ok(4704) frames)
tstamp_mode: ENABLE
tstamp_type: MONOTONIC_RAW
period_step: 1
avail_min: 940
start_threshold: 1
stop_threshold: 4704
silence_threshold: 0
silence_size: 0
boundary: 5296233161787703296
set swparams
Error: A backend-specific error has occurred: ALSA function 'snd_pcm_sw_params' failed with error 'EINVAL: Invalid argument'
Caused by:
A backend-specific error has occurred: ALSA function 'snd_pcm_sw_params' failed with error 'EINVAL: Invalid argument'
Nothing in that sw_params info seems like it would trigger the EINVAL error that I am seeing.