diff --git a/symphonia-codec-opus/Cargo.toml b/symphonia-codec-opus/Cargo.toml index efcce8e7..8a7c578d 100644 --- a/symphonia-codec-opus/Cargo.toml +++ b/symphonia-codec-opus/Cargo.toml @@ -4,7 +4,7 @@ version = "0.0.1" description = "Pure Opus decoder (a part of project Symphonia)." homepage = "https://github.com/pdeljanov/Symphonia" repository = "https://github.com/pdeljanov/Symphonia" -authors = ["Philip Deljanov "] +authors = ["Philip Deljanov ", "Darius Tan "] license = "MPL-2.0" readme = "README.md" categories = ["multimedia", "multimedia::audio", "multimedia::encoding"] diff --git a/symphonia-codec-opus/src/lib.rs b/symphonia-codec-opus/src/lib.rs index 27d285f2..a05ca41e 100644 --- a/symphonia-codec-opus/src/lib.rs +++ b/symphonia-codec-opus/src/lib.rs @@ -16,7 +16,9 @@ // Disable to better express the specification. #![allow(clippy::collapsible_else_if)] -use symphonia_core::audio::GenericAudioBufferRef; +use symphonia_core::audio::{ + AsGenericAudioBufferRef, AudioBuffer, AudioSpec, Channels, GenericAudioBufferRef, +}; use symphonia_core::codecs::audio::well_known::CODEC_ID_OPUS; use symphonia_core::codecs::audio::{ AudioCodecParameters, AudioDecoder, AudioDecoderOptions, FinalizeResult, @@ -32,6 +34,18 @@ use symphonia_core::support_audio_codec; pub struct OpusDecoder { ident_header: IdentificationHeader, params: AudioCodecParameters, + buffer: AudioBuffer, +} + +/// The operating mode for the Opus Decoder. +/// See RFC 6716 Section 3.1, https://tools.ietf.org/pdf/rfc7845.pdf. +enum Mode { + /// SILK-only mode. + Silk, + /// CELT-only mode. + Celt, + /// SILK and CELT mode. + Hybrid, } impl OpusDecoder { @@ -44,7 +58,11 @@ impl OpusDecoder { let mut reader = BufReader::new(extra_data); let ident_header = read_ident_header(&mut reader)?; - Ok(OpusDecoder { ident_header, params: params.clone() }) + Ok(OpusDecoder { + ident_header, + params: params.clone(), + buffer: AudioBuffer::new(AudioSpec::new(0, Channels::None), 0), + }) } } @@ -63,7 +81,22 @@ impl AudioDecoder for OpusDecoder { #[allow(unused_variables)] fn decode(&mut self, packet: &Packet) -> Result> { - unimplemented!() + let mut reader = packet.as_buf_reader(); + + // Configuring the decoder from the table of contents (toc) byte. + // See RFC 6716 Section 3.1, https://tools.ietf.org/pdf/rfc7845.pdf. + let toc = reader.read_byte()?; + let config = toc >> 3; + let mode = match config { + 0..=11 => Mode::Silk, + 12..=15 => Mode::Hybrid, + 16..=31 => Mode::Celt, + _ => unreachable!(), + }; + let stereo_flag = toc & 0b00000100; + let frame_count_code = toc & 0b00000011; + + Ok(self.buffer.as_generic_audio_buffer_ref()) } fn finalize(&mut self) -> FinalizeResult { @@ -103,12 +136,11 @@ pub struct IdentificationHeader { pub channel_mapping: [u8; 8], } -/** Create an IdentificationHeader from \a reader. - * - * If the header is invalid, a DecodeError is returned. - * - * See RFC 7845 Section 5.1, https://tools.ietf.org/pdf/rfc7845.pdf. - */ +/// Create an IdentificationHeader from a reader. +/// +/// If the header is invalid, a DecodeError is returned. +/// +/// See RFC 7845 Section 5.1, https://tools.ietf.org/pdf/rfc7845.pdf. fn read_ident_header(reader: &mut B) -> Result { // The first 8 bytes are the magic signature ASCII bytes. const OGG_OPUS_MAGIC_SIGNATURE: &[u8] = b"OpusHead"; diff --git a/symphonia/Cargo.toml b/symphonia/Cargo.toml index ce2306f8..5f66aa15 100644 --- a/symphonia/Cargo.toml +++ b/symphonia/Cargo.toml @@ -35,6 +35,7 @@ wav = ["dep:symphonia-format-riff", "symphonia-format-riff/wav"] ape = ["symphonia-metadata/ape"] id3v1 = ["symphonia-metadata/id3v1"] id3v2 = ["symphonia-metadata/id3v2"] +opus = ["dep:symphonia-codec-opus"] # MPEG audio codecs. mpa = ["mp1", "mp2", "mp3"] @@ -138,6 +139,11 @@ version = "0.5.4" path = "../symphonia-codec-vorbis" optional = true +[dependencies.symphonia-codec-opus] +version = "0.0.1" +path = "../symphonia-codec-opus" +optional = true + [dependencies.symphonia-format-riff] version = "0.5.4" path = "../symphonia-format-riff" diff --git a/symphonia/src/lib.rs b/symphonia/src/lib.rs index a4e2d480..50fbadfe 100644 --- a/symphonia/src/lib.rs +++ b/symphonia/src/lib.rs @@ -161,6 +161,8 @@ pub mod default { pub use symphonia_codec_adpcm::AdpcmDecoder; #[cfg(feature = "alac")] pub use symphonia_codec_alac::AlacDecoder; + #[cfg(feature = "opus")] + pub use symphonia_codec_opus::OpusDecoder; #[cfg(feature = "pcm")] pub use symphonia_codec_pcm::PcmDecoder; #[cfg(feature = "vorbis")] @@ -278,6 +280,9 @@ pub mod default { #[cfg(feature = "vorbis")] registry.register_audio_decoder::(); + + #[cfg(feature = "opus")] + registry.register_audio_decoder::(); } /// Registers all the formats selected by the `feature` flags in the includer's `Cargo.toml` on