opus/
lib.rs

1// Copyright 2016 Tad Hardesty
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](https://opus-codec.org/).
10//!
11//! Only brief descriptions are included here. For detailed information, consult
12//! the [libopus documentation](https://opus-codec.org/docs/opus_api-1.5/).
13#![warn(missing_docs)]
14
15extern crate audiopus_sys as ffi;
16
17use std::convert::TryFrom;
18use std::ffi::CStr;
19use std::marker::PhantomData;
20use std::os::raw::c_int;
21
22// ============================================================================
23// Constants
24
25/// The possible applications for the codec.
26#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
27#[repr(i32)]
28pub enum Application {
29	/// Best for most VoIP/videoconference applications where listening quality
30	/// and intelligibility matter most.
31	Voip = ffi::OPUS_APPLICATION_VOIP,
32	/// Best for broadcast/high-fidelity application where the decoded audio
33	/// should be as close as possible to the input.
34	Audio = ffi::OPUS_APPLICATION_AUDIO,
35	/// Only use when lowest-achievable latency is what matters most.
36	LowDelay = ffi::OPUS_APPLICATION_RESTRICTED_LOWDELAY,
37}
38
39impl Application {
40	fn from_raw(raw: i32, what: &'static str) -> Result<Application> {
41		match raw {
42			ffi::OPUS_APPLICATION_VOIP => Ok(Application::Voip),
43			ffi::OPUS_APPLICATION_AUDIO => Ok(Application::Audio),
44			ffi::OPUS_APPLICATION_RESTRICTED_LOWDELAY => Ok(Application::LowDelay),
45			_ => Err(Error::bad_arg(what)),
46		}
47	}
48}
49
50/// The available channel setings.
51#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
52pub enum Channels {
53	/// One channel.
54	Mono = 1,
55	/// Two channels, left and right.
56	Stereo = 2,
57}
58
59/// The available bandwidth level settings.
60#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
61#[repr(i32)]
62#[derive(Default)]
63pub enum Bandwidth {
64	/// Auto/default setting.
65	#[default]
66	Auto = ffi::OPUS_AUTO,
67	/// 4kHz bandpass.
68	Narrowband = ffi::OPUS_BANDWIDTH_NARROWBAND,
69	/// 6kHz bandpass.
70	Mediumband = ffi::OPUS_BANDWIDTH_MEDIUMBAND,
71	/// 8kHz bandpass.
72	Wideband = ffi::OPUS_BANDWIDTH_WIDEBAND,
73	/// 12kHz bandpass.
74	Superwideband = ffi::OPUS_BANDWIDTH_SUPERWIDEBAND,
75	/// 20kHz bandpass.
76	Fullband = ffi::OPUS_BANDWIDTH_FULLBAND,
77}
78
79impl Bandwidth {
80	fn from_int(value: i32) -> Option<Bandwidth> {
81		Some(match value {
82			ffi::OPUS_AUTO => Bandwidth::Auto,
83			ffi::OPUS_BANDWIDTH_NARROWBAND => Bandwidth::Narrowband,
84			ffi::OPUS_BANDWIDTH_MEDIUMBAND => Bandwidth::Mediumband,
85			ffi::OPUS_BANDWIDTH_WIDEBAND => Bandwidth::Wideband,
86			ffi::OPUS_BANDWIDTH_SUPERWIDEBAND => Bandwidth::Superwideband,
87			ffi::OPUS_BANDWIDTH_FULLBAND => Bandwidth::Fullband,
88			_ => return None,
89		})
90	}
91
92	fn decode(value: i32, what: &'static str) -> Result<Bandwidth> {
93		match Bandwidth::from_int(value) {
94			Some(bandwidth) => Ok(bandwidth),
95			None => Err(Error::bad_arg(what)),
96		}
97	}
98
99	fn raw(self) -> i32 {
100		self as i32
101	}
102}
103
104/// Possible error codes.
105#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
106#[repr(i32)]
107pub enum ErrorCode {
108	/// One or more invalid/out of range arguments.
109	BadArg = ffi::OPUS_BAD_ARG,
110	/// Not enough bytes allocated in the buffer.
111	BufferTooSmall = ffi::OPUS_BUFFER_TOO_SMALL,
112	/// An internal error was detected.
113	InternalError = ffi::OPUS_INTERNAL_ERROR,
114	/// The compressed data passed is corrupted.
115	InvalidPacket = ffi::OPUS_INVALID_PACKET,
116	/// Invalid/unsupported request number.
117	Unimplemented = ffi::OPUS_UNIMPLEMENTED,
118	/// An encoder or decoder structure is invalid or already freed.
119	InvalidState = ffi::OPUS_INVALID_STATE,
120	/// Memory allocation has failed.
121	AllocFail = ffi::OPUS_ALLOC_FAIL,
122	/// An unknown failure.
123	Unknown = -8,
124}
125
126impl ErrorCode {
127	fn from_int(value: c_int) -> ErrorCode {
128		use ErrorCode::*;
129		match value {
130			ffi::OPUS_BAD_ARG => BadArg,
131			ffi::OPUS_BUFFER_TOO_SMALL => BufferTooSmall,
132			ffi::OPUS_INTERNAL_ERROR => InternalError,
133			ffi::OPUS_INVALID_PACKET => InvalidPacket,
134			ffi::OPUS_UNIMPLEMENTED => Unimplemented,
135			ffi::OPUS_INVALID_STATE => InvalidState,
136			ffi::OPUS_ALLOC_FAIL => AllocFail,
137			_ => Unknown,
138		}
139	}
140
141	/// Get a human-readable error string for this error code.
142	pub fn description(self) -> &'static str {
143		// should always be ASCII and non-null for any input
144		unsafe { CStr::from_ptr(ffi::opus_strerror(self as c_int)) }.to_str().unwrap()
145	}
146}
147
148/// Possible bitrates.
149#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
150pub enum Bitrate {
151	/// Explicit bitrate choice (in bits/second).
152	Bits(i32),
153	/// Maximum bitrate allowed (up to maximum number of bytes for the packet).
154	Max,
155	/// Default bitrate decided by the encoder (not recommended).
156	Auto,
157}
158
159impl Bitrate {
160	fn from_raw(raw: c_int) -> Result<Bitrate> {
161		Ok(match raw {
162			ffi::OPUS_AUTO => Bitrate::Auto,
163			ffi::OPUS_BITRATE_MAX => Bitrate::Max,
164			_ => Bitrate::Bits(raw),
165		})
166	}
167
168	fn raw(self) -> c_int {
169		match self {
170			Bitrate::Auto => ffi::OPUS_AUTO,
171			Bitrate::Max => ffi::OPUS_BITRATE_MAX,
172			Bitrate::Bits(raw) => raw,
173		}
174	}
175}
176
177/// Possible signal types. Hints for the encoder's mode selection.
178#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
179#[repr(i32)]
180#[derive(Default)]
181pub enum Signal {
182	/// Auto/default setting.
183	#[default]
184	Auto = ffi::OPUS_AUTO,
185	/// Bias thresholds towards choosing LPC or Hybrid modes.
186	Voice = ffi::OPUS_SIGNAL_VOICE,
187	/// Bias thresholds towards choosing MDCT modes.
188	Music = ffi::OPUS_SIGNAL_MUSIC,
189}
190
191impl Signal {
192	fn from_raw(raw: i32, what: &'static str) -> Result<Signal> {
193		match raw {
194			ffi::OPUS_AUTO => Ok(Signal::Auto),
195			ffi::OPUS_SIGNAL_VOICE => Ok(Signal::Voice),
196			ffi::OPUS_SIGNAL_MUSIC => Ok(Signal::Music),
197			_ => Err(Error::bad_arg(what)),
198		}
199	}
200
201	fn raw(self) -> i32 {
202		self as i32
203	}
204}
205
206/// Possible frame sizes. Controls encoder's use of variable duration frames.
207#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
208#[repr(i32)]
209#[derive(Default)]
210pub enum FrameSize {
211	/// Select frame size from the argument (default).
212	#[default]
213	Arg = ffi::OPUS_FRAMESIZE_ARG,
214	/// Use 2.5 ms frames.
215	Ms2_5 = ffi::OPUS_FRAMESIZE_2_5_MS,
216	/// Use 5 ms frames.
217	Ms5 = ffi::OPUS_FRAMESIZE_5_MS,
218	/// Use 10 ms frames.
219	Ms10 = ffi::OPUS_FRAMESIZE_10_MS,
220	/// Use 20 ms frames.
221	Ms20 = ffi::OPUS_FRAMESIZE_20_MS,
222	/// Use 40 ms frames.
223	Ms40 = ffi::OPUS_FRAMESIZE_40_MS,
224	/// Use 60 ms frames.
225	Ms60 = ffi::OPUS_FRAMESIZE_60_MS,
226	/// Use 80 ms frames.
227	Ms80 = ffi::OPUS_FRAMESIZE_80_MS,
228	/// Use 100 ms frames.
229	Ms100 = ffi::OPUS_FRAMESIZE_100_MS,
230	/// Use 120 ms frames.
231	Ms120 = ffi::OPUS_FRAMESIZE_120_MS,
232}
233
234impl FrameSize {
235	fn from_raw(raw: i32, what: &'static str) -> Result<FrameSize> {
236		match raw {
237			ffi::OPUS_FRAMESIZE_ARG => Ok(FrameSize::Arg),
238			ffi::OPUS_FRAMESIZE_2_5_MS => Ok(FrameSize::Ms2_5),
239			ffi::OPUS_FRAMESIZE_5_MS => Ok(FrameSize::Ms5),
240			ffi::OPUS_FRAMESIZE_10_MS => Ok(FrameSize::Ms10),
241			ffi::OPUS_FRAMESIZE_20_MS => Ok(FrameSize::Ms20),
242			ffi::OPUS_FRAMESIZE_40_MS => Ok(FrameSize::Ms40),
243			ffi::OPUS_FRAMESIZE_60_MS => Ok(FrameSize::Ms60),
244			ffi::OPUS_FRAMESIZE_80_MS => Ok(FrameSize::Ms80),
245			ffi::OPUS_FRAMESIZE_100_MS => Ok(FrameSize::Ms100),
246			ffi::OPUS_FRAMESIZE_120_MS => Ok(FrameSize::Ms120),
247			_ => Err(Error::bad_arg(what)),
248		}
249	}
250
251	fn raw(self) -> i32 {
252		self as i32
253	}
254}
255
256/// Get the libopus version string.
257///
258/// Applications may look for the substring "-fixed" in the version string to
259/// determine whether they have a fixed-point or floating-point build at
260/// runtime.
261pub fn version() -> &'static str {
262	// verison string should always be ASCII
263	unsafe { CStr::from_ptr(ffi::opus_get_version_string()) }.to_str().unwrap()
264}
265
266macro_rules! ffi {
267	($f:ident $(, $rest:expr)*) => {
268		match unsafe { ffi::$f($($rest),*) } {
269			code if code < 0 => return Err(Error::from_code(stringify!($f), code)),
270			code => code,
271		}
272	}
273}
274
275// ============================================================================
276// Generic CTLs
277
278macro_rules! ctl {
279	($f:ident, $this:ident, $ctl:path $(, $rest:expr)*) => {
280		match unsafe { ffi::$f($this.ptr, $ctl $(, $rest)*) } {
281			code if code < 0 => return Err(Error::from_code(
282				concat!(stringify!($f), "(", stringify!($ctl), ")"),
283				code,
284			)),
285			_ => (),
286		}
287	}
288}
289
290macro_rules! generic_ctls {
291	($t:ty, $fn:ident) => {
292		/// Generic CTLs. See [Opus docs](https://opus-codec.org/docs/opus_api-1.5/group__opus__genericctls.html).
293		impl $t {
294			/// Reset the codec state to be equivalent to a freshly initialized state.
295			pub fn reset_state(&mut self) -> Result<()> {
296				ctl!($fn, self, ffi::OPUS_RESET_STATE);
297				Ok(())
298			}
299
300			/// Get the final range of the codec's entropy coder.
301			pub fn get_final_range(&mut self) -> Result<u32> {
302				let mut value: u32 = 0;
303				ctl!($fn, self, ffi::OPUS_GET_FINAL_RANGE_REQUEST, &mut value);
304				Ok(value)
305			}
306
307			/// Get the encoder's configured bandpass.
308			pub fn get_bandwidth(&mut self) -> Result<Bandwidth> {
309				let mut value: i32 = 0;
310				ctl!($fn, self, ffi::OPUS_GET_BANDWIDTH_REQUEST, &mut value);
311				Bandwidth::decode(value, concat!(stringify!($fn), "(OPUS_GET_BANDWIDTH)"))
312			}
313
314			/// Get the samping rate the encoder was intialized with.
315			pub fn get_sample_rate(&mut self) -> Result<u32> {
316				let mut value: i32 = 0;
317				ctl!($fn, self, ffi::OPUS_GET_SAMPLE_RATE_REQUEST, &mut value);
318				Ok(value as u32)
319			}
320
321			/// If set to true, disables the use of phase inversion for intensity stereo.
322			pub fn set_phase_inversion_disabled(&mut self, disabled: bool) -> Result<()> {
323				let value: i32 = if disabled { 1 } else { 0 };
324				ctl!($fn, self, ffi::OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST, value);
325				Ok(())
326			}
327
328			/// Get the encoder's configured phase inversion status.
329			pub fn get_phase_inversion_disabled(&mut self) -> Result<bool> {
330				let mut value: i32 = 0;
331				ctl!($fn, self, ffi::OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST, &mut value);
332				Ok(value != 0)
333			}
334
335			/// Get the DTX state of the encoder.
336			pub fn get_in_dtx(&mut self) -> Result<bool> {
337				let mut value: i32 = 0;
338				ctl!($fn, self, ffi::OPUS_GET_IN_DTX_REQUEST, &mut value);
339				Ok(value != 0)
340			}
341		}
342	};
343}
344
345// ============================================================================
346// Encoder
347
348/// An Opus encoder with associated state.
349#[derive(Debug)]
350pub struct Encoder {
351	ptr: *mut ffi::OpusEncoder,
352	channels: Channels,
353}
354
355impl Drop for Encoder {
356	fn drop(&mut self) {
357		unsafe { ffi::opus_encoder_destroy(self.ptr) }
358	}
359}
360
361// "A single codec state may only be accessed from a single thread at
362// a time and any required locking must be performed by the caller. Separate
363// streams must be decoded with separate decoder states and can be decoded
364// in parallel unless the library was compiled with NONTHREADSAFE_PSEUDOSTACK
365// defined."
366//
367// In other words, opus states may be moved between threads at will. A special
368// compilation mode intended for embedded platforms forbids multithreaded use
369// of the library as a whole rather than on a per-state basis, but the opus-sys
370// crate does not use this mode.
371unsafe impl Send for Encoder {}
372
373impl Encoder {
374	/// Create and initialize an encoder.
375	pub fn new(sample_rate: u32, channels: Channels, mode: Application) -> Result<Encoder> {
376		let mut error = 0;
377		let ptr = unsafe {
378			ffi::opus_encoder_create(
379				sample_rate as i32,
380				channels as c_int,
381				mode as c_int,
382				&mut error,
383			)
384		};
385		if error != ffi::OPUS_OK || ptr.is_null() {
386			Err(Error::from_code("opus_encoder_create", error))
387		} else {
388			Ok(Encoder { ptr, channels })
389		}
390	}
391
392	/// Encode an Opus frame.
393	pub fn encode(&mut self, input: &[i16], output: &mut [u8]) -> Result<usize> {
394		let len = ffi!(
395			opus_encode,
396			self.ptr,
397			input.as_ptr(),
398			len(input) / self.channels as c_int,
399			output.as_mut_ptr(),
400			len(output)
401		);
402		Ok(len as usize)
403	}
404
405	/// Encode an Opus frame from floating point input.
406	pub fn encode_float(&mut self, input: &[f32], output: &mut [u8]) -> Result<usize> {
407		let len = ffi!(
408			opus_encode_float,
409			self.ptr,
410			input.as_ptr(),
411			len(input) / self.channels as c_int,
412			output.as_mut_ptr(),
413			len(output)
414		);
415		Ok(len as usize)
416	}
417
418	/// Encode an Opus frame to a new buffer.
419	pub fn encode_vec(&mut self, input: &[i16], max_size: usize) -> Result<Vec<u8>> {
420		let mut output: Vec<u8> = vec![0; max_size];
421		let result = self.encode(input, output.as_mut_slice())?;
422		output.truncate(result);
423		Ok(output)
424	}
425
426	/// Encode an Opus frame from floating point input to a new buffer.
427	pub fn encode_vec_float(&mut self, input: &[f32], max_size: usize) -> Result<Vec<u8>> {
428		let mut output: Vec<u8> = vec![0; max_size];
429		let result = self.encode_float(input, output.as_mut_slice())?;
430		output.truncate(result);
431		Ok(output)
432	}
433}
434
435macro_rules! encoder_ctls {
436	($t:ty, $fn:ident) => {
437		/// Encoder CTLs. See [Opus docs](https://opus-codec.org/docs/opus_api-1.5/group__opus__encoderctls.html).
438		impl $t {
439			/// Configures the encoder's computational complexity.
440			pub fn set_complexity(&mut self, value: i32) -> Result<()> {
441				ctl!($fn, self, ffi::OPUS_SET_COMPLEXITY_REQUEST, value);
442				Ok(())
443			}
444
445			/// Gets the encoder's complexity configuration.
446			pub fn get_complexity(&mut self) -> Result<i32> {
447				let mut value: i32 = 0;
448				ctl!($fn, self, ffi::OPUS_GET_COMPLEXITY_REQUEST, &mut value);
449				Ok(value)
450			}
451
452			/// Set the encoder's bitrate.
453			pub fn set_bitrate(&mut self, value: Bitrate) -> Result<()> {
454				ctl!($fn, self, ffi::OPUS_SET_BITRATE_REQUEST, value.raw());
455				Ok(())
456			}
457
458			/// Get the encoder's bitrate.
459			pub fn get_bitrate(&mut self) -> Result<Bitrate> {
460				let mut value: i32 = 0;
461				ctl!($fn, self, ffi::OPUS_GET_BITRATE_REQUEST, &mut value);
462				Bitrate::from_raw(value)
463			}
464
465			/// Enable or disable variable bitrate.
466			pub fn set_vbr(&mut self, vbr: bool) -> Result<()> {
467				let value: i32 = if vbr { 1 } else { 0 };
468				ctl!($fn, self, ffi::OPUS_SET_VBR_REQUEST, value);
469				Ok(())
470			}
471
472			/// Determine if variable bitrate is enabled.
473			pub fn get_vbr(&mut self) -> Result<bool> {
474				let mut value: i32 = 0;
475				ctl!($fn, self, ffi::OPUS_GET_VBR_REQUEST, &mut value);
476				Ok(value != 0)
477			}
478
479			/// Enable or disable constrained VBR.
480			pub fn set_vbr_constraint(&mut self, vbr: bool) -> Result<()> {
481				let value: i32 = if vbr { 1 } else { 0 };
482				ctl!($fn, self, ffi::OPUS_SET_VBR_CONSTRAINT_REQUEST, value);
483				Ok(())
484			}
485
486			/// Determine if constrained VBR is enabled.
487			pub fn get_vbr_constraint(&mut self) -> Result<bool> {
488				let mut value: i32 = 0;
489				ctl!($fn, self, ffi::OPUS_GET_VBR_CONSTRAINT_REQUEST, &mut value);
490				Ok(value != 0)
491			}
492
493			/// Configures mono/stereo forcing in the encoder.
494			///
495			/// This can force the encoder to produce packets encoded as either mono or
496			/// stereo, regardless of the format of the input audio. This is useful
497			/// when the caller knows that the input signal is currently a mono source
498			/// embedded in a stereo stream.
499			pub fn set_force_channels(&mut self, value: Option<Channels>) -> Result<()> {
500				let value: i32 = match value {
501					None => ffi::OPUS_AUTO,
502					Some(Channels::Mono) => 1,
503					Some(Channels::Stereo) => 2,
504				};
505				ctl!($fn, self, ffi::OPUS_SET_FORCE_CHANNELS_REQUEST, value);
506				Ok(())
507			}
508
509			/// Gets the encoder's forced channel configuration.
510			pub fn get_force_channels(&mut self) -> Result<Option<Channels>> {
511				let mut value: i32 = 0;
512				ctl!($fn, self, ffi::OPUS_GET_FORCE_CHANNELS_REQUEST, &mut value);
513				match value {
514					ffi::OPUS_AUTO => Ok(None),
515					1 => Ok(Some(Channels::Mono)),
516					2 => Ok(Some(Channels::Stereo)),
517					_ => Err(Error::bad_arg(concat!(stringify!($fn), "(OPUS_GET_FORCE_CHANNELS)"))),
518				}
519			}
520
521			/// Configure the maximum bandpass that the encoder will select automatically.
522			pub fn set_max_bandwidth(&mut self, bandwidth: Bandwidth) -> Result<()> {
523				let value: i32 = bandwidth.raw();
524				ctl!($fn, self, ffi::OPUS_SET_MAX_BANDWIDTH_REQUEST, value);
525				Ok(())
526			}
527
528			/// Get the encoder's configured maximum allowed bandpass.
529			pub fn get_max_bandwidth(&mut self) -> Result<Bandwidth> {
530				let mut value: i32 = 0;
531				ctl!($fn, self, ffi::OPUS_GET_MAX_BANDWIDTH_REQUEST, &mut value);
532				Bandwidth::decode(value, concat!(stringify!($fn), "(OPUS_GET_MAX_BANDWIDTH)"))
533			}
534
535			/// Set the encoder's bandpass to a specific value.
536			pub fn set_bandwidth(&mut self, bandwidth: Bandwidth) -> Result<()> {
537				let value: i32 = bandwidth.raw();
538				ctl!($fn, self, ffi::OPUS_SET_BANDWIDTH_REQUEST, value);
539				Ok(())
540			}
541
542			/// Configure the type of signal being encoded.
543			pub fn set_signal(&mut self, signal: Signal) -> Result<()> {
544				let value: i32 = signal.raw();
545				ctl!($fn, self, ffi::OPUS_SET_SIGNAL_REQUEST, value);
546				Ok(())
547			}
548
549			/// Gets the encoder's configured signal type.
550			pub fn get_signal(&mut self) -> Result<Signal> {
551				let mut value: i32 = 0;
552				ctl!($fn, self, ffi::OPUS_GET_SIGNAL_REQUEST, &mut value);
553				Signal::from_raw(value, concat!(stringify!($fn), "(OPUS_GET_SIGNAL)"))
554			}
555
556			/// Configure the encoder's intended application.
557			pub fn set_application(&mut self, application: Application) -> Result<()> {
558				let value: i32 = application as i32;
559				ctl!($fn, self, ffi::OPUS_SET_APPLICATION_REQUEST, value);
560				Ok(())
561			}
562
563			/// Get the encoder's configured application.
564			pub fn get_application(&mut self) -> Result<Application> {
565				let mut value: i32 = 0;
566				ctl!($fn, self, ffi::OPUS_GET_APPLICATION_REQUEST, &mut value);
567				Application::from_raw(value, concat!(stringify!($fn), "(OPUS_GET_APPLICATION)"))
568			}
569
570			/// Gets the total samples of delay added by the entire codec.
571			pub fn get_lookahead(&mut self) -> Result<i32> {
572				let mut value: i32 = 0;
573				ctl!($fn, self, ffi::OPUS_GET_LOOKAHEAD_REQUEST, &mut value);
574				Ok(value)
575			}
576
577			/// Configures the encoder's use of inband forward error correction (FEC).
578			pub fn set_inband_fec(&mut self, value: bool) -> Result<()> {
579				let value: i32 = if value { 1 } else { 0 };
580				ctl!($fn, self, ffi::OPUS_SET_INBAND_FEC_REQUEST, value);
581				Ok(())
582			}
583
584			/// Gets encoder's configured use of inband forward error correction.
585			pub fn get_inband_fec(&mut self) -> Result<bool> {
586				let mut value: i32 = 0;
587				ctl!($fn, self, ffi::OPUS_GET_INBAND_FEC_REQUEST, &mut value);
588				Ok(value != 0)
589			}
590
591			/// Sets the encoder's expected packet loss percentage.
592			pub fn set_packet_loss_perc(&mut self, value: i32) -> Result<()> {
593				ctl!($fn, self, ffi::OPUS_SET_PACKET_LOSS_PERC_REQUEST, value);
594				Ok(())
595			}
596
597			/// Gets the encoder's expected packet loss percentage.
598			pub fn get_packet_loss_perc(&mut self) -> Result<i32> {
599				let mut value: i32 = 0;
600				ctl!($fn, self, ffi::OPUS_GET_PACKET_LOSS_PERC_REQUEST, &mut value);
601				Ok(value)
602			}
603
604			/// Configures the encoder's use of discontinuous transmission (DTX).
605			pub fn set_dtx(&mut self, value: bool) -> Result<()> {
606				let value: i32 = if value { 1 } else { 0 };
607				ctl!($fn, self, ffi::OPUS_SET_DTX_REQUEST, value);
608				Ok(())
609			}
610
611			/// Gets encoder's configured use of discontinuous transmission (DTX).
612			pub fn get_dtx(&mut self) -> Result<bool> {
613				let mut value: i32 = 0;
614				ctl!($fn, self, ffi::OPUS_GET_DTX_REQUEST, &mut value);
615				Ok(value != 0)
616			}
617
618			/// Configures the depth of signal being encoded.
619			///
620			/// Depth should be between 8 and 24 inclusive.
621			pub fn set_lsb_depth(&mut self, depth: i32) -> Result<()> {
622				ctl!($fn, self, ffi::OPUS_SET_LSB_DEPTH_REQUEST, depth);
623				Ok(())
624			}
625
626			/// Gets the encoder's configured signal depth.
627			pub fn get_lsb_depth(&mut self) -> Result<i32> {
628				let mut value: i32 = 0;
629				ctl!($fn, self, ffi::OPUS_GET_LSB_DEPTH_REQUEST, &mut value);
630				Ok(value)
631			}
632
633			/// Configures the encoder's use of variable duration frames.
634			///
635			/// Do not use this option unless you **really** know what you are doing.
636			pub fn set_expert_frame_duration(&mut self, framesize: FrameSize) -> Result<()> {
637				let value: i32 = framesize.raw();
638				ctl!($fn, self, ffi::OPUS_SET_EXPERT_FRAME_DURATION_REQUEST, value);
639				Ok(())
640			}
641
642			/// Gets the encoder's configured use of variable duration frames.
643			pub fn get_expert_frame_duration(&mut self) -> Result<FrameSize> {
644				let mut value: i32 = 0;
645				ctl!($fn, self, ffi::OPUS_GET_EXPERT_FRAME_DURATION_REQUEST, &mut value);
646				FrameSize::from_raw(
647					value,
648					concat!(stringify!($fn), "(OPUS_GET_EXPERT_FRAME_DURATION)"),
649				)
650			}
651
652			/// If set to true, disables almost all use of prediction, making frames almost completely independent.
653			pub fn set_prediction_disabled(&mut self, disabled: bool) -> Result<()> {
654				let value: i32 = if disabled { 1 } else { 0 };
655				ctl!($fn, self, ffi::OPUS_SET_PREDICTION_DISABLED_REQUEST, value);
656				Ok(())
657			}
658
659			/// Gets the encoder's configured prediction status.
660			pub fn get_prediction_disabled(&mut self) -> Result<bool> {
661				let mut value: i32 = 0;
662				ctl!($fn, self, ffi::OPUS_GET_PREDICTION_DISABLED_REQUEST, &mut value);
663				Ok(value != 0)
664			}
665
666			// TODO(#5): OPUS_SET/GET_DRED_DURATION (since Opus 1.5)
667			// TODO(#5): OPUS_SET_DNN_BLOB (since Opus 1.5)
668		}
669	};
670}
671
672generic_ctls!(Encoder, opus_encoder_ctl);
673encoder_ctls!(Encoder, opus_encoder_ctl);
674
675// ============================================================================
676// Decoder
677
678/// An Opus decoder with associated state.
679#[derive(Debug)]
680pub struct Decoder {
681	ptr: *mut ffi::OpusDecoder,
682	channels: Channels,
683}
684
685impl Drop for Decoder {
686	fn drop(&mut self) {
687		unsafe { ffi::opus_decoder_destroy(self.ptr) }
688	}
689}
690
691// See `unsafe impl Send for Encoder`.
692unsafe impl Send for Decoder {}
693
694impl Decoder {
695	/// Create and initialize a decoder.
696	pub fn new(sample_rate: u32, channels: Channels) -> Result<Decoder> {
697		let mut error = 0;
698		let ptr =
699			unsafe { ffi::opus_decoder_create(sample_rate as i32, channels as c_int, &mut error) };
700		if error != ffi::OPUS_OK || ptr.is_null() {
701			Err(Error::from_code("opus_decoder_create", error))
702		} else {
703			Ok(Decoder { ptr, channels })
704		}
705	}
706
707	/// Decode an Opus packet.
708	///
709	/// To represent packet loss, pass an empty slice `&[]`.
710	///
711	/// The return value is the number of samples *per channel* decoded from
712	/// the packet.
713	pub fn decode(&mut self, input: &[u8], output: &mut [i16], fec: bool) -> Result<usize> {
714		let ptr = match input.len() {
715			0 => std::ptr::null(),
716			_ => input.as_ptr(),
717		};
718		let len = ffi!(
719			opus_decode,
720			self.ptr,
721			ptr,
722			len(input),
723			output.as_mut_ptr(),
724			len(output) / self.channels as c_int,
725			fec as c_int
726		);
727		Ok(len as usize)
728	}
729
730	/// Decode an Opus packet with floating point output.
731	///
732	/// To represent packet loss, pass an empty slice `&[]`.
733	///
734	/// The return value is the number of samples *per channel* decoded from
735	/// the packet.
736	pub fn decode_float(&mut self, input: &[u8], output: &mut [f32], fec: bool) -> Result<usize> {
737		let ptr = match input.len() {
738			0 => std::ptr::null(),
739			_ => input.as_ptr(),
740		};
741		let len = ffi!(
742			opus_decode_float,
743			self.ptr,
744			ptr,
745			len(input),
746			output.as_mut_ptr(),
747			len(output) / self.channels as c_int,
748			fec as c_int
749		);
750		Ok(len as usize)
751	}
752
753	/// Get the number of samples *per channel* of an Opus packet.
754	pub fn get_nb_samples(&self, packet: &[u8]) -> Result<usize> {
755		let len = ffi!(opus_decoder_get_nb_samples, self.ptr, packet.as_ptr(), packet.len() as i32);
756		Ok(len as usize)
757	}
758}
759
760macro_rules! decoder_ctls {
761	($t:ty, $fn:ident) => {
762		/// Decoder CTLs. See [Opus docs](https://opus-codec.org/docs/opus_api-1.5/group__opus__decoderctls.html).
763		impl $t {
764			/// Configures decoder gain adjustment.
765			///
766			/// Scales the decoded output by a factor specified in Q8 dB units. This has
767			/// a maximum range of -32768 to 32768 inclusive, and returns `BadArg`
768			/// otherwise. The default is zero indicating no adjustment. This setting
769			/// survives decoder reset.
770			///
771			/// `gain = pow(10, x / (20.0 * 256))`
772			pub fn set_gain(&mut self, gain: i32) -> Result<()> {
773				ctl!($fn, self, ffi::OPUS_SET_GAIN_REQUEST, gain);
774				Ok(())
775			}
776
777			/// Gets the decoder's configured gain adjustment.
778			pub fn get_gain(&mut self) -> Result<i32> {
779				let mut value: i32 = 0;
780				ctl!($fn, self, ffi::OPUS_GET_GAIN_REQUEST, &mut value);
781				Ok(value)
782			}
783
784			/// Gets the duration (in samples) of the last packet successfully decoded
785			/// or concealed.
786			pub fn get_last_packet_duration(&mut self) -> Result<u32> {
787				let mut value: i32 = 0;
788				ctl!($fn, self, ffi::OPUS_GET_LAST_PACKET_DURATION_REQUEST, &mut value);
789				Ok(value as u32)
790			}
791
792			/// Gets the pitch of the last decoded frame, if available.
793			///
794			/// This can be used for any post-processing algorithm requiring the use of
795			/// pitch, e.g. time stretching/shortening. If the last frame was not
796			/// voiced, or if the pitch was not coded in the frame, then zero is
797			/// returned.
798			pub fn get_pitch(&mut self) -> Result<i32> {
799				let mut value: i32 = 0;
800				ctl!($fn, self, ffi::OPUS_GET_PITCH_REQUEST, &mut value);
801				Ok(value)
802			}
803		}
804	};
805}
806
807generic_ctls!(Decoder, opus_decoder_ctl);
808decoder_ctls!(Decoder, opus_decoder_ctl);
809
810// ============================================================================
811// Packet Analysis
812
813/// Analyze raw Opus packets.
814pub mod packet {
815	use super::ffi;
816	use super::*;
817	use std::{ptr, slice};
818
819	/// Get the bandwidth of an Opus packet.
820	pub fn get_bandwidth(packet: &[u8]) -> Result<Bandwidth> {
821		if packet.is_empty() {
822			return Err(Error::bad_arg("opus_packet_get_bandwidth"));
823		}
824		let bandwidth = ffi!(opus_packet_get_bandwidth, packet.as_ptr());
825		Bandwidth::decode(bandwidth, "opus_packet_get_bandwidth")
826	}
827
828	/// Get the number of channels from an Opus packet.
829	pub fn get_nb_channels(packet: &[u8]) -> Result<Channels> {
830		if packet.is_empty() {
831			return Err(Error::bad_arg("opus_packet_get_nb_channels"));
832		}
833		let channels = ffi!(opus_packet_get_nb_channels, packet.as_ptr());
834		match channels {
835			1 => Ok(Channels::Mono),
836			2 => Ok(Channels::Stereo),
837			_ => Err(Error::bad_arg("opus_packet_get_nb_channels")),
838		}
839	}
840
841	/// Get the number of frames in an Opus packet.
842	pub fn get_nb_frames(packet: &[u8]) -> Result<usize> {
843		let frames = ffi!(opus_packet_get_nb_frames, packet.as_ptr(), len(packet));
844		Ok(frames as usize)
845	}
846
847	/// Get the number of samples of an Opus packet.
848	pub fn get_nb_samples(packet: &[u8], sample_rate: u32) -> Result<usize> {
849		let frames =
850			ffi!(opus_packet_get_nb_samples, packet.as_ptr(), len(packet), sample_rate as c_int);
851		Ok(frames as usize)
852	}
853
854	/// Get the number of samples per frame from an Opus packet.
855	pub fn get_samples_per_frame(packet: &[u8], sample_rate: u32) -> Result<usize> {
856		if packet.is_empty() {
857			return Err(Error::bad_arg("opus_packet_get_samples_per_frame"));
858		}
859		let samples =
860			ffi!(opus_packet_get_samples_per_frame, packet.as_ptr(), sample_rate as c_int);
861		Ok(samples as usize)
862	}
863
864	/// Parse an Opus packet into one or more frames.
865	pub fn parse(packet: &[u8]) -> Result<Packet<'_>> {
866		let mut toc: u8 = 0;
867		let mut frames = [ptr::null(); 48];
868		let mut sizes = [0i16; 48];
869		let mut payload_offset: i32 = 0;
870		let num_frames = ffi!(
871			opus_packet_parse,
872			packet.as_ptr(),
873			len(packet),
874			&mut toc,
875			frames.as_mut_ptr(),
876			sizes.as_mut_ptr(),
877			&mut payload_offset
878		);
879
880		let mut frames_vec = Vec::with_capacity(num_frames as usize);
881		for i in 0..num_frames as usize {
882			frames_vec.push(unsafe { slice::from_raw_parts(frames[i], sizes[i] as usize) });
883		}
884
885		Ok(Packet {
886			toc,
887			frames: frames_vec,
888			payload_offset: payload_offset as usize,
889		})
890	}
891
892	/// A parsed Opus packet, retuned from `parse`.
893	#[derive(Debug)]
894	pub struct Packet<'a> {
895		/// The TOC byte of the packet.
896		pub toc: u8,
897		/// The frames contained in the packet.
898		pub frames: Vec<&'a [u8]>,
899		/// The offset into the packet at which the payload is located.
900		pub payload_offset: usize,
901	}
902
903	/// Pad a given Opus packet to a larger size.
904	///
905	/// The packet will be extended from the first `prev_len` bytes of the
906	/// buffer into the rest of the available space.
907	pub fn pad(packet: &mut [u8], prev_len: usize) -> Result<usize> {
908		let result = ffi!(opus_packet_pad, packet.as_mut_ptr(), check_len(prev_len), len(packet));
909		Ok(result as usize)
910	}
911
912	/// Remove all padding from a given Opus packet and rewrite the TOC sequence
913	/// to minimize space usage.
914	pub fn unpad(packet: &mut [u8]) -> Result<usize> {
915		let result = ffi!(opus_packet_unpad, packet.as_mut_ptr(), len(packet));
916		Ok(result as usize)
917	}
918
919	/// Pad a given Opus multi-stream packet to a larger size.
920	///
921	/// The packet will be extended from the first `prev_len` bytes of the
922	/// buffer into the rest of the available space.
923	pub fn multistream_pad(packet: &mut [u8], prev_len: usize, nb_streams: u8) -> Result<usize> {
924		let result = ffi!(
925			opus_multistream_packet_pad,
926			packet.as_mut_ptr(),
927			check_len(prev_len),
928			len(packet),
929			nb_streams as c_int
930		);
931		Ok(result as usize)
932	}
933
934	/// Remove all padding from a given Opus multi-stream packet and rewrite
935	/// the TOC sequence to minimize space usage.
936	pub fn multistream_unpad(packet: &mut [u8], nb_streams: u8) -> Result<usize> {
937		let result = ffi!(
938			opus_multistream_packet_unpad,
939			packet.as_mut_ptr(),
940			len(packet),
941			nb_streams as c_int
942		);
943		Ok(result as usize)
944	}
945}
946
947// ============================================================================
948// Float Soft Clipping
949
950/// Soft-clipping to bring a float signal within the [-1,1] range.
951#[derive(Debug)]
952pub struct SoftClip {
953	channels: Channels,
954	memory: [f32; 2],
955}
956
957impl SoftClip {
958	/// Initialize a new soft-clipping state.
959	pub fn new(channels: Channels) -> SoftClip {
960		SoftClip { channels, memory: [0.0; 2] }
961	}
962
963	/// Apply soft-clipping to a float signal.
964	pub fn apply(&mut self, signal: &mut [f32]) {
965		unsafe {
966			ffi::opus_pcm_soft_clip(
967				signal.as_mut_ptr(),
968				len(signal) / self.channels as c_int,
969				self.channels as c_int,
970				self.memory.as_mut_ptr(),
971			)
972		};
973	}
974}
975
976// ============================================================================
977// Repacketizer
978
979/// A repacketizer used to merge together or split apart multiple Opus packets.
980#[derive(Debug)]
981pub struct Repacketizer {
982	ptr: *mut ffi::OpusRepacketizer,
983}
984
985impl Drop for Repacketizer {
986	fn drop(&mut self) {
987		unsafe { ffi::opus_repacketizer_destroy(self.ptr) }
988	}
989}
990
991// See `unsafe impl Send for Encoder`.
992unsafe impl Send for Repacketizer {}
993
994impl Repacketizer {
995	/// Create and initialize a repacketizer.
996	pub fn new() -> Result<Repacketizer> {
997		let ptr = unsafe { ffi::opus_repacketizer_create() };
998		if ptr.is_null() {
999			Err(Error::from_code("opus_repacketizer_create", ffi::OPUS_ALLOC_FAIL))
1000		} else {
1001			Ok(Repacketizer { ptr })
1002		}
1003	}
1004
1005	/// Shortcut to combine several smaller packets into one larger one.
1006	pub fn combine(&mut self, input: &[&[u8]], output: &mut [u8]) -> Result<usize> {
1007		let mut state = self.begin();
1008		for &packet in input {
1009			state.cat(packet)?;
1010		}
1011		state.out(output)
1012	}
1013
1014	/// Begin using the repacketizer.
1015	#[allow(clippy::needless_lifetimes)]
1016	pub fn begin<'rp, 'buf>(&'rp mut self) -> RepacketizerState<'rp, 'buf> {
1017		unsafe {
1018			ffi::opus_repacketizer_init(self.ptr);
1019		}
1020		RepacketizerState { ptr: self.ptr, phantom: PhantomData }
1021	}
1022}
1023
1024// To understand why these lifetime bounds are needed, imagine that the
1025// repacketizer keeps an internal Vec<&'buf [u8]>, which is added to by cat()
1026// and accessed by get_nb_frames(), out(), and out_range(). To prove that these
1027// lifetime bounds are correct, a dummy implementation with the same signatures
1028// but a real Vec<&'buf [u8]> rather than unsafe blocks may be substituted.
1029
1030/// An in-progress repacketization.
1031#[derive(Debug)]
1032pub struct RepacketizerState<'rp, 'buf> {
1033	ptr: *mut ffi::OpusRepacketizer,
1034	phantom: PhantomData<(&'rp mut Repacketizer, &'buf [u8])>,
1035}
1036
1037// See `unsafe impl Send for Encoder`.
1038unsafe impl<'rp, 'buf> Send for RepacketizerState<'rp, 'buf> {}
1039
1040impl<'rp, 'buf> RepacketizerState<'rp, 'buf> {
1041	/// Add a packet to the current repacketizer state.
1042	pub fn cat(&mut self, packet: &'buf [u8]) -> Result<()> {
1043		ffi!(opus_repacketizer_cat, self.ptr, packet.as_ptr(), len(packet));
1044		Ok(())
1045	}
1046
1047	/// Add a packet to the current repacketizer state, moving it.
1048	#[inline]
1049	pub fn cat_move<'b2>(self, packet: &'b2 [u8]) -> Result<RepacketizerState<'rp, 'b2>>
1050	where
1051		'buf: 'b2,
1052	{
1053		let mut shorter = self;
1054		shorter.cat(packet)?;
1055		Ok(shorter)
1056	}
1057
1058	/// Get the total number of frames contained in packet data submitted so
1059	/// far via `cat`.
1060	pub fn get_nb_frames(&mut self) -> usize {
1061		unsafe { ffi::opus_repacketizer_get_nb_frames(self.ptr) as usize }
1062	}
1063
1064	/// Construct a new packet from data previously submitted via `cat`.
1065	///
1066	/// All previously submitted frames are used.
1067	pub fn out(&mut self, buffer: &mut [u8]) -> Result<usize> {
1068		let result = ffi!(opus_repacketizer_out, self.ptr, buffer.as_mut_ptr(), len(buffer));
1069		Ok(result as usize)
1070	}
1071
1072	/// Construct a new packet from data previously submitted via `cat`, with
1073	/// a manually specified subrange.
1074	///
1075	/// The `end` index should not exceed the value of `get_nb_frames()`.
1076	pub fn out_range(&mut self, begin: usize, end: usize, buffer: &mut [u8]) -> Result<usize> {
1077		let result = ffi!(
1078			opus_repacketizer_out_range,
1079			self.ptr,
1080			check_len(begin),
1081			check_len(end),
1082			buffer.as_mut_ptr(),
1083			len(buffer)
1084		);
1085		Ok(result as usize)
1086	}
1087}
1088
1089// ============================================================================
1090// Multistream API
1091
1092/// Combine individual Opus streams in a single packet, up to 255 channels.
1093///
1094/// See [Opus docs](https://opus-codec.org/docs/opus_api-1.5/group__opus__multistream.html).
1095#[derive(Debug)]
1096pub struct MSEncoder {
1097	ptr: *mut ffi::OpusMSEncoder,
1098	channels: c_int,
1099}
1100
1101impl Drop for MSEncoder {
1102	fn drop(&mut self) {
1103		unsafe { ffi::opus_multistream_encoder_destroy(self.ptr) }
1104	}
1105}
1106
1107// See `unsafe impl Send for Encoder`.
1108unsafe impl Send for MSEncoder {}
1109
1110impl MSEncoder {
1111	/// Create and initialize a multistream encoder.
1112	pub fn new(
1113		sample_rate: u32,
1114		streams: u8,
1115		coupled_streams: u8,
1116		mapping: &[u8],
1117		application: Application,
1118	) -> Result<MSEncoder> {
1119		let mut error = 0;
1120		let ptr = unsafe {
1121			ffi::opus_multistream_encoder_create(
1122				sample_rate as i32,
1123				len(mapping),
1124				streams as c_int,
1125				coupled_streams as c_int,
1126				mapping.as_ptr(),
1127				application as c_int,
1128				&mut error,
1129			)
1130		};
1131		if error != ffi::OPUS_OK || ptr.is_null() {
1132			Err(Error::from_code("opus_multistream_encoder_create", error))
1133		} else {
1134			Ok(MSEncoder { ptr, channels: len(mapping) })
1135		}
1136	}
1137
1138	// TODO: new_surround -> opus_multistream_encoder_create, but it's missing
1139	// Doxygen comments.
1140
1141	/// Encode an Opus frame.
1142	pub fn encode(&mut self, input: &[i16], output: &mut [u8]) -> Result<usize> {
1143		let len = ffi!(
1144			opus_multistream_encode,
1145			self.ptr,
1146			input.as_ptr(),
1147			len(input) / self.channels as c_int,
1148			output.as_mut_ptr(),
1149			len(output)
1150		);
1151		Ok(len as usize)
1152	}
1153
1154	/// Encode an Opus frame from floating point input.
1155	pub fn encode_float(&mut self, input: &[f32], output: &mut [u8]) -> Result<usize> {
1156		let len = ffi!(
1157			opus_multistream_encode_float,
1158			self.ptr,
1159			input.as_ptr(),
1160			len(input) / self.channels as c_int,
1161			output.as_mut_ptr(),
1162			len(output)
1163		);
1164		Ok(len as usize)
1165	}
1166
1167	/// Encode an Opus frame to a new buffer.
1168	pub fn encode_vec(&mut self, input: &[i16], max_size: usize) -> Result<Vec<u8>> {
1169		let mut output: Vec<u8> = vec![0; max_size];
1170		let result = self.encode(input, output.as_mut_slice())?;
1171		output.truncate(result);
1172		Ok(output)
1173	}
1174
1175	/// Encode an Opus frame from floating point input to a new buffer.
1176	pub fn encode_vec_float(&mut self, input: &[f32], max_size: usize) -> Result<Vec<u8>> {
1177		let mut output: Vec<u8> = vec![0; max_size];
1178		let result = self.encode_float(input, output.as_mut_slice())?;
1179		output.truncate(result);
1180		Ok(output)
1181	}
1182}
1183
1184generic_ctls!(MSEncoder, opus_multistream_encoder_ctl);
1185encoder_ctls!(MSEncoder, opus_multistream_encoder_ctl);
1186
1187/// Decode packets into many Opus streams, up to 255.
1188///
1189/// See [Opus docs](https://opus-codec.org/docs/opus_api-1.5/group__opus__multistream.html).
1190#[derive(Debug)]
1191pub struct MSDecoder {
1192	ptr: *mut ffi::OpusMSDecoder,
1193	channels: c_int,
1194}
1195
1196impl Drop for MSDecoder {
1197	fn drop(&mut self) {
1198		unsafe { ffi::opus_multistream_decoder_destroy(self.ptr) }
1199	}
1200}
1201
1202// See `unsafe impl Send for Encoder`.
1203unsafe impl Send for MSDecoder {}
1204
1205impl MSDecoder {
1206	/// Create and initialize a multistream encoder.
1207	pub fn new(
1208		sample_rate: u32,
1209		streams: u8,
1210		coupled_streams: u8,
1211		mapping: &[u8],
1212	) -> Result<MSDecoder> {
1213		let mut error = 0;
1214		let ptr = unsafe {
1215			ffi::opus_multistream_decoder_create(
1216				sample_rate as i32,
1217				len(mapping),
1218				streams as c_int,
1219				coupled_streams as c_int,
1220				mapping.as_ptr(),
1221				&mut error,
1222			)
1223		};
1224		if error != ffi::OPUS_OK || ptr.is_null() {
1225			Err(Error::from_code("opus_multistream_decoder_create", error))
1226		} else {
1227			Ok(MSDecoder { ptr, channels: len(mapping) })
1228		}
1229	}
1230
1231	/// Decode a multistream Opus packet.
1232	///
1233	/// To represent packet loss, pass an empty slice `&[]`.
1234	pub fn decode(&mut self, input: &[u8], output: &mut [i16], fec: bool) -> Result<usize> {
1235		let ptr = match input.len() {
1236			0 => std::ptr::null(),
1237			_ => input.as_ptr(),
1238		};
1239		let len = ffi!(
1240			opus_multistream_decode,
1241			self.ptr,
1242			ptr,
1243			len(input),
1244			output.as_mut_ptr(),
1245			len(output) / self.channels as c_int,
1246			fec as c_int
1247		);
1248		Ok(len as usize)
1249	}
1250
1251	/// Decode a multistream Opus packet with floating point output.
1252	pub fn decode_float(&mut self, input: &[u8], output: &mut [f32], fec: bool) -> Result<usize> {
1253		let ptr = match input.len() {
1254			0 => std::ptr::null(),
1255			_ => input.as_ptr(),
1256		};
1257		let len = ffi!(
1258			opus_multistream_decode_float,
1259			self.ptr,
1260			ptr,
1261			len(input),
1262			output.as_mut_ptr(),
1263			len(output) / self.channels as c_int,
1264			fec as c_int
1265		);
1266		Ok(len as usize)
1267	}
1268}
1269
1270generic_ctls!(MSDecoder, opus_multistream_decoder_ctl);
1271decoder_ctls!(MSDecoder, opus_multistream_decoder_ctl);
1272
1273// ============================================================================
1274// Error Handling
1275
1276/// Opus error Result alias.
1277pub type Result<T> = std::result::Result<T, Error>;
1278
1279/// An error generated by the Opus library.
1280#[derive(Debug)]
1281pub struct Error {
1282	function: &'static str,
1283	code: ErrorCode,
1284}
1285
1286impl Error {
1287	fn bad_arg(what: &'static str) -> Error {
1288		Error { function: what, code: ErrorCode::BadArg }
1289	}
1290
1291	fn from_code(what: &'static str, code: c_int) -> Error {
1292		Error {
1293			function: what,
1294			code: ErrorCode::from_int(code),
1295		}
1296	}
1297
1298	/// Get the name of the Opus function from which the error originated.
1299	#[inline]
1300	pub fn function(&self) -> &'static str {
1301		self.function
1302	}
1303
1304	/// Get a textual description of the error provided by Opus.
1305	#[inline]
1306	pub fn description(&self) -> &'static str {
1307		self.code.description()
1308	}
1309
1310	/// Get the Opus error code of the error.
1311	#[inline]
1312	pub fn code(&self) -> ErrorCode {
1313		self.code
1314	}
1315}
1316
1317impl std::fmt::Display for Error {
1318	fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1319		write!(f, "{}: {}", self.function, self.description())
1320	}
1321}
1322
1323impl std::error::Error for Error {
1324	fn description(&self) -> &str {
1325		self.code.description()
1326	}
1327}
1328
1329fn check_len(val: usize) -> c_int {
1330	match c_int::try_from(val) {
1331		Ok(val2) => val2,
1332		Err(_) => panic!("length out of range: {}", val),
1333	}
1334}
1335
1336#[inline]
1337fn len<T>(slice: &[T]) -> c_int {
1338	check_len(slice.len())
1339}