Fading music/ambient sounds decently upon biome transition

This commit is contained in:
jiminycrick 2020-10-21 15:10:32 -07:00
parent b5aea464f3
commit 0689630d98
12 changed files with 251 additions and 57 deletions

View File

@ -2,14 +2,6 @@
(
tracks: [
(
title: "Forest Day", // Ambience Track
path: "voxygen.audio.ambient.forest_day",
length: 629.0,
timing: Some(Night),
biome: Some(Forest),
artist: "https://www.youtube.com/watch?v=FwVTkB-BIvM",
),
(
title: "Forest Morning", // Ambience Track
path: "voxygen.audio.ambient.forest_morning",
@ -18,5 +10,77 @@
biome: Some(Forest),
artist: "https://www.youtube.com/watch?v=eq4nfIdK6C4",
),
(
title: "Crickets and Tawny Owl", // Ambience Track
path: "voxygen.audio.ambient.grassland_night",
length: 141.0,
timing: Some(Night),
biome: Some(Forest),
artist: "https://freesound.org/people/raoul_slayer/sounds/203598/",
),
//(
// title: "Forest Day", // Ambience Track
// path: "voxygen.audio.ambient.forest_day",
// length: 629.0,
// timing: Some(Night),
// biome: Some(Forest),
// artist: "https://www.youtube.com/watch?v=FwVTkB-BIvM",
//),
(
title: "Desert Night", // Ambience Track
path: "voxygen.audio.ambient.desert_night",
length: 328.0,
timing: Some(Night),
biome: Some(Desert),
artist: "https://freesound.org/people/kangaroovindaloo/sounds/483550/",
),
(
title: "Village Jungle Morning", // Ambience Track
path: "voxygen.audio.ambient.jungle_day",
length: 105.0,
timing: Some(Day),
biome: Some(Swamp),
artist: "https://freesound.org/people/aurelien.leveque/sounds/417635/",
),
(
title: "Jungle in Maharashtra at Night", // Ambience Track
path: "voxygen.audio.ambient.jungle_night",
length: 63.0,
timing: Some(Night),
biome: Some(Swamp),
artist: "https://freesound.org/people/Agim/sounds/417872/",
),
(
title: "Mountain Glacier Distant", // Ambience Track
path: "voxygen.audio.ambient.snowlands",
length: 22.0,
timing: Some(Day),
biome: Some(Snowlands),
artist: "https://freesound.org/people/Eelke/sounds/462623/",
),
(
title: "Mountain Glacier Distant", // Ambience Track
path: "voxygen.audio.ambient.snowlands",
length: 22.0,
timing: Some(Night),
biome: Some(Snowlands),
artist: "https://freesound.org/people/Eelke/sounds/462623/",
),
(
title: "Summer Meadow", // Ambience Track
path: "voxygen.audio.ambient.grassland_day",
length: 92.0,
timing: Some(Day),
biome: Some(Grassland),
artist: "https://freesound.org/people/baryy/sounds/409143/",
),
(
title: "Crickets and Tawny Owl", // Ambience Track
path: "voxygen.audio.ambient.grassland_night",
length: 141.0,
timing: Some(Night),
biome: Some(Grassland),
artist: "https://freesound.org/people/raoul_slayer/sounds/203598/",
),
]
)

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

View File

