1#![allow(unsafe_op_in_unsafe_fn)]
2#![allow(clippy::too_many_arguments)]
3#![allow(clippy::needless_range_loop)]
4
5pub mod analysis;
6pub mod analysis_data;
7pub mod bands;
8pub mod celt;
9pub mod celt_lpc;
10pub mod hp_cutoff;
11pub mod kiss_fft;
12pub mod mdct;
13pub mod modes;
14pub mod parallel;
15pub mod pitch;
16pub mod prof;
17pub mod pvq;
18pub mod quant_bands;
19pub mod range_coder;
20pub mod repacketizer;
21pub mod multistream;
22pub mod rate;
23pub mod silk;
24
25pub use silk::{SilkResampler, SilkResamplerDown1_3, SilkResamplerDown1_6};
26
27pub use celt::{CeltDecoder, CeltEncoder};
28use hp_cutoff::hp_cutoff;
29use range_coder::RangeCoder;
30use silk::control_codec::silk_control_encoder;
31use silk::enc_api::silk_encode;
32use silk::init_encoder::silk_init_encoder;
33use silk::lin2log::silk_lin2log;
34use silk::log2lin::silk_log2lin;
35use silk::macros::*;
36use silk::structs::SilkEncoderState;
37
38#[derive(Debug, Clone, Copy, PartialEq, Eq)]
39pub enum Application {
40 Voip = 2048,
41 Audio = 2049,
42 RestrictedLowDelay = 2051,
43}
44
45#[derive(Debug, Clone, Copy, PartialEq, Eq)]
48pub enum SignalType {
49 Voice,
50 Music,
51}
52
53#[derive(Debug, Clone, Copy, PartialEq, Eq)]
54pub enum Bandwidth {
55 Auto = -1000,
56 Narrowband = 1101,
57 Mediumband = 1102,
58 Wideband = 1103,
59 Superwideband = 1104,
60 Fullband = 1105,
61}
62
63#[derive(Debug, Clone, Copy, PartialEq, Eq)]
64enum OpusMode {
65 SilkOnly,
66 Hybrid,
67 CeltOnly,
68}
69
70pub struct OpusEncoder {
71 celt_enc: CeltEncoder,
72 silk_enc: Box<SilkEncoderState>,
73 application: Application,
74 sampling_rate: i32,
75 channels: usize,
76 bandwidth: Bandwidth,
77 pub bitrate_bps: i32,
78 pub complexity: i32,
79 pub use_cbr: bool,
80
81 pub use_inband_fec: bool,
82
83 pub use_dtx: bool,
86 nb_no_activity_ms_q1: i32,
88 range_final: u32,
91
92 pub packet_loss_perc: i32,
93 silk_initialized: bool,
94 mode: OpusMode,
95 prev_enc_mode: Option<OpusMode>,
96
97 variable_hp_smth2_q15: i32,
98 auto_bandwidth: i32,
101 first_frame: bool,
102 pub force_bandwidth: Option<Bandwidth>,
104 pub signal_type: Option<SignalType>,
106 pub max_bandwidth: Bandwidth,
108 tonality: analysis::TonalityAnalysisState,
111 analysis_kfft: Option<kiss_fft::KissFftState>,
112 pub lsb_depth: i32,
115 voice_ratio: i32,
117 detected_bandwidth: i32,
118 hp_mem: Vec<i32>,
119
120 buf_filtered: Vec<i16>,
121 buf_silk_input: Vec<i16>,
122 buf_stereo_mid: Vec<i16>,
123 buf_stereo_side: Vec<i16>,
124 buf_celt_input: Vec<f32>,
125 down2_state_first: [i32; 2],
126 down2_state_second: [i32; 2],
127 down2_3_state: [i32; 6],
128 down_1_3_state: silk::resampler::SilkResamplerDown1_3,
129 down2_3_state_r: [i32; 6],
130 down_1_3_state_r: silk::resampler::SilkResamplerDown1_3,
131 down_fir_l: Option<silk::resampler::SilkDownFirResampler>,
132 down_fir_r: Option<silk::resampler::SilkDownFirResampler>,
133 silk_prefill_tail: Vec<i16>,
136 silk_prefill_pending: bool,
137 buf_left: Vec<i16>,
138 buf_right: Vec<i16>,
139 celt_prefill_tail: Vec<f32>,
142
143 rc: RangeCoder,
144
145 gate_tap: Option<std::io::BufWriter<std::fs::File>>,
153 gate_clip: String,
155 gate_frame: u64,
157 force_mode: Option<OpusMode>,
161 pub mode_dwell: u32,
168 mode_dwell_run: u32,
170 analysis_warmup: u32,
182 analysis_frames: u32,
184}
185
186const MONO_VOICE_BANDWIDTH_THRESHOLDS: [i32; 8] = [9000, 700, 9000, 700, 13500, 1000, 14000, 2000];
189const MONO_MUSIC_BANDWIDTH_THRESHOLDS: [i32; 8] = [9000, 700, 9000, 700, 11000, 1000, 12000, 2000];
190const STEREO_VOICE_BANDWIDTH_THRESHOLDS: [i32; 8] = [9000, 700, 9000, 700, 13500, 1000, 14000, 2000];
191const STEREO_MUSIC_BANDWIDTH_THRESHOLDS: [i32; 8] = [9000, 700, 9000, 700, 11000, 1000, 12000, 2000];
192
193fn reconcile_bandwidth(mode: OpusMode, bw: Bandwidth) -> Bandwidth {
198 match mode {
199 OpusMode::CeltOnly if bw == Bandwidth::Mediumband => Bandwidth::Narrowband,
200 OpusMode::SilkOnly
201 if matches!(bw, Bandwidth::Superwideband | Bandwidth::Fullband) =>
202 {
203 Bandwidth::Wideband
204 }
205 OpusMode::Hybrid
206 if !matches!(bw, Bandwidth::Superwideband | Bandwidth::Fullband) =>
207 {
208 Bandwidth::Superwideband
209 }
210 _ => bw,
211 }
212}
213
214fn compute_equiv_rate(
215 bitrate: i32,
216 channels: usize,
217 frame_rate: i32,
218 vbr: bool,
219 complexity: i32,
220 loss: i32,
221) -> i32 {
222 let mut equiv = bitrate;
223 if frame_rate > 50 {
224 equiv -= (40 * channels as i32 + 20) * (frame_rate - 50);
225 }
226 if !vbr {
227 equiv -= equiv / 12;
228 }
229 equiv = equiv * (90 + complexity) / 100;
230 if loss > 0 {
231 equiv -= equiv * loss / (12 * loss + 20);
232 }
233 equiv
234}
235
236fn compute_mode_threshold(
237 application: Application,
238 channels: usize,
239 prev_was_celt: bool,
240 has_prev_mode: bool,
241 voice_est: i32,
242) -> i32 {
243 let mode_voice = if channels == 1 { 64000 } else { 44000 };
244 let mode_music = 10000;
245
246 let diff = mode_voice - mode_music;
247 let offset = (voice_est * voice_est * diff) >> 14;
248 let mut threshold = mode_music + offset;
249
250 if application == Application::Voip {
251 threshold += 8000;
252 }
253
254 if has_prev_mode {
255 if prev_was_celt {
256 threshold -= 4000;
257 } else {
258 threshold += 4000;
259 }
260 }
261
262 if application == Application::RestrictedLowDelay {
263 threshold = 0;
264 }
265
266 threshold
267}
268
269fn compute_silk_rate_for_hybrid(
270 rate_bps: i32,
271 bandwidth: Bandwidth,
272 frame20ms: bool,
273 vbr: bool,
274) -> i32 {
275 const RATE_TABLE: &[(i32, i32, i32)] = &[
276 (0, 0, 0),
277 (12000, 10000, 10000),
278 (16000, 13500, 13500),
279 (20000, 16000, 16000),
280 (24000, 18000, 18000),
281 (32000, 22000, 22000),
282 (64000, 38000, 38000),
283 ];
284 let n = RATE_TABLE.len();
285 let mut i = 1;
286 while i < n && RATE_TABLE[i].0 <= rate_bps {
287 i += 1;
288 }
289 let mut silk_rate = if i == n {
290 let (x_last, r10_last, r20_last) = RATE_TABLE[n - 1];
291 let base = if frame20ms { r20_last } else { r10_last };
292 base + (rate_bps - x_last) / 2
293 } else {
294 let (x0, lo10, lo20) = RATE_TABLE[i - 1];
295 let (x1, hi10, hi20) = RATE_TABLE[i];
296 let (lo, hi) = if frame20ms {
297 (lo20, hi20)
298 } else {
299 (lo10, hi10)
300 };
301 (lo * (x1 - rate_bps) + hi * (rate_bps - x0)) / (x1 - x0)
302 };
303 if !vbr {
307 silk_rate += 100;
308 }
309 if bandwidth == Bandwidth::Superwideband {
310 silk_rate += 300;
311 }
312 silk_rate
313}
314
315#[cfg(test)]
316mod reconcile_bandwidth_tests {
317 use super::{reconcile_bandwidth, Bandwidth, OpusMode};
318
319 #[test]
320 fn celt_maps_mediumband_down_to_narrowband() {
321 assert_eq!(
323 reconcile_bandwidth(OpusMode::CeltOnly, Bandwidth::Mediumband),
324 Bandwidth::Narrowband
325 );
326 }
327
328 #[test]
329 fn celt_leaves_every_other_bandwidth_alone() {
330 for bw in [
331 Bandwidth::Narrowband,
332 Bandwidth::Wideband,
333 Bandwidth::Superwideband,
334 Bandwidth::Fullband,
335 ] {
336 assert_eq!(reconcile_bandwidth(OpusMode::CeltOnly, bw), bw);
337 }
338 }
339
340 #[test]
341 fn silk_only_caps_at_wideband() {
342 assert_eq!(
343 reconcile_bandwidth(OpusMode::SilkOnly, Bandwidth::Superwideband),
344 Bandwidth::Wideband
345 );
346 assert_eq!(
347 reconcile_bandwidth(OpusMode::SilkOnly, Bandwidth::Fullband),
348 Bandwidth::Wideband
349 );
350 for bw in [Bandwidth::Narrowband, Bandwidth::Mediumband, Bandwidth::Wideband] {
352 assert_eq!(reconcile_bandwidth(OpusMode::SilkOnly, bw), bw);
353 }
354 }
355
356 #[test]
357 fn hybrid_floors_at_superwideband() {
358 for bw in [Bandwidth::Narrowband, Bandwidth::Mediumband, Bandwidth::Wideband] {
359 assert_eq!(
360 reconcile_bandwidth(OpusMode::Hybrid, bw),
361 Bandwidth::Superwideband
362 );
363 }
364 assert_eq!(
366 reconcile_bandwidth(OpusMode::Hybrid, Bandwidth::Superwideband),
367 Bandwidth::Superwideband
368 );
369 assert_eq!(
370 reconcile_bandwidth(OpusMode::Hybrid, Bandwidth::Fullband),
371 Bandwidth::Fullband
372 );
373 }
374}
375
376#[cfg(test)]
377mod silk_rate_tests {
378 use super::compute_silk_rate_for_hybrid;
379 use crate::Bandwidth;
380
381 #[test]
382 fn test_reference_table_exact_entries() {
383 assert_eq!(compute_silk_rate_for_hybrid(12000, Bandwidth::Fullband, true, true), 10000);
384 assert_eq!(compute_silk_rate_for_hybrid(16000, Bandwidth::Fullband, true, true), 13500);
385 assert_eq!(compute_silk_rate_for_hybrid(20000, Bandwidth::Fullband, true, true), 16000);
386 assert_eq!(compute_silk_rate_for_hybrid(24000, Bandwidth::Fullband, true, true), 18000);
387 assert_eq!(compute_silk_rate_for_hybrid(32000, Bandwidth::Fullband, true, true), 22000);
388 assert_eq!(compute_silk_rate_for_hybrid(64000, Bandwidth::Fullband, true, true), 38000);
389 }
390
391 #[test]
392 fn test_32kbps_gives_22kbps_silk() {
393 assert_eq!(compute_silk_rate_for_hybrid(32000, Bandwidth::Fullband, true, true), 22000);
394 }
395
396 #[test]
397 fn test_interpolation_between_table_entries() {
398 let r = compute_silk_rate_for_hybrid(18000, Bandwidth::Fullband, true, true);
399 assert_eq!(r, 14750);
400 }
401
402 #[test]
403 fn test_above_table_max_gives_half_extra() {
404 let r = compute_silk_rate_for_hybrid(72000, Bandwidth::Fullband, true, true);
405 assert_eq!(r, 38000 + (72000 - 64000) / 2);
406 }
407}
408
409impl OpusEncoder {
410 pub fn new(
411 sampling_rate: i32,
412 channels: usize,
413 application: Application,
414 ) -> Result<Self, &'static str> {
415 if ![8000, 12000, 16000, 24000, 48000].contains(&sampling_rate) {
416 return Err("Invalid sampling rate");
417 }
418 if ![1, 2].contains(&channels) {
419 return Err("Invalid number of channels");
420 }
421
422 let mode = modes::default_mode();
423 let celt_enc = CeltEncoder::new(mode, channels);
424
425 let mut silk_enc = Box::new(SilkEncoderState::default());
426 if silk_init_encoder(&mut silk_enc, 0) != 0 {
427 return Err("SILK encoder initialization failed");
428 }
429
430 let (opus_mode, bw) = match application {
431 Application::Voip => {
432 let bw = match sampling_rate {
433 8000 => Bandwidth::Narrowband,
434 12000 => Bandwidth::Mediumband,
435 16000 => Bandwidth::Wideband,
436 24000 => Bandwidth::Superwideband,
437 48000 => Bandwidth::Fullband,
438 _ => Bandwidth::Narrowband,
439 };
440
441 let mode = if sampling_rate > 16000 {
442 OpusMode::Hybrid
443 } else {
444 OpusMode::SilkOnly
445 };
446 (mode, bw)
447 }
448 Application::RestrictedLowDelay => {
449 let bw = match sampling_rate {
450 8000 => Bandwidth::Narrowband,
451 12000 => Bandwidth::Mediumband,
452 16000 => Bandwidth::Wideband,
453 24000 => Bandwidth::Superwideband,
454 _ => Bandwidth::Fullband,
455 };
456 (OpusMode::CeltOnly, bw)
457 }
458 Application::Audio => {
459 if sampling_rate <= 16000 {
460 let bw = match sampling_rate {
461 8000 => Bandwidth::Narrowband,
462 12000 => Bandwidth::Mediumband,
463 _ => Bandwidth::Wideband,
464 };
465 (OpusMode::SilkOnly, bw)
466 } else {
467 let bw = match sampling_rate {
468 24000 => Bandwidth::Superwideband,
469 _ => Bandwidth::Fullband,
470 };
471 (OpusMode::Hybrid, bw)
472 }
473 }
474 };
475
476 use silk::lin2log::silk_lin2log;
477 let variable_hp_smth2_q15 = silk_lin2log(60) << 8;
478
479 Ok(Self {
480 celt_enc,
481 silk_enc,
482 application,
483 sampling_rate,
484 channels,
485 bandwidth: bw,
486 bitrate_bps: 64000,
487 complexity: 9,
488 use_cbr: false,
489 use_inband_fec: false,
490 use_dtx: false,
491 nb_no_activity_ms_q1: 0,
492 range_final: 0,
493 packet_loss_perc: 0,
494 silk_initialized: false,
495 prev_enc_mode: None,
496 mode: opus_mode,
497 variable_hp_smth2_q15,
498 auto_bandwidth: 0,
499 first_frame: true,
500 force_bandwidth: None,
501 signal_type: None,
502 max_bandwidth: Bandwidth::Fullband,
503 tonality: analysis::TonalityAnalysisState::new(sampling_rate),
504 analysis_kfft: kiss_fft::KissFftState::new(480),
505 lsb_depth: 24,
506 voice_ratio: -1,
507 detected_bandwidth: 0,
508 hp_mem: vec![0; channels * 2],
509
510 buf_filtered: Vec::new(),
511 buf_silk_input: Vec::new(),
512 buf_stereo_mid: Vec::new(),
513 buf_stereo_side: Vec::new(),
514 buf_celt_input: Vec::new(),
515 down2_state_first: [0; 2],
516 down2_state_second: [0; 2],
517 down2_3_state: [0; 6],
518 down_1_3_state: silk::resampler::SilkResamplerDown1_3::default(),
519 down2_3_state_r: [0; 6],
520 down_1_3_state_r: silk::resampler::SilkResamplerDown1_3::default(),
521 down_fir_l: None,
522 down_fir_r: None,
523 silk_prefill_tail: Vec::new(),
524 silk_prefill_pending: false,
525 buf_left: Vec::new(),
526 buf_right: Vec::new(),
527 celt_prefill_tail: Vec::new(),
528 rc: RangeCoder::new_encoder(1),
529 gate_tap: std::env::var("RUSTY_OPUS_GATE_HARVEST").ok().and_then(|p| {
530 use std::io::Write as _;
531 let mut f = std::fs::OpenOptions::new()
532 .create(true)
533 .append(true)
534 .open(&p)
535 .ok()?;
536 if f.metadata().map(|m| m.len()).unwrap_or(0) == 0 {
537 let _ = writeln!(
538 f,
539 "clip,frame,mode,bw,ch,bitrate,complexity,equiv,voice_est,\
540 is_silence,active,valid,tonality,tonality_slope,noisiness,\
541 activity_prob,music_prob,music_prob_min,music_prob_max,\
542 det_bw,max_pitch_ratio,bytes"
543 );
544 }
545 Some(std::io::BufWriter::new(f))
546 }),
547 gate_clip: std::env::var("RUSTY_OPUS_GATE_CLIP").unwrap_or_default(),
548 gate_frame: 0,
549 force_mode: match std::env::var("RUSTY_OPUS_FORCE_MODE").ok().as_deref() {
550 Some("silk") => Some(OpusMode::SilkOnly),
551 Some("celt") => Some(OpusMode::CeltOnly),
552 Some("hybrid") => Some(OpusMode::Hybrid),
553 _ => None,
554 },
555 mode_dwell: std::env::var("RUSTY_OPUS_MODE_DWELL")
556 .ok()
557 .and_then(|s| s.parse().ok())
558 .unwrap_or(1),
559 mode_dwell_run: 0,
560 analysis_warmup: std::env::var("RUSTY_OPUS_ANALYSIS_WARMUP")
565 .ok()
566 .and_then(|s| s.parse().ok())
567 .unwrap_or(10),
568 analysis_frames: 0,
569 })
570 }
571
572 pub fn enable_hybrid_mode(&mut self) -> Result<(), &'static str> {
573 if self.sampling_rate != 24000 && self.sampling_rate != 48000 {
574 return Err("Hybrid mode requires 24kHz or 48kHz sampling rate");
575 }
576 let bw = if self.sampling_rate == 48000 {
577 Bandwidth::Fullband
578 } else {
579 Bandwidth::Superwideband
580 };
581 self.mode = OpusMode::Hybrid;
582 self.bandwidth = bw;
583 self.silk_initialized = false;
584 Ok(())
585 }
586
587 pub fn final_range(&self) -> u32 {
591 self.range_final
592 }
593
594 fn compute_voice_est(&self) -> i32 {
597 match self.signal_type {
598 Some(SignalType::Voice) => return 127,
599 Some(SignalType::Music) => return 0,
600 None => {}
601 }
602 if self.voice_ratio >= 0 {
603 let mut v = self.voice_ratio * 327 >> 8;
604 if self.application == Application::Audio {
606 v = v.min(115);
607 }
608 v
609 } else {
610 match self.application {
611 Application::Voip => 115,
612 Application::Audio => 48,
613 Application::RestrictedLowDelay => 0,
614 }
615 }
616 }
617
618 pub fn encode(
619 &mut self,
620 input: &[f32],
621 frame_size: usize,
622 output: &mut [u8],
623 ) -> Result<usize, &'static str> {
624 let _prof_total = crate::prof::scope(crate::prof::Stage::Total);
625 if output.len() < 2 {
626 return Err("Output buffer too small");
627 }
628
629 let frame_rate = frame_rate_from_params(self.sampling_rate, frame_size)
630 .ok_or("Invalid frame size for sampling rate")?;
631
632 let mut analysis_info = analysis::AnalysisInfo::default();
634 if self.complexity >= 7 && self.sampling_rate >= 16000 {
635 if let Some(kfft) = &self.analysis_kfft {
636 analysis_info = analysis::run_analysis(
637 &mut self.tonality,
638 kfft,
639 input,
640 frame_size,
641 frame_size,
642 self.channels,
643 self.sampling_rate,
644 self.lsb_depth,
645 );
646 }
647 } else if self.tonality.initialized() {
648 self.tonality.reset();
649 }
650
651 let silence_thresh = 1.0f32 / (1i64 << self.lsb_depth) as f32;
653 let is_silence = input[..(frame_size * self.channels).min(input.len())]
654 .iter()
655 .fold(0.0f32, |m, &v| m.max(v.abs()))
656 <= silence_thresh;
657 if !is_silence {
658 self.voice_ratio = -1;
659 }
660 let activity = if is_silence {
665 false
666 } else if analysis_info.valid {
667 analysis_info.activity_probability >= 0.1
668 } else {
669 true
670 };
671 if analysis_info.valid {
679 self.analysis_frames = self.analysis_frames.saturating_add(1);
680 }
681 let analysis_converged = self.analysis_frames >= self.analysis_warmup;
682
683 self.detected_bandwidth = 0;
684 if analysis_info.valid && analysis_converged {
685 let prob = if self.prev_enc_mode.is_none() {
688 analysis_info.music_prob
689 } else if self.prev_enc_mode == Some(OpusMode::CeltOnly) {
690 analysis_info.music_prob_max
691 } else {
692 analysis_info.music_prob_min
693 };
694 self.voice_ratio = (0.5 + 100.0 * (1.0 - prob)).floor() as i32;
695 let ab = analysis_info.bandwidth;
696 self.detected_bandwidth = if ab <= 12 {
697 Bandwidth::Narrowband as i32
698 } else if ab <= 14 {
699 Bandwidth::Mediumband as i32
700 } else if ab <= 16 {
701 Bandwidth::Wideband as i32
702 } else if ab <= 18 {
703 Bandwidth::Superwideband as i32
704 } else {
705 Bandwidth::Fullband as i32
706 };
707 }
708
709 let mut mode = if self.application == Application::RestrictedLowDelay {
713 OpusMode::CeltOnly
714 } else {
715 let equiv = compute_equiv_rate(
716 self.bitrate_bps,
717 self.channels,
718 frame_rate,
719 !self.use_cbr,
720 self.complexity,
721 self.packet_loss_perc,
722 );
723 let prev_was_celt = self.prev_enc_mode == Some(OpusMode::CeltOnly);
724 let has_prev_mode = self.prev_enc_mode.is_some();
725 let voice_est = self.compute_voice_est();
726 let threshold = compute_mode_threshold(
727 self.application,
728 self.channels,
729 prev_was_celt,
730 has_prev_mode,
731 voice_est,
732 );
733 if equiv >= threshold && self.sampling_rate >= 24000 {
734 OpusMode::CeltOnly
735 } else {
736 OpusMode::SilkOnly
737 }
738 };
739
740 {
747 let equiv = compute_equiv_rate(
748 self.bitrate_bps,
749 self.channels,
750 frame_rate,
751 !self.use_cbr,
752 self.complexity,
753 self.packet_loss_perc,
754 );
755 let voice_est: i32 = self.compute_voice_est();
756 let (vt, mt) = if self.channels == 2 {
757 (
758 &STEREO_VOICE_BANDWIDTH_THRESHOLDS,
759 &STEREO_MUSIC_BANDWIDTH_THRESHOLDS,
760 )
761 } else {
762 (
763 &MONO_VOICE_BANDWIDTH_THRESHOLDS,
764 &MONO_MUSIC_BANDWIDTH_THRESHOLDS,
765 )
766 };
767 let mut th = [0i32; 8];
768 for i in 0..8 {
769 th[i] = mt[i] + ((voice_est * voice_est * (vt[i] - mt[i])) >> 14);
770 }
771 const NB: i32 = Bandwidth::Narrowband as i32; const MB: i32 = Bandwidth::Mediumband as i32; const FB: i32 = Bandwidth::Fullband as i32; let mut bw = FB;
775 while bw > NB {
776 let idx = (2 * (bw - MB)) as usize;
777 let mut threshold = th[idx];
778 let hysteresis = th[idx + 1];
779 if !self.first_frame {
780 if self.auto_bandwidth >= bw {
781 threshold -= hysteresis;
782 } else {
783 threshold += hysteresis;
784 }
785 }
786 if equiv >= threshold {
787 break;
788 }
789 bw -= 1;
790 }
791 if bw == MB {
793 bw = Bandwidth::Wideband as i32;
794 }
795 self.auto_bandwidth = bw;
796 if mode != OpusMode::CeltOnly && self.use_cbr && self.bitrate_bps < 15000 {
798 bw = bw.min(Bandwidth::Wideband as i32);
799 }
800 if mode != OpusMode::CeltOnly && self.sampling_rate > 16000 {
803 bw = bw.max(Bandwidth::Wideband as i32);
804 }
805 if self.sampling_rate <= 24000 {
807 bw = bw.min(Bandwidth::Superwideband as i32);
808 }
809 if self.sampling_rate <= 16000 {
810 bw = bw.min(Bandwidth::Wideband as i32);
811 }
812 if self.sampling_rate <= 12000 {
813 bw = bw.min(Bandwidth::Mediumband as i32);
814 }
815 if self.sampling_rate <= 8000 {
816 bw = bw.min(Bandwidth::Narrowband as i32);
817 }
818 if bw == Bandwidth::Mediumband as i32 && self.sampling_rate > 12000 {
821 bw = Bandwidth::Wideband as i32;
822 }
823 if self.detected_bandwidth != 0
839 && self.force_bandwidth.is_none()
840 && mode != OpusMode::CeltOnly
841 {
842 let ch = self.channels as i32;
843 let equiv2 = equiv; let min_det = if equiv2 <= 18000 * ch && mode == OpusMode::CeltOnly {
845 NB
846 } else if equiv2 <= 24000 * ch && mode == OpusMode::CeltOnly {
847 MB
848 } else if equiv2 <= 30000 * ch {
849 Bandwidth::Wideband as i32
850 } else if equiv2 <= 44000 * ch {
851 Bandwidth::Superwideband as i32
852 } else {
853 FB
854 };
855 bw = bw.min(self.detected_bandwidth.max(min_det));
856 }
857 let mut max_bw = self.max_bandwidth as i32;
863 if mode != OpusMode::CeltOnly && self.sampling_rate > 16000 {
864 max_bw = max_bw.max(Bandwidth::Wideband as i32);
865 }
866 bw = bw.min(max_bw);
867 if mode == OpusMode::CeltOnly && bw == MB {
869 bw = NB;
870 }
871 self.bandwidth = match self.force_bandwidth {
872 Some(f) => f,
873 None => match bw {
874 x if x == NB => Bandwidth::Narrowband,
875 x if x == MB => Bandwidth::Mediumband,
876 x if x == Bandwidth::Wideband as i32 => Bandwidth::Wideband,
877 x if x == Bandwidth::Superwideband as i32 => Bandwidth::Superwideband,
878 x if x == FB => Bandwidth::Fullband,
879 _ => Bandwidth::Wideband,
880 },
881 };
882 self.first_frame = false;
883 }
884
885 let curr_bw = self.bandwidth;
886 if mode == OpusMode::SilkOnly
887 && (curr_bw == Bandwidth::Superwideband || curr_bw == Bandwidth::Fullband)
888 {
889 mode = OpusMode::Hybrid;
890 }
891 if mode == OpusMode::Hybrid
892 && (curr_bw == Bandwidth::Narrowband
893 || curr_bw == Bandwidth::Mediumband
894 || curr_bw == Bandwidth::Wideband)
895 {
896 mode = OpusMode::SilkOnly;
897 }
898
899 if self.channels == 2 && mode == OpusMode::Hybrid && self.bitrate_bps > 28000 {
909 mode = OpusMode::CeltOnly;
910 self.bandwidth = Bandwidth::Fullband;
911 }
912
913 if self.mode_dwell > 1 {
927 match self.prev_enc_mode {
928 Some(prev) if mode != prev => {
929 self.mode_dwell_run += 1;
930 if self.mode_dwell_run < self.mode_dwell {
931 mode = prev;
935 self.bandwidth = reconcile_bandwidth(mode, self.bandwidth);
936 } else {
937 self.mode_dwell_run = 0;
939 }
940 }
941 _ => self.mode_dwell_run = 0,
942 }
943 }
944
945 if let Some(fm) = self.force_mode {
949 mode = fm;
950 self.bandwidth = reconcile_bandwidth(fm, self.bandwidth);
951 }
952
953 if mode == OpusMode::CeltOnly {
954 match frame_rate {
955 400 | 200 | 100 | 50 => {}
956 _ => return Err("Unsupported frame size for CELT-only mode"),
957 }
958 }
959
960 if mode == OpusMode::Hybrid {
961 match frame_rate {
962 100 | 50 => {}
963 _ => return Err("Unsupported frame size for Hybrid mode"),
964 }
965 }
966
967 if mode == OpusMode::SilkOnly {
968 match frame_rate {
969 400 | 200 | 100 | 50 | 25 => {}
970 _ => return Err("Unsupported frame size for SILK-only mode"),
971 }
972 }
973
974 let n400 = (self.sampling_rate / 400) as usize;
975
976 if let Some(prev) = self.prev_enc_mode {
981 if prev != mode {
982 if mode != OpusMode::SilkOnly {
983 let ch = self.channels;
984 self.celt_enc = CeltEncoder::new(modes::default_mode(), ch);
985 let n400 = (self.sampling_rate / 400) as usize;
988 if self.celt_prefill_tail.len() == n400 * ch {
989 let mut dummy = RangeCoder::new_encoder(2);
990 let tail = std::mem::take(&mut self.celt_prefill_tail);
991 self.celt_enc.encode_with_budget(&tail, n400, &mut dummy, 0, 21, 16);
992 self.celt_prefill_tail = tail;
993 }
994 }
995 if mode != OpusMode::CeltOnly && prev == OpusMode::CeltOnly {
996 self.silk_initialized = false;
997 self.silk_prefill_pending = true;
998 }
999 }
1000 }
1001
1002 if self.channels == 1 {
1004 let n10 = (self.sampling_rate / 100) as usize;
1005 if frame_size >= n10 {
1006 self.silk_prefill_tail.resize(n10, 0);
1007 for i in 0..n10 {
1008 self.silk_prefill_tail[i] = (input[frame_size - n10 + i] * 32768.0)
1009 .clamp(-32768.0, 32767.0) as i16;
1010 }
1011 }
1012 }
1013
1014 {
1018 let ch = self.channels;
1019 self.celt_prefill_tail.resize(n400 * ch, 0.0);
1020 let base = frame_size - n400;
1021 for c in 0..ch {
1022 for i in 0..n400 {
1023 self.celt_prefill_tail[c * n400 + i] = input[(base + i) * ch + c];
1024 }
1025 }
1026 }
1027
1028 let toc = gen_toc(mode, frame_rate, self.bandwidth, self.channels);
1029 output[0] = toc;
1030
1031 if self.use_dtx && (analysis_info.valid || is_silence) {
1038 let frame_ms_q1 = 2 * 1000 * frame_size as i32 / self.sampling_rate;
1039 let dtx = if !activity {
1040 self.nb_no_activity_ms_q1 += frame_ms_q1;
1041 const LO: i32 = silk::define::NB_SPEECH_FRAMES_BEFORE_DTX * 20 * 2; const HI: i32 = (silk::define::NB_SPEECH_FRAMES_BEFORE_DTX + silk::define::MAX_CONSECUTIVE_DTX) * 20 * 2; if self.nb_no_activity_ms_q1 > LO {
1044 if self.nb_no_activity_ms_q1 <= HI {
1045 true
1046 } else {
1047 self.nb_no_activity_ms_q1 = LO;
1048 false
1049 }
1050 } else {
1051 false
1052 }
1053 } else {
1054 self.nb_no_activity_ms_q1 = 0;
1055 false
1056 };
1057 if dtx {
1058 self.prev_enc_mode = Some(mode);
1059 self.range_final = 0;
1060 return Ok(1);
1061 }
1062 } else {
1063 self.nb_no_activity_ms_q1 = 0;
1064 }
1065
1066 let target_bits =
1067 (self.bitrate_bps as i64 * frame_size as i64 / self.sampling_rate as i64) as i32;
1068 let cbr_bytes = ((target_bits + 4) / 8) as usize;
1069 let max_data_bytes = output.len();
1070
1071 let n_bytes = if self.use_cbr {
1076 cbr_bytes.min(max_data_bytes).max(1)
1077 } else {
1078 max_data_bytes.min(1276).max(cbr_bytes.min(max_data_bytes)).max(3)
1079 };
1080
1081 let init_rc_size = n_bytes - 1;
1082 self.rc.reset_for_encode(init_rc_size as u32);
1083
1084 if mode == OpusMode::SilkOnly || mode == OpusMode::Hybrid {
1085 let silk_fs_khz = if mode == OpusMode::Hybrid {
1086 16
1087 } else {
1088 self.sampling_rate.min(16000) / 1000
1089 };
1090
1091 let frame_ms = (frame_size as i32 * 1000) / self.sampling_rate;
1092 if !self.silk_initialized || self.silk_enc.s_cmn.fs_khz != silk_fs_khz {
1093 let silk_init_bitrate = if self.use_cbr {
1094 (((n_bytes - 1) * 8) as i64 * self.sampling_rate as i64 / frame_size as i64)
1095 as i32
1096 } else {
1097 self.bitrate_bps
1098 };
1099 silk_control_encoder(
1100 &mut self.silk_enc,
1101 silk_fs_khz,
1102 frame_ms,
1103 silk_init_bitrate,
1104 self.complexity,
1105 );
1106 self.silk_enc.s_cmn.use_cbr = if self.use_cbr { 1 } else { 0 };
1107
1108 self.silk_enc.s_cmn.n_channels = self.channels as i32;
1109 self.silk_initialized = true;
1110 self.down2_state_first = [0; 2];
1111 self.down2_state_second = [0; 2];
1112 self.down2_3_state = [0; 6];
1113 self.down_1_3_state = silk::resampler::SilkResamplerDown1_3::default();
1114 self.down2_3_state_r = [0; 6];
1115 self.down_1_3_state_r = silk::resampler::SilkResamplerDown1_3::default();
1116 self.down_fir_l =
1117 silk::resampler::SilkDownFirResampler::new(self.sampling_rate, 16000);
1118 self.down_fir_r =
1119 silk::resampler::SilkDownFirResampler::new(self.sampling_rate, 16000);
1120 }
1121
1122 if self.silk_prefill_pending {
1126 self.silk_prefill_pending = false;
1127 let n10 = (self.sampling_rate / 100) as usize;
1128 if self.channels == 1 && self.silk_prefill_tail.len() == n10 {
1129 let need = silk_fs_khz as usize * 10;
1130 let mut resampled = vec![0i16; need];
1131 if self.sampling_rate > 16000 {
1132 if let Some(r) = &mut self.down_fir_l {
1133 r.process(&mut resampled, &self.silk_prefill_tail);
1134 }
1135 } else {
1136 resampled.copy_from_slice(&self.silk_prefill_tail[..need]);
1137 }
1138 silk::enc_api::silk_encode_prefill(&mut self.silk_enc, &resampled, 0);
1139 }
1140 }
1141
1142 self.silk_enc.s_cmn.use_in_band_fec = if self.use_inband_fec { 1 } else { 0 };
1143 self.silk_enc.s_cmn.packet_loss_perc = self.packet_loss_perc.clamp(0, 100);
1144
1145 self.silk_enc.s_cmn.lbrr_enabled = if self.use_inband_fec { 1 } else { 0 };
1146
1147 self.silk_enc.s_cmn.lbrr_gain_increases =
1151 (7 - ((self.packet_loss_perc.clamp(0, 100) * 26214) >> 16)).max(2);
1152
1153 let hp_freq_smth1 = if mode == OpusMode::CeltOnly {
1154 silk_lin2log(60) << 8
1155 } else {
1156 self.silk_enc.s_cmn.variable_hp_smth1_q15
1157 };
1158
1159 const VARIABLE_HP_SMTH_COEF2_Q16: i32 = 984;
1160 self.variable_hp_smth2_q15 = silk_smlawb(
1161 self.variable_hp_smth2_q15,
1162 hp_freq_smth1 - self.variable_hp_smth2_q15,
1163 VARIABLE_HP_SMTH_COEF2_Q16,
1164 );
1165
1166 let cutoff_hz = silk_log2lin(silk_rshift(self.variable_hp_smth2_q15, 8));
1167
1168 let _prof_rs = crate::prof::scope(crate::prof::Stage::Resample);
1169 let required_size = frame_size * self.channels;
1170 self.buf_filtered.resize(required_size, 0);
1171 if self.application == Application::Voip {
1172 hp_cutoff(
1173 input,
1174 cutoff_hz,
1175 &mut self.buf_filtered,
1176 &mut self.hp_mem,
1177 frame_size,
1178 self.channels,
1179 self.sampling_rate,
1180 );
1181 } else {
1182 for (i, &x) in input.iter().enumerate() {
1183 self.buf_filtered[i] = (x * 32768.0).clamp(-32768.0, 32767.0) as i16;
1184 }
1185 }
1186
1187 let input_i16 = &self.buf_filtered;
1188
1189 let silk_input: &[i16] = if self.channels == 2 {
1190 let frame_length = input_i16.len() / 2;
1198 self.buf_left.resize(frame_length, 0);
1199 self.buf_right.resize(frame_length, 0);
1200 for i in 0..frame_length {
1201 self.buf_left[i] = input_i16[2 * i];
1202 self.buf_right[i] = input_i16[2 * i + 1];
1203 }
1204 let need_resample = self.sampling_rate > 16000;
1205 let ds_len = if !need_resample {
1206 frame_length
1207 } else if self.sampling_rate == 48000 {
1208 frame_length / 3
1209 } else {
1210 frame_length * 2 / 3
1211 };
1212 if need_resample {
1213 self.buf_stereo_mid.resize(ds_len, 0);
1214 self.buf_stereo_side.resize(ds_len, 0);
1215 if let (Some(rl), Some(rr)) = (&mut self.down_fir_l, &mut self.down_fir_r) {
1216 rl.process(&mut self.buf_stereo_mid, &self.buf_left);
1217 rr.process(&mut self.buf_stereo_side, &self.buf_right);
1218 }
1219 self.buf_left.resize(ds_len, 0);
1220 self.buf_right.resize(ds_len, 0);
1221 self.buf_left.copy_from_slice(&self.buf_stereo_mid[..ds_len]);
1222 self.buf_right.copy_from_slice(&self.buf_stereo_side[..ds_len]);
1223 }
1224 self.buf_stereo_mid.resize(ds_len, 0);
1225 self.buf_stereo_side.resize(ds_len, 0);
1226 for i in 0..ds_len {
1227 let l = self.buf_left[i] as i32;
1228 let r = self.buf_right[i] as i32;
1229 self.buf_stereo_mid[i] = ((l + r) / 2) as i16;
1230 self.buf_stereo_side[i] = (l - r) as i16;
1231 }
1232 self.silk_enc.stereo.side.resize(ds_len, 0);
1233 self.silk_enc
1234 .stereo
1235 .side
1236 .copy_from_slice(&self.buf_stereo_side[..ds_len]);
1237 &self.buf_stereo_mid
1238 } else if mode == OpusMode::SilkOnly && self.sampling_rate > 16000 {
1239 if self.sampling_rate == 48000 {
1240 let silk_frame_size = frame_size / 3;
1245 self.buf_silk_input.resize(silk_frame_size, 0);
1246 if let Some(r) = &mut self.down_fir_l {
1247 r.process(&mut self.buf_silk_input, input_i16);
1248 }
1249 &self.buf_silk_input
1250 } else if self.sampling_rate == 24000 {
1251 let silk_frame_size = frame_size * 2 / 3;
1252 self.buf_silk_input.resize(silk_frame_size, 0);
1253 if let Some(r) = &mut self.down_fir_l {
1254 r.process(&mut self.buf_silk_input, input_i16);
1255 }
1256 &self.buf_silk_input
1257 } else {
1258 input_i16
1259 }
1260 } else if mode == OpusMode::Hybrid && self.sampling_rate > 16000 {
1261 let silk_frame_size = if self.sampling_rate == 48000 {
1262 frame_size / 3
1263 } else {
1264 frame_size * 2 / 3
1265 };
1266 self.buf_silk_input.resize(silk_frame_size, 0);
1267 if let Some(r) = &mut self.down_fir_l {
1268 r.process(&mut self.buf_silk_input, input_i16);
1269 }
1270 &self.buf_silk_input
1271 } else {
1272 input_i16
1273 };
1274
1275 drop(_prof_rs);
1276
1277 let mut pn_bytes = 0;
1278
1279 let silk_rate_for_calc = if mode == OpusMode::Hybrid {
1285 16000
1286 } else {
1287 self.sampling_rate.min(16000)
1288 };
1289 let silk_frame_len = silk_input.len();
1290
1291 let silk_bitrate = if mode == OpusMode::Hybrid {
1292 let frame_duration_ms = frame_size as i32 * 1000 / self.sampling_rate;
1293 let frame20ms = frame_duration_ms >= 20;
1294 compute_silk_rate_for_hybrid(self.bitrate_bps, curr_bw, frame20ms, !self.use_cbr)
1295 } else if self.use_cbr {
1296 (8i64 * (n_bytes - 1) as i64 * silk_rate_for_calc as i64 / silk_frame_len as i64)
1297 as i32
1298 } else {
1299 self.bitrate_bps
1301 };
1302 let silk_max_bits = if mode == OpusMode::Hybrid {
1303 let total_max_bits = ((n_bytes - 1) * 8) as i32;
1304 if self.use_cbr {
1305 let silk_bits = (silk_bitrate as i64 * silk_frame_len as i64
1306 / silk_rate_for_calc as i64) as i32;
1307 let other_bits = 0i32.max(total_max_bits - silk_bits);
1308 0i32.max(total_max_bits - other_bits * 3 / 4)
1309 } else {
1310 let frame_duration_ms = frame_size as i32 * 1000 / self.sampling_rate;
1311 let frame20ms = frame_duration_ms >= 20;
1312 let max_bit_rate = compute_silk_rate_for_hybrid(
1313 total_max_bits * self.sampling_rate / frame_size as i32,
1314 curr_bw,
1315 frame20ms,
1316 !self.use_cbr,
1317 );
1318 max_bit_rate * frame_size as i32 / self.sampling_rate
1319 }
1320 } else {
1321 ((n_bytes - 1) * 8) as i32
1322 };
1323 let silk_use_cbr = if mode == OpusMode::Hybrid && self.use_cbr {
1324 0
1325 } else if self.use_cbr {
1326 1
1327 } else {
1328 0
1329 };
1330 let ret = silk_encode(
1331 &mut self.silk_enc,
1332 silk_input,
1333 silk_input.len(),
1334 &mut self.rc,
1335 &mut pn_bytes,
1336 silk_bitrate,
1337 silk_max_bits,
1338 silk_use_cbr,
1339 1,
1340 );
1341 if ret != 0 {
1342 return Err("SILK encoding failed");
1343 }
1344 }
1345
1346 if mode == OpusMode::Hybrid && self.rc.tell() + 37 <= ((n_bytes - 1) * 8) as i32 {
1351 self.rc.encode_bit_logp(false, 12); }
1353
1354 if mode == OpusMode::Hybrid {
1355 let nb_compr_bytes = (n_bytes - 1) as u32;
1356 self.rc.shrink(nb_compr_bytes);
1357 }
1358
1359 let silk_ret_bytes = if mode == OpusMode::SilkOnly {
1360 ((self.rc.tell() + 7) >> 3) as usize
1361 } else {
1362 0
1363 };
1364
1365 if mode == OpusMode::CeltOnly || mode == OpusMode::Hybrid {
1366 self.celt_enc.analysis = celt::AnalysisInfo {
1367 valid: analysis_info.valid,
1368 tonality: analysis_info.tonality,
1369 tonality_slope: analysis_info.tonality_slope,
1370 noisiness: analysis_info.noisiness,
1371 activity: analysis_info.activity,
1372 music_prob: analysis_info.music_prob,
1373 music_prob_min: analysis_info.music_prob_min,
1374 music_prob_max: analysis_info.music_prob_max,
1375 bandwidth: analysis_info.bandwidth,
1376 activity_probability: analysis_info.activity_probability,
1377 max_pitch_ratio: analysis_info.max_pitch_ratio,
1378 leak_boost: analysis_info.leak_boost,
1379 };
1380 self.celt_enc.complexity = self.complexity;
1381 self.celt_enc.lsb_depth = self.lsb_depth;
1382 self.celt_enc.loss_rate = self.packet_loss_perc;
1387 let start_band = if mode == OpusMode::Hybrid { 17 } else { 0 };
1388 let end_band = match self.bandwidth {
1391 Bandwidth::Narrowband => 13,
1392 Bandwidth::Mediumband | Bandwidth::Wideband => 17,
1393 Bandwidth::Superwideband => 19,
1394 _ => 21,
1395 };
1396 let total_packet_bits = ((n_bytes - 1) * 8) as i32;
1397 self.celt_enc.vbr_rate = if self.use_cbr {
1402 0
1403 } else {
1404 let den = self.sampling_rate >> 3; ((self.bitrate_bps as i64 * frame_size as i64 + (den >> 1) as i64)
1406 / den as i64) as i32
1407 };
1408
1409 let celt_input: &[f32] = if self.channels == 1 {
1410 input
1411 } else {
1412 let n = frame_size * self.channels;
1413 self.buf_celt_input.resize(n, 0.0);
1414 for i in 0..frame_size {
1415 for ch in 0..self.channels {
1416 self.buf_celt_input[ch * frame_size + i] = input[i * self.channels + ch];
1417 }
1418 }
1419 &self.buf_celt_input
1420 };
1421
1422 if self.rc.tell() <= total_packet_bits {
1423 self.celt_enc.encode_with_budget(
1424 celt_input,
1425 frame_size,
1426 &mut self.rc,
1427 start_band,
1428 end_band,
1429 total_packet_bits,
1430 );
1431 }
1432 }
1433
1434 self.rc.done();
1435 self.range_final = self.rc.rng;
1436
1437 if mode == OpusMode::SilkOnly {
1438 let mut ret = silk_ret_bytes.min(self.rc.storage as usize);
1439 while ret > 2 && self.rc.buf[ret - 1] == 0 {
1440 ret -= 1;
1441 }
1442
1443 let target_total = if self.use_cbr {
1444 n_bytes.min(output.len())
1445 } else {
1446 (ret + 1).min(output.len())
1447 };
1448
1449 let silk_len = ret;
1450
1451 if !self.use_cbr || silk_len + 1 >= target_total {
1452 output[0] = toc;
1454 let copy_len = silk_len.min(target_total - 1);
1455 output[1..1 + copy_len].copy_from_slice(&self.rc.buf[..copy_len]);
1456 return Ok((copy_len + 1).min(output.len()));
1457 }
1458
1459 output[0] = toc | 0x03;
1460
1461 if silk_len + 2 >= target_total {
1462 output[1] = 0x01;
1463 let copy_len = (target_total - 2).min(silk_len);
1464 output[2..2 + copy_len].copy_from_slice(&self.rc.buf[..copy_len]);
1465 self.prev_enc_mode = Some(mode);
1466 return Ok(target_total.min(output.len()));
1467 }
1468
1469 let pad_amount = target_total - silk_len - 2;
1470 output[1] = 0x41;
1471
1472 let nb_255s = (pad_amount - 1) / 255;
1473 let mut ptr = 2;
1474 for _ in 0..nb_255s {
1475 output[ptr] = 255;
1476 ptr += 1;
1477 }
1478 output[ptr] = (pad_amount - 255 * nb_255s - 1) as u8;
1479 ptr += 1;
1480
1481 output[ptr..ptr + silk_len].copy_from_slice(&self.rc.buf[..silk_len]);
1482 ptr += silk_len;
1483
1484 let fill_end = target_total.min(output.len());
1485 for byte in output[ptr..fill_end].iter_mut() {
1486 *byte = 0;
1487 }
1488
1489 self.prev_enc_mode = Some(mode);
1490 return Ok(target_total.min(output.len()));
1491 }
1492
1493 let payload_len = if self.use_cbr {
1496 n_bytes - 1
1497 } else {
1498 (self.rc.storage as usize).min(n_bytes - 1)
1499 };
1500 output[1..1 + payload_len].copy_from_slice(&self.rc.buf[..payload_len]);
1501 if self.gate_tap.is_some() {
1504 let equiv = compute_equiv_rate(
1505 self.bitrate_bps,
1506 self.channels,
1507 frame_rate,
1508 !self.use_cbr,
1509 self.complexity,
1510 self.packet_loss_perc,
1511 );
1512 let voice_est = self.compute_voice_est();
1513 let (clip, frame) = (self.gate_clip.clone(), self.gate_frame);
1514 if let Some(tap) = self.gate_tap.as_mut() {
1515 use std::io::Write as _;
1516 let mode_s = match mode {
1517 OpusMode::SilkOnly => "silk",
1518 OpusMode::CeltOnly => "celt",
1519 OpusMode::Hybrid => "hybrid",
1520 };
1521 let _ = writeln!(
1522 tap,
1523 "{},{},{},{},{},{},{},{},{},{},{},{},{:.4},{:.4},{:.4},{:.4},{:.4},{:.4},{:.4},{},{:.4},{}",
1524 clip,
1525 frame,
1526 mode_s,
1527 self.bandwidth as i32,
1528 self.channels,
1529 self.bitrate_bps,
1530 self.complexity,
1531 equiv,
1532 voice_est,
1533 is_silence as u8,
1534 activity as u8,
1535 analysis_info.valid as u8,
1536 analysis_info.tonality,
1537 analysis_info.tonality_slope,
1538 analysis_info.noisiness,
1539 analysis_info.activity_probability,
1540 analysis_info.music_prob,
1541 analysis_info.music_prob_min,
1542 analysis_info.music_prob_max,
1543 self.detected_bandwidth,
1544 analysis_info.max_pitch_ratio,
1545 1 + payload_len,
1546 );
1547 }
1548 }
1549 self.gate_frame += 1;
1550
1551 self.prev_enc_mode = Some(mode);
1552 Ok(1 + payload_len)
1553 }
1554}
1555
1556pub struct OpusDecoder {
1557 celt_dec: CeltDecoder,
1558 silk_dec: silk::dec_api::SilkDecoder,
1559 sampling_rate: i32,
1560 channels: usize,
1561
1562 prev_mode: Option<OpusMode>,
1563 frame_size: usize,
1564
1565 bandwidth: Bandwidth,
1566
1567 stream_channels: usize,
1568
1569 silk_resampler: silk::resampler::SilkResampler,
1570 silk_resampler_r: silk::resampler::SilkResampler,
1572
1573 prev_internal_rate: i32,
1574
1575 pub hybrid_skip_celt: bool,
1576
1577 w_pcm_i16: Vec<i16>,
1578 w_silk_out: Vec<f32>,
1579 w_pcm_resampled: Vec<i16>,
1580 w_celt_planar: Vec<f32>,
1581 w_celt_out: Vec<f32>,
1582
1583 silk_s_mid: [i16; 2],
1589
1590 pub last_range: u32,
1593
1594 aux: Option<Box<OpusDecoder>>,
1599 prev_used_aux: bool,
1604 prev_redundancy: bool,
1608}
1609
1610impl OpusDecoder {
1611 pub fn new(sampling_rate: i32, channels: usize) -> Result<Self, &'static str> {
1612 if ![8000, 12000, 16000, 24000, 48000].contains(&sampling_rate) {
1613 return Err("Invalid sampling rate");
1614 }
1615 if ![1, 2].contains(&channels) {
1616 return Err("Invalid number of channels");
1617 }
1618
1619 let mode = modes::default_mode();
1620 let celt_dec = CeltDecoder::new(mode, channels);
1621
1622 let mut silk_dec = silk::dec_api::SilkDecoder::new();
1623 silk_dec.init(sampling_rate.min(16000), channels as i32);
1624 silk_dec.channel_state[0].fs_api_hz = sampling_rate;
1625
1626 Ok(Self {
1627 celt_dec,
1628 silk_dec,
1629 sampling_rate,
1630 channels,
1631 prev_mode: None,
1632 frame_size: 0,
1633 bandwidth: Bandwidth::Auto,
1634 stream_channels: channels,
1635 silk_resampler: silk::resampler::SilkResampler::default(),
1636 silk_resampler_r: silk::resampler::SilkResampler::default(),
1637 prev_internal_rate: 0,
1638 hybrid_skip_celt: false,
1639
1640 w_pcm_i16: vec![0i16; 5760 * channels],
1645
1646 w_silk_out: vec![0.0f32; 5760 * channels],
1647 w_pcm_resampled: vec![0i16; 5760 * channels],
1648 w_celt_planar: vec![0.0f32; 5760 * channels],
1649 w_celt_out: vec![0.0f32; 5760 * channels],
1650 silk_s_mid: [0; 2],
1651 last_range: 0,
1652 aux: None,
1653 prev_used_aux: false,
1654 prev_redundancy: false,
1655 })
1656 }
1657
1658 fn decode_plc(
1665 &mut self,
1666 frame_size: usize,
1667 output: &mut [f32],
1668 ) -> Result<usize, &'static str> {
1669 let out_samples = frame_size * self.channels;
1670 for v in output.iter_mut().take(out_samples) {
1671 *v = 0.0;
1672 }
1673 let mode = self.prev_mode.unwrap_or(OpusMode::SilkOnly);
1674 if mode == OpusMode::CeltOnly {
1675 self.celt_dec.conceal_lost(frame_size, output);
1678 self.prev_mode = Some(mode);
1679 return Ok(frame_size);
1680 }
1681
1682 let frame_ms = (frame_size as i32 * 1000 / self.sampling_rate).max(1);
1683 let internal_rate = if mode == OpusMode::Hybrid {
1684 16000
1685 } else {
1686 match self.bandwidth {
1687 Bandwidth::Narrowband => 8000,
1688 Bandwidth::Mediumband => 12000,
1689 _ => 16000,
1690 }
1691 };
1692 if self.sampling_rate != internal_rate && internal_rate != self.prev_internal_rate {
1693 self.silk_resampler.init(internal_rate, self.sampling_rate);
1694 self.prev_internal_rate = internal_rate;
1695 }
1696 let n_silk = match frame_ms {
1697 40 => 2,
1698 60 => 3,
1699 _ => 1,
1700 };
1701 let internal_frame = (frame_ms * internal_rate / 1000) as usize;
1702 let internal_sub = internal_frame / n_silk.max(1);
1703 let ratio = self.sampling_rate as f64 / internal_rate as f64;
1704 self.silk_dec.produce_lr = false;
1706 self.silk_dec.n_channels_internal = 1;
1707
1708 let mut off = 0usize; for sf in 0..n_silk {
1710 let mut rc = RangeCoder::new_decoder(&[]);
1711 let n16 = internal_sub;
1712 if n16 + 2 > self.w_pcm_i16.len() {
1713 return Err("opus PLC: frame exceeds buffer");
1714 }
1715 self.w_pcm_i16[0] = self.silk_s_mid[0];
1716 self.w_pcm_i16[1] = self.silk_s_mid[1];
1717 let ret = self.silk_dec.decode(
1718 &mut rc,
1719 &mut self.w_pcm_i16[2..n16 + 2],
1720 silk::decode_frame::FLAG_PACKET_LOST,
1721 sf == 0,
1722 frame_ms,
1723 internal_rate,
1724 );
1725 if ret < 0 {
1726 return Err("SILK PLC failed");
1727 }
1728 let dec = ret as usize;
1729 if dec >= 2 {
1730 self.silk_s_mid[0] = self.w_pcm_i16[dec];
1731 self.silk_s_mid[1] = self.w_pcm_i16[dec + 1];
1732 }
1733 let base = off * self.channels;
1734 let out_len = if self.sampling_rate == internal_rate {
1735 for i in 0..dec {
1736 let v = self.w_pcm_i16[1 + i] as f32 / 32768.0;
1737 for ch in 0..self.channels {
1738 let idx = base + i * self.channels + ch;
1739 if idx < output.len() {
1740 output[idx] = v;
1741 }
1742 }
1743 }
1744 dec
1745 } else {
1746 let out_len = (dec as f64 * ratio) as usize;
1747 let src: Vec<i16> = self.w_pcm_i16[1..1 + dec].to_vec();
1748 self.silk_resampler
1749 .process(&mut self.w_pcm_resampled[..out_len], &src, dec as i32);
1750 for i in 0..out_len {
1751 let v = self.w_pcm_resampled[i] as f32 / 32768.0;
1752 for ch in 0..self.channels {
1753 let idx = base + i * self.channels + ch;
1754 if idx < output.len() {
1755 output[idx] = v;
1756 }
1757 }
1758 }
1759 out_len
1760 };
1761 off += out_len;
1762 }
1763 self.prev_mode = Some(mode);
1764 Ok(frame_size)
1765 }
1766
1767 pub fn decode_fec(
1775 &mut self,
1776 packet: &[u8],
1777 frame_size: usize,
1778 output: &mut [f32],
1779 ) -> Result<usize, &'static str> {
1780 if packet.is_empty() {
1781 return self.decode_plc(frame_size, output);
1782 }
1783 let toc = packet[0];
1784 let mode = mode_from_toc(toc);
1785 if mode == OpusMode::CeltOnly || (toc & 0x03) != 0 {
1787 return self.decode_plc(frame_size, output);
1788 }
1789 let bandwidth = bandwidth_from_toc(toc);
1790 let payload = &packet[1..];
1791
1792 let out_samples = frame_size * self.channels;
1793 for v in output.iter_mut().take(out_samples) {
1794 *v = 0.0;
1795 }
1796 let frame_ms = (frame_size as i32 * 1000 / self.sampling_rate).max(1);
1797 let internal_rate = if mode == OpusMode::Hybrid {
1798 16000
1799 } else {
1800 match bandwidth {
1801 Bandwidth::Narrowband => 8000,
1802 Bandwidth::Mediumband => 12000,
1803 _ => 16000,
1804 }
1805 };
1806 if self.sampling_rate != internal_rate && internal_rate != self.prev_internal_rate {
1807 self.silk_resampler.init(internal_rate, self.sampling_rate);
1808 self.prev_internal_rate = internal_rate;
1809 }
1810 let internal_frame = (frame_ms * internal_rate / 1000) as usize;
1811 let ratio = self.sampling_rate as f64 / internal_rate as f64;
1812 self.silk_dec.produce_lr = false;
1813 self.silk_dec.n_channels_internal = 1;
1814
1815 let mut rc = RangeCoder::new_decoder(payload);
1816 let n16 = internal_frame;
1817 if n16 + 2 > self.w_pcm_i16.len() {
1818 return Err("opus FEC: frame exceeds buffer");
1819 }
1820 self.w_pcm_i16[0] = self.silk_s_mid[0];
1821 self.w_pcm_i16[1] = self.silk_s_mid[1];
1822 let ret = self.silk_dec.decode(
1823 &mut rc,
1824 &mut self.w_pcm_i16[2..n16 + 2],
1825 silk::decode_frame::FLAG_DECODE_LBRR,
1826 true,
1827 frame_ms,
1828 internal_rate,
1829 );
1830 if ret < 0 {
1831 return Err("SILK FEC failed");
1832 }
1833 let dec = ret as usize;
1834 if dec >= 2 {
1835 self.silk_s_mid[0] = self.w_pcm_i16[dec];
1836 self.silk_s_mid[1] = self.w_pcm_i16[dec + 1];
1837 }
1838 if self.sampling_rate == internal_rate {
1839 for i in 0..dec {
1840 let v = self.w_pcm_i16[1 + i] as f32 / 32768.0;
1841 for ch in 0..self.channels {
1842 let idx = i * self.channels + ch;
1843 if idx < output.len() {
1844 output[idx] = v;
1845 }
1846 }
1847 }
1848 } else {
1849 let out_len = (dec as f64 * ratio) as usize;
1850 let src: Vec<i16> = self.w_pcm_i16[1..1 + dec].to_vec();
1851 self.silk_resampler
1852 .process(&mut self.w_pcm_resampled[..out_len], &src, dec as i32);
1853 for i in 0..out_len {
1854 let v = self.w_pcm_resampled[i] as f32 / 32768.0;
1855 for ch in 0..self.channels {
1856 let idx = i * self.channels + ch;
1857 if idx < output.len() {
1858 output[idx] = v;
1859 }
1860 }
1861 }
1862 }
1863 self.prev_mode = Some(mode);
1864 Ok(frame_size)
1865 }
1866
1867 pub fn decode(
1868 &mut self,
1869 input: &[u8],
1870 frame_size: usize,
1871 output: &mut [f32],
1872 ) -> Result<usize, &'static str> {
1873 if input.is_empty() {
1875 return self.decode_plc(frame_size, output);
1876 }
1877
1878 let toc = input[0];
1879 let mode = mode_from_toc(toc);
1880 let packet_channels = channels_from_toc(toc);
1881 let bandwidth = bandwidth_from_toc(toc);
1882 let frame_duration_ms = frame_duration_ms_from_toc(toc);
1883
1884 let mono_in_stereo = packet_channels == 1 && self.channels == 2;
1895
1896 if packet_channels != self.channels && !mono_in_stereo {
1897 if self
1902 .aux
1903 .as_ref()
1904 .map(|a| a.channels != packet_channels)
1905 .unwrap_or(true)
1906 {
1907 self.aux = Some(Box::new(OpusDecoder::new(
1908 self.sampling_rate,
1909 packet_channels,
1910 )?));
1911 }
1912 if !self.prev_used_aux
1917 && packet_channels == 1
1918 && self.channels == 2
1919 && (mode == OpusMode::CeltOnly || mode == OpusMode::Hybrid)
1920 {
1921 let (aux_opt, primary) = (&mut self.aux, &self.celt_dec);
1922 if let Some(aux) = aux_opt.as_mut() {
1923 aux.celt_dec.seed_from(primary);
1924 }
1925 }
1926 let aux = self.aux.as_mut().unwrap();
1927 let mut buf = vec![0.0f32; frame_size * packet_channels];
1928 let n = aux.decode(input, frame_size, &mut buf)?;
1929 self.last_range = aux.last_range;
1930 if packet_channels == 1 && self.channels == 2 {
1931 for i in 0..n {
1932 let v = buf[i];
1933 output[2 * i] = v;
1934 output[2 * i + 1] = v;
1935 }
1936 } else if packet_channels == 2 && self.channels == 1 {
1937 for i in 0..n {
1938 output[i] = 0.5 * (buf[2 * i] + buf[2 * i + 1]);
1939 }
1940 } else {
1941 let m = (n * self.channels).min(output.len()).min(buf.len());
1942 output[..m].copy_from_slice(&buf[..m]);
1943 }
1944 self.prev_mode = Some(mode);
1945 self.prev_used_aux = true;
1946 return Ok(n);
1947 }
1948
1949 if self.prev_used_aux {
1955 self.prev_used_aux = false;
1956 if (mode == OpusMode::CeltOnly || mode == OpusMode::Hybrid) && self.channels == 2 {
1957 if let Some(aux) = self.aux.as_ref() {
1958 self.celt_dec.seed_from(&aux.celt_dec);
1959 }
1960 }
1961 }
1962
1963 let code = toc & 0x03;
1964 let frame_count: usize;
1965 let frame_payloads: Vec<&[u8]>;
1966
1967 match code {
1968 0 => {
1969 frame_count = 1;
1970 frame_payloads = vec![&input[1..]];
1971 }
1972 1 => {
1973 frame_count = 2;
1974 let half = (input.len() - 1) / 2;
1975 if half == 0 {
1976 return Err("Code 1: empty frame");
1977 }
1978 frame_payloads = vec![&input[1..1 + half], &input[1 + half..]];
1979 }
1980 2 => {
1981 frame_count = 2;
1982 let data = &input[1..];
1983 if data.is_empty() {
1984 return Err("Code 2 packet has no data");
1985 }
1986 let (first_len, header_size) = read_opus_frame_len(data, 0)?;
1987 if header_size + first_len > data.len() {
1988 return Err("Code 2: first frame size exceeds packet");
1989 }
1990 frame_payloads = vec![
1991 &data[header_size..header_size + first_len],
1992 &data[header_size + first_len..],
1993 ];
1994 }
1995 3 => {
1996 if input.len() < 2 {
2002 return Err("Code 3 packet too short");
2003 }
2004 let count_byte = input[1];
2005 let m = (count_byte & 0x3F) as usize;
2006 if m < 1 || m > 48 {
2007 return Err("Code 3: invalid frame count");
2008 }
2009 if m as i32 * repacketizer::samples_per_frame(toc, 48000) > 5760 {
2016 return Err("Code 3: packet duration exceeds 120 ms");
2017 }
2018 frame_count = m;
2019 let vbr = (count_byte & 0x80) != 0;
2020 let padding = (count_byte & 0x40) != 0;
2021
2022 let mut ptr = 2usize;
2025 let mut pad_len = 0usize;
2026 if padding {
2027 loop {
2028 let p = *input.get(ptr).ok_or("Code 3: padding overflow")? as usize;
2029 ptr += 1;
2030 if p == 255 {
2031 pad_len += 254;
2032 } else {
2033 pad_len += p;
2034 break;
2035 }
2036 }
2037 }
2038 let end = input
2039 .len()
2040 .checked_sub(pad_len)
2041 .ok_or("Code 3: padding exceeds packet")?;
2042 if ptr > end {
2043 return Err("Code 3: padding exceeds packet");
2044 }
2045 let region = &input[ptr..end];
2048
2049 if vbr {
2050 let mut lens = Vec::with_capacity(m.saturating_sub(1));
2053 let mut hp = 0usize;
2054 for _ in 0..m - 1 {
2055 let (l, nb) = read_opus_frame_len(region, hp)?;
2056 hp += nb;
2057 lens.push(l);
2058 }
2059 let mut payloads = Vec::with_capacity(m);
2060 let mut fp = hp;
2061 for &l in &lens {
2062 if fp + l > region.len() {
2063 return Err("Code 3 VBR: frame length exceeds packet");
2064 }
2065 payloads.push(®ion[fp..fp + l]);
2066 fp += l;
2067 }
2068 if fp > region.len() {
2069 return Err("Code 3 VBR: no data for last frame");
2070 }
2071 payloads.push(®ion[fp..]);
2072 frame_payloads = payloads;
2073 } else {
2074 if region.len() % m != 0 {
2077 return Err("Code 3 CBR: frame data not divisible by frame count");
2078 }
2079 let frame_len = region.len() / m;
2080 frame_payloads = (0..m)
2081 .map(|i| ®ion[i * frame_len..(i + 1) * frame_len])
2082 .collect();
2083 }
2084 }
2085 _ => unreachable!(),
2086 }
2087
2088 let packet_frame_samples =
2099 repacketizer::samples_per_frame(toc, self.sampling_rate) as usize;
2100 if frame_count * packet_frame_samples > frame_size {
2101 return Err("Output buffer too small");
2102 }
2103
2104 self.frame_size = frame_size;
2105 self.bandwidth = bandwidth;
2106 self.stream_channels = packet_channels;
2107
2108 let sub_frame_size = frame_size / frame_count;
2109 let sub_output_len = sub_frame_size * self.channels;
2110
2111 match mode {
2112 OpusMode::SilkOnly => {
2113 let internal_sample_rate = match bandwidth {
2114 Bandwidth::Narrowband => 8000,
2115 Bandwidth::Mediumband => 12000,
2116 Bandwidth::Wideband => 16000,
2117 _ => 16000,
2118 };
2119 let internal_frame_size =
2120 (frame_duration_ms * internal_sample_rate / 1000) as usize;
2121
2122 if self.sampling_rate != internal_sample_rate
2123 && internal_sample_rate != self.prev_internal_rate
2124 {
2125 self.silk_resampler
2126 .init(internal_sample_rate, self.sampling_rate);
2127 self.silk_resampler_r
2128 .init(internal_sample_rate, self.sampling_rate);
2129 self.prev_internal_rate = internal_sample_rate;
2130 }
2131
2132 let silk_lr = self.channels == 2 && packet_channels == 2;
2135 self.silk_dec.produce_lr = silk_lr;
2136
2137 let prev_internal_ch = self.silk_dec.n_channels_internal;
2139 if packet_channels as i32 > prev_internal_ch {
2140 silk::init_decoder::silk_init_decoder(
2142 &mut self.silk_dec.channel_state[1],
2143 );
2144 }
2145 if self.channels == 2 && packet_channels == 2 && prev_internal_ch == 1 {
2146 self.silk_dec.s_stereo_pred_prev_q13 = [0; 2];
2149 self.silk_dec.s_stereo_side = [0; 2];
2150 self.silk_resampler_r = self.silk_resampler.clone();
2151 }
2152 self.silk_dec.n_channels_internal = packet_channels as i32;
2153
2154 let n_silk = match frame_duration_ms {
2160 40 => 2,
2161 60 => 3,
2162 _ => 1,
2163 };
2164 let internal_sub_frame_size = internal_frame_size / n_silk;
2165 let ratio = self.sampling_rate as f64 / internal_sample_rate as f64;
2166 let mut prev_mode_frame = self.prev_mode;
2169
2170 for (fi, payload) in frame_payloads.iter().enumerate() {
2171 let mut rc = RangeCoder::new_decoder(payload);
2172 let pcm_i16_len = internal_sub_frame_size * self.channels;
2173 if pcm_i16_len + 2 > self.w_pcm_i16.len() {
2177 return Err("opus: SILK frame size exceeds buffer");
2178 }
2179 let out_start = fi * sub_output_len;
2180 let mut silk_off = 0usize; for sf in 0..n_silk {
2183 let s_mid = self.silk_s_mid;
2184 let ret = {
2185 let (silk_dec, pcm_i16) = (&mut self.silk_dec, &mut self.w_pcm_i16);
2186 pcm_i16[0] = s_mid[0];
2190 pcm_i16[1] = s_mid[1];
2191 silk_dec.decode(
2192 &mut rc,
2193 &mut pcm_i16[2..pcm_i16_len + 2],
2194 silk::decode_frame::FLAG_DECODE_NORMAL,
2195 sf == 0,
2196 frame_duration_ms,
2197 internal_sample_rate,
2198 )
2199 };
2200
2201 if ret < 0 {
2202 return Err("SILK decoding failed");
2203 }
2204
2205 let decoded_samples = ret as usize;
2206 if decoded_samples >= 2 {
2208 self.silk_s_mid[0] = self.w_pcm_i16[decoded_samples];
2209 self.silk_s_mid[1] = self.w_pcm_i16[decoded_samples + 1];
2210 }
2211 let base = out_start + silk_off * self.channels;
2212
2213 let out_len = if silk_lr {
2217 if self.sampling_rate == internal_sample_rate {
2218 for i in 0..decoded_samples {
2219 let l = self.silk_dec.l_out[i] as f32 / 32768.0;
2220 let r = self.silk_dec.r_out[i] as f32 / 32768.0;
2221 let idx = base + i * 2;
2222 if idx + 1 < output.len() {
2223 output[idx] = l;
2224 output[idx + 1] = r;
2225 }
2226 }
2227 decoded_samples
2228 } else {
2229 let out_len = (decoded_samples as f64 * ratio) as usize;
2230 self.silk_resampler.process(
2232 &mut self.w_pcm_resampled[..out_len],
2233 &self.silk_dec.l_out[..decoded_samples],
2234 decoded_samples as i32,
2235 );
2236 for i in 0..out_len {
2237 let idx = base + i * 2;
2238 if idx < output.len() {
2239 output[idx] = self.w_pcm_resampled[i] as f32 / 32768.0;
2240 }
2241 }
2242 self.silk_resampler_r.process(
2244 &mut self.w_pcm_resampled[..out_len],
2245 &self.silk_dec.r_out[..decoded_samples],
2246 decoded_samples as i32,
2247 );
2248 for i in 0..out_len {
2249 let idx = base + i * 2 + 1;
2250 if idx < output.len() {
2251 output[idx] = self.w_pcm_resampled[i] as f32 / 32768.0;
2252 }
2253 }
2254 out_len
2255 }
2256 } else if self.sampling_rate == internal_sample_rate {
2257 let frames = decoded_samples;
2258 for i in 0..frames {
2259 let v = self.w_pcm_i16[1 + i] as f32 / 32768.0;
2260 for ch in 0..self.channels {
2261 let idx = base + i * self.channels + ch;
2262 if idx < output.len() {
2263 output[idx] = v;
2264 }
2265 }
2266 }
2267 frames
2268 } else {
2269 let out_len = (decoded_samples as f64 * ratio) as usize;
2270 debug_assert!(out_len <= self.w_pcm_resampled.len());
2271 {
2272 let (silk_res, pcm_i16, pcm_out) = (
2273 &mut self.silk_resampler,
2274 &self.w_pcm_i16,
2275 &mut self.w_pcm_resampled,
2276 );
2277 silk_res.process(
2278 &mut pcm_out[..out_len],
2279 &pcm_i16[1..1 + decoded_samples],
2280 decoded_samples as i32,
2281 );
2282 }
2283 for i in 0..out_len {
2284 let v = self.w_pcm_resampled[i] as f32 / 32768.0;
2285 for ch in 0..self.channels {
2286 let idx = base + i * self.channels + ch;
2287 if idx < output.len() {
2288 output[idx] = v;
2289 }
2290 }
2291 }
2292 if self.channels == 2 {
2298 self.silk_resampler_r.process(
2299 &mut self.w_pcm_resampled[..out_len],
2300 &self.w_pcm_i16[1..1 + decoded_samples],
2301 decoded_samples as i32,
2302 );
2303 for i in 0..out_len {
2304 let idx = base + i * 2 + 1;
2305 if idx < output.len() {
2306 output[idx] = self.w_pcm_resampled[i] as f32 / 32768.0;
2307 }
2308 }
2309 }
2310 out_len
2311 };
2312 silk_off += out_len;
2313 }
2314
2315 let mut redundant_rng = 0u32;
2320 let mut redundancy = false;
2321 let mut celt_to_silk = false;
2322 let plen = payload.len();
2323 let f5 = (self.sampling_rate / 200) as usize;
2324 let f2_5 = f5 / 2;
2325 let red_end_band = celt_endband_for_bandwidth(bandwidth);
2326 let mut red_buf = [0.0f32; 480]; let mut red_bytes = 0usize;
2328 if self.sampling_rate == 48000 && rc.tell() + 17 <= (plen as i32) * 8 {
2329 redundancy = true;
2330 celt_to_silk = rc.decode_bit_logp(1);
2331 red_bytes = plen - (((rc.tell() + 7) >> 3) as usize);
2332 if red_bytes < 2 || red_bytes >= plen {
2333 redundancy = false;
2334 red_bytes = 0;
2335 }
2336 }
2337 if redundancy && celt_to_silk {
2341 redundant_rng = self.decode_redundant_celt(
2342 &payload[plen - red_bytes..],
2343 false,
2344 packet_channels,
2345 red_end_band,
2346 &mut red_buf[..f5 * self.channels],
2347 );
2348 }
2349 if self.sampling_rate == 48000
2354 && prev_mode_frame == Some(OpusMode::Hybrid)
2355 && !(redundancy && celt_to_silk && self.prev_redundancy)
2356 {
2357 let silence = [0xFFu8, 0xFF];
2358 let mut sil_buf = [0.0f32; 240]; self.celt_dec.set_stream_channels(packet_channels);
2360 let mut src = RangeCoder::new_decoder(&silence);
2361 self.celt_dec.decode_from_range_coder_with_band_range(
2362 &mut src,
2363 16,
2364 f2_5,
2365 &mut sil_buf[..f2_5 * self.channels],
2366 0,
2367 red_end_band,
2368 );
2369 let region = &mut output[out_start..out_start + sub_output_len];
2370 for i in 0..f2_5 {
2371 for c in 0..self.channels {
2372 region[i * self.channels + c] += sil_buf[c * f2_5 + i];
2373 }
2374 }
2375 }
2376 if redundancy && !celt_to_silk {
2380 redundant_rng = self.decode_redundant_celt(
2381 &payload[plen - red_bytes..],
2382 true,
2383 packet_channels,
2384 red_end_band,
2385 &mut red_buf[..f5 * self.channels],
2386 );
2387 }
2388 if redundancy {
2389 let window = modes::default_mode().window;
2390 let region = &mut output[out_start..out_start + sub_output_len];
2391 if celt_to_silk {
2392 redundancy_fade_start(
2393 region,
2394 &red_buf,
2395 f5,
2396 f2_5,
2397 self.channels,
2398 window,
2399 );
2400 } else {
2401 redundancy_fade_end(
2402 region,
2403 sub_frame_size,
2404 &red_buf,
2405 f5,
2406 f2_5,
2407 self.channels,
2408 window,
2409 );
2410 }
2411 }
2412 self.prev_redundancy = redundancy && !celt_to_silk;
2413 prev_mode_frame = Some(OpusMode::SilkOnly);
2414 self.last_range = rc.rng ^ redundant_rng;
2415 }
2416 self.prev_mode = Some(OpusMode::SilkOnly);
2417 Ok(frame_size)
2418 }
2419
2420 OpusMode::CeltOnly => {
2421 let celt_end_band = self.celt_end_band_from_toc(toc);
2422 if let Some(pm) = self.prev_mode {
2426 if pm != OpusMode::CeltOnly && !self.prev_redundancy {
2427 self.celt_dec.reset();
2428 }
2429 }
2430 self.prev_redundancy = false;
2431 self.celt_dec.set_stream_channels(packet_channels);
2433
2434 for (fi, payload) in frame_payloads.iter().enumerate() {
2435 let mut rc = RangeCoder::new_decoder(payload);
2436 let total_bits = (payload.len() * 8) as i32;
2437 let needed = sub_frame_size * self.channels;
2438 let out_start = fi * needed;
2439 let out_end = (out_start + needed).min(output.len());
2440
2441 if output.len() < out_end {
2442 return Err("Output buffer too small");
2443 }
2444
2445 if self.channels == 1 {
2446 self.celt_dec.decode_from_range_coder_with_band_range(
2447 &mut rc,
2448 total_bits,
2449 sub_frame_size,
2450 &mut output[out_start..out_end],
2451 0,
2452 celt_end_band,
2453 );
2454 for sample in &mut output[out_start..out_end] {
2455 *sample = sample.clamp(-1.0, 1.0);
2456 }
2457 } else {
2458 self.celt_dec.decode_from_range_coder_with_band_range(
2459 &mut rc,
2460 total_bits,
2461 sub_frame_size,
2462 &mut self.w_celt_planar[..needed],
2463 0,
2464 celt_end_band,
2465 );
2466 for i in 0..sub_frame_size {
2467 for ch in 0..self.channels {
2468 let idx = out_start + i * self.channels + ch;
2469 output[idx] =
2470 self.w_celt_planar[ch * sub_frame_size + i].clamp(-1.0, 1.0);
2471 }
2472 }
2473 }
2474 self.last_range = rc.rng;
2475 }
2476 self.prev_mode = Some(OpusMode::CeltOnly);
2477 Ok(frame_size)
2478 }
2479
2480 OpusMode::Hybrid => {
2481 let internal_sample_rate = 16000;
2482 let internal_frame_size =
2483 (frame_duration_ms * internal_sample_rate / 1000) as usize;
2484 let celt_end_band = self.celt_end_band_from_toc(toc);
2485
2486 if self.sampling_rate != internal_sample_rate
2487 && internal_sample_rate != self.prev_internal_rate
2488 {
2489 self.silk_resampler
2490 .init(internal_sample_rate, self.sampling_rate);
2491 self.silk_resampler_r
2492 .init(internal_sample_rate, self.sampling_rate);
2493 self.prev_internal_rate = internal_sample_rate;
2494 }
2495
2496 let silk_lr = self.channels == 2 && packet_channels == 2;
2500 self.silk_dec.produce_lr = silk_lr;
2501 let prev_internal_ch = self.silk_dec.n_channels_internal;
2502 if packet_channels as i32 > prev_internal_ch {
2503 silk::init_decoder::silk_init_decoder(&mut self.silk_dec.channel_state[1]);
2504 }
2505 if self.channels == 2 && packet_channels == 2 && prev_internal_ch == 1 {
2506 self.silk_dec.s_stereo_pred_prev_q13 = [0; 2];
2507 self.silk_dec.s_stereo_side = [0; 2];
2508 self.silk_resampler_r = self.silk_resampler.clone();
2509 }
2510 self.silk_dec.n_channels_internal = packet_channels as i32;
2511
2512 for (fi, payload) in frame_payloads.iter().enumerate() {
2513 let mut rc = RangeCoder::new_decoder(payload);
2514 let pcm_silk_i16_len = internal_frame_size * self.channels;
2515 if pcm_silk_i16_len + 2 > self.w_pcm_i16.len() {
2516 return Err("opus: SILK frame size exceeds buffer");
2517 }
2518
2519 let s_mid = self.silk_s_mid;
2525 let ret = {
2526 let (silk_dec, pcm_i16) = (&mut self.silk_dec, &mut self.w_pcm_i16);
2527 pcm_i16[0] = s_mid[0];
2528 pcm_i16[1] = s_mid[1];
2529 silk_dec.decode(
2530 &mut rc,
2531 &mut pcm_i16[2..pcm_silk_i16_len + 2],
2532 silk::decode_frame::FLAG_DECODE_NORMAL,
2533 true,
2534 frame_duration_ms,
2535 internal_sample_rate,
2536 )
2537 };
2538
2539 if ret < 0 {
2540 return Err("SILK decoding failed");
2541 }
2542
2543 let silk_out_len = sub_frame_size * self.channels;
2544 self.w_silk_out[..silk_out_len].fill(0.0);
2545 if ret > 0 {
2546 let decoded_samples = ret as usize;
2547 if decoded_samples >= 2 {
2548 self.silk_s_mid[0] = self.w_pcm_i16[decoded_samples];
2549 self.silk_s_mid[1] = self.w_pcm_i16[decoded_samples + 1];
2550 }
2551 let ratio = self.sampling_rate as f64 / internal_sample_rate as f64;
2552 let out_len =
2553 ((decoded_samples as f64 * ratio) as usize).min(sub_frame_size);
2554 debug_assert!(out_len <= self.w_pcm_resampled.len());
2555 if silk_lr {
2556 self.silk_resampler.process(
2559 &mut self.w_pcm_resampled[..out_len],
2560 &self.silk_dec.l_out[..decoded_samples],
2561 decoded_samples as i32,
2562 );
2563 for i in 0..out_len {
2564 self.w_silk_out[i * 2] = self.w_pcm_resampled[i] as f32 / 32768.0;
2565 }
2566 self.silk_resampler_r.process(
2567 &mut self.w_pcm_resampled[..out_len],
2568 &self.silk_dec.r_out[..decoded_samples],
2569 decoded_samples as i32,
2570 );
2571 for i in 0..out_len {
2572 self.w_silk_out[i * 2 + 1] =
2573 self.w_pcm_resampled[i] as f32 / 32768.0;
2574 }
2575 } else {
2576 self.silk_resampler.process(
2577 &mut self.w_pcm_resampled[..out_len],
2578 &self.w_pcm_i16[1..1 + decoded_samples],
2579 decoded_samples as i32,
2580 );
2581 for i in 0..out_len {
2582 let v = self.w_pcm_resampled[i] as f32 / 32768.0;
2583 for ch in 0..self.channels {
2584 self.w_silk_out[i * self.channels + ch] = v;
2585 }
2586 }
2587 if self.channels == 2 {
2590 self.silk_resampler_r.process(
2591 &mut self.w_pcm_resampled[..out_len],
2592 &self.w_pcm_i16[1..1 + decoded_samples],
2593 decoded_samples as i32,
2594 );
2595 for i in 0..out_len {
2596 self.w_silk_out[i * 2 + 1] =
2597 self.w_pcm_resampled[i] as f32 / 32768.0;
2598 }
2599 }
2600 }
2601 }
2602
2603 let plen = payload.len();
2610 let mut redundancy = false;
2611 let mut celt_to_silk = false;
2612 let mut red_bytes = 0usize;
2613 let mut effective_len = plen;
2614 if rc.tell() + 37 <= (plen as i32) * 8 {
2615 redundancy = rc.decode_bit_logp(12);
2616 if redundancy {
2617 celt_to_silk = rc.decode_bit_logp(1);
2618 red_bytes = rc.dec_uint(256) as usize + 2;
2619 if red_bytes <= effective_len {
2620 effective_len -= red_bytes;
2621 } else {
2622 red_bytes = 0;
2623 redundancy = false;
2624 }
2625 if redundancy && (effective_len as i32) * 8 < rc.tell() {
2626 effective_len = plen;
2627 red_bytes = 0;
2628 redundancy = false;
2629 }
2630 if redundancy {
2631 rc.storage -= red_bytes as u32;
2632 }
2633 }
2634 }
2635 let f5 = (self.sampling_rate / 200) as usize;
2636 let f2_5 = f5 / 2;
2637 let red_end_band = celt_endband_for_bandwidth(bandwidth);
2638 let mut red_buf = [0.0f32; 480];
2639 let mut redundant_rng = 0u32;
2640 let do_red = redundancy && self.sampling_rate == 48000;
2641 if do_red && celt_to_silk {
2644 redundant_rng = self.decode_redundant_celt(
2645 &payload[plen - red_bytes..],
2646 false,
2647 packet_channels,
2648 red_end_band,
2649 &mut red_buf[..f5 * self.channels],
2650 );
2651 }
2652
2653 if fi == 0 {
2656 if let Some(pm) = self.prev_mode {
2657 if pm != OpusMode::Hybrid && !self.prev_redundancy {
2658 self.celt_dec.reset();
2659 }
2660 }
2661 }
2662 self.celt_dec.set_stream_channels(packet_channels);
2663 let total_bits = (effective_len * 8) as i32;
2664 {
2665 let (celt_dec, celt_planar) = (&mut self.celt_dec, &mut self.w_celt_planar);
2666 celt_dec.decode_from_range_coder_with_band_range(
2667 &mut rc,
2668 total_bits,
2669 sub_frame_size,
2670 &mut celt_planar[..silk_out_len],
2671 17,
2672 celt_end_band,
2673 );
2674
2675 if self.channels == 1 {
2676 self.w_celt_out[..silk_out_len]
2677 .copy_from_slice(&self.w_celt_planar[..silk_out_len]);
2678 } else {
2679 for i in 0..sub_frame_size {
2680 for ch in 0..self.channels {
2681 self.w_celt_out[i * self.channels + ch] =
2682 self.w_celt_planar[ch * sub_frame_size + i];
2683 }
2684 }
2685 }
2686 }
2687
2688 let out_start = fi * silk_out_len;
2689 let total = silk_out_len.min(output.len() - out_start);
2690 for j in 0..total {
2691 output[out_start + j] =
2692 (self.w_silk_out[j] + self.w_celt_out[j]).clamp(-1.0, 1.0);
2693 }
2694
2695 if do_red && !celt_to_silk {
2698 redundant_rng = self.decode_redundant_celt(
2699 &payload[plen - red_bytes..],
2700 true,
2701 packet_channels,
2702 red_end_band,
2703 &mut red_buf[..f5 * self.channels],
2704 );
2705 }
2706 if do_red {
2707 let window = modes::default_mode().window;
2708 let region = &mut output[out_start..out_start + silk_out_len];
2709 if celt_to_silk {
2710 redundancy_fade_start(
2711 region,
2712 &red_buf,
2713 f5,
2714 f2_5,
2715 self.channels,
2716 window,
2717 );
2718 } else {
2719 redundancy_fade_end(
2720 region,
2721 sub_frame_size,
2722 &red_buf,
2723 f5,
2724 f2_5,
2725 self.channels,
2726 window,
2727 );
2728 }
2729 }
2730 self.prev_redundancy = redundancy && !celt_to_silk;
2731 self.last_range = rc.rng ^ redundant_rng;
2732 }
2733 self.prev_mode = Some(OpusMode::Hybrid);
2734 Ok(frame_size)
2735 }
2736 }
2737 }
2738}
2739
2740impl OpusDecoder {
2741 #[inline(always)]
2742 fn celt_end_band_from_toc(&self, toc: u8) -> usize {
2743 let mode = modes::default_mode();
2744 let top = mode.eff_ebands;
2745 if mode_from_toc(toc) == OpusMode::CeltOnly && toc >= 0x80 {
2746 const FROM_OPUS_TABLE: [u8; 16] = [
2747 0x80, 0x88, 0x90, 0x98, 0x40, 0x48, 0x50, 0x58, 0x20, 0x28, 0x30, 0x38, 0x00, 0x08,
2748 0x10, 0x18,
2749 ];
2750 let idx = ((toc >> 3) - 16) as usize;
2751 let data0 = FROM_OPUS_TABLE[idx] | (toc & 0x7);
2752 let trim = (data0 >> 5) as usize;
2753 return top.saturating_sub(2 * trim).max(1);
2754 }
2755 if mode_from_toc(toc) == OpusMode::Hybrid
2759 && bandwidth_from_toc(toc) == Bandwidth::Superwideband
2760 {
2761 return 19.min(top);
2762 }
2763 top
2764 }
2765
2766 fn decode_redundant_celt(
2771 &mut self,
2772 red: &[u8],
2773 reset_first: bool,
2774 packet_channels: usize,
2775 end_band: usize,
2776 buf: &mut [f32],
2777 ) -> u32 {
2778 if reset_first {
2779 self.celt_dec.reset();
2780 }
2781 self.celt_dec.set_stream_channels(packet_channels);
2782 let f5 = (self.sampling_rate / 200) as usize;
2783 let mut rrc = RangeCoder::new_decoder(red);
2784 let total_bits = (red.len() * 8) as i32;
2785 self.celt_dec.decode_from_range_coder_with_band_range(
2786 &mut rrc, total_bits, f5, buf, 0, end_band,
2787 );
2788 rrc.rng
2789 }
2790}
2791
2792fn celt_endband_for_bandwidth(bw: Bandwidth) -> usize {
2794 match bw {
2795 Bandwidth::Narrowband => 13,
2796 Bandwidth::Mediumband | Bandwidth::Wideband => 17,
2797 Bandwidth::Superwideband => 19,
2798 _ => 21,
2799 }
2800}
2801
2802fn redundancy_fade_start(
2815 out: &mut [f32],
2816 red: &[f32],
2817 f5: usize,
2818 f2_5: usize,
2819 channels: usize,
2820 window: &[f32],
2821) {
2822 for i in 0..f2_5 {
2823 for c in 0..channels {
2824 out[i * channels + c] = red[c * f5 + i];
2825 }
2826 }
2827 for i in 0..f2_5 {
2828 let w = window[i] * window[i];
2829 for c in 0..channels {
2830 let idx = (f2_5 + i) * channels + c;
2831 out[idx] = (1.0 - w) * red[c * f5 + f2_5 + i] + w * out[idx];
2832 }
2833 }
2834}
2835
2836fn redundancy_fade_end(
2848 out: &mut [f32],
2849 frame_samples: usize,
2850 red: &[f32],
2851 f5: usize,
2852 f2_5: usize,
2853 channels: usize,
2854 window: &[f32],
2855) {
2856 for i in 0..f2_5 {
2857 let w = window[i] * window[i];
2858 for c in 0..channels {
2859 let idx = (frame_samples - f2_5 + i) * channels + c;
2860 out[idx] = (1.0 - w) * out[idx] + w * red[c * f5 + f2_5 + i];
2861 }
2862 }
2863}
2864
2865fn frame_rate_from_params(sampling_rate: i32, frame_size: usize) -> Option<i32> {
2866 let frame_size = frame_size as i32;
2867 if frame_size == 0 || sampling_rate % frame_size != 0 {
2868 return None;
2869 }
2870 Some(sampling_rate / frame_size)
2871}
2872
2873fn gen_toc(mode: OpusMode, frame_rate: i32, bandwidth: Bandwidth, channels: usize) -> u8 {
2874 let mut rate = frame_rate;
2875 let mut period = 0;
2876 while rate < 400 {
2877 rate <<= 1;
2878 period += 1;
2879 }
2880
2881 let mut toc = match mode {
2882 OpusMode::SilkOnly => {
2883 let bw = (bandwidth as i32 - Bandwidth::Narrowband as i32) << 5;
2884 let per = (period - 2) << 3;
2885 (bw | per) as u8
2886 }
2887 OpusMode::CeltOnly => {
2888 let mut tmp = bandwidth as i32 - Bandwidth::Mediumband as i32;
2889 if tmp < 0 {
2890 tmp = 0;
2891 }
2892 let per = period << 3;
2893 (0x80 | (tmp << 5) | per) as u8
2894 }
2895 OpusMode::Hybrid => {
2896 let base_config = if bandwidth == Bandwidth::Superwideband {
2897 12
2898 } else {
2899 14
2900 };
2901 let period_offset = if frame_rate >= 100 { 0 } else { 1 };
2902 ((base_config + period_offset) << 3) as u8
2903 }
2904 };
2905
2906 if channels == 2 {
2907 toc |= 0x04;
2908 }
2909 toc
2910}
2911
2912fn mode_from_toc(toc: u8) -> OpusMode {
2913 if toc & 0x80 != 0 {
2914 OpusMode::CeltOnly
2915 } else if toc & 0x60 == 0x60 {
2916 OpusMode::Hybrid
2917 } else {
2918 OpusMode::SilkOnly
2919 }
2920}
2921
2922fn bandwidth_from_toc(toc: u8) -> Bandwidth {
2923 let mode = mode_from_toc(toc);
2924 match mode {
2925 OpusMode::SilkOnly => {
2926 let bw_bits = (toc >> 5) & 0x03;
2927 match bw_bits {
2928 0 => Bandwidth::Narrowband,
2929 1 => Bandwidth::Mediumband,
2930 2 => Bandwidth::Wideband,
2931 _ => Bandwidth::Wideband,
2932 }
2933 }
2934 OpusMode::Hybrid => {
2935 let bw_bit = (toc >> 4) & 0x01;
2936 if bw_bit == 0 {
2937 Bandwidth::Superwideband
2938 } else {
2939 Bandwidth::Fullband
2940 }
2941 }
2942 OpusMode::CeltOnly => {
2943 let bw_bits = (toc >> 5) & 0x03;
2944 match bw_bits {
2945 0 => Bandwidth::Mediumband,
2946 1 => Bandwidth::Wideband,
2947 2 => Bandwidth::Superwideband,
2948 3 => Bandwidth::Fullband,
2949 _ => Bandwidth::Fullband,
2950 }
2951 }
2952 }
2953}
2954
2955fn frame_duration_ms_from_toc(toc: u8) -> i32 {
2956 let mode = mode_from_toc(toc);
2957 match mode {
2958 OpusMode::SilkOnly => {
2959 let config = (toc >> 3) & 0x03;
2960 match config {
2961 0 => 10,
2962 1 => 20,
2963 2 => 40,
2964 3 => 60,
2965 _ => 20,
2966 }
2967 }
2968 OpusMode::Hybrid => {
2969 let config = (toc >> 3) & 0x01;
2970 if config == 0 { 10 } else { 20 }
2971 }
2972 OpusMode::CeltOnly => {
2973 let config = (toc >> 3) & 0x03;
2974 match config {
2975 0 => 2,
2976 1 => 5,
2977 2 => 10,
2978 3 => 20,
2979 _ => 20,
2980 }
2981 }
2982 }
2983}
2984
2985fn channels_from_toc(toc: u8) -> usize {
2986 if toc & 0x04 != 0 { 2 } else { 1 }
2987}
2988
2989fn read_opus_frame_len(data: &[u8], ptr: usize) -> Result<(usize, usize), &'static str> {
2993 let b0 = *data.get(ptr).ok_or("Opus frame length: truncated")? as usize;
2994 if b0 < 252 {
2995 Ok((b0, 1))
2996 } else {
2997 let b1 = *data.get(ptr + 1).ok_or("Opus frame length: truncated 2-byte")? as usize;
2998 Ok((b1 * 4 + b0, 2))
2999 }
3000}
3001
3002#[cfg(test)]
3003mod tests {
3004 use super::*;
3005
3006 fn frame_size_from_toc(toc: u8, sampling_rate: i32) -> Option<usize> {
3007 let mode = mode_from_toc(toc);
3008 match mode {
3009 OpusMode::CeltOnly => {
3010 let period = ((toc >> 3) & 0x03) as i32;
3011 let frame_rate = 400 >> period;
3012 if frame_rate == 0 || sampling_rate % frame_rate != 0 {
3013 return None;
3014 }
3015 Some((sampling_rate / frame_rate) as usize)
3016 }
3017 OpusMode::SilkOnly => {
3018 let duration_ms = frame_duration_ms_from_toc(toc);
3019 Some((sampling_rate as i64 * duration_ms as i64 / 1000) as usize)
3020 }
3021 OpusMode::Hybrid => {
3022 let duration_ms = frame_duration_ms_from_toc(toc);
3023 Some((sampling_rate as i64 * duration_ms as i64 / 1000) as usize)
3024 }
3025 }
3026 }
3027
3028 #[test]
3029 fn gen_toc_matches_celt_reference_values() {
3030 let sampling_rate = 48_000;
3031 let cases = [
3032 (120usize, 0xE0u8),
3033 (240usize, 0xE8u8),
3034 (480usize, 0xF0u8),
3035 (960usize, 0xF8u8),
3036 ];
3037
3038 for (frame_size, expected_toc) in cases {
3039 let frame_rate = frame_rate_from_params(sampling_rate, frame_size).unwrap();
3040 let toc = gen_toc(OpusMode::CeltOnly, frame_rate, Bandwidth::Fullband, 1);
3041 assert_eq!(
3042 toc, expected_toc,
3043 "frame_size {} expected TOC {:02X} got {:02X}",
3044 frame_size, expected_toc, toc
3045 );
3046 let decoded_size = frame_size_from_toc(toc, sampling_rate).unwrap();
3047 assert_eq!(decoded_size, frame_size);
3048 }
3049
3050 let stereo_toc = gen_toc(
3051 OpusMode::CeltOnly,
3052 frame_rate_from_params(sampling_rate, 960).unwrap(),
3053 Bandwidth::Fullband,
3054 2,
3055 );
3056 assert_eq!(channels_from_toc(stereo_toc), 2);
3057 }
3058
3059 #[test]
3060 fn test_celt_decoder_large_frame_sizes() {
3061 let sampling_rate = 48000;
3062 let channels = 1;
3063
3064 let mut decoder = OpusDecoder::new(sampling_rate, channels).unwrap();
3065
3066 let frame_sizes = [120, 240, 480, 960];
3067
3068 for frame_size in frame_sizes {
3069 let toc = gen_toc(
3070 OpusMode::CeltOnly,
3071 frame_rate_from_params(sampling_rate, frame_size).unwrap(),
3072 Bandwidth::Fullband,
3073 channels,
3074 );
3075 let packet = [toc, 0, 0, 0, 0];
3076
3077 let mut output = vec![0.0f32; frame_size * channels];
3078
3079 let _ = decoder.decode(&packet, frame_size, &mut output);
3080 }
3081
3082 let channels = 2;
3083 let mut decoder = OpusDecoder::new(sampling_rate, channels).unwrap();
3084
3085 for frame_size in frame_sizes {
3086 let toc = gen_toc(
3087 OpusMode::CeltOnly,
3088 frame_rate_from_params(sampling_rate, frame_size).unwrap(),
3089 Bandwidth::Fullband,
3090 channels,
3091 );
3092 let packet = [toc, 0, 0, 0, 0];
3093
3094 let mut output = vec![0.0f32; frame_size * channels];
3095 let _ = decoder.decode(&packet, frame_size, &mut output);
3096 }
3097 }
3098
3099 #[test]
3100 fn test_celt_decoder_edge_case_frame_sizes() {
3101 let sampling_rate = 48000;
3102 let channels = 1;
3103 let mut decoder = OpusDecoder::new(sampling_rate, channels).unwrap();
3104
3105 let edge_sizes = [2048, 2167, 2168, 2169, 2880, 3072];
3106
3107 for frame_size in edge_sizes {
3108 let mut output = vec![0.0f32; frame_size * channels];
3109
3110 let _ = decoder.decode(&[0x80, 0, 0, 0], frame_size, &mut output);
3111 }
3112 }
3113
3114 #[test]
3121 fn test_invalid_small_frame_size_returns_error_not_panic() {
3122 let mut enc = OpusEncoder::new(48000, 2, Application::Voip).unwrap();
3123 enc.bitrate_bps = 64000;
3124 enc.complexity = 5;
3125 enc.use_cbr = true;
3126
3127 let input = vec![0.0f32; 48 * 2]; let mut output = vec![0u8; 256];
3130
3131 let result = enc.encode(&input, 48, &mut output);
3132 assert!(
3133 result.is_err(),
3134 "encode with invalid frame_size=48 should return Err, not panic"
3135 );
3136 }
3137
3138 #[test]
3141 fn test_invalid_small_frame_size_audio_application_returns_error() {
3142 let mut enc = OpusEncoder::new(48000, 1, Application::Audio).unwrap();
3143 let input = vec![0.0f32; 48];
3144 let mut output = vec![0u8; 256];
3145
3146 let result = enc.encode(&input, 48, &mut output);
3147 assert!(
3148 result.is_err(),
3149 "Audio/48kHz encoder with frame_size=48 should return Err"
3150 );
3151 }
3152}