symphonia_adapter_libopus/
lib.rs1#![warn(missing_docs, missing_debug_implementations)]
2#![forbid(clippy::unwrap_used)]
3#![cfg_attr(docsrs, feature(doc_cfg))]
4#![doc = include_str!("../README.md")]
5
6use std::fmt;
7
8use symphonia_core::audio::{
9 AsAudioBufferRef, AudioBuffer, AudioBufferRef, Channels, Layout, Signal, SignalSpec,
10};
11use symphonia_core::codecs::{
12 self, CODEC_TYPE_OPUS, CodecDescriptor, CodecParameters, DecoderOptions, FinalizeResult,
13};
14use symphonia_core::errors::{Result, unsupported_error};
15use symphonia_core::formats::Packet;
16use symphonia_core::io::{BufReader, ReadBytes};
17use symphonia_core::support_codec;
18
19use crate::decoder::Decoder;
20
21mod decoder;
22
23const MAX_SAMPLE_RATE: usize = 48000;
25const DEFAULT_SAMPLE_RATE: usize = 48000;
26const DEFAULT_SAMPLES_PER_CHANNEL: usize = DEFAULT_SAMPLE_RATE * 20 / 1000;
28const MAX_SAMPLES_PER_CHANNEL: usize = MAX_SAMPLE_RATE * 120 / 1000;
30
31pub struct OpusDecoder {
33 params: CodecParameters,
34 decoder: Decoder,
35 buf: AudioBuffer<f32>,
36 pcm: [f32; MAX_SAMPLES_PER_CHANNEL * 2],
37 samples_per_channel: usize,
38 sample_rate: u32,
39 num_channels: usize,
40 pre_skip: usize,
41}
42
43impl fmt::Debug for OpusDecoder {
44 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45 f.debug_struct("OpusDecoder")
46 .field("params", &self.params)
47 .field("decoder", &self.decoder)
48 .field("buf", &"<buf>")
49 .field("pcm", &self.pcm)
50 .field("samples_per_channel", &self.samples_per_channel)
51 .field("sample_rate", &self.sample_rate)
52 .field("num_channels", &self.num_channels)
53 .field("pre_skip", &self.pre_skip)
54 .finish()
55 }
56}
57
58fn parse_pre_skip(buf: &[u8]) -> Result<usize> {
60 let mut reader = BufReader::new(buf);
63
64 let mut header = [0; 8];
66 reader.read_buf_exact(&mut header)?;
67
68 reader.read_byte()?;
70
71 reader.read_byte()?;
73
74 let pre_skip = reader.read_u16()?;
76
77 Ok(pre_skip as usize)
78}
79
80impl codecs::Decoder for OpusDecoder {
81 fn try_new(params: &CodecParameters, _opts: &DecoderOptions) -> Result<Self>
82 where
83 Self: Sized,
84 {
85 let num_channels = if let Some(channels) = ¶ms.channels {
86 channels.count()
87 } else {
88 return unsupported_error("opus: channels or channel layout is required");
89 };
90 let sample_rate = if let Some(sample_rate) = params.sample_rate {
91 sample_rate
92 } else {
93 return unsupported_error("opus: sample rate required");
94 };
95
96 if !(1..=2).contains(&num_channels) {
97 return unsupported_error("opus: unsupported number of channels");
98 }
99
100 let pre_skip = if let Some(extra_data) = ¶ms.extra_data {
101 parse_pre_skip(extra_data).unwrap_or_default()
102 } else {
103 0
104 };
105
106 Ok(Self {
107 params: params.to_owned(),
108 decoder: Decoder::new(sample_rate, num_channels as u32)?,
109 buf: audio_buffer(
110 sample_rate,
111 DEFAULT_SAMPLES_PER_CHANNEL as u64,
112 num_channels,
113 ),
114 pcm: [0.0; _],
115 samples_per_channel: DEFAULT_SAMPLES_PER_CHANNEL,
116 sample_rate,
117 num_channels,
118 pre_skip,
119 })
120 }
121
122 fn supported_codecs() -> &'static [CodecDescriptor]
123 where
124 Self: Sized,
125 {
126 &[support_codec!(CODEC_TYPE_OPUS, "opus", "Opus")]
127 }
128
129 fn reset(&mut self) {
130 self.decoder.reset()
131 }
132
133 fn codec_params(&self) -> &CodecParameters {
134 &self.params
135 }
136
137 fn decode(&mut self, packet: &Packet) -> Result<AudioBufferRef<'_>> {
138 let samples_per_channel = self.decoder.decode(&packet.data, &mut self.pcm)?;
139
140 if samples_per_channel != self.samples_per_channel {
141 self.buf = audio_buffer(
142 self.sample_rate,
143 samples_per_channel as u64,
144 self.num_channels,
145 );
146 self.samples_per_channel = samples_per_channel;
147 }
148
149 let samples = samples_per_channel * self.num_channels;
150 let pcm = &self.pcm[..samples];
151
152 self.buf.clear();
153 self.buf.render_reserved(None);
154 match self.num_channels {
155 1 => {
156 self.buf.chan_mut(0).copy_from_slice(pcm);
157 }
158 2 => {
159 let (l, r) = self.buf.chan_pair_mut(0, 1);
160 for (i, j) in (0..samples).step_by(2).enumerate() {
161 l[i] = pcm[j];
162 r[i] = pcm[j + 1];
163 }
164 }
165 _ => {}
166 }
167
168 self.buf.trim(
169 packet.trim_start() as usize
170 + (self.pre_skip * self.sample_rate as usize) / DEFAULT_SAMPLE_RATE,
171 packet.trim_end() as usize,
172 );
173 self.pre_skip = 0;
175 Ok(self.buf.as_audio_buffer_ref())
176 }
177
178 fn finalize(&mut self) -> FinalizeResult {
179 FinalizeResult::default()
180 }
181
182 fn last_decoded(&self) -> AudioBufferRef<'_> {
183 self.buf.as_audio_buffer_ref()
184 }
185}
186
187fn map_to_channels(num_channels: usize) -> Option<Channels> {
188 let channels = match num_channels {
189 1 => Layout::Mono.into_channels(),
190 2 => Layout::Stereo.into_channels(),
191 _ => return None,
192 };
193
194 Some(channels)
195}
196
197fn audio_buffer(
198 sample_rate: u32,
199 samples_per_channel: u64,
200 num_channels: usize,
201) -> AudioBuffer<f32> {
202 let channels = map_to_channels(num_channels).expect("invalid channels");
203 let spec = SignalSpec::new(sample_rate, channels);
204 AudioBuffer::new(samples_per_channel, spec)
205}