Skip to main content

rusty_opus/silk/
encode_indices.rs

1use crate::range_coder::RangeCoder;
2use crate::silk::define::*;
3use crate::silk::nlsf_unpack::silk_nlsf_unpack;
4use crate::silk::structs::*;
5use crate::silk::tables::*;
6
7pub fn silk_encode_indices(
8    ps_enc_c: &mut SilkEncoderState,
9    ps_range_enc: &mut RangeCoder,
10    frame_index: usize,
11    encode_lbrr: bool,
12    cond_coding: i32,
13) {
14    let _prof = crate::prof::scope(crate::prof::Stage::SilkCode);
15    let ps_indices = if encode_lbrr {
16        ps_enc_c.s_cmn.indices_lbrr[frame_index]
17    } else {
18        ps_enc_c.s_cmn.indices
19    };
20    let ps_indices = &ps_indices;
21
22    let type_offset = 2 * ps_indices.signal_type + ps_indices.quant_offset_type;
23    if encode_lbrr || type_offset >= 2 {
24        ps_range_enc.encode_icdf((type_offset - 2) as i32, &SILK_TYPE_OFFSET_VAD_ICDF, 8);
25    } else {
26        ps_range_enc.encode_icdf(type_offset as i32, &SILK_TYPE_OFFSET_NO_VAD_ICDF, 8);
27    }
28
29    if cond_coding == CODE_CONDITIONALLY {
30        ps_range_enc.encode_icdf(ps_indices.gains_indices[0] as i32, &SILK_DELTA_GAIN_ICDF, 8);
31    } else {
32        ps_range_enc.encode_icdf(
33            (ps_indices.gains_indices[0] >> 3) as i32,
34            &SILK_GAIN_ICDF[ps_indices.signal_type as usize],
35            8,
36        );
37        ps_range_enc.encode_icdf(
38            (ps_indices.gains_indices[0] & 7) as i32,
39            &SILK_UNIFORM8_ICDF,
40            8,
41        );
42    }
43
44    for i in 1..ps_enc_c.s_cmn.nb_subfr as usize {
45        ps_range_enc.encode_icdf(ps_indices.gains_indices[i] as i32, &SILK_DELTA_GAIN_ICDF, 8);
46    }
47
48    let cb = ps_enc_c.ps_nlsf_cb.expect("NLSF codebook not initialized");
49    ps_range_enc.encode_icdf(
50        ps_indices.nlsf_indices[0] as i32,
51        &cb.cb1_icdf[((ps_indices.signal_type >> 1) as usize * cb.n_vectors as usize)..],
52        8,
53    );
54
55    let mut ec_ix = [0i16; MAX_LPC_ORDER];
56    let mut pred_q8 = [0u8; MAX_LPC_ORDER];
57    silk_nlsf_unpack(
58        &mut ec_ix,
59        &mut pred_q8,
60        cb,
61        ps_indices.nlsf_indices[0] as usize,
62    );
63
64    for i in 0..cb.order as usize {
65        if ps_indices.nlsf_indices[i + 1] >= NLSF_QUANT_MAX_AMPLITUDE as i8 {
66            ps_range_enc.encode_icdf(
67                2 * NLSF_QUANT_MAX_AMPLITUDE,
68                &cb.ec_icdf[ec_ix[i] as usize..],
69                8,
70            );
71            ps_range_enc.encode_icdf(
72                (ps_indices.nlsf_indices[i + 1] - NLSF_QUANT_MAX_AMPLITUDE as i8) as i32,
73                &SILK_NLSF_EXT_ICDF,
74                8,
75            );
76        } else if ps_indices.nlsf_indices[i + 1] <= -(NLSF_QUANT_MAX_AMPLITUDE as i8) {
77            ps_range_enc.encode_icdf(0, &cb.ec_icdf[ec_ix[i] as usize..], 8);
78            ps_range_enc.encode_icdf(
79                (-ps_indices.nlsf_indices[i + 1] - NLSF_QUANT_MAX_AMPLITUDE as i8) as i32,
80                &SILK_NLSF_EXT_ICDF,
81                8,
82            );
83        } else {
84            ps_range_enc.encode_icdf(
85                (ps_indices.nlsf_indices[i + 1] + NLSF_QUANT_MAX_AMPLITUDE as i8) as i32,
86                &cb.ec_icdf[ec_ix[i] as usize..],
87                8,
88            );
89        }
90    }
91
92    if ps_enc_c.s_cmn.nb_subfr == MAX_NB_SUBFR as i32 {
93        ps_range_enc.encode_icdf(
94            ps_indices.nlsf_interp_coef_q2 as i32,
95            &SILK_NLSF_INTERPOLATION_FACTOR_ICDF,
96            8,
97        );
98    }
99
100    if ps_indices.signal_type == TYPE_VOICED as i8 {
101        let mut encode_absolute_lag_index = true;
102        if cond_coding == CODE_CONDITIONALLY && ps_enc_c.s_cmn.ec_prev_signal_type == TYPE_VOICED {
103            let mut delta_lag_index =
104                ps_indices.lag_index as i32 - ps_enc_c.s_cmn.ec_prev_lag_index as i32;
105            if !(-8..=11).contains(&delta_lag_index) {
106                delta_lag_index = 0;
107            } else {
108                delta_lag_index += 9;
109                encode_absolute_lag_index = false;
110            }
111            ps_range_enc.encode_icdf(delta_lag_index, &SILK_PITCH_DELTA_ICDF, 8);
112        }
113        if encode_absolute_lag_index {
114            let half_fs = ps_enc_c.s_cmn.fs_khz / 2;
115
116            let max_lag_index = (SILK_PITCH_LAG_ICDF.len() as i32 - 1) * half_fs + (half_fs - 1);
117            let lag_index = (ps_indices.lag_index as i32).min(max_lag_index);
118
119            let pitch_high_bits = lag_index / half_fs;
120            let pitch_low_bits = lag_index - pitch_high_bits * half_fs;
121            ps_range_enc.encode_icdf(pitch_high_bits, &SILK_PITCH_LAG_ICDF, 8);
122
123            let low_bits_icdf = match ps_enc_c.s_cmn.fs_khz {
124                8 => &SILK_UNIFORM4_ICDF[..],
125                12 => &SILK_UNIFORM6_ICDF[..],
126                16 => &SILK_UNIFORM8_ICDF[..],
127                _ => &SILK_UNIFORM8_ICDF[..],
128            };
129            ps_range_enc.encode_icdf(pitch_low_bits, low_bits_icdf, 8);
130        }
131        ps_enc_c.s_cmn.ec_prev_lag_index = ps_indices.lag_index;
132
133        let contour_icdf = if ps_enc_c.s_cmn.nb_subfr == 2 {
134            if ps_enc_c.s_cmn.fs_khz == 8 {
135                &SILK_PITCH_CONTOUR_10_MS_NB_ICDF[..]
136            } else {
137                &SILK_PITCH_CONTOUR_10_MS_ICDF[..]
138            }
139        } else if ps_enc_c.s_cmn.fs_khz == 8 {
140            &SILK_PITCH_CONTOUR_NB_ICDF[..]
141        } else {
142            &SILK_PITCH_CONTOUR_ICDF[..]
143        };
144        ps_range_enc.encode_icdf(ps_indices.contour_index as i32, contour_icdf, 8);
145
146        ps_range_enc.encode_icdf(ps_indices.per_index as i32, &SILK_LTP_PER_INDEX_ICDF, 8);
147
148        for k in 0..ps_enc_c.s_cmn.nb_subfr as usize {
149            ps_range_enc.encode_icdf(
150                ps_indices.ltp_index[k] as i32,
151                SILK_LTP_GAIN_ICDF_PTRS[ps_indices.per_index as usize],
152                8,
153            );
154        }
155
156        if cond_coding == CODE_INDEPENDENTLY {
157            ps_range_enc.encode_icdf(ps_indices.ltp_scale_index as i32, &SILK_LTPSCALE_ICDF, 8);
158        }
159    }
160
161    ps_enc_c.s_cmn.ec_prev_signal_type = ps_indices.signal_type as i32;
162
163    ps_range_enc.encode_icdf(ps_indices.seed as i32, &SILK_UNIFORM4_ICDF, 8);
164}
165
166pub fn silk_encode_stereo(
167    ps_range_enc: &mut RangeCoder,
168    _side_idx: i8,
169    _pred_idx: i8,
170    only_middle: i8,
171) {
172    // C-compatible order: stereo_pred (5 ICDFs) first, then mid_only flag
173    // Use zero/neutral values for prediction (decoder discards these anyway)
174    ps_range_enc.encode_icdf(0, &SILK_STEREO_PRED_JOINT_ICDF, 8);
175    ps_range_enc.encode_icdf(0, &SILK_UNIFORM3_ICDF, 8);
176    ps_range_enc.encode_icdf(0, &SILK_UNIFORM5_ICDF, 8);
177    ps_range_enc.encode_icdf(0, &SILK_UNIFORM3_ICDF, 8);
178    ps_range_enc.encode_icdf(0, &SILK_UNIFORM5_ICDF, 8);
179    // Write mid-only flag (since ch1_VAD == 0 for our mid-only stereo, decoder always reads this)
180    ps_range_enc.encode_icdf(only_middle as i32, &SILK_STEREO_ONLY_CODE_MID_ICDF, 8);
181}