Fixes two SILK PLC issues

- Calling the decoder for FEC when there's no LBRR should no longer crash
- There should no longer be an issue with the PLC on frame size switching
This commit is contained in:
Koen Vos 2011-10-28 21:05:22 -04:00 committed by Jean-Marc Valin
parent acc7a6c78b
commit 0dbd0ca3e6
5 changed files with 25 additions and 18 deletions

View file

@ -54,6 +54,8 @@ void silk_PLC_Reset(
) )
{ {
psDec->sPLC.pitchL_Q8 = silk_RSHIFT( psDec->frame_length, 1 ); psDec->sPLC.pitchL_Q8 = silk_RSHIFT( psDec->frame_length, 1 );
psDec->sPLC.prevGain_Q16[ 0 ] = SILK_FIX_CONST( 1, 16 );
psDec->sPLC.prevGain_Q16[ 1 ] = SILK_FIX_CONST( 1, 16 );
} }
void silk_PLC( void silk_PLC(
@ -155,8 +157,11 @@ static inline void silk_PLC_update(
silk_memcpy( psPLC->prevLPC_Q12, psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_order * sizeof( opus_int16 ) ); silk_memcpy( psPLC->prevLPC_Q12, psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_order * sizeof( opus_int16 ) );
psPLC->prevLTP_scale_Q14 = psDecCtrl->LTP_scale_Q14; psPLC->prevLTP_scale_Q14 = psDecCtrl->LTP_scale_Q14;
/* Save Gains */ /* Save last two gains */
silk_memcpy( psPLC->prevGain_Q16, psDecCtrl->Gains_Q16, psDec->nb_subfr * sizeof( opus_int32 ) ); silk_memcpy( psPLC->prevGain_Q16, &psDecCtrl->Gains_Q16[ psDec->nb_subfr - 2 ], 2 * sizeof( opus_int32 ) );
psPLC->subfr_length = psDec->subfr_length;
psPLC->nb_subfr = psDec->nb_subfr;
} }
static inline void silk_PLC_conceal( static inline void silk_PLC_conceal(
@ -182,23 +187,23 @@ static inline void silk_PLC_conceal(
/* Find random noise component */ /* Find random noise component */
/* Scale previous excitation signal */ /* Scale previous excitation signal */
exc_buf_ptr = exc_buf; exc_buf_ptr = exc_buf;
for( k = psDec->nb_subfr - 2; k < psDec->nb_subfr; k++ ) { for( k = 0; k < 2; k++ ) {
for( i = 0; i < psDec->subfr_length; i++ ) { for( i = 0; i < psPLC->subfr_length; i++ ) {
exc_buf_ptr[ i ] = ( opus_int16 )silk_RSHIFT( exc_buf_ptr[ i ] = ( opus_int16 )silk_RSHIFT(
silk_SMULWW( psDec->exc_Q10[ i + k * psDec->subfr_length ], psPLC->prevGain_Q16[ k ] ), 10 ); silk_SMULWW( psDec->exc_Q10[ i + ( k + psPLC->nb_subfr - 2 ) * psPLC->subfr_length ], psPLC->prevGain_Q16[ k ] ), 10 );
} }
exc_buf_ptr += psDec->subfr_length; exc_buf_ptr += psPLC->subfr_length;
} }
/* Find the subframe with lowest energy of the last two and use that as random noise generator */ /* Find the subframe with lowest energy of the last two and use that as random noise generator */
silk_sum_sqr_shift( &energy1, &shift1, exc_buf, psDec->subfr_length ); silk_sum_sqr_shift( &energy1, &shift1, exc_buf, psPLC->subfr_length );
silk_sum_sqr_shift( &energy2, &shift2, &exc_buf[ psDec->subfr_length ], psDec->subfr_length ); silk_sum_sqr_shift( &energy2, &shift2, &exc_buf[ psDec->subfr_length ], psPLC->subfr_length );
if( silk_RSHIFT( energy1, shift2 ) < silk_RSHIFT( energy2, shift1 ) ) { if( silk_RSHIFT( energy1, shift2 ) < silk_RSHIFT( energy2, shift1 ) ) {
/* First sub-frame has lowest energy */ /* First sub-frame has lowest energy */
rand_ptr = &psDec->exc_Q10[ silk_max_int( 0, psDec->frame_length - psDec->subfr_length - RAND_BUF_SIZE ) ]; rand_ptr = &psDec->exc_Q10[ silk_max_int( 0, ( psPLC->nb_subfr - 1 ) * psPLC->subfr_length - RAND_BUF_SIZE ) ];
} else { } else {
/* Second sub-frame has lowest energy */ /* Second sub-frame has lowest energy */
rand_ptr = &psDec->exc_Q10[ silk_max_int( 0, psDec->frame_length - RAND_BUF_SIZE ) ]; rand_ptr = &psDec->exc_Q10[ silk_max_int( 0, psPLC->nb_subfr * psPLC->subfr_length - RAND_BUF_SIZE ) ];
} }
/* Setup Gain to random noise component */ /* Setup Gain to random noise component */
@ -253,7 +258,7 @@ static inline void silk_PLC_conceal(
silk_assert( idx > 0 ); silk_assert( idx > 0 );
silk_LPC_analysis_filter( &sLTP[ idx ], &psDec->outBuf[ idx ], A_Q12, psDec->ltp_mem_length - idx, psDec->LPC_order ); silk_LPC_analysis_filter( &sLTP[ idx ], &psDec->outBuf[ idx ], A_Q12, psDec->ltp_mem_length - idx, psDec->LPC_order );
/* Scale LTP state */ /* Scale LTP state */
inv_gain_Q16 = silk_INVERSE32_varQ( psPLC->prevGain_Q16[ psDec->nb_subfr - 1 ], 32 ); inv_gain_Q16 = silk_INVERSE32_varQ( psPLC->prevGain_Q16[ 1 ], 32 );
inv_gain_Q16 = silk_min( inv_gain_Q16, silk_int16_MAX ); inv_gain_Q16 = silk_min( inv_gain_Q16, silk_int16_MAX );
inv_gain_Q30 = silk_LSHIFT( inv_gain_Q16, 14 ); inv_gain_Q30 = silk_LSHIFT( inv_gain_Q16, 14 );
for( i = idx + psDec->LPC_order; i < psDec->ltp_mem_length; i++ ) { for( i = idx + psDec->LPC_order; i < psDec->ltp_mem_length; i++ ) {
@ -326,7 +331,7 @@ static inline void silk_PLC_conceal(
sLPC_Q14_ptr[ MAX_LPC_ORDER + i ] = silk_ADD_LSHIFT32( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], LPC_pred_Q10, 4 ); sLPC_Q14_ptr[ MAX_LPC_ORDER + i ] = silk_ADD_LSHIFT32( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], LPC_pred_Q10, 4 );
/* Scale with Gain */ /* Scale with Gain */
frame[ i ] = ( opus_int16 )silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], psPLC->prevGain_Q16[ psDec->nb_subfr - 1 ] ), 14 ) ); frame[ i ] = ( opus_int16 )silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], psPLC->prevGain_Q16[ 1 ] ), 14 ) );
} }
/* Save LPC state */ /* Save LPC state */
@ -342,7 +347,7 @@ static inline void silk_PLC_conceal(
} }
} }
/* Glues concealed frames with new good recieved frames */ /* Glues concealed frames with new good recieved frames */
void silk_PLC_glue_frames( void silk_PLC_glue_frames(
silk_decoder_state *psDec, /* I/O decoder state */ silk_decoder_state *psDec, /* I/O decoder state */
opus_int16 frame[], /* I/O signal */ opus_int16 frame[], /* I/O signal */

View file

@ -97,7 +97,6 @@
<ClCompile Include="control_audio_bandwidth.c" /> <ClCompile Include="control_audio_bandwidth.c" />
<ClCompile Include="control_codec.c" /> <ClCompile Include="control_codec.c" />
<ClCompile Include="control_SNR.c" /> <ClCompile Include="control_SNR.c" />
<ClCompile Include="create_init_destroy.c" />
<ClCompile Include="debug.c" /> <ClCompile Include="debug.c" />
<ClCompile Include="decoder_set_fs.c" /> <ClCompile Include="decoder_set_fs.c" />
<ClCompile Include="decode_core.c" /> <ClCompile Include="decode_core.c" />
@ -112,6 +111,7 @@
<ClCompile Include="enc_API.c" /> <ClCompile Include="enc_API.c" />
<ClCompile Include="gain_quant.c" /> <ClCompile Include="gain_quant.c" />
<ClCompile Include="HP_variable_cutoff.c" /> <ClCompile Include="HP_variable_cutoff.c" />
<ClCompile Include="init_decoder.c" />
<ClCompile Include="init_encoder.c" /> <ClCompile Include="init_encoder.c" />
<ClCompile Include="inner_prod_aligned.c" /> <ClCompile Include="inner_prod_aligned.c" />
<ClCompile Include="interpolate.c" /> <ClCompile Include="interpolate.c" />

View file

@ -51,9 +51,6 @@
<ClCompile Include="control_SNR.c"> <ClCompile Include="control_SNR.c">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="create_init_destroy.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="debug.c"> <ClCompile Include="debug.c">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
@ -246,6 +243,9 @@
<ClCompile Include="VQ_WMat_EC.c"> <ClCompile Include="VQ_WMat_EC.c">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="init_decoder.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\win32\config.h"> <ClInclude Include="..\win32\config.h">

View file

@ -237,8 +237,10 @@ typedef struct {
opus_int32 conc_energy; opus_int32 conc_energy;
opus_int conc_energy_shift; opus_int conc_energy_shift;
opus_int16 prevLTP_scale_Q14; opus_int16 prevLTP_scale_Q14;
opus_int32 prevGain_Q16[ MAX_NB_SUBFR ]; opus_int32 prevGain_Q16[ 2 ];
opus_int fs_kHz; opus_int fs_kHz;
opus_int nb_subfr;
opus_int subfr_length;
} silk_PLC_struct; } silk_PLC_struct;
/* Struct for CNG */ /* Struct for CNG */