Adds proper 3d sound?

Looks like loading the footstep files every time a sound is played
becomes a problem rather quickly.
This commit is contained in:
Louis Pearson 2019-09-01 15:40:54 -06:00
parent 18d84da929
commit a5b9a2e02c
3 changed files with 57 additions and 22 deletions

View File

@ -1,5 +1,6 @@
use rodio::SpatialSink; use rodio::SpatialSink;
use crate::audio::fader::Fader; use crate::audio::fader::Fader;
use vek::*;
#[derive(PartialEq, Clone, Copy)] #[derive(PartialEq, Clone, Copy)]
pub enum AudioType { pub enum AudioType {
@ -20,6 +21,7 @@ pub struct Channel {
audio_type: AudioType, audio_type: AudioType,
state: ChannelState, state: ChannelState,
fader: Fader, fader: Fader,
pub pos: Vec3::<f32>,
} }
impl Channel { impl Channel {
@ -30,16 +32,18 @@ impl Channel {
audio_type: AudioType::Music, audio_type: AudioType::Music,
state: ChannelState::Playing, state: ChannelState::Playing,
fader: Fader::fade_in(0.0), 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::<f32>) -> Self {
Self { Self {
id, id,
sink, sink,
audio_type: AudioType::Sfx, audio_type: AudioType::Sfx,
state: ChannelState::Playing, state: ChannelState::Playing,
fader: Fader::fade_in(0.0), fader: Fader::fade_in(0.0),
pos
} }
} }
@ -64,6 +68,10 @@ impl Channel {
self.sink.set_volume(volume); 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]) { pub fn set_left_ear_position(&mut self, pos: [f32; 3]) {
self.sink.set_left_ear_position(pos); self.sink.set_left_ear_position(pos);
} }

View File

@ -13,7 +13,7 @@ const RIGHT_EAR : [f32; 3] = [-1.0, 0.0, 0.0];
const EAR_LEFT : Vec3<f32> = Vec3::new(1.0, 0.0, 0.0); const EAR_LEFT : Vec3<f32> = Vec3::new(1.0, 0.0, 0.0);
const EAR_RIGHT : Vec3<f32> = Vec3::new(-1.0, 0.0, 0.0); const EAR_RIGHT : Vec3<f32> = Vec3::new(-1.0, 0.0, 0.0);
const LISTEN_DISTANCE : f32 = 25.0; const FALLOFF : f32 = 0.13;
pub struct AudioFrontend { pub struct AudioFrontend {
@ -26,8 +26,12 @@ pub struct AudioFrontend {
sfx_volume: f32, sfx_volume: f32,
music_volume: f32, music_volume: f32,
listener_pos_left: Vec3::<f32>,
listener_pos_right: Vec3::<f32>, listener_pos: Vec3::<f32>,
listener_ori: Vec3::<f32>,
listener_pos_left: [f32; 3],
listener_pos_right: [f32; 3],
} }
impl AudioFrontend { impl AudioFrontend {
@ -41,8 +45,10 @@ impl AudioFrontend {
next_channel_id: 0, next_channel_id: 0,
sfx_volume: 1.0, sfx_volume: 1.0,
music_volume: 1.0, music_volume: 1.0,
listener_pos_left: Vec3::from_slice(&LEFT_EAR), listener_pos: Vec3::zero(),
listener_pos_right: Vec3::from_slice(&RIGHT_EAR), 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, next_channel_id: 0,
sfx_volume: 1.0, sfx_volume: 1.0,
music_volume: 1.0, music_volume: 1.0,
listener_pos_left: Vec3::from_slice(&LEFT_EAR), listener_pos: Vec3::zero(),
listener_pos_right: Vec3::from_slice(&RIGHT_EAR), 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; self.next_channel_id += 1;
if let Some(device) = &self.audio_device { if let Some(device) = &self.audio_device {
let pos = pos / LISTEN_DISTANCE; let calc_pos = [
let sink = SpatialSink::new(device, pos.into_array(), (pos.x - self.listener_pos.x) * FALLOFF,
self.listener_pos_left.into_array(), (pos.y - self.listener_pos.y) * FALLOFF,
self.listener_pos_right.into_array()); (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 file = assets::load_file(&sound, &["wav"]).unwrap();
let sound = Decoder::new(file).unwrap(); let sound = Decoder::new(file).unwrap();
sink.append(sound); sink.append(sound);
self.channels.push(Channel::sfx(id, sink)); self.channels.push(Channel::sfx(id, sink, pos));
} }
id id
} }
pub fn set_listener_pos(&mut self, pos: &Vec3::<f32>) { pub fn set_listener_pos(&mut self, pos: &Vec3::<f32>, ori: &Vec3::<f32>) {
let pos_left = (pos.clone() + EAR_LEFT) / LISTEN_DISTANCE; self.listener_pos = pos.clone();
let pos_right = (pos.clone() + EAR_RIGHT) / LISTEN_DISTANCE; self.listener_ori = ori.normalized();
self.listener_pos_left = pos_left.clone(); let up = Vec3::new(0.0, 0.0, 1.0);
self.listener_pos_right = pos_right.clone();
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() { for channel in self.channels.iter_mut() {
if channel.get_audio_type() == AudioType::Sfx { 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_left_ear_position(pos_left.into_array());
channel.set_right_ear_position(pos_right.into_array()); channel.set_right_ear_position(pos_right.into_array());
} }

View File

@ -3,6 +3,7 @@ use crate::{
}; };
use common::comp::{ use common::comp::{
Pos, Pos,
Ori,
Body, Body,
CharacterState, CharacterState,
MovementState::*, MovementState::*,
@ -29,17 +30,19 @@ impl SoundMgr {
} }
pub fn maintain(&mut self, audio: &mut AudioFrontend, client: &Client) { 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 ecs = client.state().ecs();
let dt = client.state().get_delta_time();
// Get player position. // Get player position.
let player_pos = ecs let player_pos = ecs
.read_storage::<Pos>() .read_storage::<Pos>()
.get(client.entity()) .get(client.entity())
.map_or(Vec3::zero(), |pos| pos.0); .map_or(Vec3::zero(), |pos| pos.0);
audio.set_listener_pos(&player_pos); let player_ori = ecs
.read_storage::<Ori>()
.get(client.entity())
.map_or(Vec3::zero(), |pos| pos.0);
audio.set_listener_pos(&player_pos, &player_ori);
for (entity, pos, body, character) in ( for (entity, pos, body, character) in (
&ecs.entities(), &ecs.entities(),