1#[derive(Debug, Clone, PartialEq)]
7pub struct VadConfig {
8 pub threshold: f32,
10 pub neg_threshold: Option<f32>,
13 pub min_speech_ms: u32,
15 pub min_silence_ms: u32,
17 pub speech_pad_ms: u32,
19 pub max_speech_ms: u32,
21 pub sample_rate: u32,
23}
24
25impl Default for VadConfig {
26 fn default() -> Self {
28 VadConfig {
29 threshold: 0.5,
30 neg_threshold: None,
31 min_speech_ms: 250,
32 min_silence_ms: 100,
33 speech_pad_ms: 30,
34 max_speech_ms: 0,
35 sample_rate: 16000,
36 }
37 }
38}
39
40impl VadConfig {
41 pub fn aggressive() -> Self {
45 VadConfig {
46 threshold: 0.35,
47 neg_threshold: None,
48 min_speech_ms: 200,
49 min_silence_ms: 150,
50 speech_pad_ms: 50,
51 max_speech_ms: 0,
52 sample_rate: 16000,
53 }
54 }
55
56 pub fn balanced() -> Self {
58 VadConfig::default()
59 }
60
61 pub fn conservative() -> Self {
65 VadConfig {
66 threshold: 0.6,
67 neg_threshold: None,
68 min_speech_ms: 300,
69 min_silence_ms: 300,
70 speech_pad_ms: 30,
71 max_speech_ms: 0,
72 sample_rate: 16000,
73 }
74 }
75
76 pub fn resolved_neg_threshold(&self) -> f32 {
80 match self.neg_threshold {
81 Some(v) => v,
82 None => (self.threshold - 0.15).max(0.01),
83 }
84 }
85
86 pub(crate) fn frame_size(&self) -> usize {
88 if self.sample_rate == 8000 {
89 256
90 } else {
91 512
92 }
93 }
94
95 pub(crate) fn context_size(&self) -> usize {
97 if self.sample_rate == 8000 {
98 32
99 } else {
100 64
101 }
102 }
103
104 pub(crate) fn ms_to_samples(&self, ms: u32) -> u64 {
106 (u64::from(ms) * u64::from(self.sample_rate)) / 1000
107 }
108
109 pub(crate) fn validate(&self) -> Result<(), String> {
111 if self.sample_rate != 8000 && self.sample_rate != 16000 {
112 return Err(format!(
113 "sample_rate must be 8000 or 16000, got {}",
114 self.sample_rate
115 ));
116 }
117 if !(0.0..=1.0).contains(&self.threshold) {
118 return Err(format!(
119 "threshold must be within [0.0, 1.0], got {}",
120 self.threshold
121 ));
122 }
123 if let Some(nt) = self.neg_threshold {
124 if !(0.0..=1.0).contains(&nt) {
125 return Err(format!("neg_threshold must be within [0.0, 1.0], got {nt}"));
126 }
127 }
128 Ok(())
129 }
130}