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

Why is build_output_stream data length different every time? #833

Open
zhpixel517 opened this issue Feb 8, 2024 · 1 comment
Open

Why is build_output_stream data length different every time? #833

zhpixel517 opened this issue Feb 8, 2024 · 1 comment

Comments

@zhpixel517
Copy link

I am trying to build a network audio streaming application in rust and I have been using cpal to do it. I am going to have an mpsc thread that is in charge of buffering all the received samples from the network, and will then pass the received audio samples to the real-time thread inside the closure of build_output_stream. Something like this:

let stream = output_device.build_output_stream(
   &config.into(),
   move |data: &mut [f32], _: &_|  {

          data = thread_receiver.recv() // or something like that

   },
   move |err| {
        eprintln!("Output error: {:?}", err);
    },
    None 
).unwrap();

I am using this on a laptop running Ubuntu.

The tricky part is that the length of the data array as passed in from the closure is different every time, which kind of throws a wrench into my existing approach of buffering the received samples. If I were to put a println("{:?}", data.length); it would output a different number every time the closure runs.

Why does build_output_stream have this behavior, and what can I do about it?

@karasikq
Copy link

@zhpixel517 Hi, that's because you using ALSA as output backend. I'm pretty sure that SupportedBufferSize value inside your config is something like that: Range { min: 1, max: 4194304 }. And as result your data buffer always changes. I don't really know who produce this behavior cpal or ALSA, but when I use portaudio (c++) + ALSA everything was ok. Some solutions:

  • receive only needed number of sample (like .recv(data.len())
  • create external FIFO buffer, receive any number of samples, output only data.len()
  • write optional pipewire backend for CPAL :)

Some observation: if you pass to config your specified buffer size(for example 2048), in most of cases(or always) data.len() will be LESS than 2048

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

2 participants