OLD | NEW |
1 /*********************************************************************** | 1 /*********************************************************************** |
2 Copyright (c) 2006-2011, Skype Limited. All rights reserved. | 2 Copyright (c) 2006-2011, Skype Limited. All rights reserved. |
3 Redistribution and use in source and binary forms, with or without | 3 Redistribution and use in source and binary forms, with or without |
4 modification, are permitted provided that the following conditions | 4 modification, are permitted provided that the following conditions |
5 are met: | 5 are met: |
6 - Redistributions of source code must retain the above copyright notice, | 6 - Redistributions of source code must retain the above copyright notice, |
7 this list of conditions and the following disclaimer. | 7 this list of conditions and the following disclaimer. |
8 - Redistributions in binary form must reproduce the above copyright | 8 - Redistributions in binary form must reproduce the above copyright |
9 notice, this list of conditions and the following disclaimer in the | 9 notice, this list of conditions and the following disclaimer in the |
10 documentation and/or other materials provided with the distribution. | 10 documentation and/or other materials provided with the distribution. |
(...skipping 28 matching lines...) Expand all Loading... |
39 static const opus_int16 PLC_RAND_ATTENUATE_UV_Q15[NB_ATT] = { 32440, 29491 }; /*
0.99, 0.9 */ | 39 static const opus_int16 PLC_RAND_ATTENUATE_UV_Q15[NB_ATT] = { 32440, 29491 }; /*
0.99, 0.9 */ |
40 | 40 |
41 static OPUS_INLINE void silk_PLC_update( | 41 static OPUS_INLINE void silk_PLC_update( |
42 silk_decoder_state *psDec, /* I/O Decoder state
*/ | 42 silk_decoder_state *psDec, /* I/O Decoder state
*/ |
43 silk_decoder_control *psDecCtrl /* I/O Decoder contr
ol */ | 43 silk_decoder_control *psDecCtrl /* I/O Decoder contr
ol */ |
44 ); | 44 ); |
45 | 45 |
46 static OPUS_INLINE void silk_PLC_conceal( | 46 static OPUS_INLINE void silk_PLC_conceal( |
47 silk_decoder_state *psDec, /* I/O Decoder state
*/ | 47 silk_decoder_state *psDec, /* I/O Decoder state
*/ |
48 silk_decoder_control *psDecCtrl, /* I/O Decoder contr
ol */ | 48 silk_decoder_control *psDecCtrl, /* I/O Decoder contr
ol */ |
49 opus_int16 frame[] /* O LPC residual si
gnal */ | 49 opus_int16 frame[], /* O LPC residual si
gnal */ |
| 50 int arch /* I Run-time archi
tecture */ |
50 ); | 51 ); |
51 | 52 |
52 | 53 |
53 void silk_PLC_Reset( | 54 void silk_PLC_Reset( |
54 silk_decoder_state *psDec /* I/O Decoder state
*/ | 55 silk_decoder_state *psDec /* I/O Decoder state
*/ |
55 ) | 56 ) |
56 { | 57 { |
57 psDec->sPLC.pitchL_Q8 = silk_LSHIFT( psDec->frame_length, 8 - 1 ); | 58 psDec->sPLC.pitchL_Q8 = silk_LSHIFT( psDec->frame_length, 8 - 1 ); |
58 psDec->sPLC.prevGain_Q16[ 0 ] = SILK_FIX_CONST( 1, 16 ); | 59 psDec->sPLC.prevGain_Q16[ 0 ] = SILK_FIX_CONST( 1, 16 ); |
59 psDec->sPLC.prevGain_Q16[ 1 ] = SILK_FIX_CONST( 1, 16 ); | 60 psDec->sPLC.prevGain_Q16[ 1 ] = SILK_FIX_CONST( 1, 16 ); |
60 psDec->sPLC.subfr_length = 20; | 61 psDec->sPLC.subfr_length = 20; |
61 psDec->sPLC.nb_subfr = 2; | 62 psDec->sPLC.nb_subfr = 2; |
62 } | 63 } |
63 | 64 |
64 void silk_PLC( | 65 void silk_PLC( |
65 silk_decoder_state *psDec, /* I/O Decoder state
*/ | 66 silk_decoder_state *psDec, /* I/O Decoder state
*/ |
66 silk_decoder_control *psDecCtrl, /* I/O Decoder contr
ol */ | 67 silk_decoder_control *psDecCtrl, /* I/O Decoder contr
ol */ |
67 opus_int16 frame[], /* I/O signal
*/ | 68 opus_int16 frame[], /* I/O signal
*/ |
68 opus_int lost /* I Loss flag
*/ | 69 opus_int lost, /* I Loss flag
*/ |
| 70 int arch /* I Run-time archit
ecture */ |
69 ) | 71 ) |
70 { | 72 { |
71 /* PLC control function */ | 73 /* PLC control function */ |
72 if( psDec->fs_kHz != psDec->sPLC.fs_kHz ) { | 74 if( psDec->fs_kHz != psDec->sPLC.fs_kHz ) { |
73 silk_PLC_Reset( psDec ); | 75 silk_PLC_Reset( psDec ); |
74 psDec->sPLC.fs_kHz = psDec->fs_kHz; | 76 psDec->sPLC.fs_kHz = psDec->fs_kHz; |
75 } | 77 } |
76 | 78 |
77 if( lost ) { | 79 if( lost ) { |
78 /****************************/ | 80 /****************************/ |
79 /* Generate Signal */ | 81 /* Generate Signal */ |
80 /****************************/ | 82 /****************************/ |
81 silk_PLC_conceal( psDec, psDecCtrl, frame ); | 83 silk_PLC_conceal( psDec, psDecCtrl, frame, arch ); |
82 | 84 |
83 psDec->lossCnt++; | 85 psDec->lossCnt++; |
84 } else { | 86 } else { |
85 /****************************/ | 87 /****************************/ |
86 /* Update state */ | 88 /* Update state */ |
87 /****************************/ | 89 /****************************/ |
88 silk_PLC_update( psDec, psDecCtrl ); | 90 silk_PLC_update( psDec, psDecCtrl ); |
89 } | 91 } |
90 } | 92 } |
91 | 93 |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 silk_memcpy( psPLC->prevLPC_Q12, psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_or
der * sizeof( opus_int16 ) ); | 160 silk_memcpy( psPLC->prevLPC_Q12, psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_or
der * sizeof( opus_int16 ) ); |
159 psPLC->prevLTP_scale_Q14 = psDecCtrl->LTP_scale_Q14; | 161 psPLC->prevLTP_scale_Q14 = psDecCtrl->LTP_scale_Q14; |
160 | 162 |
161 /* Save last two gains */ | 163 /* Save last two gains */ |
162 silk_memcpy( psPLC->prevGain_Q16, &psDecCtrl->Gains_Q16[ psDec->nb_subfr - 2
], 2 * sizeof( opus_int32 ) ); | 164 silk_memcpy( psPLC->prevGain_Q16, &psDecCtrl->Gains_Q16[ psDec->nb_subfr - 2
], 2 * sizeof( opus_int32 ) ); |
163 | 165 |
164 psPLC->subfr_length = psDec->subfr_length; | 166 psPLC->subfr_length = psDec->subfr_length; |
165 psPLC->nb_subfr = psDec->nb_subfr; | 167 psPLC->nb_subfr = psDec->nb_subfr; |
166 } | 168 } |
167 | 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 |
168 static OPUS_INLINE void silk_PLC_conceal( | 194 static OPUS_INLINE void silk_PLC_conceal( |
169 silk_decoder_state *psDec, /* I/O Decoder state
*/ | 195 silk_decoder_state *psDec, /* I/O Decoder state
*/ |
170 silk_decoder_control *psDecCtrl, /* I/O Decoder contr
ol */ | 196 silk_decoder_control *psDecCtrl, /* I/O Decoder contr
ol */ |
171 opus_int16 frame[] /* O LPC residual si
gnal */ | 197 opus_int16 frame[], /* O LPC residual si
gnal */ |
| 198 int arch /* I Run-time archit
ecture */ |
172 ) | 199 ) |
173 { | 200 { |
174 opus_int i, j, k; | 201 opus_int i, j, k; |
175 opus_int lag, idx, sLTP_buf_idx, shift1, shift2; | 202 opus_int lag, idx, sLTP_buf_idx, shift1, shift2; |
176 opus_int32 rand_seed, harm_Gain_Q15, rand_Gain_Q15, inv_gain_Q30; | 203 opus_int32 rand_seed, harm_Gain_Q15, rand_Gain_Q15, inv_gain_Q30; |
177 opus_int32 energy1, energy2, *rand_ptr, *pred_lag_ptr; | 204 opus_int32 energy1, energy2, *rand_ptr, *pred_lag_ptr; |
178 opus_int32 LPC_pred_Q10, LTP_pred_Q12; | 205 opus_int32 LPC_pred_Q10, LTP_pred_Q12; |
179 opus_int16 rand_scale_Q14; | 206 opus_int16 rand_scale_Q14; |
180 opus_int16 *B_Q14, *exc_buf_ptr; | 207 opus_int16 *B_Q14; |
181 opus_int32 *sLPC_Q14_ptr; | 208 opus_int32 *sLPC_Q14_ptr; |
182 VARDECL( opus_int16, exc_buf ); | |
183 opus_int16 A_Q12[ MAX_LPC_ORDER ]; | 209 opus_int16 A_Q12[ MAX_LPC_ORDER ]; |
| 210 #ifdef SMALL_FOOTPRINT |
| 211 opus_int16 *sLTP; |
| 212 #else |
184 VARDECL( opus_int16, sLTP ); | 213 VARDECL( opus_int16, sLTP ); |
| 214 #endif |
185 VARDECL( opus_int32, sLTP_Q14 ); | 215 VARDECL( opus_int32, sLTP_Q14 ); |
186 silk_PLC_struct *psPLC = &psDec->sPLC; | 216 silk_PLC_struct *psPLC = &psDec->sPLC; |
187 opus_int32 prevGain_Q10[2]; | 217 opus_int32 prevGain_Q10[2]; |
188 SAVE_STACK; | 218 SAVE_STACK; |
189 | 219 |
190 ALLOC( exc_buf, 2*psPLC->subfr_length, opus_int16 ); | 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 |
191 ALLOC( sLTP, psDec->ltp_mem_length, opus_int16 ); | 225 ALLOC( sLTP, psDec->ltp_mem_length, opus_int16 ); |
192 ALLOC( sLTP_Q14, psDec->ltp_mem_length + psDec->frame_length, opus_int32 ); | 226 #endif |
193 | 227 |
194 prevGain_Q10[0] = silk_RSHIFT( psPLC->prevGain_Q16[ 0 ], 6); | 228 prevGain_Q10[0] = silk_RSHIFT( psPLC->prevGain_Q16[ 0 ], 6); |
195 prevGain_Q10[1] = silk_RSHIFT( psPLC->prevGain_Q16[ 1 ], 6); | 229 prevGain_Q10[1] = silk_RSHIFT( psPLC->prevGain_Q16[ 1 ], 6); |
196 | 230 |
197 if( psDec->first_frame_after_reset ) { | 231 if( psDec->first_frame_after_reset ) { |
198 silk_memset( psPLC->prevLPC_Q12, 0, sizeof( psPLC->prevLPC_Q12 ) ); | 232 silk_memset( psPLC->prevLPC_Q12, 0, sizeof( psPLC->prevLPC_Q12 ) ); |
199 } | 233 } |
200 | 234 |
201 /* Find random noise component */ | 235 silk_PLC_energy(&energy1, &shift1, &energy2, &shift2, psDec->exc_Q14, prevGa
in_Q10, psDec->subfr_length, psDec->nb_subfr); |
202 /* Scale previous excitation signal */ | |
203 exc_buf_ptr = exc_buf; | |
204 for( k = 0; k < 2; k++ ) { | |
205 for( i = 0; i < psPLC->subfr_length; i++ ) { | |
206 exc_buf_ptr[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT( | |
207 silk_SMULWW( psDec->exc_Q14[ i + ( k + psPLC->nb_subfr - 2 ) * p
sPLC->subfr_length ], prevGain_Q10[ k ] ), 8 ) ); | |
208 } | |
209 exc_buf_ptr += psPLC->subfr_length; | |
210 } | |
211 /* Find the subframe with lowest energy of the last two and use that as rand
om noise generator */ | |
212 silk_sum_sqr_shift( &energy1, &shift1, exc_buf, psPL
C->subfr_length ); | |
213 silk_sum_sqr_shift( &energy2, &shift2, &exc_buf[ psPLC->subfr_length ], psPL
C->subfr_length ); | |
214 | 236 |
215 if( silk_RSHIFT( energy1, shift2 ) < silk_RSHIFT( energy2, shift1 ) ) { | 237 if( silk_RSHIFT( energy1, shift2 ) < silk_RSHIFT( energy2, shift1 ) ) { |
216 /* First sub-frame has lowest energy */ | 238 /* First sub-frame has lowest energy */ |
217 rand_ptr = &psDec->exc_Q14[ silk_max_int( 0, ( psPLC->nb_subfr - 1 ) * p
sPLC->subfr_length - RAND_BUF_SIZE ) ]; | 239 rand_ptr = &psDec->exc_Q14[ silk_max_int( 0, ( psPLC->nb_subfr - 1 ) * p
sPLC->subfr_length - RAND_BUF_SIZE ) ]; |
218 } else { | 240 } else { |
219 /* Second sub-frame has lowest energy */ | 241 /* Second sub-frame has lowest energy */ |
220 rand_ptr = &psDec->exc_Q14[ silk_max_int( 0, psPLC->nb_subfr * psPLC->su
bfr_length - RAND_BUF_SIZE ) ]; | 242 rand_ptr = &psDec->exc_Q14[ silk_max_int( 0, psPLC->nb_subfr * psPLC->su
bfr_length - RAND_BUF_SIZE ) ]; |
221 } | 243 } |
222 | 244 |
223 /* Set up Gain to random noise component */ | 245 /* Set up Gain to random noise component */ |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
263 } | 285 } |
264 } | 286 } |
265 | 287 |
266 rand_seed = psPLC->rand_seed; | 288 rand_seed = psPLC->rand_seed; |
267 lag = silk_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 ); | 289 lag = silk_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 ); |
268 sLTP_buf_idx = psDec->ltp_mem_length; | 290 sLTP_buf_idx = psDec->ltp_mem_length; |
269 | 291 |
270 /* Rewhiten LTP state */ | 292 /* Rewhiten LTP state */ |
271 idx = psDec->ltp_mem_length - lag - psDec->LPC_order - LTP_ORDER / 2; | 293 idx = psDec->ltp_mem_length - lag - psDec->LPC_order - LTP_ORDER / 2; |
272 silk_assert( idx > 0 ); | 294 silk_assert( idx > 0 ); |
273 silk_LPC_analysis_filter( &sLTP[ idx ], &psDec->outBuf[ idx ], A_Q12, psDec-
>ltp_mem_length - idx, psDec->LPC_order ); | 295 silk_LPC_analysis_filter( &sLTP[ idx ], &psDec->outBuf[ idx ], A_Q12, psDec-
>ltp_mem_length - idx, psDec->LPC_order, arch ); |
274 /* Scale LTP state */ | 296 /* Scale LTP state */ |
275 inv_gain_Q30 = silk_INVERSE32_varQ( psPLC->prevGain_Q16[ 1 ], 46 ); | 297 inv_gain_Q30 = silk_INVERSE32_varQ( psPLC->prevGain_Q16[ 1 ], 46 ); |
276 inv_gain_Q30 = silk_min( inv_gain_Q30, silk_int32_MAX >> 1 ); | 298 inv_gain_Q30 = silk_min( inv_gain_Q30, silk_int32_MAX >> 1 ); |
277 for( i = idx + psDec->LPC_order; i < psDec->ltp_mem_length; i++ ) { | 299 for( i = idx + psDec->LPC_order; i < psDec->ltp_mem_length; i++ ) { |
278 sLTP_Q14[ i ] = silk_SMULWB( inv_gain_Q30, sLTP[ i ] ); | 300 sLTP_Q14[ i ] = silk_SMULWB( inv_gain_Q30, sLTP[ i ] ); |
279 } | 301 } |
280 | 302 |
281 /***************************/ | 303 /***************************/ |
282 /* LTP synthesis filtering */ | 304 /* LTP synthesis filtering */ |
283 /***************************/ | 305 /***************************/ |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
414 gain_Q16 += slope_Q16; | 436 gain_Q16 += slope_Q16; |
415 if( gain_Q16 > (opus_int32)1 << 16 ) { | 437 if( gain_Q16 > (opus_int32)1 << 16 ) { |
416 break; | 438 break; |
417 } | 439 } |
418 } | 440 } |
419 } | 441 } |
420 } | 442 } |
421 psPLC->last_frame_lost = 0; | 443 psPLC->last_frame_lost = 0; |
422 } | 444 } |
423 } | 445 } |
OLD | NEW |