From 898ebd930e0c5bb8b3f092d4c462bc38130adccf Mon Sep 17 00:00:00 2001 From: salmonik Date: Sat, 9 May 2026 17:14:39 +0200 Subject: Fix buffer underrun - pre-decode samples before playback --- src/audio.rs | 31 +++++++++++++++++++++++++++++++ src/daemon.rs | 9 ++++----- 2 files changed, 35 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/audio.rs b/src/audio.rs index 7218f84..386c041 100644 --- a/src/audio.rs +++ b/src/audio.rs @@ -197,6 +197,37 @@ fn audio_thread( Some(device_sample_rate as f64 / data.sample_rate as f64); } + // Pre-decode some samples before starting playback to prevent buffer underrun + let channels = data.channels as usize; + for _ in 0..50 { + match data.format.next_packet() { + Ok(packet) => { + match data.decoder.decode(&packet) { + Ok(decoded) => { + let spec = *decoded.spec(); + let mut sample_buf = + symphonia::core::audio::SampleBuffer::::new( + decoded.capacity() as u64, spec + ); + sample_buf.copy_interleaved_ref(decoded); + let samples = sample_buf.samples(); + + let resampled = if let Some(ratio) = data.resample_ratio { + resample_linear(samples, ratio, channels) + } else { + samples.to_vec() + }; + + data.sample_buffer.extend(resampled); + } + Err(_) => break, + } + } + Err(_) => break, + } + } + data.buffer_pos = 0; + let stream_config: cpal::StreamConfig = device.default_output_config().unwrap().into(); diff --git a/src/daemon.rs b/src/daemon.rs index f4a72b7..7488fc2 100644 --- a/src/daemon.rs +++ b/src/daemon.rs @@ -400,8 +400,9 @@ fn process_command( } _ => { let was_empty = q.is_empty(); + let was_playing = audio.is_playing(); q.add_track(path.clone()); - if was_empty && audio.is_playing() { + if was_empty && !was_playing { let track = Track::from_path(path.clone()); audio.play(path); notification::notify_track(&track); @@ -449,13 +450,11 @@ fn process_command( ) } _ => { + let was_playing = audio.is_playing(); for file in &files { q.add_track(file.clone()); } - if was_empty - && audio.is_playing() - && let Some(track) = q.current() - { + if was_empty && !was_playing && let Some(track) = q.current() { audio.play(track.path.clone()); notification::notify_track(track); } -- cgit v1.2.3