From 427acecdf096eeb963d5acc7a7c10524698a5820 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benoi=CC=82t=20Rouleau?= Date: Wed, 5 Aug 2026 19:21:48 -0400 Subject: [PATCH] clamp the default buffer size to what the device supports --- CHANGELOG.md | 1 + src/stream.rs | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e0f149dec..00c60cbff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,6 +52,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed sources to detect parameter updates after mid-span seeks. - Fixed `Stoppable` and `Skippable` not signaling exhaustion. - Fixed `SpatialAudio` left and write channel swapping +- Fixed playback on devices that cap the buffer size below the default we aim for, such as bluetooth outputs. ## Version [0.22.2] (2026-03-05) diff --git a/src/stream.rs b/src/stream.rs index fc0a45317..9887167e0 100644 --- a/src/stream.rs +++ b/src/stream.rs @@ -220,7 +220,12 @@ impl DeviceSinkBuilder { // aim for 50ms of audio let sample_rate = device.config.sample_rate().get(); - let safe_buffer_size = nearest_multiple_of_two(sample_rate / (1000 / 50)); + let mut safe_buffer_size = nearest_multiple_of_two(sample_rate / (1000 / 50)); + // Opening fails on a fixed size outside the device's range, and + // bluetooth outputs cap it well below 50ms. + if let cpal::SupportedBufferSize::Range { min, max } = default_config.buffer_size() { + safe_buffer_size = safe_buffer_size.clamp(*min, *max); + } // This is suboptimal, the builder might still change the sample rate or // channel count which would throw the buffer size off. We have fixed