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 b5a979c82e
commit 65008f7d54
3 changed files with 57 additions and 22 deletions

View File

@ -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::<f32>,
}
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::<f32>) -> 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);
}

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_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 {
@ -26,8 +26,12 @@ pub struct AudioFrontend {
sfx_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 {
@ -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::<f32>) {
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::<f32>, ori: &Vec3::<f32>) {
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());
}

View File

@ -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::<Pos>()
.get(client.entity())
.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 (
&ecs.entities(),