Skip to main content

rusty_opus/silk/
control_fixed.rs

1use crate::silk::define::*;
2use crate::silk::gain_quant::*;
3use crate::silk::lpc_analysis::*;
4use crate::silk::ltp_analysis::*;
5use crate::silk::macros::*;
6use crate::silk::nlsf::*;
7use crate::silk::sigm::*;
8use crate::silk::sigproc_fix::*;
9use crate::silk::structs::*;
10use crate::silk::tables::*;
11
12#[inline(always)]
13pub fn silk_find_pred_coefs_fix(
14    ps_enc: &mut SilkEncoderState,
15    ps_enc_ctrl: &mut SilkEncoderControl,
16    res_pitch: &[i16],
17    res_pitch_frame_idx: usize,
18    x: &[i16],
19    x_buf_full: &[i16],
20    cond_coding: i32,
21) {
22    let _prof = crate::prof::scope(crate::prof::Stage::SilkPred);
23    let mut inv_gains_q16 = [0i32; MAX_NB_SUBFR];
24    let mut local_gains = [0i32; MAX_NB_SUBFR];
25    let mut nlsf_q15 = [0i16; MAX_LPC_ORDER];
26    let mut min_gain_q16: i32;
27    let mut min_inv_gain_q30: i32;
28
29    min_gain_q16 = i32::MAX >> 6;
30    for i in 0..ps_enc.s_cmn.nb_subfr as usize {
31        min_gain_q16 = min_gain_q16.min(ps_enc_ctrl.gains_q16[i]);
32    }
33    for i in 0..ps_enc.s_cmn.nb_subfr as usize {
34        inv_gains_q16[i] = silk_div32_varq(min_gain_q16, ps_enc_ctrl.gains_q16[i], 16 - 2);
35
36        inv_gains_q16[i] = inv_gains_q16[i].max(100);
37
38        local_gains[i] = silk_div32(1 << 16, inv_gains_q16[i]);
39    }
40
41    let mut lpc_in_pre = [0i16; MAX_NB_SUBFR * MAX_LPC_ORDER + MAX_FRAME_LENGTH];
42
43    if ps_enc.s_cmn.indices.signal_type == TYPE_VOICED as i8 {
44        let mut x_xltp_q17 = [0i32; MAX_NB_SUBFR * LTP_ORDER];
45        let mut xxltp_q17 = [0i32; MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER];
46
47        silk_find_ltp_fix(
48            &mut xxltp_q17,
49            &mut x_xltp_q17,
50            res_pitch,
51            res_pitch_frame_idx,
52            &ps_enc_ctrl.pitch_l,
53            ps_enc.s_cmn.subfr_length as usize,
54            ps_enc.s_cmn.nb_subfr as usize,
55            0,
56        );
57
58        silk_quant_ltp_gains(
59            &mut ps_enc_ctrl.ltp_coef_q14,
60            &mut ps_enc.s_cmn.indices.ltp_index,
61            &mut ps_enc.s_cmn.indices.per_index,
62            &mut ps_enc.s_cmn.sum_log_gain_q7,
63            &mut ps_enc_ctrl.ltp_red_cod_gain_q7,
64            &xxltp_q17,
65            &x_xltp_q17,
66            ps_enc.s_cmn.subfr_length,
67            ps_enc.s_cmn.nb_subfr as usize,
68            0,
69        );
70
71        silk_ltp_scale_ctrl_fix(ps_enc, ps_enc_ctrl, cond_coding);
72
73        let predict_lpc_order = ps_enc.s_cmn.predict_lpc_order as usize;
74        let x_base_for_ltp = ps_enc.s_cmn.ltp_mem_length as usize - predict_lpc_order;
75        silk_ltp_analysis_filter_fix(
76            &mut lpc_in_pre,
77            x_buf_full,
78            x_base_for_ltp,
79            &ps_enc_ctrl.ltp_coef_q14,
80            &ps_enc_ctrl.pitch_l,
81            &inv_gains_q16,
82            ps_enc.s_cmn.subfr_length as usize,
83            ps_enc.s_cmn.nb_subfr as usize,
84            ps_enc.s_cmn.predict_lpc_order as usize,
85        );
86    } else {
87        let mut x_ptr_idx = 0;
88        let mut x_pre_ptr_idx = 0;
89        for i in 0..ps_enc.s_cmn.nb_subfr as usize {
90            silk_scale_copy_vector16(
91                &mut lpc_in_pre[x_pre_ptr_idx..],
92                &x[x_ptr_idx..],
93                inv_gains_q16[i],
94                (ps_enc.s_cmn.subfr_length + ps_enc.s_cmn.predict_lpc_order) as usize,
95            );
96            x_pre_ptr_idx += (ps_enc.s_cmn.subfr_length + ps_enc.s_cmn.predict_lpc_order) as usize;
97            x_ptr_idx += ps_enc.s_cmn.subfr_length as usize;
98        }
99
100        ps_enc_ctrl.ltp_coef_q14.fill(0);
101        ps_enc_ctrl.ltp_red_cod_gain_q7 = 0;
102        ps_enc.s_cmn.sum_log_gain_q7 = 0;
103        ps_enc_ctrl.ltp_scale_q14 = 0;
104    }
105
106    if ps_enc.s_cmn.first_frame_after_reset != 0 {
107        min_inv_gain_q30 =
108            (1.0f32 / MAX_PREDICTION_POWER_GAIN_AFTER_RESET * 1073741824.0f32) as i32;
109    } else {
110        min_inv_gain_q30 = silk_log2lin(silk_smlawb(
111            16 << 7,
112            ps_enc_ctrl.ltp_red_cod_gain_q7,
113            (1.0f32 / 3.0f32 * 65536.0f32) as i32,
114        ));
115        min_inv_gain_q30 = silk_div32_varq(
116            min_inv_gain_q30,
117            silk_smulww(
118                MAX_PREDICTION_POWER_GAIN as i32,
119                silk_smlawb(
120                    (0.25f32 * 262144.0f32) as i32,
121                    (0.75f32 * 262144.0f32) as i32,
122                    ps_enc_ctrl.coding_quality_q14,
123                ),
124            ),
125            14,
126        );
127    }
128
129    silk_find_lpc_fix(
130        &mut ps_enc.s_cmn,
131        &mut nlsf_q15,
132        &lpc_in_pre,
133        min_inv_gain_q30,
134    );
135
136    silk_process_nlsfs(ps_enc, ps_enc_ctrl, &mut nlsf_q15);
137
138    silk_residual_energy_fix(
139        &mut ps_enc_ctrl.res_nrg,
140        &mut ps_enc_ctrl.res_nrg_q,
141        &lpc_in_pre,
142        &ps_enc_ctrl.pred_coef_q12,
143        &local_gains,
144        ps_enc.s_cmn.subfr_length,
145        ps_enc.s_cmn.nb_subfr,
146        ps_enc.s_cmn.predict_lpc_order,
147    );
148}
149
150pub fn silk_process_gains_fix(
151    ps_enc: &mut SilkEncoderState,
152    ps_enc_ctrl: &mut SilkEncoderControl,
153    cond_coding: i32,
154) {
155    let ps_shape_st = &mut ps_enc.s_shape;
156    let s_q15: i32;
157    let mut gain_q16: i32;
158    let mut gain_squared_q16: i32;
159    let mut res_nrg_part: i32;
160
161    if ps_enc.s_cmn.indices.signal_type == TYPE_VOICED as i8 {
162        s_q15 = -silk_sigm_q15(silk_rshift_round(
163            ps_enc_ctrl.ltp_red_cod_gain_q7 - (12.0 * 128.0) as i32,
164            4,
165        ));
166        for k in 0..ps_enc.s_cmn.nb_subfr as usize {
167            ps_enc_ctrl.gains_q16[k] =
168                silk_smlawb(ps_enc_ctrl.gains_q16[k], ps_enc_ctrl.gains_q16[k], s_q15);
169        }
170    }
171
172    let log2lin_arg = silk_smulwb(
173        ((21.0 + 16.0 / 0.33) * 128.0) as i32 - ps_enc.s_cmn.snr_db_q7,
174        21627_i32,
175    );
176    let log2lin_val = silk_log2lin(log2lin_arg);
177    let inv_max_sqr_val_q16 = silk_div32_16(log2lin_val, ps_enc.s_cmn.subfr_length);
178
179    for k in 0..ps_enc.s_cmn.nb_subfr as usize {
180        let res_nrg = ps_enc_ctrl.res_nrg[k];
181        res_nrg_part = silk_smulww(res_nrg, inv_max_sqr_val_q16);
182        if ps_enc_ctrl.res_nrg_q[k] > 0 {
183            res_nrg_part = silk_rshift_round(res_nrg_part, ps_enc_ctrl.res_nrg_q[k]);
184        } else {
185            let neg_q = (-ps_enc_ctrl.res_nrg_q[k]).min(30);
186            if neg_q == 0 || res_nrg_part >= (i32::MAX >> neg_q) {
187                res_nrg_part = if neg_q == 0 { res_nrg_part } else { i32::MAX };
188            } else {
189                res_nrg_part <<= neg_q;
190            }
191        }
192        gain_q16 = ps_enc_ctrl.gains_q16[k];
193        gain_squared_q16 = silk_add_sat32(res_nrg_part, silk_smmul(gain_q16, gain_q16));
194        if gain_squared_q16 < i16::MAX as i32 {
195            gain_squared_q16 = silk_smlaww(res_nrg_part << 16, gain_q16, gain_q16);
196
197            gain_q16 = silk_sqrt_approx(gain_squared_q16);
198            gain_q16 = silk_min_32(gain_q16, i32::MAX >> 8);
199            ps_enc_ctrl.gains_q16[k] = silk_lshift_sat32(gain_q16, 8);
200        } else {
201            gain_q16 = silk_sqrt_approx(gain_squared_q16);
202            gain_q16 = silk_min_32(gain_q16, i32::MAX >> 16);
203            ps_enc_ctrl.gains_q16[k] = silk_lshift_sat32(gain_q16, 16);
204        }
205    }
206
207    for k in 0..ps_enc.s_cmn.nb_subfr as usize {
208        ps_enc_ctrl.gains_unq_q16[k] = ps_enc_ctrl.gains_q16[k];
209    }
210    ps_enc_ctrl.last_gain_index_prev = ps_shape_st.last_gain_index;
211
212    silk_gains_quant(
213        &mut ps_enc.s_cmn.indices.gains_indices,
214        &mut ps_enc_ctrl.gains_q16,
215        &mut ps_shape_st.last_gain_index,
216        if cond_coding == CODE_CONDITIONALLY {
217            1
218        } else {
219            0
220        },
221        ps_enc.s_cmn.nb_subfr as usize,
222    );
223
224    if ps_enc.s_cmn.indices.signal_type == TYPE_VOICED as i8 {
225        if ps_enc_ctrl.ltp_red_cod_gain_q7 + (ps_enc.s_cmn.input_tilt_q15 >> 8) > 128 {
226            ps_enc.s_cmn.indices.quant_offset_type = 0;
227        } else {
228            ps_enc.s_cmn.indices.quant_offset_type = 1;
229        }
230    }
231
232    let quant_offset_q10 = SILK_QUANTIZATION_OFFSETS_Q10
233        [(ps_enc.s_cmn.indices.signal_type >> 1) as usize]
234        [ps_enc.s_cmn.indices.quant_offset_type as usize] as i32;
235
236    const LAMBDA_OFFSET_Q10: i32 = 1229;
237    const LAMBDA_DELAYED_DECISIONS_Q10: i32 = -50;
238    const LAMBDA_SPEECH_ACT_Q18: i32 = -52428;
239    const LAMBDA_INPUT_QUALITY_Q12: i32 = -409;
240    const LAMBDA_CODING_QUALITY_Q12: i32 = -818;
241    const LAMBDA_QUANT_OFFSET_Q16: i32 = 52429;
242
243    ps_enc_ctrl.lambda_q10 = LAMBDA_OFFSET_Q10
244        + silk_smulbb(
245            LAMBDA_DELAYED_DECISIONS_Q10,
246            ps_enc.s_cmn.n_states_delayed_decision,
247        )
248        + silk_smulwb(LAMBDA_SPEECH_ACT_Q18, ps_enc.s_cmn.speech_activity_q8)
249        + silk_smulwb(LAMBDA_INPUT_QUALITY_Q12, ps_enc_ctrl.input_quality_q14)
250        + silk_smulwb(LAMBDA_CODING_QUALITY_Q12, ps_enc_ctrl.coding_quality_q14)
251        + silk_smulwb(LAMBDA_QUANT_OFFSET_Q16, quant_offset_q10);
252}
253
254pub fn silk_ltp_scale_ctrl_fix(
255    ps_enc: &mut SilkEncoderState,
256    ps_enc_ctrl: &mut SilkEncoderControl,
257    cond_coding: i32,
258) {
259    if cond_coding == CODE_INDEPENDENTLY {
260        let mut round_loss = ps_enc.s_cmn.packet_loss_perc * ps_enc.s_cmn.n_frames_per_packet;
261        if ps_enc.s_cmn.lbrr_flag != 0 {
262            round_loss = 2 + silk_smulbb(round_loss, round_loss) / 100;
263        }
264        ps_enc.s_cmn.indices.ltp_scale_index =
265            (silk_smulbb(ps_enc_ctrl.ltp_red_cod_gain_q7, round_loss)
266                > silk_log2lin(128 * 7 + 2900 - ps_enc.s_cmn.snr_db_q7)) as i8;
267        ps_enc.s_cmn.indices.ltp_scale_index +=
268            (silk_smulbb(ps_enc_ctrl.ltp_red_cod_gain_q7, round_loss)
269                > silk_log2lin(128 * 7 + 3900 - ps_enc.s_cmn.snr_db_q7)) as i8;
270    } else {
271        ps_enc.s_cmn.indices.ltp_scale_index = 0;
272    }
273    ps_enc_ctrl.ltp_scale_q14 =
274        SILK_LTP_SCALES_TABLE_Q14[ps_enc.s_cmn.indices.ltp_scale_index as usize] as i32;
275}