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

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

Issue 2195313002: Remove Opus from DEPS and import a local copy (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Local copy of opus, opus/src/.gitignore, opus/DEPS, update README.chromium Created 4 years, 4 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
« no previous file with comments | « third_party/opus/src/silk/PLC.h ('k') | third_party/opus/src/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')
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 "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 contr ol */
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 contr ol */
49 opus_int16 frame[], /* O LPC residual si gnal */
50 int arch /* I Run-time archi tecture */
51 );
52
53
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
65 void silk_PLC(
66 silk_decoder_state *psDec, /* I/O Decoder state */
67 silk_decoder_control *psDecCtrl, /* I/O Decoder contr ol */
68 opus_int16 frame[], /* I/O signal */
69 opus_int lost, /* I Loss flag */
70 int arch /* I Run-time archit ecture */
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 /**************************************************/
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 contr ol */
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 puls e */
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_sub fr - 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->LTPCo ef_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->LTPCo ef_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_or der * 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
170 static OPUS_INLINE void silk_PLC_energy(opus_int32 *energy1, opus_int *shift1, o pus_int32 *energy2, opus_int *shift2,
171 const opus_int32 *exc_Q14, const opus_int32 *prevGain_Q10, int subfr_lengt h, 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 rand om 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
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 contr ol */
197 opus_int16 frame[], /* O LPC residual si gnal */
198 int arch /* I Run-time archit ecture */
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, prevGa in_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 ) * p sPLC->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->su bfr_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, psD ec->lossCnt ) ];
253 } else {
254 rand_Gain_Q15 = PLC_RAND_ATTENUATE_UV_Q15[ silk_min_int( NB_ATT - 1, psD ec->lossCnt ) ];
255 }
256
257 /* LPC concealment. Apply BWE to previous LPC */
258 silk_bwexpander( psPLC->prevLPC_Q12, psDec->LPC_order, SILK_FIX_CONST( BWE_C OEF, 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_int1 6 ) );
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_Q1 4, 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 );
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 silk_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, PITC H_DRIFT_FAC_Q16 );
336 psPLC->pitchL_Q8 = silk_min_32( psPLC->pitchL_Q8, silk_LSHIFT( silk_SMUL BB( 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 silk_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_ORDE R + 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_LP C_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 */
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 signa l */
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, fram e, 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_shi ft - 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, l ength );
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 }
OLDNEW
« no previous file with comments | « third_party/opus/src/silk/PLC.h ('k') | third_party/opus/src/silk/SigProc_FIX.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698