Fix Sink playback after stop (#464)

Addressing issues #462 and #315 and #171

Given how the sink's queue is drained on stop I made some modifications in sink.append(). I added a check to ensure the sink was flushed completely (not sure this is necessary? I think it is, to avoid race conditions) and to restart the sink on append (when stopped.)

I added a test demonstrating correctness, as well as performing some trials on my own.
This commit is contained in:
Jayden Dumouchel 2023-02-17 13:12:32 -07:00 committed by GitHub
parent 0c0e086b6a
commit 44b92d43e9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -65,6 +65,14 @@ impl Sink {
f32: FromSample<S::Item>,
S::Item: Sample + Send,
{
// Wait for queue to flush then resume stopped playback
if self.controls.stopped.load(Ordering::SeqCst) {
if self.sound_count.load(Ordering::SeqCst) > 0 {
self.sleep_until_end();
}
self.controls.stopped.store(false, Ordering::SeqCst);
}
let controls = self.controls.clone();
let source = source
@ -201,6 +209,7 @@ impl Drop for Sink {
mod tests {
use crate::buffer::SamplesBuffer;
use crate::{Sink, Source};
use std::sync::atomic::Ordering;
#[test]
fn test_pause_and_stop() {
@ -233,6 +242,34 @@ mod tests {
assert_eq!(sink.empty(), true);
}
#[test]
fn test_stop_and_start() {
let (sink, mut queue_rx) = Sink::new_idle();
let v = vec![10i16, -10, 20, -20, 30, -30];
sink.append(SamplesBuffer::new(1, 1, v.clone()));
let mut src = SamplesBuffer::new(1, 1, v.clone()).convert_samples();
assert_eq!(queue_rx.next(), src.next());
assert_eq!(queue_rx.next(), src.next());
sink.stop();
assert!(sink.controls.stopped.load(Ordering::SeqCst));
assert_eq!(queue_rx.next(), Some(0.0));
src = SamplesBuffer::new(1, 1, v.clone()).convert_samples();
sink.append(SamplesBuffer::new(1, 1, v));
assert!(!sink.controls.stopped.load(Ordering::SeqCst));
// Flush silence
let mut queue_rx = queue_rx.skip_while(|v| *v == 0.0);
assert_eq!(queue_rx.next(), src.next());
assert_eq!(queue_rx.next(), src.next());
}
#[test]
fn test_volume() {
let (sink, mut queue_rx) = Sink::new_idle();