1 /***********************************************************************
2 Copyright (c) 2006-2011, Skype Limited. All rights reserved.
3 Redistribution and use in source and binary forms, with or without
4 modification, are permitted provided that the following conditions
5 are met:
6 - Redistributions of source code must retain the above copyright notice,
7 this list of conditions and the following disclaimer.
8 - Redistributions in binary form must reproduce the above copyright
9 notice, this list of conditions and the following disclaimer in the
10 documentation and/or other materials provided with the distribution.
11 - Neither the name of Internet Society, IETF or IETF Trust, nor the
12 names of specific contributors, may be used to endorse or promote
13 products derived from this software without specific prior written
14 permission.
15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 POSSIBILITY 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 "PLC.h"
35
36 #define NB_ATT 2
37 static const opus_int16 HARM_ATT_Q15[NB_ATT] = { 32440, 31130 }; /* 0.99, 0.95 */
38 static const opus_int16 PLC_RAND_ATTENUATE_V_Q15[NB_ATT] = { 31130, 26214 }; /* 0.95, 0.8 */
39 static const opus_int16 PLC_RAND_ATTENUATE_UV_Q15[NB_ATT] = { 32440, 29491 }; /* 0.99, 0.9 */
40
41 static OPUS_INLINE void silk_PLC_update(
42 silk_decoder_state *psDec, /* I/O Decoder state */
43 silk_decoder_control *psDecCtrl /* I/O Decoder control */
44 );
45
46 static OPUS_INLINE void silk_PLC_conceal(
47 silk_decoder_state *psDec, /* I/O Decoder state */
48 silk_decoder_control *psDecCtrl, /* I/O Decoder control */
49 opus_int16 frame[], /* O LPC residual signal */
50 int arch /* I Run-time architecture */
51 );
52
53
silk_PLC_Reset(silk_decoder_state * psDec)54 void silk_PLC_Reset(
55 silk_decoder_state *psDec /* I/O Decoder state */
56 )
57 {
58 psDec->sPLC.pitchL_Q8 = silk_LSHIFT( psDec->frame_length, 8 - 1 );
59 psDec->sPLC.prevGain_Q16[ 0 ] = SILK_FIX_CONST( 1, 16 );
60 psDec->sPLC.prevGain_Q16[ 1 ] = SILK_FIX_CONST( 1, 16 );
61 psDec->sPLC.subfr_length = 20;
62 psDec->sPLC.nb_subfr = 2;
63 }
64
silk_PLC(silk_decoder_state * psDec,silk_decoder_control * psDecCtrl,opus_int16 frame[],opus_int lost,int arch)65 void silk_PLC(
66 silk_decoder_state *psDec, /* I/O Decoder state */
67 silk_decoder_control *psDecCtrl, /* I/O Decoder control */
68 opus_int16 frame[], /* I/O signal */
69 opus_int lost, /* I Loss flag */
70 int arch /* I Run-time architecture */
71 )
72 {
73 /* PLC control function */
74 if( psDec->fs_kHz != psDec->sPLC.fs_kHz ) {
75 silk_PLC_Reset( psDec );
76 psDec->sPLC.fs_kHz = psDec->fs_kHz;
77 }
78
79 if( lost ) {
80 /****************************/
81 /* Generate Signal */
82 /****************************/
83 silk_PLC_conceal( psDec, psDecCtrl, frame, arch );
84
85 psDec->lossCnt++;
86 } else {
87 /****************************/
88 /* Update state */
89 /****************************/
90 silk_PLC_update( psDec, psDecCtrl );
91 }
92 }
93
94 /**************************************************/
95 /* Update state of PLC */
96 /**************************************************/
silk_PLC_update(silk_decoder_state * psDec,silk_decoder_control * psDecCtrl)97 static OPUS_INLINE void silk_PLC_update(
98 silk_decoder_state *psDec, /* I/O Decoder state */
99 silk_decoder_control *psDecCtrl /* I/O Decoder control */
100 )
101 {
102 opus_int32 LTP_Gain_Q14, temp_LTP_Gain_Q14;
103 opus_int i, j;
104 silk_PLC_struct *psPLC;
105
106 psPLC = &psDec->sPLC;
107
108 /* Update parameters used in case of packet loss */
109 psDec->prevSignalType = psDec->indices.signalType;
110 LTP_Gain_Q14 = 0;
111 if( psDec->indices.signalType == TYPE_VOICED ) {
112 /* Find the parameters for the last subframe which contains a pitch pulse */
113 for( j = 0; j * psDec->subfr_length < psDecCtrl->pitchL[ psDec->nb_subfr - 1 ]; j++ ) {
114 if( j == psDec->nb_subfr ) {
115 break;
116 }
117 temp_LTP_Gain_Q14 = 0;
118 for( i = 0; i < LTP_ORDER; i++ ) {
119 temp_LTP_Gain_Q14 += psDecCtrl->LTPCoef_Q14[ ( psDec->nb_subfr - 1 - j ) * LTP_ORDER + i ];
120 }
121 if( temp_LTP_Gain_Q14 > LTP_Gain_Q14 ) {
122 LTP_Gain_Q14 = temp_LTP_Gain_Q14;
123 silk_memcpy( psPLC->LTPCoef_Q14,
124 &psDecCtrl->LTPCoef_Q14[ silk_SMULBB( psDec->nb_subfr - 1 - j, LTP_ORDER ) ],
125 LTP_ORDER * sizeof( opus_int16 ) );
126
127 psPLC->pitchL_Q8 = silk_LSHIFT( psDecCtrl->pitchL[ psDec->nb_subfr - 1 - j ], 8 );
128 }
129 }
130
131 silk_memset( psPLC->LTPCoef_Q14, 0, LTP_ORDER * sizeof( opus_int16 ) );
132 psPLC->LTPCoef_Q14[ LTP_ORDER / 2 ] = LTP_Gain_Q14;
133
134 /* Limit LT coefs */
135 if( LTP_Gain_Q14 < V_PITCH_GAIN_START_MIN_Q14 ) {
136 opus_int scale_Q10;
137 opus_int32 tmp;
138
139 tmp = silk_LSHIFT( V_PITCH_GAIN_START_MIN_Q14, 10 );
140 scale_Q10 = silk_DIV32( tmp, silk_max( LTP_Gain_Q14, 1 ) );
141 for( i = 0; i < LTP_ORDER; i++ ) {
142 psPLC->LTPCoef_Q14[ i ] = silk_RSHIFT( silk_SMULBB( psPLC->LTPCoef_Q14[ i ], scale_Q10 ), 10 );
143 }
144 } else if( LTP_Gain_Q14 > V_PITCH_GAIN_START_MAX_Q14 ) {
145 opus_int scale_Q14;
146 opus_int32 tmp;
147
148 tmp = silk_LSHIFT( V_PITCH_GAIN_START_MAX_Q14, 14 );
149 scale_Q14 = silk_DIV32( tmp, silk_max( LTP_Gain_Q14, 1 ) );
150 for( i = 0; i < LTP_ORDER; i++ ) {
151 psPLC->LTPCoef_Q14[ i ] = silk_RSHIFT( silk_SMULBB( psPLC->LTPCoef_Q14[ i ], scale_Q14 ), 14 );
152 }
153 }
154 } else {
155 psPLC->pitchL_Q8 = silk_LSHIFT( silk_SMULBB( psDec->fs_kHz, 18 ), 8 );
156 silk_memset( psPLC->LTPCoef_Q14, 0, LTP_ORDER * sizeof( opus_int16 ));
157 }
158
159 /* Save LPC coeficients */
160 silk_memcpy( psPLC->prevLPC_Q12, psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_order * sizeof( opus_int16 ) );
161 psPLC->prevLTP_scale_Q14 = psDecCtrl->LTP_scale_Q14;
162
163 /* Save last two gains */
164 silk_memcpy( psPLC->prevGain_Q16, &psDecCtrl->Gains_Q16[ psDec->nb_subfr - 2 ], 2 * sizeof( opus_int32 ) );
165
166 psPLC->subfr_length = psDec->subfr_length;
167 psPLC->nb_subfr = psDec->nb_subfr;
168 }
169
silk_PLC_energy(opus_int32 * energy1,opus_int * shift1,opus_int32 * energy2,opus_int * shift2,const opus_int32 * exc_Q14,const opus_int32 * prevGain_Q10,int subfr_length,int nb_subfr)170 static OPUS_INLINE void silk_PLC_energy(opus_int32 *energy1, opus_int *shift1, opus_int32 *energy2, opus_int *shift2,
171 const opus_int32 *exc_Q14, const opus_int32 *prevGain_Q10, int subfr_length, int nb_subfr)
172 {
173 int i, k;
174 VARDECL( opus_int16, exc_buf );
175 opus_int16 *exc_buf_ptr;
176 SAVE_STACK;
177 ALLOC( exc_buf, 2*subfr_length, opus_int16 );
178 /* Find random noise component */
179 /* Scale previous excitation signal */
180 exc_buf_ptr = exc_buf;
181 for( k = 0; k < 2; k++ ) {
182 for( i = 0; i < subfr_length; i++ ) {
183 exc_buf_ptr[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT(
184 silk_SMULWW( exc_Q14[ i + ( k + nb_subfr - 2 ) * subfr_length ], prevGain_Q10[ k ] ), 8 ) );
185 }
186 exc_buf_ptr += subfr_length;
187 }
188 /* Find the subframe with lowest energy of the last two and use that as random noise generator */
189 silk_sum_sqr_shift( energy1, shift1, exc_buf, subfr_length );
190 silk_sum_sqr_shift( energy2, shift2, &exc_buf[ subfr_length ], subfr_length );
191 RESTORE_STACK;
192 }
193
silk_PLC_conceal(silk_decoder_state * psDec,silk_decoder_control * psDecCtrl,opus_int16 frame[],int arch)194 static OPUS_INLINE void silk_PLC_conceal(
195 silk_decoder_state *psDec, /* I/O Decoder state */
196 silk_decoder_control *psDecCtrl, /* I/O Decoder control */
197 opus_int16 frame[], /* O LPC residual signal */
198 int arch /* I Run-time architecture */
199 )
200 {
201 opus_int i, j, k;
202 opus_int lag, idx, sLTP_buf_idx, shift1, shift2;
203 opus_int32 rand_seed, harm_Gain_Q15, rand_Gain_Q15, inv_gain_Q30;
204 opus_int32 energy1, energy2, *rand_ptr, *pred_lag_ptr;
205 opus_int32 LPC_pred_Q10, LTP_pred_Q12;
206 opus_int16 rand_scale_Q14;
207 opus_int16 *B_Q14;
208 opus_int32 *sLPC_Q14_ptr;
209 opus_int16 A_Q12[ MAX_LPC_ORDER ];
210 #ifdef SMALL_FOOTPRINT
211 opus_int16 *sLTP;
212 #else
213 VARDECL( opus_int16, sLTP );
214 #endif
215 VARDECL( opus_int32, sLTP_Q14 );
216 silk_PLC_struct *psPLC = &psDec->sPLC;
217 opus_int32 prevGain_Q10[2];
218 SAVE_STACK;
219
220 ALLOC( sLTP_Q14, psDec->ltp_mem_length + psDec->frame_length, opus_int32 );
221 #ifdef SMALL_FOOTPRINT
222 /* Ugly hack that breaks aliasing rules to save stack: put sLTP at the very end of sLTP_Q14. */
223 sLTP = ((opus_int16*)&sLTP_Q14[psDec->ltp_mem_length + psDec->frame_length])-psDec->ltp_mem_length;
224 #else
225 ALLOC( sLTP, psDec->ltp_mem_length, opus_int16 );
226 #endif
227
228 prevGain_Q10[0] = silk_RSHIFT( psPLC->prevGain_Q16[ 0 ], 6);
229 prevGain_Q10[1] = silk_RSHIFT( psPLC->prevGain_Q16[ 1 ], 6);
230
231 if( psDec->first_frame_after_reset ) {
232 silk_memset( psPLC->prevLPC_Q12, 0, sizeof( psPLC->prevLPC_Q12 ) );
233 }
234
235 silk_PLC_energy(&energy1, &shift1, &energy2, &shift2, psDec->exc_Q14, prevGain_Q10, psDec->subfr_length, psDec->nb_subfr);
236
237 if( silk_RSHIFT( energy1, shift2 ) < silk_RSHIFT( energy2, shift1 ) ) {
238 /* First sub-frame has lowest energy */
239 rand_ptr = &psDec->exc_Q14[ silk_max_int( 0, ( psPLC->nb_subfr - 1 ) * psPLC->subfr_length - RAND_BUF_SIZE ) ];
240 } else {
241 /* Second sub-frame has lowest energy */
242 rand_ptr = &psDec->exc_Q14[ silk_max_int( 0, psPLC->nb_subfr * psPLC->subfr_length - RAND_BUF_SIZE ) ];
243 }
244
245 /* Set up Gain to random noise component */
246 B_Q14 = psPLC->LTPCoef_Q14;
247 rand_scale_Q14 = psPLC->randScale_Q14;
248
249 /* Set up attenuation gains */
250 harm_Gain_Q15 = HARM_ATT_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ];
251 if( psDec->prevSignalType == TYPE_VOICED ) {
252 rand_Gain_Q15 = PLC_RAND_ATTENUATE_V_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ];
253 } else {
254 rand_Gain_Q15 = PLC_RAND_ATTENUATE_UV_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ];
255 }
256
257 /* LPC concealment. Apply BWE to previous LPC */
258 silk_bwexpander( psPLC->prevLPC_Q12, psDec->LPC_order, SILK_FIX_CONST( BWE_COEF, 16 ) );
259
260 /* Preload LPC coeficients to array on stack. Gives small performance gain */
261 silk_memcpy( A_Q12, psPLC->prevLPC_Q12, psDec->LPC_order * sizeof( opus_int16 ) );
262
263 /* First Lost frame */
264 if( psDec->lossCnt == 0 ) {
265 rand_scale_Q14 = 1 << 14;
266
267 /* Reduce random noise Gain for voiced frames */
268 if( psDec->prevSignalType == TYPE_VOICED ) {
269 for( i = 0; i < LTP_ORDER; i++ ) {
270 rand_scale_Q14 -= B_Q14[ i ];
271 }
272 rand_scale_Q14 = silk_max_16( 3277, rand_scale_Q14 ); /* 0.2 */
273 rand_scale_Q14 = (opus_int16)silk_RSHIFT( silk_SMULBB( rand_scale_Q14, psPLC->prevLTP_scale_Q14 ), 14 );
274 } else {
275 /* Reduce random noise for unvoiced frames with high LPC gain */
276 opus_int32 invGain_Q30, down_scale_Q30;
277
278 invGain_Q30 = silk_LPC_inverse_pred_gain( psPLC->prevLPC_Q12, psDec->LPC_order, arch );
279
280 down_scale_Q30 = silk_min_32( silk_RSHIFT( (opus_int32)1 << 30, LOG2_INV_LPC_GAIN_HIGH_THRES ), invGain_Q30 );
281 down_scale_Q30 = silk_max_32( silk_RSHIFT( (opus_int32)1 << 30, LOG2_INV_LPC_GAIN_LOW_THRES ), down_scale_Q30 );
282 down_scale_Q30 = silk_LSHIFT( down_scale_Q30, LOG2_INV_LPC_GAIN_HIGH_THRES );
283
284 rand_Gain_Q15 = silk_RSHIFT( silk_SMULWB( down_scale_Q30, rand_Gain_Q15 ), 14 );
285 }
286 }
287
288 rand_seed = psPLC->rand_seed;
289 lag = silk_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 );
290 sLTP_buf_idx = psDec->ltp_mem_length;
291
292 /* Rewhiten LTP state */
293 idx = psDec->ltp_mem_length - lag - psDec->LPC_order - LTP_ORDER / 2;
294 celt_assert( idx > 0 );
295 silk_LPC_analysis_filter( &sLTP[ idx ], &psDec->outBuf[ idx ], A_Q12, psDec->ltp_mem_length - idx, psDec->LPC_order, arch );
296 /* Scale LTP state */
297 inv_gain_Q30 = silk_INVERSE32_varQ( psPLC->prevGain_Q16[ 1 ], 46 );
298 inv_gain_Q30 = silk_min( inv_gain_Q30, silk_int32_MAX >> 1 );
299 for( i = idx + psDec->LPC_order; i < psDec->ltp_mem_length; i++ ) {
300 sLTP_Q14[ i ] = silk_SMULWB( inv_gain_Q30, sLTP[ i ] );
301 }
302
303 /***************************/
304 /* LTP synthesis filtering */
305 /***************************/
306 for( k = 0; k < psDec->nb_subfr; k++ ) {
307 /* Set up pointer */
308 pred_lag_ptr = &sLTP_Q14[ sLTP_buf_idx - lag + LTP_ORDER / 2 ];
309 for( i = 0; i < psDec->subfr_length; i++ ) {
310 /* Unrolled loop */
311 /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
312 LTP_pred_Q12 = 2;
313 LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ 0 ], B_Q14[ 0 ] );
314 LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -1 ], B_Q14[ 1 ] );
315 LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -2 ], B_Q14[ 2 ] );
316 LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -3 ], B_Q14[ 3 ] );
317 LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -4 ], B_Q14[ 4 ] );
318 pred_lag_ptr++;
319
320 /* Generate LPC excitation */
321 rand_seed = silk_RAND( rand_seed );
322 idx = silk_RSHIFT( rand_seed, 25 ) & RAND_BUF_MASK;
323 sLTP_Q14[ sLTP_buf_idx ] = silk_LSHIFT32( silk_SMLAWB( LTP_pred_Q12, rand_ptr[ idx ], rand_scale_Q14 ), 2 );
324 sLTP_buf_idx++;
325 }
326
327 /* Gradually reduce LTP gain */
328 for( j = 0; j < LTP_ORDER; j++ ) {
329 B_Q14[ j ] = silk_RSHIFT( silk_SMULBB( harm_Gain_Q15, B_Q14[ j ] ), 15 );
330 }
331 /* Gradually reduce excitation gain */
332 rand_scale_Q14 = silk_RSHIFT( silk_SMULBB( rand_scale_Q14, rand_Gain_Q15 ), 15 );
333
334 /* Slowly increase pitch lag */
335 psPLC->pitchL_Q8 = silk_SMLAWB( psPLC->pitchL_Q8, psPLC->pitchL_Q8, PITCH_DRIFT_FAC_Q16 );
336 psPLC->pitchL_Q8 = silk_min_32( psPLC->pitchL_Q8, silk_LSHIFT( silk_SMULBB( MAX_PITCH_LAG_MS, psDec->fs_kHz ), 8 ) );
337 lag = silk_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 );
338 }
339
340 /***************************/
341 /* LPC synthesis filtering */
342 /***************************/
343 sLPC_Q14_ptr = &sLTP_Q14[ psDec->ltp_mem_length - MAX_LPC_ORDER ];
344
345 /* Copy LPC state */
346 silk_memcpy( sLPC_Q14_ptr, psDec->sLPC_Q14_buf, MAX_LPC_ORDER * sizeof( opus_int32 ) );
347
348 celt_assert( psDec->LPC_order >= 10 ); /* check that unrolling works */
349 for( i = 0; i < psDec->frame_length; i++ ) {
350 /* partly unrolled */
351 /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
352 LPC_pred_Q10 = silk_RSHIFT( psDec->LPC_order, 1 );
353 LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 1 ], A_Q12[ 0 ] );
354 LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 2 ], A_Q12[ 1 ] );
355 LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 3 ], A_Q12[ 2 ] );
356 LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 4 ], A_Q12[ 3 ] );
357 LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 5 ], A_Q12[ 4 ] );
358 LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 6 ], A_Q12[ 5 ] );
359 LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 7 ], A_Q12[ 6 ] );
360 LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 8 ], A_Q12[ 7 ] );
361 LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 9 ], A_Q12[ 8 ] );
362 LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 10 ], A_Q12[ 9 ] );
363 for( j = 10; j < psDec->LPC_order; j++ ) {
364 LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - j - 1 ], A_Q12[ j ] );
365 }
366
367 /* Add prediction to LPC excitation */
368 sLPC_Q14_ptr[ MAX_LPC_ORDER + i ] = silk_ADD_SAT32( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ],
369 silk_LSHIFT_SAT32( LPC_pred_Q10, 4 ));
370
371 /* Scale with Gain */
372 frame[ i ] = (opus_int16)silk_SAT16( silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], prevGain_Q10[ 1 ] ), 8 ) ) );
373 }
374
375 /* Save LPC state */
376 silk_memcpy( psDec->sLPC_Q14_buf, &sLPC_Q14_ptr[ psDec->frame_length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
377
378 /**************************************/
379 /* Update states */
380 /**************************************/
381 psPLC->rand_seed = rand_seed;
382 psPLC->randScale_Q14 = rand_scale_Q14;
383 for( i = 0; i < MAX_NB_SUBFR; i++ ) {
384 psDecCtrl->pitchL[ i ] = lag;
385 }
386 RESTORE_STACK;
387 }
388
389 /* Glues concealed frames with new good received frames */
silk_PLC_glue_frames(silk_decoder_state * psDec,opus_int16 frame[],opus_int length)390 void silk_PLC_glue_frames(
391 silk_decoder_state *psDec, /* I/O decoder state */
392 opus_int16 frame[], /* I/O signal */
393 opus_int length /* I length of signal */
394 )
395 {
396 opus_int i, energy_shift;
397 opus_int32 energy;
398 silk_PLC_struct *psPLC;
399 psPLC = &psDec->sPLC;
400
401 if( psDec->lossCnt ) {
402 /* Calculate energy in concealed residual */
403 silk_sum_sqr_shift( &psPLC->conc_energy, &psPLC->conc_energy_shift, frame, length );
404
405 psPLC->last_frame_lost = 1;
406 } else {
407 if( psDec->sPLC.last_frame_lost ) {
408 /* Calculate residual in decoded signal if last frame was lost */
409 silk_sum_sqr_shift( &energy, &energy_shift, frame, length );
410
411 /* Normalize energies */
412 if( energy_shift > psPLC->conc_energy_shift ) {
413 psPLC->conc_energy = silk_RSHIFT( psPLC->conc_energy, energy_shift - psPLC->conc_energy_shift );
414 } else if( energy_shift < psPLC->conc_energy_shift ) {
415 energy = silk_RSHIFT( energy, psPLC->conc_energy_shift - energy_shift );
416 }
417
418 /* Fade in the energy difference */
419 if( energy > psPLC->conc_energy ) {
420 opus_int32 frac_Q24, LZ;
421 opus_int32 gain_Q16, slope_Q16;
422
423 LZ = silk_CLZ32( psPLC->conc_energy );
424 LZ = LZ - 1;
425 psPLC->conc_energy = silk_LSHIFT( psPLC->conc_energy, LZ );
426 energy = silk_RSHIFT( energy, silk_max_32( 24 - LZ, 0 ) );
427
428 frac_Q24 = silk_DIV32( psPLC->conc_energy, silk_max( energy, 1 ) );
429
430 gain_Q16 = silk_LSHIFT( silk_SQRT_APPROX( frac_Q24 ), 4 );
431 slope_Q16 = silk_DIV32_16( ( (opus_int32)1 << 16 ) - gain_Q16, length );
432 /* Make slope 4x steeper to avoid missing onsets after DTX */
433 slope_Q16 = silk_LSHIFT( slope_Q16, 2 );
434
435 for( i = 0; i < length; i++ ) {
436 frame[ i ] = silk_SMULWB( gain_Q16, frame[ i ] );
437 gain_Q16 += slope_Q16;
438 if( gain_Q16 > (opus_int32)1 << 16 ) {
439 break;
440 }
441 }
442 }
443 }
444 psPLC->last_frame_lost = 0;
445 }
446 }
447