use crate::{
room::{Room, RoomAcoustics},
types::{Position3D, SpatialResult},
Error, Result,
};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use tracing::{debug, info, warn};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum VehicleType {
Sedan,
SUV,
Sports,
Van,
Truck,
Bus,
Motorcycle,
Electric,
Custom {
dimensions: (f32, f32, f32),
seating_capacity: u8,
engine_type: EngineType,
},
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum EngineType {
Gasoline {
cylinders: u8,
displacement_l: f32,
},
Diesel {
cylinders: u8,
displacement_l: f32,
},
Electric {
motor_count: u8,
},
Hybrid {
electric_motors: u8,
ice_cylinders: u8,
},
Hydrogen,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum SeatPosition {
Driver,
FrontPassenger,
RearLeft,
RearCenter,
RearRight,
ThirdRowLeft,
ThirdRowCenter,
ThirdRowRight,
Custom(Position3D),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VehicleAudioConfig {
pub vehicle_type: VehicleType,
pub speaker_config: VehicleSpeakerConfig,
pub acoustic_config: VehicleAcousticConfig,
pub noise_compensation: NoiseCompensationConfig,
pub passenger_config: PassengerConfig,
pub safety_config: SafetyConfig,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VehicleSpeakerConfig {
pub front_speakers: Vec<VehicleSpeaker>,
pub rear_speakers: Vec<VehicleSpeaker>,
pub subwoofers: Vec<VehicleSpeaker>,
pub tweeters: Vec<VehicleSpeaker>,
pub headrest_speakers: Vec<VehicleSpeaker>,
pub ceiling_speakers: Vec<VehicleSpeaker>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VehicleSpeaker {
pub id: String,
pub position: Position3D,
pub characteristics: SpeakerCharacteristics,
pub mounting: SpeakerMounting,
pub associated_seat: Option<SeatPosition>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SpeakerCharacteristics {
pub frequency_range: (f32, f32),
pub power_watts: f32,
pub impedance_ohms: f32,
pub driver_size_inches: f32,
pub speaker_type: SpeakerType,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum SpeakerType {
FullRange,
Woofer,
Midrange,
Tweeter,
Subwoofer,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum SpeakerMounting {
Door {
side: VehicleSide,
},
Dashboard {
side: DashboardSide,
},
APillar {
side: VehicleSide,
},
Headrest {
seat: SeatPosition,
},
Ceiling,
Floor,
Custom(String),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum VehicleSide {
Left,
Right,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum DashboardSide {
Left,
Center,
Right,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VehicleAcousticConfig {
pub interior_materials: InteriorMaterials,
pub windows: WindowConfig,
pub acoustic_treatment: AcousticTreatment,
pub hvac_config: HvacConfig,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InteriorMaterials {
pub seats: MaterialType,
pub dashboard: MaterialType,
pub door_panels: MaterialType,
pub ceiling: MaterialType,
pub floor: MaterialType,
pub carpet: Option<MaterialType>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum MaterialType {
Leather,
Cloth,
Plastic,
Metal,
Glass,
AcousticFoam,
Wood,
Custom {
absorption_coefficient: f32,
},
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WindowConfig {
pub tinting: WindowTinting,
pub thickness_mm: f32,
pub window_state: WindowState,
pub acoustic_glass: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum WindowTinting {
None,
Light,
Medium,
Dark,
VeryDark,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum WindowState {
Closed,
PartiallyOpen {
opening_percentage: f32,
},
Open,
SunroofOpen,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AcousticTreatment {
pub sound_deadening: bool,
pub insulation_level: f32,
pub active_noise_control: bool,
pub vibration_damping: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HvacConfig {
pub fan_speed: u8,
pub recirculation: bool,
pub open_vents: Vec<VentPosition>,
pub noise_levels: Vec<(u8, f32)>, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum VentPosition {
Dashboard,
Floor,
RearPassenger,
Defroster,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NoiseCompensationConfig {
pub engine_compensation: EngineNoiseCompensation,
pub road_compensation: RoadNoiseCompensation,
pub wind_compensation: WindNoiseCompensation,
pub adaptive_volume: AdaptiveVolumeConfig,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EngineNoiseCompensation {
pub enabled: bool,
pub rpm_compensation: Vec<(u32, f32)>, pub frequency_bands: Vec<FrequencyBand>,
pub engine_order_tracking: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RoadNoiseCompensation {
pub enabled: bool,
pub speed_compensation: Vec<(f32, f32)>, pub surface_detection: bool,
pub tire_noise_model: TireNoiseModel,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WindNoiseCompensation {
pub enabled: bool,
pub wind_curve: Vec<(f32, f32)>, pub window_compensation: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AdaptiveVolumeConfig {
pub enabled: bool,
pub response_speed: f32,
pub max_adjustment_db: f32,
pub frequency_weighting: FrequencyWeighting,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum FrequencyWeighting {
AWeighting,
CWeighting,
ZWeighting,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FrequencyBand {
pub frequency_hz: f32,
pub bandwidth_hz: f32,
pub compensation_db: f32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TireNoiseModel {
pub tire_type: TireType,
pub tire_size: String,
pub surface_interaction: Vec<(SurfaceType, f32)>, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum TireType {
Summer,
Winter,
AllSeason,
Performance,
OffRoad,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum SurfaceType {
SmoothAsphalt,
RoughAsphalt,
Concrete,
Gravel,
Cobblestone,
Wet,
Snow,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PassengerConfig {
pub passengers: Vec<PassengerInfo>,
pub zone_settings: Vec<AudioZone>,
pub preferences: HashMap<String, PassengerPreferences>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PassengerInfo {
pub id: String,
pub seat: SeatPosition,
pub height_cm: f32,
pub hearing: HearingCharacteristics,
pub activity: PassengerActivity,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HearingCharacteristics {
pub ability: HearingAbility,
pub preferred_volume_db: f32,
pub frequency_adjustments: Vec<FrequencyBand>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum HearingAbility {
Normal,
MildLoss,
ModerateLoss,
SevereLoss,
ProfoundLoss,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum PassengerActivity {
Driving,
Music,
PhoneCall,
Video,
Sleeping,
Reading,
Conversation,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AudioZone {
pub name: String,
pub seats: Vec<SeatPosition>,
pub audio_source: ZoneAudioSource,
pub volume_level: f32,
pub eq_settings: Vec<FrequencyBand>,
pub privacy_mode: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ZoneAudioSource {
Radio {
station: String,
},
Streaming {
service: String,
content: String,
},
Bluetooth {
device_name: String,
},
AuxInput,
PhoneCall,
Navigation,
VehicleAlerts,
Entertainment {
content_type: String,
},
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PassengerPreferences {
pub preferred_sources: Vec<ZoneAudioSource>,
pub eq_preferences: Vec<FrequencyBand>,
pub volume_preference: f32,
pub spatial_preferences: SpatialPreferences,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SpatialPreferences {
pub soundstage_width: f32,
pub center_position: Position3D,
pub bass_preference: f32,
pub surround_strength: f32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SafetyConfig {
pub driver_protection: DriverProtectionConfig,
pub emergency_config: EmergencyAudioConfig,
pub external_awareness: ExternalAwarenessConfig,
pub legal_compliance: LegalComplianceConfig,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DriverProtectionConfig {
pub limit_driver_volume: bool,
pub max_driver_volume_db: f32,
pub disable_complex_ui: bool,
pub voice_only_mode: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EmergencyAudioConfig {
pub emergency_priority: bool,
pub emergency_volume_db: f32,
pub auto_pause_media: bool,
pub alert_types: Vec<EmergencyAlertType>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum EmergencyAlertType {
CollisionWarning,
LaneDeparture,
EmergencyVehicle,
LowFuel,
SystemMalfunction,
NavigationCritical,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ExternalAwarenessConfig {
pub enable_awareness: bool,
pub external_mic_mixing: bool,
pub auto_volume_reduction: bool,
pub external_priority: f32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LegalComplianceConfig {
pub volume_limits: Vec<(String, f32)>, pub warning_messages: bool,
pub hearing_protection: bool,
pub time_limits: Option<TimeLimits>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TimeLimits {
pub max_continuous_minutes: u32,
pub required_break_minutes: u32,
pub daily_limit_minutes: u32,
}
#[derive(Debug)]
pub struct VehicleAudioProcessor {
config: VehicleAudioConfig,
vehicle_state: VehicleState,
zones: Vec<AudioZone>,
noise_compensator: NoiseCompensator,
passenger_manager: PassengerManager,
safety_monitor: SafetyMonitor,
metrics: VehicleAudioMetrics,
}
#[derive(Debug, Clone)]
pub struct VehicleState {
pub speed_kmh: f32,
pub engine_rpm: u32,
pub gear: GearPosition,
pub windows: WindowState,
pub hvac: HvacState,
pub external_conditions: ExternalConditions,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum GearPosition {
Park,
Reverse,
Neutral,
Drive(u8),
Manual(u8),
}
#[derive(Debug, Clone)]
pub struct HvacState {
pub fan_speed: u8,
pub temperature_c: f32,
pub ac_active: bool,
pub defrost_active: bool,
}
#[derive(Debug, Clone)]
pub struct ExternalConditions {
pub temperature_c: f32,
pub precipitation: PrecipitationType,
pub wind_speed_kmh: f32,
pub road_surface: SurfaceType,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum PrecipitationType {
None,
LightRain,
HeavyRain,
Snow,
Hail,
}
#[derive(Debug)]
pub struct NoiseCompensator {
engine_model: EngineNoiseModel,
road_model: RoadNoiseModel,
wind_model: WindNoiseModel,
compensation_filters: Vec<FrequencyBand>,
}
#[derive(Debug)]
pub struct EngineNoiseModel {
engine_type: EngineType,
rpm_noise_map: Vec<(u32, f32)>,
frequency_content: Vec<FrequencyBand>,
}
#[derive(Debug)]
pub struct RoadNoiseModel {
tire_model: TireNoiseModel,
speed_noise_map: Vec<(f32, f32)>,
surface_multipliers: HashMap<SurfaceType, f32>,
}
#[derive(Debug)]
pub struct WindNoiseModel {
wind_curve: Vec<(f32, f32)>,
window_impact: f32,
aero_factor: f32,
}
#[derive(Debug)]
pub struct PassengerManager {
passengers: Vec<PassengerInfo>,
preferences: HashMap<String, PassengerPreferences>,
occupancy_detection: SeatOccupancyDetection,
}
#[derive(Debug)]
pub struct SeatOccupancyDetection {
pressure_sensors: HashMap<SeatPosition, bool>,
weight_detection: HashMap<SeatPosition, f32>,
auto_detection: bool,
}
#[derive(Debug)]
pub struct SafetyMonitor {
driver_attention: DriverAttentionMonitor,
emergency_alerts: EmergencyAlertSystem,
volume_limits: VolumeLimits,
}
#[derive(Debug)]
pub struct DriverAttentionMonitor {
attention_level: f32,
complexity_limits: bool,
voice_only_active: bool,
}
#[derive(Debug)]
pub struct EmergencyAlertSystem {
active_alerts: Vec<EmergencyAlert>,
alert_queue: Vec<EmergencyAlert>,
audio_overrides: bool,
}
#[derive(Debug, Clone)]
pub struct EmergencyAlert {
alert_type: EmergencyAlertType,
priority: u8,
message: String,
audio_cue: String,
duration_s: f32,
}
#[derive(Debug)]
pub struct VolumeLimits {
zone_limits: HashMap<String, f32>,
time_limits: Option<TimeLimits>,
usage_tracking: UsageTracking,
}
#[derive(Debug)]
pub struct UsageTracking {
session_start: chrono::DateTime<chrono::Utc>,
session_time_minutes: u32,
high_volume_time: u32,
break_required: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VehicleAudioMetrics {
pub system_latency_ms: f32,
pub noise_compensation_effectiveness: f32,
pub passenger_satisfaction: HashMap<String, f32>,
pub safety_compliance_score: f32,
pub zone_quality_scores: HashMap<String, f32>,
pub resource_usage: ResourceUsage,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ResourceUsage {
pub cpu_usage: f32,
pub memory_usage_mb: f32,
pub dsp_usage: f32,
pub network_usage_mbps: f32,
}
impl VehicleAudioProcessor {
pub fn new(config: VehicleAudioConfig) -> Result<Self> {
let zones = config.passenger_config.zone_settings.clone();
Ok(Self {
config: config.clone(),
vehicle_state: VehicleState::default(),
zones,
noise_compensator: NoiseCompensator::new(&config.noise_compensation)?,
passenger_manager: PassengerManager::new(&config.passenger_config)?,
safety_monitor: SafetyMonitor::new(&config.safety_config)?,
metrics: VehicleAudioMetrics::default(),
})
}
pub fn update_vehicle_state(&mut self, state: VehicleState) -> Result<()> {
info!(
"Updating vehicle state: speed={}km/h, rpm={}",
state.speed_kmh, state.engine_rpm
);
self.vehicle_state = state;
self.noise_compensator
.update_compensation(&self.vehicle_state)?;
self.safety_monitor
.update_safety_state(&self.vehicle_state)?;
Ok(())
}
pub fn process_spatial_audio(
&mut self,
input_audio: &[f32],
) -> Result<HashMap<String, Vec<f32>>> {
let mut zone_outputs = HashMap::new();
for zone in &self.zones {
let compensated_audio = self
.noise_compensator
.apply_compensation(input_audio, &zone.name)?;
let spatial_audio = self.apply_zone_spatial_processing(&compensated_audio, zone)?;
zone_outputs.insert(zone.name.clone(), spatial_audio);
}
self.update_metrics();
Ok(zone_outputs)
}
pub fn add_passenger(&mut self, passenger: PassengerInfo) -> Result<()> {
info!(
"Adding passenger: {} at seat {:?}",
passenger.id, passenger.seat
);
self.passenger_manager.add_passenger(passenger)?;
self.update_audio_zones()?;
Ok(())
}
pub fn remove_passenger(&mut self, passenger_id: &str) -> Result<()> {
info!("Removing passenger: {}", passenger_id);
self.passenger_manager.remove_passenger(passenger_id)?;
self.update_audio_zones()?;
Ok(())
}
pub fn update_zone(&mut self, zone: AudioZone) -> Result<()> {
info!("Updating audio zone: {}", zone.name);
if let Some(existing_zone) = self.zones.iter_mut().find(|z| z.name == zone.name) {
*existing_zone = zone;
} else {
self.zones.push(zone);
}
Ok(())
}
pub fn get_metrics(&self) -> &VehicleAudioMetrics {
&self.metrics
}
pub fn handle_emergency_alert(&mut self, alert: EmergencyAlert) -> Result<()> {
warn!("Handling emergency alert: {:?}", alert.alert_type);
self.safety_monitor.handle_emergency(alert)?;
Ok(())
}
fn apply_zone_spatial_processing(&self, audio: &[f32], zone: &AudioZone) -> Result<Vec<f32>> {
let mut processed = audio.to_vec();
for eq_band in &zone.eq_settings {
let gain_linear = 10.0_f32.powf(eq_band.compensation_db / 20.0);
for sample in &mut processed {
*sample *= gain_linear;
}
}
for sample in &mut processed {
*sample *= zone.volume_level;
}
if zone.privacy_mode {
}
Ok(processed)
}
fn update_audio_zones(&mut self) -> Result<()> {
Ok(())
}
fn update_metrics(&mut self) {
self.metrics = VehicleAudioMetrics {
system_latency_ms: 25.0, noise_compensation_effectiveness: 85.0,
passenger_satisfaction: HashMap::new(),
safety_compliance_score: 95.0,
zone_quality_scores: HashMap::new(),
resource_usage: ResourceUsage {
cpu_usage: 15.0,
memory_usage_mb: 64.0,
dsp_usage: 45.0,
network_usage_mbps: 0.0,
},
};
}
}
impl NoiseCompensator {
fn new(config: &NoiseCompensationConfig) -> Result<Self> {
Ok(Self {
engine_model: EngineNoiseModel {
engine_type: EngineType::Gasoline {
cylinders: 4,
displacement_l: 2.0,
},
rpm_noise_map: config.engine_compensation.rpm_compensation.clone(),
frequency_content: config.engine_compensation.frequency_bands.clone(),
},
road_model: RoadNoiseModel {
tire_model: TireNoiseModel {
tire_type: TireType::AllSeason,
tire_size: "215/60R16".to_string(),
surface_interaction: vec![
(SurfaceType::SmoothAsphalt, 1.0),
(SurfaceType::RoughAsphalt, 1.3),
(SurfaceType::Concrete, 1.1),
],
},
speed_noise_map: config.road_compensation.speed_compensation.clone(),
surface_multipliers: HashMap::new(),
},
wind_model: WindNoiseModel {
wind_curve: config.wind_compensation.wind_curve.clone(),
window_impact: 1.0,
aero_factor: 1.0,
},
compensation_filters: Vec::new(),
})
}
fn update_compensation(&mut self, vehicle_state: &VehicleState) -> Result<()> {
self.compensation_filters.clear();
if let Some((_, compensation_db)) = self
.engine_model
.rpm_noise_map
.iter()
.find(|(rpm, _)| *rpm >= vehicle_state.engine_rpm)
{
self.compensation_filters.push(FrequencyBand {
frequency_hz: 100.0, bandwidth_hz: 50.0,
compensation_db: *compensation_db,
});
}
if let Some((_, compensation_db)) = self
.road_model
.speed_noise_map
.iter()
.find(|(speed, _)| *speed >= vehicle_state.speed_kmh)
{
self.compensation_filters.push(FrequencyBand {
frequency_hz: 1000.0, bandwidth_hz: 500.0,
compensation_db: *compensation_db,
});
}
Ok(())
}
fn apply_compensation(&self, audio: &[f32], _zone_name: &str) -> Result<Vec<f32>> {
let mut compensated = audio.to_vec();
for filter in &self.compensation_filters {
let gain_linear = 10.0_f32.powf(filter.compensation_db / 20.0);
for sample in &mut compensated {
*sample *= gain_linear;
}
}
Ok(compensated)
}
}
impl PassengerManager {
fn new(config: &PassengerConfig) -> Result<Self> {
Ok(Self {
passengers: config.passengers.clone(),
preferences: config.preferences.clone(),
occupancy_detection: SeatOccupancyDetection {
pressure_sensors: HashMap::new(),
weight_detection: HashMap::new(),
auto_detection: true,
},
})
}
fn add_passenger(&mut self, passenger: PassengerInfo) -> Result<()> {
self.passengers.push(passenger);
Ok(())
}
fn remove_passenger(&mut self, passenger_id: &str) -> Result<()> {
self.passengers.retain(|p| p.id != passenger_id);
self.preferences.remove(passenger_id);
Ok(())
}
}
impl SafetyMonitor {
fn new(config: &SafetyConfig) -> Result<Self> {
Ok(Self {
driver_attention: DriverAttentionMonitor {
attention_level: 1.0,
complexity_limits: config.driver_protection.disable_complex_ui,
voice_only_active: config.driver_protection.voice_only_mode,
},
emergency_alerts: EmergencyAlertSystem {
active_alerts: Vec::new(),
alert_queue: Vec::new(),
audio_overrides: config.emergency_config.auto_pause_media,
},
volume_limits: VolumeLimits {
zone_limits: HashMap::new(),
time_limits: config.legal_compliance.time_limits.clone(),
usage_tracking: UsageTracking {
session_start: chrono::Utc::now(),
session_time_minutes: 0,
high_volume_time: 0,
break_required: false,
},
},
})
}
fn update_safety_state(&mut self, _vehicle_state: &VehicleState) -> Result<()> {
Ok(())
}
fn handle_emergency(&mut self, alert: EmergencyAlert) -> Result<()> {
self.emergency_alerts.active_alerts.push(alert);
Ok(())
}
}
impl Default for VehicleState {
fn default() -> Self {
Self {
speed_kmh: 0.0,
engine_rpm: 800, gear: GearPosition::Park,
windows: WindowState::Closed,
hvac: HvacState {
fan_speed: 3,
temperature_c: 22.0,
ac_active: false,
defrost_active: false,
},
external_conditions: ExternalConditions {
temperature_c: 20.0,
precipitation: PrecipitationType::None,
wind_speed_kmh: 5.0,
road_surface: SurfaceType::SmoothAsphalt,
},
}
}
}
impl Default for VehicleAudioMetrics {
fn default() -> Self {
Self {
system_latency_ms: 0.0,
noise_compensation_effectiveness: 100.0,
passenger_satisfaction: HashMap::new(),
safety_compliance_score: 100.0,
zone_quality_scores: HashMap::new(),
resource_usage: ResourceUsage {
cpu_usage: 0.0,
memory_usage_mb: 0.0,
dsp_usage: 0.0,
network_usage_mbps: 0.0,
},
}
}
}
#[derive(Debug, Default)]
pub struct VehicleAudioConfigBuilder {
vehicle_type: Option<VehicleType>,
speaker_config: Option<VehicleSpeakerConfig>,
acoustic_config: Option<VehicleAcousticConfig>,
noise_compensation: Option<NoiseCompensationConfig>,
passenger_config: Option<PassengerConfig>,
safety_config: Option<SafetyConfig>,
}
impl VehicleAudioConfigBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn vehicle_type(mut self, vehicle_type: VehicleType) -> Self {
self.vehicle_type = Some(vehicle_type);
self
}
pub fn speaker_config(mut self, config: VehicleSpeakerConfig) -> Self {
self.speaker_config = Some(config);
self
}
pub fn acoustic_config(mut self, config: VehicleAcousticConfig) -> Self {
self.acoustic_config = Some(config);
self
}
pub fn noise_compensation(mut self, config: NoiseCompensationConfig) -> Self {
self.noise_compensation = Some(config);
self
}
pub fn passenger_config(mut self, config: PassengerConfig) -> Self {
self.passenger_config = Some(config);
self
}
pub fn safety_config(mut self, config: SafetyConfig) -> Self {
self.safety_config = Some(config);
self
}
pub fn build(self) -> Result<VehicleAudioConfig> {
Ok(VehicleAudioConfig {
vehicle_type: self.vehicle_type.unwrap_or(VehicleType::Sedan),
speaker_config: self.speaker_config.unwrap_or_else(|| VehicleSpeakerConfig {
front_speakers: Vec::new(),
rear_speakers: Vec::new(),
subwoofers: Vec::new(),
tweeters: Vec::new(),
headrest_speakers: Vec::new(),
ceiling_speakers: Vec::new(),
}),
acoustic_config: self
.acoustic_config
.unwrap_or_else(|| VehicleAcousticConfig {
interior_materials: InteriorMaterials {
seats: MaterialType::Cloth,
dashboard: MaterialType::Plastic,
door_panels: MaterialType::Plastic,
ceiling: MaterialType::Cloth,
floor: MaterialType::Custom {
absorption_coefficient: 0.3,
},
carpet: Some(MaterialType::Cloth),
},
windows: WindowConfig {
tinting: WindowTinting::Light,
thickness_mm: 4.0,
window_state: WindowState::Closed,
acoustic_glass: false,
},
acoustic_treatment: AcousticTreatment {
sound_deadening: true,
insulation_level: 0.7,
active_noise_control: false,
vibration_damping: true,
},
hvac_config: HvacConfig {
fan_speed: 3,
recirculation: false,
open_vents: vec![VentPosition::Dashboard],
noise_levels: vec![(0, 30.0), (5, 45.0), (10, 60.0)],
},
}),
noise_compensation: self.noise_compensation.unwrap_or_else(|| {
NoiseCompensationConfig {
engine_compensation: EngineNoiseCompensation {
enabled: true,
rpm_compensation: vec![(800, 0.0), (2000, 3.0), (4000, 6.0)],
frequency_bands: vec![FrequencyBand {
frequency_hz: 100.0,
bandwidth_hz: 50.0,
compensation_db: 3.0,
}],
engine_order_tracking: false,
},
road_compensation: RoadNoiseCompensation {
enabled: true,
speed_compensation: vec![(0.0, 0.0), (60.0, 3.0), (120.0, 6.0)],
surface_detection: false,
tire_noise_model: TireNoiseModel {
tire_type: TireType::AllSeason,
tire_size: "215/60R16".to_string(),
surface_interaction: vec![(SurfaceType::SmoothAsphalt, 1.0)],
},
},
wind_compensation: WindNoiseCompensation {
enabled: true,
wind_curve: vec![(0.0, 0.0), (80.0, 2.0), (120.0, 4.0)],
window_compensation: true,
},
adaptive_volume: AdaptiveVolumeConfig {
enabled: true,
response_speed: 0.5,
max_adjustment_db: 6.0,
frequency_weighting: FrequencyWeighting::AWeighting,
},
}
}),
passenger_config: self.passenger_config.unwrap_or_else(|| PassengerConfig {
passengers: Vec::new(),
zone_settings: vec![AudioZone {
name: "driver".to_string(),
seats: vec![SeatPosition::Driver],
audio_source: ZoneAudioSource::Radio {
station: "FM1".to_string(),
},
volume_level: 0.7,
eq_settings: Vec::new(),
privacy_mode: false,
}],
preferences: HashMap::new(),
}),
safety_config: self.safety_config.unwrap_or_else(|| SafetyConfig {
driver_protection: DriverProtectionConfig {
limit_driver_volume: true,
max_driver_volume_db: 85.0,
disable_complex_ui: true,
voice_only_mode: false,
},
emergency_config: EmergencyAudioConfig {
emergency_priority: true,
emergency_volume_db: 95.0,
auto_pause_media: true,
alert_types: vec![
EmergencyAlertType::CollisionWarning,
EmergencyAlertType::LaneDeparture,
],
},
external_awareness: ExternalAwarenessConfig {
enable_awareness: true,
external_mic_mixing: false,
auto_volume_reduction: true,
external_priority: 0.8,
},
legal_compliance: LegalComplianceConfig {
volume_limits: vec![("US".to_string(), 100.0)],
warning_messages: true,
hearing_protection: true,
time_limits: None,
},
}),
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_vehicle_audio_processor_creation() {
let config = VehicleAudioConfigBuilder::new()
.vehicle_type(VehicleType::Sedan)
.build()
.expect("Failed to build config");
let processor = VehicleAudioProcessor::new(config).expect("Failed to create processor");
assert_eq!(processor.zones.len(), 1); }
#[test]
fn test_vehicle_state_update() {
let config = VehicleAudioConfigBuilder::new()
.build()
.expect("Failed to build config");
let mut processor = VehicleAudioProcessor::new(config).expect("Failed to create processor");
let new_state = VehicleState {
speed_kmh: 60.0,
engine_rpm: 2000,
gear: GearPosition::Drive(4),
..Default::default()
};
processor
.update_vehicle_state(new_state)
.expect("Failed to update vehicle state");
assert_eq!(processor.vehicle_state.speed_kmh, 60.0);
assert_eq!(processor.vehicle_state.engine_rpm, 2000);
}
#[test]
fn test_passenger_management() {
let config = VehicleAudioConfigBuilder::new()
.build()
.expect("Failed to build config");
let mut processor = VehicleAudioProcessor::new(config).expect("Failed to create processor");
let passenger = PassengerInfo {
id: "passenger1".to_string(),
seat: SeatPosition::FrontPassenger,
height_cm: 175.0,
hearing: HearingCharacteristics {
ability: HearingAbility::Normal,
preferred_volume_db: 0.0,
frequency_adjustments: Vec::new(),
},
activity: PassengerActivity::Music,
};
processor
.add_passenger(passenger)
.expect("Failed to add passenger");
assert_eq!(processor.passenger_manager.passengers.len(), 1);
processor
.remove_passenger("passenger1")
.expect("Failed to remove passenger");
assert_eq!(processor.passenger_manager.passengers.len(), 0);
}
#[test]
fn test_noise_compensation() {
let config = NoiseCompensationConfig {
engine_compensation: EngineNoiseCompensation {
enabled: true,
rpm_compensation: vec![(1000, 2.0), (2000, 4.0)],
frequency_bands: vec![FrequencyBand {
frequency_hz: 100.0,
bandwidth_hz: 50.0,
compensation_db: 3.0,
}],
engine_order_tracking: false,
},
road_compensation: RoadNoiseCompensation {
enabled: true,
speed_compensation: vec![(50.0, 2.0), (100.0, 4.0)],
surface_detection: false,
tire_noise_model: TireNoiseModel {
tire_type: TireType::AllSeason,
tire_size: "215/60R16".to_string(),
surface_interaction: Vec::new(),
},
},
wind_compensation: WindNoiseCompensation {
enabled: true,
wind_curve: vec![(60.0, 1.0), (120.0, 3.0)],
window_compensation: true,
},
adaptive_volume: AdaptiveVolumeConfig {
enabled: true,
response_speed: 0.5,
max_adjustment_db: 6.0,
frequency_weighting: FrequencyWeighting::AWeighting,
},
};
let mut compensator = NoiseCompensator::new(&config).expect("Failed to create compensator");
assert!(compensator.compensation_filters.is_empty());
let vehicle_state = VehicleState {
speed_kmh: 60.0,
engine_rpm: 1500, gear: GearPosition::Drive(3),
windows: WindowState::Closed,
hvac: HvacState {
fan_speed: 2,
temperature_c: 22.0,
ac_active: true,
defrost_active: false,
},
external_conditions: ExternalConditions {
temperature_c: 20.0,
wind_speed_kmh: 10.0,
precipitation: PrecipitationType::None,
road_surface: SurfaceType::SmoothAsphalt,
},
};
compensator
.update_compensation(&vehicle_state)
.expect("Failed to update compensation");
assert!(!compensator.compensation_filters.is_empty());
}
#[test]
fn test_vehicle_types() {
let vehicle_types = vec![
VehicleType::Sedan,
VehicleType::SUV,
VehicleType::Electric,
VehicleType::Custom {
dimensions: (4.5, 1.8, 1.5),
seating_capacity: 5,
engine_type: EngineType::Electric { motor_count: 2 },
},
];
assert_eq!(vehicle_types.len(), 4);
}
#[test]
fn test_audio_zones() {
let zone = AudioZone {
name: "rear_passengers".to_string(),
seats: vec![SeatPosition::RearLeft, SeatPosition::RearRight],
audio_source: ZoneAudioSource::Entertainment {
content_type: "movie".to_string(),
},
volume_level: 0.8,
eq_settings: vec![FrequencyBand {
frequency_hz: 1000.0,
bandwidth_hz: 100.0,
compensation_db: 2.0,
}],
privacy_mode: true,
};
assert_eq!(zone.seats.len(), 2);
assert!(zone.privacy_mode);
}
#[test]
fn test_emergency_alerts() {
let alert = EmergencyAlert {
alert_type: EmergencyAlertType::CollisionWarning,
priority: 10,
message: "Collision imminent!".to_string(),
audio_cue: "collision_warning.wav".to_string(),
duration_s: 3.0,
};
assert_eq!(alert.priority, 10);
assert_eq!(alert.duration_s, 3.0);
}
#[test]
fn test_material_acoustics() {
let materials = InteriorMaterials {
seats: MaterialType::Leather,
dashboard: MaterialType::Plastic,
door_panels: MaterialType::Cloth,
ceiling: MaterialType::AcousticFoam,
floor: MaterialType::Custom {
absorption_coefficient: 0.4,
},
carpet: Some(MaterialType::Cloth),
};
match materials.floor {
MaterialType::Custom {
absorption_coefficient,
} => {
assert_eq!(absorption_coefficient, 0.4);
}
_ => panic!("Wrong material type"),
}
}
#[test]
fn test_safety_configuration() {
let safety_config = SafetyConfig {
driver_protection: DriverProtectionConfig {
limit_driver_volume: true,
max_driver_volume_db: 85.0,
disable_complex_ui: true,
voice_only_mode: false,
},
emergency_config: EmergencyAudioConfig {
emergency_priority: true,
emergency_volume_db: 95.0,
auto_pause_media: true,
alert_types: vec![EmergencyAlertType::CollisionWarning],
},
external_awareness: ExternalAwarenessConfig {
enable_awareness: true,
external_mic_mixing: true,
auto_volume_reduction: true,
external_priority: 0.9,
},
legal_compliance: LegalComplianceConfig {
volume_limits: vec![("EU".to_string(), 95.0)],
warning_messages: true,
hearing_protection: true,
time_limits: Some(TimeLimits {
max_continuous_minutes: 60,
required_break_minutes: 10,
daily_limit_minutes: 480,
}),
},
};
assert!(safety_config.driver_protection.limit_driver_volume);
assert_eq!(safety_config.emergency_config.emergency_volume_db, 95.0);
}
}