1#![allow(non_camel_case_types)]
2
3#[cfg(feature = "sys")]
4mod sys {
5 use crate::echo::SpeexEcho;
6 use speexdsp_sys::preprocess::*;
7 use std::convert::From;
8 use std::ffi::c_void;
9 use std::fmt;
10
11 #[derive(Clone, Copy, Debug)]
12 pub enum SpeexPreprocessConst {
13 SPEEX_PREPROCESS_SET_DENOISE = 0,
14 SPEEX_PREPROCESS_GET_DENOISE = 1,
15 SPEEX_PREPROCESS_SET_AGC = 2,
16 SPEEX_PREPROCESS_GET_AGC = 3,
17 SPEEX_PREPROCESS_SET_VAD = 4,
18 SPEEX_PREPROCESS_GET_VAD = 5,
19 SPEEX_PREPROCESS_SET_AGC_LEVEL = 6,
20 SPEEX_PREPROCESS_GET_AGC_LEVEL = 7,
21 SPEEX_PREPROCESS_SET_DEREVERB = 8,
22 SPEEX_PREPROCESS_GET_DEREVERB = 9,
23 SPEEX_PREPROCESS_SET_DEREVERB_LEVEL = 10,
24 SPEEX_PREPROCESS_GET_DEREVERB_LEVEL = 11,
25 SPEEX_PREPROCESS_SET_DEREVERB_DECAY = 12,
26 SPEEX_PREPROCESS_GET_DEREVERB_DECAY = 13,
27 SPEEX_PREPROCESS_SET_PROB_START = 14,
28 SPEEX_PREPROCESS_GET_PROB_START = 15,
29 SPEEX_PREPROCESS_SET_PROB_CONTINUE = 16,
30 SPEEX_PREPROCESS_GET_PROB_CONTINUE = 17,
31 SPEEX_PREPROCESS_SET_NOISE_SUPPRESS = 18,
32 SPEEX_PREPROCESS_GET_NOISE_SUPPRESS = 19,
33 SPEEX_PREPROCESS_SET_ECHO_SUPPRESS = 20,
34 SPEEX_PREPROCESS_GET_ECHO_SUPPRESS = 21,
35 SPEEX_PREPROCESS_SET_ECHO_SUPPRESS_ACTIVE = 22,
36 SPEEX_PREPROCESS_GET_ECHO_SUPPRESS_ACTIVE = 23,
37 SPEEX_PREPROCESS_SET_ECHO_STATE = 24,
38 SPEEX_PREPROCESS_GET_ECHO_STATE = 25,
39 SPEEX_PREPROCESS_SET_AGC_INCREMENT = 26,
40 SPEEX_PREPROCESS_GET_AGC_INCREMENT = 27,
41 SPEEX_PREPROCESS_SET_AGC_DECREMENT = 28,
42 SPEEX_PREPROCESS_GET_AGC_DECREMENT = 29,
43 SPEEX_PREPROCESS_SET_AGC_MAX_GAIN = 30,
44 SPEEX_PREPROCESS_GET_AGC_MAX_GAIN = 31,
45 SPEEX_PREPROCESS_GET_AGC_LOUDNESS = 33,
46 SPEEX_PREPROCESS_GET_AGC_GAIN = 35,
47 SPEEX_PREPROCESS_GET_PSD_SIZE = 37,
48 SPEEX_PREPROCESS_GET_PSD = 39,
49 SPEEX_PREPROCESS_GET_NOISE_PSD_SIZE = 41,
50 SPEEX_PREPROCESS_GET_NOISE_PSD = 43,
51 SPEEX_PREPROCESS_GET_PROB = 45,
52 SPEEX_PREPROCESS_SET_AGC_TARGET = 46,
53 SPEEX_PREPROCESS_GET_AGC_TARGET = 47,
54 }
55
56 #[derive(Clone, Copy, Debug)]
57 pub enum Error {
58 FailedInit,
59 UnknownRequest,
60 }
61
62 impl fmt::Display for Error {
63 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
64 let v = match self {
65 Error::FailedInit => "Failed to initialize",
66 Error::UnknownRequest => "The request is unknown",
67 };
68
69 write!(f, "{}", v)
70 }
71 }
72
73 pub enum Variant {
74 U32(u32),
75 F32(f32),
76 Echo(SpeexEcho),
77 }
78
79 impl From<u32> for Variant {
80 fn from(item: u32) -> Self {
81 Variant::U32(item)
82 }
83 }
84
85 impl From<f32> for Variant {
86 fn from(item: f32) -> Self {
87 Variant::F32(item)
88 }
89 }
90
91 impl From<&SpeexEcho> for Variant {
92 fn from(item: &SpeexEcho) -> Self {
93 Variant::Echo(item.clone())
94 }
95 }
96
97 pub struct SpeexPreprocess {
98 st: *mut SpeexPreprocessState,
99 }
100
101 impl SpeexPreprocess {
102 pub fn new(
103 frame_size: usize,
104 sampling_rate: usize,
105 ) -> Result<Self, Error> {
106 let st = unsafe {
107 speex_preprocess_state_init(
108 frame_size as i32,
109 sampling_rate as i32,
110 )
111 };
112
113 if st.is_null() {
114 Err(Error::FailedInit)
115 } else {
116 Ok(SpeexPreprocess { st })
117 }
118 }
119
120 pub fn preprocess_run(&mut self, x: &mut [i16]) -> usize {
121 unsafe { speex_preprocess_run(self.st, x.as_mut_ptr()) as usize }
122 }
123
124 pub fn preprocess(&mut self, x: &mut [i16], echo: usize) -> usize {
125 unsafe {
126 speex_preprocess(self.st, x.as_mut_ptr(), echo as *mut i32)
127 as usize
128 }
129 }
130
131 pub fn preprocess_estimate_update(&mut self, x: &mut [i16]) {
132 unsafe {
133 speex_preprocess_estimate_update(self.st, x.as_mut_ptr())
134 };
135 }
136
137 pub fn preprocess_ctl<T: Into<Variant>>(
138 &mut self,
139 request: SpeexPreprocessConst,
140 value: T,
141 ) -> Result<(), Error> {
142 let ptr_v = match (request, value.into()) {
143 (
144 SpeexPreprocessConst::SPEEX_PREPROCESS_SET_DEREVERB_DECAY,
145 Variant::F32(val),
146 )
147 | (
148 SpeexPreprocessConst::SPEEX_PREPROCESS_SET_DEREVERB_LEVEL,
149 Variant::F32(val),
150 ) => &val as *const f32 as *mut c_void,
151 (
152 SpeexPreprocessConst::SPEEX_PREPROCESS_SET_ECHO_STATE,
153 Variant::Echo(val),
154 ) => val.get_ptr() as *mut c_void,
155 (_, Variant::U32(val)) => &val as *const u32 as *mut c_void,
156 _ => panic!("This type is not accepted"),
157 };
158 let ret = unsafe {
159 speex_preprocess_ctl(self.st, request as i32, ptr_v) as usize
160 };
161 if ret != 0 {
162 Err(Error::UnknownRequest)
163 } else {
164 Ok(())
165 }
166 }
167 }
168
169 impl Drop for SpeexPreprocess {
170 fn drop(&mut self) {
171 unsafe { speex_preprocess_state_destroy(self.st) };
172 }
173 }
174}
175
176#[cfg(feature = "sys")]
177pub use self::sys::{Error, SpeexPreprocess, SpeexPreprocessConst};