@ -7,16 +7,16 @@
title: "A Solemn Quest",
path: "voxygen.audio.soundtrack.a_solemn_quest",
length: 206.0,
timing: Some(Night),
biome: Some(Grassland),
timing: Some(Day),
biome: Some(Forest),
artist: "Eden",
),
(
title: "Into The Dark Forest",
path: "voxygen.audio.soundtrack.into_the_dark_forest",
length: 184.0,
timing: Some(Night),
biome: Some(Snowlands),
timing: Some(Day),
biome: Some(Grassland),
artist: "Aeronic",
),
(
@ -24,7 +24,7 @@
path: "voxygen.audio.soundtrack.field_grazing",
length: 154.0,
timing: Some(Day),
biome: Some(Grassland),
biome: Some(Snowlands),
artist: "Aeronic",
),
(
@ -32,7 +32,7 @@
path: "voxygen.audio.soundtrack.wandering_voices",
length: 137.0,
timing: Some(Day),
biome: Some(Grassland),
biome: Some(Desert),
artist: "Aeronic",
),
(
@ -40,7 +40,7 @@
path: "voxygen.audio.soundtrack.snowtop_volume",
length: 89.0,
timing: Some(Day),
biome: Some(Snowlands),
biome: Some(Desert),
artist: "Aeronic",
),
(
@ -48,7 +48,7 @@
path: "voxygen.audio.soundtrack.mineral_deposits",
length: 148.0,
timing: Some(Day),
biome: Some(Forest),
biome: Some(Desert),
artist: "Aeronic",
),
(
@ -56,7 +56,7 @@
path: "voxygen.audio.soundtrack.moonbeams",
length: 158.0,
timing: Some(Night),
biome: Some(Forest),
biome: Some(Desert),
artist: "Aeronic",
),
(
@ -64,7 +64,7 @@
path: "voxygen.audio.soundtrack.serene_meadows",
length: 173.0,
timing: Some(Night),
biome: Some(Snowlands),
biome: Some(Desert),
artist: "Aeronic",
),
/*(
@ -72,7 +72,7 @@
path: "voxygen.audio.soundtrack.rest_assured",
length: 185.0,
timing: Some(Day),
biome: Some(Snowlands),
biome: Some(Desert),
artist: "badbbad",
),*/
(
@ -80,7 +80,7 @@
path: "voxygen.audio.soundtrack.just_the_beginning",
length: 188.0,
timing: Some(Day),
biome: Some(Snowlands),
biome: Some(Desert),
artist: "badbbad",
),
(
@ -88,7 +88,7 @@
path: "voxygen.audio.soundtrack.campfire_stories",
length: 100.0,
timing: Some(Night),
biome: Some(Snowlands),
biome: Some(Desert),
artist: "badbbad",
),
(
@ -96,7 +96,7 @@
path: "voxygen.audio.soundtrack.limits",
length: 203.0,
timing: Some(Night),
biome: Some(Snowlands),
biome: Some(Desert),
artist: "badbbad",
),
/*( // Dungeon
@ -104,7 +104,7 @@
path: "voxygen.audio.soundtrack.down_the_rabbit_hole",
length: 244.0,
timing: Some(Night),
biome: Some(Snowlands),
biome: Some(Desert),
artist: "badbbad",
),*/
(
@ -112,7 +112,7 @@
path: "voxygen.audio.soundtrack.between_the_fairies",
length: 175.0,
timing: Some(Night),
biome: Some(Snowlands),
biome: Some(Desert),
artist: "badbbad",
),
]

View File

