From 65008f7d547f4a170dfe3843c0451fa82a598c85 Mon Sep 17 00:00:00 2001 From: Louis Pearson Date: Sun, 1 Sep 2019 15:40:54 -0600 Subject: [PATCH] Adds proper 3d sound? Looks like loading the footstep files every time a sound is played becomes a problem rather quickly. --- voxygen/src/audio/channel.rs | 10 ++++++- voxygen/src/audio/mod.rs | 58 +++++++++++++++++++++++++----------- voxygen/src/scene/sound.rs | 11 ++++--- 3 files changed, 57 insertions(+), 22 deletions(-) diff --git a/voxygen/src/audio/channel.rs b/voxygen/src/audio/channel.rs index 3726592dfd..8517a2f326 100644 --- a/voxygen/src/audio/channel.rs +++ b/voxygen/src/audio/channel.rs @@ -1,5 +1,6 @@ use rodio::SpatialSink; use crate::audio::fader::Fader; +use vek::*; #[derive(PartialEq, Clone, Copy)] pub enum AudioType { @@ -20,6 +21,7 @@ pub struct Channel { audio_type: AudioType, state: ChannelState, fader: Fader, + pub pos: Vec3::, } impl Channel { @@ -30,16 +32,18 @@ impl Channel { audio_type: AudioType::Music, state: ChannelState::Playing, fader: Fader::fade_in(0.0), + pos: Vec3::zero(), } } - pub fn sfx(id: usize, sink: SpatialSink) -> Self { + pub fn sfx(id: usize, sink: SpatialSink, pos: Vec3::) -> Self { Self { id, sink, audio_type: AudioType::Sfx, state: ChannelState::Playing, fader: Fader::fade_in(0.0), + pos } } @@ -64,6 +68,10 @@ impl Channel { self.sink.set_volume(volume); } + pub fn set_emitter_position(&mut self, pos: [f32; 3]) { + self.sink.set_emitter_position(pos); + } + pub fn set_left_ear_position(&mut self, pos: [f32; 3]) { self.sink.set_left_ear_position(pos); } diff --git a/voxygen/src/audio/mod.rs b/voxygen/src/audio/mod.rs index 2a2a040930..75ff3ecf49 100644 --- a/voxygen/src/audio/mod.rs +++ b/voxygen/src/audio/mod.rs @@ -13,7 +13,7 @@ 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; +const FALLOFF : f32 = 0.13; pub struct AudioFrontend { @@ -26,8 +26,12 @@ pub struct AudioFrontend { sfx_volume: f32, music_volume: f32, - listener_pos_left: Vec3::, - listener_pos_right: Vec3::, + + listener_pos: Vec3::, + listener_ori: Vec3::, + + listener_pos_left: [f32; 3], + listener_pos_right: [f32; 3], } impl AudioFrontend { @@ -41,8 +45,10 @@ 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), + listener_pos: Vec3::zero(), + listener_ori: Vec3::zero(), + listener_pos_left: [0.0; 3], + listener_pos_right: [0.0; 3], } } @@ -56,8 +62,10 @@ 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), + listener_pos: Vec3::zero(), + listener_ori: Vec3::zero(), + listener_pos_left: [0.0; 3], + listener_pos_right: [0.0; 3], } } @@ -84,31 +92,47 @@ impl AudioFrontend { self.next_channel_id += 1; if let Some(device) = &self.audio_device { - 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 calc_pos = [ + (pos.x - self.listener_pos.x) * FALLOFF, + (pos.y - self.listener_pos.y) * FALLOFF, + (pos.z - self.listener_pos.z) * FALLOFF, + ]; + let sink = SpatialSink::new(device, calc_pos, + self.listener_pos_left, + self.listener_pos_right); let file = assets::load_file(&sound, &["wav"]).unwrap(); let sound = Decoder::new(file).unwrap(); sink.append(sound); - self.channels.push(Channel::sfx(id, sink)); + self.channels.push(Channel::sfx(id, sink, pos)); } 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; + pub fn set_listener_pos(&mut self, pos: &Vec3::, ori: &Vec3::) { + self.listener_pos = pos.clone(); + self.listener_ori = ori.normalized(); - self.listener_pos_left = pos_left.clone(); - self.listener_pos_right = pos_right.clone(); + let up = Vec3::new(0.0, 0.0, 1.0); + + let pos_left = up.cross(self.listener_ori.clone()).normalized(); + dbg!(pos_left); + let pos_right = self.listener_ori.cross(up.clone()).normalized(); + dbg!(pos_right); + + self.listener_pos_left = pos_left.into_array(); + self.listener_pos_right = pos_right.into_array(); for channel in self.channels.iter_mut() { if channel.get_audio_type() == AudioType::Sfx { + channel.set_emitter_position([ + (channel.pos.x - self.listener_pos.x) * FALLOFF, + (channel.pos.y - self.listener_pos.y) * FALLOFF, + (channel.pos.z - self.listener_pos.z) * FALLOFF, + ]); channel.set_left_ear_position(pos_left.into_array()); channel.set_right_ear_position(pos_right.into_array()); } diff --git a/voxygen/src/scene/sound.rs b/voxygen/src/scene/sound.rs index 02016dc15f..bfc1193c65 100644 --- a/voxygen/src/scene/sound.rs +++ b/voxygen/src/scene/sound.rs @@ -3,6 +3,7 @@ use crate::{ }; use common::comp::{ Pos, + Ori, Body, CharacterState, MovementState::*, @@ -29,17 +30,19 @@ impl SoundMgr { } pub fn maintain(&mut self, audio: &mut AudioFrontend, client: &Client) { - let time = client.state().get_time(); - let tick = client.get_tick(); let ecs = client.state().ecs(); - let dt = client.state().get_delta_time(); // Get player position. let player_pos = ecs .read_storage::() .get(client.entity()) .map_or(Vec3::zero(), |pos| pos.0); - audio.set_listener_pos(&player_pos); + let player_ori = ecs + .read_storage::() + .get(client.entity()) + .map_or(Vec3::zero(), |pos| pos.0); + + audio.set_listener_pos(&player_pos, &player_ori); for (entity, pos, body, character) in ( &ecs.entities(),