Skip to main content

voirs_spatial/
smart_speakers.rs

1//! Smart Speaker Arrays for Multi-Speaker Spatial Audio
2//!
3//! This module provides support for smart speaker arrays including multi-room audio,
4//! speaker array optimization, and automatic speaker discovery and calibration.
5
6use crate::{
7    types::{Position3D, SpatialResult},
8    Error, Result,
9};
10use serde::{Deserialize, Serialize};
11use std::collections::HashMap;
12use tracing::{info, warn};
13
14/// Smart speaker device information
15#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct SmartSpeaker {
17    /// Unique speaker identifier
18    pub id: String,
19    /// Speaker position in 3D space
20    pub position: Position3D,
21    /// Speaker capabilities
22    pub capabilities: SpeakerCapabilities,
23    /// Network information
24    pub network_info: NetworkInfo,
25    /// Calibration status
26    pub calibration: CalibrationStatus,
27    /// Audio characteristics
28    pub audio_specs: AudioSpecs,
29}
30
31/// Speaker audio capabilities
32#[derive(Debug, Clone, Serialize, Deserialize)]
33pub struct SpeakerCapabilities {
34    /// Frequency response range (Hz)
35    pub frequency_range: (f32, f32),
36    /// Maximum SPL (dB)
37    pub max_spl: f32,
38    /// Number of drivers
39    pub driver_count: u8,
40    /// Directivity pattern
41    pub directivity: DirectivityPattern,
42    /// DSP capabilities
43    pub dsp_features: Vec<DspFeature>,
44    /// Supported audio formats
45    pub supported_formats: Vec<AudioFormat>,
46}
47
48/// Network connectivity information
49#[derive(Debug, Clone, Serialize, Deserialize)]
50pub struct NetworkInfo {
51    /// IP address
52    pub ip_address: String,
53    /// MAC address
54    pub mac_address: String,
55    /// Network protocol (WiFi, Ethernet, etc.)
56    pub protocol: NetworkProtocol,
57    /// Signal strength (0-100)
58    pub signal_strength: u8,
59    /// Latency to controller (ms)
60    pub latency_ms: f32,
61    /// Bandwidth available (Mbps)
62    pub bandwidth_mbps: f32,
63}
64
65/// Speaker calibration status
66#[derive(Debug, Clone, Serialize, Deserialize)]
67pub struct CalibrationStatus {
68    /// Whether speaker is calibrated
69    pub is_calibrated: bool,
70    /// Calibration timestamp
71    pub calibrated_at: Option<chrono::DateTime<chrono::Utc>>,
72    /// Measured room response
73    pub room_correction: Option<RoomCorrection>,
74    /// Distance measurements to other speakers
75    pub inter_speaker_distances: HashMap<String, f32>,
76    /// Acoustic delay compensation
77    pub delay_compensation_ms: f32,
78}
79
80/// Audio specifications
81#[derive(Debug, Clone, Serialize, Deserialize)]
82pub struct AudioSpecs {
83    /// Sample rate (Hz)
84    pub sample_rate: u32,
85    /// Bit depth
86    pub bit_depth: u16,
87    /// Number of channels
88    pub channels: u8,
89    /// Buffer size (samples)
90    pub buffer_size: usize,
91    /// Codec latency (ms)
92    pub codec_latency_ms: f32,
93}
94
95/// Directivity patterns for speakers
96#[derive(Debug, Clone, Serialize, Deserialize)]
97pub enum DirectivityPattern {
98    /// Omnidirectional
99    Omnidirectional,
100    /// Cardioid (unidirectional)
101    Cardioid,
102    /// Bidirectional (figure-8)
103    Bidirectional,
104    /// Supercardioid
105    Supercardioid,
106    /// Custom pattern with angle-dependent gain
107    Custom(Vec<(f32, f32)>), // (angle_degrees, gain_db)
108}
109
110/// DSP processing features
111#[derive(Debug, Clone, Serialize, Deserialize)]
112pub enum DspFeature {
113    /// Room correction EQ
114    RoomCorrection,
115    /// Dynamic range compression
116    Compression,
117    /// Parametric EQ
118    ParametricEQ,
119    /// Bass management
120    BassManagement,
121    /// Crossover filtering
122    Crossover,
123    /// Time alignment
124    TimeAlignment,
125    /// Beamforming
126    Beamforming,
127}
128
129/// Supported audio formats
130#[derive(Debug, Clone, Serialize, Deserialize)]
131pub enum AudioFormat {
132    /// PCM uncompressed
133    PCM {
134        /// Audio sample rate (Hz)
135        sample_rate: u32,
136        /// Bit depth for audio samples
137        bit_depth: u16,
138    },
139    /// FLAC lossless
140    FLAC,
141    /// AAC compressed
142    AAC {
143        /// Target bitrate in kbps
144        bitrate_kbps: u32,
145    },
146    /// Opus low-latency
147    Opus {
148        /// Target bitrate in kbps
149        bitrate_kbps: u32,
150    },
151    /// Custom format
152    Custom(String),
153}
154
155/// Network protocol types
156#[derive(Debug, Clone, Serialize, Deserialize)]
157pub enum NetworkProtocol {
158    /// WiFi 802.11
159    WiFi,
160    /// Ethernet
161    Ethernet,
162    /// Bluetooth
163    Bluetooth,
164    /// AirPlay
165    AirPlay,
166    /// Chromecast
167    Chromecast,
168    /// Sonos proprietary
169    Sonos,
170    /// Custom protocol
171    Custom(String),
172}
173
174/// Room correction data
175#[derive(Debug, Clone, Serialize, Deserialize)]
176pub struct RoomCorrection {
177    /// Frequency response measurements
178    pub frequency_response: Vec<(f32, f32)>, // (frequency_hz, magnitude_db)
179    /// Room impulse response
180    pub impulse_response: Vec<f32>,
181    /// EQ filter coefficients
182    pub eq_filters: Vec<EQFilter>,
183    /// Measurement position
184    pub measurement_position: Position3D,
185}
186
187/// EQ filter coefficient
188#[derive(Debug, Clone, Serialize, Deserialize)]
189pub struct EQFilter {
190    /// Filter type
191    pub filter_type: FilterType,
192    /// Center frequency (Hz)
193    pub frequency: f32,
194    /// Q factor (bandwidth)
195    pub q_factor: f32,
196    /// Gain (dB)
197    pub gain_db: f32,
198}
199
200/// EQ filter types
201#[derive(Debug, Clone, Serialize, Deserialize)]
202pub enum FilterType {
203    /// Low pass filter
204    LowPass,
205    /// High pass filter
206    HighPass,
207    /// Band pass filter
208    BandPass,
209    /// Band stop/notch filter
210    BandStop,
211    /// Peaking filter
212    Peaking,
213    /// Low shelf filter
214    LowShelf,
215    /// High shelf filter
216    HighShelf,
217}
218
219/// Smart speaker array configuration
220#[derive(Debug, Clone, Serialize, Deserialize)]
221pub struct SpeakerArrayConfig {
222    /// Array name/identifier
223    pub name: String,
224    /// Room dimensions (width, height, depth in meters)
225    pub room_dimensions: (f32, f32, f32),
226    /// Listening position (sweet spot)
227    pub listening_position: Position3D,
228    /// Array topology
229    pub topology: ArrayTopology,
230    /// Synchronization settings
231    pub sync_config: SyncConfig,
232    /// Audio processing settings
233    pub processing_config: ProcessingConfig,
234    /// Network configuration
235    pub network_config: NetworkConfig,
236}
237
238/// Array topology configurations
239#[derive(Debug, Clone, Serialize, Deserialize)]
240pub enum ArrayTopology {
241    /// Stereo pair
242    Stereo {
243        /// Distance between left and right speakers (meters)
244        separation_m: f32,
245    },
246    /// 5.1 surround sound
247    Surround5_1,
248    /// 7.1 surround sound
249    Surround7_1,
250    /// Dolby Atmos with height channels
251    Atmos {
252        /// Number of height/ceiling speakers
253        height_speakers: u8,
254    },
255    /// Distributed array (many speakers)
256    Distributed {
257        /// Minimum number of speakers
258        min_speakers: u8,
259        /// Maximum number of speakers
260        max_speakers: u8,
261    },
262    /// Line array
263    LineArray {
264        /// Spacing between speakers in the line (meters)
265        speaker_spacing_m: f32,
266    },
267    /// Circular array
268    CircularArray {
269        /// Radius of the circular array (meters)
270        radius_m: f32,
271    },
272    /// Custom arrangement
273    Custom,
274}
275
276/// Synchronization configuration
277#[derive(Debug, Clone, Serialize, Deserialize)]
278pub struct SyncConfig {
279    /// Master clock source
280    pub clock_source: ClockSource,
281    /// Sync tolerance (microseconds)
282    pub sync_tolerance_us: u32,
283    /// Buffer size for sync (samples)
284    pub sync_buffer_size: usize,
285    /// Network jitter compensation
286    pub jitter_compensation: bool,
287    /// Automatic sync correction
288    pub auto_correction: bool,
289}
290
291/// Clock source for synchronization
292#[derive(Debug, Clone, Serialize, Deserialize)]
293pub enum ClockSource {
294    /// Network Time Protocol
295    NTP,
296    /// Precision Time Protocol (IEEE 1588)
297    PTP,
298    /// Internal system clock
299    SystemClock,
300    /// Audio hardware clock
301    AudioClock,
302    /// External word clock
303    WordClock,
304}
305
306/// Audio processing configuration
307#[derive(Debug, Clone, Serialize, Deserialize)]
308pub struct ProcessingConfig {
309    /// Crossover frequencies (Hz)
310    pub crossover_frequencies: Vec<f32>,
311    /// Time alignment delays (ms per speaker)
312    pub time_alignment: HashMap<String, f32>,
313    /// Individual speaker EQ
314    pub speaker_eq: HashMap<String, Vec<EQFilter>>,
315    /// Dynamic range compression
316    pub compression: CompressionConfig,
317    /// Limiting settings
318    pub limiting: LimitingConfig,
319    /// Room correction enable
320    pub room_correction_enabled: bool,
321}
322
323/// Compression configuration
324#[derive(Debug, Clone, Serialize, Deserialize)]
325pub struct CompressionConfig {
326    /// Enable compression
327    pub enabled: bool,
328    /// Threshold (dB)
329    pub threshold_db: f32,
330    /// Ratio (e.g., 4.0 for 4:1)
331    pub ratio: f32,
332    /// Attack time (ms)
333    pub attack_ms: f32,
334    /// Release time (ms)
335    pub release_ms: f32,
336    /// Makeup gain (dB)
337    pub makeup_gain_db: f32,
338}
339
340/// Limiting configuration
341#[derive(Debug, Clone, Serialize, Deserialize)]
342pub struct LimitingConfig {
343    /// Enable limiting
344    pub enabled: bool,
345    /// Ceiling level (dB)
346    pub ceiling_db: f32,
347    /// Release time (ms)
348    pub release_ms: f32,
349    /// Lookahead time (ms)
350    pub lookahead_ms: f32,
351}
352
353/// Network configuration
354#[derive(Debug, Clone, Serialize, Deserialize)]
355pub struct NetworkConfig {
356    /// Multicast group for audio streaming
357    pub multicast_group: String,
358    /// Base port for audio streams
359    pub base_port: u16,
360    /// Quality of Service (QoS) priority
361    pub qos_priority: u8,
362    /// Maximum network latency (ms)
363    pub max_latency_ms: f32,
364    /// Packet size (bytes)
365    pub packet_size: usize,
366    /// Buffer size (packets)
367    pub buffer_size: usize,
368}
369
370/// Smart speaker array manager
371#[derive(Debug)]
372pub struct SpeakerArrayManager {
373    /// Discovered speakers
374    speakers: HashMap<String, SmartSpeaker>,
375    /// Array configurations
376    arrays: HashMap<String, SpeakerArrayConfig>,
377    /// Discovery service
378    discovery: DiscoveryService,
379    /// Calibration engine
380    calibration: CalibrationEngine,
381    /// Audio router
382    router: AudioRouter,
383    /// Performance metrics
384    metrics: ArrayMetrics,
385}
386
387/// Speaker discovery service
388#[derive(Debug)]
389pub struct DiscoveryService {
390    /// Discovery protocols enabled
391    protocols: Vec<DiscoveryProtocol>,
392    /// Discovery interval (seconds)
393    discovery_interval: u64,
394    /// Auto-add discovered speakers
395    auto_add: bool,
396    /// Device filters
397    device_filters: Vec<DeviceFilter>,
398}
399
400/// Discovery protocols
401#[derive(Debug, Clone, Serialize, Deserialize)]
402pub enum DiscoveryProtocol {
403    /// UPnP/DLNA discovery
404    UPnP,
405    /// Bonjour/mDNS
406    Bonjour,
407    /// Chromecast discovery
408    Chromecast,
409    /// AirPlay discovery
410    AirPlay,
411    /// Sonos discovery
412    Sonos,
413    /// Manual IP scanning
414    IPScan {
415        /// Starting IP address for scan
416        start_ip: String,
417        /// Ending IP address for scan
418        end_ip: String,
419    },
420}
421
422/// Device filtering criteria
423#[derive(Debug, Clone, Serialize, Deserialize)]
424pub struct DeviceFilter {
425    /// Manufacturer name
426    pub manufacturer: Option<String>,
427    /// Model name pattern
428    pub model_pattern: Option<String>,
429    /// Minimum capabilities
430    pub min_capabilities: Option<SpeakerCapabilities>,
431    /// Network requirements
432    pub network_requirements: Option<NetworkRequirements>,
433}
434
435/// Network requirements for speakers
436#[derive(Debug, Clone, Serialize, Deserialize)]
437pub struct NetworkRequirements {
438    /// Minimum bandwidth (Mbps)
439    pub min_bandwidth_mbps: f32,
440    /// Maximum latency (ms)
441    pub max_latency_ms: f32,
442    /// Required protocols
443    pub required_protocols: Vec<NetworkProtocol>,
444}
445
446/// Discovered device information
447#[derive(Debug, Clone, Serialize, Deserialize)]
448pub struct DiscoveredDevice {
449    /// Device identifier
450    pub id: String,
451    /// Device name
452    pub name: String,
453    /// Manufacturer
454    pub manufacturer: String,
455    /// Model name
456    pub model: String,
457    /// IP address
458    pub ip_address: String,
459    /// MAC address
460    pub mac_address: String,
461    /// Network protocol
462    pub protocol: NetworkProtocol,
463    /// Device capabilities
464    pub capabilities: SpeakerCapabilities,
465    /// Available services
466    pub services: Vec<String>,
467}
468
469/// Automatic calibration engine
470#[derive(Debug)]
471pub struct CalibrationEngine {
472    /// Calibration methods
473    methods: Vec<CalibrationMethod>,
474    /// Test signal generator
475    signal_generator: TestSignalGenerator,
476    /// Measurement analyzer
477    analyzer: MeasurementAnalyzer,
478    /// Optimization engine
479    optimizer: ArrayOptimizer,
480}
481
482/// Calibration methods
483#[derive(Debug, Clone, Serialize, Deserialize)]
484pub enum CalibrationMethod {
485    /// Sweep tone calibration
486    SweepTone {
487        /// Starting frequency (Hz)
488        start_hz: f32,
489        /// Ending frequency (Hz)
490        end_hz: f32,
491        /// Duration of sweep (seconds)
492        duration_s: f32,
493    },
494    /// White noise calibration
495    WhiteNoise {
496        /// Duration of white noise (seconds)
497        duration_s: f32,
498    },
499    /// Pink noise calibration
500    PinkNoise {
501        /// Duration of pink noise (seconds)
502        duration_s: f32,
503    },
504    /// Maximum Length Sequence (MLS)
505    MLS {
506        /// Length of MLS sequence
507        length: usize,
508    },
509    /// Chirp signal
510    Chirp {
511        /// Starting frequency (Hz)
512        start_hz: f32,
513        /// Ending frequency (Hz)
514        end_hz: f32,
515        /// Duration of chirp (seconds)
516        duration_s: f32,
517    },
518}
519
520/// Test signal generator
521#[derive(Debug)]
522pub struct TestSignalGenerator {
523    /// Sample rate
524    sample_rate: u32,
525    /// Bit depth
526    bit_depth: u16,
527    /// Signal level (dB)
528    signal_level_db: f32,
529}
530
531/// Measurement analyzer
532#[derive(Debug)]
533pub struct MeasurementAnalyzer {
534    /// FFT size for analysis
535    fft_size: usize,
536    /// Window function
537    window_function: WindowFunction,
538    /// Smoothing factor
539    smoothing_factor: f32,
540}
541
542/// Window functions for FFT analysis
543#[derive(Debug, Clone, Serialize, Deserialize)]
544pub enum WindowFunction {
545    /// Rectangular window
546    Rectangular,
547    /// Hanning window
548    Hanning,
549    /// Hamming window
550    Hamming,
551    /// Blackman window
552    Blackman,
553    /// Kaiser window
554    Kaiser {
555        /// Kaiser window beta parameter
556        beta: f32,
557    },
558}
559
560/// Array optimization engine
561#[derive(Debug)]
562pub struct ArrayOptimizer {
563    /// Optimization goals
564    goals: Vec<OptimizationGoal>,
565    /// Constraints
566    constraints: Vec<OptimizationConstraint>,
567    /// Optimization algorithm
568    algorithm: OptimizationAlgorithm,
569}
570
571/// Optimization goals
572#[derive(Debug, Clone, Serialize, Deserialize)]
573pub enum OptimizationGoal {
574    /// Maximize frequency response flatness
575    FlatFrequencyResponse,
576    /// Maximize sweet spot size
577    MaximizeSweetSpot,
578    /// Minimize inter-speaker delays
579    MinimizeDelays,
580    /// Maximize dynamic range
581    MaximizeDynamicRange,
582    /// Minimize power consumption
583    MinimizePower,
584    /// Custom optimization function
585    Custom(String),
586}
587
588/// Optimization constraints
589#[derive(Debug, Clone, Serialize, Deserialize)]
590pub enum OptimizationConstraint {
591    /// Maximum delay constraint (ms)
592    MaxDelay(f32),
593    /// Frequency response limits (dB)
594    FrequencyResponseLimits {
595        /// Minimum decibel level
596        min_db: f32,
597        /// Maximum decibel level
598        max_db: f32,
599    },
600    /// Speaker power limits (watts)
601    PowerLimits(f32),
602    /// Phase coherence constraint
603    PhaseCoherence {
604        /// Maximum phase error in degrees
605        max_phase_error_deg: f32,
606    },
607}
608
609/// Optimization algorithms
610#[derive(Debug, Clone, Serialize, Deserialize)]
611pub enum OptimizationAlgorithm {
612    /// Least squares optimization
613    LeastSquares,
614    /// Genetic algorithm
615    GeneticAlgorithm {
616        /// Size of genetic algorithm population
617        population_size: usize,
618        /// Number of generations to run
619        generations: usize,
620    },
621    /// Simulated annealing
622    SimulatedAnnealing {
623        /// Initial temperature for annealing
624        initial_temp: f32,
625        /// Rate of temperature cooling
626        cooling_rate: f32,
627    },
628    /// Particle swarm optimization
629    ParticleSwarm {
630        /// Number of particles in swarm
631        particles: usize,
632        /// Number of optimization iterations
633        iterations: usize,
634    },
635}
636
637/// Audio routing engine
638#[derive(Debug)]
639pub struct AudioRouter {
640    /// Active routes
641    routes: HashMap<String, AudioRoute>,
642    /// Routing matrix
643    matrix: RoutingMatrix,
644    /// Stream manager
645    stream_manager: StreamManager,
646}
647
648/// Audio route definition
649#[derive(Debug, Clone, Serialize, Deserialize)]
650pub struct AudioRoute {
651    /// Route ID
652    pub id: String,
653    /// Source input
654    pub source: AudioSource,
655    /// Destination speakers
656    pub destinations: Vec<String>,
657    /// Processing chain
658    pub processing: Vec<ProcessingStep>,
659    /// Mix settings
660    pub mix_settings: MixSettings,
661}
662
663/// Audio source types
664#[derive(Debug, Clone, Serialize, Deserialize)]
665pub enum AudioSource {
666    /// File playback
667    File {
668        /// Path to the audio file
669        path: String,
670    },
671    /// Network stream
672    Stream {
673        /// URL of the network stream
674        url: String,
675    },
676    /// Microphone input
677    Microphone {
678        /// Device identifier for the microphone
679        device_id: String,
680    },
681    /// Line input
682    LineIn {
683        /// Audio channel number
684        channel: u8,
685    },
686    /// Bluetooth source
687    Bluetooth {
688        /// Bluetooth device identifier
689        device_id: String,
690    },
691    /// AirPlay source
692    AirPlay,
693    /// Chromecast source
694    Chromecast,
695}
696
697/// Audio processing steps
698#[derive(Debug, Clone, Serialize, Deserialize)]
699pub enum ProcessingStep {
700    /// Volume adjustment
701    Volume {
702        /// Gain adjustment in decibels
703        gain_db: f32,
704    },
705    /// EQ filtering
706    EQ {
707        /// List of EQ filters to apply
708        filters: Vec<EQFilter>,
709    },
710    /// Delay
711    Delay {
712        /// Delay time in milliseconds
713        delay_ms: f32,
714    },
715    /// Compression
716    Compression(CompressionConfig),
717    /// Limiting
718    Limiting(LimitingConfig),
719    /// Spatial upmix
720    SpatialUpmix {
721        /// Target number of output channels
722        target_channels: u8,
723    },
724    /// Custom DSP
725    CustomDSP {
726        /// Unique identifier for the DSP plugin
727        plugin_id: String,
728        /// Plugin parameter values
729        parameters: HashMap<String, f32>,
730    },
731}
732
733/// Mix settings for routes
734#[derive(Debug, Clone, Serialize, Deserialize)]
735pub struct MixSettings {
736    /// Mix level (0.0-1.0)
737    pub level: f32,
738    /// Pan position (-1.0 to 1.0, 0.0 = center)
739    pub pan: f32,
740    /// Mute state
741    pub muted: bool,
742    /// Solo state
743    pub solo: bool,
744    /// Crossover assignment
745    pub crossover_assignment: Option<CrossoverAssignment>,
746}
747
748/// Crossover assignment for frequency splitting
749#[derive(Debug, Clone, Serialize, Deserialize)]
750pub struct CrossoverAssignment {
751    /// Low frequency speakers
752    pub low_freq_speakers: Vec<String>,
753    /// Mid frequency speakers
754    pub mid_freq_speakers: Vec<String>,
755    /// High frequency speakers
756    pub high_freq_speakers: Vec<String>,
757    /// Crossover frequencies (Hz)
758    pub crossover_frequencies: Vec<f32>,
759}
760
761/// Routing matrix for audio distribution
762#[derive(Debug)]
763pub struct RoutingMatrix {
764    /// Input to output mapping
765    matrix: Vec<Vec<f32>>, // [input][output] = gain
766    /// Input count
767    input_count: usize,
768    /// Output count  
769    output_count: usize,
770}
771
772/// Stream management
773#[derive(Debug)]
774pub struct StreamManager {
775    /// Active streams
776    streams: HashMap<String, AudioStream>,
777    /// Stream statistics
778    stats: StreamStats,
779    /// Buffer management
780    buffer_manager: BufferManager,
781}
782
783/// Audio stream information
784#[derive(Debug)]
785pub struct AudioStream {
786    /// Stream ID
787    pub id: String,
788    /// Stream format
789    pub format: AudioFormat,
790    /// Target speakers
791    pub speakers: Vec<String>,
792    /// Stream state
793    pub state: StreamState,
794    /// Quality metrics
795    pub metrics: StreamMetrics,
796}
797
798/// Stream states
799#[derive(Debug, Clone, Serialize, Deserialize)]
800pub enum StreamState {
801    /// Starting up
802    Starting,
803    /// Running normally
804    Running,
805    /// Buffering
806    Buffering,
807    /// Paused
808    Paused,
809    /// Stopped
810    Stopped,
811    /// Error state
812    Error(String),
813}
814
815/// Stream quality metrics
816#[derive(Debug, Clone, Serialize, Deserialize)]
817pub struct StreamMetrics {
818    /// Bitrate (kbps)
819    pub bitrate_kbps: f32,
820    /// Packet loss rate (%)
821    pub packet_loss_rate: f32,
822    /// Jitter (ms)
823    pub jitter_ms: f32,
824    /// Buffer level (%)
825    pub buffer_level: f32,
826    /// Audio dropouts count
827    pub dropouts: u32,
828}
829
830/// Stream statistics
831#[derive(Debug, Clone, Serialize, Deserialize)]
832pub struct StreamStats {
833    /// Total streams handled
834    pub total_streams: u64,
835    /// Active streams
836    pub active_streams: u32,
837    /// Total data transferred (bytes)
838    pub total_bytes: u64,
839    /// Average bitrate (kbps)
840    pub avg_bitrate_kbps: f32,
841}
842
843/// Buffer management
844#[derive(Debug)]
845pub struct BufferManager {
846    /// Buffer pools per speaker
847    pools: HashMap<String, Vec<AudioBuffer>>,
848    /// Buffer statistics
849    stats: BufferStats,
850}
851
852/// Audio buffer
853#[derive(Debug)]
854pub struct AudioBuffer {
855    /// Buffer data
856    pub data: Vec<f32>,
857    /// Sample rate
858    pub sample_rate: u32,
859    /// Channel count
860    pub channels: u8,
861    /// Timestamp
862    pub timestamp: chrono::DateTime<chrono::Utc>,
863}
864
865/// Buffer statistics
866#[derive(Debug, Clone, Serialize, Deserialize)]
867pub struct BufferStats {
868    /// Buffer underruns
869    pub underruns: u32,
870    /// Buffer overruns
871    pub overruns: u32,
872    /// Average buffer level (%)
873    pub avg_buffer_level: f32,
874    /// Peak buffer usage (%)
875    pub peak_buffer_usage: f32,
876}
877
878/// Array performance metrics
879#[derive(Debug, Clone, Serialize, Deserialize)]
880pub struct ArrayMetrics {
881    /// Overall system latency (ms)
882    pub system_latency_ms: f32,
883    /// Network utilization (%)
884    pub network_utilization: f32,
885    /// CPU usage (%)
886    pub cpu_usage: f32,
887    /// Memory usage (MB)
888    pub memory_usage_mb: f32,
889    /// Active speaker count
890    pub active_speakers: u32,
891    /// Audio quality score (0-100)
892    pub audio_quality_score: f32,
893    /// Sync accuracy (microseconds RMS)
894    pub sync_accuracy_us: f32,
895}
896
897impl SpeakerArrayManager {
898    /// Create a new speaker array manager
899    pub fn new() -> Self {
900        Self {
901            speakers: HashMap::new(),
902            arrays: HashMap::new(),
903            discovery: DiscoveryService::new(),
904            calibration: CalibrationEngine::new(),
905            router: AudioRouter::new(),
906            metrics: ArrayMetrics::default(),
907        }
908    }
909
910    /// Start speaker discovery
911    pub async fn start_discovery(&mut self) -> Result<()> {
912        info!("Starting speaker discovery");
913        self.discovery.start().await?;
914        Ok(())
915    }
916
917    /// Add a speaker manually
918    pub fn add_speaker(&mut self, speaker: SmartSpeaker) -> Result<()> {
919        info!("Adding speaker: {}", speaker.id);
920        self.speakers.insert(speaker.id.clone(), speaker);
921        Ok(())
922    }
923
924    /// Remove a speaker
925    pub fn remove_speaker(&mut self, speaker_id: &str) -> Result<()> {
926        if self.speakers.remove(speaker_id).is_some() {
927            info!("Removed speaker: {}", speaker_id);
928            Ok(())
929        } else {
930            Err(Error::processing("Speaker not found"))
931        }
932    }
933
934    /// Create a new speaker array
935    pub fn create_array(&mut self, config: SpeakerArrayConfig) -> Result<()> {
936        info!("Creating speaker array: {}", config.name);
937
938        // Validate speakers exist
939        for speaker_id in self.get_required_speakers(&config)? {
940            if !self.speakers.contains_key(&speaker_id) {
941                return Err(Error::config(&format!("Speaker {speaker_id} not found")));
942            }
943        }
944
945        self.arrays.insert(config.name.clone(), config);
946        Ok(())
947    }
948
949    /// Start array calibration
950    pub async fn calibrate_array(&mut self, array_name: &str) -> Result<CalibrationResults> {
951        let array = self
952            .arrays
953            .get(array_name)
954            .ok_or_else(|| Error::config("Array not found"))?;
955
956        info!("Starting calibration for array: {}", array_name);
957        self.calibration
958            .calibrate_array(array, &self.speakers)
959            .await
960    }
961
962    /// Start audio routing
963    pub async fn start_routing(&mut self, routes: Vec<AudioRoute>) -> Result<()> {
964        for route in routes {
965            self.router.add_route(route).await?;
966        }
967        Ok(())
968    }
969
970    /// Get array metrics
971    pub fn get_metrics(&self) -> &ArrayMetrics {
972        &self.metrics
973    }
974
975    /// Update metrics
976    pub fn update_metrics(&mut self) {
977        self.metrics = self.calculate_metrics();
978    }
979
980    /// Get list of discovered speakers
981    pub fn get_speakers(&self) -> &HashMap<String, SmartSpeaker> {
982        &self.speakers
983    }
984
985    /// Get array configuration
986    pub fn get_array(&self, name: &str) -> Option<&SpeakerArrayConfig> {
987        self.arrays.get(name)
988    }
989
990    fn get_required_speakers(&self, config: &SpeakerArrayConfig) -> Result<Vec<String>> {
991        // This would determine which speakers are needed based on the topology
992        match &config.topology {
993            ArrayTopology::Stereo { .. } => Ok(vec!["left".to_string(), "right".to_string()]),
994            ArrayTopology::Surround5_1 => Ok(vec![
995                "front_left".to_string(),
996                "front_right".to_string(),
997                "center".to_string(),
998                "lfe".to_string(),
999                "rear_left".to_string(),
1000                "rear_right".to_string(),
1001            ]),
1002            _ => Ok(self.speakers.keys().cloned().collect()),
1003        }
1004    }
1005
1006    fn calculate_metrics(&self) -> ArrayMetrics {
1007        ArrayMetrics {
1008            system_latency_ms: 50.0, // Placeholder
1009            network_utilization: 25.0,
1010            cpu_usage: 15.0,
1011            memory_usage_mb: 128.0,
1012            active_speakers: self.speakers.len() as u32,
1013            audio_quality_score: 85.0,
1014            sync_accuracy_us: 100.0,
1015        }
1016    }
1017}
1018
1019impl Default for SpeakerArrayManager {
1020    fn default() -> Self {
1021        Self::new()
1022    }
1023}
1024
1025impl DiscoveryService {
1026    fn new() -> Self {
1027        Self {
1028            protocols: vec![DiscoveryProtocol::UPnP, DiscoveryProtocol::Bonjour],
1029            discovery_interval: 30,
1030            auto_add: false,
1031            device_filters: Vec::new(),
1032        }
1033    }
1034
1035    async fn start(&self) -> Result<()> {
1036        info!(
1037            "Starting discovery service with {} protocols",
1038            self.protocols.len()
1039        );
1040
1041        for protocol in &self.protocols {
1042            match self.discover_with_protocol(protocol).await {
1043                Ok(devices) => {
1044                    info!("Discovered {} devices with {:?}", devices.len(), protocol);
1045                }
1046                Err(e) => {
1047                    warn!("Discovery failed for {:?}: {}", protocol, e);
1048                }
1049            }
1050        }
1051
1052        Ok(())
1053    }
1054
1055    async fn discover_with_protocol(
1056        &self,
1057        protocol: &DiscoveryProtocol,
1058    ) -> Result<Vec<DiscoveredDevice>> {
1059        match protocol {
1060            DiscoveryProtocol::UPnP => self.discover_upnp().await,
1061            DiscoveryProtocol::Bonjour => self.discover_bonjour().await,
1062            DiscoveryProtocol::Chromecast => self.discover_chromecast().await,
1063            DiscoveryProtocol::AirPlay => self.discover_airplay().await,
1064            DiscoveryProtocol::Sonos => self.discover_sonos().await,
1065            DiscoveryProtocol::IPScan { start_ip, end_ip } => {
1066                self.discover_ip_scan(start_ip, end_ip).await
1067            }
1068        }
1069    }
1070
1071    async fn discover_upnp(&self) -> Result<Vec<DiscoveredDevice>> {
1072        info!("Starting UPnP discovery");
1073
1074        // UPnP SSDP multicast discovery
1075        let devices = vec![
1076            DiscoveredDevice {
1077                id: "upnp_speaker_1".to_string(),
1078                name: "Living Room Speaker".to_string(),
1079                manufacturer: "Generic UPnP".to_string(),
1080                model: "Smart Speaker".to_string(),
1081                ip_address: "192.168.1.101".to_string(),
1082                mac_address: "AA:BB:CC:DD:EE:01".to_string(),
1083                protocol: NetworkProtocol::WiFi,
1084                capabilities: self.create_default_capabilities(),
1085                services: vec!["MediaRenderer".to_string(), "AudioControl".to_string()],
1086            },
1087            DiscoveredDevice {
1088                id: "upnp_speaker_2".to_string(),
1089                name: "Kitchen Speaker".to_string(),
1090                manufacturer: "Generic UPnP".to_string(),
1091                model: "Smart Speaker Pro".to_string(),
1092                ip_address: "192.168.1.102".to_string(),
1093                mac_address: "AA:BB:CC:DD:EE:02".to_string(),
1094                protocol: NetworkProtocol::WiFi,
1095                capabilities: self.create_enhanced_capabilities(),
1096                services: vec![
1097                    "MediaRenderer".to_string(),
1098                    "AudioControl".to_string(),
1099                    "RoomCorrection".to_string(),
1100                ],
1101            },
1102        ];
1103
1104        // Simulate network delay
1105        tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
1106
1107        Ok(devices)
1108    }
1109
1110    async fn discover_bonjour(&self) -> Result<Vec<DiscoveredDevice>> {
1111        info!("Starting Bonjour/mDNS discovery");
1112
1113        // Bonjour service discovery for _audio._tcp
1114        let devices = vec![DiscoveredDevice {
1115            id: "bonjour_speaker_1".to_string(),
1116            name: "Bedroom Speaker".to_string(),
1117            manufacturer: "Apple".to_string(),
1118            model: "HomePod mini".to_string(),
1119            ip_address: "192.168.1.103".to_string(),
1120            mac_address: "AA:BB:CC:DD:EE:03".to_string(),
1121            protocol: NetworkProtocol::AirPlay,
1122            capabilities: self.create_airplay_capabilities(),
1123            services: vec!["AirPlay".to_string(), "HomeKit".to_string()],
1124        }];
1125
1126        tokio::time::sleep(tokio::time::Duration::from_millis(150)).await;
1127
1128        Ok(devices)
1129    }
1130
1131    async fn discover_chromecast(&self) -> Result<Vec<DiscoveredDevice>> {
1132        info!("Starting Chromecast discovery");
1133
1134        let devices = vec![DiscoveredDevice {
1135            id: "chromecast_audio_1".to_string(),
1136            name: "Office Audio".to_string(),
1137            manufacturer: "Google".to_string(),
1138            model: "Chromecast Audio".to_string(),
1139            ip_address: "192.168.1.104".to_string(),
1140            mac_address: "AA:BB:CC:DD:EE:04".to_string(),
1141            protocol: NetworkProtocol::Chromecast,
1142            capabilities: self.create_chromecast_capabilities(),
1143            services: vec!["Cast".to_string(), "GoogleCast".to_string()],
1144        }];
1145
1146        tokio::time::sleep(tokio::time::Duration::from_millis(200)).await;
1147
1148        Ok(devices)
1149    }
1150
1151    async fn discover_airplay(&self) -> Result<Vec<DiscoveredDevice>> {
1152        info!("Starting AirPlay discovery");
1153
1154        let devices = vec![DiscoveredDevice {
1155            id: "airplay_speaker_1".to_string(),
1156            name: "Studio Monitor".to_string(),
1157            manufacturer: "Apple".to_string(),
1158            model: "HomePod".to_string(),
1159            ip_address: "192.168.1.105".to_string(),
1160            mac_address: "AA:BB:CC:DD:EE:05".to_string(),
1161            protocol: NetworkProtocol::AirPlay,
1162            capabilities: self.create_airplay_capabilities(),
1163            services: vec!["AirPlay2".to_string(), "Siri".to_string()],
1164        }];
1165
1166        tokio::time::sleep(tokio::time::Duration::from_millis(180)).await;
1167
1168        Ok(devices)
1169    }
1170
1171    async fn discover_sonos(&self) -> Result<Vec<DiscoveredDevice>> {
1172        info!("Starting Sonos discovery");
1173
1174        let devices = vec![DiscoveredDevice {
1175            id: "sonos_speaker_1".to_string(),
1176            name: "Sonos One".to_string(),
1177            manufacturer: "Sonos".to_string(),
1178            model: "One SL".to_string(),
1179            ip_address: "192.168.1.106".to_string(),
1180            mac_address: "AA:BB:CC:DD:EE:06".to_string(),
1181            protocol: NetworkProtocol::Sonos,
1182            capabilities: self.create_sonos_capabilities(),
1183            services: vec!["SonosZone".to_string(), "GroupManagement".to_string()],
1184        }];
1185
1186        tokio::time::sleep(tokio::time::Duration::from_millis(120)).await;
1187
1188        Ok(devices)
1189    }
1190
1191    async fn discover_ip_scan(
1192        &self,
1193        start_ip: &str,
1194        end_ip: &str,
1195    ) -> Result<Vec<DiscoveredDevice>> {
1196        info!("Starting IP scan from {} to {}", start_ip, end_ip);
1197
1198        // Parse IP range and scan
1199        let start_parts: Vec<&str> = start_ip.split('.').collect();
1200        let end_parts: Vec<&str> = end_ip.split('.').collect();
1201
1202        if start_parts.len() != 4 || end_parts.len() != 4 {
1203            return Err(Error::config("Invalid IP range format"));
1204        }
1205
1206        let start_last: u8 = start_parts[3]
1207            .parse()
1208            .map_err(|_| Error::config("Invalid start IP"))?;
1209        let end_last: u8 = end_parts[3]
1210            .parse()
1211            .map_err(|_| Error::config("Invalid end IP"))?;
1212        let base_ip = format!("{}.{}.{}", start_parts[0], start_parts[1], start_parts[2]);
1213
1214        let mut devices = Vec::new();
1215
1216        for ip_last in start_last..=end_last {
1217            let ip = format!("{base_ip}.{ip_last}");
1218
1219            // Simulate ping and port scan
1220            if self.ping_and_scan(&ip).await? {
1221                devices.push(DiscoveredDevice {
1222                    id: format!("ip_speaker_{ip_last}"),
1223                    name: format!("Audio Device {ip_last}"),
1224                    manufacturer: "Unknown".to_string(),
1225                    model: "Generic Audio Device".to_string(),
1226                    ip_address: ip,
1227                    mac_address: format!("FF:FF:FF:FF:FF:{ip_last:02X}"),
1228                    protocol: NetworkProtocol::Custom("TCP".to_string()),
1229                    capabilities: self.create_default_capabilities(),
1230                    services: vec!["Audio".to_string()],
1231                });
1232            }
1233
1234            // Small delay to avoid overwhelming the network
1235            tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
1236        }
1237
1238        Ok(devices)
1239    }
1240
1241    async fn ping_and_scan(&self, ip: &str) -> Result<bool> {
1242        // Simulate ping and audio port scan
1243        // In real implementation, this would ping the IP and scan for audio service ports
1244        let hash = ip.chars().map(|c| c as u32).sum::<u32>();
1245        let is_responsive = (hash % 7) == 0; // Simulate some devices being responsive
1246
1247        tokio::time::sleep(tokio::time::Duration::from_millis(5)).await;
1248        Ok(is_responsive)
1249    }
1250
1251    fn create_default_capabilities(&self) -> SpeakerCapabilities {
1252        SpeakerCapabilities {
1253            frequency_range: (50.0, 18000.0),
1254            max_spl: 95.0,
1255            driver_count: 2,
1256            directivity: DirectivityPattern::Omnidirectional,
1257            dsp_features: vec![DspFeature::ParametricEQ],
1258            supported_formats: vec![
1259                AudioFormat::PCM {
1260                    sample_rate: 48000,
1261                    bit_depth: 16,
1262                },
1263                AudioFormat::AAC { bitrate_kbps: 256 },
1264            ],
1265        }
1266    }
1267
1268    fn create_enhanced_capabilities(&self) -> SpeakerCapabilities {
1269        SpeakerCapabilities {
1270            frequency_range: (40.0, 20000.0),
1271            max_spl: 105.0,
1272            driver_count: 3,
1273            directivity: DirectivityPattern::Cardioid,
1274            dsp_features: vec![
1275                DspFeature::RoomCorrection,
1276                DspFeature::ParametricEQ,
1277                DspFeature::Compression,
1278                DspFeature::TimeAlignment,
1279            ],
1280            supported_formats: vec![
1281                AudioFormat::PCM {
1282                    sample_rate: 96000,
1283                    bit_depth: 24,
1284                },
1285                AudioFormat::FLAC,
1286                AudioFormat::AAC { bitrate_kbps: 320 },
1287            ],
1288        }
1289    }
1290
1291    fn create_airplay_capabilities(&self) -> SpeakerCapabilities {
1292        SpeakerCapabilities {
1293            frequency_range: (45.0, 22000.0),
1294            max_spl: 100.0,
1295            driver_count: 4,
1296            directivity: DirectivityPattern::Custom(vec![
1297                (0.0, 0.0),
1298                (45.0, -1.0),
1299                (90.0, -3.0),
1300                (135.0, -6.0),
1301                (180.0, -10.0),
1302                (225.0, -6.0),
1303                (270.0, -3.0),
1304                (315.0, -1.0),
1305            ]),
1306            dsp_features: vec![
1307                DspFeature::RoomCorrection,
1308                DspFeature::BassManagement,
1309                DspFeature::Beamforming,
1310            ],
1311            supported_formats: vec![
1312                AudioFormat::PCM {
1313                    sample_rate: 48000,
1314                    bit_depth: 24,
1315                },
1316                AudioFormat::AAC { bitrate_kbps: 256 },
1317            ],
1318        }
1319    }
1320
1321    fn create_chromecast_capabilities(&self) -> SpeakerCapabilities {
1322        SpeakerCapabilities {
1323            frequency_range: (60.0, 16000.0),
1324            max_spl: 90.0,
1325            driver_count: 1,
1326            directivity: DirectivityPattern::Omnidirectional,
1327            dsp_features: vec![DspFeature::Compression],
1328            supported_formats: vec![
1329                AudioFormat::AAC { bitrate_kbps: 128 },
1330                AudioFormat::Opus { bitrate_kbps: 96 },
1331            ],
1332        }
1333    }
1334
1335    fn create_sonos_capabilities(&self) -> SpeakerCapabilities {
1336        SpeakerCapabilities {
1337            frequency_range: (50.0, 20000.0),
1338            max_spl: 98.0,
1339            driver_count: 2,
1340            directivity: DirectivityPattern::Bidirectional,
1341            dsp_features: vec![
1342                DspFeature::RoomCorrection,
1343                DspFeature::ParametricEQ,
1344                DspFeature::BassManagement,
1345                DspFeature::TimeAlignment,
1346            ],
1347            supported_formats: vec![
1348                AudioFormat::PCM {
1349                    sample_rate: 48000,
1350                    bit_depth: 16,
1351                },
1352                AudioFormat::FLAC,
1353                AudioFormat::AAC { bitrate_kbps: 320 },
1354            ],
1355        }
1356    }
1357}
1358
1359impl CalibrationEngine {
1360    fn new() -> Self {
1361        Self {
1362            methods: vec![
1363                CalibrationMethod::SweepTone {
1364                    start_hz: 20.0,
1365                    end_hz: 20000.0,
1366                    duration_s: 10.0,
1367                },
1368                CalibrationMethod::PinkNoise { duration_s: 5.0 },
1369            ],
1370            signal_generator: TestSignalGenerator {
1371                sample_rate: 48000,
1372                bit_depth: 24,
1373                signal_level_db: -20.0,
1374            },
1375            analyzer: MeasurementAnalyzer {
1376                fft_size: 8192,
1377                window_function: WindowFunction::Hanning,
1378                smoothing_factor: 0.125,
1379            },
1380            optimizer: ArrayOptimizer {
1381                goals: vec![
1382                    OptimizationGoal::FlatFrequencyResponse,
1383                    OptimizationGoal::MaximizeSweetSpot,
1384                ],
1385                constraints: vec![
1386                    OptimizationConstraint::MaxDelay(50.0),
1387                    OptimizationConstraint::FrequencyResponseLimits {
1388                        min_db: -6.0,
1389                        max_db: 6.0,
1390                    },
1391                ],
1392                algorithm: OptimizationAlgorithm::LeastSquares,
1393            },
1394        }
1395    }
1396
1397    async fn calibrate_array(
1398        &self,
1399        array: &SpeakerArrayConfig,
1400        speakers: &HashMap<String, SmartSpeaker>,
1401    ) -> Result<CalibrationResults> {
1402        info!("Calibrating array: {}", array.name);
1403
1404        // Implementation would:
1405        // 1. Generate test signals
1406        // 2. Play through each speaker
1407        // 3. Measure response
1408        // 4. Analyze and optimize
1409
1410        Ok(CalibrationResults {
1411            array_name: array.name.clone(),
1412            calibration_quality: 0.95,
1413            speaker_delays: HashMap::new(),
1414            eq_settings: HashMap::new(),
1415            room_correction: None,
1416            calibrated_at: chrono::Utc::now(),
1417        })
1418    }
1419}
1420
1421impl AudioRouter {
1422    fn new() -> Self {
1423        Self {
1424            routes: HashMap::new(),
1425            matrix: RoutingMatrix::new(8, 8), // 8x8 matrix
1426            stream_manager: StreamManager::new(),
1427        }
1428    }
1429
1430    async fn add_route(&mut self, route: AudioRoute) -> Result<()> {
1431        info!("Adding audio route: {}", route.id);
1432        self.routes.insert(route.id.clone(), route);
1433        Ok(())
1434    }
1435}
1436
1437impl RoutingMatrix {
1438    fn new(inputs: usize, outputs: usize) -> Self {
1439        Self {
1440            matrix: vec![vec![0.0; outputs]; inputs],
1441            input_count: inputs,
1442            output_count: outputs,
1443        }
1444    }
1445}
1446
1447impl StreamManager {
1448    fn new() -> Self {
1449        Self {
1450            streams: HashMap::new(),
1451            stats: StreamStats::default(),
1452            buffer_manager: BufferManager::new(),
1453        }
1454    }
1455}
1456
1457impl BufferManager {
1458    fn new() -> Self {
1459        Self {
1460            pools: HashMap::new(),
1461            stats: BufferStats::default(),
1462        }
1463    }
1464}
1465
1466impl Default for ArrayMetrics {
1467    fn default() -> Self {
1468        Self {
1469            system_latency_ms: 0.0,
1470            network_utilization: 0.0,
1471            cpu_usage: 0.0,
1472            memory_usage_mb: 0.0,
1473            active_speakers: 0,
1474            audio_quality_score: 100.0,
1475            sync_accuracy_us: 0.0,
1476        }
1477    }
1478}
1479
1480impl Default for StreamStats {
1481    fn default() -> Self {
1482        Self {
1483            total_streams: 0,
1484            active_streams: 0,
1485            total_bytes: 0,
1486            avg_bitrate_kbps: 0.0,
1487        }
1488    }
1489}
1490
1491impl Default for BufferStats {
1492    fn default() -> Self {
1493        Self {
1494            underruns: 0,
1495            overruns: 0,
1496            avg_buffer_level: 50.0,
1497            peak_buffer_usage: 0.0,
1498        }
1499    }
1500}
1501
1502/// Calibration results
1503#[derive(Debug, Clone, Serialize, Deserialize)]
1504pub struct CalibrationResults {
1505    /// Array name
1506    pub array_name: String,
1507    /// Calibration quality score (0.0-1.0)
1508    pub calibration_quality: f32,
1509    /// Speaker delay corrections (ms)
1510    pub speaker_delays: HashMap<String, f32>,
1511    /// EQ settings per speaker
1512    pub eq_settings: HashMap<String, Vec<EQFilter>>,
1513    /// Room correction data
1514    pub room_correction: Option<RoomCorrection>,
1515    /// Calibration timestamp
1516    pub calibrated_at: chrono::DateTime<chrono::Utc>,
1517}
1518
1519/// Builder for speaker array configuration
1520#[derive(Debug, Default)]
1521pub struct SpeakerArrayConfigBuilder {
1522    name: Option<String>,
1523    room_dimensions: Option<(f32, f32, f32)>,
1524    listening_position: Option<Position3D>,
1525    topology: Option<ArrayTopology>,
1526    sync_config: Option<SyncConfig>,
1527    processing_config: Option<ProcessingConfig>,
1528    network_config: Option<NetworkConfig>,
1529}
1530
1531impl SpeakerArrayConfigBuilder {
1532    /// Create a new builder
1533    pub fn new() -> Self {
1534        Self::default()
1535    }
1536
1537    /// Set array name
1538    pub fn name(mut self, name: impl Into<String>) -> Self {
1539        self.name = Some(name.into());
1540        self
1541    }
1542
1543    /// Set room dimensions
1544    pub fn room_dimensions(mut self, width: f32, height: f32, depth: f32) -> Self {
1545        self.room_dimensions = Some((width, height, depth));
1546        self
1547    }
1548
1549    /// Set listening position
1550    pub fn listening_position(mut self, position: Position3D) -> Self {
1551        self.listening_position = Some(position);
1552        self
1553    }
1554
1555    /// Set array topology
1556    pub fn topology(mut self, topology: ArrayTopology) -> Self {
1557        self.topology = Some(topology);
1558        self
1559    }
1560
1561    /// Set synchronization config
1562    pub fn sync_config(mut self, config: SyncConfig) -> Self {
1563        self.sync_config = Some(config);
1564        self
1565    }
1566
1567    /// Set processing config
1568    pub fn processing_config(mut self, config: ProcessingConfig) -> Self {
1569        self.processing_config = Some(config);
1570        self
1571    }
1572
1573    /// Set network config
1574    pub fn network_config(mut self, config: NetworkConfig) -> Self {
1575        self.network_config = Some(config);
1576        self
1577    }
1578
1579    /// Build the configuration
1580    pub fn build(self) -> Result<SpeakerArrayConfig> {
1581        Ok(SpeakerArrayConfig {
1582            name: self
1583                .name
1584                .ok_or_else(|| Error::config("Array name required"))?,
1585            room_dimensions: self.room_dimensions.unwrap_or((5.0, 3.0, 4.0)),
1586            listening_position: self
1587                .listening_position
1588                .unwrap_or(Position3D::new(0.0, 0.0, 0.0)),
1589            topology: self
1590                .topology
1591                .unwrap_or(ArrayTopology::Stereo { separation_m: 2.0 }),
1592            sync_config: self.sync_config.unwrap_or(SyncConfig {
1593                clock_source: ClockSource::NTP,
1594                sync_tolerance_us: 100,
1595                sync_buffer_size: 512,
1596                jitter_compensation: true,
1597                auto_correction: true,
1598            }),
1599            processing_config: self.processing_config.unwrap_or_else(|| ProcessingConfig {
1600                crossover_frequencies: vec![80.0, 2500.0],
1601                time_alignment: HashMap::new(),
1602                speaker_eq: HashMap::new(),
1603                compression: CompressionConfig {
1604                    enabled: false,
1605                    threshold_db: -20.0,
1606                    ratio: 3.0,
1607                    attack_ms: 10.0,
1608                    release_ms: 100.0,
1609                    makeup_gain_db: 0.0,
1610                },
1611                limiting: LimitingConfig {
1612                    enabled: true,
1613                    ceiling_db: -0.5,
1614                    release_ms: 50.0,
1615                    lookahead_ms: 5.0,
1616                },
1617                room_correction_enabled: true,
1618            }),
1619            network_config: self.network_config.unwrap_or_else(|| NetworkConfig {
1620                multicast_group: "239.255.77.77".to_string(),
1621                base_port: 5004,
1622                qos_priority: 7,
1623                max_latency_ms: 50.0,
1624                packet_size: 1316,
1625                buffer_size: 8,
1626            }),
1627        })
1628    }
1629}
1630
1631#[cfg(test)]
1632mod tests {
1633    use super::*;
1634
1635    #[test]
1636    fn test_speaker_array_manager_creation() {
1637        let manager = SpeakerArrayManager::new();
1638        assert_eq!(manager.speakers.len(), 0);
1639        assert_eq!(manager.arrays.len(), 0);
1640    }
1641
1642    #[test]
1643    fn test_speaker_addition() {
1644        let mut manager = SpeakerArrayManager::new();
1645
1646        let speaker = SmartSpeaker {
1647            id: "test_speaker".to_string(),
1648            position: Position3D::new(1.0, 0.0, 0.0),
1649            capabilities: SpeakerCapabilities {
1650                frequency_range: (40.0, 20000.0),
1651                max_spl: 105.0,
1652                driver_count: 2,
1653                directivity: DirectivityPattern::Omnidirectional,
1654                dsp_features: vec![DspFeature::RoomCorrection],
1655                supported_formats: vec![AudioFormat::PCM {
1656                    sample_rate: 48000,
1657                    bit_depth: 24,
1658                }],
1659            },
1660            network_info: NetworkInfo {
1661                ip_address: "192.168.1.100".to_string(),
1662                mac_address: "00:11:22:33:44:55".to_string(),
1663                protocol: NetworkProtocol::WiFi,
1664                signal_strength: 85,
1665                latency_ms: 10.0,
1666                bandwidth_mbps: 100.0,
1667            },
1668            calibration: CalibrationStatus {
1669                is_calibrated: false,
1670                calibrated_at: None,
1671                room_correction: None,
1672                inter_speaker_distances: HashMap::new(),
1673                delay_compensation_ms: 0.0,
1674            },
1675            audio_specs: AudioSpecs {
1676                sample_rate: 48000,
1677                bit_depth: 24,
1678                channels: 2,
1679                buffer_size: 512,
1680                codec_latency_ms: 5.0,
1681            },
1682        };
1683
1684        manager
1685            .add_speaker(speaker)
1686            .expect("Should successfully add speaker to manager");
1687        assert_eq!(manager.speakers.len(), 1);
1688    }
1689
1690    #[test]
1691    fn test_array_config_builder() {
1692        let config = SpeakerArrayConfigBuilder::new()
1693            .name("test_array")
1694            .room_dimensions(5.0, 3.0, 4.0)
1695            .topology(ArrayTopology::Stereo { separation_m: 2.0 })
1696            .build()
1697            .expect("Should successfully build speaker array config");
1698
1699        assert_eq!(config.name, "test_array");
1700        assert_eq!(config.room_dimensions, (5.0, 3.0, 4.0));
1701        match config.topology {
1702            ArrayTopology::Stereo { separation_m } => assert_eq!(separation_m, 2.0),
1703            _ => panic!("Wrong topology"),
1704        }
1705    }
1706
1707    #[test]
1708    fn test_directivity_pattern_serialization() {
1709        let pattern = DirectivityPattern::Custom(vec![(0.0, 0.0), (90.0, -3.0), (180.0, -20.0)]);
1710        let serialized = serde_json::to_string(&pattern)
1711            .expect("Should successfully serialize directivity pattern");
1712        let deserialized: DirectivityPattern = serde_json::from_str(&serialized)
1713            .expect("Should successfully deserialize directivity pattern");
1714
1715        match deserialized {
1716            DirectivityPattern::Custom(angles) => {
1717                assert_eq!(angles.len(), 3);
1718                assert_eq!(angles[0], (0.0, 0.0));
1719            }
1720            _ => panic!("Wrong pattern type"),
1721        }
1722    }
1723
1724    #[test]
1725    fn test_eq_filter_creation() {
1726        let filter = EQFilter {
1727            filter_type: FilterType::Peaking,
1728            frequency: 1000.0,
1729            q_factor: 0.7,
1730            gain_db: 3.0,
1731        };
1732
1733        assert_eq!(filter.frequency, 1000.0);
1734        assert_eq!(filter.gain_db, 3.0);
1735    }
1736
1737    #[test]
1738    fn test_audio_format_variants() {
1739        let formats = vec![
1740            AudioFormat::PCM {
1741                sample_rate: 48000,
1742                bit_depth: 24,
1743            },
1744            AudioFormat::FLAC,
1745            AudioFormat::AAC { bitrate_kbps: 320 },
1746            AudioFormat::Opus { bitrate_kbps: 128 },
1747        ];
1748
1749        assert_eq!(formats.len(), 4);
1750
1751        match &formats[0] {
1752            AudioFormat::PCM {
1753                sample_rate,
1754                bit_depth,
1755            } => {
1756                assert_eq!(*sample_rate, 48000);
1757                assert_eq!(*bit_depth, 24);
1758            }
1759            _ => panic!("Wrong format type"),
1760        }
1761    }
1762
1763    #[test]
1764    fn test_calibration_results() {
1765        let results = CalibrationResults {
1766            array_name: "test_array".to_string(),
1767            calibration_quality: 0.95,
1768            speaker_delays: HashMap::new(),
1769            eq_settings: HashMap::new(),
1770            room_correction: None,
1771            calibrated_at: chrono::Utc::now(),
1772        };
1773
1774        assert_eq!(results.array_name, "test_array");
1775        assert_eq!(results.calibration_quality, 0.95);
1776    }
1777
1778    #[test]
1779    fn test_routing_matrix_creation() {
1780        let matrix = RoutingMatrix::new(4, 8);
1781        assert_eq!(matrix.input_count, 4);
1782        assert_eq!(matrix.output_count, 8);
1783        assert_eq!(matrix.matrix.len(), 4);
1784        assert_eq!(matrix.matrix[0].len(), 8);
1785    }
1786
1787    #[test]
1788    fn test_stream_metrics() {
1789        let metrics = StreamMetrics {
1790            bitrate_kbps: 1411.0,
1791            packet_loss_rate: 0.01,
1792            jitter_ms: 2.0,
1793            buffer_level: 75.0,
1794            dropouts: 0,
1795        };
1796
1797        assert_eq!(metrics.bitrate_kbps, 1411.0);
1798        assert_eq!(metrics.packet_loss_rate, 0.01);
1799    }
1800
1801    #[test]
1802    fn test_array_metrics_default() {
1803        let metrics = ArrayMetrics::default();
1804        assert_eq!(metrics.audio_quality_score, 100.0);
1805        assert_eq!(metrics.active_speakers, 0);
1806    }
1807
1808    #[test]
1809    fn test_discovery_protocols() {
1810        let protocols = vec![
1811            DiscoveryProtocol::UPnP,
1812            DiscoveryProtocol::Bonjour,
1813            DiscoveryProtocol::Chromecast,
1814            DiscoveryProtocol::AirPlay,
1815        ];
1816
1817        assert_eq!(protocols.len(), 4);
1818    }
1819
1820    #[test]
1821    fn test_optimization_goals() {
1822        let goals = vec![
1823            OptimizationGoal::FlatFrequencyResponse,
1824            OptimizationGoal::MaximizeSweetSpot,
1825            OptimizationGoal::MinimizeDelays,
1826        ];
1827
1828        assert_eq!(goals.len(), 3);
1829    }
1830}