use crate::types::{Position3D, SpatialResult};
use crate::{Error, Result};
use serde::{Deserialize, Serialize};
use std::collections::{HashMap, HashSet, VecDeque};
use std::sync::{Arc, RwLock};
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
pub type UserId = String;
pub type SourceId = String;
pub type RoomId = String;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MultiUserConfig {
pub max_users_per_room: usize,
pub max_sources_per_user: usize,
pub sync_interval_ms: u64,
pub max_latency_ms: f64,
pub voice_activity_threshold: f32,
pub audio_quality: f32,
pub position_interpolation: bool,
pub max_audio_distance: f32,
pub attenuation_curve: MultiUserAttenuationCurve,
pub privacy_settings: PrivacySettings,
pub bandwidth_settings: BandwidthSettings,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum MultiUserAttenuationCurve {
Linear,
InverseDistance,
InverseSquare,
Logarithmic,
Custom {
rolloff: f32,
reference_distance: f32,
},
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PrivacySettings {
pub encryption_enabled: bool,
pub recording_allowed: bool,
pub mute_controls_enabled: bool,
pub spatial_zones_enabled: bool,
pub permission_system: PermissionSystem,
pub anonymization: AnonymizationSettings,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PermissionSystem {
pub rbac_enabled: bool,
pub default_role: UserRole,
pub role_permissions: HashMap<UserRole, Vec<Permission>>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum UserRole {
Participant,
Moderator,
Administrator,
Observer,
Presenter,
Guest,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Permission {
Speak,
Move,
MuteOthers,
KickUsers,
ModifyRoom,
CreateSources,
Record,
AccessPrivateZones,
Broadcast,
Moderate,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AnonymizationSettings {
pub anonymous_ids: bool,
pub position_obfuscation: bool,
pub temporal_obfuscation: bool,
pub voice_modulation: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BandwidthSettings {
pub adaptive_bitrate: bool,
pub max_bandwidth_kbps: u32,
pub compression_level: u8,
pub proximity_quality_scaling: bool,
pub low_bandwidth_mode: LowBandwidthMode,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LowBandwidthMode {
pub enabled: bool,
pub sample_rate: u32,
pub bit_depth: u16,
pub max_streams: usize,
pub disable_spatial_effects: bool,
}
#[derive(Debug, Clone)]
pub struct MultiUserUser {
pub id: UserId,
pub display_name: String,
pub position: Position3D,
pub orientation: [f32; 4],
pub velocity: Position3D,
pub role: UserRole,
pub is_speaking: bool,
pub audio_sources: HashMap<SourceId, MultiUserAudioSource>,
pub connection_status: ConnectionStatus,
pub last_update: Instant,
pub audio_settings: UserAudioSettings,
pub network_stats: NetworkStats,
pub accessible_zones: Vec<SpatialZone>,
pub friends: HashSet<UserId>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ConnectionStatus {
Connected,
Unstable,
Reconnecting,
Disconnected,
TimedOut,
}
#[derive(Debug, Clone)]
pub struct MultiUserAudioSource {
pub id: SourceId,
pub owner_id: UserId,
pub position: Position3D,
pub source_type: AudioSourceType,
pub volume: f32,
pub is_active: bool,
pub spatial_properties: SpatialProperties,
pub access_control: SourceAccessControl,
pub quality_settings: SourceQualitySettings,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AudioSourceType {
Voice,
Media,
Ambient,
ScreenShare,
Notification,
Interactive,
}
#[derive(Debug, Clone)]
pub struct SpatialProperties {
pub directivity: DirectionalPattern,
pub reference_distance: f32,
pub rolloff_factor: f32,
pub max_distance: f32,
pub doppler_factor: f32,
pub room_interaction: bool,
}
#[derive(Debug, Clone, Copy)]
pub enum DirectionalPattern {
Omnidirectional,
Cardioid,
Bidirectional,
Cone {
inner_angle: f32,
outer_angle: f32,
outer_gain: f32,
},
}
#[derive(Debug, Clone)]
pub struct SourceAccessControl {
pub visibility: SourceVisibility,
pub allowed_users: Vec<UserId>,
pub blocked_users: Vec<UserId>,
pub spatial_zones: Vec<SpatialZone>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SourceVisibility {
Public,
Friends,
Whitelist,
Private,
Moderators,
}
#[derive(Debug, Clone)]
pub struct SourceQualitySettings {
pub bitrate_kbps: u32,
pub spatial_quality: f32,
pub noise_reduction: f32,
pub echo_cancellation: f32,
pub compression_ratio: f32,
}
#[derive(Debug, Clone)]
pub struct UserAudioSettings {
pub master_volume: f32,
pub voice_volume: f32,
pub media_volume: f32,
pub spatial_intensity: f32,
pub hrtf_profile: Option<String>,
pub microphone_settings: MicrophoneSettings,
pub accessibility: AccessibilitySettings,
}
#[derive(Debug, Clone)]
pub struct MicrophoneSettings {
pub gain: f32,
pub noise_gate_threshold: f32,
pub auto_gain_control: bool,
pub push_to_talk: bool,
pub vad_sensitivity: f32,
}
#[derive(Debug, Clone)]
pub struct AccessibilitySettings {
pub visual_indicators: bool,
pub high_frequency_boost: f32,
pub background_noise_reduction: f32,
pub speech_to_text: bool,
pub haptic_feedback: bool,
}
#[derive(Debug, Clone, Default)]
pub struct NetworkStats {
pub rtt_ms: f64,
pub packet_loss_percent: f32,
pub jitter_ms: f64,
pub bandwidth_usage_kbps: u32,
pub reconnect_count: u32,
pub audio_dropouts: u32,
}
#[derive(Debug, Clone, PartialEq)]
pub struct SpatialZone {
pub id: String,
pub name: String,
pub zone_type: ZoneType,
pub bounds: ZoneBounds,
pub required_permissions: Vec<Permission>,
pub audio_properties: ZoneAudioProperties,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ZoneType {
Meeting,
Private,
Presentation,
Quiet,
Broadcast,
Social,
}
#[derive(Debug, Clone, PartialEq)]
pub enum ZoneBounds {
Sphere {
center: Position3D,
radius: f32,
},
Box {
min: Position3D,
max: Position3D,
},
Cylinder {
center: Position3D,
radius: f32,
height: f32,
},
Polygon {
vertices: Vec<Position3D>,
},
}
#[derive(Debug, Clone, PartialEq)]
pub struct ZoneAudioProperties {
pub volume_multiplier: f32,
pub acoustic_settings: AcousticSettings,
pub audio_isolation: bool,
pub max_speakers: Option<usize>,
pub priority: u8,
}
#[derive(Debug, Clone, PartialEq)]
pub struct AcousticSettings {
pub reverb: f32,
pub echo_delay_ms: f32,
pub echo_feedback: f32,
pub room_size: f32,
pub damping: f32,
}
pub struct MultiUserEnvironment {
pub(crate) config: MultiUserConfig,
pub(crate) users: Arc<RwLock<HashMap<UserId, MultiUserUser>>>,
pub(crate) sources: Arc<RwLock<HashMap<SourceId, MultiUserAudioSource>>>,
pub(crate) zones: Arc<RwLock<HashMap<String, SpatialZone>>>,
pub(crate) sync_manager: SynchronizationManager,
pub(crate) audio_processor: MultiUserAudioProcessor,
pub(crate) metrics: Arc<RwLock<MultiUserMetrics>>,
pub(crate) event_history: Arc<RwLock<VecDeque<MultiUserEvent>>>,
}
pub struct SynchronizationManager {
pub(crate) clock: Arc<RwLock<SynchronizedClock>>,
pub(crate) position_interpolator: PositionInterpolator,
pub(crate) latency_compensator: LatencyCompensator,
}
#[derive(Debug)]
pub struct SynchronizedClock {
pub(crate) local_time: Instant,
pub(crate) time_offset_ms: i64,
pub(crate) sync_accuracy_ms: f64,
pub(crate) last_sync: Instant,
}
pub struct PositionInterpolator {
pub(crate) position_histories: HashMap<UserId, VecDeque<PositionSnapshot>>,
pub(crate) interpolation_method: InterpolationMethod,
pub(crate) prediction_horizon_ms: f64,
}
#[derive(Debug, Clone)]
pub struct PositionSnapshot {
pub position: Position3D,
pub orientation: [f32; 4],
pub velocity: Position3D,
pub timestamp: Instant,
pub latency_ms: f64,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum InterpolationMethod {
Linear,
CubicSpline,
Kalman,
Physics,
}
pub struct LatencyCompensator {
pub(crate) user_latencies: HashMap<UserId, f64>,
pub(crate) compensation_method: CompensationMethod,
pub(crate) max_compensation_ms: f64,
}
#[derive(Debug, Clone, Copy)]
pub enum CompensationMethod {
TimeShift,
Predictive,
Adaptive,
None,
}
pub struct MultiUserAudioProcessor {
pub(crate) mixer: SpatialAudioMixer,
pub(crate) vad: VoiceActivityDetector,
pub(crate) effects: AudioEffectsProcessor,
pub(crate) codec: AudioCodec,
}
pub struct SpatialAudioMixer {
pub(crate) listener_positions: HashMap<UserId, Position3D>,
pub(crate) source_manager: Arc<RwLock<HashMap<SourceId, MixerAudioSource>>>,
pub(crate) mixer_config: MixerConfig,
}
#[derive(Debug, Clone)]
pub struct MixerAudioSource {
pub id: SourceId,
pub buffer: Vec<f32>,
pub position: Position3D,
pub properties: SpatialProperties,
pub processing_state: SourceProcessingState,
}
#[derive(Debug, Clone)]
pub struct SourceProcessingState {
pub playback_position: usize,
pub envelope_state: f32,
pub spatial_params: SpatialProcessingParams,
pub last_update: Instant,
}
#[derive(Debug, Clone)]
pub struct SpatialProcessingParams {
pub distance_attenuation: f32,
pub doppler_shift: f32,
pub listener_relative_position: Position3D,
pub occlusion: f32,
}
#[derive(Debug, Clone)]
pub struct MixerConfig {
pub max_sources: usize,
pub buffer_size: usize,
pub sample_rate: u32,
pub spatial_quality: f32,
pub optimization_level: OptimizationLevel,
}
#[derive(Debug, Clone, Copy)]
pub enum OptimizationLevel {
Quality,
Balanced,
Performance,
MinimalCpu,
}
pub struct VoiceActivityDetector {
pub(crate) algorithm: VadAlgorithm,
pub(crate) user_states: HashMap<UserId, VadState>,
pub(crate) thresholds: VadThresholds,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum VadAlgorithm {
Energy,
Spectral,
MachineLearning,
Hybrid,
}
#[derive(Debug, Clone)]
pub struct VadState {
pub is_speaking: bool,
pub confidence: f32,
pub energy_history: VecDeque<f32>,
pub speaking_duration: Duration,
pub silence_duration: Duration,
}
#[derive(Debug, Clone)]
pub struct VadThresholds {
pub energy_threshold: f32,
pub min_speaking_duration_ms: u64,
pub min_silence_duration_ms: u64,
pub confidence_threshold: f32,
}
pub struct AudioEffectsProcessor {
pub(crate) effects: HashMap<String, Box<dyn AudioEffect>>,
pub(crate) user_effects: HashMap<UserId, Vec<String>>,
pub(crate) zone_effects: HashMap<String, Vec<String>>,
}
pub trait AudioEffect {
fn process(&mut self, input: &[f32], output: &mut [f32]) -> Result<()>;
fn parameters(&self) -> HashMap<String, f32>;
fn set_parameters(&mut self, params: HashMap<String, f32>) -> Result<()>;
fn reset(&mut self);
}
pub struct AudioCodec {
pub(crate) format: AudioFormat,
pub(crate) compression: CompressionSettings,
pub(crate) codec_states: HashMap<UserId, CodecState>,
}
#[derive(Debug, Clone, Copy)]
pub enum AudioFormat {
Opus,
Aac,
Mp3,
Pcm,
}
#[derive(Debug, Clone)]
pub struct CompressionSettings {
pub bitrate_kbps: u32,
pub complexity: u8,
pub variable_bitrate: bool,
pub low_latency: bool,
}
#[derive(Debug)]
pub struct CodecState {
pub encoder_state: Vec<u8>,
pub decoder_state: Vec<u8>,
pub frame_buffer: VecDeque<Vec<u8>>,
pub timing: CodecTiming,
}
#[derive(Debug, Clone)]
pub struct CodecTiming {
pub encode_latency_ms: f64,
pub decode_latency_ms: f64,
pub buffer_latency_ms: f64,
pub total_latency_ms: f64,
}
#[derive(Debug, Clone, Default)]
pub struct MultiUserMetrics {
pub active_users: usize,
pub active_sources: usize,
pub avg_latency_ms: f64,
pub audio_cpu_usage: f32,
pub memory_usage_mb: f32,
pub bandwidth_usage_kbps: u32,
pub audio_quality: AudioQualityMetrics,
pub sync_accuracy_ms: f64,
pub reconnections_per_hour: u32,
}
#[derive(Debug, Clone, Default)]
pub struct AudioQualityMetrics {
pub snr_db: f32,
pub thd_percent: f32,
pub dropouts_per_minute: f32,
pub perceived_quality: f32,
}
#[derive(Debug, Clone)]
pub enum MultiUserEvent {
UserJoined {
user_id: UserId,
timestamp: SystemTime,
position: Position3D,
},
UserLeft {
user_id: UserId,
timestamp: SystemTime,
reason: DisconnectReason,
},
UserMoved {
user_id: UserId,
timestamp: SystemTime,
old_position: Position3D,
new_position: Position3D,
},
UserStartedSpeaking {
user_id: UserId,
timestamp: SystemTime,
confidence: f32,
},
UserStoppedSpeaking {
user_id: UserId,
timestamp: SystemTime,
duration: Duration,
},
SourceCreated {
source_id: SourceId,
user_id: UserId,
timestamp: SystemTime,
source_type: AudioSourceType,
},
SourceRemoved {
source_id: SourceId,
timestamp: SystemTime,
reason: String,
},
NetworkEvent {
user_id: UserId,
timestamp: SystemTime,
event_type: NetworkEventType,
value: f64,
},
}
#[derive(Debug, Clone, Copy)]
pub enum DisconnectReason {
UserLeft,
NetworkTimeout,
Kicked,
Error,
ServerShutdown,
}
#[derive(Debug, Clone, Copy)]
pub enum NetworkEventType {
Latency,
PacketLoss,
Jitter,
Bandwidth,
ConnectionEstablished,
ConnectionLost,
}