summaryrefslogtreecommitdiff
path: root/lib/rbcodec/codecs/libopus/silk/NSQ.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rbcodec/codecs/libopus/silk/NSQ.c')
-rw-r--r--lib/rbcodec/codecs/libopus/silk/NSQ.c437
1 files changed, 437 insertions, 0 deletions
diff --git a/lib/rbcodec/codecs/libopus/silk/NSQ.c b/lib/rbcodec/codecs/libopus/silk/NSQ.c
new file mode 100644
index 0000000000..1d64d8e257
--- /dev/null
+++ b/lib/rbcodec/codecs/libopus/silk/NSQ.c
@@ -0,0 +1,437 @@
1/***********************************************************************
2Copyright (c) 2006-2011, Skype Limited. All rights reserved.
3Redistribution and use in source and binary forms, with or without
4modification, are permitted provided that the following conditions
5are met:
6- Redistributions of source code must retain the above copyright notice,
7this list of conditions and the following disclaimer.
8- Redistributions in binary form must reproduce the above copyright
9notice, this list of conditions and the following disclaimer in the
10documentation and/or other materials provided with the distribution.
11- Neither the name of Internet Society, IETF or IETF Trust, nor the
12names of specific contributors, may be used to endorse or promote
13products derived from this software without specific prior written
14permission.
15THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25POSSIBILITY OF SUCH DAMAGE.
26***********************************************************************/
27
28#ifdef HAVE_CONFIG_H
29#include "config.h"
30#endif
31
32#include "main.h"
33#include "stack_alloc.h"
34#include "NSQ.h"
35
36
37static OPUS_INLINE void silk_nsq_scale_states(
38 const silk_encoder_state *psEncC, /* I Encoder State */
39 silk_nsq_state *NSQ, /* I/O NSQ state */
40 const opus_int16 x16[], /* I input */
41 opus_int32 x_sc_Q10[], /* O input scaled with 1/Gain */
42 const opus_int16 sLTP[], /* I re-whitened LTP state in Q0 */
43 opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
44 opus_int subfr, /* I subframe number */
45 const opus_int LTP_scale_Q14, /* I */
46 const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */
47 const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */
48 const opus_int signal_type /* I Signal type */
49);
50
51#if !defined(OPUS_X86_MAY_HAVE_SSE4_1)
52static OPUS_INLINE void silk_noise_shape_quantizer(
53 silk_nsq_state *NSQ, /* I/O NSQ state */
54 opus_int signalType, /* I Signal type */
55 const opus_int32 x_sc_Q10[], /* I */
56 opus_int8 pulses[], /* O */
57 opus_int16 xq[], /* O */
58 opus_int32 sLTP_Q15[], /* I/O LTP state */
59 const opus_int16 a_Q12[], /* I Short term prediction coefs */
60 const opus_int16 b_Q14[], /* I Long term prediction coefs */
61 const opus_int16 AR_shp_Q13[], /* I Noise shaping AR coefs */
62 opus_int lag, /* I Pitch lag */
63 opus_int32 HarmShapeFIRPacked_Q14, /* I */
64 opus_int Tilt_Q14, /* I Spectral tilt */
65 opus_int32 LF_shp_Q14, /* I */
66 opus_int32 Gain_Q16, /* I */
67 opus_int Lambda_Q10, /* I */
68 opus_int offset_Q10, /* I */
69 opus_int length, /* I Input length */
70 opus_int shapingLPCOrder, /* I Noise shaping AR filter order */
71 opus_int predictLPCOrder, /* I Prediction filter order */
72 int arch /* I Architecture */
73);
74#endif
75
76void silk_NSQ_c
77(
78 const silk_encoder_state *psEncC, /* I Encoder State */
79 silk_nsq_state *NSQ, /* I/O NSQ state */
80 SideInfoIndices *psIndices, /* I/O Quantization Indices */
81 const opus_int16 x16[], /* I Input */
82 opus_int8 pulses[], /* O Quantized pulse signal */
83 const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
84 const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
85 const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
86 const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
87 const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
88 const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
89 const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
90 const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
91 const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
92 const opus_int LTP_scale_Q14 /* I LTP state scaling */
93)
94{
95 opus_int k, lag, start_idx, LSF_interpolation_flag;
96 const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13;
97 opus_int16 *pxq;
98 VARDECL( opus_int32, sLTP_Q15 );
99 VARDECL( opus_int16, sLTP );
100 opus_int32 HarmShapeFIRPacked_Q14;
101 opus_int offset_Q10;
102 VARDECL( opus_int32, x_sc_Q10 );
103 SAVE_STACK;
104
105 NSQ->rand_seed = psIndices->Seed;
106
107 /* Set unvoiced lag to the previous one, overwrite later for voiced */
108 lag = NSQ->lagPrev;
109
110 silk_assert( NSQ->prev_gain_Q16 != 0 );
111
112 offset_Q10 = silk_Quantization_Offsets_Q10[ psIndices->signalType >> 1 ][ psIndices->quantOffsetType ];
113
114 if( psIndices->NLSFInterpCoef_Q2 == 4 ) {
115 LSF_interpolation_flag = 0;
116 } else {
117 LSF_interpolation_flag = 1;
118 }
119
120 ALLOC( sLTP_Q15, psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 );
121 ALLOC( sLTP, psEncC->ltp_mem_length + psEncC->frame_length, opus_int16 );
122 ALLOC( x_sc_Q10, psEncC->subfr_length, opus_int32 );
123 /* Set up pointers to start of sub frame */
124 NSQ->sLTP_shp_buf_idx = psEncC->ltp_mem_length;
125 NSQ->sLTP_buf_idx = psEncC->ltp_mem_length;
126 pxq = &NSQ->xq[ psEncC->ltp_mem_length ];
127 for( k = 0; k < psEncC->nb_subfr; k++ ) {
128 A_Q12 = &PredCoef_Q12[ (( k >> 1 ) | ( 1 - LSF_interpolation_flag )) * MAX_LPC_ORDER ];
129 B_Q14 = &LTPCoef_Q14[ k * LTP_ORDER ];
130 AR_shp_Q13 = &AR_Q13[ k * MAX_SHAPE_LPC_ORDER ];
131
132 /* Noise shape parameters */
133 silk_assert( HarmShapeGain_Q14[ k ] >= 0 );
134 HarmShapeFIRPacked_Q14 = silk_RSHIFT( HarmShapeGain_Q14[ k ], 2 );
135 HarmShapeFIRPacked_Q14 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 );
136
137 NSQ->rewhite_flag = 0;
138 if( psIndices->signalType == TYPE_VOICED ) {
139 /* Voiced */
140 lag = pitchL[ k ];
141
142 /* Re-whitening */
143 if( ( k & ( 3 - silk_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) {
144 /* Rewhiten with new A coefs */
145 start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2;
146 celt_assert( start_idx > 0 );
147
148 silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ],
149 A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder, psEncC->arch );
150
151 NSQ->rewhite_flag = 1;
152 NSQ->sLTP_buf_idx = psEncC->ltp_mem_length;
153 }
154 }
155
156 silk_nsq_scale_states( psEncC, NSQ, x16, x_sc_Q10, sLTP, sLTP_Q15, k, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType );
157
158 silk_noise_shape_quantizer( NSQ, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15, A_Q12, B_Q14,
159 AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ], Gains_Q16[ k ], Lambda_Q10,
160 offset_Q10, psEncC->subfr_length, psEncC->shapingLPCOrder, psEncC->predictLPCOrder, psEncC->arch );
161
162 x16 += psEncC->subfr_length;
163 pulses += psEncC->subfr_length;
164 pxq += psEncC->subfr_length;
165 }
166
167 /* Update lagPrev for next frame */
168 NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ];
169
170 /* Save quantized speech and noise shaping signals */
171 silk_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) );
172 silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) );
173 RESTORE_STACK;
174}
175
176/***********************************/
177/* silk_noise_shape_quantizer */
178/***********************************/
179
180#if !defined(OPUS_X86_MAY_HAVE_SSE4_1)
181static OPUS_INLINE
182#endif
183void silk_noise_shape_quantizer(
184 silk_nsq_state *NSQ, /* I/O NSQ state */
185 opus_int signalType, /* I Signal type */
186 const opus_int32 x_sc_Q10[], /* I */
187 opus_int8 pulses[], /* O */
188 opus_int16 xq[], /* O */
189 opus_int32 sLTP_Q15[], /* I/O LTP state */
190 const opus_int16 a_Q12[], /* I Short term prediction coefs */
191 const opus_int16 b_Q14[], /* I Long term prediction coefs */
192 const opus_int16 AR_shp_Q13[], /* I Noise shaping AR coefs */
193 opus_int lag, /* I Pitch lag */
194 opus_int32 HarmShapeFIRPacked_Q14, /* I */
195 opus_int Tilt_Q14, /* I Spectral tilt */
196 opus_int32 LF_shp_Q14, /* I */
197 opus_int32 Gain_Q16, /* I */
198 opus_int Lambda_Q10, /* I */
199 opus_int offset_Q10, /* I */
200 opus_int length, /* I Input length */
201 opus_int shapingLPCOrder, /* I Noise shaping AR filter order */
202 opus_int predictLPCOrder, /* I Prediction filter order */
203 int arch /* I Architecture */
204)
205{
206 opus_int i;
207 opus_int32 LTP_pred_Q13, LPC_pred_Q10, n_AR_Q12, n_LTP_Q13;
208 opus_int32 n_LF_Q12, r_Q10, rr_Q10, q1_Q0, q1_Q10, q2_Q10, rd1_Q20, rd2_Q20;
209 opus_int32 exc_Q14, LPC_exc_Q14, xq_Q14, Gain_Q10;
210 opus_int32 tmp1, tmp2, sLF_AR_shp_Q14;
211 opus_int32 *psLPC_Q14, *shp_lag_ptr, *pred_lag_ptr;
212#ifdef silk_short_prediction_create_arch_coef
213 opus_int32 a_Q12_arch[MAX_LPC_ORDER];
214#endif
215
216 shp_lag_ptr = &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ];
217 pred_lag_ptr = &sLTP_Q15[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ];
218 Gain_Q10 = silk_RSHIFT( Gain_Q16, 6 );
219
220 /* Set up short term AR state */
221 psLPC_Q14 = &NSQ->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 ];
222
223#ifdef silk_short_prediction_create_arch_coef
224 silk_short_prediction_create_arch_coef(a_Q12_arch, a_Q12, predictLPCOrder);
225#endif
226
227 for( i = 0; i < length; i++ ) {
228 /* Generate dither */
229 NSQ->rand_seed = silk_RAND( NSQ->rand_seed );
230
231 /* Short-term prediction */
232 LPC_pred_Q10 = silk_noise_shape_quantizer_short_prediction(psLPC_Q14, a_Q12, a_Q12_arch, predictLPCOrder, arch);
233
234 /* Long-term prediction */
235 if( signalType == TYPE_VOICED ) {
236 /* Unrolled loop */
237 /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
238 LTP_pred_Q13 = 2;
239 LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ 0 ], b_Q14[ 0 ] );
240 LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -1 ], b_Q14[ 1 ] );
241 LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -2 ], b_Q14[ 2 ] );
242 LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -3 ], b_Q14[ 3 ] );
243 LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -4 ], b_Q14[ 4 ] );
244 pred_lag_ptr++;
245 } else {
246 LTP_pred_Q13 = 0;
247 }
248
249 /* Noise shape feedback */
250 celt_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
251 n_AR_Q12 = silk_NSQ_noise_shape_feedback_loop(&NSQ->sDiff_shp_Q14, NSQ->sAR2_Q14, AR_shp_Q13, shapingLPCOrder, arch);
252
253 n_AR_Q12 = silk_SMLAWB( n_AR_Q12, NSQ->sLF_AR_shp_Q14, Tilt_Q14 );
254
255 n_LF_Q12 = silk_SMULWB( NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - 1 ], LF_shp_Q14 );
256 n_LF_Q12 = silk_SMLAWT( n_LF_Q12, NSQ->sLF_AR_shp_Q14, LF_shp_Q14 );
257
258 celt_assert( lag > 0 || signalType != TYPE_VOICED );
259
260 /* Combine prediction and noise shaping signals */
261 tmp1 = silk_SUB32( silk_LSHIFT32( LPC_pred_Q10, 2 ), n_AR_Q12 ); /* Q12 */
262 tmp1 = silk_SUB32( tmp1, n_LF_Q12 ); /* Q12 */
263 if( lag > 0 ) {
264 /* Symmetric, packed FIR coefficients */
265 n_LTP_Q13 = silk_SMULWB( silk_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 );
266 n_LTP_Q13 = silk_SMLAWT( n_LTP_Q13, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 );
267 n_LTP_Q13 = silk_LSHIFT( n_LTP_Q13, 1 );
268 shp_lag_ptr++;
269
270 tmp2 = silk_SUB32( LTP_pred_Q13, n_LTP_Q13 ); /* Q13 */
271 tmp1 = silk_ADD_LSHIFT32( tmp2, tmp1, 1 ); /* Q13 */
272 tmp1 = silk_RSHIFT_ROUND( tmp1, 3 ); /* Q10 */
273 } else {
274 tmp1 = silk_RSHIFT_ROUND( tmp1, 2 ); /* Q10 */
275 }
276
277 r_Q10 = silk_SUB32( x_sc_Q10[ i ], tmp1 ); /* residual error Q10 */
278
279 /* Flip sign depending on dither */
280 if( NSQ->rand_seed < 0 ) {
281 r_Q10 = -r_Q10;
282 }
283 r_Q10 = silk_LIMIT_32( r_Q10, -(31 << 10), 30 << 10 );
284
285 /* Find two quantization level candidates and measure their rate-distortion */
286 q1_Q10 = silk_SUB32( r_Q10, offset_Q10 );
287 q1_Q0 = silk_RSHIFT( q1_Q10, 10 );
288 if (Lambda_Q10 > 2048) {
289 /* For aggressive RDO, the bias becomes more than one pulse. */
290 int rdo_offset = Lambda_Q10/2 - 512;
291 if (q1_Q10 > rdo_offset) {
292 q1_Q0 = silk_RSHIFT( q1_Q10 - rdo_offset, 10 );
293 } else if (q1_Q10 < -rdo_offset) {
294 q1_Q0 = silk_RSHIFT( q1_Q10 + rdo_offset, 10 );
295 } else if (q1_Q10 < 0) {
296 q1_Q0 = -1;
297 } else {
298 q1_Q0 = 0;
299 }
300 }
301 if( q1_Q0 > 0 ) {
302 q1_Q10 = silk_SUB32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 );
303 q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 );
304 q2_Q10 = silk_ADD32( q1_Q10, 1024 );
305 rd1_Q20 = silk_SMULBB( q1_Q10, Lambda_Q10 );
306 rd2_Q20 = silk_SMULBB( q2_Q10, Lambda_Q10 );
307 } else if( q1_Q0 == 0 ) {
308 q1_Q10 = offset_Q10;
309 q2_Q10 = silk_ADD32( q1_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 );
310 rd1_Q20 = silk_SMULBB( q1_Q10, Lambda_Q10 );
311 rd2_Q20 = silk_SMULBB( q2_Q10, Lambda_Q10 );
312 } else if( q1_Q0 == -1 ) {
313 q2_Q10 = offset_Q10;
314 q1_Q10 = silk_SUB32( q2_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 );
315 rd1_Q20 = silk_SMULBB( -q1_Q10, Lambda_Q10 );
316 rd2_Q20 = silk_SMULBB( q2_Q10, Lambda_Q10 );
317 } else { /* Q1_Q0 < -1 */
318 q1_Q10 = silk_ADD32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 );
319 q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 );
320 q2_Q10 = silk_ADD32( q1_Q10, 1024 );
321 rd1_Q20 = silk_SMULBB( -q1_Q10, Lambda_Q10 );
322 rd2_Q20 = silk_SMULBB( -q2_Q10, Lambda_Q10 );
323 }
324 rr_Q10 = silk_SUB32( r_Q10, q1_Q10 );
325 rd1_Q20 = silk_SMLABB( rd1_Q20, rr_Q10, rr_Q10 );
326 rr_Q10 = silk_SUB32( r_Q10, q2_Q10 );
327 rd2_Q20 = silk_SMLABB( rd2_Q20, rr_Q10, rr_Q10 );
328
329 if( rd2_Q20 < rd1_Q20 ) {
330 q1_Q10 = q2_Q10;
331 }
332
333 pulses[ i ] = (opus_int8)silk_RSHIFT_ROUND( q1_Q10, 10 );
334
335 /* Excitation */
336 exc_Q14 = silk_LSHIFT( q1_Q10, 4 );
337 if ( NSQ->rand_seed < 0 ) {
338 exc_Q14 = -exc_Q14;
339 }
340
341 /* Add predictions */
342 LPC_exc_Q14 = silk_ADD_LSHIFT32( exc_Q14, LTP_pred_Q13, 1 );
343 xq_Q14 = silk_ADD_LSHIFT32( LPC_exc_Q14, LPC_pred_Q10, 4 );
344
345 /* Scale XQ back to normal level before saving */
346 xq[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( xq_Q14, Gain_Q10 ), 8 ) );
347
348 /* Update states */
349 psLPC_Q14++;
350 *psLPC_Q14 = xq_Q14;
351 NSQ->sDiff_shp_Q14 = silk_SUB_LSHIFT32( xq_Q14, x_sc_Q10[ i ], 4 );
352 sLF_AR_shp_Q14 = silk_SUB_LSHIFT32( NSQ->sDiff_shp_Q14, n_AR_Q12, 2 );
353 NSQ->sLF_AR_shp_Q14 = sLF_AR_shp_Q14;
354
355 NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx ] = silk_SUB_LSHIFT32( sLF_AR_shp_Q14, n_LF_Q12, 2 );
356 sLTP_Q15[ NSQ->sLTP_buf_idx ] = silk_LSHIFT( LPC_exc_Q14, 1 );
357 NSQ->sLTP_shp_buf_idx++;
358 NSQ->sLTP_buf_idx++;
359
360 /* Make dither dependent on quantized signal */
361 NSQ->rand_seed = silk_ADD32_ovflw( NSQ->rand_seed, pulses[ i ] );
362 }
363
364 /* Update LPC synth buffer */
365 silk_memcpy( NSQ->sLPC_Q14, &NSQ->sLPC_Q14[ length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) );
366}
367
368static OPUS_INLINE void silk_nsq_scale_states(
369 const silk_encoder_state *psEncC, /* I Encoder State */
370 silk_nsq_state *NSQ, /* I/O NSQ state */
371 const opus_int16 x16[], /* I input */
372 opus_int32 x_sc_Q10[], /* O input scaled with 1/Gain */
373 const opus_int16 sLTP[], /* I re-whitened LTP state in Q0 */
374 opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
375 opus_int subfr, /* I subframe number */
376 const opus_int LTP_scale_Q14, /* I */
377 const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */
378 const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */
379 const opus_int signal_type /* I Signal type */
380)
381{
382 opus_int i, lag;
383 opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q26;
384
385 lag = pitchL[ subfr ];
386 inv_gain_Q31 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 47 );
387 silk_assert( inv_gain_Q31 != 0 );
388
389 /* Scale input */
390 inv_gain_Q26 = silk_RSHIFT_ROUND( inv_gain_Q31, 5 );
391 for( i = 0; i < psEncC->subfr_length; i++ ) {
392 x_sc_Q10[ i ] = silk_SMULWW( x16[ i ], inv_gain_Q26 );
393 }
394
395 /* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */
396 if( NSQ->rewhite_flag ) {
397 if( subfr == 0 ) {
398 /* Do LTP downscaling */
399 inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, LTP_scale_Q14 ), 2 );
400 }
401 for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) {
402 silk_assert( i < MAX_FRAME_LENGTH );
403 sLTP_Q15[ i ] = silk_SMULWB( inv_gain_Q31, sLTP[ i ] );
404 }
405 }
406
407 /* Adjust for changing gain */
408 if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) {
409 gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 );
410
411 /* Scale long-term shaping state */
412 for( i = NSQ->sLTP_shp_buf_idx - psEncC->ltp_mem_length; i < NSQ->sLTP_shp_buf_idx; i++ ) {
413 NSQ->sLTP_shp_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q14[ i ] );
414 }
415
416 /* Scale long-term prediction state */
417 if( signal_type == TYPE_VOICED && NSQ->rewhite_flag == 0 ) {
418 for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) {
419 sLTP_Q15[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ i ] );
420 }
421 }
422
423 NSQ->sLF_AR_shp_Q14 = silk_SMULWW( gain_adj_Q16, NSQ->sLF_AR_shp_Q14 );
424 NSQ->sDiff_shp_Q14 = silk_SMULWW( gain_adj_Q16, NSQ->sDiff_shp_Q14 );
425
426 /* Scale short-term prediction and shaping states */
427 for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) {
428 NSQ->sLPC_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLPC_Q14[ i ] );
429 }
430 for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) {
431 NSQ->sAR2_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sAR2_Q14[ i ] );
432 }
433
434 /* Save inverse gain */
435 NSQ->prev_gain_Q16 = Gains_Q16[ subfr ];
436 }
437}