1use super::{Decoder, Encoder, PcmBuf, Sample};
2pub use opus_rs::Application as OpusApplication;
3use opus_rs::{Application, OpusDecoder as OpusDecoderRaw, OpusEncoder as OpusEncoderRaw};
4
5pub struct OpusDecoder {
6 decoder: OpusDecoderRaw,
7 sample_rate: u32,
8 channels: u16,
9 w_output_f32: Vec<f32>,
10 w_pcm_i16: Vec<i16>,
11}
12
13impl OpusDecoder {
14 pub fn new(sample_rate: u32, channels: u16) -> Self {
16 let decoder = OpusDecoderRaw::new(sample_rate as i32, channels as usize)
17 .expect("Failed to create Opus decoder");
18
19 Self {
20 decoder,
21 sample_rate,
22 channels,
23 w_output_f32: Vec::new(),
24 w_pcm_i16: Vec::new(),
25 }
26 }
27
28 pub fn new_default() -> Self {
30 Self::new(48000, 2)
31 }
32
33 pub fn decode_into(&mut self, data: &[u8], output: &mut [i16]) -> usize {
34 if data.is_empty() {
35 return 0;
36 }
37
38 let packet_channels = if data[0] & 0x04 != 0 { 2usize } else { 1 };
43 if self.channels as usize != packet_channels {
44 self.channels = packet_channels as u16;
45 self.decoder = OpusDecoderRaw::new(self.sample_rate as i32, packet_channels)
46 .expect("Failed to create Opus decoder");
47 }
48
49 let channels = usize::from(self.channels);
50 let frame_size = (self.sample_rate as usize * 20) / 1000;
51 let max_samples = frame_size * channels;
52 if self.w_output_f32.len() < max_samples {
53 self.w_output_f32.resize(max_samples, 0.0);
54 }
55
56 match self
57 .decoder
58 .decode(data, frame_size, &mut self.w_output_f32[..max_samples])
59 {
60 Ok(len) => {
61 let total_samples = len * channels;
62 if total_samples == 0 {
63 return 0;
64 }
65
66 if self.w_pcm_i16.len() < total_samples {
67 self.w_pcm_i16.resize(total_samples, 0);
68 }
69
70 for i in 0..total_samples {
71 self.w_pcm_i16[i] =
72 (self.w_output_f32[i] * 32768.0).clamp(-32768.0, 32767.0) as i16;
73 }
74
75 let n = total_samples.min(output.len());
76 output[..n].copy_from_slice(&self.w_pcm_i16[..n]);
77 n
78 }
79 Err(_) => 0,
80 }
81 }
82}
83
84impl Decoder for OpusDecoder {
85 fn decode(&mut self, data: &[u8]) -> PcmBuf {
86 if data.is_empty() {
87 return Vec::new();
88 }
89 let packet_channels = if data[0] & 0x04 != 0 { 2usize } else { 1 };
90
91 let frame_size = (self.sample_rate as usize * 20) / 1000;
92 let max_samples = frame_size * packet_channels;
93 let mut pcm = vec![0i16; max_samples];
94 let n = self.decode_into(data, &mut pcm);
95 pcm.truncate(n);
96 if usize::from(self.channels) == 2 {
97 pcm = pcm
98 .chunks_exact(2)
99 .map(|chunk| ((chunk[0] as i32 + chunk[1] as i32) / 2) as i16)
100 .collect();
101 }
102 pcm
103 }
104
105 fn sample_rate(&self) -> u32 {
106 self.sample_rate
107 }
108
109 fn channels(&self) -> u16 {
110 self.channels
111 }
112}
113
114pub struct OpusEncoder {
115 encoder: OpusEncoderRaw,
116 sample_rate: u32,
117 channels: u16,
118 w_input_f32: Vec<f32>,
119 w_packet: Vec<u8>,
120}
121
122impl OpusEncoder {
123 pub fn new_with_application(sample_rate: u32, channels: u16, application: Application) -> Self {
124 let encoder = OpusEncoderRaw::new(sample_rate as i32, channels as usize, application)
125 .expect("Failed to create Opus encoder");
126
127 Self {
128 encoder,
129 sample_rate,
130 channels,
131 w_input_f32: Vec::new(),
132 w_packet: vec![0u8; 1275],
133 }
134 }
135
136 pub fn new(sample_rate: u32, channels: u16) -> Self {
143 let mut enc = Self::new_with_application(sample_rate, channels, Application::Voip);
144 enc.encoder.bitrate_bps = if channels == 2 { 64000 } else { 48000 };
145 enc.encoder.complexity = 5;
146 enc.encoder.use_cbr = true;
147 enc
148 }
149
150 pub fn new_default() -> Self {
152 Self::new(48000, 2)
153 }
154
155 pub fn set_bitrate(&mut self, bitrate_bps: i32) {
157 self.encoder.bitrate_bps = bitrate_bps;
158 }
159
160 pub fn set_complexity(&mut self, complexity: i32) {
162 self.encoder.complexity = complexity;
163 }
164
165 pub fn set_cbr(&mut self, cbr: bool) {
167 self.encoder.use_cbr = cbr;
168 }
169
170 pub fn encode_into(&mut self, samples: &[Sample], output: &mut [u8]) -> Option<usize> {
174 let channels = usize::from(self.channels);
175 if samples.is_empty() || channels == 0 || samples.len() % channels != 0 {
176 return None;
177 }
178
179 let frame_size = samples.len() / channels;
180
181 if self.w_input_f32.len() < samples.len() {
182 self.w_input_f32.resize(samples.len(), 0.0);
183 }
184
185 for (dst, &s) in self.w_input_f32[..samples.len()]
186 .iter_mut()
187 .zip(samples.iter())
188 {
189 *dst = s as f32 / 32768.0;
190 }
191
192 self.encoder
193 .encode(&self.w_input_f32[..samples.len()], frame_size, output)
194 .ok()
195 }
196
197 fn encode_raw(&mut self, samples: &[Sample]) -> Vec<u8> {
198 let channels = usize::from(self.channels);
199 if samples.is_empty() || channels == 0 || samples.len() % channels != 0 {
200 return Vec::new();
201 }
202
203 let frame_size = samples.len() / channels;
204
205 if self.w_input_f32.len() < samples.len() {
206 self.w_input_f32.resize(samples.len(), 0.0);
207 }
208
209 for (dst, &s) in self.w_input_f32[..samples.len()]
210 .iter_mut()
211 .zip(samples.iter())
212 {
213 *dst = s as f32 / 32768.0;
214 }
215
216 match self.encoder.encode(
217 &self.w_input_f32[..samples.len()],
218 frame_size,
219 &mut self.w_packet,
220 ) {
221 Ok(len) => {
222 let mut out = Vec::with_capacity(len);
223 out.extend_from_slice(&self.w_packet[..len]);
224 out
225 }
226 Err(_) => Vec::new(),
227 }
228 }
229}
230
231impl Encoder for OpusEncoder {
232 fn encode(&mut self, samples: &[Sample]) -> Vec<u8> {
233 if self.channels == 2 {
234 let mut stereo_samples = Vec::with_capacity(samples.len() * 2);
235 for &sample in samples {
236 stereo_samples.push(sample);
237 stereo_samples.push(sample);
238 }
239 return self.encode_raw(&stereo_samples);
240 }
241 self.encode_raw(samples)
242 }
243
244 fn sample_rate(&self) -> u32 {
245 self.sample_rate
246 }
247
248 fn channels(&self) -> u16 {
249 self.channels
250 }
251}
252
253#[cfg(test)]
254mod tests {
255 use super::*;
256
257 fn make_mono_pcm_20ms() -> Vec<i16> {
258 (0..960).map(|i| ((i * 100) % 32767) as i16).collect()
259 }
260
261 #[test]
262 fn test_opus_encode_decode_20ms_produces_960_mono_samples() {
263 let mut enc = OpusEncoder::new_default();
264 let pcm = make_mono_pcm_20ms();
265 let opus_pkt = enc.encode(&pcm);
266 assert!(!opus_pkt.is_empty(), "encoder should produce output");
267
268 assert!(opus_pkt[0] & 0x04 != 0, "packet should be stereo");
270
271 let mut dec = OpusDecoder::new_default();
272 let decoded = dec.decode(&opus_pkt);
273
274 assert_eq!(
276 decoded.len(),
277 960,
278 "decoder should downmix stereo→mono and output 960 samples, got {}",
279 decoded.len()
280 );
281 }
282
283 #[test]
284 fn test_opus_consecutive_frames_all_produce_960() {
285 let mut enc = OpusEncoder::new_default();
286 let pcm = make_mono_pcm_20ms();
287 let opus_pkt = enc.encode(&pcm);
288
289 let mut dec = OpusDecoder::new_default();
290 for i in 0..5 {
291 let decoded = dec.decode(&opus_pkt);
292 assert_eq!(
293 decoded.len(),
294 960,
295 "frame {} should produce 960 mono samples, got {}",
296 i,
297 decoded.len()
298 );
299 }
300 }
301
302 #[test]
303 fn test_opus_decoder_output_has_reasonable_energy() {
304 let mut enc = OpusEncoder::new_default();
305 let pcm: Vec<i16> = (0..960)
307 .map(|i| {
308 let t = i as f64 / 48000.0;
309 (16384.0 * (2.0 * std::f64::consts::PI * 440.0 * t).sin()) as i16
310 })
311 .collect();
312 let opus_pkt = enc.encode(&pcm);
313
314 let mut dec = OpusDecoder::new_default();
315 let decoded = dec.decode(&opus_pkt);
316 assert_eq!(decoded.len(), 960);
317
318 let energy: f64 =
319 decoded.iter().map(|&s| (s as f64).powi(2)).sum::<f64>() / decoded.len() as f64;
320 let rms = energy.sqrt();
321 assert!(
322 rms > 100.0 && rms < 20000.0,
323 "decoded audio RMS {} should be in reasonable range",
324 rms
325 );
326 }
327
328 #[test]
329 fn test_opus_decoder_handles_mono_packet_gracefully() {
330 let mut mono_enc = OpusEncoder::new(48000, 1);
332 let pcm = make_mono_pcm_20ms();
333 let mono_pkt = mono_enc.encode(&pcm);
334 assert!(!mono_pkt.is_empty());
335 assert!(
337 mono_pkt[0] & 0x04 == 0,
338 "mono encoder should produce mono packet"
339 );
340
341 let mut dec = OpusDecoder::new_default();
343 let decoded = dec.decode(&mono_pkt);
344 assert_eq!(
345 decoded.len(),
346 960,
347 "first mono packet should produce exactly 960 mono samples, got {}",
348 decoded.len()
349 );
350
351 let decoded2 = dec.decode(&mono_pkt);
353 assert_eq!(
354 decoded2.len(),
355 960,
356 "second mono packet should also produce 960 mono samples, got {}",
357 decoded2.len()
358 );
359 }
360
361 #[test]
362 fn test_opus_stereo_packet_downmix_produces_960() {
363 let mut enc = OpusEncoder::new_default();
364 let pcm = make_mono_pcm_20ms();
365 let stereo_pkt = enc.encode(&pcm);
366 assert!(stereo_pkt[0] & 0x04 != 0);
367
368 let mut dec = OpusDecoder::new_default();
369 let decoded = dec.decode(&stereo_pkt);
370 assert_eq!(
371 decoded.len(),
372 960,
373 "stereo packet should downmix to 960 mono samples"
374 );
375 }
376}