@ -54,7 +54,7 @@ struct AmbientSoundtrackCollection {
tracks: Vec<AmbientSoundtrackItem>,
}
/// Configuration for a single music track in the soundtrack
/// Configuration for a single ambient sound track in the soundtrack
#[derive(Debug, Deserialize)]
pub struct AmbientSoundtrackItem {
title: String,
@ -75,14 +75,26 @@ enum DayPeriod {
Night,
}
/// Provides methods to control music playback
/// Determines whether the sound is stopped, playing, or fading
#[derive(Debug, Deserialize, PartialEq)]
enum PlayState {
Playing,
Stopped,
FadingOut,
FadingIn,
}
/// Provides methods to control ambient sound playback
pub struct AmbientMgr {
ambient_soundtrack: AmbientSoundtrackCollection,
began_playing: Instant,
began_fading: Instant,
next_track_change: f64,
/// The title of the last track played. Used to prevent a track
/// being played twice in a row
last_track: String,
last_biome: BiomeKind,
playing: PlayState,
}
impl AmbientMgr {
@ -91,25 +103,45 @@ impl AmbientMgr {
Self {
ambient_soundtrack: Self::load_ambient_soundtrack_items(),
began_playing: Instant::now(),
began_fading: Instant::now(),
next_track_change: 0.0,
last_track: String::from("None"),
last_biome: BiomeKind::Void,
playing: PlayState::Stopped,
}
}
/// 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) {
if audio.music_enabled()
// Gets the current player biome
let current_biome: BiomeKind = match client.current_chunk() {
Some(chunk) => chunk.meta().biome(),
_ => self.last_biome,
};
if audio.music_enabled() // TODO: Change this to ambient_enabled
&& !self.ambient_soundtrack.tracks.is_empty()
&& self.began_playing.elapsed().as_secs_f64() > self.next_track_change
&& (self.began_playing.elapsed().as_secs_f64() > self.next_track_change
|| self.playing == PlayState::Stopped)
&& self.playing != PlayState::FadingOut
{
self.play_random_track(audio, state, client);
self.playing = PlayState::Playing;
} else if current_biome != self.last_biome && self.playing == PlayState::Playing {
audio.fade_out_exploration_ambient();
self.began_fading = Instant::now();
self.playing = PlayState::FadingOut;
} else if self.began_fading.elapsed().as_secs_f64() > 5.0
&& self.playing == PlayState::FadingOut
{
audio.stop_exploration_ambient();
self.playing = PlayState::Stopped;
}
self.last_biome = current_biome;
}
fn play_random_track(&mut self, audio: &mut AudioFrontend, state: &State, client: &Client) {
const SILENCE_BETWEEN_TRACKS_SECONDS: f64 = 45.0;
let game_time = (state.get_time_of_day() as u64 % 86400) as u32;
let current_period_of_day = Self::get_current_day_period(game_time);
let current_biome = Self::get_current_biome(client);
@ -119,12 +151,9 @@ impl AmbientMgr {
.ambient_soundtrack
.tracks
.iter()
.filter(|track| {
!track.title.eq(&self.last_track)
&& match &track.timing {
Some(period_of_day) => period_of_day == &current_period_of_day,
None => true,
}
.filter(|track| match &track.timing {
Some(period_of_day) => period_of_day == &current_period_of_day,
None => true,
})
.filter(|track| match &track.biome {
Some(biome) => biome == &current_biome,
@ -135,8 +164,9 @@ impl AmbientMgr {
if let Some(track) = maybe_track {
self.last_track = String::from(&track.title);
self.began_playing = Instant::now();
self.next_track_change = track.length + SILENCE_BETWEEN_TRACKS_SECONDS;
self.next_track_change = track.length;
audio.fade_in_exploration_ambient();
audio.play_exploration_ambient(&track.path);
}
}
@ -162,7 +192,8 @@ impl AmbientMgr {
Ok(config) => config,
Err(error) => {
warn!(
"Error parsing music config file, music will not be available: {}",
"Error parsing ambient sound config file, ambient sound will not be \
available: {}",
format!("{:#?}", error)
);
@ -171,7 +202,8 @@ impl AmbientMgr {
},
Err(error) => {
warn!(
"Error reading music config file, music will not be available: {}",
"Error reading ambient sound config file, ambient sound will not be \
available: {}",
format!("{:#?}", error)
);

View File

@ -82,7 +82,7 @@ impl MusicChannel {
};
}
/// Stop whatever is playing on a given channel
/// Stop whatever is playing on a given music channel
pub fn stop(&mut self, tag: MusicChannelTag) {
self.tag = tag;
self.sink.stop();
@ -193,6 +193,12 @@ impl AmbientChannel {
};
}
/// Stop whatever is playing on a given channel
pub fn stop(&mut self, tag: AmbientChannelTag) {
self.tag = tag;
self.sink.stop();
}
/// Set the volume of the current channel. If the channel is currently
/// fading, the volume of the fader is updated to this value.
pub fn set_volume(&mut self, volume: f32) {

View File

@ -205,18 +205,49 @@ impl AudioFrontend {
let sound = Decoder::new(file).expect("Failed to decode sound");
channel.play(sound, channel_tag);
//channel.set_fader(Fader::fade_in(2.0, music_volume));
}
}
fn fade_out_music(&mut self, channel_tag: MusicChannelTag) {
let music_volume = self.music_volume;
if let Some(channel) = self.get_music_channel(channel_tag) {
channel.set_fader(Fader::fade_out(5.0, music_volume));
}
}
fn fade_in_music(&mut self, channel_tag: MusicChannelTag) {
let music_volume = self.music_volume;
if let Some(channel) = self.get_music_channel(channel_tag) {
channel.set_fader(Fader::fade_in(5.0, music_volume));
}
}
fn stop_music(&mut self, channel_tag: MusicChannelTag) {
let music_volume = self.music_volume;
if let Some(channel) = self.get_music_channel(channel_tag) {
//channel.set_fader(Fader::fade_out(5.0, music_volume));
channel.stop(channel_tag);
}
}
fn stop_ambient(&mut self, channel_tag: AmbientChannelTag) {
if let Some(channel) = self.get_ambient_channel(channel_tag) {
channel.stop(channel_tag);
}
}
fn fade_out_ambient(&mut self, channel_tag: AmbientChannelTag) {
let ambient_volume = self.ambient_volume;
if let Some(channel) = self.get_ambient_channel(channel_tag) {
channel.set_fader(Fader::fade_out(2.0, ambient_volume));
}
}
fn fade_in_ambient(&mut self, channel_tag: AmbientChannelTag) {
let ambient_volume = self.ambient_volume;
if let Some(channel) = self.get_ambient_channel(channel_tag) {
channel.set_fader(Fader::fade_in(2.0, ambient_volume));
}
}
fn play_ambient(&mut self, sound: &str, channel_tag: AmbientChannelTag) {
if let Some(channel) = self.get_ambient_channel(channel_tag) {
let file = assets::load_file(&sound, &["ogg"]).expect("Failed to load sound");
@ -258,6 +289,18 @@ impl AudioFrontend {
}
}
pub fn fade_out_exploration_music(&mut self) {
if self.music_enabled() {
self.fade_out_music(MusicChannelTag::Exploration)
}
}
pub fn fade_in_exploration_music(&mut self) {
if self.music_enabled() {
self.fade_in_music(MusicChannelTag::Exploration)
}
}
pub fn stop_exploration_music(&mut self) {
if self.music_enabled() {
self.stop_music(MusicChannelTag::Exploration)
@ -265,11 +308,29 @@ impl AudioFrontend {
}
pub fn play_exploration_ambient(&mut self, item: &str) {
if self.ambient_enabled() {
if self.music_enabled() {
self.play_ambient(item, AmbientChannelTag::Exploration)
}
}
pub fn fade_out_exploration_ambient(&mut self) {
if self.music_enabled() {
self.fade_out_ambient(AmbientChannelTag::Exploration)
}
}
pub fn fade_in_exploration_ambient(&mut self) {
if self.music_enabled() {
self.fade_in_ambient(AmbientChannelTag::Exploration)
}
}
pub fn stop_exploration_ambient(&mut self) {
if self.music_enabled() {
self.stop_ambient(AmbientChannelTag::Exploration)
}
}
pub fn get_sfx_volume(&self) -> f32 { self.sfx_volume }
pub fn get_music_volume(&self) -> f32 { self.music_volume }

View File

@ -75,16 +75,26 @@ enum DayPeriod {
Night,
}
/// Determines whether the sound is stopped, playing, or fading
#[derive(Debug, Deserialize, PartialEq)]
enum PlayState {
Playing,
Stopped,
FadingOut,
FadingIn,
}
/// Provides methods to control music playback
pub struct MusicMgr {
soundtrack: SoundtrackCollection,
began_playing: Instant,
began_fading: Instant,
next_track_change: f64,
/// The title of the last track played. Used to prevent a track
/// being played twice in a row
last_track: String,
last_biome: BiomeKind,
playing: bool,
playing: PlayState,
}
impl MusicMgr {
@ -93,10 +103,11 @@ impl MusicMgr {
Self {
soundtrack: Self::load_soundtrack_items(),
began_playing: Instant::now(),
began_fading: Instant::now(),
next_track_change: 0.0,
last_track: String::from("None"),
last_biome: BiomeKind::Void,
playing: false,
playing: PlayState::Stopped,
}
}
@ -112,25 +123,27 @@ impl MusicMgr {
if audio.music_enabled()
&& !self.soundtrack.tracks.is_empty()
&& (self.began_playing.elapsed().as_secs_f64() > self.next_track_change
|| !self.playing)
|| self.playing == PlayState::Stopped)
&& self.playing != PlayState::FadingOut
{
println!("It shoooooooooooooooooooooooooooooooooooooooooooooooooooooooould play!!!");
self.play_random_track(audio, state, client);
self.playing = true;
} else if current_biome != self.last_biome {
println!(
"SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSStop!\
!!"
);
self.playing = PlayState::Playing;
} else if current_biome != self.last_biome && self.playing == PlayState::Playing {
audio.fade_out_exploration_music();
self.began_fading = Instant::now();
self.playing = PlayState::FadingOut;
} else if self.began_fading.elapsed().as_secs_f64() > 5.0
&& self.playing == PlayState::FadingOut
{
audio.stop_exploration_music();
self.playing = false;
self.playing = PlayState::Stopped;
}
self.last_biome = current_biome;
}
fn play_random_track(&mut self, audio: &mut AudioFrontend, state: &State, client: &Client) {
//const SILENCE_BETWEEN_TRACKS_SECONDS: f64 = 45.0;
const SILENCE_BETWEEN_TRACKS_SECONDS: f64 = 5.0;
const SILENCE_BETWEEN_TRACKS_SECONDS: f64 = 45.0;
//const SILENCE_BETWEEN_TRACKS_SECONDS: f64 = 5.0;
let game_time = (state.get_time_of_day() as u64 % 86400) as u32;
let current_period_of_day = Self::get_current_day_period(game_time);