speex_safe/mode/
mod.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
8pub(crate) mod decoder;
9pub(crate) mod encoder;
10
11use std::error::Error;
12use std::ffi::c_void;
13use std::fmt::Display;
14
15pub use decoder::{DynamicDecoder, SpeexDecoder};
16pub use encoder::{DynamicEncoder, SpeexEncoder};
17use speex_sys::{SpeexMode, SPEEX_MODEID_NB, SPEEX_MODEID_UWB, SPEEX_MODEID_WB};
18
19/// Possible modes for the encoder and decoder.
20#[repr(i32)]
21#[derive(Copy, Clone, PartialEq, Eq, Debug)]
22pub enum ModeId {
23    NarrowBand = SPEEX_MODEID_NB,
24    WideBand = SPEEX_MODEID_WB,
25    UltraWideBand = SPEEX_MODEID_UWB,
26}
27
28impl From<i32> for ModeId {
29    fn from(value: i32) -> Self {
30        match value {
31            SPEEX_MODEID_NB => ModeId::NarrowBand,
32            SPEEX_MODEID_WB => ModeId::WideBand,
33            SPEEX_MODEID_UWB => ModeId::UltraWideBand,
34            _ => panic!("Invalid mode id"),
35        }
36    }
37}
38
39/// Possible submodes for the narrowband mode.
40///
41/// As wideband and ultra-wideband modes both embed narrowband, this is also
42/// used for those.
43#[repr(i32)]
44#[derive(Copy, Clone, PartialEq, Eq, Debug)]
45pub enum NbSubmodeId {
46    /// 2150 bps "vocoder-like" mode for comfort noise
47    VocoderLike = 1,
48    /// 3.95 kbps very low bit-rate mode
49    ExtremeLow = 8,
50    /// 5.95 kbps very low bit-rate mode
51    VeryLow = 2,
52    /// 8 kbps low bit-rate mode
53    Low = 3,
54    /// 11 kbps medium bit-rate mode
55    Medium = 4,
56    /// 15 kbps high bit-rate mode
57    High = 5,
58    /// 18.2 kbps very high bit-rate mode
59    VeryHigh = 6,
60    /// 24.6 kbps very high bit-rate mode
61    ExtremeHigh = 7,
62}
63
64impl From<i32> for NbSubmodeId {
65    fn from(value: i32) -> Self {
66        match value {
67            1 => NbSubmodeId::VocoderLike,
68            2 => NbSubmodeId::VeryLow,
69            3 => NbSubmodeId::Low,
70            4 => NbSubmodeId::Medium,
71            5 => NbSubmodeId::High,
72            6 => NbSubmodeId::VeryHigh,
73            7 => NbSubmodeId::ExtremeHigh,
74            8 => NbSubmodeId::ExtremeLow,
75            _ => panic!("Invalid submode id"),
76        }
77    }
78}
79
80/// Possible submodes for the Wideband mode.
81#[repr(i32)]
82#[derive(Copy, Clone, PartialEq, Eq, Debug)]
83pub enum WbSubmodeId {
84    /// disables innovation quantization entirely
85    NoQuantize = 1,
86    /// enables innovation quantization, but with a lower rate than the default
87    QuantizedLow = 2,
88    /// enables innovation quantization with the default rate
89    QuantizedMedium = 3,
90    /// enables innovation quantization, but with a higher rate than the default
91    QuantizedHigh = 4,
92}
93
94impl From<i32> for WbSubmodeId {
95    fn from(value: i32) -> Self {
96        match value {
97            1 => WbSubmodeId::NoQuantize,
98            2 => WbSubmodeId::QuantizedLow,
99            3 => WbSubmodeId::QuantizedMedium,
100            4 => WbSubmodeId::QuantizedHigh,
101            _ => panic!("Invalid submode id"),
102        }
103    }
104}
105
106/// Possible submodes for the UWB mode.
107///
108/// While this is an enum, UWB mode only has one submode, so it's effectively a
109/// constant.
110#[repr(i32)]
111#[derive(Copy, Clone, PartialEq, Eq, Debug)]
112pub enum UwbSubmodeId {
113    Only = WbSubmodeId::NoQuantize as i32,
114}
115
116impl From<i32> for UwbSubmodeId {
117    fn from(value: i32) -> Self {
118        match value {
119            1 => UwbSubmodeId::Only,
120            _ => panic!("Invalid submode id"),
121        }
122    }
123}
124
125impl ModeId {
126    pub fn get_mode(self) -> &'static SpeexMode {
127        unsafe {
128            let ptr = speex_sys::speex_lib_get_mode(self as i32);
129            // speexmodes are hard constants defined within the codebase itself, so the
130            // backing memory *should* always be valid. Should.
131            let reference: &'static SpeexMode = &*ptr;
132            reference
133        }
134    }
135
136    pub fn get_frame_size(self) -> i32 {
137        unsafe {
138            let ptr = speex_sys::speex_lib_get_mode(self as i32);
139            let mut frame_size = 0;
140            let frame_size_ptr = &mut frame_size as *mut i32;
141            speex_sys::speex_mode_query(
142                ptr,
143                speex_sys::SPEEX_MODE_FRAME_SIZE,
144                frame_size_ptr as *mut c_void,
145            );
146            frame_size
147        }
148    }
149}
150
151/// Error type for the control functions of the encoder and decoder.
152#[derive(Copy, Clone, PartialEq, Eq, Debug)]
153pub enum ControlError {
154    /// The request type passed to the control function was invalid
155    /// The parameter is the request type that was passed
156    UnknownRequest(i32),
157    /// The parameter passed to the control function was invalid (and probably
158    /// caused a segfault, making this error unreachable)
159    InvalidParameter,
160}
161
162impl Display for ControlError {
163    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
164        match self {
165            ControlError::UnknownRequest(id) => {
166                write!(
167                    f,
168                    "Unknown request type passed to a control function ({id})"
169                )
170            }
171            ControlError::InvalidParameter => write!(f, "Invalid parameter"),
172        }
173    }
174}
175
176impl Error for ControlError {}
177
178mod private {
179    pub trait Sealed {}
180}
181
182/// Trait for the control functions of the encoder and decoder
183///
184/// This trait is implemented for both the encoder and decoder, and provides a
185/// common interface for the control functions of both.
186///
187/// `ctl` is the only function that needs to be implemented, and is used to call
188/// the control functions of the underlying speex library.
189///
190/// This trait is sealed, and cannot be implemented outside of this crate.
191pub trait ControlFunctions: private::Sealed {
192    /// Internal function used to convert the error codes returned by the
193    /// control function into a result type
194    fn check_error(err_code: i32, param: Option<i32>) -> Result<(), ControlError> {
195        match err_code {
196            0 => Ok(()),
197            -1 => Err(ControlError::UnknownRequest(param.unwrap())),
198            -2 => Err(ControlError::InvalidParameter),
199            _ => panic!("Unknown error code passed to make_error(), this is a bug"),
200        }
201    }
202
203    /// Calls a control function of the underlying speex library
204    ///
205    /// # Safety
206    ///
207    /// Implementations of this function call the control functions of the
208    /// underlying speex library, and as such are unsafe. The caller must
209    /// ensure that the parameters passed to this function are valid.
210    unsafe fn ctl(&mut self, request: i32, ptr: *mut c_void) -> Result<(), ControlError>;
211
212    /// Gets the frame size (in samples) of the encoder/decoder
213    fn get_frame_size(&mut self) -> i32 {
214        let mut state = 0;
215        let ptr = &mut state as *mut i32 as *mut c_void;
216        unsafe {
217            self.ctl(speex_sys::SPEEX_GET_FRAME_SIZE, ptr).unwrap();
218        }
219        state
220    }
221
222    /// Sets whether Variable BitRate is enabled or not
223    fn set_vbr(&mut self, vbr: bool) {
224        let state = if vbr { 1 } else { 0 };
225        let ptr = &state as *const i32 as *mut c_void;
226        unsafe {
227            self.ctl(speex_sys::SPEEX_SET_VBR, ptr).unwrap();
228        }
229    }
230
231    /// Gets whether Variable BitRate is enabled or not
232    fn get_vbr(&mut self) -> bool {
233        let mut state = 0;
234        let ptr = &mut state as *mut i32 as *mut c_void;
235        unsafe {
236            self.ctl(speex_sys::SPEEX_GET_VBR, ptr).unwrap();
237        }
238        state != 0
239    }
240
241    /// Sets the VBR quality of the encoder/decoder
242    ///
243    /// The value should be between 0 and 10, with 10 being the highest quality.
244    fn set_vbr_quality(&mut self, quality: f32) {
245        let ptr = &quality as *const f32 as *mut c_void;
246        unsafe {
247            self.ctl(speex_sys::SPEEX_SET_VBR_QUALITY, ptr).unwrap();
248        }
249    }
250
251    /// Gets the VBR quality of the encoder/decoder
252    fn get_vbr_quality(&mut self) -> f32 {
253        let mut state = 0.0;
254        let ptr = &mut state as *mut f32 as *mut c_void;
255        unsafe {
256            self.ctl(speex_sys::SPEEX_GET_VBR_QUALITY, ptr).unwrap();
257        }
258        state
259    }
260
261    /// Sets whether Voice Activity Detection is enabled or not
262    fn set_vad(&mut self, vad: bool) {
263        let state = if vad { 1 } else { 0 };
264        let ptr = &state as *const i32 as *mut c_void;
265        unsafe {
266            self.ctl(speex_sys::SPEEX_SET_VAD, ptr).unwrap();
267        }
268    }
269
270    /// Gets whether Voice Activity Detection is enabled or not
271    fn get_vad(&mut self) -> bool {
272        let mut state = 0;
273        let ptr = &mut state as *mut i32 as *mut c_void;
274        unsafe {
275            self.ctl(speex_sys::SPEEX_GET_VAD, ptr).unwrap();
276        }
277        state != 0
278    }
279
280    /// Sets the Average BitRate of the encoder/decoder
281    fn set_abr(&mut self, abr: i32) {
282        let ptr = &abr as *const i32 as *mut c_void;
283        unsafe {
284            self.ctl(speex_sys::SPEEX_SET_ABR, ptr).unwrap();
285        }
286    }
287
288    /// Gets the Average BitRate of the encoder/decoder
289    fn get_abr(&mut self) -> i32 {
290        let mut state = 0;
291        let ptr = &mut state as *mut i32 as *mut c_void;
292        unsafe {
293            self.ctl(speex_sys::SPEEX_GET_ABR, ptr).unwrap();
294        }
295        state
296    }
297
298    /// Sets the overall quality of the encoder/decoder
299    /// The value should be between 0 and 10, with 10 being the highest quality.
300    /// Default is 8.
301    fn set_quality(&mut self, quality: i32) {
302        let ptr = &quality as *const i32 as *mut c_void;
303        unsafe {
304            self.ctl(speex_sys::SPEEX_SET_QUALITY, ptr).unwrap();
305        }
306    }
307
308    /// Sets the current bitrate of the encoder/decoder
309    fn set_bitrate(&mut self, bitrate: i32) {
310        let ptr = &bitrate as *const i32 as *mut c_void;
311        unsafe {
312            self.ctl(speex_sys::SPEEX_SET_BITRATE, ptr).unwrap();
313        }
314    }
315
316    /// Gets the current bitrate of the encoder/decoder
317    fn get_bitrate(&mut self) -> i32 {
318        let mut state = 0;
319        let ptr = &mut state as *mut i32 as *mut c_void;
320        unsafe {
321            self.ctl(speex_sys::SPEEX_GET_BITRATE, ptr).unwrap();
322        }
323        state
324    }
325
326    /// Sets the sampling rate used for bitrate computation
327    fn set_sampling_rate(&mut self, samplingrate: i32) {
328        let ptr = &samplingrate as *const i32 as *mut c_void;
329        unsafe {
330            self.ctl(speex_sys::SPEEX_SET_SAMPLING_RATE, ptr).unwrap();
331        }
332    }
333
334    /// Gets the sampling rate used for bitrate computation
335    fn get_sampling_rate(&mut self) -> i32 {
336        let mut state = 0;
337        let ptr = &mut state as *mut i32 as *mut c_void;
338        unsafe {
339            self.ctl(speex_sys::SPEEX_GET_SAMPLING_RATE, ptr).unwrap();
340        }
341        state
342    }
343
344    /// resets the encoder/decoder memories to zero
345    fn reset_state(&mut self) {
346        unsafe {
347            self.ctl(speex_sys::SPEEX_RESET_STATE, std::ptr::null_mut())
348                .unwrap();
349        }
350    }
351
352    /// Sets whether submode encoding is done in each frame
353    ///
354    /// Note that false breaks the specification for the format
355    fn set_submode_encoding(&mut self, submode: bool) {
356        let state = if submode { 1 } else { 0 };
357        let ptr = &state as *const i32 as *mut c_void;
358        unsafe {
359            self.ctl(speex_sys::SPEEX_SET_SUBMODE_ENCODING, ptr)
360                .unwrap();
361        }
362    }
363
364    /// Gets whether submode encoding is enabled or not
365    fn get_submode_encoding(&mut self) -> bool {
366        let mut state = 0;
367        let ptr = &mut state as *mut i32 as *mut c_void;
368        unsafe {
369            self.ctl(speex_sys::SPEEX_GET_SUBMODE_ENCODING, ptr)
370                .unwrap();
371        }
372        state != 0
373    }
374
375    /// Gets the lookahead value currently in use by the encoder/decoder
376    ///
377    /// Sum the lookahead of a Speex decoder and the lookahead of a Speex
378    /// encoder to get the total lookahead.
379    fn get_lookahead(&mut self) -> i32 {
380        let mut state = 0;
381        let ptr = &mut state as *mut i32 as *mut c_void;
382        unsafe {
383            self.ctl(speex_sys::SPEEX_GET_LOOKAHEAD, ptr).unwrap();
384        }
385        state
386    }
387
388    /// Sets tuning for Packet-Loss Concealment (expected loss rate)
389    fn set_plc_tuning(&mut self, tuning: i32) {
390        let ptr = &tuning as *const i32 as *mut c_void;
391        unsafe {
392            self.ctl(speex_sys::SPEEX_SET_PLC_TUNING, ptr).unwrap();
393        }
394    }
395
396    /// Gets current Packet-Loss Concealment tuning value
397    fn get_plc_tuning(&mut self) -> i32 {
398        let mut state = 0;
399        let ptr = &mut state as *mut i32 as *mut c_void;
400        unsafe {
401            self.ctl(speex_sys::SPEEX_GET_PLC_TUNING, ptr).unwrap();
402        }
403        state
404    }
405
406    /// Sets the max bit-rate allowed in VBR mode
407    fn set_vbr_max_bitrate(&mut self, max_bitrate: i32) {
408        let ptr = &max_bitrate as *const i32 as *mut c_void;
409        unsafe {
410            self.ctl(speex_sys::SPEEX_SET_VBR_MAX_BITRATE, ptr).unwrap();
411        }
412    }
413
414    /// Gets the max bit-rate allowed in VBR mode
415    fn get_vbr_max_bitrate(&mut self) -> i32 {
416        let mut state = 0;
417        let ptr = &mut state as *mut i32 as *mut c_void;
418        unsafe {
419            self.ctl(speex_sys::SPEEX_GET_VBR_MAX_BITRATE, ptr).unwrap();
420        }
421        state
422    }
423
424    /// Enables or disables highpass filtering of the input/output
425    fn set_highpass(&mut self, highpass: bool) {
426        let state = if highpass { 1 } else { 0 };
427        let ptr = &state as *const i32 as *mut c_void;
428        unsafe {
429            self.ctl(speex_sys::SPEEX_SET_HIGHPASS, ptr).unwrap();
430        }
431    }
432
433    /// Gets whether highpass filtering of the input/output is enabled
434    fn get_highpass(&mut self) -> bool {
435        let mut state = 0;
436        let ptr = &mut state as *mut i32 as *mut c_void;
437        unsafe {
438            self.ctl(speex_sys::SPEEX_GET_HIGHPASS, ptr).unwrap();
439        }
440        state != 0
441    }
442}
443
444#[macro_export]
445macro_rules! dynamic_mapping {
446    ($name:expr, $enum_name:ident, $inner:pat => $action:expr) => {
447        match $name {
448            $enum_name::Nb($inner) => $action,
449            $enum_name::Wb($inner) => $action,
450            $enum_name::Uwb($inner) => $action,
451        }
452    };
453}
454
455#[macro_export]
456macro_rules! shared_functions {
457    ($enum_name:ident) => {
458        /// Gets the frame size (in samples) of the encoder/decoder
459        pub fn get_frame_size(&mut self) -> i32 {
460            dynamic_mapping!(self, $enum_name, inner => inner.get_frame_size())
461        }
462
463        /// Sets whether Variable BitRate is enabled or not
464        pub fn set_vbr(&mut self, vbr: bool) {
465            dynamic_mapping!(self, $enum_name, inner => inner.set_vbr(vbr))
466        }
467
468        /// Gets whether Variable BitRate is enabled or not
469        pub fn get_vbr(&mut self) -> bool {
470            dynamic_mapping!(self, $enum_name, inner => inner.get_vbr())
471        }
472
473        /// Sets the VBR quality of the encoder/decoder
474        ///
475        /// The value should be between 0 and 10, with 10 being the highest quality.
476        pub fn set_vbr_quality(&mut self, quality: f32) {
477            dynamic_mapping!(self, $enum_name, inner => inner.set_vbr_quality(quality))
478        }
479
480        /// Gets the VBR quality of the encoder/decoder
481        pub fn get_vbr_quality(&mut self) -> f32 {
482            dynamic_mapping!(self, $enum_name, inner => inner.get_vbr_quality())
483        }
484
485        /// Sets whether Voice Activity Detection is enabled or not
486        pub fn set_vad(&mut self, vad: bool) {
487            dynamic_mapping!(self, $enum_name, inner => inner.set_vad(vad))
488        }
489
490        /// Gets whether Voice Activity Detection is enabled or not
491        pub fn get_vad(&mut self) -> bool {
492            dynamic_mapping!(self, $enum_name, inner => inner.get_vad())
493        }
494
495        /// Sets the Average BitRate of the encoder/decoder
496        pub fn set_abr(&mut self, abr: i32) {
497            dynamic_mapping!(self, $enum_name, inner => inner.set_abr(abr))
498        }
499
500        /// Gets the Average BitRate of the encoder/decoder
501        pub fn get_abr(&mut self) -> i32 {
502            dynamic_mapping!(self, $enum_name, inner => inner.get_abr())
503        }
504
505        /// Sets the overall quality of the encoder/decoder
506        /// The value should be between 0 and 10, with 10 being the highest quality.
507        /// Default is 8.
508        pub fn set_quality(&mut self, quality: i32) {
509            dynamic_mapping!(self, $enum_name, inner => inner.set_quality(quality))
510        }
511
512        /// Sets the current bitrate of the encoder/decoder
513        pub fn set_bitrate(&mut self, bitrate: i32) {
514            dynamic_mapping!(self, $enum_name, inner => inner.set_bitrate(bitrate))
515        }
516
517        /// Gets the current bitrate of the encoder/decoder
518        pub fn get_bitrate(&mut self) -> i32 {
519            dynamic_mapping!(self, $enum_name, inner => inner.get_bitrate())
520        }
521
522        /// Sets the sampling rate used for bitrate computation
523        pub fn set_sampling_rate(&mut self, samplingrate: i32) {
524            dynamic_mapping!(self, $enum_name, inner => inner.set_sampling_rate(samplingrate))
525        }
526
527        /// Gets the sampling rate used for bitrate computation
528        pub fn get_sampling_rate(&mut self) -> i32 {
529            dynamic_mapping!(self, $enum_name, inner => inner.get_sampling_rate())
530        }
531
532        /// resets the encoder/decoder memories to zero
533        pub fn reset_state(&mut self) {
534            dynamic_mapping!(self, $enum_name, inner => inner.reset_state())
535        }
536
537        /// Sets whether submode encoding is done in each frame
538        ///
539        /// Note that false breaks the specification for the format
540        pub fn set_submode_encoding(&mut self, submode: bool) {
541            dynamic_mapping!(self, $enum_name, inner => inner.set_submode_encoding(submode))
542        }
543
544        /// Gets whether submode encoding is enabled or not
545        pub fn get_submode_encoding(&mut self) -> bool {
546            dynamic_mapping!(self, $enum_name, inner => inner.get_submode_encoding())
547        }
548
549        /// Gets the lookahead value currently in use by the encoder/decoder
550        ///
551        /// Sum the lookahead of a Speex decoder and the lookahead of a Speex
552        /// encoder to get the total lookahead.
553        pub fn get_lookahead(&mut self) -> i32 {
554            dynamic_mapping!(self, $enum_name, inner => inner.get_lookahead())
555        }
556
557        /// Sets tuning for Packet-Loss Concealment (expected loss rate)
558        pub fn set_plc_tuning(&mut self, tuning: i32) {
559            dynamic_mapping!(self, $enum_name, inner => inner.set_plc_tuning(tuning))
560        }
561
562        /// Gets current Packet-Loss Concealment tuning value
563        pub fn get_plc_tuning(&mut self) -> i32 {
564            dynamic_mapping!(self, $enum_name, inner => inner.get_plc_tuning())
565        }
566
567        /// Sets the max bit-rate allowed in VBR mode
568        pub fn set_vbr_max_bitrate(&mut self, max_bitrate: i32) {
569            dynamic_mapping!(self, $enum_name, inner => inner.set_vbr_max_bitrate(max_bitrate))
570        }
571
572        /// Gets the max bit-rate allowed in VBR mode
573        pub fn get_vbr_max_bitrate(&mut self) -> i32 {
574            dynamic_mapping!(self, $enum_name, inner => inner.get_vbr_max_bitrate())
575        }
576
577        /// Enables or disables highpass filtering of the input/output
578        pub fn set_highpass(&mut self, highpass: bool) {
579            dynamic_mapping!(self, $enum_name, inner => inner.set_highpass(highpass))
580        }
581
582        /// Gets whether highpass filtering of the input/output is enabled
583        pub fn get_highpass(&mut self) -> bool {
584            dynamic_mapping!(self, $enum_name, inner => inner.get_highpass())
585        }
586    };
587}
588
589/// Marker trait used to specify the mode of the de/encoder.
590pub trait CoderMode {}
591
592/// Narrowband mode (8kHz)
593///
594/// This is a marker type used to specify the mode of the de/encoder.
595pub enum NbMode {}
596impl CoderMode for NbMode {}
597/// Wideband mode (16kHz)
598///
599/// This is a marker type used to specify the mode of the de/encoder.
600pub enum WbMode {}
601impl CoderMode for WbMode {}
602/// Ultra-wideband mode (32kHz)
603///
604/// This is a marker type used to specify the mode of the de/encoder.
605pub enum UwbMode {}
606impl CoderMode for UwbMode {}