From 148464788273a7b086c5fccdc50cf3a97df5326e Mon Sep 17 00:00:00 2001 From: David Huculak Date: Fri, 26 Apr 2024 22:11:08 -0400 Subject: [PATCH] more audio runtime disable feature dev --- Cargo.toml | 2 +- example_game/Cargo.toml | 3 +- ikari/Cargo.toml | 3 +- ikari/src/asset_loader.rs | 10 +-- ikari/src/audio.rs | 175 +++++++++++++++++++++++--------------- ikari/src/engine_state.rs | 10 +-- rust-toolchain | 2 +- 7 files changed, 120 insertions(+), 85 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a504b786..9223573c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ members = ["ikari", "build_web", "example_game", "clikari"] [workspace.package] version = "0.0.1" edition = "2021" -rust-version = "1.66" +rust-version = "1.75" description = "3D Game Engine" keywords = ["renderer", "3D", "rust", "wgpu", "game"] license = "MIT" diff --git a/example_game/Cargo.toml b/example_game/Cargo.toml index 6abf08aa..fd881002 100644 --- a/example_game/Cargo.toml +++ b/example_game/Cargo.toml @@ -10,8 +10,7 @@ name = "example_game" path = "src/main.rs" [features] -default = ["cpu-profiling", "gpu-profiling"] -# default = ["cpu-profiling", "gpu-profiling", "audio"] +default = ["cpu-profiling", "gpu-profiling", "audio"] cpu-profiling = [ "ikari/tracy-profiling", "profiling/profile-with-tracy", diff --git a/ikari/Cargo.toml b/ikari/Cargo.toml index ef545e9d..8bcc628a 100644 --- a/ikari/Cargo.toml +++ b/ikari/Cargo.toml @@ -15,8 +15,7 @@ path = "src/lib.rs" [features] # TODO: exclude all audio-related deps when audio feature is not set! -default = [] -# default = ["audio"] +default = ["audio"] tracy-profiling = ["profiling/profile-with-tracy"] gpu-profiling = [] audio = [] diff --git a/ikari/src/asset_loader.rs b/ikari/src/asset_loader.rs index dc2c10b0..2fb6193c 100644 --- a/ikari/src/asset_loader.rs +++ b/ikari/src/asset_loader.rs @@ -1,5 +1,5 @@ use crate::audio::AudioFileStreamer; -use crate::audio::AudioManager; +use crate::audio::IkariAudioManager; use crate::audio::SoundParams; use crate::audio::AUDIO_STREAM_BUFFER_LENGTH_SECONDS; use crate::buffer::GpuBuffer; @@ -77,7 +77,7 @@ pub struct AssetLoader { pending_audio: Arc>>, pub loaded_audio: Arc>>, - audio_manager: Arc>, + audio_manager: Arc>, pending_scenes: Arc>>, bindable_scenes: Arc>>, @@ -129,7 +129,7 @@ struct TimeSlicedSkyboxBinder { } impl AssetLoader { - pub fn new(audio_manager: Arc>) -> Self { + pub fn new(audio_manager: Arc>) -> Self { Self { is_exiting: Arc::new(AtomicBool::new(false)), @@ -239,7 +239,7 @@ impl AssetLoader { Default::default() }; - let signal = AudioManager::get_signal( + let signal = IkariAudioManager::get_signal( &sound_data, next_audio_params.sound_params.clone(), device_sample_rate, @@ -287,7 +287,7 @@ impl AssetLoader { fn spawn_audio_streaming_thread( is_exiting: Arc, - audio_manager: Arc>, + audio_manager: Arc>, sound_index: usize, mut audio_file_streamer: AudioFileStreamer, ) { diff --git a/ikari/src/audio.rs b/ikari/src/audio.rs index fb9949ec..f1b73e5f 100644 --- a/ikari/src/audio.rs +++ b/ikari/src/audio.rs @@ -16,11 +16,20 @@ pub struct SoundParams { pub const AUDIO_STREAM_BUFFER_LENGTH_SECONDS: f32 = 2.5; -pub trait AudioStreams {} +const CHANNEL_COUNT: usize = 2; + +#[derive(Debug, Clone, Default)] +pub struct SoundData(Vec<[f32; CHANNEL_COUNT]>); + +impl SoundData { + pub fn sample_count(&self) -> usize { + self.0.len() + } +} mod ikari_audio { - use crate::file_manager::GameFilePath; use crate::time::Instant; + use crate::{audio::CHANNEL_COUNT, file_manager::GameFilePath}; use anyhow::Result; use cpal::traits::{DeviceTrait, HostTrait, StreamTrait}; @@ -38,9 +47,7 @@ mod ikari_audio { _mixer_output_stream: cpal::Stream, } - impl AudioStreams for IkariAudioStreams {} - - pub struct AudioManager { + pub struct IkariAudioManager { master_volume: f32, device_sample_rate: u32, @@ -49,17 +56,6 @@ mod ikari_audio { sounds: Vec>, } - const CHANNEL_COUNT: usize = 2; - - #[derive(Debug, Clone, Default)] - pub struct SoundData(Vec<[f32; CHANNEL_COUNT]>); - - impl SoundData { - pub fn sample_count(&self) -> usize { - self.0.len() - } - } - pub struct Sound { volume: f32, is_playing: bool, @@ -145,7 +141,7 @@ mod ikari_audio { #[cfg(target_arch = "wasm32")] use web::get_media_source; - use super::{AudioStreams, SoundParams, SpacialParams, AUDIO_STREAM_BUFFER_LENGTH_SECONDS}; + use super::{SoundData, SoundParams, SpacialParams, AUDIO_STREAM_BUFFER_LENGTH_SECONDS}; pub struct AudioFileStreamer { device_sample_rate: u32, @@ -321,9 +317,9 @@ mod ikari_audio { } } - impl AudioManager { + impl IkariAudioManager { /// streams are returned separately since they aren't Send/Sync - pub fn new() -> Result<(AudioManager, Box)> { + pub fn new() -> Result<(IkariAudioManager, IkariAudioStreams)> { let host = cpal::default_host(); let device = host .default_output_device() @@ -365,7 +361,7 @@ mod ikari_audio { mixer_output_stream.play()?; Ok(( - AudioManager { + IkariAudioManager { master_volume: 1.0, device_sample_rate, @@ -373,10 +369,10 @@ mod ikari_audio { mixer_handle, sounds: vec![], }, - Box::new(IkariAudioStreams { + IkariAudioStreams { _spatial_scene_output_stream: spatial_scene_output_stream, _mixer_output_stream: mixer_output_stream, - }), + }, )) } @@ -490,7 +486,7 @@ mod ikari_audio { .map(|sound| &sound.file_path) } - pub fn _set_sound_volume(&mut self, sound_index: usize, volume: f32) { + pub fn set_sound_volume(&mut self, sound_index: usize, volume: f32) { if let Some(sound) = self.sounds[sound_index].as_mut() { sound.set_volume(self.master_volume, volume) } @@ -546,7 +542,7 @@ mod ikari_audio { impl Sound { fn new( - audio_manager: &mut AudioManager, + audio_manager: &mut IkariAudioManager, file_path: GameFilePath, sound_data: SoundData, length_seconds: Option, @@ -759,62 +755,97 @@ mod ikari_audio { } } -mod null_audio { - use crate::file_manager::GameFilePath; - use anyhow::Result; +pub trait AudioManager { + type SoundSignal; - use super::{AudioStreams, SoundParams}; + fn get_signal( + _sound_data: &SoundData, + _params: SoundParams, + _device_sample_rate: u32, + ) -> Option; - pub struct NullAudioStreams {} + fn add_sound( + &mut self, + _file_path: GameFilePath, + _sound_data: SoundData, + _length_seconds: Option, + _params: SoundParams, + _signal: Option, + ) -> usize; - impl AudioStreams for NullAudioStreams {} + fn write_stream_data(&mut self, sound_index: usize, sound_data: SoundData); - pub struct AudioManager {} + fn play_sound(&mut self, sound_index: usize); - #[derive(Debug, Clone, Default)] - pub struct SoundData(); + fn reload_sound(&mut self, _sound_index: usize, _params: SoundParams); - pub struct Sound {} + fn sound_is_playing(&self, sound_index: usize) -> bool; - pub struct AudioFileStreamer { + fn get_sound_length_seconds(&self, sound_index: usize) -> Option>; + fn get_sound_pos_seconds(&self, sound_index: usize) -> Option; + + fn get_sound_buffered_to_pos_seconds(&self, sound_index: usize) -> Option; + + fn get_sound_file_path(&self, sound_index: usize) -> Option<&GameFilePath>; + + fn set_sound_volume(&mut self, sound_index: usize, volume: f32); + + fn device_sample_rate(&self) -> u32; + + fn sound_indices(&self) -> impl Iterator + '_; +} + +pub trait AudioFileStreamer { + fn read_chunk(&mut self, _max_chunk_size: usize) -> anyhow::Result<(SoundData, bool)>; + + fn track_length_seconds(&self) -> Option; + + fn file_path(&self) -> &GameFilePath; +} + +mod null_audio { + use crate::file_manager::GameFilePath; + use anyhow::Result; + + use super::{AudioFileStreamer, AudioManager, SoundData, SoundParams}; + + pub struct AudioStreams {} + + pub struct NullAudioManager {} + + pub struct NullAudioFileStreamer { file_path: GameFilePath, } pub struct SoundSignal {} - impl SoundData { - pub fn sample_count(&self) -> usize { - 0 + impl AudioFileStreamer for NullAudioFileStreamer { + fn read_chunk(&mut self, _max_chunk_size: usize) -> anyhow::Result<(SoundData, bool)> { + Ok((SoundData(vec![]), true)) + } + + fn track_length_seconds(&self) -> Option { + None + } + + fn file_path(&self) -> &GameFilePath { + &self.file_path } } - impl AudioFileStreamer { + impl NullAudioFileStreamer { pub async fn new( _device_sample_rate: u32, file_path: GameFilePath, ) -> anyhow::Result { Ok(Self { file_path }) } - - pub fn read_chunk(&mut self, _max_chunk_size: usize) -> anyhow::Result<(SoundData, bool)> { - Ok((SoundData(), true)) - } - - pub fn track_length_seconds(&self) -> Option { - None - } - - pub fn file_path(&self) -> &GameFilePath { - &self.file_path - } } - impl AudioManager { - pub fn new() -> Result<(AudioManager, NullAudioStreams)> { - Ok((AudioManager {}, NullAudioStreams {})) - } + impl AudioManager for NullAudioManager { + type SoundSignal = SoundSignal; - pub fn get_signal( + fn get_signal( _sound_data: &SoundData, _params: SoundParams, _device_sample_rate: u32, @@ -822,7 +853,7 @@ mod null_audio { None } - pub fn add_sound( + fn add_sound( &mut self, _file_path: GameFilePath, _sound_data: SoundData, @@ -833,42 +864,48 @@ mod null_audio { 0 } - pub fn write_stream_data(&mut self, sound_index: usize, sound_data: SoundData) {} + fn write_stream_data(&mut self, sound_index: usize, sound_data: SoundData) {} - pub fn play_sound(&mut self, sound_index: usize) {} + fn play_sound(&mut self, sound_index: usize) {} - pub fn reload_sound(&mut self, _sound_index: usize, _params: SoundParams) {} + fn reload_sound(&mut self, _sound_index: usize, _params: SoundParams) {} - pub fn sound_is_playing(&self, sound_index: usize) -> bool { + fn sound_is_playing(&self, sound_index: usize) -> bool { false } - pub fn get_sound_length_seconds(&self, sound_index: usize) -> Option> { + fn get_sound_length_seconds(&self, sound_index: usize) -> Option> { None } - pub fn get_sound_pos_seconds(&self, sound_index: usize) -> Option { + fn get_sound_pos_seconds(&self, sound_index: usize) -> Option { None } - pub fn get_sound_buffered_to_pos_seconds(&self, sound_index: usize) -> Option { + fn get_sound_buffered_to_pos_seconds(&self, sound_index: usize) -> Option { None } - pub fn get_sound_file_path(&self, sound_index: usize) -> Option<&GameFilePath> { + fn get_sound_file_path(&self, sound_index: usize) -> Option<&GameFilePath> { None } - pub fn _set_sound_volume(&mut self, sound_index: usize, volume: f32) {} + fn set_sound_volume(&mut self, sound_index: usize, volume: f32) {} - pub fn device_sample_rate(&self) -> u32 { + fn device_sample_rate(&self) -> u32 { 1 } - pub fn sound_indices(&self) -> impl Iterator + '_ { + fn sound_indices(&self) -> impl Iterator + '_ { std::iter::empty() } } + + impl NullAudioManager { + pub fn new() -> Result<(NullAudioManager, AudioStreams)> { + Ok((NullAudioManager {}, AudioStreams {})) + } + } } #[cfg(feature = "audio")] @@ -876,3 +913,5 @@ pub use ikari_audio::*; #[cfg(not(feature = "audio"))] pub use null_audio::*; + +use crate::file_manager::GameFilePath; diff --git a/ikari/src/engine_state.rs b/ikari/src/engine_state.rs index 368e40ac..c2b1cf4d 100644 --- a/ikari/src/engine_state.rs +++ b/ikari/src/engine_state.rs @@ -1,6 +1,6 @@ use crate::{ asset_loader::{AssetBinder, AssetLoader}, - audio::{AudioManager, AudioStreams, IkariAudioStreams}, + audio::{IkariAudioManager, IkariAudioStreams}, framerate_limiter::FramerateLimiter, mutex::Mutex, physics::PhysicsState, @@ -16,10 +16,8 @@ pub struct EngineState { pub time_tracker: TimeTracker, pub framerate_limiter: FramerateLimiter, pub physics_state: PhysicsState, - // TODO: maybe instead of box dyn trait, it could be good to just have the real audio manager have a 'disable' flag, which could allow it to respond to - // audio devices being disconnected later on. - _audio_streams: Box, - pub audio_manager: Arc>, + _audio_streams: IkariAudioStreams, + pub audio_manager: Arc>, pub asset_loader: Arc, pub asset_binder: WasmNotArc, } @@ -27,7 +25,7 @@ pub struct EngineState { impl EngineState { #[profiling::function] pub fn new() -> anyhow::Result { - let (audio_manager, _audio_streams) = AudioManager::new()?; + let (audio_manager, _audio_streams) = IkariAudioManager::new()?; let audio_manager = Arc::new(Mutex::new(audio_manager)); let asset_loader = Arc::new(AssetLoader::new(audio_manager.clone())); let asset_binder = WasmNotArc::new(AssetBinder::new()); diff --git a/rust-toolchain b/rust-toolchain index 328e3f3e..e02da0b2 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -nightly-2023-07-19 \ No newline at end of file +nightly-2024-04-26 \ No newline at end of file