Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Left and right channels seem to be swapped #286

Closed
Keithcat1 opened this issue May 2, 2020 · 5 comments
Closed

Left and right channels seem to be swapped #286

Keithcat1 opened this issue May 2, 2020 · 5 comments

Comments

@Keithcat1
Copy link

I'm on windows 64-bit.
Any audio files seem to play with their left and right channels swapped.

@hugovdm
Copy link

hugovdm commented Jul 30, 2020

Potentially related: I've played with CPAL's "feedback" example (in version 0.12) on my Linux laptop (with ALSA). It seemed like sometimes the channels were swapped, and sometimes they weren't (talking input vs output).

My conclusion: CPAL isn't managing to guarantee (on my Linux laptop with ALSA) that default output and input settings alwayus produces the two channels in the same order. Maybe this CPAL behaviour could be the source of this bug in rodio...

(If swapped, one hears the "alternating left-right" effect quite well, and I didn't always hear it. And dropping either the L or the R channel made the feedback die out quickly, whereas not having them swapped meant consistent slow decay, as expected, for the channel not attenuated - I was generally setting my mixer settings to give between 0.9 and 1.0 end-to-end gain.)

@doylep
Copy link

doylep commented Aug 22, 2020

I am experiencing this issue on Linux as well. I'm happy to work to debug it if someone can point me in the right direction.

@keigen-shu
Copy link

keigen-shu commented Sep 18, 2020

I'm experiencing this issue on Linux too. For me, the output is always swapped.

EDIT: Updated code sample in: #286 (comment)

@tuzz
Copy link
Contributor

tuzz commented Jul 22, 2021

I've opened a pull request ^ that might fix this issue. If someone could kindly check, that would be great. I don't really have access to a linux/windows machine. Thanks

@est31 est31 closed this as completed Jul 24, 2021
@keigen-shu
Copy link

Hello,

Following PR #390, while I was able reproduce the issue fixed by the PR, I still had issues with the sound output after the change.

So I downloaded the source code for rodio and cpal to try to find the cause. I've tested various methods of setting up the audio output and was able to narrow down the issue to Sink::try_new(). I've updated the test code to retry repeatedly to make the issue more prominent. On my setup (Arch Linux x86_64; Ryzen 5600X; B550 chipset) with the sound mostly going to the wrong channel about 70% of the time, and to the correct channel 30% of time.

extern crate rodio;

use rodio::source::Source;
use rodio::cpal;
use rodio::cpal::traits::HostTrait;
use rodio::cpal::traits::DeviceTrait;

fn main() {
    let device = cpal::default_host().default_output_device().expect("failed to find output device");
    let config = device.default_output_config().unwrap();

    let sample_rate = config.sample_rate().0;

    let (stream, stream_handle) = rodio::OutputStream::try_from_device(&device).unwrap();

    // left = sine wave; right = silence.
    let mut lt_ch = sine_wave(sample_rate);
    let mut rt_ch = vec![0.0; lt_ch.len()];

    let data: Vec<f32> = lt_ch.iter().zip(rt_ch.iter()).flat_map(|(&a, &b)| vec![a, b]).collect();

    for i in 0..50 {
        let buffer = rodio::buffer::SamplesBuffer::new(2, sample_rate, data.clone());
        let sink = rodio::Sink::try_new(&stream_handle).unwrap();
        sink.append(buffer.repeat_infinite());
        std::thread::sleep_ms(200);
    }
}

fn sine_wave(sample_rate: u32) -> Vec<f32> {
    let OSC_FREQ  : f32   = 440.0;
    let OSC_OMEGA : f32   = std::f32::consts::TAU * OSC_FREQ as f32;
    let OSC_PERIOD: usize = (sample_rate as f32 / OSC_FREQ) as usize;
    let OSC_GAIN  : f32   = 0.5;

    (0 .. OSC_PERIOD).map(|i| f32::sin(OSC_OMEGA * (i as f32 / sample_rate as f32)) * OSC_GAIN).collect()
}

While debugging the rodio, I found that SourcesQueueOutput does not guarantee that samples are output with the correct frame boundary. Furthermore, it creates a hardcoded 441 samples of silence as a buffer when there are no sources. I think this causes sources to be output with the wrong frame boundary when they are appended to the sink.

For the stereo output setup I was testing with, changing the zero buffer to an even counted size seems to mitigate the problem. Though for a proper fix, I think frame boundary guarantees needs to be factored into the API.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants