Skip to content

Implement buffer_size_range for pipewire, alsa - #80

Draft
jacksongoode wants to merge 9 commits into
SolarLiner:mainfrom
tonarino:other-buffer-range-impl
Draft

Implement buffer_size_range for pipewire, alsa#80
jacksongoode wants to merge 9 commits into
SolarLiner:mainfrom
tonarino:other-buffer-range-impl

Conversation

@jacksongoode

@jacksongoodejacksongoode commented Jul 25, 2025

Copy link
Copy Markdown
Contributor

This provides the method to properly set the buffer size range for the pipewire and alsa backends, not just Core Audio.

Untested now.

Description

Please include a summary of the change and which issue is fixed. Include relevant motivation and context.

Fixes # (issue number)

Type of Change

Please delete options that are not relevant.

  • New feature (non-breaking change which adds functionality)

How Has This Been Tested?

Please describe the tests you added or ran to verify your changes. Provide instructions so we can reproduce. Try to run
on as many audio drivers as you can get your hands on.

  • Test on Linux

Checklist:

  • My code follows the style guidelines of this project
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • Wherever possible, I have added tests that prove my fix is effective or that my feature works. For changes that
    need to be validated manually (i.e. a new audio driver), use examples that can be run to easily validate them.
  • New and existing unit tests pass locally with my changes
  • I have checked my code and corrected any misspellings

Screenshots (if appropriate):

Additional Notes:

Add any additional notes about the PR here.

@jacksongoode
jacksongoodeforce-pushed the other-buffer-range-impl branch from 5a00469 to c6af26eCompareJuly 25, 2025 05:13

@geom3trikgeom3trik left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I'm not sure exactly where the problem is yet but this does not seem to be working on my system for WASAPI on Windows. It's failing to build a default output stream so I'm guessing there's something wrong with the buffer size range function, however I haven't gotten to the bottom of it just yet.

@jacksongoode

Copy link
Copy Markdown
ContributorAuthor

@geom3trik Could you post some logs and the command of what you're running?

@geom3trik

Copy link
Copy Markdown
Collaborator

@geom3trik Could you post some logs and the command of what you're running?

Sure. if I try to run the new set_buffer_size example, I get the following panic:

thread 'main' panicked at examples\set_buffer_size.rs:87:10:
No default output device found on this system

And if I try to run the sine_wave example, I get the following panic:

thread 'main' panicked at examples\sine_wave.rs:12:69:
called `Result::unwrap()` on an `Err` value: BackendError(Error { code: HRESULT(0x88890024), message: "" })

@jacksongoode

Copy link
Copy Markdown
ContributorAuthor

I see could you run the enumerate_wasapi example?

@geom3trik

Copy link
Copy Markdown
Collaborator

I see could you run the enumerate_wasapi example?

Sure, that runs fine and gives the following output:

Driver name : WASAPI
Driver version: unknown
Default device
Input: Analogue 1 + 2 (Focusrite USB Audio)
Output: Speakers (Focusrite USB Audio)
All devices
S24D590 (NVIDIA High Definition Audio) (DeviceType(OUTPUT))
Speakers (Focusrite USB Audio) (DeviceType(OUTPUT))
Digital Audio (S/PDIF) (High Definition Audio Device) (DeviceType(OUTPUT))
S25HG5x (NVIDIA High Definition Audio) (DeviceType(OUTPUT))
Analogue 1 + 2 (Focusrite USB Audio) (DeviceType(INPUT))

@jacksongoode

Copy link
Copy Markdown
ContributorAuthor

@geom3trik Thank you for the logs, could you try the latest commit?

@jacksongoode

jacksongoode commented Aug 7, 2025

Copy link
Copy Markdown
ContributorAuthor

This needs a little more work. On pipewire it appears to work but I should probably be using the pipewire api not the alsa passthrough

Using backend: PipewireDriver
Using device: Default
Supported buffer size range: min=N/A, max=N/A
Requesting buffer size: 256
Playing sine wave... Press enter to stop.
Actual buffer size granted by OS: 256

