use std::collections::HashMap;
use freecs::Entity;
use kira::{
AudioManager, AudioManagerSettings, Capacities, DefaultBackend,
listener::ListenerHandle,
modulator::tweener::TweenerHandle,
sound::static_sound::{StaticSoundData, StaticSoundHandle},
track::{SendTrackHandle, SpatialTrackHandle, TrackHandle},
};
#[derive(Default)]
pub struct AudioBuses {
pub master: Option<TrackHandle>,
pub music: Option<TrackHandle>,
pub sfx: Option<TrackHandle>,
pub ambient: Option<TrackHandle>,
pub voice: Option<TrackHandle>,
pub ui: Option<TrackHandle>,
}
#[derive(Default)]
pub struct AudioEngine {
pub manager: Option<AudioManager<DefaultBackend>>,
pub listener: Option<ListenerHandle>,
pub buses: AudioBuses,
pub buses_built: bool,
pub reverb_sends: HashMap<String, SendTrackHandle>,
pub voice_ducking: Option<TweenerHandle>,
pub initialized: bool,
pub sound_cache: HashMap<String, StaticSoundData>,
pub sound_handles: HashMap<Entity, StaticSoundHandle>,
pub spatial_tracks: HashMap<Entity, SpatialTrackHandle>,
}
pub fn audio_engine_initialize(engine: &mut AudioEngine) -> Result<(), Box<dyn std::error::Error>> {
if engine.initialized {
return Ok(());
}
let settings = AudioManagerSettings::<DefaultBackend> {
capacities: Capacities {
sub_track_capacity: 256,
send_track_capacity: 64,
clock_capacity: 16,
modulator_capacity: 64,
listener_capacity: 8,
},
..Default::default()
};
match AudioManager::<DefaultBackend>::new(settings) {
Ok(manager) => {
engine.manager = Some(manager);
engine.initialized = true;
tracing::info!("Audio engine initialized");
Ok(())
}
Err(error) => {
tracing::error!("Failed to initialize audio engine: {}", error);
Err(Box::new(error))
}
}
}
pub fn audio_engine_is_initialized(engine: &AudioEngine) -> bool {
engine.initialized && engine.manager.is_some()
}
pub fn audio_engine_load_sound(
engine: &mut AudioEngine,
name: impl Into<String>,
data: StaticSoundData,
) {
engine.sound_cache.insert(name.into(), data);
}
pub fn audio_engine_get_sound<'a>(
engine: &'a AudioEngine,
name: &str,
) -> Option<&'a StaticSoundData> {
engine.sound_cache.get(name)
}
pub fn audio_engine_has_handle(engine: &AudioEngine, entity: Entity) -> bool {
engine.sound_handles.contains_key(&entity) || engine.spatial_tracks.contains_key(&entity)
}
pub fn audio_engine_stop_sound(engine: &mut AudioEngine, entity: Entity) {
use kira::Tween;
use std::time::Duration;
let fade = Tween {
duration: Duration::from_millis(50),
..Default::default()
};
if let Some(handle) = engine.sound_handles.get_mut(&entity) {
handle.stop(fade);
}
engine.sound_handles.remove(&entity);
engine.spatial_tracks.remove(&entity);
}
pub fn audio_engine_cleanup_entity(engine: &mut AudioEngine, entity: Entity) {
audio_engine_stop_sound(engine, entity);
}