Make compiler settings consistent. Actually produce the libary, remove the opus_demo...
[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, 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 "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                          frame[]             /* 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_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     opus_int32 prevGain_Q10[2];
187
188     prevGain_Q10[0] = silk_RSHIFT( psPLC->prevGain_Q16[ 0 ], 6);
189     prevGain_Q10[1] = silk_RSHIFT( psPLC->prevGain_Q16[ 1 ], 6);
190
191     if( psDec->first_frame_after_reset ) {
192        silk_memset( psPLC->prevLPC_Q12, 0, sizeof( psPLC->prevLPC_Q12 ) );
193     }
194
195     /* Find random noise component */
196     /* Scale previous excitation signal */
197     exc_buf_ptr = exc_buf;
198     for( k = 0; k < 2; k++ ) {
199         for( i = 0; i < psPLC->subfr_length; i++ ) {
200             exc_buf_ptr[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT(
201                 silk_SMULWW( psDec->exc_Q14[ i + ( k + psPLC->nb_subfr - 2 ) * psPLC->subfr_length ], prevGain_Q10[ k ] ), 8 ) );
202         }
203         exc_buf_ptr += psPLC->subfr_length;
204     }
205     /* Find the subframe with lowest energy of the last two and use that as random noise generator */
206     silk_sum_sqr_shift( &energy1, &shift1, exc_buf,                         psPLC->subfr_length );
207     silk_sum_sqr_shift( &energy2, &shift2, &exc_buf[ psPLC->subfr_length ], psPLC->subfr_length );
208
209     if( silk_RSHIFT( energy1, shift2 ) < silk_RSHIFT( energy2, shift1 ) ) {
210         /* First sub-frame has lowest energy */
211         rand_ptr = &psDec->exc_Q14[ silk_max_int( 0, ( psPLC->nb_subfr - 1 ) * psPLC->subfr_length - RAND_BUF_SIZE ) ];
212     } else {
213         /* Second sub-frame has lowest energy */
214         rand_ptr = &psDec->exc_Q14[ silk_max_int( 0, psPLC->nb_subfr * psPLC->subfr_length - RAND_BUF_SIZE ) ];
215     }
216
217     /* Set up Gain to random noise component */
218     B_Q14          = psPLC->LTPCoef_Q14;
219     rand_scale_Q14 = psPLC->randScale_Q14;
220
221     /* Set up attenuation gains */
222     harm_Gain_Q15 = HARM_ATT_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ];
223     if( psDec->prevSignalType == TYPE_VOICED ) {
224         rand_Gain_Q15 = PLC_RAND_ATTENUATE_V_Q15[  silk_min_int( NB_ATT - 1, psDec->lossCnt ) ];
225     } else {
226         rand_Gain_Q15 = PLC_RAND_ATTENUATE_UV_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ];
227     }
228
229     /* LPC concealment. Apply BWE to previous LPC */
230     silk_bwexpander( psPLC->prevLPC_Q12, psDec->LPC_order, SILK_FIX_CONST( BWE_COEF, 16 ) );
231
232     /* Preload LPC coeficients to array on stack. Gives small performance gain */
233     silk_memcpy( A_Q12, psPLC->prevLPC_Q12, psDec->LPC_order * sizeof( opus_int16 ) );
234
235     /* First Lost frame */
236     if( psDec->lossCnt == 0 ) {
237         rand_scale_Q14 = 1 << 14;
238
239         /* Reduce random noise Gain for voiced frames */
240         if( psDec->prevSignalType == TYPE_VOICED ) {
241             for( i = 0; i < LTP_ORDER; i++ ) {
242                 rand_scale_Q14 -= B_Q14[ i ];
243             }
244             rand_scale_Q14 = silk_max_16( 3277, rand_scale_Q14 ); /* 0.2 */
245             rand_scale_Q14 = (opus_int16)silk_RSHIFT( silk_SMULBB( rand_scale_Q14, psPLC->prevLTP_scale_Q14 ), 14 );
246         } else {
247             /* Reduce random noise for unvoiced frames with high LPC gain */
248             opus_int32 invGain_Q30, down_scale_Q30;
249
250             invGain_Q30 = silk_LPC_inverse_pred_gain( psPLC->prevLPC_Q12, psDec->LPC_order );
251
252             down_scale_Q30 = silk_min_32( silk_RSHIFT( (opus_int32)1 << 30, LOG2_INV_LPC_GAIN_HIGH_THRES ), invGain_Q30 );
253             down_scale_Q30 = silk_max_32( silk_RSHIFT( (opus_int32)1 << 30, LOG2_INV_LPC_GAIN_LOW_THRES ), down_scale_Q30 );
254             down_scale_Q30 = silk_LSHIFT( down_scale_Q30, LOG2_INV_LPC_GAIN_HIGH_THRES );
255
256             rand_Gain_Q15 = silk_RSHIFT( silk_SMULWB( down_scale_Q30, rand_Gain_Q15 ), 14 );
257         }
258     }
259
260     rand_seed    = psPLC->rand_seed;
261     lag          = silk_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 );
262     sLTP_buf_idx = psDec->ltp_mem_length;
263
264     /* Rewhiten LTP state */
265     idx = psDec->ltp_mem_length - lag - psDec->LPC_order - LTP_ORDER / 2;
266     silk_assert( idx > 0 );
267     silk_LPC_analysis_filter( &sLTP[ idx ], &psDec->outBuf[ idx ], A_Q12, psDec->ltp_mem_length - idx, psDec->LPC_order );
268     /* Scale LTP state */
269     inv_gain_Q30 = silk_INVERSE32_varQ( psPLC->prevGain_Q16[ 1 ], 46 );
270     inv_gain_Q30 = silk_min( inv_gain_Q30, silk_int32_MAX >> 1 );
271     for( i = idx + psDec->LPC_order; i < psDec->ltp_mem_length; i++ ) {
272         sLTP_Q14[ i ] = silk_SMULWB( inv_gain_Q30, sLTP[ i ] );
273     }
274
275     /***************************/
276     /* LTP synthesis filtering */
277     /***************************/
278     for( k = 0; k < psDec->nb_subfr; k++ ) {
279         /* Set up pointer */
280         pred_lag_ptr = &sLTP_Q14[ sLTP_buf_idx - lag + LTP_ORDER / 2 ];
281         for( i = 0; i < psDec->subfr_length; i++ ) {
282             /* Unrolled loop */
283             /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
284             LTP_pred_Q12 = 2;
285             LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[  0 ], B_Q14[ 0 ] );
286             LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -1 ], B_Q14[ 1 ] );
287             LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -2 ], B_Q14[ 2 ] );
288             LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -3 ], B_Q14[ 3 ] );
289             LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -4 ], B_Q14[ 4 ] );
290             pred_lag_ptr++;
291
292             /* Generate LPC excitation */
293             rand_seed = silk_RAND( rand_seed );
294             idx = silk_RSHIFT( rand_seed, 25 ) & RAND_BUF_MASK;
295             sLTP_Q14[ sLTP_buf_idx ] = silk_LSHIFT32( silk_SMLAWB( LTP_pred_Q12, rand_ptr[ idx ], rand_scale_Q14 ), 2 );
296             sLTP_buf_idx++;
297         }
298
299         /* Gradually reduce LTP gain */
300         for( j = 0; j < LTP_ORDER; j++ ) {
301             B_Q14[ j ] = silk_RSHIFT( silk_SMULBB( harm_Gain_Q15, B_Q14[ j ] ), 15 );
302         }
303         /* Gradually reduce excitation gain */
304         rand_scale_Q14 = silk_RSHIFT( silk_SMULBB( rand_scale_Q14, rand_Gain_Q15 ), 15 );
305
306         /* Slowly increase pitch lag */
307         psPLC->pitchL_Q8 = silk_SMLAWB( psPLC->pitchL_Q8, psPLC->pitchL_Q8, PITCH_DRIFT_FAC_Q16 );
308         psPLC->pitchL_Q8 = silk_min_32( psPLC->pitchL_Q8, silk_LSHIFT( silk_SMULBB( MAX_PITCH_LAG_MS, psDec->fs_kHz ), 8 ) );
309         lag = silk_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 );
310     }
311
312     /***************************/
313     /* LPC synthesis filtering */
314     /***************************/
315     sLPC_Q14_ptr = &sLTP_Q14[ psDec->ltp_mem_length - MAX_LPC_ORDER ];
316
317     /* Copy LPC state */
318     silk_memcpy( sLPC_Q14_ptr, psDec->sLPC_Q14_buf, MAX_LPC_ORDER * sizeof( opus_int32 ) );
319
320     silk_assert( psDec->LPC_order >= 10 ); /* check that unrolling works */
321     for( i = 0; i < psDec->frame_length; i++ ) {
322         /* partly unrolled */
323         /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
324         LPC_pred_Q10 = silk_RSHIFT( psDec->LPC_order, 1 );
325         LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i -  1 ], A_Q12[ 0 ] );
326         LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i -  2 ], A_Q12[ 1 ] );
327         LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i -  3 ], A_Q12[ 2 ] );
328         LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i -  4 ], A_Q12[ 3 ] );
329         LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i -  5 ], A_Q12[ 4 ] );
330         LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i -  6 ], A_Q12[ 5 ] );
331         LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i -  7 ], A_Q12[ 6 ] );
332         LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i -  8 ], A_Q12[ 7 ] );
333         LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i -  9 ], A_Q12[ 8 ] );
334         LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 10 ], A_Q12[ 9 ] );
335         for( j = 10; j < psDec->LPC_order; j++ ) {
336             LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - j - 1 ], A_Q12[ j ] );
337         }
338
339         /* Add prediction to LPC excitation */
340         sLPC_Q14_ptr[ MAX_LPC_ORDER + i ] = silk_ADD_LSHIFT32( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], LPC_pred_Q10, 4 );
341
342         /* Scale with Gain */
343         frame[ i ] = (opus_int16)silk_SAT16( silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], prevGain_Q10[ 1 ] ), 8 ) ) );
344     }
345
346     /* Save LPC state */
347     silk_memcpy( psDec->sLPC_Q14_buf, &sLPC_Q14_ptr[ psDec->frame_length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
348
349     /**************************************/
350     /* Update states                      */
351     /**************************************/
352     psPLC->rand_seed     = rand_seed;
353     psPLC->randScale_Q14 = rand_scale_Q14;
354     for( i = 0; i < MAX_NB_SUBFR; i++ ) {
355         psDecCtrl->pitchL[ i ] = lag;
356     }
357 }
358
359 /* Glues concealed frames with new good recieved frames */
360 void silk_PLC_glue_frames(
361     silk_decoder_state                  *psDec,             /* I/O decoder state        */
362     opus_int16                          frame[],            /* I/O signal               */
363     opus_int                            length              /* I length of signal       */
364 )
365 {
366     opus_int   i, energy_shift;
367     opus_int32 energy;
368     silk_PLC_struct *psPLC;
369     psPLC = &psDec->sPLC;
370
371     if( psDec->lossCnt ) {
372         /* Calculate energy in concealed residual */
373         silk_sum_sqr_shift( &psPLC->conc_energy, &psPLC->conc_energy_shift, frame, length );
374
375         psPLC->last_frame_lost = 1;
376     } else {
377         if( psDec->sPLC.last_frame_lost ) {
378             /* Calculate residual in decoded signal if last frame was lost */
379             silk_sum_sqr_shift( &energy, &energy_shift, frame, length );
380
381             /* Normalize energies */
382             if( energy_shift > psPLC->conc_energy_shift ) {
383                 psPLC->conc_energy = silk_RSHIFT( psPLC->conc_energy, energy_shift - psPLC->conc_energy_shift );
384             } else if( energy_shift < psPLC->conc_energy_shift ) {
385                 energy = silk_RSHIFT( energy, psPLC->conc_energy_shift - energy_shift );
386             }
387
388             /* Fade in the energy difference */
389             if( energy > psPLC->conc_energy ) {
390                 opus_int32 frac_Q24, LZ;
391                 opus_int32 gain_Q16, slope_Q16;
392
393                 LZ = silk_CLZ32( psPLC->conc_energy );
394                 LZ = LZ - 1;
395                 psPLC->conc_energy = silk_LSHIFT( psPLC->conc_energy, LZ );
396                 energy = silk_RSHIFT( energy, silk_max_32( 24 - LZ, 0 ) );
397
398                 frac_Q24 = silk_DIV32( psPLC->conc_energy, silk_max( energy, 1 ) );
399
400                 gain_Q16 = silk_LSHIFT( silk_SQRT_APPROX( frac_Q24 ), 4 );
401                 slope_Q16 = silk_DIV32_16( ( (opus_int32)1 << 16 ) - gain_Q16, length );
402                 /* Make slope 4x steeper to avoid missing onsets after DTX */
403                 slope_Q16 = silk_LSHIFT( slope_Q16, 2 );
404
405                 for( i = 0; i < length; i++ ) {
406                     frame[ i ] = silk_SMULWB( gain_Q16, frame[ i ] );
407                     gain_Q16 += slope_Q16;
408                     if( gain_Q16 > (opus_int32)1 << 16 ) {
409                         break;
410                     }
411                 }
412             }
413         }
414         psPLC->last_frame_lost = 0;
415     }
416 }