1use 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 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 pub fn add_user(&self, user: MultiUserUser) -> Result<()> {
148 let user_id = user.id.clone();
149 let position = user.position;
150
151 {
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 {
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 self.record_event(MultiUserEvent::UserJoined {
173 user_id,
174 timestamp: SystemTime::now(),
175 position,
176 });
177
178 Ok(())
179 }
180
181 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 self.record_event(MultiUserEvent::UserLeft {
192 user_id: user_id.clone(),
193 timestamp: SystemTime::now(),
194 reason,
195 });
196
197 Ok(())
198 }
199
200 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 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 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 let estimated_latency = self
250 .sync_manager
251 .position_interpolator
252 .estimate_latency(user_id)
253 .unwrap_or(0.0);
254
255 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 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 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 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 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 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), new_position: Position3D::new(0.0, 0.0, 0.0), });
317
318 Ok(())
319 }
320
321 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 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 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 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 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 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 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 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 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 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 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 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 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 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 if history.len() > 1000 {
476 history.pop_front();
477 }
478 }
479}
480
481impl SynchronizationManager {
482 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 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 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 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 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 if history.len() > 10 {
538 history.pop_front();
539 }
540 }
541
542 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 fn linear_interpolation(
569 &self,
570 history: &VecDeque<PositionSnapshot>,
571 target_time: Instant,
572 ) -> Option<Position3D> {
573 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 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 let samples: Vec<_> = history.iter().collect();
620 let n = samples.len();
621
622 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 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 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 self.linear_interpolation(history, target_time)
683 }
684
685 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 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 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 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 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 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 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 Some((avg_interval * 0.5).min(100.0)) } 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 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 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 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 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 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 self.mixer
856 .set_listener_position(&listener.id, listener.position);
857
858 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]; for (source_id, source) in sources_guard.iter() {
865 if self.is_source_audible(listener, source)? {
867 let spatial_audio = self.mixer.process_source(source, listener.position)?;
869
870 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 self.effects
881 .process_user_effects(&listener.id, &mut mixed_audio)?;
882
883 Ok(mixed_audio)
884 }
885
886 fn is_source_audible(
888 &self,
889 listener: &MultiUserUser,
890 source: &MultiUserAudioSource,
891 ) -> Result<bool> {
892 let distance = listener.position.distance_to(&source.position);
894 if distance > source.spatial_properties.max_distance {
895 return Ok(false);
896 }
897
898 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 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 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 pub fn set_listener_position(&mut self, user_id: &UserId, position: Position3D) {
929 self.listener_positions.insert(user_id.clone(), position);
930 }
931
932 pub fn process_source(
934 &self,
935 source: &MultiUserAudioSource,
936 listener_position: Position3D,
937 ) -> Result<Vec<f32>> {
938 let distance = listener_position.distance_to(&source.position);
940 let attenuation = self.calculate_distance_attenuation(distance, &source.spatial_properties);
941
942 let buffer_size = self.mixer_config.buffer_size;
944 let mut output = vec![0.0f32; buffer_size];
945
946 let volume = source.volume * attenuation;
948 for sample in output.iter_mut() {
949 *sample = volume * 0.1; }
951
952 Ok(output)
953 }
954
955 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 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 pub fn process_user_audio(&mut self, user_id: &UserId, audio_buffer: &[f32]) -> bool {
983 let energy = audio_buffer.iter().map(|&x| x * x).sum::<f32>() / audio_buffer.len() as f32;
985
986 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 state.energy_history.push_back(energy);
1000 if state.energy_history.len() > 10 {
1001 state.energy_history.pop_front();
1002 }
1003
1004 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 pub fn new() -> Self {
1021 Self {
1022 effects: HashMap::new(),
1023 user_effects: HashMap::new(),
1024 zone_effects: HashMap::new(),
1025 }
1026 }
1027
1028 pub fn process_user_effects(
1030 &mut self,
1031 user_id: &UserId,
1032 audio_buffer: &mut [f32],
1033 ) -> Result<()> {
1034 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 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
1070pub struct MultiUserConfigBuilder {
1072 config: MultiUserConfig,
1073}
1074
1075impl MultiUserConfigBuilder {
1076 pub fn new() -> Self {
1078 Self {
1079 config: MultiUserConfig::default(),
1080 }
1081 }
1082
1083 pub fn max_users(mut self, max_users: usize) -> Self {
1085 self.config.max_users_per_room = max_users;
1086 self
1087 }
1088
1089 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 pub fn max_latency_ms(mut self, latency: f64) -> Self {
1097 self.config.max_latency_ms = latency;
1098 self
1099 }
1100
1101 pub fn enable_encryption(mut self, enabled: bool) -> Self {
1103 self.config.privacy_settings.encryption_enabled = enabled;
1104 self
1105 }
1106
1107 pub fn bandwidth_limit_kbps(mut self, limit: u32) -> Self {
1109 self.config.bandwidth_settings.max_bandwidth_kbps = limit;
1110 self
1111 }
1112
1113 pub fn build(self) -> MultiUserConfig {
1115 self.config
1116 }
1117}
1118
1119impl Default for MultiUserConfigBuilder {
1120 fn default() -> Self {
1121 Self::new()
1122 }
1123}