Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(505)

Side by Side Diff: opus/silk/PLC.c

Issue 11196031: Add copy of opus library in deps/third_party. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/
Patch Set: Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « opus/silk/PLC.h ('k') | opus/silk/SigProc_FIX.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
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 contr ol */
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 contr ol */
48 opus_int16 frame[] /* O LPC residual si gnal */
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 contr ol */
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 contr ol */
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 puls e */
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_sub fr - 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->LTPCo ef_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->LTPCo ef_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_or der * 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 contr ol */
170 opus_int16 frame[] /* O LPC residual si gnal */
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 ) * p sPLC->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 rand om noise generator */
206 silk_sum_sqr_shift( &energy1, &shift1, exc_buf, psPL C->subfr_length );
207 silk_sum_sqr_shift( &energy2, &shift2, &exc_buf[ psPLC->subfr_length ], psPL C->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 ) * p sPLC->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->su bfr_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, psD ec->lossCnt ) ];
225 } else {
226 rand_Gain_Q15 = PLC_RAND_ATTENUATE_UV_Q15[ silk_min_int( NB_ATT - 1, psD ec->lossCnt ) ];
227 }
228
229 /* LPC concealment. Apply BWE to previous LPC */
230 silk_bwexpander( psPLC->prevLPC_Q12, psDec->LPC_order, SILK_FIX_CONST( BWE_C OEF, 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_int1 6 ) );
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_Q1 4, 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, PITC H_DRIFT_FAC_Q16 );
308 psPLC->pitchL_Q8 = silk_min_32( psPLC->pitchL_Q8, silk_LSHIFT( silk_SMUL BB( 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_ORDE R + 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 signa l */
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, fram e, 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_shi ft - 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, l ength );
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 }
OLDNEW
« no previous file with comments | « opus/silk/PLC.h ('k') | opus/silk/SigProc_FIX.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698