Open xasopheno opened 4 years ago
Tested this on osx and it functions as it would be expected. On my Arch system, I'm using ALSA.
Can confirm, I also noticed this recently on ALSA (on NixOS).
@mitchmindtree can you point me in the direction of the problem? I'm happy to dig into if you can give me an idea where to start.
I think I would start by checking how the StreamConfig
's buffer_size
field gets passed through to and used by the ALSA backend, and seeing if anything looks suspicious there.
I would then maybe look for documentation and example demonstrations of specifying the buffer size in ALSA and see if there's anything we are missing or doing incorrectly.
Support for buffer sizes was only introduced recently in https://github.com/RustAudio/cpal/pull/401.
Hope this helps a little bit!
Thank you. That helps a lot - I'll take a look. The first buffer seems to be requested correctly, but then the following buffers are of seemingly random sizes.
I believe there are multiple (possible) factors at work here:
Right now, the way the ALSA worker threads in cpal work is as follows:
pollfd()
the file descriptor associated with the stream, until it is ready for reading/writingThis means, in general, that every call to the callback will receive a differently sized buffer, the size of which will depend on exactly when the worker thread queries the available buffer space. It should average to close to the period_len
, but will certainly not be consistent as there can be variation on the order of milliseconds in when the thread wakes up.
In my opinion, a better approach would be to allocate a buffer sized to period_len
up front. Then (for a playback stream) pass that whole buffer to the callback at once, write it into ALSA's buffer as space becomes available, only making another call to the callback once the whole buffer has been written out. That ensures the callback gets a consistently sized buffer and is called at a regular interval (on average).
I have a rewrite of the ALSA worker threads that incorporates this change, among other changes that fix some various bugs I've been experiencing with the current implementation, that I plan to submit as a pull request after #520 is merged.
This all sounds great. After it's merged, I think I'd be able to transition WereSoCool from portaudio to cpal. Thank you for taking the time to work on it.
Hi @alexmoon, #582 (which is a rebase of #520) has been merged. That should unblock your plan for a rewrite of the ALSA worker threads.
In fact, I've taken your branch https://github.com/RustAudio/cpal/compare/master...alexmoon:alsa-worker and rebased it on cpal master: https://github.com/RustAudio/cpal/compare/master...strohel:alsa-worker The last extra commit is my attempt to make user-visible behaviour consistent with other backends, but may be off. With it applied, I get buffer sizes exactly as requested.
If you want to drive that effort that would be cool. If not, I can submit that as a PR myself once I familiarize myself with the code.
What can be done to help making this progress?
Can confirm the problem with Pipewire and the Alsa drop-in replacement ... the blocksize isn't as random as in the original post, but the buffer size changes from the first to the next block.
For those who are still struggling with this, if you are using Pipewire, there's a way to force buffer size and sample rate through terminal.
pw-metadata -n settings
returns current settings
pw-metadata -n settings 0 clock.force-quantum 1024
forces buffer size to 1024 samples
pw-metadata -n settings 0 clock.force-rate 44100
forces sample rate to 44100 Hz
I don't know how this could be implemented in cpal, but after playing a bit with buffer_size
values in my StreamConfig
, I've finally managed to get a fixed buffer size.
For further reading, this thread contains a lot of useful information.
I'd like to switch to cpal from rust-portaudio, but I'm unable to reproduce the same behavior.
When using the
beep.rs
example. When I set the buffer size via the config like this:and then inspect the size of the output buffer length, these are the lengths I see.
Is there a way for me to guarantee a fixed buffer size?
I am on Arch Linux.
Thank you! Danny