Skip to main content

rusty_opus/silk/
decode_frame.rs

1use crate::range_coder::RangeCoder;
2use crate::silk::decode_core::silk_decode_core;
3use crate::silk::decode_indices::silk_decode_indices;
4use crate::silk::decode_parameters::silk_decode_parameters;
5use crate::silk::decode_pulses::silk_decode_pulses;
6use crate::silk::decoder_structs::{SilkDecoderControl, SilkDecoderState};
7use crate::silk::define::*;
8use crate::silk::plc::{silk_plc, silk_plc_glue_frames};
9
10pub const FLAG_DECODE_NORMAL: i32 = 0;
11pub const FLAG_PACKET_LOST: i32 = 1;
12pub const FLAG_DECODE_LBRR: i32 = 2;
13
14pub fn silk_decode_frame(
15    ps_dec: &mut SilkDecoderState,
16    ps_range_dec: &mut RangeCoder,
17    p_out: &mut [i16],
18    p_n: &mut i32,
19    lost_flag: i32,
20    cond_coding: i32,
21) -> i32 {
22    let l = ps_dec.frame_length as usize;
23    let mut ps_dec_ctrl = SilkDecoderControl::new();
24    ps_dec_ctrl.ltp_scale_q14 = 0;
25
26    debug_assert!(l > 0 && l <= MAX_FRAME_LENGTH);
27
28    if lost_flag == FLAG_DECODE_NORMAL
29        || (lost_flag == FLAG_DECODE_LBRR
30            && ps_dec.lbrr_flags[ps_dec.n_frames_decoded as usize] == 1)
31    {
32        let mut pulses: [i16; MAX_FRAME_LENGTH] = [0; MAX_FRAME_LENGTH];
33
34        silk_decode_indices(
35            ps_dec,
36            ps_range_dec,
37            ps_dec.n_frames_decoded,
38            lost_flag,
39            cond_coding,
40        );
41
42        silk_decode_pulses(
43            ps_range_dec,
44            &mut pulses,
45            ps_dec.indices.signal_type as i32,
46            ps_dec.indices.quant_offset_type as i32,
47            ps_dec.frame_length,
48        );
49
50        silk_decode_parameters(ps_dec, &mut ps_dec_ctrl, cond_coding);
51
52        silk_decode_core(ps_dec, &ps_dec_ctrl, p_out, &pulses);
53
54        // Update PLC state from this good frame (silk_PLC lost=0).
55        silk_plc(ps_dec, &mut ps_dec_ctrl, p_out, 0);
56
57        ps_dec.loss_cnt = 0;
58        ps_dec.prev_signal_type = ps_dec.indices.signal_type as i32;
59
60        ps_dec.first_frame_after_reset = 0;
61    } else {
62        // Handle packet loss by extrapolation (silk_PLC lost=1 writes p_out and
63        // bumps loss_cnt). Previously we just zeroed the frame — hard silence.
64        silk_plc(ps_dec, &mut ps_dec_ctrl, p_out, 1);
65    }
66
67    // Comfort-noise generation: tracks background noise on active silence frames
68    // and overlays it on the PLC output during loss/DTX (silk_CNG).
69    crate::silk::cng::silk_cng(ps_dec, &ps_dec_ctrl, p_out, l);
70
71    // Update output buffer (both paths).
72    let mv_len = ps_dec.ltp_mem_length - ps_dec.frame_length;
73    ps_dec.out_buf.rotate_left(ps_dec.frame_length as usize);
74    ps_dec.out_buf[mv_len as usize..mv_len as usize + l].copy_from_slice(&p_out[..l]);
75
76    // Ensure smooth connection of extrapolated and good frames.
77    silk_plc_glue_frames(ps_dec, p_out, l);
78
79    ps_dec.lag_prev = ps_dec_ctrl.pitch_l[ps_dec.nb_subfr as usize - 1];
80
81    *p_n = l as i32;
82
83    0
84}