1 use source::Spatial; 2 use std::f32; 3 use std::fmt::Debug; 4 use std::sync::{Arc, Mutex}; 5 use std::time::Duration; 6 use Device; 7 use Sample; 8 use Sink; 9 use Source; 10 11 pub struct SpatialSink { 12 sink: Sink, 13 positions: Arc<Mutex<SoundPositions>>, 14 } 15 16 struct SoundPositions { 17 emitter_position: [f32; 3], 18 left_ear: [f32; 3], 19 right_ear: [f32; 3], 20 } 21 22 impl SpatialSink { 23 /// Builds a new `SpatialSink`. 24 #[inline] new( device: &Device, emitter_position: [f32; 3], left_ear: [f32; 3], right_ear: [f32; 3], ) -> SpatialSink25 pub fn new( 26 device: &Device, emitter_position: [f32; 3], left_ear: [f32; 3], right_ear: [f32; 3], 27 ) -> SpatialSink { 28 SpatialSink { 29 sink: Sink::new(device), 30 positions: Arc::new(Mutex::new(SoundPositions { 31 emitter_position, 32 left_ear, 33 right_ear, 34 })), 35 } 36 } 37 38 /// Sets the position of the sound emitter in 3 dimensional space. set_emitter_position(&self, pos: [f32; 3])39 pub fn set_emitter_position(&self, pos: [f32; 3]) { 40 self.positions.lock().unwrap().emitter_position = pos; 41 } 42 43 /// Sets the position of the left ear in 3 dimensional space. set_left_ear_position(&self, pos: [f32; 3])44 pub fn set_left_ear_position(&self, pos: [f32; 3]) { 45 self.positions.lock().unwrap().left_ear = pos; 46 } 47 48 /// Sets the position of the right ear in 3 dimensional space. set_right_ear_position(&self, pos: [f32; 3])49 pub fn set_right_ear_position(&self, pos: [f32; 3]) { 50 self.positions.lock().unwrap().right_ear = pos; 51 } 52 53 /// Appends a sound to the queue of sounds to play. 54 #[inline] append<S>(&self, source: S) where S: Source + Send + 'static, S::Item: Sample + Send + Debug,55 pub fn append<S>(&self, source: S) 56 where 57 S: Source + Send + 'static, 58 S::Item: Sample + Send + Debug, 59 { 60 let positions = self.positions.clone(); 61 let pos_lock = self.positions.lock().unwrap(); 62 let source = Spatial::new( 63 source, 64 pos_lock.emitter_position, 65 pos_lock.left_ear, 66 pos_lock.right_ear, 67 ).periodic_access(Duration::from_millis(10), move |i| { 68 let pos = positions.lock().unwrap(); 69 i.set_positions(pos.emitter_position, pos.left_ear, pos.right_ear); 70 }); 71 self.sink.append(source); 72 } 73 74 // Gets the volume of the sound. 75 /// 76 /// The value `1.0` is the "normal" volume (unfiltered input). Any value other than 1.0 will 77 /// multiply each sample by this value. 78 #[inline] volume(&self) -> f3279 pub fn volume(&self) -> f32 { 80 self.sink.volume() 81 } 82 83 /// Changes the volume of the sound. 84 /// 85 /// The value `1.0` is the "normal" volume (unfiltered input). Any value other than 1.0 will 86 /// multiply each sample by this value. 87 #[inline] set_volume(&self, value: f32)88 pub fn set_volume(&self, value: f32) { 89 self.sink.set_volume(value); 90 } 91 92 /// Resumes playback of a paused sound. 93 /// 94 /// No effect if not paused. 95 #[inline] play(&self)96 pub fn play(&self) { 97 self.sink.play(); 98 } 99 100 /// Pauses playback of this sink. 101 /// 102 /// No effect if already paused. 103 /// 104 /// A paused sound can be resumed with `play()`. pause(&self)105 pub fn pause(&self) { 106 self.sink.pause(); 107 } 108 109 /// Gets if a sound is paused 110 /// 111 /// Sounds can be paused and resumed using pause() and play(). This gets if a sound is paused. is_paused(&self) -> bool112 pub fn is_paused(&self) -> bool { 113 self.sink.is_paused() 114 } 115 116 /// Stops the sink by emptying the queue. 117 #[inline] stop(&self)118 pub fn stop(&self) { 119 self.sink.stop() 120 } 121 122 /// Destroys the sink without stopping the sounds that are still playing. 123 #[inline] detach(self)124 pub fn detach(self) { 125 self.sink.detach(); 126 } 127 128 /// Sleeps the current thread until the sound ends. 129 #[inline] sleep_until_end(&self)130 pub fn sleep_until_end(&self) { 131 self.sink.sleep_until_end(); 132 } 133 134 /// Returns true if this sink has no more sounds to play. 135 #[inline] empty(&self) -> bool136 pub fn empty(&self) -> bool { 137 self.sink.empty() 138 } 139 } 140