diff --git a/voxygen/src/audio/channel.rs b/voxygen/src/audio/channel.rs index 1c4a509496..3726592dfd 100644 --- a/voxygen/src/audio/channel.rs +++ b/voxygen/src/audio/channel.rs @@ -64,6 +64,14 @@ impl Channel { self.sink.set_volume(volume); } + pub fn set_left_ear_position(&mut self, pos: [f32; 3]) { + self.sink.set_left_ear_position(pos); + } + + pub fn set_right_ear_position(&mut self, pos: [f32; 3]) { + self.sink.set_right_ear_position(pos); + } + pub fn update(&mut self, dt: f32) { match self.state { ChannelState::Playing => {}, diff --git a/voxygen/src/audio/mod.rs b/voxygen/src/audio/mod.rs index 3d4fa2c12b..2a2a040930 100644 --- a/voxygen/src/audio/mod.rs +++ b/voxygen/src/audio/mod.rs @@ -5,10 +5,16 @@ use channel::{AudioType, Channel}; use common::assets; use rodio::{Decoder, Device, SpatialSink}; +use vek::*; const LEFT_EAR : [f32; 3] = [1.0, 0.0, 0.0]; const RIGHT_EAR : [f32; 3] = [-1.0, 0.0, 0.0]; +const EAR_LEFT : Vec3 = Vec3::new(1.0, 0.0, 0.0); +const EAR_RIGHT : Vec3 = Vec3::new(-1.0, 0.0, 0.0); + +const LISTEN_DISTANCE : f32 = 25.0; + pub struct AudioFrontend { pub device: String, @@ -20,6 +26,8 @@ pub struct AudioFrontend { sfx_volume: f32, music_volume: f32, + listener_pos_left: Vec3::, + listener_pos_right: Vec3::, } impl AudioFrontend { @@ -33,6 +41,8 @@ impl AudioFrontend { next_channel_id: 0, sfx_volume: 1.0, music_volume: 1.0, + listener_pos_left: Vec3::from_slice(&LEFT_EAR), + listener_pos_right: Vec3::from_slice(&RIGHT_EAR), } } @@ -46,6 +56,8 @@ impl AudioFrontend { next_channel_id: 0, sfx_volume: 1.0, music_volume: 1.0, + listener_pos_left: Vec3::from_slice(&LEFT_EAR), + listener_pos_right: Vec3::from_slice(&RIGHT_EAR), } } @@ -67,12 +79,15 @@ impl AudioFrontend { ///```ignore ///audio.play_sound("voxygen.audio.sfx.step"); ///``` - pub fn play_sound(&mut self, sound: String) -> usize { + pub fn play_sound(&mut self, sound: String, pos: Vec3::) -> usize { let id = self.next_channel_id; self.next_channel_id += 1; if let Some(device) = &self.audio_device { - let sink = SpatialSink::new(device, [0.0, 0.0, 0.0], LEFT_EAR, RIGHT_EAR); + let pos = pos / LISTEN_DISTANCE; + let sink = SpatialSink::new(device, pos.into_array(), + self.listener_pos_left.into_array(), + self.listener_pos_right.into_array()); let file = assets::load_file(&sound, &["wav"]).unwrap(); let sound = Decoder::new(file).unwrap(); @@ -85,6 +100,21 @@ impl AudioFrontend { id } + pub fn set_listener_pos(&mut self, pos: &Vec3::) { + let pos_left = (pos.clone() + EAR_LEFT) / LISTEN_DISTANCE; + let pos_right = (pos.clone() + EAR_RIGHT) / LISTEN_DISTANCE; + + self.listener_pos_left = pos_left.clone(); + self.listener_pos_right = pos_right.clone(); + + for channel in self.channels.iter_mut() { + if channel.get_audio_type() == AudioType::Sfx { + channel.set_left_ear_position(pos_left.into_array()); + channel.set_right_ear_position(pos_right.into_array()); + } + } + } + pub fn play_music(&mut self, sound: String) -> usize { let id = self.next_channel_id; self.next_channel_id += 1; @@ -138,6 +168,7 @@ impl AudioFrontend { } } + // TODO: figure out how badly this will break things when it is called pub fn set_device(&mut self, name: String) { self.device = name.clone(); self.audio_device = get_device_raw(name); diff --git a/voxygen/src/scene/sound.rs b/voxygen/src/scene/sound.rs index 927cfde9a3..b72ae6c4c6 100644 --- a/voxygen/src/scene/sound.rs +++ b/voxygen/src/scene/sound.rs @@ -39,6 +39,8 @@ impl SoundMgr { .get(client.entity()) .map_or(Vec3::zero(), |pos| pos.0); + audio.set_listener_pos(&player_pos); + for (entity, pos, body, character) in ( &ecs.entities(), &ecs.read_storage::(), @@ -60,7 +62,7 @@ impl SoundMgr { if let Run = &character.movement { if state.last_step_sound.elapsed().as_secs_f64() > 0.5 { let rand_step = (rand::random::() % 7) + 1; - audio.play_sound(format!("voxygen.audio.footsteps.stepdirt_{}", rand_step)); + audio.play_sound(format!("voxygen.audio.footsteps.stepdirt_{}", rand_step), pos.0); state.last_step_sound = Instant::now(); } }