1#![cfg_attr(not(feature = "std"), no_std)]
2#![allow(unsafe_op_in_unsafe_fn)]
3#![allow(clippy::too_many_arguments)]
4#![allow(clippy::needless_range_loop)]
5
6mod compat;
7mod fixedvec;
8
9pub mod bands;
10pub mod celt;
11pub mod celt_lpc;
12pub mod hp_cutoff;
13pub mod kiss_fft;
14pub mod mdct;
15pub mod modes;
16pub mod pitch;
17pub mod pvq;
18pub mod quant_bands;
19pub mod range_coder;
20pub mod rate;
21pub mod silk;
22
23pub use silk::{SilkResampler, SilkResamplerDown1_3, SilkResamplerDown1_6};
24
25pub use celt::{CeltDecoder, CeltEncoder};
26use hp_cutoff::hp_cutoff;
27use range_coder::RangeCoder;
28use silk::control_codec::silk_control_encoder;
29use silk::enc_api::silk_encode;
30use silk::init_encoder::silk_init_encoder;
31use silk::lin2log::silk_lin2log;
32use silk::log2lin::silk_log2lin;
33use silk::macros::*;
34use silk::resampler::{silk_resampler_down2, silk_resampler_down2_3};
35use silk::structs::SilkEncoderState;
36use crate::fixedvec::FixedVec;
37
38const OPUS_MAX_CHANNELS: usize = 2;
40const OPUS_MAX_FRAME: usize = 5760;
43const OPUS_MAX_SUBFRAME: usize = 2880;
47const OPUS_SUBFRAME_SCRATCH: usize = OPUS_MAX_SUBFRAME * OPUS_MAX_CHANNELS;
49const OPUS_HP_MEM: usize = OPUS_MAX_CHANNELS * 2;
51const OPUS_PCM_I16: usize = 960 * OPUS_MAX_CHANNELS;
53const OPUS_PCM_TAIL: usize = 240 * OPUS_MAX_CHANNELS;
55const OPUS_MAX_PACKET_FRAMES: usize = 48;
58const OPUS_MAX_PACKET_BYTES: usize = 1276;
60
61#[derive(Debug, Clone, Copy, PartialEq, Eq)]
62pub enum Application {
63 Voip = 2048,
64 Audio = 2049,
65 RestrictedLowDelay = 2051,
66}
67
68#[derive(Debug, Clone, Copy, PartialEq, Eq)]
69pub enum Bandwidth {
70 Auto = -1000,
71 Narrowband = 1101,
72 Mediumband = 1102,
73 Wideband = 1103,
74 Superwideband = 1104,
75 Fullband = 1105,
76}
77
78#[derive(Debug, Clone, Copy, PartialEq, Eq)]
79enum OpusMode {
80 SilkOnly,
81 Hybrid,
82 CeltOnly,
83}
84
85pub struct OpusEncoder {
86 #[cfg(not(feature = "heap"))]
87 celt_enc: CeltEncoder,
88 #[cfg(feature = "heap")]
89 celt_enc: Box<CeltEncoder>,
90 #[cfg(not(feature = "heap"))]
91 silk_enc: SilkEncoderState,
92 #[cfg(feature = "heap")]
93 silk_enc: Box<SilkEncoderState>,
94 application: Application,
95 sampling_rate: i32,
96 channels: usize,
97 bandwidth: Bandwidth,
98 pub bitrate_bps: i32,
99 pub complexity: i32,
100 pub use_cbr: bool,
101
102 pub use_inband_fec: bool,
103
104 pub packet_loss_perc: i32,
105 silk_initialized: bool,
106 mode: OpusMode,
107 prev_enc_mode: Option<OpusMode>,
108
109 variable_hp_smth2_q15: i32,
110 hp_mem: FixedVec<i32, OPUS_HP_MEM>,
111
112 #[cfg(not(feature = "heap"))]
113 buf_filtered: FixedVec<i16, OPUS_MAX_FRAME>,
114 #[cfg(feature = "heap")]
115 buf_filtered: Box<FixedVec<i16, OPUS_MAX_FRAME>>,
116 #[cfg(not(feature = "heap"))]
117 buf_silk_input: FixedVec<i16, OPUS_MAX_FRAME>,
118 #[cfg(feature = "heap")]
119 buf_silk_input: Box<FixedVec<i16, OPUS_MAX_FRAME>>,
120 #[cfg(not(feature = "heap"))]
121 buf_stereo_mid: FixedVec<i16, OPUS_MAX_FRAME>,
122 #[cfg(feature = "heap")]
123 buf_stereo_mid: Box<FixedVec<i16, OPUS_MAX_FRAME>>,
124 #[cfg(not(feature = "heap"))]
125 buf_stereo_side: FixedVec<i16, OPUS_MAX_FRAME>,
126 #[cfg(feature = "heap")]
127 buf_stereo_side: Box<FixedVec<i16, OPUS_MAX_FRAME>>,
128 #[cfg(not(feature = "heap"))]
129 buf_celt_input: FixedVec<f32, OPUS_MAX_FRAME>,
130 #[cfg(feature = "heap")]
131 buf_celt_input: Box<FixedVec<f32, OPUS_MAX_FRAME>>,
132 down2_state_first: [i32; 2],
133 down2_state_second: [i32; 2],
134 down2_3_state: [i32; 6],
135 down_1_3_state: silk::resampler::SilkResamplerDown1_3,
136
137 rc: RangeCoder,
138}
139
140fn compute_equiv_rate(
141 bitrate: i32,
142 channels: usize,
143 frame_rate: i32,
144 vbr: bool,
145 complexity: i32,
146 loss: i32,
147) -> i32 {
148 let mut equiv = bitrate;
149 if frame_rate > 50 {
150 equiv -= (40 * channels as i32 + 20) * (frame_rate - 50);
151 }
152 if !vbr {
153 equiv -= equiv / 12;
154 }
155 equiv = equiv * (90 + complexity) / 100;
156 if loss > 0 {
157 equiv -= equiv * loss / (12 * loss + 20);
158 }
159 equiv
160}
161
162fn compute_mode_threshold(
163 application: Application,
164 channels: usize,
165 prev_was_celt: bool,
166 has_prev_mode: bool,
167 voice_est: i32,
168) -> i32 {
169 let mode_voice = if channels == 1 { 64000 } else { 44000 };
170 let mode_music = 10000;
171
172 let diff = mode_voice - mode_music;
173 let offset = (voice_est * voice_est * diff) >> 14;
174 let mut threshold = mode_music + offset;
175
176 if application == Application::Voip {
177 threshold += 8000;
178 }
179
180 if has_prev_mode {
181 if prev_was_celt {
182 threshold -= 4000;
183 } else {
184 threshold += 4000;
185 }
186 }
187
188 if application == Application::RestrictedLowDelay {
189 threshold = 0;
190 }
191
192 threshold
193}
194
195fn compute_silk_rate_for_hybrid(rate_bps: i32, frame20ms: bool) -> i32 {
196 const RATE_TABLE: &[(i32, i32, i32)] = &[
197 (0, 0, 0),
198 (12000, 10000, 10000),
199 (16000, 13500, 13500),
200 (20000, 16000, 16000),
201 (24000, 18000, 18000),
202 (32000, 22000, 22000),
203 (64000, 38000, 38000),
204 ];
205 let n = RATE_TABLE.len();
206 let mut i = 1;
207 while i < n && RATE_TABLE[i].0 <= rate_bps {
208 i += 1;
209 }
210 if i == n {
211 let (x_last, r10_last, r20_last) = RATE_TABLE[n - 1];
212 let base = if frame20ms { r20_last } else { r10_last };
213 base + (rate_bps - x_last) / 2
214 } else {
215 let (x0, lo10, lo20) = RATE_TABLE[i - 1];
216 let (x1, hi10, hi20) = RATE_TABLE[i];
217 let (lo, hi) = if frame20ms {
218 (lo20, hi20)
219 } else {
220 (lo10, hi10)
221 };
222 (lo * (x1 - rate_bps) + hi * (rate_bps - x0)) / (x1 - x0)
223 }
224}
225
226#[cfg(all(test, feature = "std"))]
227mod silk_rate_tests {
228 use super::compute_silk_rate_for_hybrid;
229
230 #[test]
231 fn test_reference_table_exact_entries() {
232 assert_eq!(compute_silk_rate_for_hybrid(12000, true), 10000);
233 assert_eq!(compute_silk_rate_for_hybrid(16000, true), 13500);
234 assert_eq!(compute_silk_rate_for_hybrid(20000, true), 16000);
235 assert_eq!(compute_silk_rate_for_hybrid(24000, true), 18000);
236 assert_eq!(compute_silk_rate_for_hybrid(32000, true), 22000);
237 assert_eq!(compute_silk_rate_for_hybrid(64000, true), 38000);
238 }
239
240 #[test]
241 fn test_32kbps_gives_22kbps_silk() {
242 assert_eq!(compute_silk_rate_for_hybrid(32000, true), 22000);
243 }
244
245 #[test]
246 fn test_interpolation_between_table_entries() {
247 let r = compute_silk_rate_for_hybrid(18000, true);
248 assert_eq!(r, 14750);
249 }
250
251 #[test]
252 fn test_above_table_max_gives_half_extra() {
253 let r = compute_silk_rate_for_hybrid(72000, true);
254 assert_eq!(r, 38000 + (72000 - 64000) / 2);
255 }
256}
257
258#[cfg(feature = "heap")]
267#[inline(always)]
268fn state_ref<T: core::ops::Deref>(b: &T) -> &T::Target {
269 b
270}
271#[cfg(not(feature = "heap"))]
272#[inline(always)]
273fn state_ref<T: ?Sized>(b: &T) -> &T {
274 b
275}
276
277#[cfg(feature = "heap")]
278#[inline(always)]
279fn state_mut<T: core::ops::DerefMut>(b: &mut T) -> &mut T::Target {
280 b
281}
282#[cfg(not(feature = "heap"))]
283#[inline(always)]
284fn state_mut<T: ?Sized>(b: &mut T) -> &mut T {
285 b
286}
287
288impl OpusEncoder {
289 pub fn new(
290 sampling_rate: i32,
291 channels: usize,
292 application: Application,
293 ) -> Result<Self, &'static str> {
294 if ![8000, 12000, 16000, 24000, 48000].contains(&sampling_rate) {
295 return Err("Invalid sampling rate");
296 }
297 if ![1, 2].contains(&channels) {
298 return Err("Invalid number of channels");
299 }
300
301 let mode = modes::default_mode();
302 #[cfg(feature = "heap")]
303 let celt_enc = Box::new(CeltEncoder::new(mode, channels));
304 #[cfg(not(feature = "heap"))]
305 let celt_enc = CeltEncoder::new(mode, channels);
306
307 #[cfg(feature = "heap")]
308 let mut silk_enc = Box::new(SilkEncoderState::default());
309 #[cfg(not(feature = "heap"))]
310 let mut silk_enc = SilkEncoderState::default();
311 if silk_init_encoder(state_mut(&mut silk_enc), 0) != 0 {
312 return Err("SILK encoder initialization failed");
313 }
314
315 let (opus_mode, bw) = match application {
316 Application::Voip => {
317 let bw = match sampling_rate {
318 8000 => Bandwidth::Narrowband,
319 12000 => Bandwidth::Mediumband,
320 16000 => Bandwidth::Wideband,
321 24000 => Bandwidth::Superwideband,
322 48000 => Bandwidth::Fullband,
323 _ => Bandwidth::Narrowband,
324 };
325
326 let mode = if sampling_rate > 16000 {
327 OpusMode::Hybrid
328 } else {
329 OpusMode::SilkOnly
330 };
331 (mode, bw)
332 }
333 Application::RestrictedLowDelay => {
334 let bw = match sampling_rate {
335 8000 => Bandwidth::Narrowband,
336 12000 => Bandwidth::Mediumband,
337 16000 => Bandwidth::Wideband,
338 24000 => Bandwidth::Superwideband,
339 _ => Bandwidth::Fullband,
340 };
341 (OpusMode::CeltOnly, bw)
342 }
343 Application::Audio => {
344 if sampling_rate <= 16000 {
345 let bw = match sampling_rate {
346 8000 => Bandwidth::Narrowband,
347 12000 => Bandwidth::Mediumband,
348 _ => Bandwidth::Wideband,
349 };
350 (OpusMode::SilkOnly, bw)
351 } else {
352 let bw = match sampling_rate {
353 24000 => Bandwidth::Superwideband,
354 _ => Bandwidth::Fullband,
355 };
356 (OpusMode::Hybrid, bw)
357 }
358 }
359 };
360
361 use silk::lin2log::silk_lin2log;
362 let variable_hp_smth2_q15 = silk_lin2log(60) << 8;
363
364 Ok(Self {
365 celt_enc,
366 silk_enc,
367 application,
368 sampling_rate,
369 channels,
370 bandwidth: bw,
371 bitrate_bps: 64000,
372 complexity: 9,
373 use_cbr: false,
374 use_inband_fec: false,
375 packet_loss_perc: 0,
376 silk_initialized: false,
377 prev_enc_mode: None,
378 mode: opus_mode,
379 variable_hp_smth2_q15,
380 hp_mem: FixedVec::from_value(0, channels * 2),
381
382 #[cfg(not(feature = "heap"))]
383 buf_filtered: FixedVec::new(),
384 #[cfg(feature = "heap")]
385 buf_filtered: Box::new(FixedVec::new()),
386 #[cfg(not(feature = "heap"))]
387 buf_silk_input: FixedVec::new(),
388 #[cfg(feature = "heap")]
389 buf_silk_input: Box::new(FixedVec::new()),
390 #[cfg(not(feature = "heap"))]
391 buf_stereo_mid: FixedVec::new(),
392 #[cfg(feature = "heap")]
393 buf_stereo_mid: Box::new(FixedVec::new()),
394 #[cfg(not(feature = "heap"))]
395 buf_stereo_side: FixedVec::new(),
396 #[cfg(feature = "heap")]
397 buf_stereo_side: Box::new(FixedVec::new()),
398 #[cfg(not(feature = "heap"))]
399 buf_celt_input: FixedVec::new(),
400 #[cfg(feature = "heap")]
401 buf_celt_input: Box::new(FixedVec::new()),
402 down2_state_first: [0; 2],
403 down2_state_second: [0; 2],
404 down2_3_state: [0; 6],
405 down_1_3_state: silk::resampler::SilkResamplerDown1_3::default(),
406 rc: RangeCoder::new_encoder(1),
407 })
408 }
409
410 pub fn enable_hybrid_mode(&mut self) -> Result<(), &'static str> {
411 if self.sampling_rate != 24000 && self.sampling_rate != 48000 {
412 return Err("Hybrid mode requires 24kHz or 48kHz sampling rate");
413 }
414 let bw = if self.sampling_rate == 48000 {
415 Bandwidth::Fullband
416 } else {
417 Bandwidth::Superwideband
418 };
419 self.mode = OpusMode::Hybrid;
420 self.bandwidth = bw;
421 self.silk_initialized = false;
422 Ok(())
423 }
424
425 pub fn encode(
426 &mut self,
427 input: &[f32],
428 frame_size: usize,
429 output: &mut [u8],
430 ) -> Result<usize, &'static str> {
431 if output.len() < 2 {
432 return Err("Output buffer too small");
433 }
434
435 let frame_rate = frame_rate_from_params(self.sampling_rate, frame_size)
436 .ok_or("Invalid frame size for sampling rate")?;
437
438 let mut mode = if self.application == Application::RestrictedLowDelay {
442 OpusMode::CeltOnly
443 } else {
444 let equiv = compute_equiv_rate(
445 self.bitrate_bps,
446 self.channels,
447 frame_rate,
448 !self.use_cbr,
449 self.complexity,
450 self.packet_loss_perc,
451 );
452 let prev_was_celt = self.prev_enc_mode == Some(OpusMode::CeltOnly);
453 let has_prev_mode = self.prev_enc_mode.is_some();
454 let voice_est = match self.application {
455 Application::Voip => 115,
456 Application::Audio => 48,
457 Application::RestrictedLowDelay => 0,
458 };
459 let threshold = compute_mode_threshold(
460 self.application,
461 self.channels,
462 prev_was_celt,
463 has_prev_mode,
464 voice_est,
465 );
466 if equiv >= threshold && self.sampling_rate >= 24000 {
467 OpusMode::CeltOnly
468 } else {
469 OpusMode::SilkOnly
470 }
471 };
472
473 let curr_bw = self.bandwidth;
474 if mode == OpusMode::SilkOnly
475 && (curr_bw == Bandwidth::Superwideband || curr_bw == Bandwidth::Fullband)
476 {
477 mode = OpusMode::Hybrid;
478 }
479 if mode == OpusMode::Hybrid
480 && (curr_bw == Bandwidth::Narrowband
481 || curr_bw == Bandwidth::Mediumband
482 || curr_bw == Bandwidth::Wideband)
483 {
484 mode = OpusMode::SilkOnly;
485 }
486
487 if mode == OpusMode::CeltOnly {
488 match frame_rate {
489 400 | 200 | 100 | 50 => {}
490 _ => return Err("Unsupported frame size for CELT-only mode"),
491 }
492 }
493
494 if mode == OpusMode::Hybrid {
495 match frame_rate {
496 100 | 50 => {}
497 _ => return Err("Unsupported frame size for Hybrid mode"),
498 }
499 }
500
501 if mode == OpusMode::SilkOnly {
502 match frame_rate {
503 400 | 200 | 100 | 50 | 25 => {}
504 _ => return Err("Unsupported frame size for SILK-only mode"),
505 }
506 }
507
508 let toc = gen_toc(mode, frame_rate, self.bandwidth, self.channels);
509 output[0] = toc;
510
511 let target_bits =
512 (self.bitrate_bps as i64 * frame_size as i64 / self.sampling_rate as i64) as i32;
513 let cbr_bytes = ((target_bits + 4) / 8) as usize;
514 let max_data_bytes = output.len();
515
516 let mut n_bytes = cbr_bytes
519 .min(max_data_bytes)
520 .max(1)
521 .min(OPUS_MAX_PACKET_BYTES);
522 let init_rc_size = n_bytes - 1;
523 self.rc.reset_for_encode(init_rc_size as u32);
524
525 if mode == OpusMode::SilkOnly || mode == OpusMode::Hybrid {
526 let silk_fs_khz = if mode == OpusMode::Hybrid {
527 16
528 } else {
529 self.sampling_rate.min(16000) / 1000
530 };
531
532 let frame_ms = (frame_size as i32 * 1000) / self.sampling_rate;
533 if !self.silk_initialized || self.silk_enc.s_cmn.fs_khz != silk_fs_khz {
534 let silk_init_bitrate = (((n_bytes - 1) * 8) as i64 * self.sampling_rate as i64
535 / frame_size as i64) as i32;
536 silk_control_encoder(
537 state_mut(&mut self.silk_enc),
538 silk_fs_khz,
539 frame_ms,
540 silk_init_bitrate,
541 self.complexity,
542 );
543 self.silk_enc.s_cmn.use_cbr = if self.use_cbr { 1 } else { 0 };
544
545 self.silk_enc.s_cmn.n_channels = self.channels as i32;
546 self.silk_initialized = true;
547 self.down2_state_first = [0; 2];
548 self.down2_state_second = [0; 2];
549 self.down2_3_state = [0; 6];
550 self.down_1_3_state = silk::resampler::SilkResamplerDown1_3::default();
551 }
552
553 self.silk_enc.s_cmn.use_in_band_fec = if self.use_inband_fec { 1 } else { 0 };
554 self.silk_enc.s_cmn.packet_loss_perc = self.packet_loss_perc.clamp(0, 100);
555
556 self.silk_enc.s_cmn.lbrr_enabled = if self.use_inband_fec { 1 } else { 0 };
557
558 if self.silk_enc.s_cmn.lbrr_gain_increases == 0 {
559 self.silk_enc.s_cmn.lbrr_gain_increases = 2;
560 }
561
562 let hp_freq_smth1 = if mode == OpusMode::CeltOnly {
563 silk_lin2log(60) << 8
564 } else {
565 self.silk_enc.s_cmn.variable_hp_smth1_q15
566 };
567
568 const VARIABLE_HP_SMTH_COEF2_Q16: i32 = 984;
569 self.variable_hp_smth2_q15 = silk_smlawb(
570 self.variable_hp_smth2_q15,
571 hp_freq_smth1 - self.variable_hp_smth2_q15,
572 VARIABLE_HP_SMTH_COEF2_Q16,
573 );
574
575 let cutoff_hz = silk_log2lin(silk_rshift(self.variable_hp_smth2_q15, 8));
576
577 let required_size = frame_size * self.channels;
578 self.buf_filtered.resize(required_size, 0);
579 if self.application == Application::Voip {
580 hp_cutoff(
581 input,
582 cutoff_hz,
583 state_mut(&mut self.buf_filtered),
584 &mut self.hp_mem,
585 frame_size,
586 self.channels,
587 self.sampling_rate,
588 );
589 } else {
590 for (i, &x) in input.iter().enumerate() {
591 self.buf_filtered[i] = (x * 32768.0).clamp(-32768.0, 32767.0) as i16;
592 }
593 }
594
595 let input_i16 = state_ref(&self.buf_filtered);
596
597 let silk_input: &[i16] = if mode == OpusMode::SilkOnly && self.sampling_rate > 16000 {
598 if self.sampling_rate == 48000 {
599 let stage1_size = frame_size / 2;
600 let mut stage1_buf = [0i16; 480];
601 silk_resampler_down2(
602 &mut self.down2_state_first,
603 &mut stage1_buf[..stage1_size],
604 input_i16,
605 frame_size as i32,
606 );
607 let silk_frame_size = stage1_size * 2 / 3;
608 self.buf_silk_input.resize(silk_frame_size, 0);
609 silk_resampler_down2_3(
610 &mut self.down2_3_state,
611 state_mut(&mut self.buf_silk_input),
612 &stage1_buf[..stage1_size],
613 stage1_size as i32,
614 );
615 state_ref(&self.buf_silk_input)
616 } else if self.sampling_rate == 24000 {
617 let silk_frame_size = frame_size * 2 / 3;
618 self.buf_silk_input.resize(silk_frame_size, 0);
619 silk_resampler_down2_3(
620 &mut self.down2_3_state,
621 state_mut(&mut self.buf_silk_input),
622 input_i16,
623 frame_size as i32,
624 );
625 state_ref(&self.buf_silk_input)
626 } else {
627 input_i16
628 }
629 } else if mode == OpusMode::SilkOnly && self.channels == 2 {
630 let frame_length = input_i16.len() / 2;
631 self.buf_stereo_mid.resize(frame_length, 0);
632 self.buf_stereo_side.resize(frame_length, 0);
633 for i in 0..frame_length {
634 let l = input_i16[2 * i] as i32;
635 let r = input_i16[2 * i + 1] as i32;
636 self.buf_stereo_mid[i] = ((l + r) / 2) as i16;
637 self.buf_stereo_side[i] = (l - r) as i16;
638 }
639
640 self.silk_enc.stereo.side.resize(frame_length, 0);
641 self.silk_enc
642 .stereo
643 .side
644 .copy_from_slice(&self.buf_stereo_side[..frame_length]);
645 state_ref(&self.buf_stereo_mid)
646 } else if mode == OpusMode::Hybrid && self.sampling_rate > 16000 {
647 if self.sampling_rate == 48000 {
648 let silk_frame_size = frame_size / 3;
649 self.buf_silk_input.resize(silk_frame_size, 0);
650 silk::resampler::silk_resampler_down_1_3(
651 &mut self.down_1_3_state,
652 state_mut(&mut self.buf_silk_input),
653 input_i16,
654 );
655 } else {
656 let silk_frame_size = frame_size * 2 / 3;
657 self.buf_silk_input.resize(silk_frame_size, 0);
658 silk_resampler_down2_3(
659 &mut self.down2_3_state,
660 state_mut(&mut self.buf_silk_input),
661 input_i16,
662 frame_size as i32,
663 );
664 }
665 state_ref(&self.buf_silk_input)
666 } else {
667 input_i16
668 };
669
670 let mut pn_bytes = 0;
671
672 let silk_rate_for_calc = if mode == OpusMode::Hybrid {
673 16000
674 } else {
675 self.sampling_rate
676 };
677 let silk_frame_len = silk_input.len();
678
679 let silk_bitrate = if mode == OpusMode::Hybrid {
680 let frame_duration_ms = frame_size as i32 * 1000 / self.sampling_rate;
681 let frame20ms = frame_duration_ms >= 20;
682 compute_silk_rate_for_hybrid(self.bitrate_bps, frame20ms)
683 } else {
684 (8i64 * (n_bytes - 1) as i64 * silk_rate_for_calc as i64 / silk_frame_len as i64)
685 as i32
686 };
687 let silk_max_bits = if mode == OpusMode::Hybrid {
688 let total_max_bits = ((n_bytes - 1) * 8) as i32;
689 if self.use_cbr {
690 let silk_bits = (silk_bitrate as i64 * silk_frame_len as i64
691 / silk_rate_for_calc as i64) as i32;
692 let other_bits = 0i32.max(total_max_bits - silk_bits);
693 0i32.max(total_max_bits - other_bits * 3 / 4)
694 } else {
695 let frame_duration_ms = frame_size as i32 * 1000 / self.sampling_rate;
696 let frame20ms = frame_duration_ms >= 20;
697 let max_bit_rate = compute_silk_rate_for_hybrid(
698 total_max_bits * self.sampling_rate / frame_size as i32,
699 frame20ms,
700 );
701 max_bit_rate * frame_size as i32 / self.sampling_rate
702 }
703 } else {
704 ((n_bytes - 1) * 8) as i32
705 };
706 let silk_use_cbr = if mode == OpusMode::Hybrid && self.use_cbr {
707 0
708 } else if self.use_cbr {
709 1
710 } else {
711 0
712 };
713 let ret = silk_encode(
714 state_mut(&mut self.silk_enc),
715 silk_input,
716 silk_input.len(),
717 &mut self.rc,
718 &mut pn_bytes,
719 silk_bitrate,
720 silk_max_bits,
721 silk_use_cbr,
722 1,
723 );
724 if ret != 0 {
725 return Err("SILK encoding failed");
726 }
727 }
728
729 if mode == OpusMode::Hybrid {
730 self.rc.encode_bit_logp(false, 12); }
732
733 if mode == OpusMode::Hybrid {
734 let nb_compr_bytes = (n_bytes - 1) as u32;
735 self.rc.shrink(nb_compr_bytes);
736 }
737
738 let silk_ret_bytes = if mode == OpusMode::SilkOnly {
739 ((self.rc.tell() + 7) >> 3) as usize
740 } else {
741 0
742 };
743
744 if mode != OpusMode::SilkOnly {
747 let tell = self.rc.tell();
748 if tell > 1 {
749 let tmp = self.bitrate_bps as i64 * frame_size as i64 + tell as i64 * self.sampling_rate as i64;
750 let adjusted = ((tmp + 4 * self.sampling_rate as i64) / (8 * self.sampling_rate as i64)) as usize;
751 let new_n = adjusted.min(max_data_bytes).max(1).min(OPUS_MAX_PACKET_BYTES);
752 if new_n < n_bytes {
753 n_bytes = new_n;
754 let new_payload = n_bytes - 1;
756 self.rc.shrink(new_payload as u32);
757 }
758 }
759 }
760
761 if mode == OpusMode::CeltOnly || mode == OpusMode::Hybrid {
762 self.celt_enc.complexity = self.complexity;
763 let start_band = if mode == OpusMode::Hybrid { 17 } else { 0 };
764 let total_packet_bits = ((n_bytes - 1) * 8) as i32;
765 let celt_bitrate = if mode == OpusMode::Hybrid {
767 let frame_ms = frame_size as i32 * 1000 / self.sampling_rate;
768 let frame20ms = frame_ms >= 20;
769 let silk_rate = compute_silk_rate_for_hybrid(self.bitrate_bps, frame20ms);
770 (self.bitrate_bps - silk_rate).max(8000)
771 } else {
772 self.bitrate_bps
773 };
774 self.celt_enc.set_bitrate(celt_bitrate);
775 self.celt_enc.set_vbr(!self.use_cbr);
776 self.celt_enc.set_constrained_vbr(mode == OpusMode::CeltOnly);
778
779 let celt_input: &[f32] = if self.channels == 1 {
780 input
781 } else {
782 let n = frame_size * self.channels;
783 self.buf_celt_input.resize(n, 0.0);
784 for i in 0..frame_size {
785 for ch in 0..self.channels {
786 self.buf_celt_input[ch * frame_size + i] = input[i * self.channels + ch];
787 }
788 }
789 state_ref(&self.buf_celt_input)
790 };
791
792 if self.rc.tell() <= total_packet_bits {
793 let is_vbr = !self.use_cbr;
794 self.celt_enc.encode_with_budget_vbr(
795 celt_input,
796 frame_size,
797 &mut self.rc,
798 start_band,
799 total_packet_bits,
800 is_vbr,
801 );
802 }
803 }
804
805 self.rc.done();
806
807 if self.rc.error != 0 {
808 return Err("Range coder buffer overflow: encoded data exceeds packet budget");
809 }
810
811 if mode == OpusMode::SilkOnly {
812 let mut ret = silk_ret_bytes.min(self.rc.storage as usize);
813 while ret > 2 && self.rc.buf[ret - 1] == 0 {
814 ret -= 1;
815 }
816
817 let target_total = if self.use_cbr {
818 n_bytes.min(output.len())
819 } else {
820 (ret + 1).min(output.len())
821 };
822
823 let silk_len = ret;
824
825 if !self.use_cbr || silk_len + 1 >= target_total {
826 output[0] = toc;
828 let copy_len = silk_len.min(target_total - 1);
829 output[1..1 + copy_len].copy_from_slice(&self.rc.buf[..copy_len]);
830 return Ok((copy_len + 1).min(output.len()));
831 }
832
833 output[0] = toc | 0x03;
834
835 if silk_len + 2 >= target_total {
836 output[1] = 0x01;
837 let copy_len = (target_total - 2).min(silk_len);
838 output[2..2 + copy_len].copy_from_slice(&self.rc.buf[..copy_len]);
839 self.prev_enc_mode = Some(mode);
840 return Ok(target_total.min(output.len()));
841 }
842
843 let pad_amount = target_total - silk_len - 2;
844 output[1] = 0x41;
845
846 let nb_255s = (pad_amount - 1) / 255;
847 let mut ptr = 2;
848 for _ in 0..nb_255s {
849 output[ptr] = 255;
850 ptr += 1;
851 }
852 output[ptr] = (pad_amount - 255 * nb_255s - 1) as u8;
853 ptr += 1;
854
855 output[ptr..ptr + silk_len].copy_from_slice(&self.rc.buf[..silk_len]);
856 ptr += silk_len;
857
858 let fill_end = target_total.min(output.len());
859 for byte in output[ptr..fill_end].iter_mut() {
860 *byte = 0;
861 }
862
863 self.prev_enc_mode = Some(mode);
864 return Ok(target_total.min(output.len()));
865 }
866
867 let payload_len = (self.rc.storage as usize).min(output.len() - 1);
869 output[1..1 + payload_len].copy_from_slice(&self.rc.buf[..payload_len]);
870 self.prev_enc_mode = Some(mode);
871 Ok(payload_len + 1)
872 }
873}
874
875pub struct OpusDecoder {
876 #[cfg(not(feature = "heap"))]
877 celt_dec: CeltDecoder,
878 #[cfg(feature = "heap")]
879 celt_dec: Box<CeltDecoder>,
880 #[cfg(not(feature = "heap"))]
881 silk_dec: silk::dec_api::SilkDecoder,
882 #[cfg(feature = "heap")]
883 silk_dec: Box<silk::dec_api::SilkDecoder>,
884 sampling_rate: i32,
885 channels: usize,
886
887 prev_mode: Option<OpusMode>,
888
889 prev_redundancy: bool,
891 frame_size: usize,
892
893 bandwidth: Bandwidth,
894
895 stream_channels: usize,
896
897 silk_resampler: silk::resampler::SilkResampler,
898
899 silk_resampler_2: silk::resampler::SilkResampler,
901
902 prev_internal_rate: i32,
903
904 pub hybrid_skip_celt: bool,
905
906 #[cfg(not(feature = "heap"))]
907 w_pcm_i16: FixedVec<i16, OPUS_PCM_I16>,
908 #[cfg(feature = "heap")]
909 w_pcm_i16: Box<FixedVec<i16, OPUS_PCM_I16>>,
910 #[cfg(not(feature = "heap"))]
911 w_silk_out: FixedVec<f32, OPUS_SUBFRAME_SCRATCH>,
912 #[cfg(feature = "heap")]
913 w_silk_out: Box<FixedVec<f32, OPUS_SUBFRAME_SCRATCH>>,
914 #[cfg(not(feature = "heap"))]
915 w_pcm_resampled: FixedVec<i16, OPUS_SUBFRAME_SCRATCH>,
916 #[cfg(feature = "heap")]
917 w_pcm_resampled: Box<FixedVec<i16, OPUS_SUBFRAME_SCRATCH>>,
918 #[cfg(not(feature = "heap"))]
919 w_celt_planar: FixedVec<f32, OPUS_SUBFRAME_SCRATCH>,
920 #[cfg(feature = "heap")]
921 w_celt_planar: Box<FixedVec<f32, OPUS_SUBFRAME_SCRATCH>>,
922 #[cfg(not(feature = "heap"))]
923 w_celt_out: FixedVec<f32, OPUS_SUBFRAME_SCRATCH>,
924 #[cfg(feature = "heap")]
925 w_celt_out: Box<FixedVec<f32, OPUS_SUBFRAME_SCRATCH>>,
926
927 #[cfg(not(feature = "heap"))]
930 prev_pcm_tail: FixedVec<f32, OPUS_PCM_TAIL>,
931 #[cfg(feature = "heap")]
932 prev_pcm_tail: Box<FixedVec<f32, OPUS_PCM_TAIL>>,
933}
934
935impl OpusDecoder {
936 pub fn new(sampling_rate: i32, channels: usize) -> Result<Self, &'static str> {
937 if ![8000, 12000, 16000, 24000, 48000].contains(&sampling_rate) {
938 return Err("Invalid sampling rate");
939 }
940 if ![1, 2].contains(&channels) {
941 return Err("Invalid number of channels");
942 }
943
944 let mode = modes::default_mode();
945 #[cfg(feature = "heap")]
946 let celt_dec = Box::new(CeltDecoder::new(mode, channels, sampling_rate));
947 #[cfg(not(feature = "heap"))]
948 let celt_dec = CeltDecoder::new(mode, channels, sampling_rate);
949
950 #[cfg(feature = "heap")]
951 let mut silk_dec = Box::new(silk::dec_api::SilkDecoder::new());
952 #[cfg(not(feature = "heap"))]
953 let mut silk_dec = silk::dec_api::SilkDecoder::new();
954 silk_dec.init(sampling_rate.min(16000), channels as i32);
955 silk_dec.channel_state[0].fs_api_hz = sampling_rate;
956
957 Ok(Self {
958 celt_dec,
959 silk_dec,
960 sampling_rate,
961 channels,
962 prev_mode: None,
963 prev_redundancy: false,
964 frame_size: 0,
965 bandwidth: Bandwidth::Auto,
966 stream_channels: channels,
967 silk_resampler: silk::resampler::SilkResampler::default(),
968 silk_resampler_2: silk::resampler::SilkResampler::default(),
969 prev_internal_rate: 0,
970 hybrid_skip_celt: false,
971
972 #[cfg(not(feature = "heap"))]
973 w_pcm_i16: FixedVec::from_value(0i16, 960 * channels),
974 #[cfg(feature = "heap")]
975 w_pcm_i16: Box::new(FixedVec::from_value(0i16, 960 * channels)),
976
977 #[cfg(not(feature = "heap"))]
978 w_silk_out: FixedVec::from_value(0.0f32, OPUS_MAX_SUBFRAME * channels),
979 #[cfg(feature = "heap")]
980 w_silk_out: Box::new(FixedVec::from_value(0.0f32, OPUS_MAX_SUBFRAME * channels)),
981 #[cfg(not(feature = "heap"))]
982 w_pcm_resampled: FixedVec::from_value(0i16, OPUS_MAX_SUBFRAME * channels),
983 #[cfg(feature = "heap")]
984 w_pcm_resampled: Box::new(FixedVec::from_value(0i16, OPUS_MAX_SUBFRAME * channels)),
985 #[cfg(not(feature = "heap"))]
986 w_celt_planar: FixedVec::from_value(0.0f32, OPUS_MAX_SUBFRAME * channels),
987 #[cfg(feature = "heap")]
988 w_celt_planar: Box::new(FixedVec::from_value(0.0f32, OPUS_MAX_SUBFRAME * channels)),
989 #[cfg(not(feature = "heap"))]
990 w_celt_out: FixedVec::from_value(0.0f32, OPUS_MAX_SUBFRAME * channels),
991 #[cfg(feature = "heap")]
992 w_celt_out: Box::new(FixedVec::from_value(0.0f32, OPUS_MAX_SUBFRAME * channels)),
993
994 #[cfg(not(feature = "heap"))]
995 prev_pcm_tail: FixedVec::from_value(0.0f32, 240 * channels),
996 #[cfg(feature = "heap")]
997 prev_pcm_tail: Box::new(FixedVec::from_value(0.0f32, 240 * channels)),
998 })
999 }
1000
1001 pub fn decode(
1002 &mut self,
1003 input: &[u8],
1004 frame_size: usize,
1005 output: &mut [f32],
1006 ) -> Result<usize, &'static str> {
1007 if input.is_empty() {
1008 return Err("Input packet empty");
1009 }
1010
1011 let toc = input[0];
1012 let mode = mode_from_toc(toc);
1013 let packet_channels = channels_from_toc(toc);
1014 let bandwidth = bandwidth_from_toc(toc);
1015 let frame_duration_ms = frame_duration_ms_from_toc(toc);
1016
1017 let lost_frame = input.len() <= 1;
1021
1022 if packet_channels != self.channels {
1023 return Err("Channel count mismatch between packet and decoder");
1024 }
1025
1026 let code = toc & 0x03;
1027 let frame_count: usize;
1028 let frame_payloads: FixedVec<&[u8], OPUS_MAX_PACKET_FRAMES>;
1029
1030 match code {
1031 0 => {
1032 frame_count = 1;
1033 frame_payloads = FixedVec::from_slice(&[&input[1..]]);
1034 }
1035 1 => {
1036 frame_count = 2;
1037 let data_len = input.len() - 1;
1038 if data_len % 2 != 0 {
1041 return Err("Code 1: payload length must be even");
1042 }
1043 let half = data_len / 2;
1044 if half == 0 {
1045 return Err("Code 1: empty frame");
1046 }
1047 frame_payloads = FixedVec::from_slice(&[&input[1..1 + half], &input[1 + half..]]);
1048 }
1049 2 => {
1050 frame_count = 2;
1051 let data = &input[1..];
1052 if data.is_empty() {
1053 return Err("Code 2 packet has no data");
1054 }
1055 let (first_len, header_size) = parse_frame_size(data)?;
1056 if header_size + first_len > data.len() {
1057 return Err("Code 2: first frame size exceeds packet");
1058 }
1059 frame_payloads = FixedVec::from_slice(&[
1060 &data[header_size..header_size + first_len],
1061 &data[header_size + first_len..],
1062 ]);
1063 }
1064 3 => {
1065 if input.len() < 2 {
1066 return Err("Code 3 packet too short");
1067 }
1068 let count_byte = input[1];
1069 let n_frames = (count_byte & 0x3F) as usize;
1070 if n_frames < 1 || n_frames > 48 {
1071 return Err("Code 3: invalid frame count");
1072 }
1073 frame_count = n_frames;
1074 let padding_flag = (count_byte & 0x40) != 0;
1076 let vbr = (count_byte & 0x80) != 0;
1077
1078 let mut ptr = 2usize;
1082 let mut pad_len = 0usize;
1083 if padding_flag {
1084 loop {
1085 if ptr >= input.len() {
1086 return Err("Code 3: padding overflow");
1087 }
1088 let p = input[ptr] as usize;
1089 ptr += 1;
1090 if p == 255 {
1091 pad_len += 254;
1092 } else {
1093 pad_len += p;
1094 break;
1095 }
1096 }
1097 }
1098 if ptr + pad_len > input.len() {
1099 return Err("Code 3: padding exceeds packet");
1100 }
1101 let payload_end = input.len() - pad_len;
1102 let payload = &input[ptr..payload_end];
1103
1104 let mut payloads: FixedVec<&[u8], OPUS_MAX_PACKET_FRAMES> = FixedVec::new();
1105 if frame_count == 1 {
1106 payloads.push(payload);
1109 } else if vbr {
1110 let mut cursor = 0usize;
1113 for i in 0..frame_count {
1114 if i + 1 < frame_count {
1115 if cursor >= payload.len() {
1116 return Err("Code 3: unexpected end in VBR header");
1117 }
1118 let (frame_len, header_bytes) =
1119 parse_frame_size(&payload[cursor..])?;
1120 cursor += header_bytes;
1121 if cursor + frame_len > payload.len() {
1122 return Err("Code 3: frame length exceeds packet");
1123 }
1124 payloads.push(&payload[cursor..cursor + frame_len]);
1125 cursor += frame_len;
1126 } else {
1127 if cursor > payload.len() {
1129 return Err("Code 3: no data for last frame");
1130 }
1131 payloads.push(&payload[cursor..]);
1132 }
1133 }
1134 } else {
1135 if payload.len() % frame_count != 0 {
1139 return Err("Code 3 CBR: payload not divisible by frame count");
1140 }
1141 let frame_len = payload.len() / frame_count;
1142 for i in 0..frame_count {
1143 payloads.push(&payload[i * frame_len..(i + 1) * frame_len]);
1144 }
1145 }
1146 frame_payloads = payloads;
1147 }
1148 _ => unreachable!(),
1149 }
1150
1151 self.frame_size = frame_size;
1152 self.bandwidth = bandwidth;
1153 self.stream_channels = packet_channels;
1154
1155 let toc_frame_size = frame_samples_from_toc(toc, self.sampling_rate)
1160 .ok_or("Invalid TOC for sampling rate")?;
1161 let decoded_total = toc_frame_size * frame_count;
1162 if frame_size < decoded_total {
1163 return Err("frame_size too small for packet");
1164 }
1165 if output.len() < decoded_total * self.channels {
1166 return Err("Output buffer too small for packet");
1167 }
1168 if output.len() > decoded_total * self.channels {
1171 for v in &mut output[decoded_total * self.channels..] {
1172 *v = 0.0;
1173 }
1174 }
1175 let sub_frame_size = toc_frame_size;
1176 let sub_output_len = sub_frame_size * self.channels;
1177
1178 let mode_transition = match self.prev_mode {
1184 Some(prev) if prev != mode && !self.prev_redundancy => true,
1185 _ => false,
1186 };
1187 if mode_transition {
1188 self.celt_dec.reset_state();
1189 }
1190
1191 let f5_bridge = self.sampling_rate as usize / 200; if mode_transition
1197 && f5_bridge > 0
1198 && matches!(
1199 self.prev_mode,
1200 Some(OpusMode::SilkOnly) | Some(OpusMode::Hybrid)
1201 )
1202 && self.prev_internal_rate > 0
1203 {
1204 let internal_rate = self.prev_internal_rate;
1205 let plc_internal_len = (10 * internal_rate / 1000) as usize;
1206 let mut plc_rc = RangeCoder::new_decoder(&[]);
1207 let mut plc_i16: FixedVec<i16, OPUS_PCM_I16> =
1208 FixedVec::from_value(0i16, plc_internal_len * self.channels);
1209 let n = self.silk_dec.decode(
1210 &mut plc_rc,
1211 &mut plc_i16,
1212 silk::decode_frame::FLAG_PACKET_LOST,
1213 true,
1214 10,
1215 internal_rate,
1216 );
1217 if n > 0 {
1218 let bridge_ch = f5_bridge * self.channels;
1219 let bridge_len = bridge_ch.min(self.prev_pcm_tail.len());
1220 if internal_rate == self.sampling_rate {
1221 let n_us = n as usize;
1223 for ch in 0..self.channels {
1224 let src_base = ch * n_us;
1225 for i in 0..(bridge_len / self.channels).min(n_us) {
1226 let dst = i * self.channels + ch;
1227 if dst < bridge_len {
1228 self.prev_pcm_tail[dst] = plc_i16[src_base + i] as f32 / 32768.0;
1229 }
1230 }
1231 }
1232 } else if self.silk_resampler.is_initialized() {
1233 let ratio = self.sampling_rate as f64 / internal_rate as f64;
1235 let out_len = ((n as f64 * ratio) as usize).min(f5_bridge);
1236 let n_us = n as usize;
1237 let mut resampled: FixedVec<i16, OPUS_MAX_FRAME> = FixedVec::from_value(0i16, out_len);
1238 self.silk_resampler.process(
1239 &mut resampled,
1240 &plc_i16[..n_us],
1241 n,
1242 );
1243 for i in 0..out_len {
1244 if i < bridge_len / self.channels {
1245 for ch in 0..self.channels {
1246 self.prev_pcm_tail[i * self.channels + ch] =
1247 resampled[i] as f32 / 32768.0;
1248 }
1249 }
1250 }
1251 }
1252 }
1253 }
1254
1255 let mut has_redundancy = false;
1257
1258 match mode {
1259 OpusMode::SilkOnly => {
1260 let internal_sample_rate = match bandwidth {
1261 Bandwidth::Narrowband => 8000,
1262 Bandwidth::Mediumband => 12000,
1263 Bandwidth::Wideband => 16000,
1264 _ => 16000,
1265 };
1266 let internal_frame_size =
1267 (frame_duration_ms * internal_sample_rate / 1000) as usize;
1268
1269 if self.sampling_rate != internal_sample_rate
1270 && internal_sample_rate != self.prev_internal_rate
1271 {
1272 self.silk_resampler
1273 .init(internal_sample_rate, self.sampling_rate);
1274 self.silk_resampler_2
1275 .init(internal_sample_rate, self.sampling_rate);
1276 }
1277 self.prev_internal_rate = internal_sample_rate;
1281
1282 for (fi, payload) in frame_payloads.iter().enumerate() {
1283 let mut rc = RangeCoder::new_decoder(payload);
1284 let pcm_i16_len = internal_frame_size * self.channels;
1285 debug_assert!(pcm_i16_len <= self.w_pcm_i16.len());
1286
1287 let ret = {
1288 let (silk_dec, pcm_i16) =
1289 (state_mut(&mut self.silk_dec), state_mut(&mut self.w_pcm_i16));
1290 let lost_flag = if lost_frame {
1291 silk::decode_frame::FLAG_PACKET_LOST
1292 } else {
1293 silk::decode_frame::FLAG_DECODE_NORMAL
1294 };
1295 silk_dec.decode(
1296 &mut rc,
1297 &mut pcm_i16[..pcm_i16_len],
1298 lost_flag,
1299 true,
1300 frame_duration_ms,
1301 internal_sample_rate,
1302 )
1303 };
1304
1305 if ret < 0 {
1306 return Err("SILK decoding failed");
1307 }
1308
1309 let decoded_samples = ret as usize;
1310 let out_start = fi * sub_output_len;
1311
1312 if self.sampling_rate == internal_sample_rate {
1314 let frames = decoded_samples.min(sub_frame_size);
1315 for i in 0..frames {
1316 for ch in 0..self.channels {
1317 let src = if ch == 0 { i } else { internal_frame_size + i };
1318 let v = self.w_pcm_i16[src] as f32 / 32768.0;
1319 let idx = out_start + i * self.channels + ch;
1320 if idx < output.len() {
1321 output[idx] = v;
1322 }
1323 }
1324 }
1325 } else {
1326 let ratio = self.sampling_rate as f64 / internal_sample_rate as f64;
1327 let out_len =
1328 ((decoded_samples as f64 * ratio) as usize).min(sub_frame_size);
1329 debug_assert!(out_len * self.channels <= self.w_pcm_resampled.len());
1330 {
1332 let (res, inp, out) = (
1333 &mut self.silk_resampler,
1334 state_ref(&self.w_pcm_i16),
1335 state_mut(&mut self.w_pcm_resampled),
1336 );
1337 res.process(
1338 &mut out[..out_len],
1339 &inp[..decoded_samples],
1340 decoded_samples as i32,
1341 );
1342 }
1343 if self.channels == 2 {
1345 let (res, inp, out) = (
1346 &mut self.silk_resampler_2,
1347 state_ref(&self.w_pcm_i16),
1348 state_mut(&mut self.w_pcm_resampled),
1349 );
1350 res.process(
1351 &mut out[out_len..2 * out_len],
1352 &inp[internal_frame_size..internal_frame_size + decoded_samples],
1353 decoded_samples as i32,
1354 );
1355 }
1356 let frames = out_len.min(sub_frame_size);
1357 for i in 0..frames {
1358 for ch in 0..self.channels {
1359 let v = self.w_pcm_resampled[ch * out_len + i] as f32 / 32768.0;
1360 let idx = out_start + i * self.channels + ch;
1361 if idx < output.len() {
1362 output[idx] = v;
1363 }
1364 }
1365 }
1366 }
1367 }
1368 decoded_total
1369 }
1370
1371 OpusMode::CeltOnly => {
1372 let celt_end_band = self.celt_end_band_from_toc(toc);
1373
1374 for (fi, payload) in frame_payloads.iter().enumerate() {
1375 let mut rc = RangeCoder::new_decoder(payload);
1376 let total_bits = (payload.len() * 8) as i32;
1377 let needed = sub_frame_size * self.channels;
1378 let out_start = fi * needed;
1379 let out_end = (out_start + needed).min(output.len());
1380
1381 if output.len() < out_end {
1382 return Err("Output buffer too small");
1383 }
1384
1385 if self.channels == 1 {
1386 self.celt_dec.decode_from_range_coder_with_band_range(
1387 &mut rc,
1388 total_bits,
1389 sub_frame_size,
1390 &mut output[out_start..out_end],
1391 0,
1392 celt_end_band,
1393 );
1394 for sample in &mut output[out_start..out_end] {
1395 *sample = sample.clamp(-1.0, 1.0);
1396 }
1397 } else {
1398 self.celt_dec.decode_from_range_coder_with_band_range(
1399 &mut rc,
1400 total_bits,
1401 sub_frame_size,
1402 &mut self.w_celt_planar[..needed],
1403 0,
1404 celt_end_band,
1405 );
1406 for i in 0..sub_frame_size {
1407 for ch in 0..self.channels {
1408 let idx = out_start + i * self.channels + ch;
1409 output[idx] =
1410 self.w_celt_planar[ch * sub_frame_size + i].clamp(-1.0, 1.0);
1411 }
1412 }
1413 }
1414 }
1415 decoded_total
1416 }
1417
1418 OpusMode::Hybrid => {
1419 let internal_sample_rate = 16000;
1420 let internal_frame_size =
1421 (frame_duration_ms * internal_sample_rate / 1000) as usize;
1422 let celt_end_band = self.celt_end_band_from_toc(toc);
1423
1424 if self.sampling_rate != internal_sample_rate
1425 && internal_sample_rate != self.prev_internal_rate
1426 {
1427 self.silk_resampler
1428 .init(internal_sample_rate, self.sampling_rate);
1429 self.silk_resampler_2
1430 .init(internal_sample_rate, self.sampling_rate);
1431 }
1432 self.prev_internal_rate = internal_sample_rate;
1433
1434 for (fi, payload) in frame_payloads.iter().enumerate() {
1435 let mut rc = RangeCoder::new_decoder(payload);
1436 let pcm_silk_i16_len = internal_frame_size * self.channels;
1437 debug_assert!(pcm_silk_i16_len <= self.w_pcm_i16.len());
1438
1439 let ret = {
1440 let (silk_dec, pcm_i16) =
1441 (state_mut(&mut self.silk_dec), state_mut(&mut self.w_pcm_i16));
1442 let lost_flag = if lost_frame {
1443 silk::decode_frame::FLAG_PACKET_LOST
1444 } else {
1445 silk::decode_frame::FLAG_DECODE_NORMAL
1446 };
1447 silk_dec.decode(
1448 &mut rc,
1449 &mut pcm_i16[..pcm_silk_i16_len],
1450 lost_flag,
1451 true,
1452 frame_duration_ms,
1453 internal_sample_rate,
1454 )
1455 };
1456
1457 if ret < 0 {
1458 return Err("SILK decoding failed");
1459 }
1460
1461 let silk_out_len = sub_frame_size * self.channels;
1462 self.w_silk_out[..silk_out_len].fill(0.0);
1463 if ret > 0 {
1464 let decoded_samples = ret as usize;
1465 if self.sampling_rate == internal_sample_rate {
1467 let frames = decoded_samples.min(sub_frame_size);
1468 for i in 0..frames {
1469 for ch in 0..self.channels {
1470 let src = if ch == 0 { i } else { internal_frame_size + i };
1471 let v = self.w_pcm_i16[src] as f32 / 32768.0;
1472 let idx = i * self.channels + ch;
1473 if idx < silk_out_len {
1474 self.w_silk_out[idx] = v;
1475 }
1476 }
1477 }
1478 } else {
1479 let ratio = self.sampling_rate as f64 / internal_sample_rate as f64;
1480 let out_len =
1481 ((decoded_samples as f64 * ratio) as usize).min(sub_frame_size);
1482 debug_assert!(out_len * self.channels <= self.w_pcm_resampled.len());
1483 {
1485 let (res, inp, out) = (
1486 &mut self.silk_resampler,
1487 state_ref(&self.w_pcm_i16),
1488 state_mut(&mut self.w_pcm_resampled),
1489 );
1490 res.process(
1491 &mut out[..out_len],
1492 &inp[..decoded_samples],
1493 decoded_samples as i32,
1494 );
1495 }
1496 if self.channels == 2 {
1498 let (res, inp, out) = (
1499 &mut self.silk_resampler_2,
1500 state_ref(&self.w_pcm_i16),
1501 state_mut(&mut self.w_pcm_resampled),
1502 );
1503 res.process(
1504 &mut out[out_len..2 * out_len],
1505 &inp[internal_frame_size..internal_frame_size + decoded_samples],
1506 decoded_samples as i32,
1507 );
1508 }
1509 let frames = out_len.min(sub_frame_size);
1510 for i in 0..frames {
1511 for ch in 0..self.channels {
1512 let v = self.w_pcm_resampled[ch * out_len + i] as f32 / 32768.0;
1513 let idx = i * self.channels + ch;
1514 if idx < silk_out_len {
1515 self.w_silk_out[idx] = v;
1516 }
1517 }
1518 }
1519 }
1520 }
1521
1522 let total_bits = (payload.len() * 8) as i32;
1523 let redundancy = rc.decode_bit_logp(12);
1524 let skip_celt = if redundancy {
1525 let _celt_to_silk = rc.decode_bit_logp(1);
1526 has_redundancy = true;
1527 true
1533 } else {
1534 false
1535 };
1536
1537 if skip_celt {
1538 self.w_celt_out[..silk_out_len].fill(0.0);
1539 } else {
1540 let (celt_dec, celt_planar) =
1541 (state_mut(&mut self.celt_dec), state_mut(&mut self.w_celt_planar));
1542 celt_dec.decode_from_range_coder_with_band_range(
1543 &mut rc,
1544 total_bits,
1545 sub_frame_size,
1546 &mut celt_planar[..silk_out_len],
1547 17,
1548 celt_end_band,
1549 );
1550
1551 if self.channels == 1 {
1552 self.w_celt_out[..silk_out_len]
1553 .copy_from_slice(&self.w_celt_planar[..silk_out_len]);
1554 } else {
1555 for i in 0..sub_frame_size {
1556 for ch in 0..self.channels {
1557 self.w_celt_out[i * self.channels + ch] =
1558 self.w_celt_planar[ch * sub_frame_size + i];
1559 }
1560 }
1561 }
1562 }
1563
1564 let out_start = fi * silk_out_len;
1565 let total = silk_out_len.min(output.len() - out_start);
1566 for j in 0..total {
1567 output[out_start + j] =
1568 (self.w_silk_out[j] + self.w_celt_out[j]).clamp(-1.0, 1.0);
1569 }
1570 }
1571 decoded_total
1572 }
1573 };
1574
1575 let f2_5 = self.sampling_rate as usize / 400;
1581 let f5 = f2_5 * 2;
1582 if mode_transition && f5 > 0 && decoded_total >= f5 {
1583 let window = modes::default_mode().window;
1584 let inc = (48000 / self.sampling_rate) as usize;
1585 let f2_5_ch = f2_5 * self.channels;
1586 let f5_ch = f5 * self.channels;
1587 output[..f2_5_ch].copy_from_slice(&self.prev_pcm_tail[..f2_5_ch]);
1589 let new_mid: FixedVec<f32, OPUS_PCM_TAIL> = FixedVec::from_slice(&output[f2_5_ch..f5_ch]);
1591 smooth_fade(
1592 &self.prev_pcm_tail[f2_5_ch..f5_ch],
1593 &new_mid,
1594 &mut output[f2_5_ch..f5_ch],
1595 f2_5,
1596 self.channels,
1597 window,
1598 inc,
1599 );
1600 }
1601
1602 let tail_len = f5 * self.channels;
1604 let out_total = decoded_total * self.channels;
1605 if out_total >= tail_len && tail_len <= self.prev_pcm_tail.len() {
1606 self.prev_pcm_tail[..tail_len]
1607 .copy_from_slice(&output[out_total - tail_len..out_total]);
1608 }
1609
1610 self.prev_mode = Some(mode);
1611 self.prev_redundancy = has_redundancy;
1612 Ok(decoded_total)
1613 }
1614}
1615
1616impl OpusDecoder {
1617 #[inline(always)]
1618 fn celt_end_band_from_toc(&self, toc: u8) -> usize {
1619 let mode = modes::default_mode();
1620 let top = mode.eff_ebands;
1621 if mode_from_toc(toc) == OpusMode::CeltOnly && toc >= 0x80 {
1622 const FROM_OPUS_TABLE: [u8; 16] = [
1623 0x80, 0x88, 0x90, 0x98, 0x40, 0x48, 0x50, 0x58, 0x20, 0x28, 0x30, 0x38, 0x00, 0x08,
1624 0x10, 0x18,
1625 ];
1626 let idx = ((toc >> 3) - 16) as usize;
1627 let data0 = FROM_OPUS_TABLE[idx] | (toc & 0x7);
1628 let trim = (data0 >> 5) as usize;
1629 return top.saturating_sub(2 * trim).max(1);
1630 }
1631 top
1632 }
1633}
1634
1635fn frame_rate_from_params(sampling_rate: i32, frame_size: usize) -> Option<i32> {
1636 let frame_size = frame_size as i32;
1637 if frame_size == 0 || sampling_rate % frame_size != 0 {
1638 return None;
1639 }
1640 Some(sampling_rate / frame_size)
1641}
1642
1643fn gen_toc(mode: OpusMode, frame_rate: i32, bandwidth: Bandwidth, channels: usize) -> u8 {
1644 let mut rate = frame_rate;
1645 let mut period = 0;
1646 while rate < 400 {
1647 rate <<= 1;
1648 period += 1;
1649 }
1650
1651 let mut toc = match mode {
1652 OpusMode::SilkOnly => {
1653 let bw = (bandwidth as i32 - Bandwidth::Narrowband as i32) << 5;
1654 let per = (period - 2) << 3;
1655 (bw | per) as u8
1656 }
1657 OpusMode::CeltOnly => {
1658 let mut tmp = bandwidth as i32 - Bandwidth::Mediumband as i32;
1659 if tmp < 0 {
1660 tmp = 0;
1661 }
1662 let per = period << 3;
1663 (0x80 | (tmp << 5) | per) as u8
1664 }
1665 OpusMode::Hybrid => {
1666 let base_config = if bandwidth == Bandwidth::Superwideband {
1667 12
1668 } else {
1669 14
1670 };
1671 let period_offset = if frame_rate >= 100 { 0 } else { 1 };
1672 ((base_config + period_offset) << 3) as u8
1673 }
1674 };
1675
1676 if channels == 2 {
1677 toc |= 0x04;
1678 }
1679 toc
1680}
1681
1682fn mode_from_toc(toc: u8) -> OpusMode {
1683 if toc & 0x80 != 0 {
1684 OpusMode::CeltOnly
1685 } else if toc & 0x60 == 0x60 {
1686 OpusMode::Hybrid
1687 } else {
1688 OpusMode::SilkOnly
1689 }
1690}
1691
1692fn bandwidth_from_toc(toc: u8) -> Bandwidth {
1693 let mode = mode_from_toc(toc);
1694 match mode {
1695 OpusMode::SilkOnly => {
1696 let bw_bits = (toc >> 5) & 0x03;
1697 match bw_bits {
1698 0 => Bandwidth::Narrowband,
1699 1 => Bandwidth::Mediumband,
1700 2 => Bandwidth::Wideband,
1701 _ => Bandwidth::Wideband,
1702 }
1703 }
1704 OpusMode::Hybrid => {
1705 let bw_bit = (toc >> 4) & 0x01;
1706 if bw_bit == 0 {
1707 Bandwidth::Superwideband
1708 } else {
1709 Bandwidth::Fullband
1710 }
1711 }
1712 OpusMode::CeltOnly => {
1713 let bw_bits = (toc >> 5) & 0x03;
1714 match bw_bits {
1715 0 => Bandwidth::Mediumband,
1716 1 => Bandwidth::Wideband,
1717 2 => Bandwidth::Superwideband,
1718 3 => Bandwidth::Fullband,
1719 _ => Bandwidth::Fullband,
1720 }
1721 }
1722 }
1723}
1724
1725fn frame_duration_ms_from_toc(toc: u8) -> i32 {
1726 let mode = mode_from_toc(toc);
1727 match mode {
1728 OpusMode::SilkOnly => {
1729 let config = (toc >> 3) & 0x03;
1730 match config {
1731 0 => 10,
1732 1 => 20,
1733 2 => 40,
1734 3 => 60,
1735 _ => 20,
1736 }
1737 }
1738 OpusMode::Hybrid => {
1739 let config = (toc >> 3) & 0x01;
1740 if config == 0 { 10 } else { 20 }
1741 }
1742 OpusMode::CeltOnly => {
1743 let config = (toc >> 3) & 0x03;
1744 match config {
1745 0 => 2,
1746 1 => 5,
1747 2 => 10,
1748 3 => 20,
1749 _ => 20,
1750 }
1751 }
1752 }
1753}
1754
1755fn frame_samples_from_toc(toc: u8, sampling_rate: i32) -> Option<usize> {
1759 let mode = mode_from_toc(toc);
1760 match mode {
1761 OpusMode::CeltOnly => {
1762 let period = ((toc >> 3) & 0x03) as i32;
1763 let frame_rate = 400 >> period;
1764 if frame_rate == 0 || sampling_rate % frame_rate != 0 {
1765 return None;
1766 }
1767 Some((sampling_rate / frame_rate) as usize)
1768 }
1769 OpusMode::SilkOnly | OpusMode::Hybrid => {
1770 let duration_ms = frame_duration_ms_from_toc(toc);
1771 Some((sampling_rate as i64 * duration_ms as i64 / 1000) as usize)
1772 }
1773 }
1774}
1775
1776fn channels_from_toc(toc: u8) -> usize {
1777 if toc & 0x04 != 0 { 2 } else { 1 }
1778}
1779
1780fn smooth_fade(
1783 in1: &[f32],
1784 in2: &[f32],
1785 out: &mut [f32],
1786 overlap: usize,
1787 channels: usize,
1788 window: &[f32],
1789 inc: usize,
1790) {
1791 for c in 0..channels {
1792 for i in 0..overlap {
1793 let wi = i * inc;
1794 if wi >= window.len() {
1795 break;
1796 }
1797 let w = window[wi] * window[wi];
1798 out[i * channels + c] = w * in2[i * channels + c] + (1.0 - w) * in1[i * channels + c];
1799 }
1800 }
1801}
1802
1803fn parse_frame_size(data: &[u8]) -> Result<(usize, usize), &'static str> {
1811 let first = *data.first().ok_or("truncated frame length")? as usize;
1812 if first < 252 {
1813 Ok((first, 1))
1814 } else {
1815 let second = *data.get(1).ok_or("truncated frame length")? as usize;
1816 Ok((second * 4 + first, 2))
1817 }
1818}
1819
1820#[cfg(all(test, feature = "std"))]
1821mod tests {
1822 use super::*;
1823
1824 fn frame_size_from_toc(toc: u8, sampling_rate: i32) -> Option<usize> {
1825 let mode = mode_from_toc(toc);
1826 match mode {
1827 OpusMode::CeltOnly => {
1828 let period = ((toc >> 3) & 0x03) as i32;
1829 let frame_rate = 400 >> period;
1830 if frame_rate == 0 || sampling_rate % frame_rate != 0 {
1831 return None;
1832 }
1833 Some((sampling_rate / frame_rate) as usize)
1834 }
1835 OpusMode::SilkOnly => {
1836 let duration_ms = frame_duration_ms_from_toc(toc);
1837 Some((sampling_rate as i64 * duration_ms as i64 / 1000) as usize)
1838 }
1839 OpusMode::Hybrid => {
1840 let duration_ms = frame_duration_ms_from_toc(toc);
1841 Some((sampling_rate as i64 * duration_ms as i64 / 1000) as usize)
1842 }
1843 }
1844 }
1845
1846 #[test]
1847 fn gen_toc_matches_celt_reference_values() {
1848 let sampling_rate = 48_000;
1849 let cases = [
1850 (120usize, 0xE0u8),
1851 (240usize, 0xE8u8),
1852 (480usize, 0xF0u8),
1853 (960usize, 0xF8u8),
1854 ];
1855
1856 for (frame_size, expected_toc) in cases {
1857 let frame_rate = frame_rate_from_params(sampling_rate, frame_size).unwrap();
1858 let toc = gen_toc(OpusMode::CeltOnly, frame_rate, Bandwidth::Fullband, 1);
1859 assert_eq!(
1860 toc, expected_toc,
1861 "frame_size {} expected TOC {:02X} got {:02X}",
1862 frame_size, expected_toc, toc
1863 );
1864 let decoded_size = frame_size_from_toc(toc, sampling_rate).unwrap();
1865 assert_eq!(decoded_size, frame_size);
1866 }
1867
1868 let stereo_toc = gen_toc(
1869 OpusMode::CeltOnly,
1870 frame_rate_from_params(sampling_rate, 960).unwrap(),
1871 Bandwidth::Fullband,
1872 2,
1873 );
1874 assert_eq!(channels_from_toc(stereo_toc), 2);
1875 }
1876
1877 #[test]
1878 fn test_celt_decoder_large_frame_sizes() {
1879 let sampling_rate = 48000;
1880 let channels = 1;
1881
1882 let mut decoder = OpusDecoder::new(sampling_rate, channels).unwrap();
1883
1884 let frame_sizes = [120, 240, 480, 960];
1885
1886 for frame_size in frame_sizes {
1887 let toc = gen_toc(
1888 OpusMode::CeltOnly,
1889 frame_rate_from_params(sampling_rate, frame_size).unwrap(),
1890 Bandwidth::Fullband,
1891 channels,
1892 );
1893 let packet = [toc, 0, 0, 0, 0];
1894
1895 let mut output = vec![0.0f32; frame_size * channels];
1896
1897 let _ = decoder.decode(&packet, frame_size, &mut output);
1898 }
1899
1900 let channels = 2;
1901 let mut decoder = OpusDecoder::new(sampling_rate, channels).unwrap();
1902
1903 for frame_size in frame_sizes {
1904 let toc = gen_toc(
1905 OpusMode::CeltOnly,
1906 frame_rate_from_params(sampling_rate, frame_size).unwrap(),
1907 Bandwidth::Fullband,
1908 channels,
1909 );
1910 let packet = [toc, 0, 0, 0, 0];
1911
1912 let mut output = vec![0.0f32; frame_size * channels];
1913 let _ = decoder.decode(&packet, frame_size, &mut output);
1914 }
1915 }
1916
1917 #[test]
1918 fn test_celt_decoder_edge_case_frame_sizes() {
1919 let sampling_rate = 48000;
1920 let channels = 1;
1921 let mut decoder = OpusDecoder::new(sampling_rate, channels).unwrap();
1922
1923 let edge_sizes = [2048, 2167, 2168, 2169, 2880, 3072];
1924
1925 for frame_size in edge_sizes {
1926 let mut output = vec![0.0f32; frame_size * channels];
1927
1928 let _ = decoder.decode(&[0x80, 0, 0, 0], frame_size, &mut output);
1929 }
1930 }
1931
1932 #[test]
1939 fn test_invalid_small_frame_size_returns_error_not_panic() {
1940 let mut enc = OpusEncoder::new(48000, 2, Application::Voip).unwrap();
1941 enc.bitrate_bps = 64000;
1942 enc.complexity = 5;
1943 enc.use_cbr = true;
1944
1945 let input = vec![0.0f32; 48 * 2]; let mut output = vec![0u8; 256];
1948
1949 let result = enc.encode(&input, 48, &mut output);
1950 assert!(
1951 result.is_err(),
1952 "encode with invalid frame_size=48 should return Err, not panic"
1953 );
1954 }
1955
1956 #[test]
1959 fn test_invalid_small_frame_size_audio_application_returns_error() {
1960 let mut enc = OpusEncoder::new(48000, 1, Application::Audio).unwrap();
1961 let input = vec![0.0f32; 48];
1962 let mut output = vec![0u8; 256];
1963
1964 let result = enc.encode(&input, 48, &mut output);
1965 assert!(
1966 result.is_err(),
1967 "Audio/48kHz encoder with frame_size=48 should return Err"
1968 );
1969 }
1970}