Skip to main content

rusty_opus/
lib.rs

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::resampler::{silk_resampler_down2, silk_resampler_down2_3};
37use silk::structs::SilkEncoderState;
38
39#[derive(Debug, Clone, Copy, PartialEq, Eq)]
40pub enum Application {
41    Voip = 2048,
42    Audio = 2049,
43    RestrictedLowDelay = 2051,
44}
45
46/// OPUS_SET_SIGNAL hint: bias mode selection toward speech or music. `None` =
47/// OPUS_AUTO (let the analysis decide).
48#[derive(Debug, Clone, Copy, PartialEq, Eq)]
49pub enum SignalType {
50    Voice,
51    Music,
52}
53
54#[derive(Debug, Clone, Copy, PartialEq, Eq)]
55pub enum Bandwidth {
56    Auto = -1000,
57    Narrowband = 1101,
58    Mediumband = 1102,
59    Wideband = 1103,
60    Superwideband = 1104,
61    Fullband = 1105,
62}
63
64#[derive(Debug, Clone, Copy, PartialEq, Eq)]
65enum OpusMode {
66    SilkOnly,
67    Hybrid,
68    CeltOnly,
69}
70
71pub struct OpusEncoder {
72    celt_enc: CeltEncoder,
73    silk_enc: Box<SilkEncoderState>,
74    application: Application,
75    sampling_rate: i32,
76    channels: usize,
77    bandwidth: Bandwidth,
78    pub bitrate_bps: i32,
79    pub complexity: i32,
80    pub use_cbr: bool,
81
82    pub use_inband_fec: bool,
83
84    /// Discontinuous transmission: after enough consecutive inactive frames,
85    /// emit a 1-byte (TOC-only) packet so the decoder runs comfort-noise/PLC.
86    pub use_dtx: bool,
87    /// Consecutive inactive milliseconds, in Q1 (opus_encoder.c nb_no_activity).
88    nb_no_activity_ms_q1: i32,
89    /// Final range-coder state of the last packet (0 for DTX/PLC packets, which
90    /// carry no coded range — opus_encoder.c st->rangeFinal).
91    range_final: u32,
92
93    pub packet_loss_perc: i32,
94    silk_initialized: bool,
95    mode: OpusMode,
96    prev_enc_mode: Option<OpusMode>,
97
98    variable_hp_smth2_q15: i32,
99    /// Rate-dependent automatic bandwidth (libopus auto_bandwidth), stored as the
100    /// Bandwidth discriminant (1101 NB .. 1105 FB). Hysteresis state.
101    auto_bandwidth: i32,
102    first_frame: bool,
103    /// Overrides automatic bandwidth selection when set (OPUS_SET_BANDWIDTH).
104    pub force_bandwidth: Option<Bandwidth>,
105    /// OPUS_SET_SIGNAL: force the voice/music bias (None = auto from analysis).
106    pub signal_type: Option<SignalType>,
107    /// OPUS_SET_MAX_BANDWIDTH: cap the automatically-selected bandwidth.
108    pub max_bandwidth: Bandwidth,
109    /// Tonality/music/bandwidth analysis (libopus src/analysis.c); runs when
110    /// complexity >= 7 and the API rate is >= 16 kHz.
111    tonality: analysis::TonalityAnalysisState,
112    analysis_kfft: Option<kiss_fft::KissFftState>,
113    /// Input bit depth assumed by the analysis noise floors. The float API
114    /// default is 24; set 16 for s16-sourced content (opus_demo parity).
115    pub lsb_depth: i32,
116    /// 0..100 voice probability from the analysis (-1 = unknown), C voice_ratio.
117    voice_ratio: i32,
118    detected_bandwidth: i32,
119    hp_mem: Vec<i32>,
120
121    buf_filtered: Vec<i16>,
122    buf_silk_input: Vec<i16>,
123    buf_stereo_mid: Vec<i16>,
124    buf_stereo_side: Vec<i16>,
125    buf_celt_input: Vec<f32>,
126    down2_state_first: [i32; 2],
127    down2_state_second: [i32; 2],
128    down2_3_state: [i32; 6],
129    down_1_3_state: silk::resampler::SilkResamplerDown1_3,
130    down2_3_state_r: [i32; 6],
131    down_1_3_state_r: silk::resampler::SilkResamplerDown1_3,
132    down_fir_l: Option<silk::resampler::SilkDownFirResampler>,
133    down_fir_r: Option<silk::resampler::SilkDownFirResampler>,
134    /// Last 10 ms of API-rate mono input, for the SILK prefill after a
135    /// CELT-only -> SILK/hybrid transition (opus_encoder.c:1449 prefill=1).
136    silk_prefill_tail: Vec<i16>,
137    silk_prefill_pending: bool,
138    buf_left: Vec<i16>,
139    buf_right: Vec<i16>,
140    /// Last 2.5 ms of the previous frame's input (planar), for the CELT
141    /// prefill after a mode-transition reset (opus_encoder.c:2060).
142    celt_prefill_tail: Vec<f32>,
143
144    rc: RangeCoder,
145}
146
147// libopus opus_encoder.c bandwidth thresholds: (threshold, hysteresis) pairs for
148// NB<->MB, MB<->WB, WB<->SWB, SWB<->FB, interpolated voice<->music by voice_est^2.
149const MONO_VOICE_BANDWIDTH_THRESHOLDS: [i32; 8] = [9000, 700, 9000, 700, 13500, 1000, 14000, 2000];
150const MONO_MUSIC_BANDWIDTH_THRESHOLDS: [i32; 8] = [9000, 700, 9000, 700, 11000, 1000, 12000, 2000];
151const STEREO_VOICE_BANDWIDTH_THRESHOLDS: [i32; 8] = [9000, 700, 9000, 700, 13500, 1000, 14000, 2000];
152const STEREO_MUSIC_BANDWIDTH_THRESHOLDS: [i32; 8] = [9000, 700, 9000, 700, 11000, 1000, 12000, 2000];
153
154fn compute_equiv_rate(
155    bitrate: i32,
156    channels: usize,
157    frame_rate: i32,
158    vbr: bool,
159    complexity: i32,
160    loss: i32,
161) -> i32 {
162    let mut equiv = bitrate;
163    if frame_rate > 50 {
164        equiv -= (40 * channels as i32 + 20) * (frame_rate - 50);
165    }
166    if !vbr {
167        equiv -= equiv / 12;
168    }
169    equiv = equiv * (90 + complexity) / 100;
170    if loss > 0 {
171        equiv -= equiv * loss / (12 * loss + 20);
172    }
173    equiv
174}
175
176fn compute_mode_threshold(
177    application: Application,
178    channels: usize,
179    prev_was_celt: bool,
180    has_prev_mode: bool,
181    voice_est: i32,
182) -> i32 {
183    let mode_voice = if channels == 1 { 64000 } else { 44000 };
184    let mode_music = 10000;
185
186    let diff = mode_voice - mode_music;
187    let offset = (voice_est * voice_est * diff) >> 14;
188    let mut threshold = mode_music + offset;
189
190    if application == Application::Voip {
191        threshold += 8000;
192    }
193
194    if has_prev_mode {
195        if prev_was_celt {
196            threshold -= 4000;
197        } else {
198            threshold += 4000;
199        }
200    }
201
202    if application == Application::RestrictedLowDelay {
203        threshold = 0;
204    }
205
206    threshold
207}
208
209fn compute_silk_rate_for_hybrid(
210    rate_bps: i32,
211    bandwidth: Bandwidth,
212    frame20ms: bool,
213    vbr: bool,
214) -> i32 {
215    const RATE_TABLE: &[(i32, i32, i32)] = &[
216        (0, 0, 0),
217        (12000, 10000, 10000),
218        (16000, 13500, 13500),
219        (20000, 16000, 16000),
220        (24000, 18000, 18000),
221        (32000, 22000, 22000),
222        (64000, 38000, 38000),
223    ];
224    let n = RATE_TABLE.len();
225    let mut i = 1;
226    while i < n && RATE_TABLE[i].0 <= rate_bps {
227        i += 1;
228    }
229    let mut silk_rate = if i == n {
230        let (x_last, r10_last, r20_last) = RATE_TABLE[n - 1];
231        let base = if frame20ms { r20_last } else { r10_last };
232        base + (rate_bps - x_last) / 2
233    } else {
234        let (x0, lo10, lo20) = RATE_TABLE[i - 1];
235        let (x1, hi10, hi20) = RATE_TABLE[i];
236        let (lo, hi) = if frame20ms {
237            (lo20, hi20)
238        } else {
239            (lo10, hi10)
240        };
241        (lo * (x1 - rate_bps) + hi * (rate_bps - x0)) / (x1 - x0)
242    };
243    // C tail adjustments (opus_encoder.c:789): tiny SILK boost for CBR, and
244    // +300 for SWB hybrid (the CELT part starts at band 17 either way but
245    // covers less spectrum, so SILK earns a bigger share).
246    if !vbr {
247        silk_rate += 100;
248    }
249    if bandwidth == Bandwidth::Superwideband {
250        silk_rate += 300;
251    }
252    silk_rate
253}
254
255#[cfg(test)]
256mod silk_rate_tests {
257    use super::compute_silk_rate_for_hybrid;
258    use crate::Bandwidth;
259
260    #[test]
261    fn test_reference_table_exact_entries() {
262        assert_eq!(compute_silk_rate_for_hybrid(12000, Bandwidth::Fullband, true, true), 10000);
263        assert_eq!(compute_silk_rate_for_hybrid(16000, Bandwidth::Fullband, true, true), 13500);
264        assert_eq!(compute_silk_rate_for_hybrid(20000, Bandwidth::Fullband, true, true), 16000);
265        assert_eq!(compute_silk_rate_for_hybrid(24000, Bandwidth::Fullband, true, true), 18000);
266        assert_eq!(compute_silk_rate_for_hybrid(32000, Bandwidth::Fullband, true, true), 22000);
267        assert_eq!(compute_silk_rate_for_hybrid(64000, Bandwidth::Fullband, true, true), 38000);
268    }
269
270    #[test]
271    fn test_32kbps_gives_22kbps_silk() {
272        assert_eq!(compute_silk_rate_for_hybrid(32000, Bandwidth::Fullband, true, true), 22000);
273    }
274
275    #[test]
276    fn test_interpolation_between_table_entries() {
277        let r = compute_silk_rate_for_hybrid(18000, Bandwidth::Fullband, true, true);
278        assert_eq!(r, 14750);
279    }
280
281    #[test]
282    fn test_above_table_max_gives_half_extra() {
283        let r = compute_silk_rate_for_hybrid(72000, Bandwidth::Fullband, true, true);
284        assert_eq!(r, 38000 + (72000 - 64000) / 2);
285    }
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        let celt_enc = CeltEncoder::new(mode, channels);
303
304        let mut silk_enc = Box::new(SilkEncoderState::default());
305        if silk_init_encoder(&mut silk_enc, 0) != 0 {
306            return Err("SILK encoder initialization failed");
307        }
308
309        let (opus_mode, bw) = match application {
310            Application::Voip => {
311                let bw = match sampling_rate {
312                    8000 => Bandwidth::Narrowband,
313                    12000 => Bandwidth::Mediumband,
314                    16000 => Bandwidth::Wideband,
315                    24000 => Bandwidth::Superwideband,
316                    48000 => Bandwidth::Fullband,
317                    _ => Bandwidth::Narrowband,
318                };
319
320                let mode = if sampling_rate > 16000 {
321                    OpusMode::Hybrid
322                } else {
323                    OpusMode::SilkOnly
324                };
325                (mode, bw)
326            }
327            Application::RestrictedLowDelay => {
328                let bw = match sampling_rate {
329                    8000 => Bandwidth::Narrowband,
330                    12000 => Bandwidth::Mediumband,
331                    16000 => Bandwidth::Wideband,
332                    24000 => Bandwidth::Superwideband,
333                    _ => Bandwidth::Fullband,
334                };
335                (OpusMode::CeltOnly, bw)
336            }
337            Application::Audio => {
338                if sampling_rate <= 16000 {
339                    let bw = match sampling_rate {
340                        8000 => Bandwidth::Narrowband,
341                        12000 => Bandwidth::Mediumband,
342                        _ => Bandwidth::Wideband,
343                    };
344                    (OpusMode::SilkOnly, bw)
345                } else {
346                    let bw = match sampling_rate {
347                        24000 => Bandwidth::Superwideband,
348                        _ => Bandwidth::Fullband,
349                    };
350                    (OpusMode::Hybrid, bw)
351                }
352            }
353        };
354
355        use silk::lin2log::silk_lin2log;
356        let variable_hp_smth2_q15 = silk_lin2log(60) << 8;
357
358        Ok(Self {
359            celt_enc,
360            silk_enc,
361            application,
362            sampling_rate,
363            channels,
364            bandwidth: bw,
365            bitrate_bps: 64000,
366            complexity: 9,
367            use_cbr: false,
368            use_inband_fec: false,
369            use_dtx: false,
370            nb_no_activity_ms_q1: 0,
371            range_final: 0,
372            packet_loss_perc: 0,
373            silk_initialized: false,
374            prev_enc_mode: None,
375            mode: opus_mode,
376            variable_hp_smth2_q15,
377            auto_bandwidth: 0,
378            first_frame: true,
379            force_bandwidth: None,
380            signal_type: None,
381            max_bandwidth: Bandwidth::Fullband,
382            tonality: analysis::TonalityAnalysisState::new(sampling_rate),
383            analysis_kfft: kiss_fft::KissFftState::new(480),
384            lsb_depth: 24,
385            voice_ratio: -1,
386            detected_bandwidth: 0,
387            hp_mem: vec![0; channels * 2],
388
389            buf_filtered: Vec::new(),
390            buf_silk_input: Vec::new(),
391            buf_stereo_mid: Vec::new(),
392            buf_stereo_side: Vec::new(),
393            buf_celt_input: Vec::new(),
394            down2_state_first: [0; 2],
395            down2_state_second: [0; 2],
396            down2_3_state: [0; 6],
397            down_1_3_state: silk::resampler::SilkResamplerDown1_3::default(),
398            down2_3_state_r: [0; 6],
399            down_1_3_state_r: silk::resampler::SilkResamplerDown1_3::default(),
400            down_fir_l: None,
401            down_fir_r: None,
402            silk_prefill_tail: Vec::new(),
403            silk_prefill_pending: false,
404            buf_left: Vec::new(),
405            buf_right: Vec::new(),
406            celt_prefill_tail: Vec::new(),
407            rc: RangeCoder::new_encoder(1),
408        })
409    }
410
411    pub fn enable_hybrid_mode(&mut self) -> Result<(), &'static str> {
412        if self.sampling_rate != 24000 && self.sampling_rate != 48000 {
413            return Err("Hybrid mode requires 24kHz or 48kHz sampling rate");
414        }
415        let bw = if self.sampling_rate == 48000 {
416            Bandwidth::Fullband
417        } else {
418            Bandwidth::Superwideband
419        };
420        self.mode = OpusMode::Hybrid;
421        self.bandwidth = bw;
422        self.silk_initialized = false;
423        Ok(())
424    }
425
426    /// Final range-coder state of the last encoded packet (libopus
427    /// OPUS_GET_FINAL_RANGE). Stored in opus_demo `.bit` framing so the reference
428    /// decoder can verify encoder/decoder range-coder agreement per packet.
429    pub fn final_range(&self) -> u32 {
430        self.range_final
431    }
432
433    /// opus_encoder.c:1296 voice_est ladder (signal_type is AUTO for us):
434    /// analysis-driven when voice_ratio is known, else application defaults.
435    fn compute_voice_est(&self) -> i32 {
436        match self.signal_type {
437            Some(SignalType::Voice) => return 127,
438            Some(SignalType::Music) => return 0,
439            None => {}
440        }
441        if self.voice_ratio >= 0 {
442            let mut v = self.voice_ratio * 327 >> 8;
443            // For AUDIO, never be more than 90% confident of having speech.
444            if self.application == Application::Audio {
445                v = v.min(115);
446            }
447            v
448        } else {
449            match self.application {
450                Application::Voip => 115,
451                Application::Audio => 48,
452                Application::RestrictedLowDelay => 0,
453            }
454        }
455    }
456
457    pub fn encode(
458        &mut self,
459        input: &[f32],
460        frame_size: usize,
461        output: &mut [u8],
462    ) -> Result<usize, &'static str> {
463        let _prof_total = crate::prof::scope(crate::prof::Stage::Total);
464        if output.len() < 2 {
465            return Err("Output buffer too small");
466        }
467
468        let frame_rate = frame_rate_from_params(self.sampling_rate, frame_size)
469            .ok_or("Invalid frame size for sampling rate")?;
470
471        // ---- Tonality analysis (opus_encoder.c:1123) ----
472        let mut analysis_info = analysis::AnalysisInfo::default();
473        if self.complexity >= 7 && self.sampling_rate >= 16000 {
474            if let Some(kfft) = &self.analysis_kfft {
475                analysis_info = analysis::run_analysis(
476                    &mut self.tonality,
477                    kfft,
478                    input,
479                    frame_size,
480                    frame_size,
481                    self.channels,
482                    self.sampling_rate,
483                    self.lsb_depth,
484                );
485            }
486        } else if self.tonality.initialized() {
487            self.tonality.reset();
488        }
489
490        // voice_ratio / detected_bandwidth from the analysis (opus_encoder.c:1154).
491        let silence_thresh = 1.0f32 / (1i64 << self.lsb_depth) as f32;
492        let is_silence = input[..(frame_size * self.channels).min(input.len())]
493            .iter()
494            .fold(0.0f32, |m, &v| m.max(v.abs()))
495            <= silence_thresh;
496        if !is_silence {
497            self.voice_ratio = -1;
498        }
499        // Voice-activity flag for DTX (opus_encoder.c:1160). Silence is always
500        // inactive; with analysis, use the VAD probability; without it, assume
501        // active (conservative — never DTX away real audio). We skip the
502        // peak-energy SNR fallback, which only ever ADDS activity.
503        let activity = if is_silence {
504            false
505        } else if analysis_info.valid {
506            analysis_info.activity_probability >= 0.1
507        } else {
508            true
509        };
510        self.detected_bandwidth = 0;
511        if analysis_info.valid {
512            // signal_type is AUTO: pick the hysteresis-correct probability.
513            let prob = if self.prev_enc_mode.is_none() {
514                analysis_info.music_prob
515            } else if self.prev_enc_mode == Some(OpusMode::CeltOnly) {
516                analysis_info.music_prob_max
517            } else {
518                analysis_info.music_prob_min
519            };
520            self.voice_ratio = (0.5 + 100.0 * (1.0 - prob)).floor() as i32;
521            let ab = analysis_info.bandwidth;
522            self.detected_bandwidth = if ab <= 12 {
523                Bandwidth::Narrowband as i32
524            } else if ab <= 14 {
525                Bandwidth::Mediumband as i32
526            } else if ab <= 16 {
527                Bandwidth::Wideband as i32
528            } else if ab <= 18 {
529                Bandwidth::Superwideband as i32
530            } else {
531                Bandwidth::Fullband as i32
532            };
533        }
534
535        // Mode selection: match C's opus_encode_native() behavior.
536        // C reference auto-selects between SILK_ONLY and CELT_ONLY; Hybrid is
537        // produced afterwards by bandwidth overrides (SILK-only + FB/SWB → Hybrid).
538        let mut mode = if self.application == Application::RestrictedLowDelay {
539            OpusMode::CeltOnly
540        } else {
541            let equiv = compute_equiv_rate(
542                self.bitrate_bps,
543                self.channels,
544                frame_rate,
545                !self.use_cbr,
546                self.complexity,
547                self.packet_loss_perc,
548            );
549            let prev_was_celt = self.prev_enc_mode == Some(OpusMode::CeltOnly);
550            let has_prev_mode = self.prev_enc_mode.is_some();
551            let voice_est = self.compute_voice_est();
552            let threshold = compute_mode_threshold(
553                self.application,
554                self.channels,
555                prev_was_celt,
556                has_prev_mode,
557                voice_est,
558            );
559            if equiv >= threshold && self.sampling_rate >= 24000 {
560                OpusMode::CeltOnly
561            } else {
562                OpusMode::SilkOnly
563            }
564        };
565
566        // ---- Automatic rate-dependent bandwidth selection (opus_encoder.c:1456) ----
567        // Walk down from FB; stop at the first bandwidth whose hysteresis-adjusted
568        // threshold the equivalent rate meets. Thresholds interpolate voice<->music
569        // by voice_est^2. Without the tonality analysis we cannot do
570        // detected-bandwidth reduction, so this reproduces libopus's
571        // complexity-0 choices (measured: WB @16k, SWB @20k, FB @24k+ voip mono).
572        {
573            let equiv = compute_equiv_rate(
574                self.bitrate_bps,
575                self.channels,
576                frame_rate,
577                !self.use_cbr,
578                self.complexity,
579                self.packet_loss_perc,
580            );
581            let voice_est: i32 = self.compute_voice_est();
582            let (vt, mt) = if self.channels == 2 {
583                (
584                    &STEREO_VOICE_BANDWIDTH_THRESHOLDS,
585                    &STEREO_MUSIC_BANDWIDTH_THRESHOLDS,
586                )
587            } else {
588                (
589                    &MONO_VOICE_BANDWIDTH_THRESHOLDS,
590                    &MONO_MUSIC_BANDWIDTH_THRESHOLDS,
591                )
592            };
593            let mut th = [0i32; 8];
594            for i in 0..8 {
595                th[i] = mt[i] + ((voice_est * voice_est * (vt[i] - mt[i])) >> 14);
596            }
597            const NB: i32 = Bandwidth::Narrowband as i32; // 1101
598            const MB: i32 = Bandwidth::Mediumband as i32; // 1102
599            const FB: i32 = Bandwidth::Fullband as i32; // 1105
600            let mut bw = FB;
601            while bw > NB {
602                let idx = (2 * (bw - MB)) as usize;
603                let mut threshold = th[idx];
604                let hysteresis = th[idx + 1];
605                if !self.first_frame {
606                    if self.auto_bandwidth >= bw {
607                        threshold -= hysteresis;
608                    } else {
609                        threshold += hysteresis;
610                    }
611                }
612                if equiv >= threshold {
613                    break;
614                }
615                bw -= 1;
616            }
617            // Mediumband is no longer used by libopus's selector.
618            if bw == MB {
619                bw = Bandwidth::Wideband as i32;
620            }
621            self.auto_bandwidth = bw;
622            // Hybrid at unsafe CBR rates starves SILK: cap at WB below 15 kb/s.
623            if mode != OpusMode::CeltOnly && self.use_cbr && self.bitrate_bps < 15000 {
624                bw = bw.min(Bandwidth::Wideband as i32);
625            }
626            // NB/MB SILK-internal rates (8/12 kHz) aren't wired for >16 kHz API
627            // input yet (no 48k->8k/12k encode resamplers); clamp to WB.
628            if mode != OpusMode::CeltOnly && self.sampling_rate > 16000 {
629                bw = bw.max(Bandwidth::Wideband as i32);
630            }
631            // Never code above the input's Nyquist (opus_encoder.c:1516).
632            if self.sampling_rate <= 24000 {
633                bw = bw.min(Bandwidth::Superwideband as i32);
634            }
635            if self.sampling_rate <= 16000 {
636                bw = bw.min(Bandwidth::Wideband as i32);
637            }
638            if self.sampling_rate <= 12000 {
639                bw = bw.min(Bandwidth::Mediumband as i32);
640            }
641            if self.sampling_rate <= 8000 {
642                bw = bw.min(Bandwidth::Narrowband as i32);
643            }
644            // (MB remap above may have been undone by the caps; keep WB floor
645            // only where the API rate allows it.)
646            if bw == Bandwidth::Mediumband as i32 && self.sampling_rate > 12000 {
647                bw = Bandwidth::Wideband as i32;
648            }
649            // Use the detected bandwidth to reduce the coded bandwidth
650            // (opus_encoder.c:1526), conservatively floored by rate. (For
651            // CELT-only this is currently undone below — no end-band support.)
652            // For CELT-only, hold the detected-bandwidth narrowing until the
653            // leak_boost dynalloc lands: decisions already match libopus
654            // frame-for-frame (64k st music: 27:704/31:680/23:90 both), but our
655            // dynalloc lacks C's leakage compensation at the spectral cut, so
656            // the same narrowing costs 0.25 ODG more than C pays (PEAQ-gated
657            // out). Hybrid/SILK caps (incl. hybrid SWB) stay live.
658            // CELT-only keeps FULL bandwidth by choice: C's detected-bandwidth
659            // narrowing costs PEAQ universally (libopus's own -2.11 at 64k st
660            // IS its narrowed score; our FB encode scores -1.65 on the same
661            // clip). leak_boost did NOT change this verdict (tested 2026-07-09
662            // with the full dynalloc live: narrowing still -2.37). Hybrid/SILK
663            // caps stay (they pick coding MODE, not spectral truncation).
664            if self.detected_bandwidth != 0
665                && self.force_bandwidth.is_none()
666                && mode != OpusMode::CeltOnly
667            {
668                let ch = self.channels as i32;
669                let equiv2 = equiv; // same 20-ms equivalent rate as the walk
670                let min_det = if equiv2 <= 18000 * ch && mode == OpusMode::CeltOnly {
671                    NB
672                } else if equiv2 <= 24000 * ch && mode == OpusMode::CeltOnly {
673                    MB
674                } else if equiv2 <= 30000 * ch {
675                    Bandwidth::Wideband as i32
676                } else if equiv2 <= 44000 * ch {
677                    Bandwidth::Superwideband as i32
678                } else {
679                    FB
680                };
681                bw = bw.min(self.detected_bandwidth.max(min_det));
682            }
683            // Cap by OPUS_SET_MAX_BANDWIDTH before the force override
684            // (opus_encoder.c: bandwidth = IMIN(bandwidth, max_bandwidth)), but
685            // keep the WB floor for non-CELT >16 kHz input — NB/MB SILK from
686            // 48 kHz needs the 48->8/12k encode resamplers we don't have, so a
687            // max_bandwidth of NB/MB there would emit an uncodeable config.
688            let mut max_bw = self.max_bandwidth as i32;
689            if mode != OpusMode::CeltOnly && self.sampling_rate > 16000 {
690                max_bw = max_bw.max(Bandwidth::Wideband as i32);
691            }
692            bw = bw.min(max_bw);
693            // The CELT TOC has no mediumband config; C maps MB down to NB.
694            if mode == OpusMode::CeltOnly && bw == MB {
695                bw = NB;
696            }
697            self.bandwidth = match self.force_bandwidth {
698                Some(f) => f,
699                None => match bw {
700                    x if x == NB => Bandwidth::Narrowband,
701                    x if x == MB => Bandwidth::Mediumband,
702                    x if x == Bandwidth::Wideband as i32 => Bandwidth::Wideband,
703                    x if x == Bandwidth::Superwideband as i32 => Bandwidth::Superwideband,
704                    x if x == FB => Bandwidth::Fullband,
705                    _ => Bandwidth::Wideband,
706                },
707            };
708            self.first_frame = false;
709        }
710
711        let curr_bw = self.bandwidth;
712        if mode == OpusMode::SilkOnly
713            && (curr_bw == Bandwidth::Superwideband || curr_bw == Bandwidth::Fullband)
714        {
715            mode = OpusMode::Hybrid;
716        }
717        if mode == OpusMode::Hybrid
718            && (curr_bw == Bandwidth::Narrowband
719                || curr_bw == Bandwidth::Mediumband
720                || curr_bw == Bandwidth::Wideband)
721        {
722            mode = OpusMode::SilkOnly;
723        }
724
725        // Stereo hybrid is now CONFORMANT (the CELT intensity-clamp fix), but
726        // our FIXED-point stereo SILK executes it worse than plain CELT-FB above
727        // ~28 kb/s: PEAQ on stereo speech (ODG) measured hybrid −2.196/−2.193 vs
728        // CELT-FB −2.136/−2.057 at 32k/48k (CELT-FB wins), while at 24k hybrid
729        // −2.198 beats CELT-FB −2.240. libopus's FLOAT stereo SILK hybrid beats
730        // both everywhere — the gap is fixed-vs-float, not a bug. So route
731        // stereo hybrid to CELT-FB except at the low rates where it wins. (Force
732        // via OPUS_SET_BANDWIDTH if the true hybrid path is wanted.) The clean
733        // fix is float stereo SILK — a large port, tracked in the roadmap.
734        if self.channels == 2 && mode == OpusMode::Hybrid && self.bitrate_bps > 28000 {
735            mode = OpusMode::CeltOnly;
736            self.bandwidth = Bandwidth::Fullband;
737        }
738
739        if mode == OpusMode::CeltOnly {
740            match frame_rate {
741                400 | 200 | 100 | 50 => {}
742                _ => return Err("Unsupported frame size for CELT-only mode"),
743            }
744        }
745
746        if mode == OpusMode::Hybrid {
747            match frame_rate {
748                100 | 50 => {}
749                _ => return Err("Unsupported frame size for Hybrid mode"),
750            }
751        }
752
753        if mode == OpusMode::SilkOnly {
754            match frame_rate {
755                400 | 200 | 100 | 50 | 25 => {}
756                _ => return Err("Unsupported frame size for SILK-only mode"),
757            }
758        }
759
760        let n400 = (self.sampling_rate / 400) as usize;
761
762        // ---- Mode-transition resets (opus_encoder.c:1449 + 2054) ----
763        // The decoder resets its CELT state on ANY mode change (when there is
764        // no redundancy) and its SILK state when leaving CELT-only; the
765        // encoder must mirror both or the streams desync from that frame on.
766        if let Some(prev) = self.prev_enc_mode {
767            if prev != mode {
768                if mode != OpusMode::SilkOnly {
769                    let ch = self.channels;
770                    self.celt_enc = CeltEncoder::new(modes::default_mode(), ch);
771                    // Prefill 2.5 ms so the fresh state has real preemph/overlap
772                    // history instead of a hard edge (opus_encoder.c:2060).
773                    let n400 = (self.sampling_rate / 400) as usize;
774                    if self.celt_prefill_tail.len() == n400 * ch {
775                        let mut dummy = RangeCoder::new_encoder(2);
776                        let tail = std::mem::take(&mut self.celt_prefill_tail);
777                        self.celt_enc.encode_with_budget(&tail, n400, &mut dummy, 0, 21, 16);
778                        self.celt_prefill_tail = tail;
779                    }
780                }
781                if mode != OpusMode::CeltOnly && prev == OpusMode::CeltOnly {
782                    self.silk_initialized = false;
783                    self.silk_prefill_pending = true;
784                }
785            }
786        }
787
788        // SILK prefill tail: last 10 ms of API-rate mono input.
789        if self.channels == 1 {
790            let n10 = (self.sampling_rate / 100) as usize;
791            if frame_size >= n10 {
792                self.silk_prefill_tail.resize(n10, 0);
793                for i in 0..n10 {
794                    self.silk_prefill_tail[i] = (input[frame_size - n10 + i] * 32768.0)
795                        .clamp(-32768.0, 32767.0) as i16;
796                }
797            }
798        }
799
800        // Save THIS frame's last 2.5 ms (planar) for a possible prefill at the
801        // next mode transition. (The transition block above consumed the
802        // PREVIOUS frame's tail.)
803        {
804            let ch = self.channels;
805            self.celt_prefill_tail.resize(n400 * ch, 0.0);
806            let base = frame_size - n400;
807            for c in 0..ch {
808                for i in 0..n400 {
809                    self.celt_prefill_tail[c * n400 + i] = input[(base + i) * ch + c];
810                }
811            }
812        }
813
814        let toc = gen_toc(mode, frame_rate, self.bandwidth, self.channels);
815        output[0] = toc;
816
817        // ---- DTX decision (opus_encoder.c:2137 decide_dtx_mode) ----
818        // After enough consecutive inactive frames, emit a TOC-only 1-byte
819        // packet: the decoder sees an empty payload and runs comfort-noise /
820        // PLC. We decide before the (skipped) SILK/CELT encode — SILK's own DTX
821        // likewise stops coding, so the encoder state simply doesn't advance;
822        // the codecs resync on the next active frame.
823        if self.use_dtx && (analysis_info.valid || is_silence) {
824            let frame_ms_q1 = 2 * 1000 * frame_size as i32 / self.sampling_rate;
825            let dtx = if !activity {
826                self.nb_no_activity_ms_q1 += frame_ms_q1;
827                const LO: i32 = silk::define::NB_SPEECH_FRAMES_BEFORE_DTX * 20 * 2; // 400
828                const HI: i32 = (silk::define::NB_SPEECH_FRAMES_BEFORE_DTX + silk::define::MAX_CONSECUTIVE_DTX) * 20 * 2; // 1200
829                if self.nb_no_activity_ms_q1 > LO {
830                    if self.nb_no_activity_ms_q1 <= HI {
831                        true
832                    } else {
833                        self.nb_no_activity_ms_q1 = LO;
834                        false
835                    }
836                } else {
837                    false
838                }
839            } else {
840                self.nb_no_activity_ms_q1 = 0;
841                false
842            };
843            if dtx {
844                self.prev_enc_mode = Some(mode);
845                self.range_final = 0;
846                return Ok(1);
847            }
848        } else {
849            self.nb_no_activity_ms_q1 = 0;
850        }
851
852        let target_bits =
853            (self.bitrate_bps as i64 * frame_size as i64 / self.sampling_rate as i64) as i32;
854        let cbr_bytes = ((target_bits + 4) / 8) as usize;
855        let max_data_bytes = output.len();
856
857        // CBR: the packet is exactly the target size. VBR: start the coder on a
858        // generous buffer — SILK-only packets end at whatever SILK produced, and
859        // the CELT layer picks its own frame size (compute_vbr) and shrinks the
860        // coder to it (libopus opus_encoder.c / celt_encoder.c VBR flow).
861        let n_bytes = if self.use_cbr {
862            cbr_bytes.min(max_data_bytes).max(1)
863        } else {
864            max_data_bytes.min(1276).max(cbr_bytes.min(max_data_bytes)).max(3)
865        };
866
867        let init_rc_size = n_bytes - 1;
868        self.rc.reset_for_encode(init_rc_size as u32);
869
870        if mode == OpusMode::SilkOnly || mode == OpusMode::Hybrid {
871            let silk_fs_khz = if mode == OpusMode::Hybrid {
872                16
873            } else {
874                self.sampling_rate.min(16000) / 1000
875            };
876
877            let frame_ms = (frame_size as i32 * 1000) / self.sampling_rate;
878            if !self.silk_initialized || self.silk_enc.s_cmn.fs_khz != silk_fs_khz {
879                let silk_init_bitrate = if self.use_cbr {
880                    (((n_bytes - 1) * 8) as i64 * self.sampling_rate as i64 / frame_size as i64)
881                        as i32
882                } else {
883                    self.bitrate_bps
884                };
885                silk_control_encoder(
886                    &mut self.silk_enc,
887                    silk_fs_khz,
888                    frame_ms,
889                    silk_init_bitrate,
890                    self.complexity,
891                );
892                self.silk_enc.s_cmn.use_cbr = if self.use_cbr { 1 } else { 0 };
893
894                self.silk_enc.s_cmn.n_channels = self.channels as i32;
895                self.silk_initialized = true;
896                self.down2_state_first = [0; 2];
897                self.down2_state_second = [0; 2];
898                self.down2_3_state = [0; 6];
899                self.down_1_3_state = silk::resampler::SilkResamplerDown1_3::default();
900                self.down2_3_state_r = [0; 6];
901                self.down_1_3_state_r = silk::resampler::SilkResamplerDown1_3::default();
902                self.down_fir_l =
903                    silk::resampler::SilkDownFirResampler::new(self.sampling_rate, 16000);
904                self.down_fir_r =
905                    silk::resampler::SilkDownFirResampler::new(self.sampling_rate, 16000);
906            }
907
908            // SILK prefill after CELT-only (opus_encoder.c prefill=1): run 10 ms
909            // of the previous audio through the fresh resampler + SILK warmup
910            // path so the first coded SILK frame has real LTP/shape history.
911            if self.silk_prefill_pending {
912                self.silk_prefill_pending = false;
913                let n10 = (self.sampling_rate / 100) as usize;
914                if self.channels == 1 && self.silk_prefill_tail.len() == n10 {
915                    let need = silk_fs_khz as usize * 10;
916                    let mut resampled = vec![0i16; need];
917                    if self.sampling_rate > 16000 {
918                        if let Some(r) = &mut self.down_fir_l {
919                            r.process(&mut resampled, &self.silk_prefill_tail);
920                        }
921                    } else {
922                        resampled.copy_from_slice(&self.silk_prefill_tail[..need]);
923                    }
924                    silk::enc_api::silk_encode_prefill(&mut self.silk_enc, &resampled, 0);
925                }
926            }
927
928            self.silk_enc.s_cmn.use_in_band_fec = if self.use_inband_fec { 1 } else { 0 };
929            self.silk_enc.s_cmn.packet_loss_perc = self.packet_loss_perc.clamp(0, 100);
930
931            self.silk_enc.s_cmn.lbrr_enabled = if self.use_inband_fec { 1 } else { 0 };
932
933            if self.silk_enc.s_cmn.lbrr_gain_increases == 0 {
934                self.silk_enc.s_cmn.lbrr_gain_increases = 2;
935            }
936
937            let hp_freq_smth1 = if mode == OpusMode::CeltOnly {
938                silk_lin2log(60) << 8
939            } else {
940                self.silk_enc.s_cmn.variable_hp_smth1_q15
941            };
942
943            const VARIABLE_HP_SMTH_COEF2_Q16: i32 = 984;
944            self.variable_hp_smth2_q15 = silk_smlawb(
945                self.variable_hp_smth2_q15,
946                hp_freq_smth1 - self.variable_hp_smth2_q15,
947                VARIABLE_HP_SMTH_COEF2_Q16,
948            );
949
950            let cutoff_hz = silk_log2lin(silk_rshift(self.variable_hp_smth2_q15, 8));
951
952            let _prof_rs = crate::prof::scope(crate::prof::Stage::Resample);
953            let required_size = frame_size * self.channels;
954            self.buf_filtered.resize(required_size, 0);
955            if self.application == Application::Voip {
956                hp_cutoff(
957                    input,
958                    cutoff_hz,
959                    &mut self.buf_filtered,
960                    &mut self.hp_mem,
961                    frame_size,
962                    self.channels,
963                    self.sampling_rate,
964                );
965            } else {
966                for (i, &x) in input.iter().enumerate() {
967                    self.buf_filtered[i] = (x * 32768.0).clamp(-32768.0, 32767.0) as i16;
968                }
969            }
970
971            let input_i16 = &self.buf_filtered;
972
973            let silk_input: &[i16] = if self.channels == 2 {
974                // Stereo SILK/hybrid: deinterleave, resample EACH channel to the
975                // SILK-internal rate (separate filter states), then split
976                // mid/side — C's order (per-channel resampling inside
977                // silk_Encode, then silk_stereo_LR_to_MS). The old code only
978                // handled stereo at <=16 kHz and fed resampled INTERLEAVED
979                // audio to a stereo-configured SILK above that (never
980                // exercised until the analysis started picking stereo hybrid).
981                let frame_length = input_i16.len() / 2;
982                self.buf_left.resize(frame_length, 0);
983                self.buf_right.resize(frame_length, 0);
984                for i in 0..frame_length {
985                    self.buf_left[i] = input_i16[2 * i];
986                    self.buf_right[i] = input_i16[2 * i + 1];
987                }
988                let need_resample = self.sampling_rate > 16000;
989                let ds_len = if !need_resample {
990                    frame_length
991                } else if self.sampling_rate == 48000 {
992                    frame_length / 3
993                } else {
994                    frame_length * 2 / 3
995                };
996                if need_resample {
997                    self.buf_stereo_mid.resize(ds_len, 0);
998                    self.buf_stereo_side.resize(ds_len, 0);
999                    if let (Some(rl), Some(rr)) = (&mut self.down_fir_l, &mut self.down_fir_r) {
1000                        rl.process(&mut self.buf_stereo_mid, &self.buf_left);
1001                        rr.process(&mut self.buf_stereo_side, &self.buf_right);
1002                    }
1003                    self.buf_left.resize(ds_len, 0);
1004                    self.buf_right.resize(ds_len, 0);
1005                    self.buf_left.copy_from_slice(&self.buf_stereo_mid[..ds_len]);
1006                    self.buf_right.copy_from_slice(&self.buf_stereo_side[..ds_len]);
1007                }
1008                self.buf_stereo_mid.resize(ds_len, 0);
1009                self.buf_stereo_side.resize(ds_len, 0);
1010                for i in 0..ds_len {
1011                    let l = self.buf_left[i] as i32;
1012                    let r = self.buf_right[i] as i32;
1013                    self.buf_stereo_mid[i] = ((l + r) / 2) as i16;
1014                    self.buf_stereo_side[i] = (l - r) as i16;
1015                }
1016                self.silk_enc.stereo.side.resize(ds_len, 0);
1017                self.silk_enc
1018                    .stereo
1019                    .side
1020                    .copy_from_slice(&self.buf_stereo_side[..ds_len]);
1021                &self.buf_stereo_mid
1022            } else if mode == OpusMode::SilkOnly && self.sampling_rate > 16000 {
1023                if self.sampling_rate == 48000 {
1024                    // 48k -> 16k via the same direct FIR the Hybrid path uses. The
1025                    // old down2 + down2_3 two-stage chain ALIASES: a 1 kHz sine
1026                    // came out with a 7 kHz mirror at ~1/3 amplitude (spectrum-
1027                    // verified), wrecking every SILK-only encode from 48 kHz input.
1028                    let silk_frame_size = frame_size / 3;
1029                    self.buf_silk_input.resize(silk_frame_size, 0);
1030                    if let Some(r) = &mut self.down_fir_l {
1031                        r.process(&mut self.buf_silk_input, input_i16);
1032                    }
1033                    &self.buf_silk_input
1034                } else if self.sampling_rate == 24000 {
1035                    let silk_frame_size = frame_size * 2 / 3;
1036                    self.buf_silk_input.resize(silk_frame_size, 0);
1037                    if let Some(r) = &mut self.down_fir_l {
1038                        r.process(&mut self.buf_silk_input, input_i16);
1039                    }
1040                    &self.buf_silk_input
1041                } else {
1042                    input_i16
1043                }
1044            } else if mode == OpusMode::Hybrid && self.sampling_rate > 16000 {
1045                let silk_frame_size = if self.sampling_rate == 48000 {
1046                    frame_size / 3
1047                } else {
1048                    frame_size * 2 / 3
1049                };
1050                self.buf_silk_input.resize(silk_frame_size, 0);
1051                if let Some(r) = &mut self.down_fir_l {
1052                    r.process(&mut self.buf_silk_input, input_i16);
1053                }
1054                &self.buf_silk_input
1055            } else {
1056                input_i16
1057            };
1058
1059            drop(_prof_rs);
1060
1061            let mut pn_bytes = 0;
1062
1063            // The frames-per-second math below divides by silk_input.len(), which is
1064            // at the SILK-INTERNAL rate — so the rate here must be internal too.
1065            // Using the API rate at 48 kHz told SILK to target 3x the real budget
1066            // with a hard max_bits cap -> the gain loop crushed every frame to fit
1067            // -> near-silent output (only worked at 16 kHz API where they coincide).
1068            let silk_rate_for_calc = if mode == OpusMode::Hybrid {
1069                16000
1070            } else {
1071                self.sampling_rate.min(16000)
1072            };
1073            let silk_frame_len = silk_input.len();
1074
1075            let silk_bitrate = if mode == OpusMode::Hybrid {
1076                let frame_duration_ms = frame_size as i32 * 1000 / self.sampling_rate;
1077                let frame20ms = frame_duration_ms >= 20;
1078                compute_silk_rate_for_hybrid(self.bitrate_bps, curr_bw, frame20ms, !self.use_cbr)
1079            } else if self.use_cbr {
1080                (8i64 * (n_bytes - 1) as i64 * silk_rate_for_calc as i64 / silk_frame_len as i64)
1081                    as i32
1082            } else {
1083                // VBR: n_bytes is only the buffer cap; target the configured rate.
1084                self.bitrate_bps
1085            };
1086            let silk_max_bits = if mode == OpusMode::Hybrid {
1087                let total_max_bits = ((n_bytes - 1) * 8) as i32;
1088                if self.use_cbr {
1089                    let silk_bits = (silk_bitrate as i64 * silk_frame_len as i64
1090                        / silk_rate_for_calc as i64) as i32;
1091                    let other_bits = 0i32.max(total_max_bits - silk_bits);
1092                    0i32.max(total_max_bits - other_bits * 3 / 4)
1093                } else {
1094                    let frame_duration_ms = frame_size as i32 * 1000 / self.sampling_rate;
1095                    let frame20ms = frame_duration_ms >= 20;
1096                    let max_bit_rate = compute_silk_rate_for_hybrid(
1097                        total_max_bits * self.sampling_rate / frame_size as i32,
1098                        curr_bw,
1099                        frame20ms,
1100                        !self.use_cbr,
1101                    );
1102                    max_bit_rate * frame_size as i32 / self.sampling_rate
1103                }
1104            } else {
1105                ((n_bytes - 1) * 8) as i32
1106            };
1107            let silk_use_cbr = if mode == OpusMode::Hybrid && self.use_cbr {
1108                0
1109            } else if self.use_cbr {
1110                1
1111            } else {
1112                0
1113            };
1114            let ret = silk_encode(
1115                &mut self.silk_enc,
1116                silk_input,
1117                silk_input.len(),
1118                &mut self.rc,
1119                &mut pn_bytes,
1120                silk_bitrate,
1121                silk_max_bits,
1122                silk_use_cbr,
1123                1,
1124            );
1125            if ret != 0 {
1126                return Err("SILK encoding failed");
1127            }
1128        }
1129
1130        // The hybrid redundancy flag is only present when >=37 bits remain
1131        // (opus_encoder.c: ec_tell+17+20 <= 8*(max_data_bytes-1)); the decoder
1132        // gates its read identically. Writing it unconditionally desynced every
1133        // frame where SILK left fewer than 37 bits (starved low-rate hybrid).
1134        if mode == OpusMode::Hybrid && self.rc.tell() + 37 <= ((n_bytes - 1) * 8) as i32 {
1135            self.rc.encode_bit_logp(false, 12); // redundancy = 0
1136        }
1137
1138        if mode == OpusMode::Hybrid {
1139            let nb_compr_bytes = (n_bytes - 1) as u32;
1140            self.rc.shrink(nb_compr_bytes);
1141        }
1142
1143        let silk_ret_bytes = if mode == OpusMode::SilkOnly {
1144            ((self.rc.tell() + 7) >> 3) as usize
1145        } else {
1146            0
1147        };
1148
1149        if mode == OpusMode::CeltOnly || mode == OpusMode::Hybrid {
1150            self.celt_enc.analysis = celt::AnalysisInfo {
1151                valid: analysis_info.valid,
1152                tonality: analysis_info.tonality,
1153                tonality_slope: analysis_info.tonality_slope,
1154                noisiness: analysis_info.noisiness,
1155                activity: analysis_info.activity,
1156                music_prob: analysis_info.music_prob,
1157                music_prob_min: analysis_info.music_prob_min,
1158                music_prob_max: analysis_info.music_prob_max,
1159                bandwidth: analysis_info.bandwidth,
1160                activity_probability: analysis_info.activity_probability,
1161                max_pitch_ratio: analysis_info.max_pitch_ratio,
1162                leak_boost: analysis_info.leak_boost,
1163            };
1164            self.celt_enc.complexity = self.complexity;
1165            self.celt_enc.lsb_depth = self.lsb_depth;
1166            let start_band = if mode == OpusMode::Hybrid { 17 } else { 0 };
1167            // CELT end band from the coded bandwidth (mirrors the decoder's
1168            // celt_endband_for_bandwidth): NB->13, MB/WB->17, SWB->19, FB->21.
1169            let end_band = match self.bandwidth {
1170                Bandwidth::Narrowband => 13,
1171                Bandwidth::Mediumband | Bandwidth::Wideband => 17,
1172                Bandwidth::Superwideband => 19,
1173                _ => 21,
1174            };
1175            let total_packet_bits = ((n_bytes - 1) * 8) as i32;
1176            // VBR: hand CELT the target in eighth-bits per frame; it picks the
1177            // frame's size (compute_vbr) and shrinks the range coder to it. The
1178            // hybrid target covers the whole packet (CELT adds back the SILK
1179            // bits via `target += tell`).
1180            self.celt_enc.vbr_rate = if self.use_cbr {
1181                0
1182            } else {
1183                let den = self.sampling_rate >> 3; // Fs >> BITRES
1184                ((self.bitrate_bps as i64 * frame_size as i64 + (den >> 1) as i64)
1185                    / den as i64) as i32
1186            };
1187
1188            let celt_input: &[f32] = if self.channels == 1 {
1189                input
1190            } else {
1191                let n = frame_size * self.channels;
1192                self.buf_celt_input.resize(n, 0.0);
1193                for i in 0..frame_size {
1194                    for ch in 0..self.channels {
1195                        self.buf_celt_input[ch * frame_size + i] = input[i * self.channels + ch];
1196                    }
1197                }
1198                &self.buf_celt_input
1199            };
1200
1201            if self.rc.tell() <= total_packet_bits {
1202                self.celt_enc.encode_with_budget(
1203                    celt_input,
1204                    frame_size,
1205                    &mut self.rc,
1206                    start_band,
1207                    end_band,
1208                    total_packet_bits,
1209                );
1210            }
1211        }
1212
1213        self.rc.done();
1214        self.range_final = self.rc.rng;
1215
1216        if mode == OpusMode::SilkOnly {
1217            let mut ret = silk_ret_bytes.min(self.rc.storage as usize);
1218            while ret > 2 && self.rc.buf[ret - 1] == 0 {
1219                ret -= 1;
1220            }
1221
1222            let target_total = if self.use_cbr {
1223                n_bytes.min(output.len())
1224            } else {
1225                (ret + 1).min(output.len())
1226            };
1227
1228            let silk_len = ret;
1229
1230            if !self.use_cbr || silk_len + 1 >= target_total {
1231                // VBR or payload fills the target: simple code 0 packet
1232                output[0] = toc;
1233                let copy_len = silk_len.min(target_total - 1);
1234                output[1..1 + copy_len].copy_from_slice(&self.rc.buf[..copy_len]);
1235                return Ok((copy_len + 1).min(output.len()));
1236            }
1237
1238            output[0] = toc | 0x03;
1239
1240            if silk_len + 2 >= target_total {
1241                output[1] = 0x01;
1242                let copy_len = (target_total - 2).min(silk_len);
1243                output[2..2 + copy_len].copy_from_slice(&self.rc.buf[..copy_len]);
1244                self.prev_enc_mode = Some(mode);
1245                return Ok(target_total.min(output.len()));
1246            }
1247
1248            let pad_amount = target_total - silk_len - 2;
1249            output[1] = 0x41;
1250
1251            let nb_255s = (pad_amount - 1) / 255;
1252            let mut ptr = 2;
1253            for _ in 0..nb_255s {
1254                output[ptr] = 255;
1255                ptr += 1;
1256            }
1257            output[ptr] = (pad_amount - 255 * nb_255s - 1) as u8;
1258            ptr += 1;
1259
1260            output[ptr..ptr + silk_len].copy_from_slice(&self.rc.buf[..silk_len]);
1261            ptr += silk_len;
1262
1263            let fill_end = target_total.min(output.len());
1264            for byte in output[ptr..fill_end].iter_mut() {
1265                *byte = 0;
1266            }
1267
1268            self.prev_enc_mode = Some(mode);
1269            return Ok(target_total.min(output.len()));
1270        }
1271
1272        // CBR: fixed payload. VBR (CELT/hybrid): the CELT layer shrank the coder
1273        // to this frame's chosen size — emit exactly that many payload bytes.
1274        let payload_len = if self.use_cbr {
1275            n_bytes - 1
1276        } else {
1277            (self.rc.storage as usize).min(n_bytes - 1)
1278        };
1279        output[1..1 + payload_len].copy_from_slice(&self.rc.buf[..payload_len]);
1280        self.prev_enc_mode = Some(mode);
1281        Ok(1 + payload_len)
1282    }
1283}
1284
1285pub struct OpusDecoder {
1286    celt_dec: CeltDecoder,
1287    silk_dec: silk::dec_api::SilkDecoder,
1288    sampling_rate: i32,
1289    channels: usize,
1290
1291    prev_mode: Option<OpusMode>,
1292    frame_size: usize,
1293
1294    bandwidth: Bandwidth,
1295
1296    stream_channels: usize,
1297
1298    silk_resampler: silk::resampler::SilkResampler,
1299    // Second resampler for the SILK stereo right channel (L uses silk_resampler).
1300    silk_resampler_r: silk::resampler::SilkResampler,
1301
1302    prev_internal_rate: i32,
1303
1304    pub hybrid_skip_celt: bool,
1305
1306    w_pcm_i16: Vec<i16>,
1307    w_silk_out: Vec<f32>,
1308    w_pcm_resampled: Vec<i16>,
1309    w_celt_planar: Vec<f32>,
1310    w_celt_out: Vec<f32>,
1311
1312    // SILK per-frame history: libopus prepends the previous frame's last two
1313    // decoded samples (`sStereo.sMid`) and feeds the resampler from offset 1, a
1314    // 1-internal-sample delay line. Replicated here so our SILK output aligns
1315    // with the reference across every bandwidth (was leading by 1 internal
1316    // sample = 3/4/6 output samples at WB/MB/NB).
1317    silk_s_mid: [i16; 2],
1318
1319    // Range decoder final `rng` from the last decoded frame (conformance/desync
1320    // diagnostic: compare against the encoder's stored final range).
1321    pub last_range: u32,
1322
1323    // Auxiliary decoder for packets whose channel count differs from ours
1324    // (a stream may switch between mono and stereo). It decodes at the packet's
1325    // native channel count; we then up/downmix to our output count. Persistent
1326    // so the "other" channel mode keeps its own inter-frame state.
1327    aux: Option<Box<OpusDecoder>>,
1328    // Set when a packet was just decoded by the aux (a mono packet in a stereo
1329    // stream); triggers seeding the primary CELT decoder's overlap/energy state
1330    // from the aux at the next primary (stereo) CELT/Hybrid packet, so the MDCT
1331    // overlap-add is continuous across the mono->stereo switch.
1332    prev_used_aux: bool,
1333    // libopus st->prev_redundancy: the previous frame carried a SILK->CELT
1334    // redundant frame (redundancy && !celt_to_silk). Suppresses the CELT reset on
1335    // the following mode change (the redundant frame already primed CELT state).
1336    prev_redundancy: bool,
1337}
1338
1339impl OpusDecoder {
1340    pub fn new(sampling_rate: i32, channels: usize) -> Result<Self, &'static str> {
1341        if ![8000, 12000, 16000, 24000, 48000].contains(&sampling_rate) {
1342            return Err("Invalid sampling rate");
1343        }
1344        if ![1, 2].contains(&channels) {
1345            return Err("Invalid number of channels");
1346        }
1347
1348        let mode = modes::default_mode();
1349        let celt_dec = CeltDecoder::new(mode, channels);
1350
1351        let mut silk_dec = silk::dec_api::SilkDecoder::new();
1352        silk_dec.init(sampling_rate.min(16000), channels as i32);
1353        silk_dec.channel_state[0].fs_api_hz = sampling_rate;
1354
1355        Ok(Self {
1356            celt_dec,
1357            silk_dec,
1358            sampling_rate,
1359            channels,
1360            prev_mode: None,
1361            frame_size: 0,
1362            bandwidth: Bandwidth::Auto,
1363            stream_channels: channels,
1364            silk_resampler: silk::resampler::SilkResampler::default(),
1365            silk_resampler_r: silk::resampler::SilkResampler::default(),
1366            prev_internal_rate: 0,
1367            hybrid_skip_celt: false,
1368
1369            // SILK internal scratch: max frame is 60 ms at the 16 kHz WB internal
1370            // rate (960 samples/ch), i.e. 1920 stereo. Sized like the sibling
1371            // buffers below for headroom — the old fixed 640 overflowed on any
1372            // 60 ms SILK frame (panic decoding valid streams).
1373            w_pcm_i16: vec![0i16; 5760 * channels],
1374
1375            w_silk_out: vec![0.0f32; 5760 * channels],
1376            w_pcm_resampled: vec![0i16; 5760 * channels],
1377            w_celt_planar: vec![0.0f32; 5760 * channels],
1378            w_celt_out: vec![0.0f32; 5760 * channels],
1379            silk_s_mid: [0; 2],
1380            last_range: 0,
1381            aux: None,
1382            prev_used_aux: false,
1383            prev_redundancy: false,
1384        })
1385    }
1386
1387    /// Packet-loss concealment for a lost frame (empty/None packet). Runs the
1388    /// SILK PLC (LTP+LPC extrapolation) for the last-known SILK/hybrid mode and
1389    /// resamples to the output rate. CELT-only loss has no CELT PLC yet, so it
1390    /// yields silence (a documented Tier-1 follow-up); the SILK path covers the
1391    /// dominant VoIP case. Mono conceal is duplicated to both channels on a
1392    /// stereo output.
1393    fn decode_plc(
1394        &mut self,
1395        frame_size: usize,
1396        output: &mut [f32],
1397    ) -> Result<usize, &'static str> {
1398        let out_samples = frame_size * self.channels;
1399        for v in output.iter_mut().take(out_samples) {
1400            *v = 0.0;
1401        }
1402        let mode = self.prev_mode.unwrap_or(OpusMode::SilkOnly);
1403        if mode == OpusMode::CeltOnly {
1404            // CELT packet-loss concealment (noise-based celt_decode_lost): real
1405            // attenuating audio instead of silence.
1406            self.celt_dec.conceal_lost(frame_size, output);
1407            self.prev_mode = Some(mode);
1408            return Ok(frame_size);
1409        }
1410
1411        let frame_ms = (frame_size as i32 * 1000 / self.sampling_rate).max(1);
1412        let internal_rate = if mode == OpusMode::Hybrid {
1413            16000
1414        } else {
1415            match self.bandwidth {
1416                Bandwidth::Narrowband => 8000,
1417                Bandwidth::Mediumband => 12000,
1418                _ => 16000,
1419            }
1420        };
1421        if self.sampling_rate != internal_rate && internal_rate != self.prev_internal_rate {
1422            self.silk_resampler.init(internal_rate, self.sampling_rate);
1423            self.prev_internal_rate = internal_rate;
1424        }
1425        let n_silk = match frame_ms {
1426            40 => 2,
1427            60 => 3,
1428            _ => 1,
1429        };
1430        let internal_frame = (frame_ms * internal_rate / 1000) as usize;
1431        let internal_sub = internal_frame / n_silk.max(1);
1432        let ratio = self.sampling_rate as f64 / internal_rate as f64;
1433        // Conceal mono only (the SILK low band); stereo output duplicates it.
1434        self.silk_dec.produce_lr = false;
1435        self.silk_dec.n_channels_internal = 1;
1436
1437        let mut off = 0usize; // output samples/ch written so far
1438        for sf in 0..n_silk {
1439            let mut rc = RangeCoder::new_decoder(&[]);
1440            let n16 = internal_sub;
1441            if n16 + 2 > self.w_pcm_i16.len() {
1442                return Err("opus PLC: frame exceeds buffer");
1443            }
1444            self.w_pcm_i16[0] = self.silk_s_mid[0];
1445            self.w_pcm_i16[1] = self.silk_s_mid[1];
1446            let ret = self.silk_dec.decode(
1447                &mut rc,
1448                &mut self.w_pcm_i16[2..n16 + 2],
1449                silk::decode_frame::FLAG_PACKET_LOST,
1450                sf == 0,
1451                frame_ms,
1452                internal_rate,
1453            );
1454            if ret < 0 {
1455                return Err("SILK PLC failed");
1456            }
1457            let dec = ret as usize;
1458            if dec >= 2 {
1459                self.silk_s_mid[0] = self.w_pcm_i16[dec];
1460                self.silk_s_mid[1] = self.w_pcm_i16[dec + 1];
1461            }
1462            let base = off * self.channels;
1463            let out_len = if self.sampling_rate == internal_rate {
1464                for i in 0..dec {
1465                    let v = self.w_pcm_i16[1 + i] as f32 / 32768.0;
1466                    for ch in 0..self.channels {
1467                        let idx = base + i * self.channels + ch;
1468                        if idx < output.len() {
1469                            output[idx] = v;
1470                        }
1471                    }
1472                }
1473                dec
1474            } else {
1475                let out_len = (dec as f64 * ratio) as usize;
1476                let src: Vec<i16> = self.w_pcm_i16[1..1 + dec].to_vec();
1477                self.silk_resampler
1478                    .process(&mut self.w_pcm_resampled[..out_len], &src, dec as i32);
1479                for i in 0..out_len {
1480                    let v = self.w_pcm_resampled[i] as f32 / 32768.0;
1481                    for ch in 0..self.channels {
1482                        let idx = base + i * self.channels + ch;
1483                        if idx < output.len() {
1484                            output[idx] = v;
1485                        }
1486                    }
1487                }
1488                out_len
1489            };
1490            off += out_len;
1491        }
1492        self.prev_mode = Some(mode);
1493        Ok(frame_size)
1494    }
1495
1496    /// Forward-error-correction decode: reconstruct a LOST frame from the LBRR
1497    /// (low-bitrate redundancy) embedded in the NEXT received `packet`. Drives
1498    /// the SILK decoder in FLAG_DECODE_LBRR mode, which self-selects: it decodes
1499    /// the redundant frame when the packet carries LBRR for it, and falls back
1500    /// to PLC extrapolation when it doesn't. CELT-only or multi-frame packets
1501    /// fall back to plain PLC (no SILK LBRR to recover). After this call the
1502    /// caller decodes `packet` normally for the following frame.
1503    pub fn decode_fec(
1504        &mut self,
1505        packet: &[u8],
1506        frame_size: usize,
1507        output: &mut [f32],
1508    ) -> Result<usize, &'static str> {
1509        if packet.is_empty() {
1510            return self.decode_plc(frame_size, output);
1511        }
1512        let toc = packet[0];
1513        let mode = mode_from_toc(toc);
1514        // FEC only lives in SILK/hybrid low band; code-0 (single frame) only.
1515        if mode == OpusMode::CeltOnly || (toc & 0x03) != 0 {
1516            return self.decode_plc(frame_size, output);
1517        }
1518        let bandwidth = bandwidth_from_toc(toc);
1519        let payload = &packet[1..];
1520
1521        let out_samples = frame_size * self.channels;
1522        for v in output.iter_mut().take(out_samples) {
1523            *v = 0.0;
1524        }
1525        let frame_ms = (frame_size as i32 * 1000 / self.sampling_rate).max(1);
1526        let internal_rate = if mode == OpusMode::Hybrid {
1527            16000
1528        } else {
1529            match bandwidth {
1530                Bandwidth::Narrowband => 8000,
1531                Bandwidth::Mediumband => 12000,
1532                _ => 16000,
1533            }
1534        };
1535        if self.sampling_rate != internal_rate && internal_rate != self.prev_internal_rate {
1536            self.silk_resampler.init(internal_rate, self.sampling_rate);
1537            self.prev_internal_rate = internal_rate;
1538        }
1539        let internal_frame = (frame_ms * internal_rate / 1000) as usize;
1540        let ratio = self.sampling_rate as f64 / internal_rate as f64;
1541        self.silk_dec.produce_lr = false;
1542        self.silk_dec.n_channels_internal = 1;
1543
1544        let mut rc = RangeCoder::new_decoder(payload);
1545        let n16 = internal_frame;
1546        if n16 + 2 > self.w_pcm_i16.len() {
1547            return Err("opus FEC: frame exceeds buffer");
1548        }
1549        self.w_pcm_i16[0] = self.silk_s_mid[0];
1550        self.w_pcm_i16[1] = self.silk_s_mid[1];
1551        let ret = self.silk_dec.decode(
1552            &mut rc,
1553            &mut self.w_pcm_i16[2..n16 + 2],
1554            silk::decode_frame::FLAG_DECODE_LBRR,
1555            true,
1556            frame_ms,
1557            internal_rate,
1558        );
1559        if ret < 0 {
1560            return Err("SILK FEC failed");
1561        }
1562        let dec = ret as usize;
1563        if dec >= 2 {
1564            self.silk_s_mid[0] = self.w_pcm_i16[dec];
1565            self.silk_s_mid[1] = self.w_pcm_i16[dec + 1];
1566        }
1567        if self.sampling_rate == internal_rate {
1568            for i in 0..dec {
1569                let v = self.w_pcm_i16[1 + i] as f32 / 32768.0;
1570                for ch in 0..self.channels {
1571                    let idx = i * self.channels + ch;
1572                    if idx < output.len() {
1573                        output[idx] = v;
1574                    }
1575                }
1576            }
1577        } else {
1578            let out_len = (dec as f64 * ratio) as usize;
1579            let src: Vec<i16> = self.w_pcm_i16[1..1 + dec].to_vec();
1580            self.silk_resampler
1581                .process(&mut self.w_pcm_resampled[..out_len], &src, dec as i32);
1582            for i in 0..out_len {
1583                let v = self.w_pcm_resampled[i] as f32 / 32768.0;
1584                for ch in 0..self.channels {
1585                    let idx = i * self.channels + ch;
1586                    if idx < output.len() {
1587                        output[idx] = v;
1588                    }
1589                }
1590            }
1591        }
1592        self.prev_mode = Some(mode);
1593        Ok(frame_size)
1594    }
1595
1596    pub fn decode(
1597        &mut self,
1598        input: &[u8],
1599        frame_size: usize,
1600        output: &mut [f32],
1601    ) -> Result<usize, &'static str> {
1602        // Lost packet (data==NULL / empty) -> packet-loss concealment.
1603        if input.is_empty() {
1604            return self.decode_plc(frame_size, output);
1605        }
1606
1607        let toc = input[0];
1608        let mode = mode_from_toc(toc);
1609        let packet_channels = channels_from_toc(toc);
1610        let bandwidth = bandwidth_from_toc(toc);
1611        let frame_duration_ms = frame_duration_ms_from_toc(toc);
1612
1613        // A mono SILK packet inside a stereo stream is decoded through the PRIMARY
1614        // decoder (unified path), not a separate aux — the aux's SILK/resampler
1615        // state is blind to the interleaved stereo packets, so its state is stale
1616        // at every mono<->stereo switch. libopus keeps ONE decoder whose channel-0
1617        // resampler and stereo state run continuously across the switches.
1618        // A mono packet of ANY mode in a stereo stream decodes through the PRIMARY
1619        // (unified path) so inter-frame state stays one continuous chain across
1620        // mono<->stereo switches — SILK resampler/stereo state; CELT (and the
1621        // redundant/silence transition frames) via stream_channels=1 (C=1/CC=2) —
1622        // matching libopus's single decoder.
1623        let mono_in_stereo = packet_channels == 1 && self.channels == 2;
1624
1625        if packet_channels != self.channels && !mono_in_stereo {
1626            // The packet's channel count differs from ours (a stream can switch
1627            // between mono and stereo). Decode it at its native channel count in
1628            // a persistent auxiliary decoder, then render to our output count:
1629            // mono->stereo duplicates, stereo->mono averages the two channels.
1630            if self
1631                .aux
1632                .as_ref()
1633                .map(|a| a.channels != packet_channels)
1634                .unwrap_or(true)
1635            {
1636                self.aux = Some(Box::new(OpusDecoder::new(
1637                    self.sampling_rate,
1638                    packet_channels,
1639                )?));
1640            }
1641            // Reverse of the mono->stereo seed: on a stereo->mono switch, seed the
1642            // aux (mono) CELT decoder from the primary (stereo channel 0) so its
1643            // MDCT-overlap/energy state is continuous with the preceding stereo
1644            // packets (the primary was the continuous decoder during them).
1645            if !self.prev_used_aux
1646                && packet_channels == 1
1647                && self.channels == 2
1648                && (mode == OpusMode::CeltOnly || mode == OpusMode::Hybrid)
1649            {
1650                let (aux_opt, primary) = (&mut self.aux, &self.celt_dec);
1651                if let Some(aux) = aux_opt.as_mut() {
1652                    aux.celt_dec.seed_from(primary);
1653                }
1654            }
1655            let aux = self.aux.as_mut().unwrap();
1656            let mut buf = vec![0.0f32; frame_size * packet_channels];
1657            let n = aux.decode(input, frame_size, &mut buf)?;
1658            self.last_range = aux.last_range;
1659            if packet_channels == 1 && self.channels == 2 {
1660                for i in 0..n {
1661                    let v = buf[i];
1662                    output[2 * i] = v;
1663                    output[2 * i + 1] = v;
1664                }
1665            } else if packet_channels == 2 && self.channels == 1 {
1666                for i in 0..n {
1667                    output[i] = 0.5 * (buf[2 * i] + buf[2 * i + 1]);
1668                }
1669            } else {
1670                let m = (n * self.channels).min(output.len()).min(buf.len());
1671                output[..m].copy_from_slice(&buf[..m]);
1672            }
1673            self.prev_mode = Some(mode);
1674            self.prev_used_aux = true;
1675            return Ok(n);
1676        }
1677
1678        // First primary (native-channel) packet after a run of aux (mono-in-stereo)
1679        // packets: seed the primary CELT decoder's inter-frame state from the aux
1680        // so the mono->stereo MDCT overlap-add is continuous (matches libopus's
1681        // single continuous decoder). SILK carries its own state through the
1682        // primary already; this is for the CELT/Hybrid high band.
1683        if self.prev_used_aux {
1684            self.prev_used_aux = false;
1685            if (mode == OpusMode::CeltOnly || mode == OpusMode::Hybrid) && self.channels == 2 {
1686                if let Some(aux) = self.aux.as_ref() {
1687                    self.celt_dec.seed_from(&aux.celt_dec);
1688                }
1689            }
1690        }
1691
1692        let code = toc & 0x03;
1693        let frame_count: usize;
1694        let frame_payloads: Vec<&[u8]>;
1695
1696        match code {
1697            0 => {
1698                frame_count = 1;
1699                frame_payloads = vec![&input[1..]];
1700            }
1701            1 => {
1702                frame_count = 2;
1703                let half = (input.len() - 1) / 2;
1704                if half == 0 {
1705                    return Err("Code 1: empty frame");
1706                }
1707                frame_payloads = vec![&input[1..1 + half], &input[1 + half..]];
1708            }
1709            2 => {
1710                frame_count = 2;
1711                let data = &input[1..];
1712                if data.is_empty() {
1713                    return Err("Code 2 packet has no data");
1714                }
1715                let (first_len, header_size) = read_opus_frame_len(data, 0)?;
1716                if header_size + first_len > data.len() {
1717                    return Err("Code 2: first frame size exceeds packet");
1718                }
1719                frame_payloads = vec![
1720                    &data[header_size..header_size + first_len],
1721                    &data[header_size + first_len..],
1722                ];
1723            }
1724            3 => {
1725                // RFC 6716 §3.2.5. Frame-count byte: bit 7 = VBR flag, bit 6 =
1726                // padding flag, bits 5..0 = frame count M. VBR and padding are
1727                // independent; the earlier code conflated them (and used a
1728                // non-standard length coding), which mis-parsed CBR and padded
1729                // packets — exactly what the RFC test vectors exercise.
1730                if input.len() < 2 {
1731                    return Err("Code 3 packet too short");
1732                }
1733                let count_byte = input[1];
1734                let m = (count_byte & 0x3F) as usize;
1735                if m < 1 || m > 48 {
1736                    return Err("Code 3: invalid frame count");
1737                }
1738                // libopus opus.c opus_packet_parse_impl (code 3):
1739                //   if (count <= 0 || framesize*(opus_int32)count > 5760)
1740                //      return OPUS_INVALID_PACKET;
1741                // (framesize at 48 kHz; 5760 = 120 ms, the RFC 6716 packet cap.)
1742                // A hostile frame count past this cap would otherwise shrink our
1743                // per-frame size below the redundancy-fade windows further down.
1744                if m as i32 * repacketizer::samples_per_frame(toc, 48000) > 5760 {
1745                    return Err("Code 3: packet duration exceeds 120 ms");
1746                }
1747                frame_count = m;
1748                let vbr = (count_byte & 0x80) != 0;
1749                let padding = (count_byte & 0x40) != 0;
1750
1751                // Padding length indicator bytes follow the count byte; the
1752                // padding data itself sits at the end of the packet.
1753                let mut ptr = 2usize;
1754                let mut pad_len = 0usize;
1755                if padding {
1756                    loop {
1757                        let p = *input.get(ptr).ok_or("Code 3: padding overflow")? as usize;
1758                        ptr += 1;
1759                        if p == 255 {
1760                            pad_len += 254;
1761                        } else {
1762                            pad_len += p;
1763                            break;
1764                        }
1765                    }
1766                }
1767                let end = input
1768                    .len()
1769                    .checked_sub(pad_len)
1770                    .ok_or("Code 3: padding exceeds packet")?;
1771                if ptr > end {
1772                    return Err("Code 3: padding exceeds packet");
1773                }
1774                // Frame-data region, with the length headers (VBR) at its front
1775                // and the trailing padding already excluded.
1776                let region = &input[ptr..end];
1777
1778                if vbr {
1779                    // M-1 explicit frame lengths, contiguous, then the frame
1780                    // data; the last frame is the remainder.
1781                    let mut lens = Vec::with_capacity(m.saturating_sub(1));
1782                    let mut hp = 0usize;
1783                    for _ in 0..m - 1 {
1784                        let (l, nb) = read_opus_frame_len(region, hp)?;
1785                        hp += nb;
1786                        lens.push(l);
1787                    }
1788                    let mut payloads = Vec::with_capacity(m);
1789                    let mut fp = hp;
1790                    for &l in &lens {
1791                        if fp + l > region.len() {
1792                            return Err("Code 3 VBR: frame length exceeds packet");
1793                        }
1794                        payloads.push(&region[fp..fp + l]);
1795                        fp += l;
1796                    }
1797                    if fp > region.len() {
1798                        return Err("Code 3 VBR: no data for last frame");
1799                    }
1800                    payloads.push(&region[fp..]);
1801                    frame_payloads = payloads;
1802                } else {
1803                    // CBR: the region splits into M equal frames (possibly all
1804                    // empty, e.g. DTX).
1805                    if region.len() % m != 0 {
1806                        return Err("Code 3 CBR: frame data not divisible by frame count");
1807                    }
1808                    let frame_len = region.len() / m;
1809                    frame_payloads = (0..m)
1810                        .map(|i| &region[i * frame_len..(i + 1) * frame_len])
1811                        .collect();
1812                }
1813            }
1814            _ => unreachable!(),
1815        }
1816
1817        // libopus opus_decoder.c opus_decode_native:
1818        //   if (count*packet_frame_size > frame_size)
1819        //      return OPUS_BUFFER_TOO_SMALL;
1820        // The packet's own TOC duration must fit the caller's frame_size. We split
1821        // the caller's buffer as sub_frame_size = frame_size / frame_count, so a
1822        // malformed multi-frame packet (large frame count vs. a small caller
1823        // buffer) would otherwise make sub_frame_size smaller than the 2.5/5 ms
1824        // redundancy-fade region — the fuzzer-found out-of-bounds/underflow panics
1825        // in redundancy_fade_start/redundancy_fade_end. C rejects such packets
1826        // here; so do we.
1827        let packet_frame_samples =
1828            repacketizer::samples_per_frame(toc, self.sampling_rate) as usize;
1829        if frame_count * packet_frame_samples > frame_size {
1830            return Err("Output buffer too small");
1831        }
1832
1833        self.frame_size = frame_size;
1834        self.bandwidth = bandwidth;
1835        self.stream_channels = packet_channels;
1836
1837        let sub_frame_size = frame_size / frame_count;
1838        let sub_output_len = sub_frame_size * self.channels;
1839
1840        match mode {
1841            OpusMode::SilkOnly => {
1842                let internal_sample_rate = match bandwidth {
1843                    Bandwidth::Narrowband => 8000,
1844                    Bandwidth::Mediumband => 12000,
1845                    Bandwidth::Wideband => 16000,
1846                    _ => 16000,
1847                };
1848                let internal_frame_size =
1849                    (frame_duration_ms * internal_sample_rate / 1000) as usize;
1850
1851                if self.sampling_rate != internal_sample_rate
1852                    && internal_sample_rate != self.prev_internal_rate
1853                {
1854                    self.silk_resampler
1855                        .init(internal_sample_rate, self.sampling_rate);
1856                    self.silk_resampler_r
1857                        .init(internal_sample_rate, self.sampling_rate);
1858                    self.prev_internal_rate = internal_sample_rate;
1859                }
1860
1861                // Pure-SILK stereo (both stream and output are 2ch): reconstruct
1862                // true L/R via SILK MS->LR instead of duplicating the mono mid.
1863                let silk_lr = self.channels == 2 && packet_channels == 2;
1864                self.silk_dec.produce_lr = silk_lr;
1865
1866                // Per-packet internal channel switch (libopus dec_API.c:119-166).
1867                let prev_internal_ch = self.silk_dec.n_channels_internal;
1868                if packet_channels as i32 > prev_internal_ch {
1869                    // mono -> stereo: reset the side channel decoder.
1870                    silk::init_decoder::silk_init_decoder(
1871                        &mut self.silk_dec.channel_state[1],
1872                    );
1873                }
1874                if self.channels == 2 && packet_channels == 2 && prev_internal_ch == 1 {
1875                    // Switching to stereo: clear stereo prediction/side history and
1876                    // seed the right-channel resampler from the (continuous) left.
1877                    self.silk_dec.s_stereo_pred_prev_q13 = [0; 2];
1878                    self.silk_dec.s_stereo_side = [0; 2];
1879                    self.silk_resampler_r = self.silk_resampler.clone();
1880                }
1881                self.silk_dec.n_channels_internal = packet_channels as i32;
1882
1883                // A 40/60 ms Opus frame carries 2/3 internal 20 ms SILK frames;
1884                // 10/20 ms carry one. libopus calls silk_Decode once per internal
1885                // frame (continuing the same range coder within the payload). We
1886                // must too — decoding only the first internal frame leaves the
1887                // rest of a 40/60 ms packet silent (the "collapse" bug).
1888                let n_silk = match frame_duration_ms {
1889                    40 => 2,
1890                    60 => 3,
1891                    _ => 1,
1892                };
1893                let internal_sub_frame_size = internal_frame_size / n_silk;
1894                let ratio = self.sampling_rate as f64 / internal_sample_rate as f64;
1895                // Per-FRAME previous mode (libopus updates prev_mode per frame; for
1896                // payloads after the first, the previous frame is this same packet).
1897                let mut prev_mode_frame = self.prev_mode;
1898
1899                for (fi, payload) in frame_payloads.iter().enumerate() {
1900                    let mut rc = RangeCoder::new_decoder(payload);
1901                    let pcm_i16_len = internal_sub_frame_size * self.channels;
1902                    // A malformed packet can imply a frame larger than our scratch
1903                    // buffer; reject it gracefully instead of slicing out of bounds
1904                    // (a decode-path DoS on attacker-controlled input).
1905                    if pcm_i16_len + 2 > self.w_pcm_i16.len() {
1906                        return Err("opus: SILK frame size exceeds buffer");
1907                    }
1908                    let out_start = fi * sub_output_len;
1909                    let mut silk_off = 0usize; // output samples/ch within this Opus frame
1910
1911                    for sf in 0..n_silk {
1912                        let s_mid = self.silk_s_mid;
1913                        let ret = {
1914                            let (silk_dec, pcm_i16) = (&mut self.silk_dec, &mut self.w_pcm_i16);
1915                            // Prepend the previous frame's last two samples (sMid) at
1916                            // [0..2] and decode at offset 2, matching libopus's
1917                            // samplesOut1_tmp[n][2] layout.
1918                            pcm_i16[0] = s_mid[0];
1919                            pcm_i16[1] = s_mid[1];
1920                            silk_dec.decode(
1921                                &mut rc,
1922                                &mut pcm_i16[2..pcm_i16_len + 2],
1923                                silk::decode_frame::FLAG_DECODE_NORMAL,
1924                                sf == 0,
1925                                frame_duration_ms,
1926                                internal_sample_rate,
1927                            )
1928                        };
1929
1930                        if ret < 0 {
1931                            return Err("SILK decoding failed");
1932                        }
1933
1934                        let decoded_samples = ret as usize;
1935                        // Carry the last two decoded samples as next frame's sMid.
1936                        if decoded_samples >= 2 {
1937                            self.silk_s_mid[0] = self.w_pcm_i16[decoded_samples];
1938                            self.silk_s_mid[1] = self.w_pcm_i16[decoded_samples + 1];
1939                        }
1940                        let base = out_start + silk_off * self.channels;
1941
1942                        // Stereo SILK: L in silk_dec.l_out, R in silk_dec.r_out,
1943                        // both already in the 1-sample-delay-line layout. Resample
1944                        // each channel through its own resampler.
1945                        let out_len = if silk_lr {
1946                            if self.sampling_rate == internal_sample_rate {
1947                                for i in 0..decoded_samples {
1948                                    let l = self.silk_dec.l_out[i] as f32 / 32768.0;
1949                                    let r = self.silk_dec.r_out[i] as f32 / 32768.0;
1950                                    let idx = base + i * 2;
1951                                    if idx + 1 < output.len() {
1952                                        output[idx] = l;
1953                                        output[idx + 1] = r;
1954                                    }
1955                                }
1956                                decoded_samples
1957                            } else {
1958                                let out_len = (decoded_samples as f64 * ratio) as usize;
1959                                // Left
1960                                self.silk_resampler.process(
1961                                    &mut self.w_pcm_resampled[..out_len],
1962                                    &self.silk_dec.l_out[..decoded_samples],
1963                                    decoded_samples as i32,
1964                                );
1965                                for i in 0..out_len {
1966                                    let idx = base + i * 2;
1967                                    if idx < output.len() {
1968                                        output[idx] = self.w_pcm_resampled[i] as f32 / 32768.0;
1969                                    }
1970                                }
1971                                // Right (reuse the scratch)
1972                                self.silk_resampler_r.process(
1973                                    &mut self.w_pcm_resampled[..out_len],
1974                                    &self.silk_dec.r_out[..decoded_samples],
1975                                    decoded_samples as i32,
1976                                );
1977                                for i in 0..out_len {
1978                                    let idx = base + i * 2 + 1;
1979                                    if idx < output.len() {
1980                                        output[idx] = self.w_pcm_resampled[i] as f32 / 32768.0;
1981                                    }
1982                                }
1983                                out_len
1984                            }
1985                        } else if self.sampling_rate == internal_sample_rate {
1986                            let frames = decoded_samples;
1987                            for i in 0..frames {
1988                                let v = self.w_pcm_i16[1 + i] as f32 / 32768.0;
1989                                for ch in 0..self.channels {
1990                                    let idx = base + i * self.channels + ch;
1991                                    if idx < output.len() {
1992                                        output[idx] = v;
1993                                    }
1994                                }
1995                            }
1996                            frames
1997                        } else {
1998                            let out_len = (decoded_samples as f64 * ratio) as usize;
1999                            debug_assert!(out_len <= self.w_pcm_resampled.len());
2000                            {
2001                                let (silk_res, pcm_i16, pcm_out) = (
2002                                    &mut self.silk_resampler,
2003                                    &self.w_pcm_i16,
2004                                    &mut self.w_pcm_resampled,
2005                                );
2006                                silk_res.process(
2007                                    &mut pcm_out[..out_len],
2008                                    &pcm_i16[1..1 + decoded_samples],
2009                                    decoded_samples as i32,
2010                                );
2011                            }
2012                            for i in 0..out_len {
2013                                let v = self.w_pcm_resampled[i] as f32 / 32768.0;
2014                                for ch in 0..self.channels {
2015                                    let idx = base + i * self.channels + ch;
2016                                    if idx < output.len() {
2017                                        output[idx] = v;
2018                                    }
2019                                }
2020                            }
2021                            // Stereo output, mono packet: also run the mono signal
2022                            // through the RIGHT-channel resampler so its state stays
2023                            // continuous for the next stereo packet (libopus
2024                            // dec_API.c:351-355). Its output overwrites channel 1,
2025                            // which is numerically ~identical to the left here.
2026                            if self.channels == 2 {
2027                                self.silk_resampler_r.process(
2028                                    &mut self.w_pcm_resampled[..out_len],
2029                                    &self.w_pcm_i16[1..1 + decoded_samples],
2030                                    decoded_samples as i32,
2031                                );
2032                                for i in 0..out_len {
2033                                    let idx = base + i * 2 + 1;
2034                                    if idx < output.len() {
2035                                        output[idx] = self.w_pcm_resampled[i] as f32 / 32768.0;
2036                                    }
2037                                }
2038                            }
2039                            out_len
2040                        };
2041                        silk_off += out_len;
2042                    }
2043
2044                    // --- Opus redundancy layer (opus_decoder.c:420-580) ---
2045                    // A SILK-only frame carries IMPLICIT CELT redundancy: if >= 17
2046                    // bits remain after SILK, the trailing bytes ARE a 5 ms CELT
2047                    // frame (no flag) used to smooth mode/bandwidth transitions.
2048                    let mut redundant_rng = 0u32;
2049                    let mut redundancy = false;
2050                    let mut celt_to_silk = false;
2051                    let plen = payload.len();
2052                    let f5 = (self.sampling_rate / 200) as usize;
2053                    let f2_5 = f5 / 2;
2054                    let red_end_band = celt_endband_for_bandwidth(bandwidth);
2055                    let mut red_buf = [0.0f32; 480]; // F5 * <=2ch, planar
2056                    let mut red_bytes = 0usize;
2057                    if self.sampling_rate == 48000 && rc.tell() + 17 <= (plen as i32) * 8 {
2058                        redundancy = true;
2059                        celt_to_silk = rc.decode_bit_logp(1);
2060                        red_bytes = plen - (((rc.tell() + 7) >> 3) as usize);
2061                        if red_bytes < 2 || red_bytes >= plen {
2062                            redundancy = false;
2063                            red_bytes = 0;
2064                        }
2065                    }
2066                    // CELT->SILK: the redundant frame continues the prior CELT
2067                    // state (a fade-out of the previous CELT mode). Decode BEFORE
2068                    // the hybrid->SILK silence frame to keep libopus state order.
2069                    if redundancy && celt_to_silk {
2070                        redundant_rng = self.decode_redundant_celt(
2071                            &payload[plen - red_bytes..],
2072                            false,
2073                            packet_channels,
2074                            red_end_band,
2075                            &mut red_buf[..f5 * self.channels],
2076                        );
2077                    }
2078                    // Hybrid->SILK transition: let the CELT MDCT fade out by
2079                    // decoding a 2-byte silence frame; its 2.5 ms overlap tail is
2080                    // ADDED to the output (libopus decodes it into pcm before the
2081                    // SILK sum).
2082                    if self.sampling_rate == 48000
2083                        && prev_mode_frame == Some(OpusMode::Hybrid)
2084                        && !(redundancy && celt_to_silk && self.prev_redundancy)
2085                    {
2086                        let silence = [0xFFu8, 0xFF];
2087                        let mut sil_buf = [0.0f32; 240]; // F2_5 * <=2ch, planar
2088                        self.celt_dec.set_stream_channels(packet_channels);
2089                        let mut src = RangeCoder::new_decoder(&silence);
2090                        self.celt_dec.decode_from_range_coder_with_band_range(
2091                            &mut src,
2092                            16,
2093                            f2_5,
2094                            &mut sil_buf[..f2_5 * self.channels],
2095                            0,
2096                            red_end_band,
2097                        );
2098                        let region = &mut output[out_start..out_start + sub_output_len];
2099                        for i in 0..f2_5 {
2100                            for c in 0..self.channels {
2101                                region[i * self.channels + c] += sil_buf[c * f2_5 + i];
2102                            }
2103                        }
2104                    }
2105                    // SILK->CELT: reset, then decode — this PRIMES the CELT state
2106                    // for the upcoming CELT-mode frames (which is why the next mode
2107                    // change skips its reset when prev_redundancy is set).
2108                    if redundancy && !celt_to_silk {
2109                        redundant_rng = self.decode_redundant_celt(
2110                            &payload[plen - red_bytes..],
2111                            true,
2112                            packet_channels,
2113                            red_end_band,
2114                            &mut red_buf[..f5 * self.channels],
2115                        );
2116                    }
2117                    if redundancy {
2118                        let window = modes::default_mode().window;
2119                        let region = &mut output[out_start..out_start + sub_output_len];
2120                        if celt_to_silk {
2121                            redundancy_fade_start(
2122                                region,
2123                                &red_buf,
2124                                f5,
2125                                f2_5,
2126                                self.channels,
2127                                window,
2128                            );
2129                        } else {
2130                            redundancy_fade_end(
2131                                region,
2132                                sub_frame_size,
2133                                &red_buf,
2134                                f5,
2135                                f2_5,
2136                                self.channels,
2137                                window,
2138                            );
2139                        }
2140                    }
2141                    self.prev_redundancy = redundancy && !celt_to_silk;
2142                    prev_mode_frame = Some(OpusMode::SilkOnly);
2143                    self.last_range = rc.rng ^ redundant_rng;
2144                }
2145                self.prev_mode = Some(OpusMode::SilkOnly);
2146                Ok(frame_size)
2147            }
2148
2149            OpusMode::CeltOnly => {
2150                let celt_end_band = self.celt_end_band_from_toc(toc);
2151                // libopus opus_decoder.c:515 — discard CELT state on a mode change
2152                // unless the previous frame's SILK->CELT redundant frame already
2153                // primed it.
2154                if let Some(pm) = self.prev_mode {
2155                    if pm != OpusMode::CeltOnly && !self.prev_redundancy {
2156                        self.celt_dec.reset();
2157                    }
2158                }
2159                self.prev_redundancy = false;
2160                // Mono packet in a stereo stream => C=1, CC=2 (continuous state).
2161                self.celt_dec.set_stream_channels(packet_channels);
2162
2163                for (fi, payload) in frame_payloads.iter().enumerate() {
2164                    let mut rc = RangeCoder::new_decoder(payload);
2165                    let total_bits = (payload.len() * 8) as i32;
2166                    let needed = sub_frame_size * self.channels;
2167                    let out_start = fi * needed;
2168                    let out_end = (out_start + needed).min(output.len());
2169
2170                    if output.len() < out_end {
2171                        return Err("Output buffer too small");
2172                    }
2173
2174                    if self.channels == 1 {
2175                        self.celt_dec.decode_from_range_coder_with_band_range(
2176                            &mut rc,
2177                            total_bits,
2178                            sub_frame_size,
2179                            &mut output[out_start..out_end],
2180                            0,
2181                            celt_end_band,
2182                        );
2183                        for sample in &mut output[out_start..out_end] {
2184                            *sample = sample.clamp(-1.0, 1.0);
2185                        }
2186                    } else {
2187                        self.celt_dec.decode_from_range_coder_with_band_range(
2188                            &mut rc,
2189                            total_bits,
2190                            sub_frame_size,
2191                            &mut self.w_celt_planar[..needed],
2192                            0,
2193                            celt_end_band,
2194                        );
2195                        for i in 0..sub_frame_size {
2196                            for ch in 0..self.channels {
2197                                let idx = out_start + i * self.channels + ch;
2198                                output[idx] =
2199                                    self.w_celt_planar[ch * sub_frame_size + i].clamp(-1.0, 1.0);
2200                            }
2201                        }
2202                    }
2203                    self.last_range = rc.rng;
2204                }
2205                self.prev_mode = Some(OpusMode::CeltOnly);
2206                Ok(frame_size)
2207            }
2208
2209            OpusMode::Hybrid => {
2210                let internal_sample_rate = 16000;
2211                let internal_frame_size =
2212                    (frame_duration_ms * internal_sample_rate / 1000) as usize;
2213                let celt_end_band = self.celt_end_band_from_toc(toc);
2214
2215                if self.sampling_rate != internal_sample_rate
2216                    && internal_sample_rate != self.prev_internal_rate
2217                {
2218                    self.silk_resampler
2219                        .init(internal_sample_rate, self.sampling_rate);
2220                    self.silk_resampler_r
2221                        .init(internal_sample_rate, self.sampling_rate);
2222                    self.prev_internal_rate = internal_sample_rate;
2223                }
2224
2225                // Same SILK stereo/channel handling as the SilkOnly arm: true L/R
2226                // low band via MS->LR for stereo packets; per-packet internal
2227                // channel switch with side-channel/stereo-state resets.
2228                let silk_lr = self.channels == 2 && packet_channels == 2;
2229                self.silk_dec.produce_lr = silk_lr;
2230                let prev_internal_ch = self.silk_dec.n_channels_internal;
2231                if packet_channels as i32 > prev_internal_ch {
2232                    silk::init_decoder::silk_init_decoder(&mut self.silk_dec.channel_state[1]);
2233                }
2234                if self.channels == 2 && packet_channels == 2 && prev_internal_ch == 1 {
2235                    self.silk_dec.s_stereo_pred_prev_q13 = [0; 2];
2236                    self.silk_dec.s_stereo_side = [0; 2];
2237                    self.silk_resampler_r = self.silk_resampler.clone();
2238                }
2239                self.silk_dec.n_channels_internal = packet_channels as i32;
2240
2241                for (fi, payload) in frame_payloads.iter().enumerate() {
2242                    let mut rc = RangeCoder::new_decoder(payload);
2243                    let pcm_silk_i16_len = internal_frame_size * self.channels;
2244                    if pcm_silk_i16_len + 2 > self.w_pcm_i16.len() {
2245                        return Err("opus: SILK frame size exceeds buffer");
2246                    }
2247
2248                    // Prepend the previous frame's last two samples (sMid) and
2249                    // decode at offset 2, matching libopus's samplesOut1_tmp[n][2]
2250                    // layout — the resampler is fed from offset 1 (the 1-sample
2251                    // delay line), keeping the SILK low band aligned with the CELT
2252                    // high band exactly as in the reference.
2253                    let s_mid = self.silk_s_mid;
2254                    let ret = {
2255                        let (silk_dec, pcm_i16) = (&mut self.silk_dec, &mut self.w_pcm_i16);
2256                        pcm_i16[0] = s_mid[0];
2257                        pcm_i16[1] = s_mid[1];
2258                        silk_dec.decode(
2259                            &mut rc,
2260                            &mut pcm_i16[2..pcm_silk_i16_len + 2],
2261                            silk::decode_frame::FLAG_DECODE_NORMAL,
2262                            true,
2263                            frame_duration_ms,
2264                            internal_sample_rate,
2265                        )
2266                    };
2267
2268                    if ret < 0 {
2269                        return Err("SILK decoding failed");
2270                    }
2271
2272                    let silk_out_len = sub_frame_size * self.channels;
2273                    self.w_silk_out[..silk_out_len].fill(0.0);
2274                    if ret > 0 {
2275                        let decoded_samples = ret as usize;
2276                        if decoded_samples >= 2 {
2277                            self.silk_s_mid[0] = self.w_pcm_i16[decoded_samples];
2278                            self.silk_s_mid[1] = self.w_pcm_i16[decoded_samples + 1];
2279                        }
2280                        let ratio = self.sampling_rate as f64 / internal_sample_rate as f64;
2281                        let out_len =
2282                            ((decoded_samples as f64 * ratio) as usize).min(sub_frame_size);
2283                        debug_assert!(out_len <= self.w_pcm_resampled.len());
2284                        if silk_lr {
2285                            // Stereo low band: L/R from dec_api (already in the
2286                            // 1-sample-delay layout), each through its own resampler.
2287                            self.silk_resampler.process(
2288                                &mut self.w_pcm_resampled[..out_len],
2289                                &self.silk_dec.l_out[..decoded_samples],
2290                                decoded_samples as i32,
2291                            );
2292                            for i in 0..out_len {
2293                                self.w_silk_out[i * 2] = self.w_pcm_resampled[i] as f32 / 32768.0;
2294                            }
2295                            self.silk_resampler_r.process(
2296                                &mut self.w_pcm_resampled[..out_len],
2297                                &self.silk_dec.r_out[..decoded_samples],
2298                                decoded_samples as i32,
2299                            );
2300                            for i in 0..out_len {
2301                                self.w_silk_out[i * 2 + 1] =
2302                                    self.w_pcm_resampled[i] as f32 / 32768.0;
2303                            }
2304                        } else {
2305                            self.silk_resampler.process(
2306                                &mut self.w_pcm_resampled[..out_len],
2307                                &self.w_pcm_i16[1..1 + decoded_samples],
2308                                decoded_samples as i32,
2309                            );
2310                            for i in 0..out_len {
2311                                let v = self.w_pcm_resampled[i] as f32 / 32768.0;
2312                                for ch in 0..self.channels {
2313                                    self.w_silk_out[i * self.channels + ch] = v;
2314                                }
2315                            }
2316                            // Mono packet, stereo output: keep the right-channel
2317                            // resampler continuous (libopus dec_API.c:351-355).
2318                            if self.channels == 2 {
2319                                self.silk_resampler_r.process(
2320                                    &mut self.w_pcm_resampled[..out_len],
2321                                    &self.w_pcm_i16[1..1 + decoded_samples],
2322                                    decoded_samples as i32,
2323                                );
2324                                for i in 0..out_len {
2325                                    self.w_silk_out[i * 2 + 1] =
2326                                        self.w_pcm_resampled[i] as f32 / 32768.0;
2327                                }
2328                            }
2329                        }
2330                    }
2331
2332                    // --- Opus redundancy layer, hybrid form (opus_decoder.c) ---
2333                    // redundancy = bit(12); if set: celt_to_silk = bit(1),
2334                    // redundancy_bytes = uint(256)+2 taken from the END of the
2335                    // packet — the MAIN CELT layer still decodes, but with the
2336                    // range coder's storage shrunk by those bytes (this changes
2337                    // its raw-bit region and tell budget).
2338                    let plen = payload.len();
2339                    let mut redundancy = false;
2340                    let mut celt_to_silk = false;
2341                    let mut red_bytes = 0usize;
2342                    let mut effective_len = plen;
2343                    if rc.tell() + 37 <= (plen as i32) * 8 {
2344                        redundancy = rc.decode_bit_logp(12);
2345                        if redundancy {
2346                            celt_to_silk = rc.decode_bit_logp(1);
2347                            red_bytes = rc.dec_uint(256) as usize + 2;
2348                            if red_bytes <= effective_len {
2349                                effective_len -= red_bytes;
2350                            } else {
2351                                red_bytes = 0;
2352                                redundancy = false;
2353                            }
2354                            if redundancy && (effective_len as i32) * 8 < rc.tell() {
2355                                effective_len = plen;
2356                                red_bytes = 0;
2357                                redundancy = false;
2358                            }
2359                            if redundancy {
2360                                rc.storage -= red_bytes as u32;
2361                            }
2362                        }
2363                    }
2364                    let f5 = (self.sampling_rate / 200) as usize;
2365                    let f2_5 = f5 / 2;
2366                    let red_end_band = celt_endband_for_bandwidth(bandwidth);
2367                    let mut red_buf = [0.0f32; 480];
2368                    let mut redundant_rng = 0u32;
2369                    let do_red = redundancy && self.sampling_rate == 48000;
2370                    // CELT->SILK: redundant frame decodes BEFORE the main CELT,
2371                    // continuing the prior CELT state (fade-out of previous CELT).
2372                    if do_red && celt_to_silk {
2373                        redundant_rng = self.decode_redundant_celt(
2374                            &payload[plen - red_bytes..],
2375                            false,
2376                            packet_channels,
2377                            red_end_band,
2378                            &mut red_buf[..f5 * self.channels],
2379                        );
2380                    }
2381
2382                    // Main CELT high band. libopus opus_decoder.c:515 — reset CELT
2383                    // on a mode change unless primed by prior SILK->CELT redundancy.
2384                    if fi == 0 {
2385                        if let Some(pm) = self.prev_mode {
2386                            if pm != OpusMode::Hybrid && !self.prev_redundancy {
2387                                self.celt_dec.reset();
2388                            }
2389                        }
2390                    }
2391                    self.celt_dec.set_stream_channels(packet_channels);
2392                    let total_bits = (effective_len * 8) as i32;
2393                    {
2394                        let (celt_dec, celt_planar) = (&mut self.celt_dec, &mut self.w_celt_planar);
2395                        celt_dec.decode_from_range_coder_with_band_range(
2396                            &mut rc,
2397                            total_bits,
2398                            sub_frame_size,
2399                            &mut celt_planar[..silk_out_len],
2400                            17,
2401                            celt_end_band,
2402                        );
2403
2404                        if self.channels == 1 {
2405                            self.w_celt_out[..silk_out_len]
2406                                .copy_from_slice(&self.w_celt_planar[..silk_out_len]);
2407                        } else {
2408                            for i in 0..sub_frame_size {
2409                                for ch in 0..self.channels {
2410                                    self.w_celt_out[i * self.channels + ch] =
2411                                        self.w_celt_planar[ch * sub_frame_size + i];
2412                                }
2413                            }
2414                        }
2415                    }
2416
2417                    let out_start = fi * silk_out_len;
2418                    let total = silk_out_len.min(output.len() - out_start);
2419                    for j in 0..total {
2420                        output[out_start + j] =
2421                            (self.w_silk_out[j] + self.w_celt_out[j]).clamp(-1.0, 1.0);
2422                    }
2423
2424                    // SILK->CELT: reset + decode the redundant frame AFTER the main
2425                    // decode; it primes the CELT state for the upcoming CELT mode.
2426                    if do_red && !celt_to_silk {
2427                        redundant_rng = self.decode_redundant_celt(
2428                            &payload[plen - red_bytes..],
2429                            true,
2430                            packet_channels,
2431                            red_end_band,
2432                            &mut red_buf[..f5 * self.channels],
2433                        );
2434                    }
2435                    if do_red {
2436                        let window = modes::default_mode().window;
2437                        let region = &mut output[out_start..out_start + silk_out_len];
2438                        if celt_to_silk {
2439                            redundancy_fade_start(
2440                                region,
2441                                &red_buf,
2442                                f5,
2443                                f2_5,
2444                                self.channels,
2445                                window,
2446                            );
2447                        } else {
2448                            redundancy_fade_end(
2449                                region,
2450                                sub_frame_size,
2451                                &red_buf,
2452                                f5,
2453                                f2_5,
2454                                self.channels,
2455                                window,
2456                            );
2457                        }
2458                    }
2459                    self.prev_redundancy = redundancy && !celt_to_silk;
2460                    self.last_range = rc.rng ^ redundant_rng;
2461                }
2462                self.prev_mode = Some(OpusMode::Hybrid);
2463                Ok(frame_size)
2464            }
2465        }
2466    }
2467}
2468
2469impl OpusDecoder {
2470    #[inline(always)]
2471    fn celt_end_band_from_toc(&self, toc: u8) -> usize {
2472        let mode = modes::default_mode();
2473        let top = mode.eff_ebands;
2474        if mode_from_toc(toc) == OpusMode::CeltOnly && toc >= 0x80 {
2475            const FROM_OPUS_TABLE: [u8; 16] = [
2476                0x80, 0x88, 0x90, 0x98, 0x40, 0x48, 0x50, 0x58, 0x20, 0x28, 0x30, 0x38, 0x00, 0x08,
2477                0x10, 0x18,
2478            ];
2479            let idx = ((toc >> 3) - 16) as usize;
2480            let data0 = FROM_OPUS_TABLE[idx] | (toc & 0x7);
2481            let trim = (data0 >> 5) as usize;
2482            return top.saturating_sub(2 * trim).max(1);
2483        }
2484        // Hybrid: libopus maps the packet bandwidth to a CELT end band
2485        // (opus_decoder.c: SWB -> 19, FB -> 21). Decoding SWB hybrid with 21
2486        // reads two bands the encoder never coded -> range desync every packet.
2487        if mode_from_toc(toc) == OpusMode::Hybrid
2488            && bandwidth_from_toc(toc) == Bandwidth::Superwideband
2489        {
2490            return 19.min(top);
2491        }
2492        top
2493    }
2494
2495    /// Decode a redundant CELT frame (opus_decoder.c "5 ms redundant frame"):
2496    /// start band 0, end band from the packet bandwidth, 5 ms, its own range
2497    /// decoder. Returns the redundant final range; PLANAR output in `buf`
2498    /// (F5 samples per state channel). Only valid at 48 kHz output.
2499    fn decode_redundant_celt(
2500        &mut self,
2501        red: &[u8],
2502        reset_first: bool,
2503        packet_channels: usize,
2504        end_band: usize,
2505        buf: &mut [f32],
2506    ) -> u32 {
2507        if reset_first {
2508            self.celt_dec.reset();
2509        }
2510        self.celt_dec.set_stream_channels(packet_channels);
2511        let f5 = (self.sampling_rate / 200) as usize;
2512        let mut rrc = RangeCoder::new_decoder(red);
2513        let total_bits = (red.len() * 8) as i32;
2514        self.celt_dec.decode_from_range_coder_with_band_range(
2515            &mut rrc, total_bits, f5, buf, 0, end_band,
2516        );
2517        rrc.rng
2518    }
2519}
2520
2521/// libopus opus_decoder.c bandwidth -> CELT end band for the packet.
2522fn celt_endband_for_bandwidth(bw: Bandwidth) -> usize {
2523    match bw {
2524        Bandwidth::Narrowband => 13,
2525        Bandwidth::Mediumband | Bandwidth::Wideband => 17,
2526        Bandwidth::Superwideband => 19,
2527        _ => 21,
2528    }
2529}
2530
2531/// smooth_fade cross-fades (w = window[i]^2, 48 kHz inc=1) applied to the
2532/// interleaved output region of one frame. `red` is PLANAR (F5 per channel).
2533/// celt_to_silk: redundant frame occupies the START of the frame — first 2.5 ms
2534/// copied verbatim, next 2.5 ms fades redundant -> main.
2535///
2536/// Indexing invariant: `out.len() >= f5 * channels` (writes reach sample
2537/// f5-1 = 2*f2_5-1). A malformed multi-frame packet used to violate this (a
2538/// hostile frame count made the per-frame region tinier than F5, fuzzer-found
2539/// OOB panics here); decode() now rejects such packets up front exactly as C
2540/// libopus does (opus_decode_native's count*packet_frame_size > frame_size ->
2541/// OPUS_BUFFER_TOO_SMALL, and the 120 ms cap of opus_packet_parse_impl), so a
2542/// redundant frame always has >= 10 ms of frame to fade into, as in C.
2543fn redundancy_fade_start(
2544    out: &mut [f32],
2545    red: &[f32],
2546    f5: usize,
2547    f2_5: usize,
2548    channels: usize,
2549    window: &[f32],
2550) {
2551    for i in 0..f2_5 {
2552        for c in 0..channels {
2553            out[i * channels + c] = red[c * f5 + i];
2554        }
2555    }
2556    for i in 0..f2_5 {
2557        let w = window[i] * window[i];
2558        for c in 0..channels {
2559            let idx = (f2_5 + i) * channels + c;
2560            out[idx] = (1.0 - w) * red[c * f5 + f2_5 + i] + w * out[idx];
2561        }
2562    }
2563}
2564
2565/// SILK->CELT: redundant frame occupies the END of the frame — the last 2.5 ms
2566/// fades main -> redundant (second half of the redundant frame).
2567///
2568/// Indexing invariant: `frame_samples >= f2_5` and `out.len() >=
2569/// frame_samples * channels` (the index `frame_samples - f2_5 + i` would
2570/// otherwise underflow). A malformed multi-frame packet used to violate this
2571/// (fuzzer-found subtract-with-overflow panic here); decode() now rejects such
2572/// packets up front exactly as C libopus does (opus_decode_native's
2573/// count*packet_frame_size > frame_size -> OPUS_BUFFER_TOO_SMALL, plus the
2574/// 120 ms cap of opus_packet_parse_impl), so redundancy only ever runs on
2575/// frames of >= 10 ms, as in C.
2576fn redundancy_fade_end(
2577    out: &mut [f32],
2578    frame_samples: usize,
2579    red: &[f32],
2580    f5: usize,
2581    f2_5: usize,
2582    channels: usize,
2583    window: &[f32],
2584) {
2585    for i in 0..f2_5 {
2586        let w = window[i] * window[i];
2587        for c in 0..channels {
2588            let idx = (frame_samples - f2_5 + i) * channels + c;
2589            out[idx] = (1.0 - w) * out[idx] + w * red[c * f5 + f2_5 + i];
2590        }
2591    }
2592}
2593
2594fn frame_rate_from_params(sampling_rate: i32, frame_size: usize) -> Option<i32> {
2595    let frame_size = frame_size as i32;
2596    if frame_size == 0 || sampling_rate % frame_size != 0 {
2597        return None;
2598    }
2599    Some(sampling_rate / frame_size)
2600}
2601
2602fn gen_toc(mode: OpusMode, frame_rate: i32, bandwidth: Bandwidth, channels: usize) -> u8 {
2603    let mut rate = frame_rate;
2604    let mut period = 0;
2605    while rate < 400 {
2606        rate <<= 1;
2607        period += 1;
2608    }
2609
2610    let mut toc = match mode {
2611        OpusMode::SilkOnly => {
2612            let bw = (bandwidth as i32 - Bandwidth::Narrowband as i32) << 5;
2613            let per = (period - 2) << 3;
2614            (bw | per) as u8
2615        }
2616        OpusMode::CeltOnly => {
2617            let mut tmp = bandwidth as i32 - Bandwidth::Mediumband as i32;
2618            if tmp < 0 {
2619                tmp = 0;
2620            }
2621            let per = period << 3;
2622            (0x80 | (tmp << 5) | per) as u8
2623        }
2624        OpusMode::Hybrid => {
2625            let base_config = if bandwidth == Bandwidth::Superwideband {
2626                12
2627            } else {
2628                14
2629            };
2630            let period_offset = if frame_rate >= 100 { 0 } else { 1 };
2631            ((base_config + period_offset) << 3) as u8
2632        }
2633    };
2634
2635    if channels == 2 {
2636        toc |= 0x04;
2637    }
2638    toc
2639}
2640
2641fn mode_from_toc(toc: u8) -> OpusMode {
2642    if toc & 0x80 != 0 {
2643        OpusMode::CeltOnly
2644    } else if toc & 0x60 == 0x60 {
2645        OpusMode::Hybrid
2646    } else {
2647        OpusMode::SilkOnly
2648    }
2649}
2650
2651fn bandwidth_from_toc(toc: u8) -> Bandwidth {
2652    let mode = mode_from_toc(toc);
2653    match mode {
2654        OpusMode::SilkOnly => {
2655            let bw_bits = (toc >> 5) & 0x03;
2656            match bw_bits {
2657                0 => Bandwidth::Narrowband,
2658                1 => Bandwidth::Mediumband,
2659                2 => Bandwidth::Wideband,
2660                _ => Bandwidth::Wideband,
2661            }
2662        }
2663        OpusMode::Hybrid => {
2664            let bw_bit = (toc >> 4) & 0x01;
2665            if bw_bit == 0 {
2666                Bandwidth::Superwideband
2667            } else {
2668                Bandwidth::Fullband
2669            }
2670        }
2671        OpusMode::CeltOnly => {
2672            let bw_bits = (toc >> 5) & 0x03;
2673            match bw_bits {
2674                0 => Bandwidth::Mediumband,
2675                1 => Bandwidth::Wideband,
2676                2 => Bandwidth::Superwideband,
2677                3 => Bandwidth::Fullband,
2678                _ => Bandwidth::Fullband,
2679            }
2680        }
2681    }
2682}
2683
2684fn frame_duration_ms_from_toc(toc: u8) -> i32 {
2685    let mode = mode_from_toc(toc);
2686    match mode {
2687        OpusMode::SilkOnly => {
2688            let config = (toc >> 3) & 0x03;
2689            match config {
2690                0 => 10,
2691                1 => 20,
2692                2 => 40,
2693                3 => 60,
2694                _ => 20,
2695            }
2696        }
2697        OpusMode::Hybrid => {
2698            let config = (toc >> 3) & 0x01;
2699            if config == 0 { 10 } else { 20 }
2700        }
2701        OpusMode::CeltOnly => {
2702            let config = (toc >> 3) & 0x03;
2703            match config {
2704                0 => 2,
2705                1 => 5,
2706                2 => 10,
2707                3 => 20,
2708                _ => 20,
2709            }
2710        }
2711    }
2712}
2713
2714fn channels_from_toc(toc: u8) -> usize {
2715    if toc & 0x04 != 0 { 2 } else { 1 }
2716}
2717
2718/// RFC 6716 §3.1 frame-length coding (used by code 2 and VBR code 3): a length
2719/// of 0..=251 is one byte with that value; 252..=1275 is two bytes `b0` (252..255)
2720/// then `b1`, giving `b1*4 + b0`. Returns `(length, bytes_consumed)`.
2721fn read_opus_frame_len(data: &[u8], ptr: usize) -> Result<(usize, usize), &'static str> {
2722    let b0 = *data.get(ptr).ok_or("Opus frame length: truncated")? as usize;
2723    if b0 < 252 {
2724        Ok((b0, 1))
2725    } else {
2726        let b1 = *data.get(ptr + 1).ok_or("Opus frame length: truncated 2-byte")? as usize;
2727        Ok((b1 * 4 + b0, 2))
2728    }
2729}
2730
2731#[cfg(test)]
2732mod tests {
2733    use super::*;
2734
2735    fn frame_size_from_toc(toc: u8, sampling_rate: i32) -> Option<usize> {
2736        let mode = mode_from_toc(toc);
2737        match mode {
2738            OpusMode::CeltOnly => {
2739                let period = ((toc >> 3) & 0x03) as i32;
2740                let frame_rate = 400 >> period;
2741                if frame_rate == 0 || sampling_rate % frame_rate != 0 {
2742                    return None;
2743                }
2744                Some((sampling_rate / frame_rate) as usize)
2745            }
2746            OpusMode::SilkOnly => {
2747                let duration_ms = frame_duration_ms_from_toc(toc);
2748                Some((sampling_rate as i64 * duration_ms as i64 / 1000) as usize)
2749            }
2750            OpusMode::Hybrid => {
2751                let duration_ms = frame_duration_ms_from_toc(toc);
2752                Some((sampling_rate as i64 * duration_ms as i64 / 1000) as usize)
2753            }
2754        }
2755    }
2756
2757    #[test]
2758    fn gen_toc_matches_celt_reference_values() {
2759        let sampling_rate = 48_000;
2760        let cases = [
2761            (120usize, 0xE0u8),
2762            (240usize, 0xE8u8),
2763            (480usize, 0xF0u8),
2764            (960usize, 0xF8u8),
2765        ];
2766
2767        for (frame_size, expected_toc) in cases {
2768            let frame_rate = frame_rate_from_params(sampling_rate, frame_size).unwrap();
2769            let toc = gen_toc(OpusMode::CeltOnly, frame_rate, Bandwidth::Fullband, 1);
2770            assert_eq!(
2771                toc, expected_toc,
2772                "frame_size {} expected TOC {:02X} got {:02X}",
2773                frame_size, expected_toc, toc
2774            );
2775            let decoded_size = frame_size_from_toc(toc, sampling_rate).unwrap();
2776            assert_eq!(decoded_size, frame_size);
2777        }
2778
2779        let stereo_toc = gen_toc(
2780            OpusMode::CeltOnly,
2781            frame_rate_from_params(sampling_rate, 960).unwrap(),
2782            Bandwidth::Fullband,
2783            2,
2784        );
2785        assert_eq!(channels_from_toc(stereo_toc), 2);
2786    }
2787
2788    #[test]
2789    fn test_celt_decoder_large_frame_sizes() {
2790        let sampling_rate = 48000;
2791        let channels = 1;
2792
2793        let mut decoder = OpusDecoder::new(sampling_rate, channels).unwrap();
2794
2795        let frame_sizes = [120, 240, 480, 960];
2796
2797        for frame_size in frame_sizes {
2798            let toc = gen_toc(
2799                OpusMode::CeltOnly,
2800                frame_rate_from_params(sampling_rate, frame_size).unwrap(),
2801                Bandwidth::Fullband,
2802                channels,
2803            );
2804            let packet = [toc, 0, 0, 0, 0];
2805
2806            let mut output = vec![0.0f32; frame_size * channels];
2807
2808            let _ = decoder.decode(&packet, frame_size, &mut output);
2809        }
2810
2811        let channels = 2;
2812        let mut decoder = OpusDecoder::new(sampling_rate, channels).unwrap();
2813
2814        for frame_size in frame_sizes {
2815            let toc = gen_toc(
2816                OpusMode::CeltOnly,
2817                frame_rate_from_params(sampling_rate, frame_size).unwrap(),
2818                Bandwidth::Fullband,
2819                channels,
2820            );
2821            let packet = [toc, 0, 0, 0, 0];
2822
2823            let mut output = vec![0.0f32; frame_size * channels];
2824            let _ = decoder.decode(&packet, frame_size, &mut output);
2825        }
2826    }
2827
2828    #[test]
2829    fn test_celt_decoder_edge_case_frame_sizes() {
2830        let sampling_rate = 48000;
2831        let channels = 1;
2832        let mut decoder = OpusDecoder::new(sampling_rate, channels).unwrap();
2833
2834        let edge_sizes = [2048, 2167, 2168, 2169, 2880, 3072];
2835
2836        for frame_size in edge_sizes {
2837            let mut output = vec![0.0f32; frame_size * channels];
2838
2839            let _ = decoder.decode(&[0x80, 0, 0, 0], frame_size, &mut output);
2840        }
2841    }
2842
2843    // Regression test for: "index out of bounds: the len is 48 but the index is 119"
2844    // Root cause: frame_size=48 at 48kHz gives frame_rate=1000, which is not a valid
2845    // Hybrid-mode frame rate but was not validated.  CELT's lm-search then silently
2846    // fell back to lm=0, computed n2=120, and wrote output[119] into a 48-element
2847    // slice.  Triggered via G.729-decoded PCM (8kHz) passed to a 48kHz Opus encoder
2848    // without proper resampling, so the encoder received 48 samples instead of 480.
2849    #[test]
2850    fn test_invalid_small_frame_size_returns_error_not_panic() {
2851        let mut enc = OpusEncoder::new(48000, 2, Application::Voip).unwrap();
2852        enc.bitrate_bps = 64000;
2853        enc.complexity = 5;
2854        enc.use_cbr = true;
2855
2856        // 48 samples at 48kHz = 1ms → frame_rate=1000, invalid for Hybrid mode.
2857        let input = vec![0.0f32; 48 * 2]; // stereo interleaved
2858        let mut output = vec![0u8; 256];
2859
2860        let result = enc.encode(&input, 48, &mut output);
2861        assert!(
2862            result.is_err(),
2863            "encode with invalid frame_size=48 should return Err, not panic"
2864        );
2865    }
2866
2867    // Also verify that the Audio application path (always Hybrid at 48 kHz) rejects
2868    // the same bad frame size.
2869    #[test]
2870    fn test_invalid_small_frame_size_audio_application_returns_error() {
2871        let mut enc = OpusEncoder::new(48000, 1, Application::Audio).unwrap();
2872        let input = vec![0.0f32; 48];
2873        let mut output = vec![0u8; 256];
2874
2875        let result = enc.encode(&input, 48, &mut output);
2876        assert!(
2877            result.is_err(),
2878            "Audio/48kHz encoder with frame_size=48 should return Err"
2879        );
2880    }
2881}