Skip to main content

voirs_spatial/multiuser/
impls.rs

1//! Implementation blocks for multi-user types
2
3use super::types::*;
4use crate::types::{Position3D, SpatialResult};
5use crate::{Error, Result};
6use std::collections::{HashMap, HashSet, VecDeque};
7use std::sync::{Arc, RwLock};
8use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
9
10impl Default for MultiUserConfig {
11    fn default() -> Self {
12        Self {
13            max_users_per_room: 50,
14            max_sources_per_user: 5,
15            sync_interval_ms: 50,
16            max_latency_ms: 100.0,
17            voice_activity_threshold: 0.3,
18            audio_quality: 0.8,
19            position_interpolation: true,
20            max_audio_distance: 100.0,
21            attenuation_curve: MultiUserAttenuationCurve::InverseDistance,
22            privacy_settings: PrivacySettings::default(),
23            bandwidth_settings: BandwidthSettings::default(),
24        }
25    }
26}
27
28impl Default for PrivacySettings {
29    fn default() -> Self {
30        Self {
31            encryption_enabled: true,
32            recording_allowed: false,
33            mute_controls_enabled: true,
34            spatial_zones_enabled: true,
35            permission_system: PermissionSystem::default(),
36            anonymization: AnonymizationSettings::default(),
37        }
38    }
39}
40
41impl Default for PermissionSystem {
42    fn default() -> Self {
43        let mut role_permissions = HashMap::new();
44
45        role_permissions.insert(UserRole::Guest, vec![Permission::Speak, Permission::Move]);
46        role_permissions.insert(
47            UserRole::Participant,
48            vec![
49                Permission::Speak,
50                Permission::Move,
51                Permission::CreateSources,
52            ],
53        );
54        role_permissions.insert(
55            UserRole::Presenter,
56            vec![
57                Permission::Speak,
58                Permission::Move,
59                Permission::CreateSources,
60                Permission::Broadcast,
61            ],
62        );
63        role_permissions.insert(
64            UserRole::Moderator,
65            vec![
66                Permission::Speak,
67                Permission::Move,
68                Permission::CreateSources,
69                Permission::MuteOthers,
70                Permission::ModifyRoom,
71                Permission::Moderate,
72            ],
73        );
74        role_permissions.insert(
75            UserRole::Administrator,
76            vec![
77                Permission::Speak,
78                Permission::Move,
79                Permission::CreateSources,
80                Permission::MuteOthers,
81                Permission::KickUsers,
82                Permission::ModifyRoom,
83                Permission::Record,
84                Permission::AccessPrivateZones,
85                Permission::Broadcast,
86                Permission::Moderate,
87            ],
88        );
89        role_permissions.insert(UserRole::Observer, vec![Permission::Move]);
90
91        Self {
92            rbac_enabled: true,
93            default_role: UserRole::Participant,
94            role_permissions,
95        }
96    }
97}
98
99impl Default for AnonymizationSettings {
100    fn default() -> Self {
101        Self {
102            anonymous_ids: false,
103            position_obfuscation: false,
104            temporal_obfuscation: false,
105            voice_modulation: false,
106        }
107    }
108}
109
110impl Default for BandwidthSettings {
111    fn default() -> Self {
112        Self {
113            adaptive_bitrate: true,
114            max_bandwidth_kbps: 128,
115            compression_level: 5,
116            proximity_quality_scaling: true,
117            low_bandwidth_mode: LowBandwidthMode {
118                enabled: false,
119                sample_rate: 16000,
120                bit_depth: 16,
121                max_streams: 5,
122                disable_spatial_effects: true,
123            },
124        }
125    }
126}
127
128impl MultiUserEnvironment {
129    /// Create a new multi-user environment
130    pub fn new(config: MultiUserConfig) -> Result<Self> {
131        let sync_manager = SynchronizationManager::new();
132        let audio_processor = MultiUserAudioProcessor::new(&config)?;
133
134        Ok(Self {
135            config,
136            users: Arc::new(RwLock::new(HashMap::new())),
137            sources: Arc::new(RwLock::new(HashMap::new())),
138            zones: Arc::new(RwLock::new(HashMap::new())),
139            sync_manager,
140            audio_processor,
141            metrics: Arc::new(RwLock::new(MultiUserMetrics::default())),
142            event_history: Arc::new(RwLock::new(VecDeque::new())),
143        })
144    }
145
146    /// Add a user to the environment
147    pub fn add_user(&self, user: MultiUserUser) -> Result<()> {
148        let user_id = user.id.clone();
149        let position = user.position;
150
151        // Check user limit
152        {
153            let users = self.users.read().map_err(|e| {
154                Error::LegacyProcessing(format!("Failed to acquire read lock on users: {}", e))
155            })?;
156            if users.len() >= self.config.max_users_per_room {
157                return Err(Error::LegacyProcessing(
158                    "Maximum users per room exceeded".to_string(),
159                ));
160            }
161        }
162
163        // Add user
164        {
165            let mut users = self.users.write().map_err(|e| {
166                Error::LegacyProcessing(format!("Failed to acquire write lock on users: {}", e))
167            })?;
168            users.insert(user_id.clone(), user);
169        }
170
171        // Record event
172        self.record_event(MultiUserEvent::UserJoined {
173            user_id,
174            timestamp: SystemTime::now(),
175            position,
176        });
177
178        Ok(())
179    }
180
181    /// Remove a user from the environment
182    pub fn remove_user(&self, user_id: &UserId, reason: DisconnectReason) -> Result<()> {
183        {
184            let mut users = self.users.write().map_err(|e| {
185                Error::LegacyProcessing(format!("Failed to acquire write lock on users: {}", e))
186            })?;
187            users.remove(user_id);
188        }
189
190        // Record event
191        self.record_event(MultiUserEvent::UserLeft {
192            user_id: user_id.clone(),
193            timestamp: SystemTime::now(),
194            reason,
195        });
196
197        Ok(())
198    }
199
200    /// Update user position
201    pub fn update_user_position(
202        &mut self,
203        user_id: &UserId,
204        position: Position3D,
205        orientation: [f32; 4],
206    ) -> Result<()> {
207        let old_position;
208        let old_timestamp;
209        let calculated_velocity;
210
211        {
212            let mut users = self.users.write().map_err(|e| {
213                Error::LegacyProcessing(format!("Failed to acquire write lock on users: {}", e))
214            })?;
215            if let Some(user) = users.get_mut(user_id) {
216                old_position = user.position;
217                old_timestamp = user.last_update;
218
219                // Calculate velocity based on position change over time
220                let current_time = Instant::now();
221                let time_delta = current_time.duration_since(old_timestamp).as_secs_f32();
222
223                if time_delta > 0.0 {
224                    let position_delta = Position3D::new(
225                        position.x - old_position.x,
226                        position.y - old_position.y,
227                        position.z - old_position.z,
228                    );
229                    calculated_velocity = Position3D::new(
230                        position_delta.x / time_delta,
231                        position_delta.y / time_delta,
232                        position_delta.z / time_delta,
233                    );
234                    user.velocity = calculated_velocity;
235                } else {
236                    // If no time has passed, maintain previous velocity
237                    calculated_velocity = user.velocity;
238                }
239
240                user.position = position;
241                user.orientation = orientation;
242                user.last_update = current_time;
243            } else {
244                return Err(Error::LegacyPosition(format!("User {user_id} not found")));
245            }
246        }
247
248        // Estimate latency based on position interpolator history
249        let estimated_latency = self
250            .sync_manager
251            .position_interpolator
252            .estimate_latency(user_id)
253            .unwrap_or(0.0);
254
255        // Update position interpolator
256        self.sync_manager.position_interpolator.add_position_sample(
257            user_id,
258            PositionSnapshot {
259                position,
260                orientation,
261                velocity: calculated_velocity,
262                timestamp: Instant::now(),
263                latency_ms: estimated_latency,
264            },
265        );
266
267        // Record event
268        self.record_event(MultiUserEvent::UserMoved {
269            user_id: user_id.clone(),
270            timestamp: SystemTime::now(),
271            old_position,
272            new_position: position,
273        });
274
275        Ok(())
276    }
277
278    /// Add a friend relationship between two users
279    pub fn add_friend(&self, user_id: &UserId, friend_id: &UserId) -> Result<()> {
280        if user_id == friend_id {
281            return Err(Error::LegacyPosition(
282                "Cannot add self as friend".to_string(),
283            ));
284        }
285
286        {
287            let mut users = self.users.write().map_err(|e| {
288                Error::LegacyProcessing(format!("Failed to acquire write lock on users: {}", e))
289            })?;
290
291            // Verify both users exist
292            if !users.contains_key(user_id) {
293                return Err(Error::LegacyPosition(format!("User {user_id} not found")));
294            }
295            if !users.contains_key(friend_id) {
296                return Err(Error::LegacyPosition(format!(
297                    "Friend {friend_id} not found"
298                )));
299            }
300
301            // Add bidirectional friendship
302            if let Some(user) = users.get_mut(user_id) {
303                user.friends.insert(friend_id.clone());
304            }
305            if let Some(friend) = users.get_mut(friend_id) {
306                friend.friends.insert(user_id.clone());
307            }
308        }
309
310        // Record event
311        self.record_event(MultiUserEvent::UserMoved {
312            user_id: user_id.clone(),
313            timestamp: SystemTime::now(),
314            old_position: Position3D::new(0.0, 0.0, 0.0), // Placeholder
315            new_position: Position3D::new(0.0, 0.0, 0.0), // Placeholder
316        });
317
318        Ok(())
319    }
320
321    /// Remove a friend relationship between two users
322    pub fn remove_friend(&self, user_id: &UserId, friend_id: &UserId) -> Result<()> {
323        {
324            let mut users = self.users.write().map_err(|e| {
325                Error::LegacyProcessing(format!("Failed to acquire write lock on users: {}", e))
326            })?;
327
328            // Remove bidirectional friendship
329            if let Some(user) = users.get_mut(user_id) {
330                user.friends.remove(friend_id);
331            }
332            if let Some(friend) = users.get_mut(friend_id) {
333                friend.friends.remove(user_id);
334            }
335        }
336
337        Ok(())
338    }
339
340    /// Check if two users are friends
341    pub fn are_friends(&self, user_id: &UserId, friend_id: &UserId) -> Result<bool> {
342        let users = self.users.read().map_err(|e| {
343            Error::LegacyProcessing(format!("Failed to acquire read lock on users: {}", e))
344        })?;
345
346        if let Some(user) = users.get(user_id) {
347            Ok(user.friends.contains(friend_id))
348        } else {
349            Err(Error::LegacyPosition(format!("User {user_id} not found")))
350        }
351    }
352
353    /// Get list of friends for a user
354    pub fn get_friends(&self, user_id: &UserId) -> Result<Vec<UserId>> {
355        let users = self.users.read().map_err(|e| {
356            Error::LegacyProcessing(format!("Failed to acquire read lock on users: {}", e))
357        })?;
358
359        if let Some(user) = users.get(user_id) {
360            Ok(user.friends.iter().cloned().collect())
361        } else {
362            Err(Error::LegacyPosition(format!("User {user_id} not found")))
363        }
364    }
365
366    /// Add an audio source
367    pub fn add_audio_source(&self, source: MultiUserAudioSource) -> Result<()> {
368        let source_id = source.id.clone();
369        let user_id = source.owner_id.clone();
370        let source_type = source.source_type;
371
372        {
373            let mut sources = self.sources.write().map_err(|e| {
374                Error::LegacyProcessing(format!("Failed to acquire write lock on sources: {}", e))
375            })?;
376            sources.insert(source_id.clone(), source);
377        }
378
379        // Record event
380        self.record_event(MultiUserEvent::SourceCreated {
381            source_id,
382            user_id,
383            timestamp: SystemTime::now(),
384            source_type,
385        });
386
387        Ok(())
388    }
389
390    /// Remove an audio source
391    pub fn remove_audio_source(&self, source_id: &SourceId, reason: &str) -> Result<()> {
392        {
393            let mut sources = self.sources.write().map_err(|e| {
394                Error::LegacyProcessing(format!("Failed to acquire write lock on sources: {}", e))
395            })?;
396            sources.remove(source_id);
397        }
398
399        // Record event
400        self.record_event(MultiUserEvent::SourceRemoved {
401            source_id: source_id.clone(),
402            timestamp: SystemTime::now(),
403            reason: reason.to_string(),
404        });
405
406        Ok(())
407    }
408
409    /// Process spatial audio for all users
410    pub fn process_audio(&mut self) -> Result<HashMap<UserId, Vec<f32>>> {
411        let users = self.users.read().map_err(|e| {
412            Error::LegacyProcessing(format!("Failed to acquire read lock on users: {}", e))
413        })?;
414        let mut output_buffers = HashMap::new();
415
416        for (user_id, user) in users.iter() {
417            // Create personalized audio mix for this user
418            let audio_buffer =
419                self.audio_processor
420                    .process_for_user(user, &users, &self.sources)?;
421            output_buffers.insert(user_id.clone(), audio_buffer);
422        }
423
424        Ok(output_buffers)
425    }
426
427    /// Get current performance metrics
428    pub fn metrics(&self) -> MultiUserMetrics {
429        self.metrics
430            .read()
431            .expect("Failed to acquire read lock on metrics for retrieval")
432            .clone()
433    }
434
435    /// Create a spatial zone
436    pub fn create_zone(&self, zone: SpatialZone) -> Result<()> {
437        let mut zones = self.zones.write().map_err(|e| {
438            Error::LegacyProcessing(format!("Failed to acquire write lock on zones: {}", e))
439        })?;
440        zones.insert(zone.id.clone(), zone);
441        Ok(())
442    }
443
444    /// Check if user has permission for an action
445    pub fn check_permission(&self, user_id: &UserId, permission: Permission) -> Result<bool> {
446        let users = self.users.read().map_err(|e| {
447            Error::LegacyProcessing(format!("Failed to acquire read lock on users: {}", e))
448        })?;
449        if let Some(user) = users.get(user_id) {
450            if let Some(permissions) = self
451                .config
452                .privacy_settings
453                .permission_system
454                .role_permissions
455                .get(&user.role)
456            {
457                Ok(permissions.contains(&permission))
458            } else {
459                Ok(false)
460            }
461        } else {
462            Err(Error::LegacyPosition(format!("User {user_id} not found")))
463        }
464    }
465
466    /// Record an event in the history
467    fn record_event(&self, event: MultiUserEvent) {
468        let mut history = self
469            .event_history
470            .write()
471            .expect("Failed to acquire write lock on event history");
472        history.push_back(event);
473
474        // Keep only recent events (last 1000)
475        if history.len() > 1000 {
476            history.pop_front();
477        }
478    }
479}
480
481impl SynchronizationManager {
482    /// Create a new synchronization manager
483    pub fn new() -> Self {
484        Self {
485            clock: Arc::new(RwLock::new(SynchronizedClock::new())),
486            position_interpolator: PositionInterpolator::new(),
487            latency_compensator: LatencyCompensator::new(),
488        }
489    }
490}
491
492impl Default for SynchronizationManager {
493    fn default() -> Self {
494        Self::new()
495    }
496}
497
498impl SynchronizedClock {
499    /// Create a new synchronized clock
500    pub fn new() -> Self {
501        Self {
502            local_time: Instant::now(),
503            time_offset_ms: 0,
504            sync_accuracy_ms: 0.0,
505            last_sync: Instant::now(),
506        }
507    }
508
509    /// Get the current synchronized time
510    pub fn current_time(&self) -> Instant {
511        self.local_time
512    }
513}
514
515impl Default for SynchronizedClock {
516    fn default() -> Self {
517        Self::new()
518    }
519}
520
521impl PositionInterpolator {
522    /// Create a new position interpolator
523    pub fn new() -> Self {
524        Self {
525            position_histories: HashMap::new(),
526            interpolation_method: InterpolationMethod::Linear,
527            prediction_horizon_ms: 50.0,
528        }
529    }
530
531    /// Add a position sample for a user
532    pub fn add_position_sample(&mut self, user_id: &UserId, snapshot: PositionSnapshot) {
533        let history = self.position_histories.entry(user_id.clone()).or_default();
534        history.push_back(snapshot);
535
536        // Keep only recent samples (last 10)
537        if history.len() > 10 {
538            history.pop_front();
539        }
540    }
541
542    /// Interpolate user position at a specific time
543    pub fn interpolate_position(
544        &self,
545        user_id: &UserId,
546        target_time: Instant,
547    ) -> Option<Position3D> {
548        let history = self.position_histories.get(user_id)?;
549        if history.len() < 1 {
550            return None;
551        }
552
553        if history.len() == 1 {
554            return history.back().map(|s| s.position);
555        }
556
557        match self.interpolation_method {
558            InterpolationMethod::Linear => self.linear_interpolation(history, target_time),
559            InterpolationMethod::CubicSpline => {
560                self.cubic_spline_interpolation(history, target_time)
561            }
562            InterpolationMethod::Kalman => self.kalman_interpolation(history, target_time),
563            InterpolationMethod::Physics => self.physics_interpolation(history, target_time),
564        }
565    }
566
567    /// Linear interpolation between two closest points
568    fn linear_interpolation(
569        &self,
570        history: &VecDeque<PositionSnapshot>,
571        target_time: Instant,
572    ) -> Option<Position3D> {
573        // Find the two samples that bracket the target time
574        let mut before_sample = None;
575        let mut after_sample = None;
576
577        for (i, sample) in history.iter().enumerate() {
578            if sample.timestamp <= target_time {
579                before_sample = Some(sample);
580            }
581            if sample.timestamp >= target_time && after_sample.is_none() {
582                after_sample = Some(sample);
583                break;
584            }
585        }
586
587        match (before_sample, after_sample) {
588            (Some(before), Some(after)) if before.timestamp != after.timestamp => {
589                let total_duration = after
590                    .timestamp
591                    .duration_since(before.timestamp)
592                    .as_secs_f32();
593                let elapsed_duration = target_time.duration_since(before.timestamp).as_secs_f32();
594                let t = elapsed_duration / total_duration;
595
596                Some(Position3D::new(
597                    before.position.x + t * (after.position.x - before.position.x),
598                    before.position.y + t * (after.position.y - before.position.y),
599                    before.position.z + t * (after.position.z - before.position.z),
600                ))
601            }
602            (Some(sample), _) => Some(sample.position),
603            (_, Some(sample)) => Some(sample.position),
604            _ => history.back().map(|s| s.position),
605        }
606    }
607
608    /// Cubic spline interpolation for smoother movement
609    fn cubic_spline_interpolation(
610        &self,
611        history: &VecDeque<PositionSnapshot>,
612        target_time: Instant,
613    ) -> Option<Position3D> {
614        if history.len() < 4 {
615            return self.linear_interpolation(history, target_time);
616        }
617
618        // For simplicity, use a cubic Hermite spline with velocity information
619        let samples: Vec<_> = history.iter().collect();
620        let n = samples.len();
621
622        // Find the segment containing target_time
623        for i in 1..n {
624            if samples[i].timestamp >= target_time {
625                let p0 = if i >= 2 { samples[i - 2] } else { samples[0] };
626                let p1 = samples[i - 1];
627                let p2 = samples[i];
628                let p3 = if i + 1 < n {
629                    samples[i + 1]
630                } else {
631                    samples[n - 1]
632                };
633
634                let t1 = p1
635                    .timestamp
636                    .duration_since(p0.timestamp)
637                    .as_secs_f32()
638                    .max(0.001);
639                let t2 = p2
640                    .timestamp
641                    .duration_since(p1.timestamp)
642                    .as_secs_f32()
643                    .max(0.001);
644                let t3 = p3
645                    .timestamp
646                    .duration_since(p2.timestamp)
647                    .as_secs_f32()
648                    .max(0.001);
649
650                let target_offset = target_time.duration_since(p1.timestamp).as_secs_f32();
651                let t = target_offset / t2;
652
653                // Calculate tangents (velocities)
654                let m1 = Position3D::new(
655                    (p2.position.x - p0.position.x) / (t1 + t2),
656                    (p2.position.y - p0.position.y) / (t1 + t2),
657                    (p2.position.z - p0.position.z) / (t1 + t2),
658                );
659                let m2 = Position3D::new(
660                    (p3.position.x - p1.position.x) / (t2 + t3),
661                    (p3.position.y - p1.position.y) / (t2 + t3),
662                    (p3.position.z - p1.position.z) / (t2 + t3),
663                );
664
665                // Hermite basis functions
666                let t2 = t * t;
667                let t3 = t2 * t;
668                let h00 = 2.0 * t3 - 3.0 * t2 + 1.0;
669                let h10 = t3 - 2.0 * t2 + t;
670                let h01 = -2.0 * t3 + 3.0 * t2;
671                let h11 = t3 - t2;
672
673                return Some(Position3D::new(
674                    h00 * p1.position.x + h10 * m1.x * t2 + h01 * p2.position.x + h11 * m2.x * t2,
675                    h00 * p1.position.y + h10 * m1.y * t2 + h01 * p2.position.y + h11 * m2.y * t2,
676                    h00 * p1.position.z + h10 * m1.z * t2 + h01 * p2.position.z + h11 * m2.z * t2,
677                ));
678            }
679        }
680
681        // Fallback to linear interpolation
682        self.linear_interpolation(history, target_time)
683    }
684
685    /// Kalman filter-based prediction with velocity estimation
686    fn kalman_interpolation(
687        &self,
688        history: &VecDeque<PositionSnapshot>,
689        target_time: Instant,
690    ) -> Option<Position3D> {
691        if history.len() < 2 {
692            return history.back().map(|s| s.position);
693        }
694
695        let latest = history.back()?;
696        let time_delta = target_time.duration_since(latest.timestamp).as_secs_f32();
697
698        // Simple Kalman-like prediction using stored velocity
699        Some(Position3D::new(
700            latest.position.x + latest.velocity.x * time_delta,
701            latest.position.y + latest.velocity.y * time_delta,
702            latest.position.z + latest.velocity.z * time_delta,
703        ))
704    }
705
706    /// Physics-based prediction considering acceleration
707    fn physics_interpolation(
708        &self,
709        history: &VecDeque<PositionSnapshot>,
710        target_time: Instant,
711    ) -> Option<Position3D> {
712        if history.len() < 3 {
713            return self.kalman_interpolation(history, target_time);
714        }
715
716        let samples: Vec<_> = history.iter().rev().take(3).collect();
717        let latest = samples[0];
718        let prev1 = samples[1];
719        let prev2 = samples[2];
720
721        let dt1 = latest
722            .timestamp
723            .duration_since(prev1.timestamp)
724            .as_secs_f32()
725            .max(0.001);
726        let dt2 = prev1
727            .timestamp
728            .duration_since(prev2.timestamp)
729            .as_secs_f32()
730            .max(0.001);
731
732        // Calculate acceleration from velocity changes
733        let accel = Position3D::new(
734            (latest.velocity.x - prev1.velocity.x) / dt1,
735            (latest.velocity.y - prev1.velocity.y) / dt1,
736            (latest.velocity.z - prev1.velocity.z) / dt1,
737        );
738
739        let time_delta = target_time.duration_since(latest.timestamp).as_secs_f32();
740
741        // Physics equation: s = s0 + v0*t + 0.5*a*t^2
742        Some(Position3D::new(
743            latest.position.x
744                + latest.velocity.x * time_delta
745                + 0.5 * accel.x * time_delta * time_delta,
746            latest.position.y
747                + latest.velocity.y * time_delta
748                + 0.5 * accel.y * time_delta * time_delta,
749            latest.position.z
750                + latest.velocity.z * time_delta
751                + 0.5 * accel.z * time_delta * time_delta,
752        ))
753    }
754
755    /// Estimate network latency based on position update patterns
756    pub fn estimate_latency(&self, user_id: &UserId) -> Option<f64> {
757        let history = self.position_histories.get(user_id)?;
758
759        if history.len() < 2 {
760            return Some(0.0);
761        }
762
763        // Calculate average time between position updates
764        let mut total_intervals = 0.0;
765        let mut interval_count = 0;
766
767        for i in 1..history.len() {
768            let current_sample = &history[i];
769            let previous_sample = &history[i - 1];
770
771            let interval = current_sample
772                .timestamp
773                .duration_since(previous_sample.timestamp)
774                .as_secs_f64()
775                * 1000.0;
776            total_intervals += interval;
777            interval_count += 1;
778        }
779
780        if interval_count > 0 {
781            let avg_interval = total_intervals / interval_count as f64;
782            // Estimate latency as half the average update interval
783            // This assumes network latency is roughly proportional to update frequency
784            Some((avg_interval * 0.5).min(100.0)) // Cap at 100ms
785        } else {
786            Some(0.0)
787        }
788    }
789}
790
791impl Default for PositionInterpolator {
792    fn default() -> Self {
793        Self::new()
794    }
795}
796
797impl LatencyCompensator {
798    /// Create a new latency compensator
799    pub fn new() -> Self {
800        Self {
801            user_latencies: HashMap::new(),
802            compensation_method: CompensationMethod::Adaptive,
803            max_compensation_ms: 100.0,
804        }
805    }
806
807    /// Update the measured latency for a user
808    pub fn update_user_latency(&mut self, user_id: &UserId, latency_ms: f64) {
809        self.user_latencies.insert(user_id.clone(), latency_ms);
810    }
811
812    /// Get the compensation delay for a user
813    pub fn get_compensation_delay(&self, user_id: &UserId) -> f64 {
814        if let Some(&latency) = self.user_latencies.get(user_id) {
815            (latency * 0.5).min(self.max_compensation_ms)
816        } else {
817            0.0
818        }
819    }
820}
821
822impl Default for LatencyCompensator {
823    fn default() -> Self {
824        Self::new()
825    }
826}
827
828impl MultiUserAudioProcessor {
829    /// Create a new multi-user audio processor
830    pub fn new(config: &MultiUserConfig) -> Result<Self> {
831        let mixer_config = MixerConfig {
832            max_sources: config.max_sources_per_user * config.max_users_per_room,
833            buffer_size: 1024,
834            sample_rate: 48000,
835            spatial_quality: config.audio_quality,
836            optimization_level: OptimizationLevel::Balanced,
837        };
838
839        Ok(Self {
840            mixer: SpatialAudioMixer::new(mixer_config),
841            vad: VoiceActivityDetector::new(),
842            effects: AudioEffectsProcessor::new(),
843            codec: AudioCodec::new(AudioFormat::Opus),
844        })
845    }
846
847    /// Process spatial audio for a specific user
848    pub fn process_for_user(
849        &mut self,
850        listener: &MultiUserUser,
851        all_users: &HashMap<UserId, MultiUserUser>,
852        sources: &Arc<RwLock<HashMap<SourceId, MultiUserAudioSource>>>,
853    ) -> Result<Vec<f32>> {
854        // Set listener position for spatial processing
855        self.mixer
856            .set_listener_position(&listener.id, listener.position);
857
858        // Process all audible sources for this listener
859        let sources_guard = sources.read().map_err(|e| {
860            Error::LegacyProcessing(format!("Failed to acquire read lock on sources: {}", e))
861        })?;
862        let mut mixed_audio = vec![0.0f32; 1024]; // Buffer size
863
864        for (source_id, source) in sources_guard.iter() {
865            // Check if this source is audible to the listener
866            if self.is_source_audible(listener, source)? {
867                // Calculate spatial audio for this source
868                let spatial_audio = self.mixer.process_source(source, listener.position)?;
869
870                // Mix into output buffer
871                for (i, sample) in spatial_audio.iter().enumerate() {
872                    if i < mixed_audio.len() {
873                        mixed_audio[i] += sample;
874                    }
875                }
876            }
877        }
878
879        // Apply listener-specific effects
880        self.effects
881            .process_user_effects(&listener.id, &mut mixed_audio)?;
882
883        Ok(mixed_audio)
884    }
885
886    /// Check if an audio source is audible to a listener
887    fn is_source_audible(
888        &self,
889        listener: &MultiUserUser,
890        source: &MultiUserAudioSource,
891    ) -> Result<bool> {
892        // Check distance
893        let distance = listener.position.distance_to(&source.position);
894        if distance > source.spatial_properties.max_distance {
895            return Ok(false);
896        }
897
898        // Check access control
899        match source.access_control.visibility {
900            SourceVisibility::Public => Ok(true),
901            SourceVisibility::Private => Ok(source.owner_id == listener.id),
902            SourceVisibility::Whitelist => {
903                Ok(source.access_control.allowed_users.contains(&listener.id))
904            }
905            SourceVisibility::Friends => {
906                // Check if listener is friends with the source owner
907                Ok(listener.friends.contains(&source.owner_id) || source.owner_id == listener.id)
908            }
909            SourceVisibility::Moderators => Ok(matches!(
910                listener.role,
911                UserRole::Moderator | UserRole::Administrator
912            )),
913        }
914    }
915}
916
917impl SpatialAudioMixer {
918    /// Create a new spatial audio mixer
919    pub fn new(config: MixerConfig) -> Self {
920        Self {
921            listener_positions: HashMap::new(),
922            source_manager: Arc::new(RwLock::new(HashMap::new())),
923            mixer_config: config,
924        }
925    }
926
927    /// Set the position of a listener for spatial audio processing
928    pub fn set_listener_position(&mut self, user_id: &UserId, position: Position3D) {
929        self.listener_positions.insert(user_id.clone(), position);
930    }
931
932    /// Process an audio source for spatial audio rendering
933    pub fn process_source(
934        &self,
935        source: &MultiUserAudioSource,
936        listener_position: Position3D,
937    ) -> Result<Vec<f32>> {
938        // Calculate spatial parameters
939        let distance = listener_position.distance_to(&source.position);
940        let attenuation = self.calculate_distance_attenuation(distance, &source.spatial_properties);
941
942        // Generate dummy spatial audio (in real implementation, this would be proper HRTF processing)
943        let buffer_size = self.mixer_config.buffer_size;
944        let mut output = vec![0.0f32; buffer_size];
945
946        // Simple distance-based attenuation
947        let volume = source.volume * attenuation;
948        for sample in output.iter_mut() {
949            *sample = volume * 0.1; // Dummy audio signal
950        }
951
952        Ok(output)
953    }
954
955    /// Calculate volume attenuation based on distance
956    fn calculate_distance_attenuation(&self, distance: f32, properties: &SpatialProperties) -> f32 {
957        if distance <= properties.reference_distance {
958            return 1.0;
959        }
960
961        let ratio = properties.reference_distance / distance;
962        ratio.powf(properties.rolloff_factor).min(1.0)
963    }
964}
965
966impl VoiceActivityDetector {
967    /// Create a new voice activity detector
968    pub fn new() -> Self {
969        Self {
970            algorithm: VadAlgorithm::Energy,
971            user_states: HashMap::new(),
972            thresholds: VadThresholds {
973                energy_threshold: 0.01,
974                min_speaking_duration_ms: 100,
975                min_silence_duration_ms: 200,
976                confidence_threshold: 0.7,
977            },
978        }
979    }
980
981    /// Process audio buffer to detect voice activity
982    pub fn process_user_audio(&mut self, user_id: &UserId, audio_buffer: &[f32]) -> bool {
983        // Calculate energy level
984        let energy = audio_buffer.iter().map(|&x| x * x).sum::<f32>() / audio_buffer.len() as f32;
985
986        // Get or create user state
987        let state = self
988            .user_states
989            .entry(user_id.clone())
990            .or_insert_with(|| VadState {
991                is_speaking: false,
992                confidence: 0.0,
993                energy_history: VecDeque::new(),
994                speaking_duration: Duration::new(0, 0),
995                silence_duration: Duration::new(0, 0),
996            });
997
998        // Update energy history
999        state.energy_history.push_back(energy);
1000        if state.energy_history.len() > 10 {
1001            state.energy_history.pop_front();
1002        }
1003
1004        // Simple energy-based detection
1005        state.is_speaking = energy > self.thresholds.energy_threshold;
1006        state.confidence = if state.is_speaking { 0.9 } else { 0.1 };
1007
1008        state.is_speaking
1009    }
1010}
1011
1012impl Default for VoiceActivityDetector {
1013    fn default() -> Self {
1014        Self::new()
1015    }
1016}
1017
1018impl AudioEffectsProcessor {
1019    /// Create a new audio effects processor
1020    pub fn new() -> Self {
1021        Self {
1022            effects: HashMap::new(),
1023            user_effects: HashMap::new(),
1024            zone_effects: HashMap::new(),
1025        }
1026    }
1027
1028    /// Apply user-specific audio effects to an audio buffer
1029    pub fn process_user_effects(
1030        &mut self,
1031        user_id: &UserId,
1032        audio_buffer: &mut [f32],
1033    ) -> Result<()> {
1034        // Apply user-specific effects
1035        if let Some(effect_chain) = self.user_effects.get(user_id) {
1036            let mut temp_buffer = audio_buffer.to_vec();
1037            for effect_name in effect_chain {
1038                if let Some(effect) = self.effects.get_mut(effect_name) {
1039                    effect.process(&temp_buffer, audio_buffer)?;
1040                    temp_buffer.copy_from_slice(audio_buffer);
1041                }
1042            }
1043        }
1044        Ok(())
1045    }
1046}
1047
1048impl Default for AudioEffectsProcessor {
1049    fn default() -> Self {
1050        Self::new()
1051    }
1052}
1053
1054impl AudioCodec {
1055    /// Create a new audio codec with the specified format
1056    pub fn new(format: AudioFormat) -> Self {
1057        Self {
1058            format,
1059            compression: CompressionSettings {
1060                bitrate_kbps: 64,
1061                complexity: 5,
1062                variable_bitrate: true,
1063                low_latency: true,
1064            },
1065            codec_states: HashMap::new(),
1066        }
1067    }
1068}
1069
1070/// Builder for multi-user configuration
1071pub struct MultiUserConfigBuilder {
1072    config: MultiUserConfig,
1073}
1074
1075impl MultiUserConfigBuilder {
1076    /// Create a new multi-user configuration builder
1077    pub fn new() -> Self {
1078        Self {
1079            config: MultiUserConfig::default(),
1080        }
1081    }
1082
1083    /// Set maximum number of users per room
1084    pub fn max_users(mut self, max_users: usize) -> Self {
1085        self.config.max_users_per_room = max_users;
1086        self
1087    }
1088
1089    /// Set audio quality level (0.0-1.0)
1090    pub fn audio_quality(mut self, quality: f32) -> Self {
1091        self.config.audio_quality = quality.clamp(0.0, 1.0);
1092        self
1093    }
1094
1095    /// Set maximum latency in milliseconds
1096    pub fn max_latency_ms(mut self, latency: f64) -> Self {
1097        self.config.max_latency_ms = latency;
1098        self
1099    }
1100
1101    /// Enable or disable encryption
1102    pub fn enable_encryption(mut self, enabled: bool) -> Self {
1103        self.config.privacy_settings.encryption_enabled = enabled;
1104        self
1105    }
1106
1107    /// Set bandwidth limit in kbps
1108    pub fn bandwidth_limit_kbps(mut self, limit: u32) -> Self {
1109        self.config.bandwidth_settings.max_bandwidth_kbps = limit;
1110        self
1111    }
1112
1113    /// Build the configuration
1114    pub fn build(self) -> MultiUserConfig {
1115        self.config
1116    }
1117}
1118
1119impl Default for MultiUserConfigBuilder {
1120    fn default() -> Self {
1121        Self::new()
1122    }
1123}