use serde::{Deserialize, Serialize};
use std::path::PathBuf;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SpatialConfig {
pub hrtf_database_path: Option<PathBuf>,
pub sample_rate: u32,
pub buffer_size: usize,
pub room_dimensions: (f32, f32, f32),
pub reverb_time: f32,
pub enable_distance_attenuation: bool,
pub enable_air_absorption: bool,
pub enable_doppler: bool,
pub max_distance: f32,
pub speed_of_sound: f32,
pub quality_level: f32,
pub max_sources: usize,
pub use_gpu: bool,
}
impl Default for SpatialConfig {
fn default() -> Self {
Self {
hrtf_database_path: None,
sample_rate: 44100,
buffer_size: 1024,
room_dimensions: (10.0, 8.0, 3.0), reverb_time: 1.2, enable_distance_attenuation: true,
enable_air_absorption: true,
enable_doppler: false,
max_distance: 100.0, speed_of_sound: 343.0, quality_level: 0.8, max_sources: 16, use_gpu: false, }
}
}
impl SpatialConfig {
pub fn validate(&self) -> crate::Result<()> {
if self.sample_rate == 0 {
return Err(crate::Error::LegacyConfig(
"Sample rate must be positive".to_string(),
));
}
if self.buffer_size == 0 {
return Err(crate::Error::LegacyConfig(
"Buffer size must be positive".to_string(),
));
}
if self.reverb_time < 0.0 {
return Err(crate::Error::LegacyConfig(
"Reverb time cannot be negative".to_string(),
));
}
if self.max_distance <= 0.0 {
return Err(crate::Error::LegacyConfig(
"Max distance must be positive".to_string(),
));
}
if self.speed_of_sound <= 0.0 {
return Err(crate::Error::LegacyConfig(
"Speed of sound must be positive".to_string(),
));
}
Ok(())
}
}
#[derive(Debug, Default)]
pub struct SpatialConfigBuilder {
config: SpatialConfig,
}
impl SpatialConfigBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn hrtf_database_path(mut self, path: PathBuf) -> Self {
self.config.hrtf_database_path = Some(path);
self
}
pub fn sample_rate(mut self, sample_rate: u32) -> Self {
self.config.sample_rate = sample_rate;
self
}
pub fn buffer_size(mut self, buffer_size: usize) -> Self {
self.config.buffer_size = buffer_size;
self
}
pub fn room_dimensions(mut self, width: f32, height: f32, depth: f32) -> Self {
self.config.room_dimensions = (width, height, depth);
self
}
pub fn reverb_time(mut self, reverb_time: f32) -> Self {
self.config.reverb_time = reverb_time;
self
}
pub fn distance_attenuation(mut self, enabled: bool) -> Self {
self.config.enable_distance_attenuation = enabled;
self
}
pub fn air_absorption(mut self, enabled: bool) -> Self {
self.config.enable_air_absorption = enabled;
self
}
pub fn doppler(mut self, enabled: bool) -> Self {
self.config.enable_doppler = enabled;
self
}
pub fn max_distance(mut self, max_distance: f32) -> Self {
self.config.max_distance = max_distance;
self
}
pub fn speed_of_sound(mut self, speed: f32) -> Self {
self.config.speed_of_sound = speed;
self
}
pub fn build(self) -> crate::Result<SpatialConfig> {
self.config.validate()?;
Ok(self.config)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config() {
let config = SpatialConfig::default();
assert!(config.validate().is_ok());
}
#[test]
fn test_config_builder() {
let config = SpatialConfigBuilder::new()
.sample_rate(48000)
.buffer_size(512)
.reverb_time(1.5)
.build()
.unwrap();
assert_eq!(config.sample_rate, 48000);
assert_eq!(config.buffer_size, 512);
assert_eq!(config.reverb_time, 1.5);
}
#[test]
fn test_config_validation() {
let mut config = SpatialConfig::default();
config.sample_rate = 0;
assert!(config.validate().is_err());
config.sample_rate = 44100;
config.max_distance = -1.0;
assert!(config.validate().is_err());
}
}