RustAudio / cpal

Cross-platform audio I/O library in pure Rust
Apache License 2.0
2.69k stars 355 forks source link

Alsa output opened incorrectly #564

Closed roderickvd closed 3 years ago

roderickvd commented 3 years ago

I'm running into strange behavior running librespot-org/librespot#660 on the Rodio backend and Alsa host. On the current cpal master, output is opened four times. Last time is with incorrect parameters causing incorrect playback.

Regardless of the --format setting librespot is launched with (F32 or S16): First time opening is with FloatLE, 44100 Hz and 2 channels (as expected). Second time is FloatLE, 4294967295 Hz and 2 channels. Third time is FloatLE, 44100 Hz and 2 channels. Fourth time is FloatLE, 4000 Hz and 2 channels.

This behavior is triggered by lines 194-201 in stream.rs of Rodio:

self.new_output_stream_with_format(default_format)
            .unwrap_or_else(|err| {
                // look through all supported formats to see if another works
                supported_output_formats(self)
                    .filter_map(|format| self.new_output_stream_with_format(format).ok())
                    .next()
                    .ok_or(err)
                    .expect("build_output_stream failed with all supported formats")

The first three iterations trigger the unwrap_or_else closure because cpal fails to prepare the Alsa stream. This line fails:

https://github.com/RustAudio/cpal/blob/fbc0f71e21bb7491797138fe107d27034b3c8e08/src/host/alsa/mod.rs#L260

I am stumped why this fails. This is Alsa on a Raspberry Pi 3 Model B+, running 32-bit Raspian 10 (Linux 5.10.17-v7+) over I2S to an external DAC. aplay --dump-hw-params gives:

ACCESS:  MMAP_INTERLEAVED MMAP_NONINTERLEAVED MMAP_COMPLEX RW_INTERLEAVED RW_NONINTERLEAVED
FORMAT:  S8 U8 S16_LE S16_BE U16_LE U16_BE S24_LE S24_BE U24_LE U24_BE S32_LE S32_BE U32_LE U32_BE FLOAT_LE FLOAT_BE FLOAT64_LE FLOAT64_BE MU_LAW A_LAW IMA_ADPCM S20_LE S20_BE U20_LE U20_BE S24_3LE S24_3BE U24_3LE U24_3BE S20_3LE S20_3BE U20_3LE U20_3BE S18_3LE S18_3BE U18_3LE U18_3BE
SUBFORMAT:  STD
SAMPLE_BITS: [4 64]
FRAME_BITS: [4 640000]
CHANNELS: [1 10000]
RATE: [4000 4294967295)
PERIOD_TIME: (166 8192000]
PERIOD_SIZE: (0 4294967295)
PERIOD_BYTES: (0 4294967295)
PERIODS: (0 4294967295]
BUFFER_TIME: [1 4294967295]
BUFFER_SIZE: [1 4294967294]
BUFFER_BYTES: [1 4294967295]
TICK_TIME: ALL

Indeed this is reflected as SupportedStreamConfig. Using the native Alsa backend in librespot works just fine for all formats F32, S32, S24, S24_3 and S16 so the Alsa soundcard itself is working fine.

Applying #520 by @alexmoon fixes one issue, being that the output is now opened once and correctly, but introduces another issue: after opening, no sound is played and the librespot player thread hangs when writing.

Again I've been banging my head trying to get this down for several nights of debugging now. Any suggestions?

roderickvd commented 3 years ago

This seems fixed on cpal 0.13.3 and/or Rodio 0.13.1.