use std::collections::HashMap;
use std::collections::{BTreeMap};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HRTFProfile {
Generic,
SmallHead,
MediumHead,
LargeHead,
Custom,
}
impl Default for HRTFProfile {
fn default() -> Self {
Self::Generic
}
}
#[derive(Debug, Clone)]
pub struct AudioConfig {
pub sample_rate: u32,
pub channels: u32,
pub hrtf_profile: HRTFProfile,
pub enable_reverb: bool,
pub enable_occlusion: bool,
}
impl Default for AudioConfig {
fn default() -> Self {
Self {
sample_rate: 48000,
channels: 2,
hrtf_profile: HRTFProfile::Generic,
enable_reverb: true,
enable_occlusion: false,
}
}
}
#[derive(Debug, Clone)]
pub struct AudioSource {
pub id: String,
pub position: [f32; 3],
pub volume: f32,
pub loop_audio: bool,
}
pub struct SpatialAudioSystem {
config: AudioConfig,
sources: HashMap<String, AudioSource>,
listener_position: [f32; 3],
listener_rotation: [f32; 4],
master_volume: f32,
}
impl SpatialAudioSystem {
pub fn new(config: AudioConfig) -> Result<Self, AudioError> {
Ok(Self {
config,
sources: HashMap::new(),
listener_position: [0.0, 0.0, 0.0],
listener_rotation: [0.0, 0.0, 0.0, 1.0],
master_volume: 1.0,
})
}
pub fn config(&self) -> &AudioConfig {
&self.config
}
pub fn add_source(&mut self, source: AudioSource) -> Result<(), AudioError> {
self.sources.insert(source.id.clone(), source);
Ok(())
}
pub fn remove_source(&mut self, id: &str) -> Option<AudioSource> {
self.sources.remove(id)
}
pub fn get_source(&self, id: &str) -> Option<&AudioSource> {
self.sources.get(id)
}
pub fn update_listener(&mut self, position: [f32; 3], rotation: [f32; 4]) {
self.listener_position = position;
self.listener_rotation = rotation;
}
pub fn set_master_volume(&mut self, volume: f32) {
self.master_volume = volume.clamp(0.0, 1.0);
}
pub fn master_volume(&self) -> f32 {
self.master_volume
}
pub fn process_frame(&self, buffer: &mut [f32]) -> Result<(), AudioError> {
Ok(())
}
pub fn source_count(&self) -> usize {
self.sources.len()
}
}
#[derive(Debug, Clone)]
pub enum AudioError {
InitializationFailed(String),
SourceError(String),
PlaybackFailed(String),
}
impl std::fmt::Display for AudioError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::InitializationFailed(msg) => write!(f, "音频初始化失败: {}", msg),
Self::SourceError(msg) => write!(f, "音频源错误: {}", msg),
Self::PlaybackFailed(msg) => write!(f, "播放失败: {}", msg),
}
}
}
impl std::error::Error for AudioError {}