speex_safe/mode/
encoder.rs

1////////////////////////////////////////////////////////////////////////////////
2// Copyright (c) 2023.                                                         /
3// This Source Code Form is subject to the terms of the Mozilla Public License,/
4// v. 2.0. If a copy of the MPL was not distributed with this file, You can    /
5// obtain one at http://mozilla.org/MPL/2.0/.                                  /
6////////////////////////////////////////////////////////////////////////////////
7
8use std::ffi::c_void;
9use std::marker::{PhantomData, PhantomPinned};
10
11use speex_sys::SpeexMode;
12
13use crate::mode::{CoderMode, ControlError, ControlFunctions, ModeId, NbMode, UwbMode, WbMode};
14use crate::{dynamic_mapping, mode, shared_functions, NbSubmodeId, SpeexBits, WbSubmodeId};
15
16/// Handle for the encoder, speex represents this as an opaque pointer so this
17/// is an unconstructable type that is always intended to be behind a pointer.
18#[repr(C)]
19pub struct SpeexEncoderHandle {
20    _data: [u8; 0],
21    _marker: PhantomData<(*mut u8, PhantomPinned)>,
22}
23
24impl SpeexEncoderHandle {
25    /// Create a new encoder handle for the given mode.
26    ///
27    /// # Safety
28    /// This allocates, so you *must* call SpeexEncoderHandle::destroy whith the
29    /// handle when are done with the handle.
30    ///
31    /// It is not recommended to use these methods directly, instead use the
32    /// `SpeexEncoder` struct.
33    pub unsafe fn create(mode: &SpeexMode) -> *mut Self {
34        let ptr = unsafe {
35            let mode_ptr = mode as *const SpeexMode;
36            speex_sys::speex_encoder_init(mode_ptr)
37        };
38        ptr as *mut SpeexEncoderHandle
39    }
40
41    /// Destroy the encoder handle. This MUST be called when you are done with
42    /// the encoder handle.
43    ///
44    /// # Safety
45    /// This function must *only* be called on a handle that was created with
46    /// `SpeexEncoderHandle::create`. It shouldn't be called on an already
47    /// destroyed handle.
48    pub unsafe fn destroy(handle: *mut SpeexEncoderHandle) {
49        unsafe { speex_sys::speex_encoder_destroy(handle as *mut c_void) }
50    }
51}
52
53/// A struct representing a speex encoder.
54pub struct SpeexEncoder<T: CoderMode> {
55    encoder_handle: *mut SpeexEncoderHandle,
56    pub mode: &'static SpeexMode,
57    _phantom: PhantomData<T>,
58}
59
60impl<T: CoderMode> mode::private::Sealed for SpeexEncoder<T> {}
61
62impl<T: CoderMode> ControlFunctions for SpeexEncoder<T> {
63    unsafe fn ctl(&mut self, request: i32, ptr: *mut c_void) -> Result<(), ControlError> {
64        let result = speex_sys::speex_encoder_ctl(self.encoder_handle as *mut c_void, request, ptr);
65        Self::check_error(result, Some(request))
66    }
67}
68
69impl<T: CoderMode> SpeexEncoder<T> {
70    fn get_low_submode_internal(&mut self) -> NbSubmodeId {
71        let mut low_mode = 0;
72        let ptr = &mut low_mode as *mut i32 as *mut c_void;
73        unsafe {
74            self.ctl(speex_sys::SPEEX_GET_LOW_MODE, ptr).unwrap();
75        }
76        low_mode.into()
77    }
78
79    fn set_low_submode_internal(&mut self, low_mode: NbSubmodeId) {
80        let low_mode = low_mode as i32;
81        let ptr = &low_mode as *const i32 as *mut c_void;
82        unsafe {
83            self.ctl(speex_sys::SPEEX_SET_LOW_MODE, ptr).unwrap();
84        }
85    }
86
87    fn set_high_submode_internal(&mut self, high_mode: WbSubmodeId) {
88        let high_mode = high_mode as i32;
89        let ptr = &high_mode as *const i32 as *mut c_void;
90        unsafe {
91            self.ctl(speex_sys::SPEEX_SET_HIGH_MODE, ptr).unwrap();
92        }
93    }
94
95    fn get_high_submode_internal(&mut self) -> WbSubmodeId {
96        let mut high_mode = 0;
97        let ptr = &mut high_mode as *mut i32 as *mut c_void;
98        unsafe {
99            self.ctl(speex_sys::SPEEX_GET_HIGH_MODE, ptr).unwrap();
100        }
101        high_mode.into()
102    }
103
104    /// Sets the analysis complexity of the encoder.
105    pub fn set_complexity(&mut self, complexity: i32) {
106        let ptr = &complexity as *const i32 as *mut c_void;
107        unsafe {
108            self.ctl(speex_sys::SPEEX_SET_COMPLEXITY, ptr).unwrap();
109        }
110    }
111
112    /// Gets the analysis complexity of the encoder.
113    pub fn get_complexity(&mut self) -> i32 {
114        let mut state = 0;
115        let ptr = &mut state as *mut i32 as *mut c_void;
116        unsafe {
117            self.ctl(speex_sys::SPEEX_GET_COMPLEXITY, ptr).unwrap();
118        }
119        state
120    }
121
122    /// Encode one frame of audio into the given bits.
123    pub fn encode(&mut self, input: &mut [f32], bits: &mut SpeexBits) {
124        let input_ptr = input.as_mut_ptr();
125        unsafe {
126            speex_sys::speex_encode(
127                self.encoder_handle as *mut c_void,
128                input_ptr,
129                bits.backing_mut_ptr(),
130            );
131        }
132    }
133
134    /// Encode one frame of audio into the given bits, using an integer
135    /// representation.
136    pub fn encode_int(&mut self, input: &mut [i16], bits: &mut SpeexBits) {
137        let bits_ptr = bits.backing_mut_ptr();
138        let input_ptr = input.as_mut_ptr();
139        unsafe {
140            speex_sys::speex_encode_int(self.encoder_handle as *mut c_void, input_ptr, bits_ptr);
141        }
142    }
143}
144
145impl SpeexEncoder<NbMode> {
146    /// Create a new narrowband encoder.
147    pub fn new() -> SpeexEncoder<NbMode> {
148        let mode = ModeId::NarrowBand.get_mode();
149        let encoder_handle = unsafe { SpeexEncoderHandle::create(mode) };
150        Self {
151            encoder_handle,
152            mode,
153            _phantom: PhantomData,
154        }
155    }
156
157    /// Sets the submode to use for encoding.
158    pub fn set_submode(&mut self, submode: NbSubmodeId) {
159        self.set_low_submode_internal(submode);
160    }
161
162    /// Gets the submode currently in use for encoding.
163    pub fn get_submode(&mut self) -> NbSubmodeId {
164        self.get_low_submode_internal()
165    }
166}
167
168impl Default for SpeexEncoder<NbMode> {
169    fn default() -> Self {
170        Self::new()
171    }
172}
173
174impl SpeexEncoder<WbMode> {
175    /// Create a new wideband encoder.
176    pub fn new() -> SpeexEncoder<WbMode> {
177        let mode = ModeId::WideBand.get_mode();
178        let encoder_handle = unsafe { SpeexEncoderHandle::create(mode) };
179        Self {
180            encoder_handle,
181            mode,
182            _phantom: PhantomData,
183        }
184    }
185
186    /// Sets the submode of the narrowband part of the encoder.
187    pub fn set_low_submode(&mut self, low_mode: NbSubmodeId) {
188        self.set_low_submode_internal(low_mode);
189    }
190
191    /// Gets the submode of the narrowband part of the encoder.
192    pub fn get_low_submode(&mut self) -> NbSubmodeId {
193        self.get_low_submode_internal()
194    }
195
196    /// Sets the submode of the wideband part of the encoder.
197    pub fn set_high_submode(&mut self, high_mode: WbSubmodeId) {
198        self.set_high_submode_internal(high_mode);
199    }
200
201    /// Gets the submode of the wideband part of the encoder.
202    pub fn get_high_submode(&mut self) -> WbSubmodeId {
203        self.get_high_submode_internal()
204    }
205}
206
207impl Default for SpeexEncoder<WbMode> {
208    fn default() -> Self {
209        Self::new()
210    }
211}
212
213impl SpeexEncoder<UwbMode> {
214    /// Create a new ultra-wideband encoder.
215    pub fn new() -> SpeexEncoder<UwbMode> {
216        let mode = ModeId::UltraWideBand.get_mode();
217        let encoder_handle = unsafe { SpeexEncoderHandle::create(mode) };
218        Self {
219            encoder_handle,
220            mode,
221            _phantom: PhantomData,
222        }
223    }
224
225    /// Sets the submode of the narrowband part of the encoder.
226    pub fn set_low_submode(&mut self, low_mode: NbSubmodeId) {
227        self.set_low_submode_internal(low_mode);
228    }
229
230    /// Gets the submode of the narrowband part of the encoder.
231    pub fn get_low_submode(&mut self) -> NbSubmodeId {
232        self.get_low_submode_internal()
233    }
234}
235
236impl Default for SpeexEncoder<UwbMode> {
237    fn default() -> Self {
238        Self::new()
239    }
240}
241
242impl<T: CoderMode> Drop for SpeexEncoder<T> {
243    fn drop(&mut self) {
244        unsafe {
245            SpeexEncoderHandle::destroy(self.encoder_handle);
246        }
247    }
248}
249
250/// An enumeration over the different encoder modes.
251/// For usecases where the encoder mode is not known at compile time.
252pub enum DynamicEncoder {
253    Nb(SpeexEncoder<NbMode>),
254    Wb(SpeexEncoder<WbMode>),
255    Uwb(SpeexEncoder<UwbMode>),
256}
257
258impl DynamicEncoder {
259    shared_functions!(DynamicEncoder);
260
261    /// Sets the analysis complexity of the encoder.
262    pub fn set_complexity(&mut self, complexity: i32) {
263        dynamic_mapping!(self, DynamicEncoder, inner => inner.set_complexity(complexity))
264    }
265
266    /// Gets the analysis complexity of the encoder.
267    pub fn get_complexity(&mut self) -> i32 {
268        dynamic_mapping!(self, DynamicEncoder, inner => inner.get_complexity())
269    }
270
271    /// Encode one frame of audio into the given bits.
272    pub fn encode(&mut self, input: &mut [f32], bits: &mut SpeexBits) {
273        match self {
274            DynamicEncoder::Nb(inner) => inner.encode(input, bits),
275            DynamicEncoder::Wb(inner) => inner.encode(input, bits),
276            DynamicEncoder::Uwb(inner) => inner.encode(input, bits),
277        }
278    }
279
280    /// Encode one frame of audio into the given bits, using an integer
281    /// representation.
282    pub fn encode_int(&mut self, input: &mut [i16], bits: &mut SpeexBits) {
283        match self {
284            DynamicEncoder::Nb(inner) => inner.encode_int(input, bits),
285            DynamicEncoder::Wb(inner) => inner.encode_int(input, bits),
286            DynamicEncoder::Uwb(inner) => inner.encode_int(input, bits),
287        }
288    }
289
290    pub fn new(mode: ModeId) -> DynamicEncoder {
291        match mode {
292            ModeId::NarrowBand => DynamicEncoder::Nb(SpeexEncoder::<NbMode>::new()),
293            ModeId::WideBand => DynamicEncoder::Wb(SpeexEncoder::<WbMode>::new()),
294            ModeId::UltraWideBand => DynamicEncoder::Uwb(SpeexEncoder::<UwbMode>::new()),
295        }
296    }
297
298    pub fn into_nb(self) -> Option<SpeexEncoder<NbMode>> {
299        match self {
300            DynamicEncoder::Nb(nb) => Some(nb),
301            _ => None,
302        }
303    }
304
305    pub fn into_wb(self) -> Option<SpeexEncoder<WbMode>> {
306        match self {
307            DynamicEncoder::Wb(wb) => Some(wb),
308            _ => None,
309        }
310    }
311
312    pub fn into_uwb(self) -> Option<SpeexEncoder<UwbMode>> {
313        match self {
314            DynamicEncoder::Uwb(uwb) => Some(uwb),
315            _ => None,
316        }
317    }
318}
319
320
321#[cfg(test)]
322mod test {
323    use super::*;
324
325    macro_rules! set_get_test {
326        ($name:ident, $set:ident, $get:ident, $value:expr) => {
327            #[test]
328            fn $name() {
329                let mut encoder = SpeexEncoder::<WbMode>::new();
330                encoder.$set($value);
331                let result = encoder.$get();
332
333                assert_eq!(result, $value);
334            }
335        };
336    }
337
338    set_get_test!(
339        set_get_high_submode,
340        set_high_submode,
341        get_high_submode,
342        WbSubmodeId::NoQuantize
343    );
344
345    set_get_test!(set_get_vbr, set_vbr, get_vbr, true);
346
347    set_get_test!(set_get_vbr_quality, set_vbr_quality, get_vbr_quality, 8.0);
348
349    set_get_test!(set_get_vad, set_vad, get_vad, true);
350
351    set_get_test!(set_get_abr, set_abr, get_abr, 2000);
352
353    #[test]
354    fn set_quality() {
355        let mut encoder = SpeexEncoder::<WbMode>::new();
356        encoder.set_quality(10);
357    }
358
359    set_get_test!(set_get_bitrate, set_bitrate, get_bitrate, 3950);
360
361    set_get_test!(
362        set_get_sampling_rate,
363        set_sampling_rate,
364        get_sampling_rate,
365        3950
366    );
367
368    #[test]
369    fn get_frame_size() {
370        let mut encoder = SpeexEncoder::<WbMode>::new();
371        encoder.get_frame_size();
372    }
373
374    #[test]
375    fn encodes_frame_without_segfault() {
376        let mut encoder = SpeexEncoder::<NbMode>::new();
377        let mut bits = SpeexBits::new();
378        let frame_size = encoder.get_frame_size();
379        let mut input = vec![23i16; frame_size as usize];
380
381        encoder.encode_int(&mut input, &mut bits);
382    }
383}