Skip to content

Conversation

abique
Copy link
Contributor

@abique abique commented Sep 24, 2024

With ALSA, the buffer size is nperiod * period_size. We want 2 periods ideally.
The default is now set to 1024 samples which is a reasonable default, yet still too large for real-time audio.
Also the default value uses the same code path as custom values.

Fixes #913
Depends on #915 for successful compilation.
Replaces #914

With ALSA, the buffer size is `nperiod * period_size`.
We want 2 periods ideally.

The default is now set to 1024 samples which is a reasonable default,
yet still too large for real-time audio.

The default value now uses the same code path as custom values.

Fixes RustAudio#913
@abique
Copy link
Contributor Author

abique commented Nov 4, 2024

It is now a month that this PR is opened.
Can someone review it please?

Copy link

@SolarLiner SolarLiner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no rights to cpal, so this is symbolic, but having implemented a ALSA backend for my interflow crate, those changes are small enough that there's no worry to merge this.

@abique
Copy link
Contributor Author

abique commented Jan 23, 2025

@est31 Hi, any chance this PR gets merged or closed with a comment?
Thanks.

@mbernat
Copy link

mbernat commented Jun 19, 2025

Hey, I tested this PR and I don't think it works as expected because the PR is not explicitly setting the buffer size at all and I received unexpectedly huge buffers (~1MB) whereas with fixed buffer setting I'm expecting to get a buffer of that exact size.

Full disclosure: we are using alsa's pipewire device and we were struggling with getting buffers of the right size. Because of the former v / 4 period code we were getting buffers quarter the expected size. I have found no combination of settings that would produce correctly sized buffers but it should be possible because we can get those when using PortAudio. But PortAudio has a very complex logic for setting alsa parameters, so I'm not sure how exactly they do it.

@abique
Copy link
Contributor Author

abique commented Jun 19, 2025

Buffer size isn't relevant.
What's important is the period size and the number of periods.

@mbernat
Copy link

mbernat commented Jun 19, 2025

Buffer size isn't relevant.

Can you elaborate? Are you perhaps suggesting that the buffer contains a period size worth of actual samples and the rest is just junk that can be ignored?

We use a webrtc processor for AEC and it seems to require fixed sized buffers. We tried doing buffering ourselves on top of non-fixed buffers given to us by cpal but that introduced timing jitter that prevented AEC to work correctly.

With portaudio we get fixed size buffers and AEC works correctly. To be sure, I'm a beginner when it comes to audio, so it's very much possible I misunderstand some core concepts but it sure does appear that buffer sizes are relevant at least in some cases.

@abique
Copy link
Contributor Author

abique commented Jun 20, 2025

An alsa buffer, is a continuous memory used as a circular buffer.
It contains many periods. What alsa calls a period is what asio would call a buffer.

What is important is the period size (in frames) that defines your latency.
You can have a period of 128 samples, work with 2 or 3 periods and have a buffer that could contain a lot more.
The rule is: buffer_size >= perdiod_size * nperiods.

So there's nothing wrong with a bigger buffer, it just takes more memory.
You probably want to shrink your buffer to the minimum required frames.

For alsa, period size and num periods defines your latency and working context.

@mbernat
Copy link

mbernat commented Jun 20, 2025

Thank you @abique, that makes a lot of sense!

It would be nice to also improve the BufferSize documentation. I'm not sure how much of this behavior is portable between backends but I don't see why there couldn't be an alsa-specific section in the docs. Relatedly, pipewire can also be configured to behave very similarly, from my recent experiments (bigger buffers, fixed periods).

@roderickvd
Copy link
Member

@abique doing backlog grooming as new maintainer. Yes the current calculation is off and your proposal is better.

I'm just thinking that the period size could be even more optimally calculated by taking into account the sampling rate. At high sampling rates, 1024 frames is short and increases risk of stutter, correct?

I also agree with @mbernat that the documentation can use improvement, particularly because buffer size and period size do not mean the same thing in Alsa land.

Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR refactors ALSA audio buffer configuration to properly handle buffer size and period size calculations. The changes ensure that both fixed and default buffer sizes follow the same code path and implement the ALSA requirement that buffer size equals nperiod * period_size with an ideal of 2 periods.

  • Unifies buffer size handling for both fixed and default configurations
  • Sets a more reasonable default period size of 1024 samples
  • Explicitly configures 2 periods for optimal ALSA performance

Comment on lines +1065 to +1067
BufferSize::Fixed(v) => v as alsa::pcm::Frames,
BufferSize::Default => {
// These values together represent a moderate latency and wakeup interval.
// Without them, we are at the mercy of the device
hw_params.set_period_time_near(25_000, alsa::ValueOr::Nearest)?;
hw_params.set_buffer_time_near(100_000, alsa::ValueOr::Nearest)?;
// This value represent a moderate latency and wakeup interval.
Copy link

Copilot AI Jul 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Fixed buffer size case is treating the buffer size as period size directly, but according to the PR description and ALSA documentation, buffer size should be nperiod * period_size. For 2 periods, the period size should be v / 2, not v.

Copilot uses AI. Check for mistakes.

hw_params.set_period_time_near(25_000, alsa::ValueOr::Nearest)?;
hw_params.set_buffer_time_near(100_000, alsa::ValueOr::Nearest)?;
// This value represent a moderate latency and wakeup interval.
1024 as alsa::pcm::Frames
Copy link

Copilot AI Jul 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The explicit cast as alsa::pcm::Frames is unnecessary here since 1024 can be directly assigned to the alsa::pcm::Frames type. Consider using just 1024.

Suggested change
1024 as alsa::pcm::Frames
1024

Copilot uses AI. Check for mistakes.

@abique
Copy link
Contributor Author

abique commented Aug 1, 2025

Hey, I'm not feeling like continuing this PR, so feel free to take the changes and finish it.
It's been a year already I've moved on to other things.

@roderickvd
Copy link
Member

Understood. Apologies for the late response and thank you for your earlier efforts 🙏

@roderickvd
Copy link
Member

Superseded by #990

@roderickvd roderickvd closed this Aug 26, 2025
roderickvd referenced this pull request Sep 12, 2025
This mostly reverts #990 for device compatibility, by letting ALSA calculate
the period size from the device default period count. Forcing the period count
to 2 caused underruns on some systems.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Invalid period size specification for ALSA?
4 participants