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