opus/
lib.rs

1// Copyright 2016 Tad Hardesty and 2020 Markus Hadenfeldt
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9//! High-level bindings for libopus.
10//!
11//! Only brief descriptions are included here. For detailed information, consult
12//! the [libopus documentation](https://opus-codec.org/docs/opus_api-1.1.2/).
13#![warn(missing_docs)]
14
15extern crate opus_cmake_sys;
16
17use std::ffi::CStr;
18use std::marker::PhantomData;
19use std::os::raw::c_int;
20
21// ============================================================================
22// Constants
23
24// Generic CTLs
25const OPUS_RESET_STATE: c_int = 4028; // void
26const OPUS_GET_FINAL_RANGE: c_int = 4031; // out *u32
27const OPUS_GET_BANDWIDTH: c_int = 4009; // out *i32
28const OPUS_GET_SAMPLE_RATE: c_int = 4029; // out *i32
29// Encoder CTLs
30const OPUS_SET_BITRATE: c_int = 4002; // in i32
31const OPUS_GET_BITRATE: c_int = 4003; // out *i32
32const OPUS_SET_VBR: c_int = 4006; // in i32
33const OPUS_GET_VBR: c_int = 4007; // out *i32
34const OPUS_SET_VBR_CONSTRAINT: c_int = 4020; // in i32
35const OPUS_GET_VBR_CONSTRAINT: c_int = 4021; // out *i32
36const OPUS_SET_INBAND_FEC: c_int = 4012; // in i32
37const OPUS_GET_INBAND_FEC: c_int = 4013; // out *i32
38const OPUS_SET_PACKET_LOSS_PERC: c_int = 4014; // in i32
39const OPUS_GET_PACKET_LOSS_PERC: c_int = 4015; // out *i32
40const OPUS_GET_LOOKAHEAD: c_int = 4027; // out *i32
41// Decoder CTLs
42const OPUS_SET_GAIN: c_int = 4034; // in i32
43const OPUS_GET_GAIN: c_int = 4045; // out *i32
44const OPUS_GET_LAST_PACKET_DURATION: c_int = 4039; // out *i32
45const OPUS_GET_PITCH: c_int = 4033; // out *i32
46
47// Bitrate
48const OPUS_AUTO: c_int = -1000;
49const OPUS_BITRATE_MAX: c_int = -1;
50
51/// Unsafe opus-sys bindings
52pub mod ffi {
53    pub use opus_cmake_sys::*;
54}
55
56/// The possible applications for the codec.
57#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
58pub enum Application {
59    /// Best for most VoIP/videoconference applications where listening quality
60    /// and intelligibility matter most.
61    Voip = 2048,
62    /// Best for broadcast/high-fidelity application where the decoded audio
63    /// should be as close as possible to the input.
64    Audio = 2049,
65    /// Only use when lowest-achievable latency is what matters most.
66    LowDelay = 2051,
67}
68
69/// The available channel setings.
70#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
71pub enum Channels {
72    /// One channel.
73    Mono = 1,
74    /// Two channels, left and right.
75    Stereo = 2,
76}
77
78/// The available bandwidth level settings.
79#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
80pub enum Bandwidth {
81    /// Auto/default setting.
82    Auto = -1000,
83    /// 4kHz bandpass.
84    Narrowband = 1101,
85    /// 6kHz bandpass.
86    Mediumband = 1102,
87    /// 8kHz bandpass.
88    Wideband = 1103,
89    /// 12kHz bandpass.
90    Superwideband = 1104,
91    /// 20kHz bandpass.
92    Fullband = 1105,
93}
94
95impl Bandwidth {
96    fn from_int(value: i32) -> Option<Bandwidth> {
97        Some(match value {
98            -1000 => Bandwidth::Auto,
99            1101 => Bandwidth::Narrowband,
100            1102 => Bandwidth::Mediumband,
101            1103 => Bandwidth::Wideband,
102            1104 => Bandwidth::Superwideband,
103            1105 => Bandwidth::Fullband,
104            _ => return None,
105        })
106    }
107
108    fn decode(value: i32, what: &'static str) -> Result<Bandwidth> {
109        match Bandwidth::from_int(value) {
110            Some(bandwidth) => Ok(bandwidth),
111            None => Err(Error::bad_arg(what)),
112        }
113    }
114}
115
116/// Possible error codes.
117#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
118pub enum ErrorCode {
119    /// One or more invalid/out of range arguments.
120    BadArg = -1,
121    /// Not enough bytes allocated in the buffer.
122    BufferTooSmall = -2,
123    /// An internal error was detected.
124    InternalError = -3,
125    /// The compressed data passed is corrupted.
126    InvalidPacket = -4,
127    /// Invalid/unsupported request number.
128    Unimplemented = -5,
129    /// An encoder or decoder structure is invalid or already freed.
130    InvalidState = -6,
131    /// Memory allocation has failed.
132    AllocFail = -7,
133    /// An unknown failure.
134    Unknown = -8,
135}
136
137impl ErrorCode {
138    fn from_int(value: c_int) -> ErrorCode {
139        use ErrorCode::*;
140        match value {
141            ffi::OPUS_BAD_ARG => BadArg,
142            ffi::OPUS_BUFFER_TOO_SMALL => BufferTooSmall,
143            ffi::OPUS_INTERNAL_ERROR => InternalError,
144            ffi::OPUS_INVALID_PACKET => InvalidPacket,
145            ffi::OPUS_UNIMPLEMENTED => Unimplemented,
146            ffi::OPUS_INVALID_STATE => InvalidState,
147            ffi::OPUS_ALLOC_FAIL => AllocFail,
148            _ => Unknown,
149        }
150    }
151
152    /// Get a human-readable error string for this error code.
153    pub fn description(self) -> &'static str {
154        // should always be ASCII and non-null for any input
155        unsafe { CStr::from_ptr(ffi::opus_strerror(self as c_int)) }.to_str().unwrap()
156    }
157}
158
159/// Possible bitrates.
160#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
161pub enum Bitrate {
162    /// Explicit bitrate choice (in bits/second).
163    Bits(i32),
164    /// Maximum bitrate allowed (up to maximum number of bytes for the packet).
165    Max,
166    /// Default bitrate decided by the encoder (not recommended).
167    Auto,
168}
169
170/// Get the libopus version string.
171///
172/// Applications may look for the substring "-fixed" in the version string to
173/// determine whether they have a fixed-point or floating-point build at
174/// runtime.
175pub fn version() -> &'static str {
176    // verison string should always be ASCII
177    unsafe { CStr::from_ptr(ffi::opus_get_version_string()) }.to_str().unwrap()
178}
179
180macro_rules! ffi {
181	($f:ident $(, $rest:expr)*) => {
182		match unsafe { ffi::$f($($rest),*) } {
183			code if code < 0 => return Err(Error::from_code(stringify!($f), code)),
184			code => code,
185		}
186	}
187}
188
189macro_rules! ctl {
190	($f:ident, $this:ident, $ctl:ident, $($rest:expr),*) => {
191		match unsafe { ffi::$f($this.ptr, $ctl, $($rest),*) } {
192			code if code < 0 => return Err(Error::from_code(
193				concat!(stringify!($f), "(", stringify!($ctl), ")"),
194				code,
195			)),
196			_ => (),
197		}
198	}
199}
200
201// ============================================================================
202// Encoder
203
204macro_rules! enc_ctl {
205	($this:ident, $ctl:ident $(, $rest:expr)*) => {
206		ctl!(opus_encoder_ctl, $this, $ctl, $($rest),*)
207	}
208}
209
210/// An Opus encoder with associated state.
211#[derive(Debug)]
212pub struct Encoder {
213    ptr: *mut ffi::OpusEncoder,
214    channels: Channels,
215}
216
217impl Encoder {
218    /// Create and initialize an encoder.
219    pub fn new(sample_rate: u32, channels: Channels, mode: Application) -> Result<Encoder> {
220        let mut error = 0;
221        let ptr = unsafe {
222            ffi::opus_encoder_create(
223            sample_rate as i32,
224            channels as c_int,
225            mode as c_int,
226            &mut error)
227        };
228        if error != ffi::OPUS_OK || ptr.is_null() {
229            Err(Error::from_code("opus_encoder_create", error))
230        } else {
231            Ok(Encoder { ptr: ptr, channels: channels })
232        }
233    }
234
235    /// Encode an Opus frame.
236    pub fn encode(&mut self, input: &[i16], output: &mut [u8]) -> Result<usize> {
237        let len = ffi!(opus_encode, self.ptr,
238			input.as_ptr(), len(input) / self.channels as c_int,
239			output.as_mut_ptr(), len(output));
240        Ok(len as usize)
241    }
242
243    /// Encode an Opus frame from floating point input.
244    pub fn encode_float(&mut self, input: &[f32], output: &mut [u8]) -> Result<usize> {
245        let len = ffi!(opus_encode_float, self.ptr,
246			input.as_ptr(), len(input) / self.channels as c_int,
247			output.as_mut_ptr(), len(output));
248        Ok(len as usize)
249    }
250
251    /// Encode an Opus frame to a new buffer.
252    pub fn encode_vec(&mut self, input: &[i16], max_size: usize) -> Result<Vec<u8>> {
253        let mut output: Vec<u8> = vec![0; max_size];
254        let result = self.encode(input, output.as_mut_slice())?;
255        output.truncate(result);
256        Ok(output)
257    }
258
259    /// Encode an Opus frame from floating point input to a new buffer.
260    pub fn encode_vec_float(&mut self, input: &[f32], max_size: usize) -> Result<Vec<u8>> {
261        let mut output: Vec<u8> = vec![0; max_size];
262        let result = self.encode_float(input, output.as_mut_slice())?;
263        output.truncate(result);
264        Ok(output)
265    }
266
267    // ------------
268    // Generic CTLs
269
270    /// Reset the codec state to be equivalent to a freshly initialized state.
271    pub fn reset_state(&mut self) -> Result<()> {
272        enc_ctl!(self, OPUS_RESET_STATE);
273        Ok(())
274    }
275
276    /// Get the final range of the codec's entropy coder.
277    pub fn get_final_range(&mut self) -> Result<u32> {
278        let mut value: u32 = 0;
279        enc_ctl!(self, OPUS_GET_FINAL_RANGE, &mut value);
280        Ok(value)
281    }
282
283    /// Get the encoder's configured bandpass.
284    pub fn get_bandwidth(&mut self) -> Result<Bandwidth> {
285        let mut value: i32 = 0;
286        enc_ctl!(self, OPUS_GET_BANDWIDTH, &mut value);
287        Bandwidth::decode(value, "opus_encoder_ctl(OPUS_GET_BANDWIDTH)")
288    }
289
290    /// Get the samping rate the encoder was intialized with.
291    pub fn get_sample_rate(&mut self) -> Result<u32> {
292        let mut value: i32 = 0;
293        enc_ctl!(self, OPUS_GET_SAMPLE_RATE, &mut value);
294        Ok(value as u32)
295    }
296
297    // ------------
298    // Encoder CTLs
299
300    /// Set the encoder's bitrate.
301    pub fn set_bitrate(&mut self, value: Bitrate) -> Result<()> {
302        let value: i32 = match value {
303            Bitrate::Auto => OPUS_AUTO,
304            Bitrate::Max => OPUS_BITRATE_MAX,
305            Bitrate::Bits(b) => b,
306        };
307        enc_ctl!(self, OPUS_SET_BITRATE, value);
308        Ok(())
309    }
310
311    /// Get the encoder's bitrate.
312    pub fn get_bitrate(&mut self) -> Result<Bitrate> {
313        let mut value: i32 = 0;
314        enc_ctl!(self, OPUS_GET_BITRATE, &mut value);
315        Ok(match value {
316            OPUS_AUTO => Bitrate::Auto,
317            OPUS_BITRATE_MAX => Bitrate::Max,
318            _ => Bitrate::Bits(value),
319        })
320    }
321
322    /// Enable or disable variable bitrate.
323    pub fn set_vbr(&mut self, vbr: bool) -> Result<()> {
324        let value: i32 = if vbr { 1 } else { 0 };
325        enc_ctl!(self, OPUS_SET_VBR, value);
326        Ok(())
327    }
328
329    /// Determine if variable bitrate is enabled.
330    pub fn get_vbr(&mut self) -> Result<bool> {
331        let mut value: i32 = 0;
332        enc_ctl!(self, OPUS_GET_VBR, &mut value);
333        Ok(value != 0)
334    }
335
336    /// Enable or disable constrained VBR.
337    pub fn set_vbr_constraint(&mut self, vbr: bool) -> Result<()> {
338        let value: i32 = if vbr { 1 } else { 0 };
339        enc_ctl!(self, OPUS_SET_VBR_CONSTRAINT, value);
340        Ok(())
341    }
342
343    /// Determine if constrained VBR is enabled.
344    pub fn get_vbr_constraint(&mut self) -> Result<bool> {
345        let mut value: i32 = 0;
346        enc_ctl!(self, OPUS_GET_VBR_CONSTRAINT, &mut value);
347        Ok(value != 0)
348    }
349
350    /// Configures the encoder's use of inband forward error correction (FEC).
351    pub fn set_inband_fec(&mut self, value: bool) -> Result<()> {
352        let value: i32 = if value { 1 } else { 0 };
353        enc_ctl!(self, OPUS_SET_INBAND_FEC, value);
354        Ok(())
355    }
356
357    /// Gets encoder's configured use of inband forward error correction.
358    pub fn get_inband_fec(&mut self) -> Result<bool> {
359        let mut value: i32 = 0;
360        enc_ctl!(self, OPUS_GET_INBAND_FEC, &mut value);
361        Ok(value != 0)
362    }
363
364    /// Sets the encoder's expected packet loss percentage.
365    pub fn set_packet_loss_perc(&mut self, value: i32) -> Result<()> {
366        enc_ctl!(self, OPUS_SET_PACKET_LOSS_PERC, value);
367        Ok(())
368    }
369
370    /// Gets the encoder's expected packet loss percentage.
371    pub fn get_packet_loss_perc(&mut self) -> Result<i32> {
372        let mut value: i32 = 0;
373        enc_ctl!(self, OPUS_GET_PACKET_LOSS_PERC, &mut value);
374        Ok(value)
375    }
376
377    /// Gets the total samples of delay added by the entire codec.
378    pub fn get_lookahead(&mut self) -> Result<i32> {
379        let mut value: i32 = 0;
380        enc_ctl!(self, OPUS_GET_LOOKAHEAD, &mut value);
381        Ok(value)
382    }
383
384    // TODO: Encoder-specific CTLs
385}
386
387impl Drop for Encoder {
388    fn drop(&mut self) {
389        unsafe { ffi::opus_encoder_destroy(self.ptr) }
390    }
391}
392
393// "A single codec state may only be accessed from a single thread at
394// a time and any required locking must be performed by the caller. Separate
395// streams must be decoded with separate decoder states and can be decoded
396// in parallel unless the library was compiled with NONTHREADSAFE_PSEUDOSTACK
397// defined."
398//
399// In other words, opus states may be moved between threads at will. A special
400// compilation mode intended for embedded platforms forbids multithreaded use
401// of the library as a whole rather than on a per-state basis, but the opus-sys
402// crate does not use this mode.
403unsafe impl Send for Encoder {}
404
405// ============================================================================
406// Decoder
407
408macro_rules! dec_ctl {
409	($this:ident, $ctl:ident $(, $rest:expr)*) => {
410		ctl!(opus_decoder_ctl, $this, $ctl, $($rest),*)
411	}
412}
413
414/// An Opus decoder with associated state.
415#[derive(Debug)]
416pub struct Decoder {
417    ptr: *mut ffi::OpusDecoder,
418    channels: Channels,
419}
420
421impl Decoder {
422    /// Create and initialize a decoder.
423    pub fn new(sample_rate: u32, channels: Channels) -> Result<Decoder> {
424        let mut error = 0;
425        let ptr = unsafe { ffi::opus_decoder_create(
426            sample_rate as i32,
427            channels as c_int,
428            &mut error) };
429        if error != ffi::OPUS_OK || ptr.is_null() {
430            Err(Error::from_code("opus_decoder_create", error))
431        } else {
432            Ok(Decoder { ptr: ptr, channels: channels })
433        }
434    }
435
436    /// Decode an Opus packet.
437    pub fn decode(&mut self, input: &[u8], output: &mut [i16], fec: bool) -> Result<usize> {
438        let ptr = match input.len() {
439            0 => std::ptr::null(),
440            _ => input.as_ptr(),
441        };
442        let len = ffi!(opus_decode, self.ptr,
443			ptr, len(input),
444			output.as_mut_ptr(), len(output) / self.channels as c_int,
445			fec as c_int);
446        Ok(len as usize)
447    }
448
449    /// Decode an Opus packet with floating point output.
450    pub fn decode_float(&mut self, input: &[u8], output: &mut [f32], fec: bool) -> Result<usize> {
451        let ptr = match input.len() {
452            0 => std::ptr::null(),
453            _ => input.as_ptr(),
454        };
455        let len = ffi!(opus_decode_float, self.ptr,
456			ptr, len(input),
457			output.as_mut_ptr(), len(output) / self.channels as c_int,
458			fec as c_int);
459        Ok(len as usize)
460    }
461
462    /// Get the number of samples of an Opus packet.
463    pub fn get_nb_samples(&self, packet: &[u8]) -> Result<usize> {
464        let len = ffi!(opus_decoder_get_nb_samples, self.ptr,
465			packet.as_ptr(), packet.len() as i32);
466        Ok(len as usize)
467    }
468
469    // ------------
470    // Generic CTLs
471
472    /// Reset the codec state to be equivalent to a freshly initialized state.
473    pub fn reset_state(&mut self) -> Result<()> {
474        dec_ctl!(self, OPUS_RESET_STATE);
475        Ok(())
476    }
477
478    /// Get the final range of the codec's entropy coder.
479    pub fn get_final_range(&mut self) -> Result<u32> {
480        let mut value: u32 = 0;
481        dec_ctl!(self, OPUS_GET_FINAL_RANGE, &mut value);
482        Ok(value)
483    }
484
485    /// Get the decoder's last bandpass.
486    pub fn get_bandwidth(&mut self) -> Result<Bandwidth> {
487        let mut value: i32 = 0;
488        dec_ctl!(self, OPUS_GET_BANDWIDTH, &mut value);
489        Bandwidth::decode(value, "opus_decoder_ctl(OPUS_GET_BANDWIDTH)")
490    }
491
492    /// Get the samping rate the decoder was intialized with.
493    pub fn get_sample_rate(&mut self) -> Result<u32> {
494        let mut value: i32 = 0;
495        dec_ctl!(self, OPUS_GET_SAMPLE_RATE, &mut value);
496        Ok(value as u32)
497    }
498
499    // ------------
500    // Decoder CTLs
501
502    /// Configures decoder gain adjustment.
503    ///
504    /// Scales the decoded output by a factor specified in Q8 dB units. This has
505    /// a maximum range of -32768 to 32768 inclusive, and returns `BadArg`
506    /// otherwise. The default is zero indicating no adjustment. This setting
507    /// survives decoder reset.
508    ///
509    /// `gain = pow(10, x / (20.0 * 256))`
510    pub fn set_gain(&mut self, gain: i32) -> Result<()> {
511        dec_ctl!(self, OPUS_SET_GAIN, gain);
512        Ok(())
513    }
514
515    /// Gets the decoder's configured gain adjustment.
516    pub fn get_gain(&mut self) -> Result<i32> {
517        let mut value: i32 = 0;
518        dec_ctl!(self, OPUS_GET_GAIN, &mut value);
519        Ok(value)
520    }
521
522    /// Gets the duration (in samples) of the last packet successfully decoded
523    /// or concealed.
524    pub fn get_last_packet_duration(&mut self) -> Result<u32> {
525        let mut value: i32 = 0;
526        dec_ctl!(self, OPUS_GET_LAST_PACKET_DURATION, &mut value);
527        Ok(value as u32)
528    }
529
530    /// Gets the pitch of the last decoded frame, if available.
531    ///
532    /// This can be used for any post-processing algorithm requiring the use of
533    /// pitch, e.g. time stretching/shortening. If the last frame was not
534    /// voiced, or if the pitch was not coded in the frame, then zero is
535    /// returned.
536    pub fn get_pitch(&mut self) -> Result<i32> {
537        let mut value: i32 = 0;
538        dec_ctl!(self, OPUS_GET_PITCH, &mut value);
539        Ok(value)
540    }
541}
542
543impl Drop for Decoder {
544    fn drop(&mut self) {
545        unsafe { ffi::opus_decoder_destroy(self.ptr) }
546    }
547}
548
549// See `unsafe impl Send for Encoder`.
550unsafe impl Send for Decoder {}
551
552// ============================================================================
553// Packet Analysis
554
555/// Analyze raw Opus packets.
556pub mod packet {
557    use super::*;
558    use super::ffi;
559    use std::{ptr, slice};
560
561    /// Get the bandwidth of an Opus packet.
562    pub fn get_bandwidth(packet: &[u8]) -> Result<Bandwidth> {
563        if packet.len() < 1 {
564            return Err(Error::bad_arg("opus_packet_get_bandwidth"));
565        }
566        let bandwidth = ffi!(opus_packet_get_bandwidth, packet.as_ptr());
567        Bandwidth::decode(bandwidth, "opus_packet_get_bandwidth")
568    }
569
570    /// Get the number of channels from an Opus packet.
571    pub fn get_nb_channels(packet: &[u8]) -> Result<Channels> {
572        if packet.len() < 1 {
573            return Err(Error::bad_arg("opus_packet_get_nb_channels"));
574        }
575        let channels = ffi!(opus_packet_get_nb_channels, packet.as_ptr());
576        match channels {
577            1 => Ok(Channels::Mono),
578            2 => Ok(Channels::Stereo),
579            _ => Err(Error::bad_arg("opus_packet_get_nb_channels")),
580        }
581    }
582
583    /// Get the number of frames in an Opus packet.
584    pub fn get_nb_frames(packet: &[u8]) -> Result<usize> {
585        let frames = ffi!(opus_packet_get_nb_frames, packet.as_ptr(), len(packet));
586        Ok(frames as usize)
587    }
588
589    /// Get the number of samples of an Opus packet.
590    pub fn get_nb_samples(packet: &[u8], sample_rate: u32) -> Result<usize> {
591        let frames = ffi!(opus_packet_get_nb_samples,
592			packet.as_ptr(), len(packet),
593			sample_rate as c_int);
594        Ok(frames as usize)
595    }
596
597    /// Get the number of samples per frame from an Opus packet.
598    pub fn get_samples_per_frame(packet: &[u8], sample_rate: u32) -> Result<usize> {
599        if packet.len() < 1 {
600            return Err(Error::bad_arg("opus_packet_get_samples_per_frame"))
601        }
602        let samples = ffi!(opus_packet_get_samples_per_frame,
603			packet.as_ptr(), sample_rate as c_int);
604        Ok(samples as usize)
605    }
606
607    /// Parse an Opus packet into one or more frames.
608    pub fn parse(packet: &[u8]) -> Result<Packet> {
609        let mut toc: u8 = 0;
610        let mut frames = [ptr::null(); 48];
611        let mut sizes = [0i16; 48];
612        let mut payload_offset: i32 = 0;
613        let num_frames = ffi!(opus_packet_parse,
614			packet.as_ptr(), len(packet),
615			&mut toc, frames.as_mut_ptr(),
616			sizes.as_mut_ptr(), &mut payload_offset);
617
618        let mut frames_vec = Vec::with_capacity(num_frames as usize);
619        for i in 0..num_frames as usize {
620            frames_vec.push(unsafe { slice::from_raw_parts(frames[i], sizes[i] as usize) });
621        }
622
623        Ok(Packet {
624            toc: toc,
625            frames: frames_vec,
626            payload_offset: payload_offset as usize,
627        })
628    }
629
630    /// A parsed Opus packet, retuned from `parse`.
631    #[derive(Debug)]
632    pub struct Packet<'a> {
633        /// The TOC byte of the packet.
634        pub toc: u8,
635        /// The frames contained in the packet.
636        pub frames: Vec<&'a [u8]>,
637        /// The offset into the packet at which the payload is located.
638        pub payload_offset: usize,
639    }
640
641    /// Pad a given Opus packet to a larger size.
642    ///
643    /// The packet will be extended from the first `prev_len` bytes of the
644    /// buffer into the rest of the available space.
645    pub fn pad(packet: &mut [u8], prev_len: usize) -> Result<usize> {
646        let result = ffi!(opus_packet_pad, packet.as_mut_ptr(),
647			check_len(prev_len), len(packet));
648        Ok(result as usize)
649    }
650
651    /// Remove all padding from a given Opus packet and rewrite the TOC sequence
652    /// to minimize space usage.
653    pub fn unpad(packet: &mut [u8]) -> Result<usize> {
654        let result = ffi!(opus_packet_unpad, packet.as_mut_ptr(), len(packet));
655        Ok(result as usize)
656    }
657}
658
659// ============================================================================
660// Float Soft Clipping
661
662/// Soft-clipping to bring a float signal within the [-1,1] range.
663#[derive(Debug)]
664pub struct SoftClip {
665    channels: Channels,
666    memory: [f32; 2],
667}
668
669impl SoftClip {
670    /// Initialize a new soft-clipping state.
671    pub fn new(channels: Channels) -> SoftClip {
672        SoftClip { channels: channels, memory: [0.0; 2] }
673    }
674
675    /// Apply soft-clipping to a float signal.
676    pub fn apply(&mut self, signal: &mut [f32]) {
677        unsafe { ffi::opus_pcm_soft_clip(
678            signal.as_mut_ptr(),
679            len(signal) / self.channels as c_int,
680            self.channels as c_int,
681            self.memory.as_mut_ptr()) };
682    }
683}
684
685// ============================================================================
686// Repacketizer
687
688/// A repacketizer used to merge together or split apart multiple Opus packets.
689#[derive(Debug)]
690pub struct Repacketizer {
691    ptr: *mut ffi::OpusRepacketizer,
692}
693
694impl Repacketizer {
695    /// Create and initialize a repacketizer.
696    pub fn new() -> Result<Repacketizer> {
697        let ptr = unsafe { ffi::opus_repacketizer_create() };
698        if ptr.is_null() {
699            Err(Error::from_code("opus_repacketizer_create", ffi::OPUS_ALLOC_FAIL))
700        } else {
701            Ok(Repacketizer { ptr: ptr })
702        }
703    }
704
705    /// Shortcut to combine several smaller packets into one larger one.
706    pub fn combine(&mut self, input: &[&[u8]], output: &mut [u8]) -> Result<usize> {
707        let mut state = self.begin();
708        for &packet in input {
709            state.cat(packet)?;
710        }
711        state.out(output)
712    }
713
714    /// Begin using the repacketizer.
715    pub fn begin<'rp, 'buf>(&'rp mut self) -> RepacketizerState<'rp, 'buf> {
716        unsafe { ffi::opus_repacketizer_init(self.ptr); }
717        RepacketizerState { rp: self, phantom: PhantomData }
718    }
719}
720
721impl Drop for Repacketizer {
722    fn drop(&mut self) {
723        unsafe { ffi::opus_repacketizer_destroy(self.ptr) }
724    }
725}
726
727// See `unsafe impl Send for Encoder`.
728unsafe impl Send for Repacketizer {}
729
730// To understand why these lifetime bounds are needed, imagine that the
731// repacketizer keeps an internal Vec<&'buf [u8]>, which is added to by cat()
732// and accessed by get_nb_frames(), out(), and out_range(). To prove that these
733// lifetime bounds are correct, a dummy implementation with the same signatures
734// but a real Vec<&'buf [u8]> rather than unsafe blocks may be substituted.
735
736/// An in-progress repacketization.
737#[derive(Debug)]
738pub struct RepacketizerState<'rp, 'buf> {
739    rp: &'rp mut Repacketizer,
740    phantom: PhantomData<&'buf [u8]>,
741}
742
743impl<'rp, 'buf> RepacketizerState<'rp, 'buf> {
744    /// Add a packet to the current repacketizer state.
745    pub fn cat(&mut self, packet: &'buf [u8]) -> Result<()> {
746        ffi!(opus_repacketizer_cat, self.rp.ptr,
747			packet.as_ptr(), len(packet));
748        Ok(())
749    }
750
751    /// Add a packet to the current repacketizer state, moving it.
752    #[inline]
753    pub fn cat_move<'b2>(self, packet: &'b2 [u8]) -> Result<RepacketizerState<'rp, 'b2>> where 'buf: 'b2 {
754        let mut shorter = self;
755        shorter.cat(packet)?;
756        Ok(shorter)
757    }
758
759    /// Get the total number of frames contained in packet data submitted so
760    /// far via `cat`.
761    pub fn get_nb_frames(&mut self) -> usize {
762        unsafe { ffi::opus_repacketizer_get_nb_frames(self.rp.ptr) as usize }
763    }
764
765    /// Construct a new packet from data previously submitted via `cat`.
766    ///
767    /// All previously submitted frames are used.
768    pub fn out(&mut self, buffer: &mut [u8]) -> Result<usize> {
769        let result = ffi!(opus_repacketizer_out, self.rp.ptr,
770			buffer.as_mut_ptr(), len(buffer));
771        Ok(result as usize)
772    }
773
774    /// Construct a new packet from data previously submitted via `cat`, with
775    /// a manually specified subrange.
776    ///
777    /// The `end` index should not exceed the value of `get_nb_frames()`.
778    pub fn out_range(&mut self, begin: usize, end: usize, buffer: &mut [u8]) -> Result<usize> {
779        let result = ffi!(opus_repacketizer_out_range, self.rp.ptr,
780			check_len(begin), check_len(end),
781			buffer.as_mut_ptr(), len(buffer));
782        Ok(result as usize)
783    }
784}
785
786// ============================================================================
787// TODO: Multistream API
788
789// ============================================================================
790// Error Handling
791
792/// Opus error Result alias.
793pub type Result<T> = std::result::Result<T, Error>;
794
795/// An error generated by the Opus library.
796#[derive(Debug)]
797pub struct Error {
798    function: &'static str,
799    code: ErrorCode,
800}
801
802impl Error {
803    fn bad_arg(what: &'static str) -> Error {
804        Error { function: what, code: ErrorCode::BadArg }
805    }
806
807    fn from_code(what: &'static str, code: c_int) -> Error {
808        Error { function: what, code: ErrorCode::from_int(code) }
809    }
810
811    /// Get the name of the Opus function from which the error originated.
812    #[inline]
813    pub fn function(&self) -> &'static str { self.function }
814
815    /// Get a textual description of the error provided by Opus.
816    #[inline]
817    pub fn description(&self) -> &'static str { self.code.description() }
818
819    /// Get the Opus error code of the error.
820    #[inline]
821    pub fn code(&self) -> ErrorCode { self.code }
822}
823
824impl std::fmt::Display for Error {
825    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
826        write!(f, "{}: {}", self.function, self.description())
827    }
828}
829
830impl std::error::Error for Error {
831    fn description(&self) -> &str {
832        self.code.description()
833    }
834}
835
836fn check_len(val: usize) -> c_int {
837    let len = val as c_int;
838    if len as usize != val {
839        panic!("length out of range: {}", val);
840    }
841    len
842}
843
844#[inline]
845fn len<T>(slice: &[T]) -> c_int {
846    check_len(slice.len())
847}