opusic_c/
dred.rs

1//! DRED decoder
2//!
3//! Deep Audio Redundancy relies on encoder to embed historic speech data within OPUS packet's
4//! padding to provide extra data for DRED decoder to re-construct speech in case of data loss.
5//! Therefore this decoder is only useful when you rely on unreliable transport protocol like UDP
6//! (common for VOIP applications).
7//! There is no benefit in using it when you do not expect packet loss (e.g. working with reliable
8//! transport protocols like TCP)
9//!
10//! ## Encoder configuration
11//!
12//! In order to enable encoder to embed redundancy data you must specify following configuration:
13//! - [set_dred_duration](../struct.Encoder.html#method.set_dred_duration) - specify number of 10ms
14//! frames to embed within OPUS packets from the past
15//!
16//! Following options should be considered:
17//! - [set_inband_fec](../struct.Encoder.html#method.set_inband_fec) - should not be any value
18//! other than `InbandFec::Off` as it is OPUS's default error correction mechanism which would be
19//! of no use when DRED is used
20//! - [Application::Voip](../enum.Application.html#variant.Voip) - might be a desirable setting for
21//! encoder to ensure speech quality is given priority
22//!
23//! ## Decoder configuration
24//!
25//! There is no special configuration is necessary, but you must use special wrapper over standard
26//! [Decoder](../struct.Decoder.html) provided by this module: [Dred](struct.Dred.html) in order
27//! to decode data as regular decoder will not be able to make use of DRED data within frames
28
29use crate::{sys, mem, Decoder, ErrorCode, SampleRate, Bandwidth};
30
31use core::num;
32
33///Opus DRED packet size (used to alloc memory)
34pub const DRED_PACKET_SIZE: usize = 10592;
35
36///Retrieves OPUS DRED packet size as per libopus requirements
37pub fn dred_packet_size() -> usize {
38    unsafe {
39        sys::opus_dred_get_size() as _
40    }
41}
42
43#[repr(transparent)]
44///Opus DRED packet state
45pub struct DredPacket {
46    inner: mem::Unique<sys::OpusDRED>
47}
48
49impl DredPacket {
50    ///Creates new uninitialized packet
51    pub fn new() -> Result<Self, ErrorCode> {
52        match mem::Unique::new(DRED_PACKET_SIZE) {
53            Some(inner) => Ok(DredPacket {
54                inner,
55            }),
56            None => Err(ErrorCode::AllocFail),
57        }
58    }
59}
60
61unsafe impl Send for DredPacket {}
62
63///OPUS DRED Decoder
64pub struct Dred {
65    inner: mem::Unique<sys::OpusDREDDecoder>,
66    decoder: Decoder,
67    packet: DredPacket,
68}
69
70impl Dred {
71    ///Creates new decoder instance
72    pub fn new(decoder: Decoder) -> Result<Self, ErrorCode> {
73        let size = unsafe {
74            sys::opus_dred_decoder_get_size()
75        };
76
77        if size == 0 {
78            return Err(ErrorCode::Internal);
79        }
80
81        let packet = DredPacket::new()?;
82        let mut decoder = match mem::Unique::new(size as _) {
83            Some(inner) => Dred {
84                inner,
85                decoder,
86                packet,
87            },
88            None => return Err(ErrorCode::AllocFail)
89        };
90
91        let result = unsafe {
92            sys::opus_dred_decoder_init(decoder.inner.as_mut())
93        };
94
95        map_sys_error!(result => decoder)
96    }
97
98    ///Access underlying decoder
99    pub fn decoder(&mut self) -> &Decoder {
100        &self.decoder
101    }
102
103    ///Access underlying decoder
104    pub fn decoder_mut(&mut self) -> &mut Decoder {
105        &mut self.decoder
106    }
107
108    ///Decodes input packet, returning number of decoded samples.
109    ///
110    ///Output size must correspond to sampling rate.
111    ///For example, at 48 kHz allowed frame sizes are 120, 240, 480, 960, 1920, and 2880.
112    ///
113    ///Maximum packet duration is 120ms therefore maximum `frame size` must be
114    ///`frame_bytes_size(SampleRate::Hz48000, Channels::Stereo, 120)`
115    pub fn decode_to(&mut self, input: &[u8], output: &mut [mem::MaybeUninit<i16>]) -> Result<usize, ErrorCode> {
116        const MAX_SAMPLE_RATE: i32 = SampleRate::Hz48000 as _;
117
118        let mut _dred_end = 0;
119        let input_ptr = input.as_ptr();
120        let input_len = input.len() as _;
121
122        let frame_size = (output.len() / self.decoder.channels() as usize) as _;
123
124        let result = unsafe {
125            sys::opus_dred_parse(self.inner.as_mut(), self.packet.inner.as_mut(),
126                                 input_ptr, input_len,
127                                 MAX_SAMPLE_RATE, MAX_SAMPLE_RATE,
128                                 &mut _dred_end, 0)
129        };
130
131        if result < 0 {
132            return Err(result.into());
133        }
134
135        let result = unsafe {
136            sys::opus_decoder_dred_decode(
137                self.decoder.inner.as_mut(), self.packet.inner.as_ptr(),
138                frame_size, output.as_ptr() as _, frame_size
139            )
140        };
141
142        map_sys_error!(result => result as _)
143    }
144
145    #[inline(always)]
146    ///Decodes input packet, returning number of decoded samples.
147    ///
148    ///Refer to `decode_to` for details
149    pub fn decode_to_slice(&mut self, input: &[u8], output: &mut [u16]) -> Result<usize, ErrorCode> {
150        self.decode_to(input, unsafe { mem::transmute(output) })
151    }
152
153    ///Decodes input packet, returning number of decoded samples.
154    ///
155    ///Output size must correspond to sampling rate.
156    ///For example, at 48 kHz allowed frame sizes are 120, 240, 480, 960, 1920, and 2880.
157    ///
158    ///Maximum packet duration is 120ms therefore maximum `frame size` must be
159    ///`frame_bytes_size(SampleRate::Hz48000, Channels::Stereo, 120)`
160    pub fn decode_float_to(&mut self, input: &[u8], output: &mut [mem::MaybeUninit<f32>]) -> Result<usize, ErrorCode> {
161        const MAX_SAMPLE_RATE: i32 = SampleRate::Hz48000 as _;
162
163        let mut _dred_end = 0;
164        let input_ptr = input.as_ptr();
165        let input_len = input.len() as _;
166
167        let frame_size = (output.len() / self.decoder.channels() as usize) as _;
168
169        let result = unsafe {
170            sys::opus_dred_parse(self.inner.as_mut(), self.packet.inner.as_mut(),
171                                 input_ptr, input_len,
172                                 MAX_SAMPLE_RATE, MAX_SAMPLE_RATE,
173                                 &mut _dred_end, 0)
174        };
175
176        if result < 0 {
177            return Err(result.into());
178        }
179
180        let result = unsafe {
181            sys::opus_decoder_dred_decode_float(
182                self.decoder.inner.as_mut(), self.packet.inner.as_ptr(),
183                frame_size, output.as_ptr() as _, frame_size
184            )
185        };
186
187        map_sys_error!(result => result as _)
188    }
189
190    #[inline(always)]
191    ///Decodes input packet, returning number of decoded samples.
192    ///
193    ///Refer to `decode_to` for details
194    pub fn decode_float_to_slice(&mut self, input: &[u8], output: &mut [f32]) -> Result<usize, ErrorCode> {
195        self.decode_float_to(input, unsafe { mem::transmute(output) })
196    }
197
198    #[inline]
199    ///Resets state to initial
200    pub fn reset(&mut self) -> Result<(), ErrorCode> {
201        self.decoder.reset()?;
202        let result = unsafe {
203            sys::opus_dred_decoder_ctl(self.inner.as_mut(), sys::OPUS_RESET_STATE)
204        };
205
206        map_sys_error!(result => ())
207    }
208
209    #[inline]
210    ///Gets the pitch of the last decoded frame, if available.
211    ///
212    ///This can be used for any post-processing algorithm requiring the use of pitch, e.g. time
213    ///stretching/shortening. If the last frame was not voiced, or if the pitch was not coded in
214    ///the frame, then zero is returned.
215    pub fn get_pitch(&mut self) -> Result<Option<num::NonZeroU32>, ErrorCode> {
216        let mut value: i32 = 0;
217        let result = unsafe {
218            sys::opus_dred_decoder_ctl(self.inner.as_mut(), sys::OPUS_GET_PITCH_REQUEST, &mut value)
219        };
220
221        map_sys_error!(result => num::NonZeroU32::new(result as _))
222    }
223
224    #[inline]
225    ///Gets the duration (in samples) of the last packet successfully decoded or concealed.
226    pub fn get_last_packet_duration(&mut self) -> Result<u32, ErrorCode> {
227        let mut value: i32 = 0;
228        let result = unsafe {
229            sys::opus_dred_decoder_ctl(self.inner.as_mut(), sys::OPUS_GET_LAST_PACKET_DURATION_REQUEST, &mut value)
230        };
231
232        map_sys_error!(result => value as _)
233    }
234
235    #[inline]
236    ///Gets the decoder's gain configuration
237    pub fn get_gain(&mut self) -> Result<i32, ErrorCode> {
238        let mut value: i32 = 0;
239        let result = unsafe {
240            sys::opus_dred_decoder_ctl(self.inner.as_mut(), sys::OPUS_GET_GAIN_REQUEST, &mut value)
241        };
242
243        map_sys_error!(result => value)
244    }
245
246    #[inline]
247    ///Configures decoder gain adjustment.
248    ///
249    ///Scales the decoded output by a factor specified in Q8 dB units.
250    ///This has a maximum range of -32768 to 32767 inclusive, and returns `BadArg` otherwise.
251    ///
252    ///The default is zero indicating no adjustment.
253    ///
254    ///_This setting survives decoder reset_.
255    ///
256    ///Formula:
257    ///
258    ///`gain = pow(10, x/(20.0*256))`
259    pub fn set_gain(&mut self, value: i32) -> Result<(), ErrorCode> {
260        let result = unsafe {
261            sys::opus_dred_decoder_ctl(self.inner.as_mut(), sys::OPUS_SET_GAIN_REQUEST, value)
262        };
263
264        map_sys_error!(result => ())
265    }
266
267    #[inline]
268    ///Gets the decoder's last bandpass
269    pub fn get_bandwidth(&mut self) -> Result<Bandwidth, ErrorCode> {
270        let mut value: i32 = 0;
271        let result = unsafe {
272            sys::opus_dred_decoder_ctl(self.inner.as_mut(), sys::OPUS_GET_BANDWIDTH_REQUEST, &mut value)
273        };
274
275        map_sys_error!(result => value.into())
276    }
277
278    #[inline]
279    ///Gets configured sample rate of this instance
280    pub fn get_sample_rate(&mut self) -> Result<SampleRate, ErrorCode> {
281        let mut value: i32 = 0;
282        let result = unsafe {
283            sys::opus_dred_decoder_ctl(self.inner.as_mut(), sys::OPUS_GET_SAMPLE_RATE_REQUEST, &mut value)
284        };
285
286        map_sys_error!(result => match value {
287            8000 => SampleRate::Hz8000,
288            12000 => SampleRate::Hz12000,
289            16000 => SampleRate::Hz16000,
290            24000 => SampleRate::Hz24000,
291            48000 => SampleRate::Hz48000,
292            _ => return Err(ErrorCode::unknown())
293        })
294    }
295
296    #[inline]
297    ///Gets the decoder's configured phase inversion status.
298    pub fn get_phase_inversion_disabled(&mut self) -> Result<bool, ErrorCode> {
299        let mut value: i32 = 0;
300        let result = unsafe {
301            sys::opus_dred_decoder_ctl(self.inner.as_mut(), sys::OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST, &mut value)
302        };
303
304        map_sys_error!(result => value == 1)
305    }
306
307    #[inline]
308    ///Configures phase inversion.
309    ///
310    ///If set to `true`, disables the use of phase inversion for intensity stereo, improving the quality
311    ///of mono downmixes, but slightly reducing normal stereo quality.
312    ///
313    ///Disabling phase inversion in the decoder does not comply with RFC 6716, although it does not
314    ///cause any interoperability issue and is expected to become part of the Opus standard once
315    ///RFC 6716 is updated by draft-ietf-codec-opus-update.
316    pub fn set_phase_inversion_disabled(&mut self, value: bool) -> Result<(), ErrorCode> {
317        let value: i32 = match value {
318            true => 1,
319            false => 0,
320        };
321
322        let result = unsafe {
323            sys::opus_dred_decoder_ctl(self.inner.as_mut(), sys::OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST, value)
324        };
325
326        map_sys_error!(result => ())
327    }
328}
329
330unsafe impl Send for Dred {}