Skip to content

Commit

Permalink
feat: pause and resume sources
Browse files Browse the repository at this point in the history
  • Loading branch information
anon committed Feb 17, 2021
1 parent cff41ba commit 0528672
Showing 1 changed file with 65 additions and 1 deletion.
66 changes: 65 additions & 1 deletion src/bstream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use crate::bformat::{Bformat, Bweights};
use crate::constants::SPEED_OF_SOUND;
use rodio::Source;
use rodio::{Sample, Source};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex};
use std::time::Duration;
Expand Down Expand Up @@ -49,6 +49,7 @@ pub fn bstream<I: Source<Item = f32> + Send + 'static>(
next_sample: source.next().unwrap_or(0.0),
bridge,
input: Box::new(source),
paused: false,
};

(stream, controller)
Expand Down Expand Up @@ -118,6 +119,7 @@ pub struct Bstream {
sampling_offset: f32,
previous_sample: f32,
next_sample: f32,
paused: bool,
}

impl Bstream {}
Expand Down Expand Up @@ -161,12 +163,19 @@ impl Iterator for Bstream {
self.bridge.stopped.store(true, Ordering::SeqCst);
return None;
}
Command::Pause => self.paused = true,
Command::Resume => self.paused = false,
}
}

self.bridge.pending_commands.store(false, Ordering::SeqCst);
}

if self.paused {
self.bweights = self.target_weights; // during pause we can allow the source to jump
return Some(Bformat::zero_value());
}

// adjusting the weights slowly avoids audio artifacts but prevents very fast position
// changes
self.bweights.approach(&self.target_weights, 0.001);
Expand Down Expand Up @@ -199,6 +208,8 @@ enum Command {
SetTarget(Bweights),
SetSpeed(f32),
Stop,
Pause,
Resume,
}

/// Bridges a Bstream and its controller across threads
Expand Down Expand Up @@ -274,6 +285,18 @@ impl SoundController {
self.bridge.pending_commands.store(true, Ordering::SeqCst);
}

/// Pause playback
pub fn pause(&self) {
self.bridge.commands.lock().unwrap().push(Command::Pause);
self.bridge.pending_commands.store(true, Ordering::SeqCst);
}

/// Resume playback
pub fn resume(&self) {
self.bridge.commands.lock().unwrap().push(Command::Resume);
self.bridge.pending_commands.store(true, Ordering::SeqCst);
}

/// Set doppler factor
pub fn set_doppler_factor(&mut self, factor: f32) {
self.doppler_factor = factor;
Expand Down Expand Up @@ -357,6 +380,47 @@ mod tests {
assert_eq!(stream.next(), Some(3.0));
}

#[test]
fn pausing_a_source_makes_it_emit_zeros() {
let (mut stream, controller) = bstream(
Ramp::new(1),
BstreamConfig::new().with_position([1.0, 0.0, 0.0]),
);

let mut stream = extract_x_component(&mut stream);

assert_eq!(stream.next(), Some(0.0));
assert_eq!(stream.next(), Some(1.0));

controller.pause();

assert_eq!(stream.next(), Some(0.0));
assert_eq!(stream.next(), Some(0.0));
}

#[test]
fn resuming_a_source_makes_it_continue_where_it_paused() {
let (mut stream, controller) = bstream(
Ramp::new(1),
BstreamConfig::new().with_position([1.0, 0.0, 0.0]),
);

let mut stream = extract_x_component(&mut stream);

assert_eq!(stream.next(), Some(0.0));
assert_eq!(stream.next(), Some(1.0));

controller.pause();

assert_eq!(stream.next(), Some(0.0));
assert_eq!(stream.next(), Some(0.0));

controller.resume();

assert_eq!(stream.next(), Some(2.0));
assert_eq!(stream.next(), Some(3.0));
}

fn extract_x_component(stream: impl Iterator<Item = Bformat>) -> impl Iterator<Item = f32> {
stream.map(|bsample| Bweights::new(0.0, 1.0, 0.0, 0.0).dot(bsample))
}
Expand Down

0 comments on commit 0528672

Please sign in to comment.