Skip to main content

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