1#![no_std]
12#![deny(missing_docs)]
13
14use az::SaturatingAs;
15use core::ffi::{c_int, CStr};
16use num_enum::{IntoPrimitive, TryFromPrimitive};
17use opus_embedded_sys::*;
18
19pub mod prelude {
20 pub use super::{Channels, Decoder, SamplingRate};
32}
33
34unsafe trait RawOpusError {
40 fn numeric(&self) -> c_int;
44}
45
46pub trait OpusError {
48 fn message(&self) -> &'static str;
50}
51
52impl<E: RawOpusError> OpusError for E {
53 fn message(&self) -> &'static str {
54 let error = unsafe {
56 let error = opus_strerror(self.numeric());
57 if error.is_null() {
58 return "Unknown error";
59 }
60 CStr::from_ptr(error)
61 };
62 error.to_str().unwrap()
63 }
64}
65
66#[derive(Debug, PartialEq)]
68pub struct DecoderError {
69 error_code: c_int,
70}
71
72unsafe impl RawOpusError for DecoderError {
73 fn numeric(&self) -> c_int {
74 self.error_code
76 }
77}
78
79impl core::fmt::Display for DecoderError {
80 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
81 f.write_str(self.message())
82 }
83}
84
85impl core::error::Error for DecoderError {
86 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
87 None
88 }
89}
90
91#[derive(Debug, PartialEq)]
93pub struct InvalidPacket {}
94
95unsafe impl RawOpusError for InvalidPacket {
96 fn numeric(&self) -> c_int {
97 OPUS_INVALID_PACKET
98 }
99}
100
101impl core::fmt::Display for InvalidPacket {
102 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
103 f.write_str(self.message())
104 }
105}
106
107impl core::error::Error for InvalidPacket {
108 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
109 None
110 }
111}
112
113#[derive(Copy, Clone, Debug, Eq, PartialEq, IntoPrimitive, TryFromPrimitive)]
119#[repr(u8)]
120pub enum Channels {
121 Mono = 1,
123 Stereo = 2,
125}
126
127impl Channels {
128 pub fn channels(&self) -> u8 {
130 (*self).into()
131 }
132}
133
134#[derive(Debug)]
136pub struct Decoder {
137 decoder: OpusDecoder,
138 channels: Channels,
139}
140
141#[derive(Copy, Clone, Debug, Eq, PartialEq, IntoPrimitive, TryFromPrimitive)]
147#[repr(i32)]
148pub enum SamplingRate {
149 F8k = 8000,
151 F12k = 12000,
153 F16k = 16000,
155 F24k = 24000,
157 F48k = 48000,
159}
160
161impl SamplingRate {
162 pub fn closest(value: i32) -> Self {
164 use SamplingRate::*;
165 if value <= F8k.into() {
166 F8k
167 } else if value <= F12k.into() {
168 F12k
169 } else if value <= F16k.into() {
170 F16k
171 } else if value <= F24k.into() {
172 F24k
173 } else {
174 F48k
175 }
176 }
177}
178
179impl Decoder {
180 pub fn new(freq: SamplingRate, channels: Channels) -> Result<Self, DecoderError> {
186 if !cfg!(feature = "stereo") && channels == Channels::Stereo {
187 let error_code = OPUS_ALLOC_FAIL;
188 return Err(DecoderError { error_code });
189 }
190 let mut decoder = Decoder {
191 decoder: OpusDecoder::default(),
192 channels,
193 };
194 let channels = channels.channels().into();
195 let size = unsafe { opus_decoder_get_size(channels) };
197 assert!(
198 core::mem::size_of::<OpusDecoder>() >= size.try_into().unwrap(),
199 "OpusDecoder struct is too small!"
200 );
201 let error_code = unsafe { opus_decoder_init(&mut decoder.decoder, freq.into(), channels) };
203 if error_code != OPUS_OK.try_into().unwrap() {
205 Err(DecoderError { error_code })
206 } else {
207 Ok(decoder)
208 }
209 }
210
211 pub fn get_nb_samples_total(&self, data: &[u8]) -> Result<usize, DecoderError> {
220 match self.channels {
221 Channels::Mono => self.get_nb_samples(data),
222 Channels::Stereo => Ok(self.get_nb_samples(data)? * 2),
223 }
224 }
225
226 pub fn get_nb_samples(&self, data: &[u8]) -> Result<usize, DecoderError> {
235 let samples = unsafe {
238 let len = data.len().saturating_as();
239 let data = if !data.is_empty() {
240 data.as_ptr()
241 } else {
242 core::ptr::null()
243 };
244 opus_decoder_get_nb_samples(&self.decoder, data, len)
245 };
246 if samples < 0 {
247 Err(DecoderError {
248 error_code: samples,
249 })
250 } else {
251 Ok(samples.saturating_as())
252 }
253 }
254
255 pub fn decode<'output>(
275 &mut self,
276 data: &[u8],
277 output: &'output mut [i16],
278 ) -> Result<&'output [i16], DecoderError> {
279 let samples = unsafe {
282 let len: i32 = data.len().saturating_as();
283 let data = if !data.is_empty() {
284 data.as_ptr()
285 } else {
286 core::ptr::null()
287 };
288 let frame_size: i32 = match self.channels {
290 Channels::Mono => output.len(),
291 Channels::Stereo => output.len() / 2,
292 }
293 .saturating_as();
294 let output = if !output.is_empty() {
295 output.as_mut_ptr()
296 } else {
297 core::ptr::null_mut()
298 };
299 opus_decode(&mut self.decoder, data, len, output, frame_size, 0)
300 };
301 if samples < 0 {
302 Err(DecoderError {
303 error_code: samples,
304 })
305 } else {
306 let frame_size = match self.channels {
307 Channels::Mono => samples as usize,
308 Channels::Stereo => samples as usize * 2,
309 };
310 Ok(&output[..frame_size])
311 }
312 }
313}
314
315#[derive(Copy, Clone, Debug, PartialEq)]
317pub enum Bandwidth {
318 Narrowband,
320 Mediumband,
322 Wideband,
324 Superwideband,
326 Fullband,
328}
329
330#[derive(Debug)]
332pub struct OpusPacket<'data> {
333 data: &'data [u8],
334}
335
336impl<'data> OpusPacket<'data> {
337 pub fn new(data: &'data [u8]) -> Self {
348 assert!(!data.is_empty());
349 Self { data }
350 }
351
352 pub fn get_nb_channels(&self) -> Result<u8, InvalidPacket> {
354 let channels = unsafe {
356 let data = self.data.as_ptr();
357 opus_packet_get_nb_channels(data)
358 };
359 if channels < 0 {
360 debug_assert_eq!(channels, OPUS_INVALID_PACKET);
361 Err(InvalidPacket {})
362 } else {
363 Ok(channels.saturating_as())
364 }
365 }
366
367 pub fn get_nb_frames(&self) -> Result<u32, InvalidPacket> {
373 let frames = unsafe {
376 let len = self.data.len().saturating_as();
377 let data = self.data.as_ptr();
378 opus_packet_get_nb_frames(data, len)
379 };
380 if frames < 0 {
381 debug_assert_eq!(frames, OPUS_INVALID_PACKET);
382 Err(InvalidPacket {})
383 } else {
384 Ok(frames.saturating_as())
385 }
386 }
387
388 pub fn get_bandwidth(&self) -> Result<Bandwidth, InvalidPacket> {
394 let bandwidth = unsafe {
396 let data = self.data.as_ptr();
397 opus_packet_get_bandwidth(data)
398 };
399 if bandwidth < 0 {
400 debug_assert_eq!(bandwidth, OPUS_INVALID_PACKET);
401 Err(InvalidPacket {})
402 } else {
403 use Bandwidth::*;
404 #[allow(non_snake_case)]
406 Ok(match bandwidth.try_into().unwrap() {
407 OPUS_BANDWIDTH_NARROWBAND => Narrowband,
408 OPUS_BANDWIDTH_MEDIUMBAND => Mediumband,
409 OPUS_BANDWIDTH_WIDEBAND => Wideband,
410 OPUS_BANDWIDTH_SUPERWIDEBAND => Superwideband,
411 OPUS_BANDWIDTH_FULLBAND => Fullband,
412 _ => panic!("Invalid bandwidth value returned by libopus"),
413 })
414 }
415 }
416
417 pub fn get_samples_per_frame(&self) -> Result<u32, InvalidPacket> {
423 let samples = unsafe {
426 let len = self.data.len().saturating_as();
427 let data = self.data.as_ptr();
428 opus_packet_get_samples_per_frame(data, len)
429 };
430 if samples < 0 {
431 debug_assert_eq!(samples, OPUS_INVALID_PACKET);
432 Err(InvalidPacket {})
433 } else {
434 Ok(samples.saturating_as())
435 }
436 }
437}
438
439#[cfg(test)]
440mod tests {
441 extern crate alloc;
442 use super::*;
443 use alloc::string::ToString;
444 use core::error::Error;
445
446 #[test]
447 fn create_decoder() {
448 let decoder = Decoder::new(SamplingRate::F8k, Channels::Mono);
449 assert!(decoder.is_ok());
450 }
451
452 #[test]
453 fn create_decoder_stereo() {
454 let decoder = Decoder::new(SamplingRate::F16k, Channels::Stereo);
455 if cfg!(feature = "stereo") {
456 assert!(decoder.is_ok());
457 } else {
458 assert!(decoder.is_err());
459 assert_eq!(decoder.unwrap_err().numeric(), OPUS_ALLOC_FAIL);
460 }
461 }
462
463 #[test]
464 fn sampling_rate() {
465 assert_eq!(SamplingRate::closest(8_000), SamplingRate::F8k);
466 assert_eq!(SamplingRate::closest(12_000), SamplingRate::F12k);
467 assert_eq!(SamplingRate::closest(16_000), SamplingRate::F16k);
468 assert_eq!(SamplingRate::closest(24_000), SamplingRate::F24k);
469 assert_eq!(SamplingRate::closest(48_000), SamplingRate::F48k);
470 }
471
472 #[test]
473 fn sampling_rate_from_primitive() {
474 assert!(SamplingRate::try_from(1_000).is_err());
475 assert!(SamplingRate::try_from(8_000).is_ok());
476 assert!(SamplingRate::try_from(12_000).is_ok());
477 assert!(SamplingRate::try_from(16_000).is_ok());
478 assert!(SamplingRate::try_from(24_000).is_ok());
479 assert!(SamplingRate::try_from(48_000).is_ok());
480 assert!(SamplingRate::try_from(64_000).is_err());
481 }
482
483 #[test]
484 fn channels_from_primitive() {
485 assert!(Channels::try_from(0).is_err());
486 assert!(Channels::try_from(1).is_ok());
487 assert!(Channels::try_from(2).is_ok());
488 for channels in 3..=255 {
489 assert!(Channels::try_from(channels).is_err());
490 }
491 }
492
493 #[test]
494 fn test_decoder_with_zero_length_packet() {
495 const DATA: [u8; 0] = [0u8; 0];
497 let mut decoder = Decoder::new(SamplingRate::F8k, Channels::Mono).unwrap();
498 let result = decoder.get_nb_samples(&DATA);
499 assert_eq!(
500 result,
501 Err(DecoderError {
502 error_code: OPUS_BAD_ARG
503 })
504 );
505 let error = result.unwrap_err();
506 assert_eq!(error.numeric(), OPUS_BAD_ARG);
507 assert!(error.source().is_none());
508 assert_eq!(error.to_string(), "invalid argument");
509 let mut output = [0i16; 100];
511 let result = decoder.decode(&DATA, &mut output);
512 assert_eq!(result.unwrap().len(), output.len());
513 for v in output {
514 assert_eq!(v, 0);
515 }
516 let mut output = [0i16; 0];
518 let result = decoder.decode(&[0, 0, 0, 0, 0], &mut output);
519 assert_eq!(
520 result,
521 Err(DecoderError {
522 error_code: OPUS_BAD_ARG
523 })
524 );
525 let error = result.unwrap_err();
526 assert_eq!(error.numeric(), OPUS_BAD_ARG);
527 assert!(error.source().is_none());
528 assert_eq!(error.to_string(), "invalid argument");
529 }
530
531 #[test]
532 fn test_decoder_with_zero_packet() {
533 const DATA: [u8; 8] = [0x00u8; 8];
534 let mut decoder = Decoder::new(SamplingRate::F8k, Channels::Mono).unwrap();
535 assert_eq!(decoder.get_nb_samples(&DATA), Ok(80));
536 let mut output = [0i16; 80];
537 assert_eq!(decoder.decode(&DATA, &mut output).unwrap().len(), 80);
538 }
539
540 #[test]
541 fn test_decoder_with_0xff_packet() {
542 const DATA: [u8; 8] = [0xffu8; 8];
543 let mut decoder = Decoder::new(SamplingRate::F8k, Channels::Mono).unwrap();
544 let result = decoder.get_nb_samples(&DATA);
545 assert_eq!(
546 result,
547 Err(DecoderError {
548 error_code: OPUS_INVALID_PACKET
549 })
550 );
551 let error = result.unwrap_err();
552 assert_eq!(error.numeric(), OPUS_INVALID_PACKET);
553 assert!(error.source().is_none());
554 assert_eq!(error.to_string(), "corrupted stream");
555 let mut output = [0i16; 80];
556 let result = decoder.decode(&DATA, &mut output);
557 assert_eq!(
558 result,
559 Err(DecoderError {
560 error_code: OPUS_INVALID_PACKET
561 })
562 );
563 let error = result.unwrap_err();
564 assert_eq!(error.numeric(), OPUS_INVALID_PACKET);
565 assert!(error.source().is_none());
566 assert_eq!(error.to_string(), "corrupted stream");
567 }
568
569 #[test]
570 #[should_panic]
571 fn test_zero_length_packet() {
572 const DATA: [u8; 0] = [0u8; 0];
573 let _packet = OpusPacket::new(&DATA);
574 }
575
576 #[test]
577 fn test_zero_packet() {
578 let data = [0x00u8; 8];
579 let packet = OpusPacket::new(&data);
580 assert_eq!(packet.get_nb_channels(), Ok(1));
581 assert_eq!(packet.get_nb_frames(), Ok(1));
582 assert_eq!(packet.get_bandwidth(), Ok(Bandwidth::Narrowband));
583 assert_eq!(packet.get_samples_per_frame(), Ok(0));
584 }
585
586 #[test]
587 fn test_0xff_packet() {
588 let data = [0xFFu8; 8];
589 let packet = OpusPacket::new(&data);
590 assert_eq!(packet.get_nb_channels(), Ok(2));
591 assert_eq!(packet.get_nb_frames(), Ok(63));
592 assert_eq!(packet.get_bandwidth(), Ok(Bandwidth::Fullband));
593 assert_eq!(packet.get_samples_per_frame(), Ok(0));
594 }
595
596 #[test]
597 fn test_one_length_packet() {
598 let packet = OpusPacket::new(&[0xff]);
600 assert_eq!(packet.get_nb_channels(), Ok(2));
601 let result = packet.get_nb_frames();
602 assert_eq!(result, Err(InvalidPacket {}));
603 let error = result.unwrap_err();
604 assert_eq!(error.numeric(), OPUS_INVALID_PACKET);
605 assert!(error.source().is_none());
606 assert_eq!(error.to_string(), "corrupted stream");
607 assert_eq!(packet.get_bandwidth(), Ok(Bandwidth::Fullband));
608 assert_eq!(packet.get_samples_per_frame(), Ok(0));
609 }
610
611 #[test]
612 fn test_packet_bandwidths() {
613 let packet = OpusPacket::new(&[0x00]);
615 assert_eq!(packet.get_bandwidth(), Ok(Bandwidth::Narrowband));
616 let packet = OpusPacket::new(&[0x20]);
617 assert_eq!(packet.get_bandwidth(), Ok(Bandwidth::Mediumband));
618 let packet = OpusPacket::new(&[0xB0]);
619 assert_eq!(packet.get_bandwidth(), Ok(Bandwidth::Wideband));
620 let packet = OpusPacket::new(&[0xC0]);
621 assert_eq!(packet.get_bandwidth(), Ok(Bandwidth::Superwideband));
622 let packet = OpusPacket::new(&[0xF0]);
623 assert_eq!(packet.get_bandwidth(), Ok(Bandwidth::Fullband));
624 }
625}