1use crate::silk::decoder_structs::{SilkDecoderControl, SilkDecoderState};
2use crate::silk::define::*;
3use crate::silk::macros::*;
4use crate::silk::tables::SILK_QUANTIZATION_OFFSETS_Q10;
5
6pub fn silk_decode_core(
7 ps_dec: &mut SilkDecoderState,
8 ps_dec_ctrl: &SilkDecoderControl,
9 xq: &mut [i16],
10 pulses: &[i16],
11) {
12 let nlsf_interpolation_flag = if ps_dec.indices.nlsf_interp_coef_q2 < 4 {
13 1
14 } else {
15 0
16 };
17
18 let offset_q10 = SILK_QUANTIZATION_OFFSETS_Q10[(ps_dec.indices.signal_type >> 1) as usize]
19 [ps_dec.indices.quant_offset_type as usize] as i32;
20
21 let mut rand_seed = ps_dec.indices.seed as i32;
22 for i in 0..ps_dec.frame_length as usize {
23 rand_seed = silk_rand(rand_seed);
24 ps_dec.exc_q14[i] = (pulses[i] as i32) << 14;
25 if ps_dec.exc_q14[i] > 0 {
26 ps_dec.exc_q14[i] -= QUANT_LEVEL_ADJUST_Q10 << 4;
27 } else if ps_dec.exc_q14[i] < 0 {
28 ps_dec.exc_q14[i] += QUANT_LEVEL_ADJUST_Q10 << 4;
29 }
30 ps_dec.exc_q14[i] += offset_q10 << 4;
31 if rand_seed < 0 {
32 ps_dec.exc_q14[i] = -ps_dec.exc_q14[i];
33 }
34 rand_seed = silk_add32_ovflw(rand_seed, pulses[i] as i32);
35 }
36
37 let mut s_lpc_q14: [i32; MAX_SUB_FRAME_LENGTH + MAX_LPC_ORDER] =
38 [0; MAX_SUB_FRAME_LENGTH + MAX_LPC_ORDER];
39 s_lpc_q14[..MAX_LPC_ORDER].copy_from_slice(&ps_dec.s_lpc_q14_buf);
40
41 let mut pexc_q14_idx: usize = 0;
42 let mut pxq_idx: usize = 0;
43 let mut s_ltp_buf_idx = ps_dec.ltp_mem_length;
44
45 let s_ltp_q15_len = ps_dec.ltp_mem_length as usize + ps_dec.frame_length as usize;
46 let s_ltp_len = ps_dec.ltp_mem_length as usize;
47
48 const MAX_S_LTP_Q15: usize = 640;
49 const MAX_S_LTP: usize = 320;
50 debug_assert!(s_ltp_q15_len <= MAX_S_LTP_Q15);
51 debug_assert!(s_ltp_len <= MAX_S_LTP);
52 let mut s_ltp_q15_buf = [0i32; MAX_S_LTP_Q15];
53 let s_ltp_q15 = &mut s_ltp_q15_buf[..s_ltp_q15_len];
54 let mut s_ltp_buf = [0i16; MAX_S_LTP];
55 let s_ltp = &mut s_ltp_buf[..s_ltp_len];
56
57 for k in 0..ps_dec.nb_subfr as usize {
58 let a_q12 = &ps_dec_ctrl.pred_coef_q12[k >> 1];
59 let b_q14 = &ps_dec_ctrl.ltp_coef_q14[k * LTP_ORDER..];
60 let signal_type = ps_dec.indices.signal_type;
61
62 let mut inv_gain_q31 = silk_inverse32_varq(ps_dec_ctrl.gains_q16[k], 47);
63
64 let gain_adj_q16 = if ps_dec_ctrl.gains_q16[k] != ps_dec.prev_gain_q16 {
65 let adj = silk_div32_varq(ps_dec.prev_gain_q16, ps_dec_ctrl.gains_q16[k], 16);
66
67 for i in 0..MAX_LPC_ORDER {
68 s_lpc_q14[i] = silk_smulww(adj, s_lpc_q14[i]);
69 }
70 adj
71 } else {
72 1 << 16
73 };
74
75 ps_dec.prev_gain_q16 = ps_dec_ctrl.gains_q16[k];
76
77 let (eff_signal_type, eff_pitch_l) = if ps_dec.loss_cnt > 0
78 && ps_dec.prev_signal_type == TYPE_VOICED
79 && ps_dec.indices.signal_type as i32 != TYPE_VOICED
80 && k < MAX_NB_SUBFR / 2
81 {
82 (TYPE_VOICED, ps_dec.lag_prev)
83 } else {
84 (signal_type as i32, ps_dec_ctrl.pitch_l[k])
85 };
86
87 let mut lag = 0;
88 if eff_signal_type == TYPE_VOICED {
89 lag = eff_pitch_l;
90
91 if k == 0 || (k == 2 && nlsf_interpolation_flag != 0) {
92 let start_idx =
93 ps_dec.ltp_mem_length - lag - ps_dec.lpc_order - (LTP_ORDER / 2) as i32;
94 debug_assert!(start_idx > 0);
95
96 if k == 2 {
97 let copy_start = ps_dec.ltp_mem_length as usize;
98 let copy_len = 2 * ps_dec.subfr_length as usize;
99 ps_dec.out_buf[copy_start..copy_start + copy_len]
100 .copy_from_slice(&xq[0..copy_len]);
101 }
102
103 let filter_input_offset = start_idx as usize + k * ps_dec.subfr_length as usize;
104 let filter_len = (ps_dec.ltp_mem_length - start_idx) as usize;
105 silk_lpc_analysis_filter_offset(
106 s_ltp,
107 start_idx as usize,
108 &ps_dec.out_buf,
109 filter_input_offset,
110 a_q12,
111 filter_len,
112 ps_dec.lpc_order as usize,
113 );
114
115 if k == 0 {
116 inv_gain_q31 =
117 silk_lshift(silk_smulwb(inv_gain_q31, ps_dec_ctrl.ltp_scale_q14), 2);
118 }
119 for i in 0..(lag + LTP_ORDER as i32 / 2) as usize {
120 s_ltp_q15[s_ltp_buf_idx as usize - i - 1] = silk_smulwb(
121 inv_gain_q31,
122 s_ltp[ps_dec.ltp_mem_length as usize - i - 1] as i32,
123 );
124 }
125 } else if gain_adj_q16 != (1 << 16) {
126 for i in 0..(lag + LTP_ORDER as i32 / 2) as usize {
127 s_ltp_q15[s_ltp_buf_idx as usize - i - 1] =
128 silk_smulww(gain_adj_q16, s_ltp_q15[s_ltp_buf_idx as usize - i - 1]);
129 }
130 }
131 }
132
133 let mut res_q14: [i32; MAX_SUB_FRAME_LENGTH] = [0; MAX_SUB_FRAME_LENGTH];
134
135 if eff_signal_type == TYPE_VOICED {
136 let pred_lag_ptr_start = (s_ltp_buf_idx - lag + LTP_ORDER as i32 / 2) as usize;
137 for i in 0..ps_dec.subfr_length as usize {
138 let mut ltp_pred_q13: i32 = 2;
139 ltp_pred_q13 = silk_smlawb(
140 ltp_pred_q13,
141 s_ltp_q15[pred_lag_ptr_start + i],
142 b_q14[0] as i32,
143 );
144 ltp_pred_q13 = silk_smlawb(
145 ltp_pred_q13,
146 s_ltp_q15[pred_lag_ptr_start + i - 1],
147 b_q14[1] as i32,
148 );
149 ltp_pred_q13 = silk_smlawb(
150 ltp_pred_q13,
151 s_ltp_q15[pred_lag_ptr_start + i - 2],
152 b_q14[2] as i32,
153 );
154 ltp_pred_q13 = silk_smlawb(
155 ltp_pred_q13,
156 s_ltp_q15[pred_lag_ptr_start + i - 3],
157 b_q14[3] as i32,
158 );
159 ltp_pred_q13 = silk_smlawb(
160 ltp_pred_q13,
161 s_ltp_q15[pred_lag_ptr_start + i - 4],
162 b_q14[4] as i32,
163 );
164
165 res_q14[i] = silk_add_lshift32(ps_dec.exc_q14[pexc_q14_idx + i], ltp_pred_q13, 1);
166
167 s_ltp_q15[s_ltp_buf_idx as usize] = res_q14[i] << 1;
168 s_ltp_buf_idx += 1;
169 }
170 } else {
171 res_q14[..(ps_dec.subfr_length as usize)].copy_from_slice(
172 &ps_dec.exc_q14[pexc_q14_idx..(ps_dec.subfr_length as usize + pexc_q14_idx)],
173 );
174 }
175
176 for i in 0..ps_dec.subfr_length as usize {
177 let mut lpc_pred_q10: i32 = ps_dec.lpc_order >> 1;
178
179 lpc_pred_q10 = silk_smlawb(
180 lpc_pred_q10,
181 s_lpc_q14[MAX_LPC_ORDER + i - 1],
182 a_q12[0] as i32,
183 );
184 lpc_pred_q10 = silk_smlawb(
185 lpc_pred_q10,
186 s_lpc_q14[MAX_LPC_ORDER + i - 2],
187 a_q12[1] as i32,
188 );
189 lpc_pred_q10 = silk_smlawb(
190 lpc_pred_q10,
191 s_lpc_q14[MAX_LPC_ORDER + i - 3],
192 a_q12[2] as i32,
193 );
194 lpc_pred_q10 = silk_smlawb(
195 lpc_pred_q10,
196 s_lpc_q14[MAX_LPC_ORDER + i - 4],
197 a_q12[3] as i32,
198 );
199 lpc_pred_q10 = silk_smlawb(
200 lpc_pred_q10,
201 s_lpc_q14[MAX_LPC_ORDER + i - 5],
202 a_q12[4] as i32,
203 );
204 lpc_pred_q10 = silk_smlawb(
205 lpc_pred_q10,
206 s_lpc_q14[MAX_LPC_ORDER + i - 6],
207 a_q12[5] as i32,
208 );
209 lpc_pred_q10 = silk_smlawb(
210 lpc_pred_q10,
211 s_lpc_q14[MAX_LPC_ORDER + i - 7],
212 a_q12[6] as i32,
213 );
214 lpc_pred_q10 = silk_smlawb(
215 lpc_pred_q10,
216 s_lpc_q14[MAX_LPC_ORDER + i - 8],
217 a_q12[7] as i32,
218 );
219 lpc_pred_q10 = silk_smlawb(
220 lpc_pred_q10,
221 s_lpc_q14[MAX_LPC_ORDER + i - 9],
222 a_q12[8] as i32,
223 );
224 lpc_pred_q10 = silk_smlawb(
225 lpc_pred_q10,
226 s_lpc_q14[MAX_LPC_ORDER + i - 10],
227 a_q12[9] as i32,
228 );
229
230 if ps_dec.lpc_order == 16 {
231 lpc_pred_q10 = silk_smlawb(
232 lpc_pred_q10,
233 s_lpc_q14[MAX_LPC_ORDER + i - 11],
234 a_q12[10] as i32,
235 );
236 lpc_pred_q10 = silk_smlawb(
237 lpc_pred_q10,
238 s_lpc_q14[MAX_LPC_ORDER + i - 12],
239 a_q12[11] as i32,
240 );
241 lpc_pred_q10 = silk_smlawb(
242 lpc_pred_q10,
243 s_lpc_q14[MAX_LPC_ORDER + i - 13],
244 a_q12[12] as i32,
245 );
246 lpc_pred_q10 = silk_smlawb(
247 lpc_pred_q10,
248 s_lpc_q14[MAX_LPC_ORDER + i - 14],
249 a_q12[13] as i32,
250 );
251 lpc_pred_q10 = silk_smlawb(
252 lpc_pred_q10,
253 s_lpc_q14[MAX_LPC_ORDER + i - 15],
254 a_q12[14] as i32,
255 );
256 lpc_pred_q10 = silk_smlawb(
257 lpc_pred_q10,
258 s_lpc_q14[MAX_LPC_ORDER + i - 16],
259 a_q12[15] as i32,
260 );
261 }
262
263 s_lpc_q14[MAX_LPC_ORDER + i] =
264 silk_add_sat32(res_q14[i], silk_lshift_sat32(lpc_pred_q10, 4));
265
266 let gain_q10 = ps_dec_ctrl.gains_q16[k] >> 6;
267 let product = silk_smulww(s_lpc_q14[MAX_LPC_ORDER + i], gain_q10);
268 xq[pxq_idx + i] = silk_sat16(silk_rshift_round(product, 8)) as i16;
269 }
270
271 for i in 0..MAX_LPC_ORDER {
272 s_lpc_q14[i] = s_lpc_q14[ps_dec.subfr_length as usize + i];
273 }
274 pexc_q14_idx += ps_dec.subfr_length as usize;
275 pxq_idx += ps_dec.subfr_length as usize;
276 }
277
278 ps_dec
279 .s_lpc_q14_buf
280 .copy_from_slice(&s_lpc_q14[..MAX_LPC_ORDER]);
281}
282
283fn silk_lpc_analysis_filter_offset(
284 out: &mut [i16],
285 out_offset: usize,
286 input: &[i16],
287 input_offset: usize,
288 b: &[i16],
289 len: usize,
290 d: usize,
291) {
292 for ix in 0..d {
293 out[out_offset + ix] = 0;
294 }
295
296 for ix in d..len {
297 let mut out32_q12: i32 = 0;
298 for j in 0..d {
299 out32_q12 = out32_q12.wrapping_add(silk_smulbb(
300 input[input_offset + ix - j - 1] as i32,
301 b[j] as i32,
302 ));
303 }
304
305 out32_q12 = ((input[input_offset + ix] as i32) << 12).wrapping_sub(out32_q12);
306
307 let out32 = silk_rshift_round(out32_q12, 12);
308
309 out[out_offset + ix] = silk_sat16(out32) as i16;
310 }
311}