Disabling LBRR for whever there's a change in bandwidth/channels/framesize
[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_RSHIFT( psDec->frame_length, 1 );
57 }
58
59 void silk_PLC(
60     silk_decoder_state          *psDec,             /* I Decoder state          */
61     silk_decoder_control        *psDecCtrl,         /* I Decoder control        */
62     opus_int16                   frame[],            /* O Concealed signal       */
63     opus_int                     lost                /* I Loss flag              */
64 )
65 {
66     /* PLC control function */
67     if( psDec->fs_kHz != psDec->sPLC.fs_kHz ) {
68         silk_PLC_Reset( psDec );
69         psDec->sPLC.fs_kHz = psDec->fs_kHz;
70     }
71
72     if( lost ) {
73         /****************************/
74         /* Generate Signal          */
75         /****************************/
76         silk_PLC_conceal( psDec, psDecCtrl, frame );
77
78         psDec->lossCnt++;
79     } else {
80         /****************************/
81         /* Update state             */
82         /****************************/
83         silk_PLC_update( psDec, psDecCtrl );
84     }
85 }
86
87 /**************************************************/
88 /* Update state of PLC                            */
89 /**************************************************/
90 static inline void silk_PLC_update(
91     silk_decoder_state          *psDec,             /* (I/O) Decoder state          */
92     silk_decoder_control        *psDecCtrl          /* (I/O) Decoder control        */
93 )
94 {
95     opus_int32 LTP_Gain_Q14, temp_LTP_Gain_Q14;
96     opus_int   i, j;
97     silk_PLC_struct *psPLC;
98
99     psPLC = &psDec->sPLC;
100
101     /* Update parameters used in case of packet loss */
102     psDec->prevSignalType = psDec->indices.signalType;
103     LTP_Gain_Q14 = 0;
104     if( psDec->indices.signalType == TYPE_VOICED ) {
105         /* Find the parameters for the last subframe which contains a pitch pulse */
106         for( j = 0; j * psDec->subfr_length < psDecCtrl->pitchL[ psDec->nb_subfr - 1 ]; j++ ) {
107             if( j == psDec->nb_subfr ){
108                 break;
109             }
110             temp_LTP_Gain_Q14 = 0;
111             for( i = 0; i < LTP_ORDER; i++ ) {
112                 temp_LTP_Gain_Q14 += psDecCtrl->LTPCoef_Q14[ ( psDec->nb_subfr - 1 - j ) * LTP_ORDER  + i ];
113             }
114             if( temp_LTP_Gain_Q14 > LTP_Gain_Q14 ) {
115                 LTP_Gain_Q14 = temp_LTP_Gain_Q14;
116                 silk_memcpy( psPLC->LTPCoef_Q14,
117                     &psDecCtrl->LTPCoef_Q14[ silk_SMULBB( psDec->nb_subfr - 1 - j, LTP_ORDER ) ],
118                     LTP_ORDER * sizeof( opus_int16 ) );
119
120                 psPLC->pitchL_Q8 = silk_LSHIFT( psDecCtrl->pitchL[ psDec->nb_subfr - 1 - j ], 8 );
121             }
122         }
123
124 #if USE_SINGLE_TAP
125         silk_memset( psPLC->LTPCoef_Q14, 0, LTP_ORDER * sizeof( opus_int16 ) );
126         psPLC->LTPCoef_Q14[ LTP_ORDER / 2 ] = LTP_Gain_Q14;
127 #endif
128
129         /* Limit LT coefs */
130         if( LTP_Gain_Q14 < V_PITCH_GAIN_START_MIN_Q14 ) {
131             opus_int   scale_Q10;
132             opus_int32 tmp;
133
134             tmp = silk_LSHIFT( V_PITCH_GAIN_START_MIN_Q14, 10 );
135             scale_Q10 = silk_DIV32( tmp, silk_max( LTP_Gain_Q14, 1 ) );
136             for( i = 0; i < LTP_ORDER; i++ ) {
137                 psPLC->LTPCoef_Q14[ i ] = silk_RSHIFT( silk_SMULBB( psPLC->LTPCoef_Q14[ i ], scale_Q10 ), 10 );
138             }
139         } else if( LTP_Gain_Q14 > V_PITCH_GAIN_START_MAX_Q14 ) {
140             opus_int   scale_Q14;
141             opus_int32 tmp;
142
143             tmp = silk_LSHIFT( V_PITCH_GAIN_START_MAX_Q14, 14 );
144             scale_Q14 = silk_DIV32( tmp, silk_max( LTP_Gain_Q14, 1 ) );
145             for( i = 0; i < LTP_ORDER; i++ ) {
146                 psPLC->LTPCoef_Q14[ i ] = silk_RSHIFT( silk_SMULBB( psPLC->LTPCoef_Q14[ i ], scale_Q14 ), 14 );
147             }
148         }
149     } else {
150         psPLC->pitchL_Q8 = silk_LSHIFT( silk_SMULBB( psDec->fs_kHz, 18 ), 8 );
151         silk_memset( psPLC->LTPCoef_Q14, 0, LTP_ORDER * sizeof( opus_int16 ));
152     }
153
154     /* Save LPC coeficients */
155     silk_memcpy( psPLC->prevLPC_Q12, psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_order * sizeof( opus_int16 ) );
156     psPLC->prevLTP_scale_Q14 = psDecCtrl->LTP_scale_Q14;
157
158     /* Save Gains */
159     silk_memcpy( psPLC->prevGain_Q16, psDecCtrl->Gains_Q16, psDec->nb_subfr * sizeof( opus_int32 ) );
160 }
161
162 static inline void silk_PLC_conceal(
163     silk_decoder_state          *psDec,             /* I/O Decoder state */
164     silk_decoder_control        *psDecCtrl,         /* I/O Decoder control */
165     opus_int16                   frame[]            /* O concealed signal */
166 )
167 {
168     opus_int   i, j, k;
169     opus_int16 *B_Q14, exc_buf[ MAX_FRAME_LENGTH ], *exc_buf_ptr;
170     opus_int16 rand_scale_Q14, A_Q12_tmp[ MAX_LPC_ORDER ];
171     opus_int32 rand_seed, harm_Gain_Q15, rand_Gain_Q15;
172     opus_int   lag, idx, sLTP_buf_idx, shift1, shift2;
173     opus_int32 energy1, energy2, *rand_ptr, *pred_lag_ptr;
174     opus_int32 sig_Q10[ MAX_FRAME_LENGTH ], *sig_Q10_ptr, LPC_exc_Q10, LPC_pred_Q10,  LTP_pred_Q14;
175     silk_PLC_struct *psPLC;
176     psPLC = &psDec->sPLC;
177
178     /* Update LTP buffer */
179     silk_memmove( psDec->sLTP_Q16, &psDec->sLTP_Q16[ psDec->frame_length ], psDec->ltp_mem_length * sizeof( opus_int32 ) );
180
181     /* LPC concealment. Apply BWE to previous LPC */
182     silk_bwexpander( psPLC->prevLPC_Q12, psDec->LPC_order, SILK_FIX_CONST( BWE_COEF, 16 ) );
183
184     /* Find random noise component */
185     /* Scale previous excitation signal */
186     exc_buf_ptr = exc_buf;
187     /* FIXME: JMV: Is this the right fix? */
188     for (i=0;i<MAX_FRAME_LENGTH;i++)
189         exc_buf[i] = 0;
190     for( k = ( psDec->nb_subfr >> 1 ); k < psDec->nb_subfr; k++ ) {
191         for( i = 0; i < psDec->subfr_length; i++ ) {
192             exc_buf_ptr[ i ] = ( opus_int16 )silk_RSHIFT(
193                 silk_SMULWW( psDec->exc_Q10[ i + k * psDec->subfr_length ], psPLC->prevGain_Q16[ k ] ), 10 );
194         }
195         exc_buf_ptr += psDec->subfr_length;
196     }
197     /* Find the subframe with lowest energy of the last two and use that as random noise generator */
198     silk_sum_sqr_shift( &energy1, &shift1, exc_buf,                         psDec->subfr_length );
199     silk_sum_sqr_shift( &energy2, &shift2, &exc_buf[ psDec->subfr_length ], psDec->subfr_length );
200
201     if( silk_RSHIFT( energy1, shift2 ) < silk_RSHIFT( energy2, shift1 ) ) {
202         /* First sub-frame has lowest energy */
203         rand_ptr = &psDec->exc_Q10[ silk_max_int( 0, 3 * psDec->subfr_length - RAND_BUF_SIZE ) ];
204     } else {
205         /* Second sub-frame has lowest energy */
206         rand_ptr = &psDec->exc_Q10[ silk_max_int( 0, psDec->frame_length - RAND_BUF_SIZE ) ];
207     }
208
209     /* Setup Gain to random noise component */
210     B_Q14          = psPLC->LTPCoef_Q14;
211     rand_scale_Q14 = psPLC->randScale_Q14;
212
213     /* Setup attenuation gains */
214     harm_Gain_Q15 = HARM_ATT_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ];
215     if( psDec->prevSignalType == TYPE_VOICED ) {
216         rand_Gain_Q15 = PLC_RAND_ATTENUATE_V_Q15[  silk_min_int( NB_ATT - 1, psDec->lossCnt ) ];
217     } else {
218         rand_Gain_Q15 = PLC_RAND_ATTENUATE_UV_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ];
219     }
220
221     /* First Lost frame */
222     if( psDec->lossCnt == 0 ) {
223         rand_scale_Q14 = 1 << 14;
224
225         /* Reduce random noise Gain for voiced frames */
226         if( psDec->prevSignalType == TYPE_VOICED ) {
227             for( i = 0; i < LTP_ORDER; i++ ) {
228                 rand_scale_Q14 -= B_Q14[ i ];
229             }
230             rand_scale_Q14 = silk_max_16( 3277, rand_scale_Q14 ); /* 0.2 */
231             rand_scale_Q14 = ( opus_int16 )silk_RSHIFT( silk_SMULBB( rand_scale_Q14, psPLC->prevLTP_scale_Q14 ), 14 );
232         } else {
233             /* Reduce random noise for unvoiced frames with high LPC gain */
234             opus_int32 invGain_Q30, down_scale_Q30;
235
236             silk_LPC_inverse_pred_gain( &invGain_Q30, psPLC->prevLPC_Q12, psDec->LPC_order );
237
238             down_scale_Q30 = silk_min_32( silk_RSHIFT( 1 << 30, LOG2_INV_LPC_GAIN_HIGH_THRES ), invGain_Q30 );
239             down_scale_Q30 = silk_max_32( silk_RSHIFT( 1 << 30, LOG2_INV_LPC_GAIN_LOW_THRES ), down_scale_Q30 );
240             down_scale_Q30 = silk_LSHIFT( down_scale_Q30, LOG2_INV_LPC_GAIN_HIGH_THRES );
241
242             rand_Gain_Q15 = silk_RSHIFT( silk_SMULWB( down_scale_Q30, rand_Gain_Q15 ), 14 );
243         }
244     }
245
246     rand_seed    = psPLC->rand_seed;
247     lag          = silk_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 );
248     sLTP_buf_idx = psDec->ltp_mem_length;
249
250     /***************************/
251     /* LTP synthesis filtering */
252     /***************************/
253     sig_Q10_ptr = sig_Q10;
254     for( k = 0; k < psDec->nb_subfr; k++ ) {
255         /* Setup pointer */
256         pred_lag_ptr = &psDec->sLTP_Q16[ sLTP_buf_idx - lag + LTP_ORDER / 2 ];
257         for( i = 0; i < psDec->subfr_length; i++ ) {
258             rand_seed = silk_RAND( rand_seed );
259             idx = silk_RSHIFT( rand_seed, 25 ) & RAND_BUF_MASK;
260
261             /* Unrolled loop */
262             LTP_pred_Q14 = silk_SMULWB(               pred_lag_ptr[  0 ], B_Q14[ 0 ] );
263             LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -1 ], B_Q14[ 1 ] );
264             LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -2 ], B_Q14[ 2 ] );
265             LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -3 ], B_Q14[ 3 ] );
266             LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -4 ], B_Q14[ 4 ] );
267             pred_lag_ptr++;
268
269             /* Generate LPC residual */
270             LPC_exc_Q10 = silk_LSHIFT( silk_SMULWB( rand_ptr[ idx ], rand_scale_Q14 ), 2 ); /* Random noise part */
271             LPC_exc_Q10 = silk_ADD32( LPC_exc_Q10, silk_RSHIFT_ROUND( LTP_pred_Q14, 4 ) );  /* Harmonic part */
272
273             /* Update states */
274             psDec->sLTP_Q16[ sLTP_buf_idx ] = silk_LSHIFT( LPC_exc_Q10, 6 );
275             sLTP_buf_idx++;
276
277             /* Save LPC residual */
278             sig_Q10_ptr[ i ] = LPC_exc_Q10;
279         }
280         sig_Q10_ptr += psDec->subfr_length;
281         /* Gradually reduce LTP gain */
282         for( j = 0; j < LTP_ORDER; j++ ) {
283             B_Q14[ j ] = silk_RSHIFT( silk_SMULBB( harm_Gain_Q15, B_Q14[ j ] ), 15 );
284         }
285         /* Gradually reduce excitation gain */
286         rand_scale_Q14 = silk_RSHIFT( silk_SMULBB( rand_scale_Q14, rand_Gain_Q15 ), 15 );
287
288         /* Slowly increase pitch lag */
289         psPLC->pitchL_Q8 += silk_SMULWB( psPLC->pitchL_Q8, PITCH_DRIFT_FAC_Q16 );
290         psPLC->pitchL_Q8 = silk_min_32( psPLC->pitchL_Q8, silk_LSHIFT( silk_SMULBB( MAX_PITCH_LAG_MS, psDec->fs_kHz ), 8 ) );
291         lag = silk_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 );
292     }
293
294     /***************************/
295     /* LPC synthesis filtering */
296     /***************************/
297     sig_Q10_ptr = sig_Q10;
298     /* Preload LPC coeficients to array on stack. Gives small performance gain */
299     silk_memcpy( A_Q12_tmp, psPLC->prevLPC_Q12, psDec->LPC_order * sizeof( opus_int16 ) );
300     silk_assert( psDec->LPC_order >= 10 ); /* check that unrolling works */
301     for( k = 0; k < psDec->nb_subfr; k++ ) {
302         for( i = 0; i < psDec->subfr_length; i++ ){
303             /* partly unrolled */
304             LPC_pred_Q10 = silk_SMULWB(               psDec->sLPC_Q14[ MAX_LPC_ORDER + i -  1 ], A_Q12_tmp[ 0 ] );
305             LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i -  2 ], A_Q12_tmp[ 1 ] );
306             LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i -  3 ], A_Q12_tmp[ 2 ] );
307             LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i -  4 ], A_Q12_tmp[ 3 ] );
308             LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i -  5 ], A_Q12_tmp[ 4 ] );
309             LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i -  6 ], A_Q12_tmp[ 5 ] );
310             LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i -  7 ], A_Q12_tmp[ 6 ] );
311             LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i -  8 ], A_Q12_tmp[ 7 ] );
312             LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i -  9 ], A_Q12_tmp[ 8 ] );
313             LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 10 ], A_Q12_tmp[ 9 ] );
314
315             for( j = 10; j < psDec->LPC_order; j++ ) {
316                 LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - j - 1 ], A_Q12_tmp[ j ] );
317             }
318
319             /* Add prediction to LPC residual */
320             sig_Q10_ptr[ i ] = silk_ADD32( sig_Q10_ptr[ i ], LPC_pred_Q10 );
321
322             /* Update states */
323             psDec->sLPC_Q14[ MAX_LPC_ORDER + i ] = silk_LSHIFT( sig_Q10_ptr[ i ], 4 );
324         }
325         sig_Q10_ptr += psDec->subfr_length;
326         /* Update LPC filter state */
327         silk_memcpy( psDec->sLPC_Q14, &psDec->sLPC_Q14[ psDec->subfr_length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
328     }
329
330     /* Scale with Gain */
331     for( i = 0; i < psDec->frame_length; i++ ) {
332         frame[ i ] = ( opus_int16 )silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sig_Q10[ i ], psPLC->prevGain_Q16[ psDec->nb_subfr - 1 ] ), 10 ) );
333     }
334
335     /**************************************/
336     /* Update states                      */
337     /**************************************/
338     psPLC->rand_seed     = rand_seed;
339     psPLC->randScale_Q14 = rand_scale_Q14;
340     for( i = 0; i < MAX_NB_SUBFR; i++ ) {
341         psDecCtrl->pitchL[ i ] = lag;
342     }
343 }
344
345 /* Glues concealed frames with new good recieved frames             */
346 void silk_PLC_glue_frames(
347     silk_decoder_state          *psDec,             /* I/O decoder state    */
348     opus_int16                   frame[],            /* I/O signal           */
349     opus_int                     length              /* I length of residual */
350 )
351 {
352     opus_int   i, energy_shift;
353     opus_int32 energy;
354     silk_PLC_struct *psPLC;
355     psPLC = &psDec->sPLC;
356
357     if( psDec->lossCnt ) {
358         /* Calculate energy in concealed residual */
359         silk_sum_sqr_shift( &psPLC->conc_energy, &psPLC->conc_energy_shift, frame, length );
360
361         psPLC->last_frame_lost = 1;
362     } else {
363         if( psDec->sPLC.last_frame_lost ) {
364             /* Calculate residual in decoded signal if last frame was lost */
365             silk_sum_sqr_shift( &energy, &energy_shift, frame, length );
366
367             /* Normalize energies */
368             if( energy_shift > psPLC->conc_energy_shift ) {
369                 psPLC->conc_energy = silk_RSHIFT( psPLC->conc_energy, energy_shift - psPLC->conc_energy_shift );
370             } else if( energy_shift < psPLC->conc_energy_shift ) {
371                 energy = silk_RSHIFT( energy, psPLC->conc_energy_shift - energy_shift );
372             }
373
374             /* Fade in the energy difference */
375             if( energy > psPLC->conc_energy ) {
376                 opus_int32 frac_Q24, LZ;
377                 opus_int32 gain_Q16, slope_Q16;
378
379                 LZ = silk_CLZ32( psPLC->conc_energy );
380                 LZ = LZ - 1;
381                 psPLC->conc_energy = silk_LSHIFT( psPLC->conc_energy, LZ );
382                 energy = silk_RSHIFT( energy, silk_max_32( 24 - LZ, 0 ) );
383
384                 frac_Q24 = silk_DIV32( psPLC->conc_energy, silk_max( energy, 1 ) );
385
386                 gain_Q16 = silk_LSHIFT( silk_SQRT_APPROX( frac_Q24 ), 4 );
387                 slope_Q16 = silk_DIV32_16( ( 1 << 16 ) - gain_Q16, length );
388                 /* Make slope 4x steeper to avoid missing onsets after DTX */
389                 slope_Q16 = silk_LSHIFT( slope_Q16, 2 );
390
391                 for( i = 0; i < length; i++ ) {
392                     frame[ i ] = silk_SMULWB( gain_Q16, frame[ i ] );
393                     gain_Q16 += slope_Q16;
394                     if( gain_Q16 > 1 << 16 ) {
395                         break;
396                     }
397                 }
398             }
399         }
400         psPLC->last_frame_lost = 0;
401     }
402 }