WIP: New music, "now playing" line in debug overlay, and music frequency slider

This commit is contained in:
DaforLynx 2022-08-01 17:41:44 +00:00 committed by Marcel
parent d059eefcc8
commit bf4a582cf7
13 changed files with 161 additions and 24 deletions

View File

@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
### Added ### Added
- Currently playing music track and artist now shows in the debug menu.
- Added a setting to influence the gap between music track plays.
### Changed ### Changed

View File

@ -12,6 +12,31 @@
[ [
// Overworld exploration tracks // Overworld exploration tracks
Individual((
title: "The Undergrowth",
path: "voxygen.audio.soundtrack.overworld.the_undergrowth",
length: 165.0,
timing: None,
biomes: [
(Jungle, 1),
],
site: Some(Void),
music_state: Activity(Explore),
artist: "Oolnokk",
)),
Individual((
title: "Moonlit Canopy",
path: "voxygen.audio.soundtrack.overworld.moonlit_canopy",
length: 170.0,
timing: Some(Night),
biomes: [
(Forest, 2),
(Taiga, 1),
],
site: Some(Void),
music_state: Activity(Explore),
artist: "GeekyGami",
)),
Individual(( Individual((
title: "Adventurous Soul", title: "Adventurous Soul",
path: "voxygen.audio.soundtrack.overworld.adventurous_soul", path: "voxygen.audio.soundtrack.overworld.adventurous_soul",
@ -129,7 +154,7 @@
title: "Jungle Ambient", title: "Jungle Ambient",
path: "voxygen.audio.soundtrack.overworld.jungle_ambient", path: "voxygen.audio.soundtrack.overworld.jungle_ambient",
length: 218.0, length: 218.0,
timing: Some(Day), timing: None,
weather: None, weather: None,
biomes: [ biomes: [
(Jungle, 1), (Jungle, 1),
@ -283,8 +308,6 @@
weather: None, weather: None,
biomes: [ biomes: [
(Forest, 2), (Forest, 2),
(Jungle, 1),
(Taiga, 1),
], ],
site: Some(Void), site: Some(Void),
music_state: Activity(Explore), music_state: Activity(Explore),
@ -649,28 +672,29 @@
Segmented( Segmented(
title: "Barred Paths", title: "Barred Paths",
author: "DaforLynx",
timing: None, timing: None,
weather: None, weather: None,
biomes: [], biomes: [],
site: Some(Dungeon), site: Some(Dungeon),
segments: [ segments: [
("voxygen.audio.soundtrack.combat.barred_paths.barred_paths-start", 55.97, Transition(Explore, Combat(High)), Some(Combat(High))), ("voxygen.audio.soundtrack.combat.barred_paths.barred_paths-start", 56.0, Transition(Explore, Combat(High)), Some(Combat(High))),
("voxygen.audio.soundtrack.combat.barred_paths.barred_paths-loop", 53.97, Activity(Combat(High)), None), ("voxygen.audio.soundtrack.combat.barred_paths.barred_paths-loop", 54.0, Activity(Combat(High)), None),
("voxygen.audio.soundtrack.combat.barred_paths.barred_paths-end", 6.0, Transition(Combat(High), Explore), None), ("voxygen.audio.soundtrack.combat.barred_paths.barred_paths-end", 6.0, Transition(Combat(High), Explore), None),
], ],
artist: "DaforLynx",
), ),
Segmented( Segmented(
title: "Reversal", title: "Reversal",
author: "DaforLynx",
timing: None, timing: None,
weather: None,
biomes: [], biomes: [],
site: Some(Dungeon), site: Some(Dungeon),
segments: [ segments: [
("voxygen.audio.soundtrack.combat.reversal.reversal-start", 59.97, Transition(Explore, Combat(High)), Some(Combat(High))), ("voxygen.audio.soundtrack.combat.reversal.reversal-start", 60.0, Transition(Explore, Combat(High)), Some(Combat(High))),
("voxygen.audio.soundtrack.combat.reversal.reversal-loop", 59.97, Activity(Combat(High)), None), ("voxygen.audio.soundtrack.combat.reversal.reversal-loop", 60.0, Activity(Combat(High)), None),
("voxygen.audio.soundtrack.combat.reversal.reversal-end", 4.0, Transition(Combat(High), Explore), None), ("voxygen.audio.soundtrack.combat.reversal.reversal-end", 4.0, Transition(Combat(High), Explore), None),
], ],
artist: "DaforLynx",
), ),
] ]
) )

BIN
assets/voxygen/audio/soundtrack/overworld/moonlit_canopy.ogg (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

View File

@ -120,6 +120,7 @@
"hud.settings.music_volume": "Music Volume", "hud.settings.music_volume": "Music Volume",
"hud.settings.sound_effect_volume": "Sound Effects Volume", "hud.settings.sound_effect_volume": "Sound Effects Volume",
"hud.settings.ambience_volume": "Ambience Volume", "hud.settings.ambience_volume": "Ambience Volume",
"hud.settings.music_frequency": "Gap Between Songs",
"hud.settings.audio_device": "Audio Device", "hud.settings.audio_device": "Audio Device",
"hud.settings.reset_sound": "Reset to Defaults", "hud.settings.reset_sound": "Reset to Defaults",

View File

@ -55,6 +55,7 @@ pub struct AudioFrontend {
ambience_volume: f32, ambience_volume: f32,
music_volume: f32, music_volume: f32,
master_volume: f32, master_volume: f32,
music_frequency: f32,
listener: Listener, listener: Listener,
mtm: AssetHandle<MusicTransitionManifest>, mtm: AssetHandle<MusicTransitionManifest>,
@ -107,6 +108,7 @@ impl AudioFrontend {
ambience_volume: 1.0, ambience_volume: 1.0,
music_volume: 1.0, music_volume: 1.0,
master_volume: 1.0, master_volume: 1.0,
music_frequency: 1.0,
listener: Listener::default(), listener: Listener::default(),
mtm: AssetExt::load_expect("voxygen.audio.music_transition_manifest"), mtm: AssetExt::load_expect("voxygen.audio.music_transition_manifest"),
} }
@ -138,6 +140,7 @@ impl AudioFrontend {
ambience_volume: 1.0, ambience_volume: 1.0,
music_volume: 1.0, music_volume: 1.0,
master_volume: 1.0, master_volume: 1.0,
music_frequency: 1.0,
listener: Listener::default(), listener: Listener::default(),
mtm, mtm,
} }
@ -179,6 +182,14 @@ impl AudioFrontend {
None None
} }
fn play_music(&mut self, sound: &str, channel_tag: MusicChannelTag) {
if self.music_enabled() {
if let Some(channel) = self.get_music_channel(channel_tag) {
channel.play(load_ogg(sound), channel_tag);
}
}
}
/// Retrieve a music channel from the channel list. This inspects the /// Retrieve a music channel from the channel list. This inspects the
/// MusicChannelTag to determine whether we are transitioning between /// MusicChannelTag to determine whether we are transitioning between
/// music types and acts accordingly. For example transitioning between /// music types and acts accordingly. For example transitioning between
@ -373,14 +384,6 @@ impl AudioFrontend {
// } // }
// } // }
fn play_music(&mut self, sound: &str, channel_tag: MusicChannelTag) {
if self.music_enabled() {
if let Some(channel) = self.get_music_channel(channel_tag) {
channel.play(load_ogg(sound), channel_tag);
}
}
}
/* These functions are saved for if we want music playback control at some /* These functions are saved for if we want music playback control at some
* point. They are not used currently but may be useful for later work. * point. They are not used currently but may be useful for later work.
* *
@ -476,6 +479,8 @@ impl AudioFrontend {
} }
} }
pub fn set_music_frequency(&mut self, multiplier: f32) { self.music_frequency = multiplier }
/// Updates master volume in all channels /// Updates master volume in all channels
pub fn set_master_volume(&mut self, master_volume: f32) { pub fn set_master_volume(&mut self, master_volume: f32) {
self.master_volume = master_volume; self.master_volume = master_volume;

View File

@ -93,6 +93,8 @@ pub struct SoundtrackItem {
/// transitions) /// transitions)
#[serde(default)] #[serde(default)]
activity_override: Option<MusicActivity>, activity_override: Option<MusicActivity>,
/// Song artist
artist: String,
} }
#[derive(Clone, Debug, Deserialize)] #[derive(Clone, Debug, Deserialize)]
@ -105,6 +107,7 @@ enum RawSoundtrackItem {
biomes: Vec<(BiomeKind, u8)>, biomes: Vec<(BiomeKind, u8)>,
site: Option<SitesKind>, site: Option<SitesKind>,
segments: Vec<(String, f32, MusicState, Option<MusicActivity>)>, segments: Vec<(String, f32, MusicState, Option<MusicActivity>)>,
artist: String,
}, },
} }
@ -159,6 +162,10 @@ pub struct MusicMgr {
last_interrupt: Instant, last_interrupt: Instant,
/// The previous track's activity kind, for transitions /// The previous track's activity kind, for transitions
last_activity: MusicState, last_activity: MusicState,
// For debug menu
pub current_track: String,
pub current_artist: String,
track_length: f32,
} }
#[derive(Deserialize)] #[derive(Deserialize)]
@ -206,6 +213,9 @@ impl Default for MusicMgr {
last_track: String::from("None"), last_track: String::from("None"),
last_interrupt: Instant::now(), last_interrupt: Instant::now(),
last_activity: MusicState::Activity(MusicActivity::Explore), last_activity: MusicState::Activity(MusicActivity::Explore),
current_track: String::from("None"),
current_artist: String::from("None"),
track_length: 0.0,
} }
} }
} }
@ -294,6 +304,12 @@ impl MusicMgr {
let interrupt = matches!(music_state, MusicState::Transition(_, _)) let interrupt = matches!(music_state, MusicState::Transition(_, _))
&& self.last_interrupt.elapsed().as_secs_f32() > mtm.interrupt_delay; && self.last_interrupt.elapsed().as_secs_f32() > mtm.interrupt_delay;
// When the current track ends, clear the debug values
if self.began_playing.elapsed().as_secs_f32() > self.track_length {
self.current_track = String::from("None");
self.current_artist = String::from("None");
}
if audio.music_enabled() if audio.music_enabled()
&& !self.soundtrack.read().tracks.is_empty() && !self.soundtrack.read().tracks.is_empty()
&& (self.began_playing.elapsed().as_secs_f32() > self.next_track_change || interrupt) && (self.began_playing.elapsed().as_secs_f32() > self.next_track_change || interrupt)
@ -325,20 +341,29 @@ impl MusicMgr {
// a town, or exploring. // a town, or exploring.
// TODO: make this something that is decided when a song ends, instead of when // TODO: make this something that is decided when a song ends, instead of when
// it begins // it begins
let frequency_multipler = audio.music_frequency;
let silence_between_tracks_seconds: f32 = let silence_between_tracks_seconds: f32 =
if matches!(music_state, MusicState::Activity(MusicActivity::Explore)) if matches!(music_state, MusicState::Activity(MusicActivity::Explore))
&& matches!(client.current_site(), SitesKind::Settlement) && matches!(client.current_site(), SitesKind::Settlement)
{ {
rng.gen_range(100.0..130.0) rng.gen_range(120.0 * frequency_multipler..180.0 * frequency_multipler)
} else if matches!(music_state, MusicState::Activity(MusicActivity::Explore))
&& matches!(client.current_site(), SitesKind::Dungeon)
{
rng.gen_range(10.0 * frequency_multipler..20.0 * frequency_multipler)
} else if matches!(music_state, MusicState::Activity(MusicActivity::Explore))
&& matches!(client.current_site(), SitesKind::Cave)
{
rng.gen_range(20.0 * frequency_multipler..40.0 * frequency_multipler)
} else if matches!(music_state, MusicState::Activity(MusicActivity::Explore)) { } else if matches!(music_state, MusicState::Activity(MusicActivity::Explore)) {
rng.gen_range(90.0..180.0) rng.gen_range(120.0 * frequency_multipler..240.0 * frequency_multipler)
} else if matches!( } else if matches!(
music_state, music_state,
MusicState::Activity(MusicActivity::Combat(_)) | MusicState::Transition(_, _) MusicState::Activity(MusicActivity::Combat(_)) | MusicState::Transition(_, _)
) { ) {
0.0 0.0
} else { } else {
rng.gen_range(30.0..60.0) rng.gen_range(30.0 * frequency_multipler..60.0 * frequency_multipler)
}; };
let is_dark = (state.get_day_period().is_dark()) as bool; let is_dark = (state.get_day_period().is_dark()) as bool;
@ -427,7 +452,15 @@ impl MusicMgr {
// println!("Now playing {:?}", track.title); // println!("Now playing {:?}", track.title);
self.last_track = String::from(&track.title); self.last_track = String::from(&track.title);
self.began_playing = Instant::now(); self.began_playing = Instant::now();
self.track_length = track.length;
self.next_track_change = track.length + silence_between_tracks_seconds; self.next_track_change = track.length + silence_between_tracks_seconds;
if audio.music_enabled() {
self.current_track = String::from(&track.title);
self.current_artist = String::from(&track.artist);
} else {
self.current_track = String::from("None");
self.current_artist = String::from("None");
}
let tag = if matches!(music_state, MusicState::Activity(MusicActivity::Explore)) { let tag = if matches!(music_state, MusicState::Activity(MusicActivity::Explore)) {
MusicChannelTag::Exploration MusicChannelTag::Exploration
@ -481,6 +514,7 @@ impl assets::Compound for SoundtrackCollection<SoundtrackItem> {
biomes, biomes,
site, site,
segments, segments,
artist,
} => { } => {
for (path, length, music_state, activity_override) in segments.into_iter() { for (path, length, music_state, activity_override) in segments.into_iter() {
soundtracks.tracks.push(SoundtrackItem { soundtracks.tracks.push(SoundtrackItem {
@ -493,6 +527,7 @@ impl assets::Compound for SoundtrackCollection<SoundtrackItem> {
site, site,
music_state, music_state,
activity_override, activity_override,
artist: artist.clone(),
}); });
} }
}, },

View File

@ -265,6 +265,7 @@ widget_ids! {
graphics_backend, graphics_backend,
gpu_timings[], gpu_timings[],
weather, weather,
song_info,
// Game Version // Game Version
version, version,
@ -493,6 +494,8 @@ pub struct DebugInfo {
pub num_figures_visible: u32, pub num_figures_visible: u32,
pub num_particles: u32, pub num_particles: u32,
pub num_particles_visible: u32, pub num_particles_visible: u32,
pub current_track: String,
pub current_artist: String,
} }
pub struct HudInfo { pub struct HudInfo {
@ -2443,10 +2446,21 @@ impl Hud {
.font_size(self.fonts.cyri.scale(14)) .font_size(self.fonts.cyri.scale(14))
.set(self.ids.current_site, ui_widgets); .set(self.ids.current_site, ui_widgets);
// Current song info
Text::new(&format!(
"Currently playing: {} [{}]",
debug_info.current_track, debug_info.current_artist,
))
.color(TEXT_COLOR)
.down_from(self.ids.current_site, V_PAD)
.font_id(self.fonts.cyri.conrod_id)
.font_size(self.fonts.cyri.scale(14))
.set(self.ids.song_info, ui_widgets);
// Number of lights // Number of lights
Text::new(&format!("Lights: {}", debug_info.num_lights,)) Text::new(&format!("Lights: {}", debug_info.num_lights,))
.color(TEXT_COLOR) .color(TEXT_COLOR)
.down_from(self.ids.current_site, V_PAD) .down_from(self.ids.song_info, V_PAD)
.font_id(self.fonts.cyri.conrod_id) .font_id(self.fonts.cyri.conrod_id)
.font_size(self.fonts.cyri.scale(14)) .font_size(self.fonts.cyri.scale(14))
.set(self.ids.num_lights, ui_widgets); .set(self.ids.num_lights, ui_widgets);
@ -2525,7 +2539,7 @@ impl Hud {
// Set debug box dimensions, only timings height is dynamic // Set debug box dimensions, only timings height is dynamic
// TODO: Make the background box size fully dynamic // TODO: Make the background box size fully dynamic
let debug_bg_size = [320.0, 385.0 + timings_height]; let debug_bg_size = [375.0, 405.0 + timings_height];
Rectangle::fill(debug_bg_size) Rectangle::fill(debug_bg_size)
.rgba(0.0, 0.0, 0.0, global_state.settings.chat.chat_opacity) .rgba(0.0, 0.0, 0.0, global_state.settings.chat.chat_opacity)

View File

@ -34,6 +34,9 @@ widget_ids! {
ambience_volume_text, ambience_volume_text,
ambience_volume_slider, ambience_volume_slider,
ambience_volume_number, ambience_volume_number,
music_frequency_text,
music_frequency_slider,
music_frequency_number,
//audio_device_list, //audio_device_list,
//audio_device_text, //audio_device_text,
reset_sound_button, reset_sound_button,
@ -284,6 +287,41 @@ impl<'a> Widget for Sound<'a> {
.color(TEXT_COLOR) .color(TEXT_COLOR)
.set(state.ids.ambience_volume_number, ui); .set(state.ids.ambience_volume_number, ui);
// Music frequency (actually gap between songs)
Text::new(self.localized_strings.get("hud.settings.music_frequency"))
.down_from(state.ids.ambience_volume_slider, 10.0)
.font_size(self.fonts.cyri.scale(14))
.font_id(self.fonts.cyri.conrod_id)
.color(TEXT_COLOR)
.set(state.ids.music_frequency_text, ui);
// Music frequency Slider
if let Some(new_val) = ImageSlider::continuous(
self.global_state.settings.audio.music_frequency,
0.0,
2.0,
self.imgs.slider_indicator,
self.imgs.slider,
)
.w_h(104.0, 22.0)
.down_from(state.ids.music_frequency_text, 10.0)
.track_breadth(12.0)
.slider_length(10.0)
.pad_track((5.0, 5.0))
.set(state.ids.music_frequency_slider, ui)
{
events.push(AdjustMusicFrequency(new_val));
}
// Music frequency Number
Text::new(&format!(
"{:1.2}x",
self.global_state.settings.audio.music_frequency
))
.right_from(state.ids.music_frequency_slider, 8.0)
.font_size(self.fonts.cyri.scale(14))
.font_id(self.fonts.cyri.conrod_id)
.color(TEXT_COLOR)
.set(state.ids.music_frequency_number, ui);
// Audio Device Selector // Audio Device Selector
// -------------------------------------------- // --------------------------------------------
// let device = &self.global_state.audio.device; // let device = &self.global_state.audio.device;
@ -316,7 +354,7 @@ impl<'a> Widget for Sound<'a> {
.w_h(RESET_BUTTONS_WIDTH, RESET_BUTTONS_HEIGHT) .w_h(RESET_BUTTONS_WIDTH, RESET_BUTTONS_HEIGHT)
.hover_image(self.imgs.button_hover) .hover_image(self.imgs.button_hover)
.press_image(self.imgs.button_press) .press_image(self.imgs.button_press)
.down_from(state.ids.ambience_volume_slider, 12.0) .down_from(state.ids.music_frequency_slider, 12.0)
.label(self.localized_strings.get("hud.settings.reset_sound")) .label(self.localized_strings.get("hud.settings.reset_sound"))
.label_font_size(self.fonts.cyri.scale(14)) .label_font_size(self.fonts.cyri.scale(14))
.label_color(TEXT_COLOR) .label_color(TEXT_COLOR)

View File

@ -104,7 +104,7 @@ pub struct Scene {
trail_mgr: TrailMgr, trail_mgr: TrailMgr,
figure_mgr: FigureMgr, figure_mgr: FigureMgr,
pub sfx_mgr: SfxMgr, pub sfx_mgr: SfxMgr,
music_mgr: MusicMgr, pub music_mgr: MusicMgr,
ambient_mgr: AmbientMgr, ambient_mgr: AmbientMgr,
integrated_rain_vel: f32, integrated_rain_vel: f32,
@ -352,6 +352,8 @@ impl Scene {
/// Get a reference to the scene's figure manager. /// Get a reference to the scene's figure manager.
pub fn figure_mgr(&self) -> &FigureMgr { &self.figure_mgr } pub fn figure_mgr(&self) -> &FigureMgr { &self.figure_mgr }
pub fn music_mgr(&self) -> &MusicMgr { &self.music_mgr }
/// Get a mutable reference to the scene's camera. /// Get a mutable reference to the scene's camera.
pub fn camera_mut(&mut self) -> &mut Camera { &mut self.camera } pub fn camera_mut(&mut self) -> &mut Camera { &mut self.camera }

View File

@ -1132,6 +1132,8 @@ impl PlayState for SessionState {
num_particles: self.scene.particle_mgr().particle_count() as u32, num_particles: self.scene.particle_mgr().particle_count() as u32,
num_particles_visible: self.scene.particle_mgr().particle_count_visible() num_particles_visible: self.scene.particle_mgr().particle_count_visible()
as u32, as u32,
current_track: self.scene.music_mgr().current_track.clone(),
current_artist: self.scene.music_mgr().current_artist.clone(),
} }
}); });

View File

@ -23,6 +23,7 @@ pub enum Audio {
AdjustMusicVolume(f32), AdjustMusicVolume(f32),
AdjustSfxVolume(f32), AdjustSfxVolume(f32),
AdjustAmbienceVolume(f32), AdjustAmbienceVolume(f32),
AdjustMusicFrequency(f32),
//ChangeAudioDevice(String), //ChangeAudioDevice(String),
ResetAudioSettings, ResetAudioSettings,
} }
@ -208,6 +209,11 @@ impl SettingsChange {
settings.audio.ambience_volume = ambience_volume; settings.audio.ambience_volume = ambience_volume;
}, },
Audio::AdjustMusicFrequency(multiplier) => {
global_state.audio.set_music_frequency(multiplier);
settings.audio.music_frequency = multiplier;
},
//Audio::ChangeAudioDevice(name) => { //Audio::ChangeAudioDevice(name) => {
// global_state.audio.set_device(name.clone()); // global_state.audio.set_device(name.clone());

View File

@ -28,6 +28,7 @@ pub struct AudioSettings {
pub ambience_volume: f32, pub ambience_volume: f32,
pub num_sfx_channels: usize, pub num_sfx_channels: usize,
pub num_ui_channels: usize, pub num_ui_channels: usize,
pub music_frequency: f32,
/// Audio Device that Voxygen will use to play audio. /// Audio Device that Voxygen will use to play audio.
pub output: AudioOutput, pub output: AudioOutput,
@ -43,6 +44,7 @@ impl Default for AudioSettings {
ambience_volume: 0.6, ambience_volume: 0.6,
num_sfx_channels: 60, num_sfx_channels: 60,
num_ui_channels: 10, num_ui_channels: 10,
music_frequency: 1.0,
output: AudioOutput::Automatic, output: AudioOutput::Automatic,
} }
} }