1use std::os::raw::c_void;
2#[derive(Debug, Clone)]
5pub struct AecConfig {
6 pub frame_size: usize,
7 pub filter_length: i32,
8 pub sample_rate: u32,
9 pub enable_preprocess: bool,
10}
11
12impl Default for AecConfig {
13 fn default() -> Self {
15 Self {
16 frame_size: 160,
17 filter_length: 1600,
18 sample_rate: 16000,
19 enable_preprocess: true,
20 }
21 }
22}
23
24pub struct Aec {
25 echo_state: *mut aec_rs_sys::SpeexEchoState,
26 preprocess_state: Option<*mut aec_rs_sys::SpeexPreprocessState>,
27}
28
29impl Aec {
30 pub fn new(config: &AecConfig) -> Self {
31 let echo_state = unsafe {
32 aec_rs_sys::speex_echo_state_init(config.frame_size as i32, config.filter_length)
33 };
34 let preprocess_state = if config.enable_preprocess {
35 unsafe {
36 let den = aec_rs_sys::speex_preprocess_state_init(
37 config.frame_size as i32,
38 config.sample_rate as _,
39 );
40 aec_rs_sys::speex_preprocess_ctl(
41 den,
42 aec_rs_sys::SPEEX_PREPROCESS_SET_ECHO_STATE as _,
43 echo_state as *mut c_void,
44 );
45 Some(den)
46 }
47 } else {
48 None
49 };
50
51 Aec {
52 echo_state,
53 preprocess_state,
54 }
55 }
56
57 pub fn cancel_echo(&self, rec_buffer: &[i16], echo_buffer: &[i16], out_buffer: &mut [i16]) {
58 unsafe {
59 aec_rs_sys::speex_echo_cancellation(
60 self.echo_state,
61 rec_buffer.as_ptr(),
62 echo_buffer.as_ptr(),
63 out_buffer.as_mut_ptr(),
64 );
65 if let Some(preprocess_state) = self.preprocess_state {
66 aec_rs_sys::speex_preprocess_run(preprocess_state, out_buffer.as_mut_ptr());
67 }
68 }
69 }
70}
71
72impl Drop for Aec {
73 fn drop(&mut self) {
74 unsafe {
75 aec_rs_sys::speex_echo_state_destroy(self.echo_state);
76 if let Some(preprocess_state) = self.preprocess_state {
77 aec_rs_sys::speex_preprocess_state_destroy(preprocess_state);
78 }
79 }
80 }
81}