diff --git a/CHANGELOG.md b/CHANGELOG.md index 83fd100f..bf75382a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,8 +36,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [connect] Fix step size on volume up/down events - [playback] Incorrect `PlayerConfig::default().normalisation_threshold` caused distortion when using dynamic volume normalisation downstream - [playback] Fix `log` and `cubic` volume controls to be mute at zero volume +- [playback] Fix `S24_3` format on big-endian systems - [playback] `alsamixer`: make `cubic` consistent between cards that report minimum volume as mute, and cards that report some dB value - [playback] `alsamixer`: make `--volume-ctrl {linear|log}` work as expected +- [playback] `alsa`, `gstreamer`, `pulseaudio`: always output in native endianness ## [0.2.0] - 2021-05-04 diff --git a/playback/src/audio_backend/alsa.rs b/playback/src/audio_backend/alsa.rs index b5deb2eb..8a590c6f 100644 --- a/playback/src/audio_backend/alsa.rs +++ b/playback/src/audio_backend/alsa.rs @@ -45,8 +45,12 @@ fn open_device(dev_name: &str, format: AudioFormat) -> Result<(PCM, Frames), Box AudioFormat::F32 => Format::float(), AudioFormat::S32 => Format::s32(), AudioFormat::S24 => Format::s24(), - AudioFormat::S24_3 => Format::S243LE, AudioFormat::S16 => Format::s16(), + + #[cfg(target_endian = "little")] + AudioFormat::S24_3 => Format::S243LE, + #[cfg(target_endian = "big")] + AudioFormat::S24_3 => Format::S243BE, }; // http://www.linuxjournal.com/article/6735?page=0,1#N0x19ab2890.0x19ba78d8 diff --git a/playback/src/audio_backend/gstreamer.rs b/playback/src/audio_backend/gstreamer.rs index b5273102..bd76863c 100644 --- a/playback/src/audio_backend/gstreamer.rs +++ b/playback/src/audio_backend/gstreamer.rs @@ -34,9 +34,14 @@ impl Open for GstreamerSink { let sample_size = format.size(); let gst_bytes = 2048 * sample_size; + #[cfg(target_endian = "little")] + const ENDIANNESS: &str = "LE"; + #[cfg(target_endian = "big")] + const ENDIANNESS: &str = "BE"; + let pipeline_str_preamble = format!( - "appsrc caps=\"audio/x-raw,format={}LE,layout=interleaved,channels={},rate={}\" block=true max-bytes={} name=appsrc0 ", - gst_format, NUM_CHANNELS, SAMPLE_RATE, gst_bytes + "appsrc caps=\"audio/x-raw,format={}{},layout=interleaved,channels={},rate={}\" block=true max-bytes={} name=appsrc0 ", + gst_format, ENDIANNESS, NUM_CHANNELS, SAMPLE_RATE, gst_bytes ); // no need to dither twice; use librespot dithering instead let pipeline_str_rest = r#" ! audioconvert dithering=none ! autoaudiosink"#; diff --git a/playback/src/audio_backend/pulseaudio.rs b/playback/src/audio_backend/pulseaudio.rs index 1298cd7c..75bd49de 100644 --- a/playback/src/audio_backend/pulseaudio.rs +++ b/playback/src/audio_backend/pulseaudio.rs @@ -23,11 +23,11 @@ impl Open for PulseAudioSink { // PulseAudio calls S24 and S24_3 different from the rest of the world let pulse_format = match format { - AudioFormat::F32 => pulse::sample::Format::F32le, - AudioFormat::S32 => pulse::sample::Format::S32le, - AudioFormat::S24 => pulse::sample::Format::S24_32le, - AudioFormat::S24_3 => pulse::sample::Format::S24le, - AudioFormat::S16 => pulse::sample::Format::S16le, + AudioFormat::F32 => pulse::sample::Format::FLOAT32NE, + AudioFormat::S32 => pulse::sample::Format::S32NE, + AudioFormat::S24 => pulse::sample::Format::S24_32NE, + AudioFormat::S24_3 => pulse::sample::Format::S24NE, + AudioFormat::S16 => pulse::sample::Format::S16NE, _ => { unimplemented!("PulseAudio currently does not support {:?} output", format) } diff --git a/playback/src/convert.rs b/playback/src/convert.rs index ddeff2fc..37e53fc0 100644 --- a/playback/src/convert.rs +++ b/playback/src/convert.rs @@ -8,8 +8,12 @@ pub struct i24([u8; 3]); impl i24 { fn from_s24(sample: i32) -> Self { // trim the padding in the most significant byte - let [a, b, c, _d] = sample.to_le_bytes(); - i24([a, b, c]) + #[allow(unused_variables)] + let [a, b, c, d] = sample.to_ne_bytes(); + #[cfg(target_endian = "little")] + return Self([a, b, c]); + #[cfg(target_endian = "big")] + return Self([b, c, d]); } }