Remove unused AudioFrame10ms/20ms structs, disable_failed_vad_backend(), and ServerState dead accessors (replace_from_snapshot, channel_count, client_count). Update tests to use .channels().count()/.clients().count().
44 lines
1.3 KiB
Rust
44 lines
1.3 KiB
Rust
//! Canonical P1 voice frame helpers.
|
|
//!
|
|
//! The network contract remains 48 kHz mono, 20 ms Opus frames. P1
|
|
//! processing works internally on 10 ms f32 frames so VAD and future
|
|
//! processors can share a stable frame size without changing the
|
|
//! transport layer.
|
|
|
|
/// P1 sample rate in Hz.
|
|
pub const SAMPLE_RATE_HZ: u32 = 48_000;
|
|
/// Network frame duration in milliseconds.
|
|
pub const NETWORK_FRAME_MS: u32 = 20;
|
|
/// Processing frame duration in milliseconds.
|
|
pub const PROCESSING_FRAME_MS: u32 = 10;
|
|
/// Samples in one 10 ms mono frame at 48 kHz.
|
|
pub const FRAME_10MS_SAMPLES: usize = 480;
|
|
/// Samples in one 20 ms mono frame at 48 kHz.
|
|
pub const FRAME_20MS_SAMPLES: usize = 960;
|
|
|
|
/// Convert i16 PCM to normalized f32 PCM.
|
|
pub fn i16_to_f32(sample: i16) -> f32 {
|
|
sample as f32 / i16::MAX as f32
|
|
}
|
|
|
|
/// Convert normalized f32 PCM to saturated i16 PCM.
|
|
pub fn f32_to_i16(sample: f32) -> i16 {
|
|
(sample.clamp(-1.0, 1.0) * i16::MAX as f32) as i16
|
|
}
|
|
|
|
/// RMS dBFS for a normalized f32 slice. Silence returns `-120.0`.
|
|
pub fn dbfs(samples: &[f32]) -> f32 {
|
|
if samples.is_empty() {
|
|
return -120.0;
|
|
}
|
|
let sum = samples.iter().map(|s| s * s).sum::<f32>();
|
|
let rms = (sum / samples.len() as f32).sqrt();
|
|
if rms <= 0.000_001 {
|
|
-120.0
|
|
} else {
|
|
20.0 * rms.log10()
|
|
}
|
|
}
|
|
|
|
|