Skip to content

Commit

Permalink
opus: Decode table of contents (TOC) byte. (#111)
Browse files Browse the repository at this point in the history
  • Loading branch information
thinking-tower authored and a1phyr committed Sep 21, 2024
1 parent 38083a0 commit 4bee01f
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 10 deletions.
2 changes: 1 addition & 1 deletion symphonia-codec-opus/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 <philip.deljanov@gmail.com>"]
authors = ["Philip Deljanov <philip.deljanov@gmail.com>", "Darius Tan <dariustancode@gmail.com>"]
license = "MPL-2.0"
readme = "README.md"
categories = ["multimedia", "multimedia::audio", "multimedia::encoding"]
Expand Down
50 changes: 41 additions & 9 deletions symphonia-codec-opus/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -32,6 +34,18 @@ use symphonia_core::support_audio_codec;
pub struct OpusDecoder {
ident_header: IdentificationHeader,
params: AudioCodecParameters,
buffer: AudioBuffer<f32>,
}

/// 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 {
Expand All @@ -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),
})
}
}

Expand All @@ -63,7 +81,22 @@ impl AudioDecoder for OpusDecoder {

#[allow(unused_variables)]
fn decode(&mut self, packet: &Packet) -> Result<GenericAudioBufferRef<'_>> {
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 {
Expand Down Expand Up @@ -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<B: ReadBytes>(reader: &mut B) -> Result<IdentificationHeader> {
// The first 8 bytes are the magic signature ASCII bytes.
const OGG_OPUS_MAGIC_SIGNATURE: &[u8] = b"OpusHead";
Expand Down
6 changes: 6 additions & 0 deletions symphonia/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ pcm = ["symphonia-codec-pcm"]
aiff = ["symphonia-format-riff/aiff"]
vorbis = ["symphonia-codec-vorbis"]
wav = ["symphonia-format-riff/wav"]
opus = ["symphonia-codec-opus"]

# MPEG audio codecs.
mpa = ["mp1", "mp2", "mp3"]
Expand Down Expand Up @@ -127,6 +128,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"
Expand Down
5 changes: 5 additions & 0 deletions symphonia/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,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")]
Expand Down Expand Up @@ -257,6 +259,9 @@ pub mod default {

#[cfg(feature = "vorbis")]
registry.register_audio_decoder::<codecs::VorbisDecoder>();

#[cfg(feature = "opus")]
registry.register_audio_decoder::<codecs::OpusDecoder>();
}

/// Registers all the formats selected by the `feature` flags in the includer's `Cargo.toml` on
Expand Down

0 comments on commit 4bee01f

Please sign in to comment.