Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use pinboard crate to avoid blocking Sinks during playback #419

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ hound = { version = "3.3.1", optional = true }
lewton = { version = "0.10", optional = true }
minimp3 = { version = "0.5.0", optional = true }
symphonia = {version = "0.5", optional = true }
pinboard = "2.1.0"

[features]
default = ["flac", "vorbis", "wav", "mp3"]
Expand Down
22 changes: 12 additions & 10 deletions src/sink.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ use std::sync::mpsc::Receiver;
use std::sync::{Arc, Mutex};
use std::time::Duration;

use pinboard::NonEmptyPinboard;

use crate::stream::{OutputStreamHandle, PlayError};
use crate::{queue, source::Done, Sample, Source};

Expand All @@ -22,9 +24,9 @@ pub struct Sink {

struct Controls {
pause: AtomicBool,
volume: Mutex<f32>,
volume: NonEmptyPinboard<f32>,
stopped: AtomicBool,
speed: Mutex<f32>,
speed: NonEmptyPinboard<f32>,
}

impl Sink {
Expand All @@ -46,9 +48,9 @@ impl Sink {
sleep_until_end: Mutex::new(None),
controls: Arc::new(Controls {
pause: AtomicBool::new(false),
volume: Mutex::new(1.0),
volume: NonEmptyPinboard::new(1.0),
stopped: AtomicBool::new(false),
speed: Mutex::new(1.0),
speed: NonEmptyPinboard::new(1.0),
}),
sound_count: Arc::new(AtomicUsize::new(0)),
detached: false,
Expand All @@ -75,14 +77,14 @@ impl Sink {
if controls.stopped.load(Ordering::SeqCst) {
src.stop();
} else {
src.inner_mut().set_factor(*controls.volume.lock().unwrap());
src.inner_mut().set_factor(controls.volume.read());
src.inner_mut()
.inner_mut()
.set_paused(controls.pause.load(Ordering::SeqCst));
src.inner_mut()
.inner_mut()
.inner_mut()
.set_factor(*controls.speed.lock().unwrap());
.set_factor(controls.speed.read());
}
})
.convert_samples();
Expand All @@ -97,7 +99,7 @@ impl Sink {
/// multiply each sample by this value.
#[inline]
pub fn volume(&self) -> f32 {
*self.controls.volume.lock().unwrap()
self.controls.volume.read()
}

/// Changes the volume of the sound.
Expand All @@ -106,7 +108,7 @@ impl Sink {
/// multiply each sample by this value.
#[inline]
pub fn set_volume(&self, value: f32) {
*self.controls.volume.lock().unwrap() = value;
self.controls.volume.set(value);
}

/// Gets the speed of the sound.
Expand All @@ -115,7 +117,7 @@ impl Sink {
/// change the play speed of the sound.
#[inline]
pub fn speed(&self) -> f32 {
*self.controls.speed.lock().unwrap()
self.controls.speed.read()
}

/// Changes the speed of the sound.
Expand All @@ -124,7 +126,7 @@ impl Sink {
/// change the play speed of the sound.
#[inline]
pub fn set_speed(&self, value: f32) {
*self.controls.speed.lock().unwrap() = value;
self.controls.speed.set(value);
}

/// Resumes playback of a paused sink.
Expand Down
42 changes: 23 additions & 19 deletions src/spatial_sink.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
use std::f32;
use std::sync::{Arc, Mutex};
use std::sync::Arc;
use std::time::Duration;

use pinboard::NonEmptyPinboard;

use crate::source::Spatial;
use crate::stream::{OutputStreamHandle, PlayError};
use crate::{Sample, Sink, Source};

pub struct SpatialSink {
sink: Sink,
positions: Arc<Mutex<SoundPositions>>,
positions: Arc<SoundPositions>,
}

struct SoundPositions {
emitter_position: [f32; 3],
left_ear: [f32; 3],
right_ear: [f32; 3],
emitter_position: NonEmptyPinboard<[f32; 3]>,
left_ear: NonEmptyPinboard<[f32; 3]>,
right_ear: NonEmptyPinboard<[f32; 3]>,
}

impl SpatialSink {
Expand All @@ -27,27 +29,27 @@ impl SpatialSink {
) -> Result<SpatialSink, PlayError> {
Ok(SpatialSink {
sink: Sink::try_new(stream)?,
positions: Arc::new(Mutex::new(SoundPositions {
emitter_position,
left_ear,
right_ear,
})),
positions: Arc::new(SoundPositions {
emitter_position: NonEmptyPinboard::new(emitter_position),
left_ear: NonEmptyPinboard::new(left_ear),
right_ear: NonEmptyPinboard::new(right_ear),
}),
})
}

/// Sets the position of the sound emitter in 3 dimensional space.
pub fn set_emitter_position(&self, pos: [f32; 3]) {
self.positions.lock().unwrap().emitter_position = pos;
self.positions.emitter_position.set(pos);
}

/// Sets the position of the left ear in 3 dimensional space.
pub fn set_left_ear_position(&self, pos: [f32; 3]) {
self.positions.lock().unwrap().left_ear = pos;
self.positions.left_ear.set(pos);
}

/// Sets the position of the right ear in 3 dimensional space.
pub fn set_right_ear_position(&self, pos: [f32; 3]) {
self.positions.lock().unwrap().right_ear = pos;
self.positions.right_ear.set(pos);
}

/// Appends a sound to the queue of sounds to play.
Expand All @@ -58,16 +60,18 @@ impl SpatialSink {
S::Item: Sample + Send,
{
let positions = self.positions.clone();
let pos_lock = self.positions.lock().unwrap();
let source = Spatial::new(
source,
pos_lock.emitter_position,
pos_lock.left_ear,
pos_lock.right_ear,
positions.emitter_position.read(),
positions.left_ear.read(),
positions.right_ear.read(),
)
.periodic_access(Duration::from_millis(10), move |i| {
let pos = positions.lock().unwrap();
i.set_positions(pos.emitter_position, pos.left_ear, pos.right_ear);
i.set_positions(
positions.emitter_position.read(),
positions.left_ear.read(),
positions.right_ear.read(),
);
});
self.sink.append(source);
}
Expand Down