| 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 |