Skip to content

Commit dfd0914

Browse files
thinking-towera1phyr
authored andcommitted
opus: Decode table of contents (TOC) byte. (#111)
1 parent f75ceb6 commit dfd0914

File tree

4 files changed

+53
-10
lines changed

4 files changed

+53
-10
lines changed

symphonia-codec-opus/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ version = "0.0.1"
44
description = "Pure Opus decoder (a part of project Symphonia)."
55
homepage = "https://github.com/pdeljanov/Symphonia"
66
repository = "https://github.com/pdeljanov/Symphonia"
7-
authors = ["Philip Deljanov <[email protected]>"]
7+
authors = ["Philip Deljanov <[email protected]>", "Darius Tan <[email protected]>"]
88
license = "MPL-2.0"
99
readme = "README.md"
1010
categories = ["multimedia", "multimedia::audio", "multimedia::encoding"]

symphonia-codec-opus/src/lib.rs

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
// Disable to better express the specification.
1717
#![allow(clippy::collapsible_else_if)]
1818

19-
use symphonia_core::audio::GenericAudioBufferRef;
19+
use symphonia_core::audio::{
20+
AsGenericAudioBufferRef, AudioBuffer, AudioSpec, Channels, GenericAudioBufferRef,
21+
};
2022
use symphonia_core::codecs::audio::well_known::CODEC_ID_OPUS;
2123
use symphonia_core::codecs::audio::{
2224
AudioCodecParameters, AudioDecoder, AudioDecoderOptions, FinalizeResult,
@@ -32,6 +34,18 @@ use symphonia_core::support_audio_codec;
3234
pub struct OpusDecoder {
3335
ident_header: IdentificationHeader,
3436
params: AudioCodecParameters,
37+
buffer: AudioBuffer<f32>,
38+
}
39+
40+
/// The operating mode for the Opus Decoder.
41+
/// See RFC 6716 Section 3.1, https://tools.ietf.org/pdf/rfc7845.pdf.
42+
enum Mode {
43+
/// SILK-only mode.
44+
Silk,
45+
/// CELT-only mode.
46+
Celt,
47+
/// SILK and CELT mode.
48+
Hybrid,
3549
}
3650

3751
impl OpusDecoder {
@@ -44,7 +58,11 @@ impl OpusDecoder {
4458
let mut reader = BufReader::new(extra_data);
4559

4660
let ident_header = read_ident_header(&mut reader)?;
47-
Ok(OpusDecoder { ident_header, params: params.clone() })
61+
Ok(OpusDecoder {
62+
ident_header,
63+
params: params.clone(),
64+
buffer: AudioBuffer::new(AudioSpec::new(0, Channels::None), 0),
65+
})
4866
}
4967
}
5068

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

6482
#[allow(unused_variables)]
6583
fn decode(&mut self, packet: &Packet) -> Result<GenericAudioBufferRef<'_>> {
66-
unimplemented!()
84+
let mut reader = packet.as_buf_reader();
85+
86+
// Configuring the decoder from the table of contents (toc) byte.
87+
// See RFC 6716 Section 3.1, https://tools.ietf.org/pdf/rfc7845.pdf.
88+
let toc = reader.read_byte()?;
89+
let config = toc >> 3;
90+
let mode = match config {
91+
0..=11 => Mode::Silk,
92+
12..=15 => Mode::Hybrid,
93+
16..=31 => Mode::Celt,
94+
_ => unreachable!(),
95+
};
96+
let stereo_flag = toc & 0b00000100;
97+
let frame_count_code = toc & 0b00000011;
98+
99+
Ok(self.buffer.as_generic_audio_buffer_ref())
67100
}
68101

69102
fn finalize(&mut self) -> FinalizeResult {
@@ -103,12 +136,11 @@ pub struct IdentificationHeader {
103136
pub channel_mapping: [u8; 8],
104137
}
105138

106-
/** Create an IdentificationHeader from \a reader.
107-
*
108-
* If the header is invalid, a DecodeError is returned.
109-
*
110-
* See RFC 7845 Section 5.1, https://tools.ietf.org/pdf/rfc7845.pdf.
111-
*/
139+
/// Create an IdentificationHeader from a reader.
140+
///
141+
/// If the header is invalid, a DecodeError is returned.
142+
///
143+
/// See RFC 7845 Section 5.1, https://tools.ietf.org/pdf/rfc7845.pdf.
112144
fn read_ident_header<B: ReadBytes>(reader: &mut B) -> Result<IdentificationHeader> {
113145
// The first 8 bytes are the magic signature ASCII bytes.
114146
const OGG_OPUS_MAGIC_SIGNATURE: &[u8] = b"OpusHead";

symphonia/Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ pcm = ["symphonia-codec-pcm"]
3434
aiff = ["symphonia-format-riff/aiff"]
3535
vorbis = ["symphonia-codec-vorbis"]
3636
wav = ["symphonia-format-riff/wav"]
37+
opus = ["symphonia-codec-opus"]
3738

3839
# MPEG audio codecs.
3940
mpa = ["mp1", "mp2", "mp3"]
@@ -127,6 +128,11 @@ version = "0.5.4"
127128
path = "../symphonia-codec-vorbis"
128129
optional = true
129130

131+
[dependencies.symphonia-codec-opus]
132+
version = "0.0.1"
133+
path = "../symphonia-codec-opus"
134+
optional = true
135+
130136
[dependencies.symphonia-format-riff]
131137
version = "0.5.4"
132138
path = "../symphonia-format-riff"

symphonia/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@ pub mod default {
155155
pub use symphonia_codec_adpcm::AdpcmDecoder;
156156
#[cfg(feature = "alac")]
157157
pub use symphonia_codec_alac::AlacDecoder;
158+
#[cfg(feature = "opus")]
159+
pub use symphonia_codec_opus::OpusDecoder;
158160
#[cfg(feature = "pcm")]
159161
pub use symphonia_codec_pcm::PcmDecoder;
160162
#[cfg(feature = "vorbis")]
@@ -259,6 +261,9 @@ pub mod default {
259261

260262
#[cfg(feature = "vorbis")]
261263
registry.register_audio_decoder::<codecs::VorbisDecoder>();
264+
265+
#[cfg(feature = "opus")]
266+
registry.register_audio_decoder::<codecs::OpusDecoder>();
262267
}
263268

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

0 commit comments

Comments
 (0)