perf(rodio): set fixed ALSA buffer size on linux

This commit is contained in:
vicrodh committed 2026-01-13 08:38:24 -06:00
1 parent f2c1fce6da
commit 166571566a
1 file changed
+25 -11
+25 -11
View File
@@ -7,7 +7,7 @@ use crate::dynamic_mixer::{self, DynamicMixerController};
use crate::sink::Sink;
use crate::source::Source;
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
use cpal::{Sample, SupportedStreamConfig};
use cpal::{BufferSize, Sample, SupportedBufferSize, SupportedStreamConfig};
/// `cpal::Stream` container. Also see the more useful `OutputStreamHandle`.
///
@@ -210,9 +210,23 @@ impl CpalDeviceExt for cpal::Device {
let error_callback = |err| eprintln!("an error occurred on output stream: {}", err);
let mut config = format.config();
#[cfg(target_os = "linux")]
{
if let SupportedBufferSize::Range { min, max } = *format.buffer_size() {
// Aim for ~400ms buffer to reduce wakeups during music playback.
let target_frames =
(config.sample_rate.0 as u64).saturating_mul(2).saturating_div(5);
let clamped = target_frames
.clamp(min as u64, max as u64)
.min(u32::MAX as u64) as u32;
config.buffer_size = BufferSize::Fixed(clamped);
}
}
match format.sample_format() {
cpal::SampleFormat::F32 => self.build_output_stream::<f32, _, _>(
&format.config(),
&config,
move |data, _| {
data.iter_mut()
.for_each(|d| *d = mixer_rx.next().unwrap_or(0f32))
@@ -221,7 +235,7 @@ impl CpalDeviceExt for cpal::Device {
None,
),
cpal::SampleFormat::F64 => self.build_output_stream::<f64, _, _>(
&format.config(),
&config,
move |data, _| {
data.iter_mut()
.for_each(|d| *d = mixer_rx.next().map(Sample::from_sample).unwrap_or(0f64))
@@ -230,7 +244,7 @@ impl CpalDeviceExt for cpal::Device {
None,
),
cpal::SampleFormat::I8 => self.build_output_stream::<i8, _, _>(
&format.config(),
&config,
move |data, _| {
data.iter_mut()
.for_each(|d| *d = mixer_rx.next().map(Sample::from_sample).unwrap_or(0i8))
@@ -239,7 +253,7 @@ impl CpalDeviceExt for cpal::Device {
None,
),
cpal::SampleFormat::I16 => self.build_output_stream::<i16, _, _>(
&format.config(),
&config,
move |data, _| {
data.iter_mut()
.for_each(|d| *d = mixer_rx.next().map(Sample::from_sample).unwrap_or(0i16))
@@ -248,7 +262,7 @@ impl CpalDeviceExt for cpal::Device {
None,
),
cpal::SampleFormat::I32 => self.build_output_stream::<i32, _, _>(
&format.config(),
&config,
move |data, _| {
data.iter_mut()
.for_each(|d| *d = mixer_rx.next().map(Sample::from_sample).unwrap_or(0i32))
@@ -257,7 +271,7 @@ impl CpalDeviceExt for cpal::Device {
None,
),
cpal::SampleFormat::I64 => self.build_output_stream::<i64, _, _>(
&format.config(),
&config,
move |data, _| {
data.iter_mut()
.for_each(|d| *d = mixer_rx.next().map(Sample::from_sample).unwrap_or(0i64))
@@ -266,7 +280,7 @@ impl CpalDeviceExt for cpal::Device {
None,
),
cpal::SampleFormat::U8 => self.build_output_stream::<u8, _, _>(
&format.config(),
&config,
move |data, _| {
data.iter_mut().for_each(|d| {
*d = mixer_rx
@@ -279,7 +293,7 @@ impl CpalDeviceExt for cpal::Device {
None,
),
cpal::SampleFormat::U16 => self.build_output_stream::<u16, _, _>(
&format.config(),
&config,
move |data, _| {
data.iter_mut().for_each(|d| {
*d = mixer_rx
@@ -292,7 +306,7 @@ impl CpalDeviceExt for cpal::Device {
None,
),
cpal::SampleFormat::U32 => self.build_output_stream::<u32, _, _>(
&format.config(),
&config,
move |data, _| {
data.iter_mut().for_each(|d| {
*d = mixer_rx
@@ -305,7 +319,7 @@ impl CpalDeviceExt for cpal::Device {
None,
),
cpal::SampleFormat::U64 => self.build_output_stream::<u64, _, _>(
&format.config(),
&config,
move |data, _| {
data.iter_mut().for_each(|d| {
*d = mixer_rx