Skip to content

Commit

Permalink
feat: smooth source movement
Browse files Browse the repository at this point in the history
  • Loading branch information
mbillingr committed Jul 20, 2018
1 parent 8457a2f commit d3efa64
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 4 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,12 @@ let scene = AmbisonicBuilder::default().build();

let source = rodio::source::SineWave::new(440);
let mut sound = scene.play(source);
sound.set_position([50.0, 1.0, 0.0]);

// move sound from right to left
sound.set_velocity([-10.0, 0.0, 0.0]);
for i in 0..1000 {
sound.set_position([50.0 - i as f32 / 10.0, 1.0, 0.0]);
sound.adjust_position([50.0 - i as f32 / 10.0, 1.0, 0.0]);
sleep(Duration::from_millis(10));
}
sound.set_velocity([0.0, 0.0, 0.0]);
Expand Down
16 changes: 16 additions & 0 deletions src/bformat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,4 +151,20 @@ impl Bweights {
z: self.z * s,
}
}

/// adjust weights towards target
pub fn approach(&mut self, target: &Bweights, max_step: f32) {
// if this turns out too slow we could try to replace it with simple steps along each dimension
let dir = [target.w - self.w, target.x - self.x, target.y - self.y, target.z - self.z];
let dist = (dir[0] * dir[0] + dir[1] * dir[1] + dir[2] * dir[2] + dir[3] * dir[3]).sqrt();
if dist <= max_step {
*self = *target;
} else {
let d = max_step / dist;
self.w += dir[0] * d;
self.x += dir[1] * d;
self.y += dir[2] * d;
self.z += dir[3] * d;
}
}
}
27 changes: 26 additions & 1 deletion src/bstream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ pub fn bstream<I: Source<Item = f32> + Send + 'static>(source: I) -> (Bstream, S
let stream = Bstream {
input: Box::new(source),
bweights: Bweights::omni_source(),
target_weights: Bweights::omni_source(),
speed: 1.0,
sampling_offset: 0.0,
previous_sample: 0.0,
Expand All @@ -46,12 +47,15 @@ pub fn bstream<I: Source<Item = f32> + Send + 'static>(source: I) -> (Bstream, S
/// Consumes samples from the inner source and converts them to *B-format* samples.
pub struct Bstream {
input: Box<Source<Item = f32> + Send>,
bridge: Arc<BstreamBridge>,

bweights: Bweights,
target_weights: Bweights,

speed: f32,
sampling_offset: f32,
previous_sample: f32,
next_sample: f32,
bridge: Arc<BstreamBridge>,
}

impl Bstream {}
Expand Down Expand Up @@ -89,6 +93,7 @@ impl Iterator for Bstream {
for cmd in commands.drain(..) {
match cmd {
Command::SetWeights(bw) => self.bweights = bw,
Command::SetTarget(bw) => self.target_weights = bw,
Command::SetSpeed(s) => self.speed = s,
Command::Stop => {
self.bridge.stopped.store(true, Ordering::SeqCst);
Expand All @@ -100,6 +105,10 @@ impl Iterator for Bstream {
self.bridge.pending_commands.store(false, Ordering::SeqCst);
}

// adjusting the weights slowly avoids audio artifacts but prevents very fast position
// changes
self.bweights.approach(&self.target_weights, 0.001);

while self.sampling_offset >= 1.0 {
match self.input.next() {
Some(x) => {
Expand All @@ -124,6 +133,7 @@ impl Iterator for Bstream {

enum Command {
SetWeights(Bweights),
SetTarget(Bweights),
SetSpeed(f32),
Stop,
}
Expand Down Expand Up @@ -154,6 +164,21 @@ impl SoundController {
let mut cmds = self.bridge.commands.lock().unwrap();
cmds.push(Command::SetSpeed(rate));
cmds.push(Command::SetWeights(weights));
cmds.push(Command::SetTarget(weights));
}
self.bridge.pending_commands.store(true, Ordering::SeqCst);
}
/// Adjust source position relative to listener
///
/// The source transitions smoothly to the new position
pub fn adjust_position(&mut self, pos: [f32; 3]) {
self.position = pos;
let weights = Bweights::from_position(pos);
let rate = self.doppler_rate();
{
let mut cmds = self.bridge.commands.lock().unwrap();
cmds.push(Command::SetSpeed(rate));
cmds.push(Command::SetTarget(weights));
}
self.bridge.pending_commands.store(true, Ordering::SeqCst);
}
Expand Down
6 changes: 4 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@
//!
//! let source = rodio::source::SineWave::new(440);
//! let mut sound = scene.play(source);
//! sound.set_position([50.0, 1.0, 0.0]);
//!
//! // move sound from right to left
//! sound.set_velocity([-10.0, 0.0, 0.0]);
//! for i in 0..1000 {
//! sound.set_position([50.0 - i as f32 / 10.0, 1.0, 0.0]);
//! sound.adjust_position([50.0 - i as f32 / 10.0, 1.0, 0.0]);
//! sleep(Duration::from_millis(10));
//! }
//! sound.set_velocity([0.0, 0.0, 0.0]);
Expand Down Expand Up @@ -164,11 +165,12 @@ mod tests {

let source = rodio::source::SineWave::new(440);
let mut sound = scene.play(source);
sound.set_position([50.0, 1.0, 0.0]);

// move sound from right to left
sound.set_velocity([-10.0, 0.0, 0.0]);
for i in 0..1000 {
sound.set_position([50.0 - i as f32 / 10.0, 1.0, 0.0]);
sound.adjust_position([50.0 - i as f32 / 10.0, 1.0, 0.0]);
sleep(Duration::from_millis(10));
}
sound.set_velocity([0.0, 0.0, 0.0]);
Expand Down

0 comments on commit d3efa64

Please sign in to comment.