1use crate::silk::define::*;
2use crate::silk::macros::*;
3use crate::silk::sigproc_fix::*;
4use crate::silk::structs::*;
5use crate::silk::tables::*;
6
7#[derive(Copy, Clone)]
8pub struct NSQDelDecStruct {
9 pub s_lpc_q14: [i32; MAX_SUB_FRAME_LENGTH + NSQ_LPC_BUF_LENGTH],
10 pub rand_state: [i32; DECISION_DELAY],
11 pub q_q10: [i32; DECISION_DELAY],
12 pub xq_q14: [i32; DECISION_DELAY],
13 pub pred_q15: [i32; DECISION_DELAY],
14 pub shape_q14: [i32; DECISION_DELAY],
15 pub s_ar2_q14: [i32; MAX_SHAPE_LPC_ORDER],
16 pub lf_ar_q14: i32,
17 pub diff_q14: i32,
18 pub seed: i32,
19 pub seed_init: i32,
20 pub rd_q10: i32,
21}
22
23impl Default for NSQDelDecStruct {
24 fn default() -> Self {
25 Self {
26 s_lpc_q14: [0; MAX_SUB_FRAME_LENGTH + NSQ_LPC_BUF_LENGTH],
27 rand_state: [0; DECISION_DELAY],
28 q_q10: [0; DECISION_DELAY],
29 xq_q14: [0; DECISION_DELAY],
30 pred_q15: [0; DECISION_DELAY],
31 shape_q14: [0; DECISION_DELAY],
32 s_ar2_q14: [0; MAX_SHAPE_LPC_ORDER],
33 lf_ar_q14: 0,
34 diff_q14: 0,
35 seed: 0,
36 seed_init: 0,
37 rd_q10: 0,
38 }
39 }
40}
41
42#[derive(Copy, Clone, Default)]
43pub struct NSQSampleStruct {
44 pub q_q10: i32,
45 pub rd_q10: i32,
46 pub xq_q14: i32,
47 pub lf_ar_q14: i32,
48 pub diff_q14: i32,
49 pub s_ltp_shp_q14: i32,
50 pub lpc_exc_q14: i32,
51}
52
53pub type NSQSamplePair = [NSQSampleStruct; 2];
54
55#[inline]
56fn silk_nsq_del_dec_scale_states(
57 ps_enc_c: &SilkEncoderStateCommon,
58 nsq: &mut SilkNSQState,
59 ps_del_dec: &mut [NSQDelDecStruct],
60 x16: &[i16],
61 x_sc_q10: &mut [i32],
62 s_ltp: &[i16],
63 s_ltp_q15: &mut [i32],
64 subfr: usize,
65 n_states_delayed_decision: i32,
66 ltp_scale_q14: i32,
67 gains_q16: &[i32],
68 pitch_l: &[i32],
69 signal_type: i32,
70 decision_delay: i32,
71) {
72 let lag = pitch_l[subfr] as usize;
73 let inv_gain_q31 = silk_inverse32_varq(gains_q16[subfr].max(1), 47);
74
75 let inv_gain_q26 = silk_rshift_round(inv_gain_q31, 5);
76 let n = ps_enc_c.subfr_length as usize;
77 for (x_out, &x_in) in x_sc_q10[..n].iter_mut().zip(x16[..n].iter()) {
78 *x_out = silk_smulww(x_in as i32, inv_gain_q26);
79 }
80
81 if nsq.rewhite_flag != 0 {
82 let mut inv_gain_q31_scaled = inv_gain_q31;
83 if subfr == 0 {
84 inv_gain_q31_scaled = silk_lshift(silk_smulwb(inv_gain_q31, ltp_scale_q14), 2);
85 }
86 for i in (nsq.s_ltp_buf_idx as usize - lag - LTP_ORDER / 2)..(nsq.s_ltp_buf_idx as usize) {
87 s_ltp_q15[i] = silk_smulwb(inv_gain_q31_scaled, s_ltp[i] as i32);
88 }
89 }
90
91 if gains_q16[subfr] != nsq.prev_gain_q16 {
92 let gain_adj_q16 = silk_div32_varq(nsq.prev_gain_q16, gains_q16[subfr], 16);
93
94 for i in (nsq.s_ltp_shp_buf_idx as usize - ps_enc_c.ltp_mem_length as usize)
95 ..(nsq.s_ltp_shp_buf_idx as usize)
96 {
97 nsq.s_ltp_shp_q14[i] = silk_smulww(gain_adj_q16, nsq.s_ltp_shp_q14[i]);
98 }
99
100 if signal_type == TYPE_VOICED && nsq.rewhite_flag == 0 {
101 let ltp_start = nsq.s_ltp_buf_idx as usize - lag - LTP_ORDER / 2;
102 let ltp_end = nsq.s_ltp_buf_idx as usize - decision_delay as usize;
103 for v in s_ltp_q15[ltp_start..ltp_end].iter_mut() {
104 *v = silk_smulww(gain_adj_q16, *v);
105 }
106 }
107
108 let n_states = (n_states_delayed_decision as usize).min(NSQ_MAX_STATES_OPERATING);
109 for k in 0..n_states {
110 let ps_dd = &mut ps_del_dec[k];
111 ps_dd.lf_ar_q14 = silk_smulww(gain_adj_q16, ps_dd.lf_ar_q14);
112 ps_dd.diff_q14 = silk_smulww(gain_adj_q16, ps_dd.diff_q14);
113 for i in 0..NSQ_LPC_BUF_LENGTH {
114 ps_dd.s_lpc_q14[i] = silk_smulww(gain_adj_q16, ps_dd.s_lpc_q14[i]);
115 }
116 for i in 0..MAX_SHAPE_LPC_ORDER {
117 ps_dd.s_ar2_q14[i] = silk_smulww(gain_adj_q16, ps_dd.s_ar2_q14[i]);
118 }
119 for i in 0..DECISION_DELAY {
120 ps_dd.pred_q15[i] = silk_smulww(gain_adj_q16, ps_dd.pred_q15[i]);
121 ps_dd.shape_q14[i] = silk_smulww(gain_adj_q16, ps_dd.shape_q14[i]);
122 }
123 }
124 nsq.prev_gain_q16 = gains_q16[subfr];
125 }
126}
127
128#[cfg(target_arch = "aarch64")]
129#[inline(always)]
130#[allow(unsafe_op_in_unsafe_fn)]
131unsafe fn silk_lpc_prediction_neon(
132 ps_lpc_q14: &[i32],
133 idx: usize,
134 a_q12: &[i16],
135 predict_lpc_order: i32,
136) -> i32 {
137 use std::arch::aarch64::*;
138
139 let order = predict_lpc_order as usize;
140 let lpc_base = ps_lpc_q14.as_ptr().add(idx);
141 let a_ptr = a_q12.as_ptr();
142
143 let mut acc = vdupq_n_s32(0i32);
144 let neon_taps = order & !3;
145
146 let mut j = 0usize;
147 while j < neon_taps {
148 let lpc_asc = vld1q_s32(lpc_base.sub(j + 3));
149
150 let coef_narrow = vld1_s16(a_ptr.add(j));
151 let coef_wide = vmovl_s16(coef_narrow);
152
153 let coef_rev = vrev64q_s32(vcombine_s32(
154 vget_high_s32(coef_wide),
155 vget_low_s32(coef_wide),
156 ));
157
158 let prod_lo = vmull_s32(vget_low_s32(lpc_asc), vget_low_s32(coef_rev));
159 let prod_hi = vmull_s32(vget_high_s32(lpc_asc), vget_high_s32(coef_rev));
160
161 let shr_lo = vshrn_n_s64::<16>(prod_lo); let shr_hi = vshrn_n_s64::<16>(prod_hi); acc = vaddq_s32(acc, vcombine_s32(shr_lo, shr_hi));
165 j += 4;
166 }
167
168 let mut out = silk_rshift(predict_lpc_order, 1) + vaddvq_s32(acc);
169
170 while j < order {
171 out = silk_smlawb(out, ps_lpc_q14[idx - j], a_q12[j] as i32);
172 j += 1;
173 }
174
175 out
176}
177
178#[inline]
179#[cfg(target_arch = "x86_64")]
192#[target_feature(enable = "avx2")]
193unsafe fn silk_lpc_prediction_avx2(
194 ps_lpc_q14: &[i32],
195 idx: usize,
196 a_q12: &[i16],
197 predict_lpc_order: i32,
198) -> i32 {
199 use core::arch::x86_64::*;
200
201 let order = predict_lpc_order as usize;
202 let lpc = ps_lpc_q14.as_ptr();
203 let mut acc_e = _mm256_setzero_si256();
207 let mut acc_o = _mm256_setzero_si256();
208 let asr16 = |x: __m256i| -> __m256i {
210 let sign = _mm256_cmpgt_epi64(_mm256_setzero_si256(), x); let fill = _mm256_slli_epi64(sign, 64 - 16);
212 _mm256_or_si256(_mm256_srli_epi64(x, 16), fill)
213 };
214
215 let mut j = 0usize;
216 let main = order & !7; while j < main {
218 let l = _mm256_loadu_si256(lpc.add(idx - j - 7) as *const __m256i);
222 let c16 = _mm_loadu_si128(a_q12.as_ptr().add(j) as *const __m128i);
223 let c = _mm256_cvtepi16_epi32(c16); let crev = _mm256_permutevar8x32_epi32(c, _mm256_setr_epi32(7, 6, 5, 4, 3, 2, 1, 0));
225
226 let pe = _mm256_mul_epi32(l, crev);
228 let lo = _mm256_shuffle_epi32(l, 0b11_11_01_01);
229 let co = _mm256_shuffle_epi32(crev, 0b11_11_01_01);
230 let po = _mm256_mul_epi32(lo, co);
231
232 acc_e = _mm256_add_epi64(acc_e, asr16(pe));
233 acc_o = _mm256_add_epi64(acc_o, asr16(po));
234 j += 8;
235 }
236
237 let s = _mm256_add_epi64(acc_e, acc_o); let s2 = _mm_add_epi64(
240 _mm256_castsi256_si128(s),
241 _mm256_extracti128_si256(s, 1),
242 ); let s3 = _mm_add_epi64(s2, _mm_unpackhi_epi64(s2, s2)); let mut out = silk_rshift(predict_lpc_order, 1).wrapping_add(_mm_cvtsi128_si32(s3));
245
246 while j < order {
247 out = silk_smlawb(out, ps_lpc_q14[idx - j], a_q12[j] as i32);
248 j += 1;
249 }
250 out
251}
252
253#[cfg(target_arch = "x86_64")]
257#[inline(always)]
258fn lpc_avx2_enabled() -> bool {
259 use std::sync::atomic::{AtomicU8, Ordering};
260 static STATE: AtomicU8 = AtomicU8::new(0); match STATE.load(Ordering::Relaxed) {
262 1 => true,
263 2 => false,
264 _ => {
265 let on = is_x86_feature_detected!("avx2")
266 && std::env::var_os("RUSTY_OPUS_NO_AVX2").is_none();
267 STATE.store(if on { 1 } else { 2 }, Ordering::Relaxed);
268 on
269 }
270 }
271}
272
273#[inline(always)]
274fn silk_lpc_prediction_scalar(
275 ps_lpc_q14: &[i32],
276 idx: usize,
277 a_q12: &[i16],
278 predict_lpc_order: i32,
279) -> i32 {
280 let mut out = silk_rshift(predict_lpc_order, 1);
281 for j in 0..predict_lpc_order as usize {
282 out = silk_smlawb(out, ps_lpc_q14[idx - j], a_q12[j] as i32);
283 }
284 out
285}
286
287fn silk_noise_shape_quantizer_short_prediction(
288 ps_lpc_q14: &[i32],
289 idx: usize,
290 a_q12: &[i16],
291 predict_lpc_order: i32,
292) -> i32 {
293 #[cfg(target_arch = "aarch64")]
294 unsafe {
296 return silk_lpc_prediction_neon(ps_lpc_q14, idx, a_q12, predict_lpc_order);
297 }
298 #[cfg(target_arch = "x86_64")]
299 {
300 if lpc_avx2_enabled() && idx + 1 >= predict_lpc_order as usize {
303 return unsafe {
305 silk_lpc_prediction_avx2(ps_lpc_q14, idx, a_q12, predict_lpc_order)
306 };
307 }
308 }
309 #[allow(unreachable_code)]
310 silk_lpc_prediction_scalar(ps_lpc_q14, idx, a_q12, predict_lpc_order)
311}
312
313#[cfg(target_arch = "x86_64")]
316#[inline(always)]
317fn nsq_shape_avx2_enabled() -> bool {
318 use std::sync::atomic::{AtomicU8, Ordering};
319 static STATE: AtomicU8 = AtomicU8::new(0);
320 match STATE.load(Ordering::Relaxed) {
321 1 => true,
322 2 => false,
323 _ => {
324 let on = is_x86_feature_detected!("avx2")
325 && std::env::var_os("RUSTY_OPUS_NO_AVX2").is_none()
326 && std::env::var_os("RUSTY_OPUS_NO_NSQ_AVX2").is_none();
327 STATE.store(if on { 1 } else { 2 }, Ordering::Relaxed);
328 on
329 }
330 }
331}
332
333#[inline(always)]
337fn nsq_shape_filter_soa_scalar(
338 sar: &mut [[i32; 4]],
339 diff: &[i32; 4],
340 warp: i32,
341 ar_shp_q13: &[i16],
342 order: usize,
343 base: i32,
344 n_ar: &mut [i32; 4],
345) {
346 for k in 0..4 {
347 let mut tmp2 = silk_smlawb(diff[k], sar[0][k], warp);
348 let mut tmp1 = silk_smlawb(sar[0][k], silk_sub32_ovflw(sar[1][k], tmp2), warp);
349 sar[0][k] = tmp2;
350 let mut acc = silk_smlawb(base, tmp2, ar_shp_q13[0] as i32);
351 let mut j = 2;
352 while j < order {
353 tmp2 = silk_smlawb(sar[j - 1][k], silk_sub32_ovflw(sar[j][k], tmp1), warp);
354 sar[j - 1][k] = tmp1;
355 acc = silk_smlawb(acc, tmp1, ar_shp_q13[j - 1] as i32);
356 tmp1 = silk_smlawb(sar[j][k], silk_sub32_ovflw(sar[j + 1][k], tmp2), warp);
357 sar[j][k] = tmp2;
358 acc = silk_smlawb(acc, tmp2, ar_shp_q13[j] as i32);
359 j += 2;
360 }
361 sar[order - 1][k] = tmp1;
362 n_ar[k] = silk_smlawb(acc, tmp1, ar_shp_q13[order - 1] as i32);
363 }
364}
365
366#[cfg(target_arch = "x86_64")]
375#[target_feature(enable = "avx2")]
376unsafe fn nsq_shape_filter_soa_avx2(
377 sar: &mut [[i32; 4]],
378 diff: &[i32; 4],
379 warp: i32,
380 ar_shp_q13: &[i16],
381 order: usize,
382 base: i32,
383 n_ar: &mut [i32; 4],
384) {
385 use core::arch::x86_64::*;
386 let wb = _mm256_set1_epi64x(warp as i64);
387 let asr16 = |x: __m256i| {
388 let s = _mm256_cmpgt_epi64(_mm256_setzero_si256(), x);
389 _mm256_or_si256(_mm256_srli_epi64(x, 16), _mm256_slli_epi64(s, 48))
390 };
391 let smlawb_v =
392 |a: __m256i, b: __m256i, cb: __m256i| _mm256_add_epi64(a, asr16(_mm256_mul_epi32(b, cb)));
393 let ldv = |p: &[i32; 4]| _mm256_cvtepi32_epi64(_mm_loadu_si128(p.as_ptr() as *const __m128i));
394 let stv = |p: &mut [i32; 4], v: __m256i| {
395 let g = _mm256_permutevar8x32_epi32(v, _mm256_setr_epi32(0, 2, 4, 6, 0, 2, 4, 6));
396 _mm_storeu_si128(p.as_mut_ptr() as *mut __m128i, _mm256_castsi256_si128(g));
397 };
398 let cbv = |c: i32| _mm256_set1_epi64x(c as i16 as i64);
399
400 let mut vsar = [_mm256_setzero_si256(); MAX_SHAPE_LPC_ORDER];
402 for j in 0..order {
403 vsar[j] = ldv(&sar[j]);
404 }
405 let vdiff = ldv(diff);
406 let mut tmp2 = smlawb_v(vdiff, vsar[0], wb);
407 let mut tmp1 = smlawb_v(vsar[0], _mm256_sub_epi64(vsar[1], tmp2), wb);
408 vsar[0] = tmp2;
409 let mut acc = smlawb_v(_mm256_set1_epi64x(base as i64), tmp2, cbv(ar_shp_q13[0] as i32));
410 let mut j = 2;
411 while j < order {
412 tmp2 = smlawb_v(vsar[j - 1], _mm256_sub_epi64(vsar[j], tmp1), wb);
413 vsar[j - 1] = tmp1;
414 acc = smlawb_v(acc, tmp1, cbv(ar_shp_q13[j - 1] as i32));
415 tmp1 = smlawb_v(vsar[j], _mm256_sub_epi64(vsar[j + 1], tmp2), wb);
416 vsar[j] = tmp2;
417 acc = smlawb_v(acc, tmp2, cbv(ar_shp_q13[j] as i32));
418 j += 2;
419 }
420 vsar[order - 1] = tmp1;
421 acc = smlawb_v(acc, tmp1, cbv(ar_shp_q13[order - 1] as i32));
422 for j in 0..order {
423 stv(&mut sar[j], vsar[j]);
424 }
425 stv(n_ar, acc);
426}
427
428#[inline(always)]
429fn nsq_shape_filter_soa(
430 sar: &mut [[i32; 4]],
431 diff: &[i32; 4],
432 warp: i32,
433 ar_shp_q13: &[i16],
434 order: usize,
435 base: i32,
436 n_ar: &mut [i32; 4],
437) {
438 #[cfg(target_arch = "x86_64")]
439 {
440 if nsq_shape_avx2_enabled() {
441 unsafe { nsq_shape_filter_soa_avx2(sar, diff, warp, ar_shp_q13, order, base, n_ar) };
443 return;
444 }
445 }
446 nsq_shape_filter_soa_scalar(sar, diff, warp, ar_shp_q13, order, base, n_ar);
447}
448
449#[cfg(all(test, target_arch = "x86_64"))]
450mod lpc_pred_avx2_tests {
451 use super::*;
452
453 #[test]
456 fn avx2_matches_scalar() {
457 if !is_x86_feature_detected!("avx2") {
458 return;
459 }
460 let mut s: u64 = 0x1234_5678_9abc_def1;
462 let mut rng = || {
463 s ^= s << 13;
464 s ^= s >> 7;
465 s ^= s << 17;
466 s
467 };
468 for order in [10usize, 12, 14, 16] {
469 for _ in 0..50_000 {
470 let mut lpc = [0i32; 64];
472 for v in lpc.iter_mut() {
473 *v = (rng() as i32) >> (rng() as u32 % 12);
475 }
476 let mut a = [0i16; 16];
477 for v in a.iter_mut().take(order) {
478 *v = (rng() as i16) >> (rng() as u32 % 3);
479 }
480 let idx = 32 + (rng() as usize % 16);
481 let got = unsafe {
482 silk_lpc_prediction_avx2(&lpc, idx, &a, order as i32)
483 };
484 let want = silk_lpc_prediction_scalar(&lpc, idx, &a, order as i32);
485 assert_eq!(got, want, "order={order} idx={idx}");
486 }
487 }
488 }
489
490 #[test]
495 fn nsq_shape_filter_avx2_matches_scalar() {
496 if !is_x86_feature_detected!("avx2") {
497 return;
498 }
499 let mut s: u64 = 0xC0FF_EE00_1234_5678;
500 let mut rng = || {
501 s ^= s << 13;
502 s ^= s >> 7;
503 s ^= s << 17;
504 s
505 };
506 for order in [16usize, 24] {
507 for _ in 0..20_000 {
508 let sh = 6 + (rng() % 20) as u32;
509 let mut sar_a = vec![[0i32; 4]; order];
510 for row in sar_a.iter_mut() {
511 for v in row.iter_mut() {
512 *v = (rng() as i32) >> sh;
513 }
514 }
515 let mut sar_b = sar_a.clone();
516 let diff = [
517 (rng() as i32) >> sh,
518 (rng() as i32) >> sh,
519 (rng() as i32) >> sh,
520 (rng() as i32) >> sh,
521 ];
522 let ar: Vec<i16> = (0..order).map(|_| (rng() >> 8) as i16).collect();
523 let warp = 13421;
524 let base = (order as i32) >> 1;
525 let mut na = [0i32; 4];
526 let mut nb = [0i32; 4];
527 nsq_shape_filter_soa_scalar(&mut sar_a, &diff, warp, &ar, order, base, &mut na);
528 unsafe {
529 nsq_shape_filter_soa_avx2(&mut sar_b, &diff, warp, &ar, order, base, &mut nb)
530 };
531 assert_eq!(na, nb, "n_ar mismatch order={order} sh={sh}");
532 assert_eq!(sar_a, sar_b, "sar mismatch order={order} sh={sh}");
533 }
534 }
535 }
536}
537
538pub fn silk_noise_shape_quantizer_del_dec(
539 nsq: &mut SilkNSQState,
540 ps_del_dec: &mut [NSQDelDecStruct],
541 signal_type: i32,
542 x_q10: &[i32],
543 pulses: &mut [i8],
544 pulses_offset: i32,
545 xq_ptr: i32,
546 s_ltp_q15: &mut [i32],
547 delayed_ga_q10: &mut [i32],
548 a_q12: &[i16],
549 b_q14: &[i16],
550 ar_shp_q13: &[i16],
551 lag: i32,
552 harm_shape_fir_packed_q14: i32,
553 tilt_q14: i32,
554 lf_shp_q14: i32,
555 gain_q16: i32,
556 lambda_q10: i32,
557 offset_q10: i32,
558 length: i32,
559 subfr: i32,
560 shaping_lpc_order: i32,
561 predict_lpc_order: i32,
562 warping_q16: i32,
563 n_states_delayed_decision: i32,
564 smpl_buf_idx: &mut i32,
565 decision_delay: i32,
566 _frame_counter: i32,
567) {
568 let mut ps_sample_state = [[NSQSampleStruct::default(); 2]; NSQ_MAX_STATES_OPERATING];
569 let gain_q10 = silk_rshift(gain_q16, 6);
570
571 let n_states = (n_states_delayed_decision as usize).min(NSQ_MAX_STATES_OPERATING);
572
573 let pred_lag_ptr_base = nsq.s_ltp_buf_idx - lag + LTP_ORDER as i32 / 2;
574 let shp_lag_ptr_base = nsq.s_ltp_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS as i32 / 2;
575
576 let shp_ord = shaping_lpc_order as usize;
582 let shp_base = silk_rshift(shaping_lpc_order, 1);
583 let mut sar_soa = [[0i32; 4]; MAX_SHAPE_LPC_ORDER];
584 for k in 0..n_states {
585 for j in 0..shp_ord {
586 sar_soa[j][k] = ps_del_dec[k].s_ar2_q14[j];
587 }
588 }
589
590 for i in 0..length {
591 let idx = i as usize;
592 let mut ltp_pred_q14 = 0;
593 if signal_type == TYPE_VOICED {
594 let pred_lag_idx_calc = pred_lag_ptr_base + i;
595 if pred_lag_idx_calc >= LTP_ORDER as i32 && pred_lag_idx_calc < s_ltp_q15.len() as i32 {
596 let pred_lag_idx = pred_lag_idx_calc as usize;
597 ltp_pred_q14 = 2;
598 ltp_pred_q14 = silk_smlawb(ltp_pred_q14, s_ltp_q15[pred_lag_idx], b_q14[0] as i32);
599 ltp_pred_q14 =
600 silk_smlawb(ltp_pred_q14, s_ltp_q15[pred_lag_idx - 1], b_q14[1] as i32);
601 ltp_pred_q14 =
602 silk_smlawb(ltp_pred_q14, s_ltp_q15[pred_lag_idx - 2], b_q14[2] as i32);
603 ltp_pred_q14 =
604 silk_smlawb(ltp_pred_q14, s_ltp_q15[pred_lag_idx - 3], b_q14[3] as i32);
605 ltp_pred_q14 =
606 silk_smlawb(ltp_pred_q14, s_ltp_q15[pred_lag_idx - 4], b_q14[4] as i32);
607 ltp_pred_q14 = silk_lshift(ltp_pred_q14, 1);
608 }
609 }
610
611 let mut n_ltp_q14 = 0;
612 if lag > 0 {
613 let shp_lag_idx_calc = shp_lag_ptr_base + i;
614 if shp_lag_idx_calc >= HARM_SHAPE_FIR_TAPS as i32
615 && shp_lag_idx_calc < nsq.s_ltp_shp_q14.len() as i32
616 {
617 let shp_lag_idx = shp_lag_idx_calc as usize;
618 n_ltp_q14 = silk_smulwb(
619 silk_add_sat32(
620 nsq.s_ltp_shp_q14[shp_lag_idx],
621 nsq.s_ltp_shp_q14[shp_lag_idx - 2],
622 ),
623 harm_shape_fir_packed_q14,
624 );
625 n_ltp_q14 = silk_smlawt(
626 n_ltp_q14,
627 nsq.s_ltp_shp_q14[shp_lag_idx - 1],
628 harm_shape_fir_packed_q14,
629 );
630 n_ltp_q14 = silk_sub_lshift32(ltp_pred_q14, n_ltp_q14, 2);
631 }
632 }
633
634 let mut lpc_pred_arr = [0i32; NSQ_MAX_STATES_OPERATING];
639 let mut n_ar_arr = [0i32; NSQ_MAX_STATES_OPERATING];
640 let mut n_lf_arr = [0i32; NSQ_MAX_STATES_OPERATING];
641 let mut diff_arr = [0i32; 4];
642 for k in 0..n_states {
643 let ps_dd = &mut ps_del_dec[k];
644 ps_dd.seed = silk_rand(ps_dd.seed);
645 let ps_lpc_q14_idx = NSQ_LPC_BUF_LENGTH - 1 + idx;
646 lpc_pred_arr[k] = silk_lshift(
647 silk_noise_shape_quantizer_short_prediction(
648 &ps_dd.s_lpc_q14,
649 ps_lpc_q14_idx,
650 a_q12,
651 predict_lpc_order,
652 ),
653 4,
654 );
655 diff_arr[k] = ps_dd.diff_q14;
656 }
657 let mut n_ar_raw = [0i32; 4];
658 nsq_shape_filter_soa(
659 &mut sar_soa,
660 &diff_arr,
661 warping_q16,
662 ar_shp_q13,
663 shp_ord,
664 shp_base,
665 &mut n_ar_raw,
666 );
667 let smpl_idx = (*smpl_buf_idx as usize).min(DECISION_DELAY - 1);
668 for k in 0..n_states {
669 let ps_dd = &ps_del_dec[k];
670 let mut n_ar_q14 = silk_lshift(n_ar_raw[k], 1);
671 n_ar_q14 = silk_smlawb(n_ar_q14, ps_dd.lf_ar_q14, tilt_q14);
672 n_ar_q14 = silk_lshift(n_ar_q14, 2);
673 n_ar_arr[k] = n_ar_q14;
674 let mut n_lf_q14 = silk_smulwb(ps_dd.shape_q14[smpl_idx], lf_shp_q14);
675 n_lf_q14 = silk_smlawt(n_lf_q14, ps_dd.lf_ar_q14, lf_shp_q14);
676 n_lf_q14 = silk_lshift(n_lf_q14, 2);
677 n_lf_arr[k] = n_lf_q14;
678 }
679
680 for k in 0..n_states {
682 let ps_dd = &mut ps_del_dec[k];
683 let ps_ss = &mut ps_sample_state[k];
684 let lpc_pred_q14 = lpc_pred_arr[k];
685 let n_ar_q14 = n_ar_arr[k];
686 let n_lf_q14 = n_lf_arr[k];
687
688 let tmp1_val = silk_sub_sat32(
689 silk_add32_ovflw(n_ltp_q14, lpc_pred_q14),
690 silk_add_sat32(n_ar_q14, n_lf_q14),
691 );
692 let r_q10 = x_q10[idx] - silk_rshift_round(tmp1_val, 4);
693
694 let r_q10_signed = if ps_dd.seed < 0 { -r_q10 } else { r_q10 };
695 let r_q10_signed = silk_limit_32(r_q10_signed, -(31 << 10), 30 << 10);
696
697 let q1_q10_in = r_q10_signed - offset_q10;
698 let mut q1_q0 = silk_rshift(q1_q10_in, 10);
699 if lambda_q10 > 2048 {
700 let rdo_offset = lambda_q10 / 2 - 512;
701 if q1_q10_in > rdo_offset {
702 q1_q0 = silk_rshift(q1_q10_in - rdo_offset, 10);
703 } else if q1_q10_in < -rdo_offset {
704 q1_q0 = silk_rshift(q1_q10_in + rdo_offset, 10);
705 } else if q1_q10_in < 0 {
706 q1_q0 = -1;
707 } else {
708 q1_q0 = 0;
709 }
710 }
711
712 let (rd1_q10, rd2_q10, q1_q10_val, q2_q10_val);
713 if q1_q0 > 0 {
714 q1_q10_val =
715 silk_sub32(silk_lshift(q1_q0, 10), QUANT_LEVEL_ADJUST_Q10) + offset_q10;
716 q2_q10_val = q1_q10_val + 1024;
717 rd1_q10 = silk_smulbb(q1_q10_val, lambda_q10);
718 rd2_q10 = silk_smulbb(q2_q10_val, lambda_q10);
719 } else if q1_q0 == 0 {
720 q1_q10_val = offset_q10;
721 q2_q10_val = q1_q10_val + 1024 - QUANT_LEVEL_ADJUST_Q10;
722 rd1_q10 = silk_smulbb(q1_q10_val, lambda_q10);
723 rd2_q10 = silk_smulbb(q2_q10_val, lambda_q10);
724 } else if q1_q0 == -1 {
725 q2_q10_val = offset_q10;
726 q1_q10_val = q2_q10_val - (1024 - QUANT_LEVEL_ADJUST_Q10);
727 rd1_q10 = silk_smulbb(-q1_q10_val, lambda_q10);
728 rd2_q10 = silk_smulbb(q2_q10_val, lambda_q10);
729 } else {
730 q1_q10_val =
731 silk_add32(silk_lshift(q1_q0, 10), QUANT_LEVEL_ADJUST_Q10) + offset_q10;
732 q2_q10_val = q1_q10_val + 1024;
733 rd1_q10 = silk_smulbb(-q1_q10_val, lambda_q10);
734 rd2_q10 = silk_smulbb(-q2_q10_val, lambda_q10);
735 }
736
737 let mut rr_q10 = r_q10_signed - q1_q10_val;
738 let rd1_q10_final = silk_rshift(silk_smlabb(rd1_q10, rr_q10, rr_q10), 10);
739 rr_q10 = r_q10_signed - q2_q10_val;
740 let rd2_q10_final = silk_rshift(silk_smlabb(rd2_q10, rr_q10, rr_q10), 10);
741
742 if rd1_q10_final < rd2_q10_final {
743 ps_ss[0].rd_q10 = ps_dd.rd_q10 + rd1_q10_final;
744 ps_ss[1].rd_q10 = ps_dd.rd_q10 + rd2_q10_final;
745 ps_ss[0].q_q10 = q1_q10_val;
746 ps_ss[1].q_q10 = q2_q10_val;
747 } else {
748 ps_ss[0].rd_q10 = ps_dd.rd_q10 + rd2_q10_final;
749 ps_ss[1].rd_q10 = ps_dd.rd_q10 + rd1_q10_final;
750 ps_ss[0].q_q10 = q2_q10_val;
751 ps_ss[1].q_q10 = q1_q10_val;
752 }
753
754 for j in 0..2 {
755 let mut exc_q14 = silk_lshift(ps_ss[j].q_q10, 4);
756 if ps_dd.seed < 0 {
757 exc_q14 = -exc_q14;
758 }
759 let lpc_exc_q14 = silk_add32(exc_q14, ltp_pred_q14);
760 let xq_q14 = silk_add32_ovflw(lpc_exc_q14, lpc_pred_q14);
761 ps_ss[j].diff_q14 = silk_sub32_ovflw(xq_q14, silk_lshift(x_q10[idx], 4));
762 let s_lf_ar_shp_q14 = silk_sub32_ovflw(ps_ss[j].diff_q14, n_ar_q14);
763 ps_ss[j].s_ltp_shp_q14 = silk_sub_sat32(s_lf_ar_shp_q14, n_lf_q14);
764 ps_ss[j].lf_ar_q14 = s_lf_ar_shp_q14;
765 ps_ss[j].lpc_exc_q14 = lpc_exc_q14;
766 ps_ss[j].xq_q14 = xq_q14;
767 }
768 }
769
770 *smpl_buf_idx = (*smpl_buf_idx - 1 + DECISION_DELAY as i32) % DECISION_DELAY as i32;
771 let last_smple_idx = ((*smpl_buf_idx + decision_delay) % DECISION_DELAY as i32) as usize;
772
773 let mut winner_ind = 0;
774 let mut rd_min_q10 = ps_sample_state[0][0].rd_q10;
775 for k in 1..n_states {
776 if ps_sample_state[k][0].rd_q10 < rd_min_q10 {
777 rd_min_q10 = ps_sample_state[k][0].rd_q10;
778 winner_ind = k;
779 }
780 }
781
782 let winner_rand_state = ps_del_dec[winner_ind].rand_state[last_smple_idx];
783 for k in 0..n_states {
784 if ps_del_dec[k].rand_state[last_smple_idx] != winner_rand_state {
785 ps_sample_state[k][0].rd_q10 =
786 ps_sample_state[k][0].rd_q10.saturating_add(i32::MAX >> 4);
787 ps_sample_state[k][1].rd_q10 =
788 ps_sample_state[k][1].rd_q10.saturating_add(i32::MAX >> 4);
789 }
790 }
791
792 let mut rd_max_q10 = ps_sample_state[0][0].rd_q10;
793 let mut rd_max_ind = 0;
794 let mut rd_min_q10_2 = ps_sample_state[0][1].rd_q10;
795 let mut rd_min_ind = 0;
796 for k in 1..n_states {
797 if ps_sample_state[k][0].rd_q10 > rd_max_q10 {
798 rd_max_q10 = ps_sample_state[k][0].rd_q10;
799 rd_max_ind = k;
800 }
801 if ps_sample_state[k][1].rd_q10 < rd_min_q10_2 {
802 rd_min_q10_2 = ps_sample_state[k][1].rd_q10;
803 rd_min_ind = k;
804 }
805 }
806
807 if rd_min_q10_2 < rd_max_q10 {
808 if rd_min_ind != rd_max_ind {
809 let (min_state, max_state) = if rd_min_ind < rd_max_ind {
810 let (left, right) = ps_del_dec.split_at_mut(rd_max_ind);
811 (&left[rd_min_ind], &mut right[0])
812 } else {
813 let (left, right) = ps_del_dec.split_at_mut(rd_min_ind);
814 (&right[0], &mut left[rd_max_ind])
815 };
816 max_state.s_lpc_q14[idx..].copy_from_slice(&min_state.s_lpc_q14[idx..]);
817 max_state.rand_state = min_state.rand_state;
818 max_state.q_q10 = min_state.q_q10;
819 max_state.xq_q14 = min_state.xq_q14;
820 max_state.pred_q15 = min_state.pred_q15;
821 max_state.shape_q14 = min_state.shape_q14;
822 max_state.lf_ar_q14 = min_state.lf_ar_q14;
823 max_state.diff_q14 = min_state.diff_q14;
824 max_state.seed = min_state.seed;
825 max_state.seed_init = min_state.seed_init;
826 max_state.rd_q10 = min_state.rd_q10;
827 for j in 0..shp_ord {
829 sar_soa[j][rd_max_ind] = sar_soa[j][rd_min_ind];
830 }
831 }
832
833 ps_sample_state[rd_max_ind][0] = ps_sample_state[rd_min_ind][1];
834 }
835
836 let ps_dd = &ps_del_dec[winner_ind];
837 if subfr > 0 || i >= decision_delay {
838 let pulse_idx = (pulses_offset + i - decision_delay) as isize;
839 let xq_idx = (xq_ptr + i - decision_delay) as isize;
840 let shp_idx = (nsq.s_ltp_shp_buf_idx - decision_delay) as isize;
841 let ltp_idx = (nsq.s_ltp_buf_idx - decision_delay) as isize;
842
843 if pulse_idx >= 0 && pulse_idx < pulses.len() as isize {
844 pulses[pulse_idx as usize] =
845 silk_rshift_round(ps_dd.q_q10[last_smple_idx], 10) as i8;
846 }
847 if xq_idx >= 0 && xq_idx < nsq.xq.len() as isize {
848 nsq.xq[xq_idx as usize] = silk_sat16(silk_rshift_round(
849 silk_smulww(ps_dd.xq_q14[last_smple_idx], delayed_ga_q10[last_smple_idx]),
850 8,
851 )) as i16;
852 }
853 if shp_idx >= 0 && shp_idx < nsq.s_ltp_shp_q14.len() as isize {
854 nsq.s_ltp_shp_q14[shp_idx as usize] = ps_dd.shape_q14[last_smple_idx];
855 }
856 if ltp_idx >= 0 && ltp_idx < s_ltp_q15.len() as isize {
857 s_ltp_q15[ltp_idx as usize] = ps_dd.pred_q15[last_smple_idx];
858 }
859 }
860 nsq.s_ltp_shp_buf_idx += 1;
861 nsq.s_ltp_buf_idx += 1;
862
863 for k in 0..n_states {
864 let ps_ss = &ps_sample_state[k][0];
865 let ps_dd = &mut ps_del_dec[k];
866 ps_dd.lf_ar_q14 = ps_ss.lf_ar_q14;
867 ps_dd.diff_q14 = ps_ss.diff_q14;
868
869 let lpc_idx = NSQ_LPC_BUF_LENGTH + idx;
870 if lpc_idx < ps_dd.s_lpc_q14.len() {
871 ps_dd.s_lpc_q14[lpc_idx] = ps_ss.xq_q14;
872 }
873 let smpl_idx = (*smpl_buf_idx as usize).min(DECISION_DELAY - 1);
874 ps_dd.xq_q14[smpl_idx] = ps_ss.xq_q14;
875 ps_dd.q_q10[smpl_idx] = ps_ss.q_q10;
876 ps_dd.pred_q15[smpl_idx] = silk_lshift(ps_ss.lpc_exc_q14, 1);
877 ps_dd.shape_q14[smpl_idx] = ps_ss.s_ltp_shp_q14;
878 ps_dd.seed = silk_add32_ovflw(ps_dd.seed, silk_rshift_round(ps_ss.q_q10, 10));
879 ps_dd.rand_state[smpl_idx] = ps_dd.seed;
880 ps_dd.rd_q10 = ps_ss.rd_q10;
881 }
882 let smpl_idx = (*smpl_buf_idx as usize).min(DECISION_DELAY - 1);
883 delayed_ga_q10[smpl_idx] = gain_q10;
884 }
885 for k in 0..n_states {
888 for j in 0..shp_ord {
889 ps_del_dec[k].s_ar2_q14[j] = sar_soa[j][k];
890 }
891 }
892 for k in 0..n_states {
893 let ps_dd = &mut ps_del_dec[k];
894 let mut tmp = [0i32; NSQ_LPC_BUF_LENGTH];
895 tmp.copy_from_slice(
896 &ps_dd.s_lpc_q14[length as usize..length as usize + NSQ_LPC_BUF_LENGTH],
897 );
898 ps_dd.s_lpc_q14[..NSQ_LPC_BUF_LENGTH].copy_from_slice(&tmp);
899 }
900}
901
902pub fn silk_nsq_del_dec(
903 ps_common: &SilkEncoderStateCommon,
904 ps_nsq: &mut SilkNSQState,
905 ps_indices: &SideInfoIndices,
906
907 x16: &[i16],
908 pulses: &mut [i8],
909 pred_coef_q12: &[i16],
910 ltp_coef_q14: &[i16],
911 ar_q13: &[i16],
912 harm_shape_gain_q14: &[i32],
913 tilt_q14: &[i32],
914 lf_shp_q14: &[i32],
915 gains_q16: &[i32],
916 pitch_l: &[i32],
917 lambda_q10: i32,
918 ltp_scale_q14: i32,
919) -> i32 {
920 let _prof = crate::prof::scope(crate::prof::Stage::SilkNsq);
921 let mut x_sc_q10 = [0i32; MAX_SUB_FRAME_LENGTH];
922 let mut delayed_ga_q10 = [0i32; DECISION_DELAY];
923 let mut s_ltp_q15 = [0i32; LTP_MEM_LENGTH_MS * MAX_FS_KHZ + MAX_FRAME_LENGTH];
924 let mut s_ltp = [0i16; LTP_MEM_LENGTH_MS * MAX_FS_KHZ + MAX_FRAME_LENGTH];
925 let mut ps_del_dec = [NSQDelDecStruct::default(); NSQ_MAX_STATES_OPERATING];
926
927 let mut lag = ps_nsq.lag_prev;
928
929 let n_states = (ps_common.n_states_delayed_decision as usize).min(NSQ_MAX_STATES_OPERATING);
930
931 for k in 0..n_states {
932 let ps_dd = &mut ps_del_dec[k];
933 ps_dd.seed = (k as i32 + ps_indices.seed as i32) & 3;
934 ps_dd.seed_init = ps_dd.seed;
935 ps_dd.rd_q10 = 0;
936 ps_dd.lf_ar_q14 = ps_nsq.s_lf_ar_q14;
937 ps_dd.diff_q14 = ps_nsq.s_diff_shp_q14;
938
939 if ps_common.ltp_mem_length > 0 {
940 ps_dd.shape_q14[0] = ps_nsq.s_ltp_shp_q14[ps_common.ltp_mem_length as usize - 1];
941 }
942 ps_dd.s_lpc_q14[..NSQ_LPC_BUF_LENGTH]
943 .copy_from_slice(&ps_nsq.s_lpc_q14[..NSQ_LPC_BUF_LENGTH]);
944 ps_dd.s_ar2_q14.copy_from_slice(&ps_nsq.s_ar2_q14);
945 }
946
947 let offset_q10 = SILK_QUANT_OFFSETS_Q10[(ps_indices.signal_type >> 1) as usize]
948 [ps_indices.quant_offset_type as usize] as i32;
949 let mut smpl_buf_idx = 0i32;
950 let mut decision_delay = (DECISION_DELAY as i32).min(ps_common.subfr_length);
951
952 if ps_indices.signal_type as i32 == TYPE_VOICED {
953 for k in 0..ps_common.nb_subfr as usize {
954 let pitch_constraint = pitch_l[k] - LTP_ORDER as i32 / 2 - 1;
955 if pitch_constraint > 0 {
956 decision_delay = decision_delay.min(pitch_constraint);
957 }
958 }
959 } else if lag > 0 {
960 let lag_constraint = lag - LTP_ORDER as i32 / 2 - 1;
961 if lag_constraint > 0 {
962 decision_delay = decision_delay.min(lag_constraint);
963 }
964 }
965
966 let lsf_interpolation_flag = if ps_indices.nlsf_interp_coef_q2 == 4 {
967 0
968 } else {
969 1
970 };
971
972 ps_nsq.s_ltp_shp_buf_idx = ps_common.ltp_mem_length;
973 ps_nsq.s_ltp_buf_idx = ps_common.ltp_mem_length;
974
975 let mut x_ptr = 0;
976 let mut pulses_ptr = 0;
977 let mut xq_ptr = ps_common.ltp_mem_length as usize;
978 let mut subfr_nsq = 0;
979
980 for k in 0..ps_common.nb_subfr as usize {
981 let a_q12 =
982 &pred_coef_q12[((k >> 1) | (1 - lsf_interpolation_flag as usize)) * MAX_LPC_ORDER..];
983 let b_q14 = <p_coef_q14[k * LTP_ORDER..];
984 let ar_shp_q13 = &ar_q13[k * MAX_SHAPE_LPC_ORDER..];
985
986 let harm_shape_gain = harm_shape_gain_q14[k];
987 let mut harm_shape_fir_packed_q14 = silk_rshift(harm_shape_gain, 2);
988 harm_shape_fir_packed_q14 |= silk_lshift(silk_rshift(harm_shape_gain, 1), 16);
989
990 ps_nsq.rewhite_flag = 0;
991 if ps_indices.signal_type as i32 == TYPE_VOICED {
992 lag = pitch_l[k];
993 if (k & (3 - silk_lshift(lsf_interpolation_flag, 1) as usize)) == 0 {
994 if k == 2 {
995 let mut rd_min_q10 = ps_del_dec[0].rd_q10;
996 let mut winner_ind = 0;
997 for i in 1..n_states {
998 if ps_del_dec[i].rd_q10 < rd_min_q10 {
999 rd_min_q10 = ps_del_dec[i].rd_q10;
1000 winner_ind = i;
1001 }
1002 }
1003 for i in 0..n_states {
1004 if i != winner_ind {
1005 ps_del_dec[i].rd_q10 =
1006 ps_del_dec[i].rd_q10.saturating_add(i32::MAX >> 4);
1007 }
1008 }
1009
1010 let ps_dd = &ps_del_dec[winner_ind];
1011 let mut last_smple_idx =
1012 (smpl_buf_idx + decision_delay) % DECISION_DELAY as i32;
1013 for i in 0..decision_delay {
1014 last_smple_idx =
1015 (last_smple_idx - 1 + DECISION_DELAY as i32) % DECISION_DELAY as i32;
1016 let pulse_idx = (pulses_ptr as i32 + i - decision_delay) as isize;
1017 let xq_idx = (xq_ptr as i32 + i - decision_delay) as isize;
1018 let shp_idx = (ps_nsq.s_ltp_shp_buf_idx + i - decision_delay) as isize;
1019 if pulse_idx >= 0 && xq_idx >= 0 && shp_idx >= 0 {
1020 pulses[pulse_idx as usize] =
1021 silk_rshift_round(ps_dd.q_q10[last_smple_idx as usize], 10) as i8;
1022 ps_nsq.xq[xq_idx as usize] = silk_sat16(silk_rshift_round(
1023 silk_smulww(ps_dd.xq_q14[last_smple_idx as usize], gains_q16[1]),
1024 14,
1025 )) as i16;
1026 ps_nsq.s_ltp_shp_q14[shp_idx as usize] =
1027 ps_dd.shape_q14[last_smple_idx as usize];
1028 }
1029 }
1030 subfr_nsq = 0;
1031 }
1032
1033 let start_idx_calc = ps_common.ltp_mem_length
1034 - lag
1035 - ps_common.predict_lpc_order
1036 - LTP_ORDER as i32 / 2;
1037 if start_idx_calc < 0 {
1038 continue;
1039 }
1040 let start_idx = start_idx_calc as usize;
1041 let xq_start = start_idx + k * ps_common.subfr_length as usize;
1042 let filter_len = ps_common.ltp_mem_length as usize - start_idx;
1043
1044 if start_idx + filter_len > s_ltp.len() || xq_start + filter_len > ps_nsq.xq.len() {
1045 continue;
1046 }
1047 silk_lpc_analysis_filter(
1048 &mut s_ltp[start_idx..],
1049 &ps_nsq.xq[xq_start..],
1050 a_q12,
1051 filter_len,
1052 ps_common.predict_lpc_order as usize,
1053 0,
1054 );
1055 ps_nsq.s_ltp_buf_idx = ps_common.ltp_mem_length;
1056 ps_nsq.rewhite_flag = 1;
1057 }
1058 }
1059
1060 silk_nsq_del_dec_scale_states(
1061 ps_common,
1062 ps_nsq,
1063 &mut ps_del_dec,
1064 &x16[x_ptr..],
1065 &mut x_sc_q10,
1066 &s_ltp,
1067 &mut s_ltp_q15,
1068 k,
1069 ps_common.n_states_delayed_decision,
1070 ltp_scale_q14,
1071 gains_q16,
1072 pitch_l,
1073 ps_indices.signal_type as i32,
1074 decision_delay,
1075 );
1076
1077 silk_noise_shape_quantizer_del_dec(
1078 ps_nsq,
1079 &mut ps_del_dec,
1080 ps_indices.signal_type as i32,
1081 &x_sc_q10,
1082 pulses,
1083 pulses_ptr as i32,
1084 xq_ptr as i32,
1085 &mut s_ltp_q15,
1086 &mut delayed_ga_q10,
1087 a_q12,
1088 b_q14,
1089 ar_shp_q13,
1090 lag,
1091 harm_shape_fir_packed_q14,
1092 tilt_q14[k],
1093 lf_shp_q14[k],
1094 gains_q16[k],
1095 lambda_q10,
1096 offset_q10,
1097 ps_common.subfr_length,
1098 subfr_nsq,
1099 ps_common.shaping_lpc_order,
1100 ps_common.predict_lpc_order,
1101 ps_common.warping_q16,
1102 ps_common.n_states_delayed_decision,
1103 &mut smpl_buf_idx,
1104 decision_delay,
1105 ps_common.frame_counter,
1106 );
1107
1108 x_ptr += ps_common.subfr_length as usize;
1109 pulses_ptr += ps_common.subfr_length as usize;
1110 xq_ptr += ps_common.subfr_length as usize;
1111 subfr_nsq += 1;
1112 }
1113
1114 let mut rd_min_q10 = ps_del_dec[0].rd_q10;
1115 let mut winner_ind = 0;
1116 for k in 1..n_states {
1117 if ps_del_dec[k].rd_q10 < rd_min_q10 {
1118 rd_min_q10 = ps_del_dec[k].rd_q10;
1119 winner_ind = k;
1120 }
1121 }
1122
1123 let ps_dd = &ps_del_dec[winner_ind];
1124 ps_nsq.s_lf_ar_q14 = ps_dd.lf_ar_q14;
1125 ps_nsq.s_diff_shp_q14 = ps_dd.diff_q14;
1126 ps_nsq.lag_prev = pitch_l[ps_common.nb_subfr as usize - 1];
1127
1128 let gain_q10_final = silk_rshift(gains_q16[ps_common.nb_subfr as usize - 1], 6);
1129 let mut last_smple_idx = smpl_buf_idx + decision_delay;
1130 for i in 0..decision_delay {
1131 last_smple_idx = (last_smple_idx - 1 + DECISION_DELAY as i32) % DECISION_DELAY as i32;
1132 let pulse_idx = (pulses_ptr as i32 + i - decision_delay) as isize;
1133 let xq_idx = (xq_ptr as i32 + i - decision_delay) as isize;
1134 if pulse_idx >= 0 && (pulse_idx as usize) < pulses.len() {
1135 pulses[pulse_idx as usize] =
1136 silk_rshift_round(ps_dd.q_q10[last_smple_idx as usize], 10) as i8;
1137 }
1138 if xq_idx >= 0 && (xq_idx as usize) < ps_nsq.xq.len() {
1139 ps_nsq.xq[xq_idx as usize] = silk_sat16(silk_rshift_round(
1140 silk_smulww(ps_dd.xq_q14[last_smple_idx as usize], gain_q10_final),
1141 8,
1142 )) as i16;
1143 }
1144 let shp_idx = (ps_nsq.s_ltp_shp_buf_idx - decision_delay + i) as isize;
1145 if shp_idx >= 0 && (shp_idx as usize) < ps_nsq.s_ltp_shp_q14.len() {
1146 ps_nsq.s_ltp_shp_q14[shp_idx as usize] = ps_dd.shape_q14[last_smple_idx as usize];
1147 }
1148 }
1149
1150 let subfr_len = ps_common.subfr_length as usize;
1151 ps_nsq.s_lpc_q14[..NSQ_LPC_BUF_LENGTH]
1152 .copy_from_slice(&ps_dd.s_lpc_q14[subfr_len..subfr_len + NSQ_LPC_BUF_LENGTH]);
1153 ps_nsq.s_ar2_q14.copy_from_slice(&ps_dd.s_ar2_q14);
1154
1155 let ltp_mem_len = ps_common.ltp_mem_length as usize;
1156 let frame_len = ps_common.frame_length as usize;
1157 ps_nsq.xq.copy_within(frame_len..frame_len + ltp_mem_len, 0);
1158 ps_nsq
1159 .s_ltp_shp_q14
1160 .copy_within(frame_len..frame_len + ltp_mem_len, 0);
1161
1162 ps_del_dec[winner_ind].seed_init
1163}