added sound for rain

This commit is contained in:
Benjam Soule H. Walker 2021-11-20 01:46:14 +00:00 committed by IsseW
parent 502145a6f9
commit 99c76be297
7 changed files with 195 additions and 57 deletions

View File

@ -2,8 +2,12 @@
tracks: [
(
path: "voxygen.audio.ambient.wind",
length: 14.2,
length: 14.203,
tag: Wind,
),
), (
path: "voxygen.audio.ambient.rain",
length: 17.0,
tag: Rain,
),
]
)

BIN
assets/voxygen/audio/ambient/rain.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/audio/sfx/ambient/rain_sfx.ogg (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -29,18 +29,26 @@ pub struct AmbientItem {
tag: AmbientChannelTag,
}
pub struct AmbientMgr {
soundtrack: AssetHandle<AmbientCollection>,
pub struct AmbientWindMgr {
ambience: AssetHandle<AmbientCollection>,
began_playing: Instant,
next_track_change: f32,
volume: f32,
tree_multiplier: f32,
}
impl Default for AmbientMgr {
pub struct AmbientRainMgr {
ambience: AssetHandle<AmbientCollection>,
began_playing: Instant,
next_track_change: f32,
volume: f32,
rain_intensity: f32,
}
impl Default for AmbientWindMgr {
fn default() -> Self {
Self {
soundtrack: Self::load_soundtrack_items(),
ambience: load_ambience_items(),
began_playing: Instant::now(),
next_track_change: 0.0,
volume: 0.0,
@ -49,7 +57,19 @@ impl Default for AmbientMgr {
}
}
impl AmbientMgr {
impl Default for AmbientRainMgr {
fn default() -> Self {
Self {
ambience: load_ambience_items(),
began_playing: Instant::now(),
next_track_change: 0.0,
volume: 0.0,
rain_intensity: 0.0,
}
}
}
impl AmbientWindMgr {
/// Checks whether the previous track has completed. If so, sends a
/// request to play the next (random) track
pub fn maintain(
@ -59,7 +79,7 @@ impl AmbientMgr {
client: &Client,
camera: &Camera,
) {
if audio.sfx_enabled() && !self.soundtrack.read().tracks.is_empty() {
if audio.sfx_enabled() && !self.ambience.read().tracks.is_empty() {
let focus_off = camera.get_focus_pos().map(f32::trunc);
let cam_pos = camera.dependents().cam_pos + focus_off;
@ -95,6 +115,7 @@ impl AmbientMgr {
{
volume_multiplier *= 0.1;
}
// Is the camera roughly under the terrain?
if cam_pos.z < terrain_alt - 10.0 {
volume_multiplier = 0.0;
}
@ -103,40 +124,121 @@ impl AmbientMgr {
};
// Transitions the ambient sounds (more) smoothly
self.volume = audio.get_ambient_volume();
audio.set_ambient_volume(Lerp::lerp(self.volume, target_volume, 0.01));
if audio.get_ambient_channel(AmbientChannelTag::Wind).is_none() {
audio.new_ambient_channel(AmbientChannelTag::Wind);
} else {
self.volume = audio.get_ambient_volume(AmbientChannelTag::Wind);
audio.set_ambient_volume(
AmbientChannelTag::Wind,
Lerp::lerp(self.volume, target_volume, 0.01),
);
}
if self.began_playing.elapsed().as_secs_f32() > self.next_track_change {
// Right now there is only wind non-positional sfx so it is always
// selected. Modify this variable assignment when adding other non-
// positional sfx
let soundtrack = self.soundtrack.read();
let track = &soundtrack
let ambience = self.ambience.read();
let wind_track = &ambience
.tracks
.iter()
.find(|track| track.tag == AmbientChannelTag::Wind);
if let Some(track) = track {
self.began_playing = Instant::now();
self.next_track_change = track.length;
audio.play_ambient(AmbientChannelTag::Wind, &track.path, target_volume);
self.began_playing = Instant::now();
if let Some(wind_track) = wind_track {
self.next_track_change = wind_track.length;
audio.play_ambient(AmbientChannelTag::Wind, &wind_track.path, target_volume);
}
}
}
}
}
fn load_soundtrack_items() -> AssetHandle<AmbientCollection> {
AmbientCollection::load_or_insert_with("voxygen.audio.ambient", |error| {
warn!(
"Error reading ambience config file, ambience will not be available: {:#?}",
error
);
AmbientCollection::default()
})
impl AmbientRainMgr {
/// Checks whether the previous track has completed. If so, sends a
/// request to play the next (random) track
pub fn maintain(
&mut self,
audio: &mut AudioFrontend,
state: &State,
client: &Client,
camera: &Camera,
) {
if audio.sfx_enabled() && !self.ambience.read().tracks.is_empty() {
let focus_off = camera.get_focus_pos().map(f32::trunc);
let cam_pos = camera.dependents().cam_pos + focus_off;
let terrain_alt = if let Some(chunk) = client.current_chunk() {
chunk.meta().alt()
} else {
0.0
};
// multipler at end will have to change depending on how intense rain normally
// is
self.rain_intensity = client.current_weather().rain * 5.0;
let mut volume_multiplier = self.rain_intensity;
// TODO: make rain diminish with distance above terrain
let target_volume = {
// Checks if the camera is underwater to stop ambient sounds
if state
.terrain()
.get((cam_pos).map(|e| e.floor() as i32))
.map(|b| b.is_liquid())
.unwrap_or(false)
{
volume_multiplier *= 0.1;
}
// Is the camera roughly under the terrain?
if cam_pos.z < terrain_alt - 10.0 {
volume_multiplier = 0.0;
}
volume_multiplier = volume_multiplier.clamped(0.0, 1.0);
// possibly remove noise
if volume_multiplier < 0.05 {
0.0
} else {
volume_multiplier
}
};
// Transitions the ambient sounds (more) smoothly
if audio.get_ambient_channel(AmbientChannelTag::Rain).is_none() {
audio.new_ambient_channel(AmbientChannelTag::Rain);
} else {
self.volume = audio.get_ambient_volume(AmbientChannelTag::Rain);
audio.set_ambient_volume(
AmbientChannelTag::Rain,
Lerp::lerp(self.volume, target_volume, 0.01),
);
}
if self.began_playing.elapsed().as_secs_f32() > self.next_track_change {
let ambience = self.ambience.read();
let rain_track = &ambience
.tracks
.iter()
.find(|track| track.tag == AmbientChannelTag::Rain);
self.began_playing = Instant::now();
if let Some(rain_track) = rain_track {
self.next_track_change = rain_track.length;
audio.play_ambient(AmbientChannelTag::Rain, &rain_track.path, target_volume);
}
}
}
}
}
fn load_ambience_items() -> AssetHandle<AmbientCollection> {
AmbientCollection::load_or_insert_with("voxygen.audio.ambient", |error| {
warn!(
"Error reading ambience config file, ambience will not be available: {:#?}",
error
);
AmbientCollection::default()
})
}
impl assets::Asset for AmbientCollection {
type Loader = assets::RonLoader;

View File

@ -160,6 +160,7 @@ impl MusicChannel {
#[derive(Debug, PartialEq, Clone, Copy, Deserialize)]
pub enum AmbientChannelTag {
Wind,
Rain,
}
/// A AmbientChannel uses a non-positional audio sink designed to play sounds
/// which are always heard at the camera's position.
@ -179,7 +180,7 @@ impl AmbientChannel {
sink,
},
Err(_) => {
warn!("Failed to create rodio sink. May not play wind sounds.");
warn!("Failed to create rodio sink. May not play ambient sounds.");
Self {
tag,
multiplier,
@ -207,6 +208,8 @@ impl AmbientChannel {
pub fn get_volume(&mut self) -> f32 { self.sink.volume() }
pub fn get_multiplier(&mut self) -> f32 { self.multiplier }
pub fn get_tag(&self) -> AmbientChannelTag { self.tag }
}

View File

@ -287,6 +287,7 @@ impl AudioFrontend {
Ok(())
}
// plays a file at a given volume in the channel with a given tag
fn play_ambient(
&mut self,
channel_tag: AmbientChannelTag,
@ -294,52 +295,63 @@ impl AudioFrontend {
volume_multiplier: f32,
) {
if self.audio_stream.is_some() {
if let Some(channel) = self.get_ambient_channel(channel_tag, volume_multiplier) {
if let Some(channel) = self.get_ambient_channel(channel_tag) {
channel.set_volume(volume_multiplier);
channel.play(load_ogg(sound));
}
}
}
// adds a new ambient channel of the given tag at zero volume
fn new_ambient_channel(&mut self, channel_tag: AmbientChannelTag) {
if let Some(audio_stream) = &self.audio_stream {
let ambient_channel = AmbientChannel::new(audio_stream, channel_tag, 0.0);
self.ambient_channels.push(ambient_channel);
}
}
// retrieves the channel currently having the given tag
fn get_ambient_channel(
&mut self,
channel_tag: AmbientChannelTag,
volume_multiplier: f32,
) -> Option<&mut AmbientChannel> {
if let Some(audio_stream) = &self.audio_stream {
if self.ambient_channels.is_empty() {
let mut ambient_channel =
AmbientChannel::new(audio_stream, channel_tag, volume_multiplier);
ambient_channel.set_volume(self.get_sfx_volume());
self.ambient_channels.push(ambient_channel);
} else {
let sfx_volume = self.get_sfx_volume();
for channel in self.ambient_channels.iter_mut() {
if channel.get_tag() == channel_tag {
channel.set_multiplier(volume_multiplier);
channel.set_volume(sfx_volume);
return Some(channel);
}
if self.audio_stream.is_some() {
let mut tag_match = false;
let mut found_channel = None;
for channel in self.ambient_channels.iter_mut() {
if channel.get_tag() == channel_tag {
tag_match = true;
found_channel = Some(channel);
break;
}
}
if tag_match {
return found_channel;
} else {
return None;
}
} else {
return None;
}
None
}
fn set_ambient_volume(&mut self, volume_multiplier: f32) {
// sets the volume of the channel with the given tag to the given volume
fn set_ambient_volume(&mut self, channel_tag: AmbientChannelTag, volume_multiplier: f32) {
if self.audio_stream.is_some() {
let sfx_volume = self.get_sfx_volume();
if let Some(channel) = self.ambient_channels.iter_mut().last() {
if let Some(channel) = self.get_ambient_channel(channel_tag) {
channel.set_multiplier(volume_multiplier);
channel.set_volume(sfx_volume);
}
}
}
fn get_ambient_volume(&mut self) -> f32 {
// retrieves volume (pre-sfx-setting) of the channel with a given tag
fn get_ambient_volume(&mut self, channel_tag: AmbientChannelTag) -> f32 {
if self.audio_stream.is_some() {
if let Some(channel) = self.ambient_channels.iter_mut().last() {
channel.get_volume() / self.get_sfx_volume()
if let Some(channel) = self.get_ambient_channel(channel_tag) {
let channel_multiplier = channel.get_multiplier();
channel_multiplier
} else {
0.0
}
@ -406,8 +418,10 @@ impl AudioFrontend {
}
}
// this retrieves the current setting for sfx volume
pub fn get_sfx_volume(&self) -> f32 { self.sfx_volume * self.master_volume }
// this retrieves the current setting for music volume
pub fn get_music_volume(&self) -> f32 { self.music_volume * self.master_volume }
pub fn sfx_enabled(&self) -> bool { self.get_sfx_volume() > 0.0 }

View File

@ -19,7 +19,12 @@ pub use self::{
trail::TrailMgr,
};
use crate::{
audio::{ambient::AmbientMgr, music::MusicMgr, sfx::SfxMgr, AudioFrontend},
audio::{
ambient::{AmbientRainMgr, AmbientWindMgr},
music::MusicMgr,
sfx::SfxMgr,
AudioFrontend,
},
render::{
create_skybox_mesh, CloudsLocals, Consts, Drawer, GlobalModel, Globals, GlobalsBindGroup,
Light, Model, PointLightMatrix, PostProcessLocals, Renderer, Shadow, ShadowLocals,
@ -102,7 +107,8 @@ pub struct Scene {
figure_mgr: FigureMgr,
pub sfx_mgr: SfxMgr,
music_mgr: MusicMgr,
ambient_mgr: AmbientMgr,
ambient_wind_mgr: AmbientWindMgr,
ambient_rain_mgr: AmbientRainMgr,
}
pub struct SceneData<'a> {
@ -314,7 +320,8 @@ impl Scene {
figure_mgr: FigureMgr::new(renderer),
sfx_mgr: SfxMgr::default(),
music_mgr: MusicMgr::default(),
ambient_mgr: AmbientMgr::default(),
ambient_wind_mgr: AmbientWindMgr::default(),
ambient_rain_mgr: AmbientRainMgr::default(),
}
}
@ -1066,7 +1073,9 @@ impl Scene {
client,
);
self.music_mgr.maintain(audio, scene_data.state, client);
self.ambient_mgr
self.ambient_wind_mgr
.maintain(audio, scene_data.state, client, &self.camera);
self.ambient_rain_mgr
.maintain(audio, scene_data.state, client, &self.camera);
}