use std::collections::HashMap;
use freecs::Entity;
use kira::{
AudioManager, AudioManagerSettings, DefaultBackend, Mix,
effect::reverb::ReverbBuilder,
listener::ListenerHandle,
sound::static_sound::{StaticSoundData, StaticSoundHandle},
track::{SendTrackBuilder, SendTrackHandle, SpatialTrackHandle},
};
#[derive(Default)]
pub struct AudioEngine {
pub manager: Option<AudioManager<DefaultBackend>>,
pub listener: Option<ListenerHandle>,
pub reverb_send: Option<SendTrackHandle>,
pub initialized: bool,
pub sound_cache: HashMap<String, StaticSoundData>,
pub sound_handles: HashMap<Entity, StaticSoundHandle>,
pub spatial_tracks: HashMap<Entity, SpatialTrackHandle>,
}
impl AudioEngine {
pub fn new() -> Self {
Self::default()
}
pub fn initialize(&mut self) -> Result<(), Box<dyn std::error::Error>> {
if self.initialized {
return Ok(());
}
match AudioManager::<DefaultBackend>::new(AudioManagerSettings::default()) {
Ok(mut manager) => {
let reverb_send = manager
.add_send_track(
SendTrackBuilder::new()
.with_effect(ReverbBuilder::new().mix(Mix::WET).damping(0.5)),
)
.map_err(|e| format!("Failed to create reverb send track: {}", e))?;
self.reverb_send = Some(reverb_send);
self.manager = Some(manager);
self.initialized = true;
tracing::info!("Audio engine initialized successfully with reverb");
Ok(())
}
Err(error) => {
tracing::error!("Failed to initialize audio engine: {}", error);
Err(Box::new(error))
}
}
}
pub fn is_initialized(&self) -> bool {
self.initialized && self.manager.is_some()
}
pub fn load_sound(&mut self, name: impl Into<String>, data: StaticSoundData) {
self.sound_cache.insert(name.into(), data);
}
pub fn get_sound(&self, name: &str) -> Option<&StaticSoundData> {
self.sound_cache.get(name)
}
pub fn has_handle(&self, entity: Entity) -> bool {
self.sound_handles.contains_key(&entity) || self.spatial_tracks.contains_key(&entity)
}
pub fn stop_sound(&mut self, entity: Entity) {
use kira::Tween;
if let Some(handle) = self.sound_handles.get_mut(&entity) {
handle.stop(Tween::default());
}
self.sound_handles.remove(&entity);
self.spatial_tracks.remove(&entity);
}
pub fn cleanup_entity(&mut self, entity: Entity) {
self.stop_sound(entity);
}
}