webrtc_audio_processing_sys/
lib.rs

1#![allow(non_upper_case_globals)]
2#![allow(non_camel_case_types)]
3#![allow(non_snake_case)]
4
5include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
6
7impl Into<Option<bool>> for OptionalBool {
8    fn into(self) -> Option<bool> {
9        if self.has_value {
10            Some(self.value)
11        } else {
12            None
13        }
14    }
15}
16
17impl From<Option<bool>> for OptionalBool {
18    fn from(other: Option<bool>) -> OptionalBool {
19        if let Some(value) = other {
20            OptionalBool { has_value: true, value }
21        } else {
22            OptionalBool { has_value: false, value: false }
23        }
24    }
25}
26
27impl Into<Option<i32>> for OptionalInt {
28    fn into(self) -> Option<i32> {
29        if self.has_value {
30            Some(self.value)
31        } else {
32            None
33        }
34    }
35}
36
37impl From<Option<i32>> for OptionalInt {
38    fn from(other: Option<i32>) -> OptionalInt {
39        if let Some(value) = other {
40            OptionalInt { has_value: true, value }
41        } else {
42            OptionalInt { has_value: false, value: 0 }
43        }
44    }
45}
46
47impl Into<Option<f64>> for OptionalDouble {
48    fn into(self) -> Option<f64> {
49        if self.has_value {
50            Some(self.value)
51        } else {
52            None
53        }
54    }
55}
56
57impl From<Option<f64>> for OptionalDouble {
58    fn from(other: Option<f64>) -> OptionalDouble {
59        if let Some(value) = other {
60            OptionalDouble { has_value: true, value }
61        } else {
62            OptionalDouble { has_value: false, value: 0.0 }
63        }
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use super::*;
70
71    fn init_config_with_all_enabled() -> InitializationConfig {
72        InitializationConfig {
73            num_capture_channels: 1,
74            num_render_channels: 1,
75            enable_experimental_agc: true,
76            enable_intelligibility_enhancer: true,
77        }
78    }
79
80    fn config_with_all_enabled() -> Config {
81        Config {
82            echo_cancellation: EchoCancellation {
83                enable: true,
84                suppression_level: EchoCancellation_SuppressionLevel::HIGH,
85            },
86            gain_control: GainControl {
87                enable: true,
88                target_level_dbfs: 3,
89                compression_gain_db: 3,
90                enable_limiter: true,
91            },
92            noise_suppression: NoiseSuppression {
93                enable: true,
94                suppression_level: NoiseSuppression_SuppressionLevel::HIGH,
95            },
96            voice_detection: VoiceDetection {
97                enable: true,
98                detection_likelihood: VoiceDetection_DetectionLikelihood::HIGH,
99            },
100            enable_extended_filter: true,
101            enable_delay_agnostic: true,
102            enable_transient_suppressor: true,
103            enable_high_pass_filter: true,
104        }
105    }
106
107    #[test]
108    fn test_create_failure() {
109        unsafe {
110            let config = InitializationConfig::default();
111            let mut error = 0;
112            let ap = audio_processing_create(&config, &mut error);
113            assert!(ap.is_null());
114            assert!(!is_success(error));
115        }
116    }
117
118    #[test]
119    fn test_create_delete() {
120        unsafe {
121            let config = InitializationConfig {
122                num_capture_channels: 1,
123                num_render_channels: 1,
124                ..InitializationConfig::default()
125            };
126            let mut error = 0;
127            let ap = audio_processing_create(&config, &mut error);
128            assert!(!ap.is_null());
129            assert!(is_success(error));
130            audio_processing_delete(ap);
131        }
132    }
133
134    #[test]
135    fn test_config() {
136        unsafe {
137            let mut error = 0;
138            let ap = audio_processing_create(&init_config_with_all_enabled(), &mut error);
139            assert!(!ap.is_null());
140            assert!(is_success(error));
141
142            let config = Config::default();
143            set_config(ap, &config);
144
145            let config = config_with_all_enabled();
146            set_config(ap, &config);
147
148            audio_processing_delete(ap);
149        }
150    }
151
152    #[test]
153    fn test_process() {
154        unsafe {
155            let mut error = 0;
156            let ap = audio_processing_create(&init_config_with_all_enabled(), &mut error);
157            assert!(!ap.is_null());
158            assert!(is_success(error));
159
160            let config = config_with_all_enabled();
161            set_config(ap, &config);
162
163            let mut frame = vec![vec![0f32; NUM_SAMPLES_PER_FRAME as usize]; 1];
164            let mut frame_ptr = frame.iter_mut().map(|v| v.as_mut_ptr()).collect::<Vec<*mut f32>>();
165            assert!(is_success(process_render_frame(ap, frame_ptr.as_mut_ptr())));
166            assert!(is_success(process_capture_frame(ap, frame_ptr.as_mut_ptr())));
167
168            audio_processing_delete(ap);
169        }
170    }
171
172    #[test]
173    fn test_empty_stats() {
174        unsafe {
175            let config = InitializationConfig {
176                num_capture_channels: 1,
177                num_render_channels: 1,
178                ..InitializationConfig::default()
179            };
180            let mut error = 0;
181            let ap = audio_processing_create(&config, &mut error);
182            assert!(!ap.is_null());
183            assert!(is_success(error));
184
185            let stats = get_stats(ap);
186            println!("Stats:\n{:#?}", stats);
187            assert!(!stats.has_voice.has_value);
188            assert!(!stats.has_echo.has_value);
189            assert!(!stats.rms_dbfs.has_value);
190            assert!(!stats.speech_probability.has_value);
191            assert!(!stats.residual_echo_return_loss.has_value);
192            assert!(!stats.echo_return_loss.has_value);
193            assert!(!stats.echo_return_loss_enhancement.has_value);
194            assert!(!stats.a_nlp.has_value);
195            assert!(!stats.delay_median_ms.has_value);
196            assert!(!stats.delay_standard_deviation_ms.has_value);
197            assert!(!stats.delay_fraction_poor_delays.has_value);
198
199            audio_processing_delete(ap);
200        }
201    }
202
203    #[test]
204    fn test_some_stats() {
205        unsafe {
206            let mut error = 0;
207            let ap = audio_processing_create(&init_config_with_all_enabled(), &mut error);
208            assert!(!ap.is_null());
209            assert!(is_success(error));
210
211            let config = config_with_all_enabled();
212            set_config(ap, &config);
213
214            let mut frame = vec![vec![0f32; NUM_SAMPLES_PER_FRAME as usize]; 1];
215            let mut frame_ptr = frame.iter_mut().map(|v| v.as_mut_ptr()).collect::<Vec<*mut f32>>();
216            assert!(is_success(process_render_frame(ap, frame_ptr.as_mut_ptr())));
217            assert!(is_success(process_capture_frame(ap, frame_ptr.as_mut_ptr())));
218            let stats = get_stats(ap);
219            println!("Stats:\n{:#?}", stats);
220            assert!(stats.has_voice.has_value);
221            assert!(stats.has_echo.has_value);
222            assert!(stats.rms_dbfs.has_value);
223            assert!(stats.speech_probability.has_value);
224            assert!(stats.residual_echo_return_loss.has_value);
225            assert!(stats.echo_return_loss.has_value);
226            assert!(stats.echo_return_loss_enhancement.has_value);
227            assert!(stats.a_nlp.has_value);
228            assert!(stats.delay_median_ms.has_value);
229            assert!(stats.delay_standard_deviation_ms.has_value);
230            assert!(stats.delay_fraction_poor_delays.has_value);
231
232            audio_processing_delete(ap);
233        }
234    }
235}