on alsa it appears to do what it wants

Using backend: AlsaDriver
Using device: default
Supported buffer size range: min=1, max=4194304
Requesting buffer size: 256
Playing sine wave... Press enter to stop.
Actual buffer size granted by OS: 10

@jacksongoode
jacksongoodeforce-pushed the other-buffer-range-impl branch from dd393cc to 8b2105bCompareAugust 13, 2025 10:01

@SolarLinerSolarLiner left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Pretty nice, thank you ! LGTM except for a few cosmetic changes in the code.

Comment on lines -156 to +168
buffer_size_range: (None, None),
buffer_size_range: self.buffer_size_range()?,

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I'd like to avoid doing an API lookup here, (None, None) already means "the entire supported buffer range". People that need the data can themselves call buffer_size_range() if they want to.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

This is also valid for the PipeWire and WASAPI backends

Comment threadsrc/backends/wasapi/device.rs Outdated
Comment on lines +75 to +99
unsafe {
// Get the mix format, now managed by our RAII wrapper.
let format_ptr = ComWaveFormat(audio_client.GetMixFormat()?);

let mut closest_match_ptr: *mut Audio::WAVEFORMATEX = ptr::null_mut();
let res = audio_client.IsFormatSupported(
Audio::AUDCLNT_SHAREMODE_SHARED,
&*format_ptr.0,
Some(&mut closest_match_ptr),
);

if res.is_ok() {
// The original format is supported.
return Ok(format_ptr.0.read_unaligned());
}

// Wrap the returned suggestion in our RAII struct as well.
let closest_match = ComWaveFormat(closest_match_ptr);
if !closest_match.0.is_null() {
return Ok(closest_match.0.read_unaligned());
}

res.ok()?;
unreachable!();
}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Suggested change
unsafe{
// Get the mix format, now managed by our RAII wrapper.
let format_ptr = ComWaveFormat(audio_client.GetMixFormat()?);
letmut closest_match_ptr:*mutAudio::WAVEFORMATEX = ptr::null_mut();
let res = audio_client.IsFormatSupported(
Audio::AUDCLNT_SHAREMODE_SHARED,
&*format_ptr.0,
Some(&mut closest_match_ptr),
);
if res.is_ok(){
// The original format is supported.
returnOk(format_ptr.0.read_unaligned());
}
// Wrap the returned suggestion in our RAII struct as well.
let closest_match = ComWaveFormat(closest_match_ptr);
if !closest_match.0.is_null(){
returnOk(closest_match.0.read_unaligned());
}
res.ok()?;
unreachable!();
}
unsafe{
// Get the mix format, now managed by our RAII wrapper.
let format_ptr = ComWaveFormat(audio_client.GetMixFormat()?);
letmut closest_match = ComWaveFormat(ptr::null_mut());
let res = audio_client
.IsFormatSupported(
Audio::AUDCLNT_SHAREMODE_SHARED,
&*format_ptr.0,
Some(&mut closest_match.0),
)
.ok();
match res {
Ok(()) => Ok(format_ptr.0.read_unaligned()),
Err(err)if closest_match.0.is_null() => {
Err(error::WasapiError::FoundationError(err.to_string()))
}
Err(..) => Ok(closest_match.0.read_unaligned()),
}
}

Using match simplifies the code a bit IMHO, and makes the flow clearer. Hopefully I haven't messed up and it should still have the same behavior.

@jacksongoode
jacksongoode marked this pull request as draft August 19, 2025 04:16
@jacksongoode

Copy link
Copy Markdown
ContributorAuthor

Pretty nice, thank you ! LGTM except for a few cosmetic changes in the code.

Hey @SolarLiner sorry about this, I finally got to testing on Windows and it didn't work at all so I have made it a draft until I can confirm its behavior actually works on Windows.

@jacksongoodejacksongoode changed the title Implement buffer_size_range for pipewire, alsa, and wasapiImplement buffer_size_range for pipewire, alsaSep 24, 2025
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@jacksongoode@geom3trik@SolarLiner