mirror of
https://github.com/xiph/opus.git
synced 2025-05-31 23:57:42 +00:00
cng exitation signal can saturate. Use same scaling as PLC and normal decoding
This commit is contained in:
parent
e40df01625
commit
fab6397ae6
1 changed files with 32 additions and 29 deletions
59
silk/CNG.c
59
silk/CNG.c
|
@ -34,9 +34,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
/* Generates excitation for CNG LPC synthesis */
|
||||
static OPUS_INLINE void silk_CNG_exc(
|
||||
opus_int32 exc_Q10[], /* O CNG excitation signal Q10 */
|
||||
opus_int32 exc_Q14[], /* O CNG excitation signal Q10 */
|
||||
opus_int32 exc_buf_Q14[], /* I Random samples buffer Q10 */
|
||||
opus_int32 Gain_Q16, /* I Gain to apply */
|
||||
opus_int length, /* I Length */
|
||||
opus_int32 *rand_seed /* I/O Seed to random index generator */
|
||||
)
|
||||
|
@ -55,7 +54,7 @@ static OPUS_INLINE void silk_CNG_exc(
|
|||
idx = (opus_int)( silk_RSHIFT( seed, 24 ) & exc_mask );
|
||||
silk_assert( idx >= 0 );
|
||||
silk_assert( idx <= CNG_BUF_MASK_MAX );
|
||||
exc_Q10[ i ] = (opus_int16)silk_SAT16( silk_SMULWW( exc_buf_Q14[ idx ], Gain_Q16 >> 4 ) );
|
||||
exc_Q14[ i ] = exc_buf_Q14[ idx ];
|
||||
}
|
||||
*rand_seed = seed;
|
||||
}
|
||||
|
@ -85,7 +84,7 @@ void silk_CNG(
|
|||
)
|
||||
{
|
||||
opus_int i, subfr;
|
||||
opus_int32 sum_Q6, max_Gain_Q16, gain_Q16;
|
||||
opus_int32 LPC_pred_Q10, max_Gain_Q16, gain_Q16, gain_Q10;
|
||||
opus_int16 A_Q12[ MAX_LPC_ORDER ];
|
||||
silk_CNG_struct *psCNG = &psDec->sCNG;
|
||||
SAVE_STACK;
|
||||
|
@ -124,8 +123,8 @@ void silk_CNG(
|
|||
|
||||
/* Add CNG when packet is lost or during DTX */
|
||||
if( psDec->lossCnt ) {
|
||||
VARDECL( opus_int32, CNG_sig_Q10 );
|
||||
ALLOC( CNG_sig_Q10, length + MAX_LPC_ORDER, opus_int32 );
|
||||
VARDECL( opus_int32, CNG_sig_Q14 );
|
||||
ALLOC( CNG_sig_Q14, length + MAX_LPC_ORDER, opus_int32 );
|
||||
|
||||
/* Generate CNG excitation */
|
||||
gain_Q16 = silk_SMULWW( psDec->sPLC.randScale_Q14, psDec->sPLC.prevGain_Q16[1] );
|
||||
|
@ -138,42 +137,46 @@ void silk_CNG(
|
|||
gain_Q16 = silk_SUB_LSHIFT32(silk_SMULWW( psCNG->CNG_smth_Gain_Q16, psCNG->CNG_smth_Gain_Q16 ), gain_Q16, 5 );
|
||||
gain_Q16 = silk_LSHIFT32( silk_SQRT_APPROX( gain_Q16 ), 8 );
|
||||
}
|
||||
silk_CNG_exc( CNG_sig_Q10 + MAX_LPC_ORDER, psCNG->CNG_exc_buf_Q14, gain_Q16, length, &psCNG->rand_seed );
|
||||
gain_Q10 = silk_RSHIFT( gain_Q16, 6 );
|
||||
|
||||
silk_CNG_exc( CNG_sig_Q14 + MAX_LPC_ORDER, psCNG->CNG_exc_buf_Q14, length, &psCNG->rand_seed );
|
||||
|
||||
/* Convert CNG NLSF to filter representation */
|
||||
silk_NLSF2A( A_Q12, psCNG->CNG_smth_NLSF_Q15, psDec->LPC_order );
|
||||
|
||||
/* Generate CNG signal, by synthesis filtering */
|
||||
silk_memcpy( CNG_sig_Q10, psCNG->CNG_synth_state, MAX_LPC_ORDER * sizeof( opus_int32 ) );
|
||||
silk_memcpy( CNG_sig_Q14, psCNG->CNG_synth_state, MAX_LPC_ORDER * sizeof( opus_int32 ) );
|
||||
for( i = 0; i < length; i++ ) {
|
||||
silk_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 );
|
||||
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
|
||||
sum_Q6 = silk_RSHIFT( psDec->LPC_order, 1 );
|
||||
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 1 ], A_Q12[ 0 ] );
|
||||
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 2 ], A_Q12[ 1 ] );
|
||||
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 3 ], A_Q12[ 2 ] );
|
||||
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 4 ], A_Q12[ 3 ] );
|
||||
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 5 ], A_Q12[ 4 ] );
|
||||
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 6 ], A_Q12[ 5 ] );
|
||||
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 7 ], A_Q12[ 6 ] );
|
||||
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 8 ], A_Q12[ 7 ] );
|
||||
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 9 ], A_Q12[ 8 ] );
|
||||
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 10 ], A_Q12[ 9 ] );
|
||||
LPC_pred_Q10 = silk_RSHIFT( psDec->LPC_order, 1 );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 1 ], A_Q12[ 0 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 2 ], A_Q12[ 1 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 3 ], A_Q12[ 2 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 4 ], A_Q12[ 3 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 5 ], A_Q12[ 4 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 6 ], A_Q12[ 5 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 7 ], A_Q12[ 6 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 8 ], A_Q12[ 7 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 9 ], A_Q12[ 8 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 10 ], A_Q12[ 9 ] );
|
||||
if( psDec->LPC_order == 16 ) {
|
||||
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 11 ], A_Q12[ 10 ] );
|
||||
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 12 ], A_Q12[ 11 ] );
|
||||
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 13 ], A_Q12[ 12 ] );
|
||||
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 14 ], A_Q12[ 13 ] );
|
||||
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 15 ], A_Q12[ 14 ] );
|
||||
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 16 ], A_Q12[ 15 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 11 ], A_Q12[ 10 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 12 ], A_Q12[ 11 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 13 ], A_Q12[ 12 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 14 ], A_Q12[ 13 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 15 ], A_Q12[ 14 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 16 ], A_Q12[ 15 ] );
|
||||
}
|
||||
|
||||
/* Update states */
|
||||
CNG_sig_Q10[ MAX_LPC_ORDER + i ] = silk_ADD_LSHIFT( CNG_sig_Q10[ MAX_LPC_ORDER + i ], sum_Q6, 4 );
|
||||
CNG_sig_Q14[ MAX_LPC_ORDER + i ] = silk_ADD_LSHIFT( CNG_sig_Q14[ MAX_LPC_ORDER + i ], LPC_pred_Q10, 4 );
|
||||
|
||||
/* Scale with Gain and add to input signal */
|
||||
frame[ i ] = (opus_int16)silk_ADD_SAT16( frame[ i ], silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( CNG_sig_Q14[ MAX_LPC_ORDER + i ], gain_Q10 ), 8 ) ) );
|
||||
|
||||
frame[ i ] = silk_ADD_SAT16( frame[ i ], silk_RSHIFT_ROUND( CNG_sig_Q10[ MAX_LPC_ORDER + i ], 10 ) );
|
||||
}
|
||||
silk_memcpy( psCNG->CNG_synth_state, &CNG_sig_Q10[ length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
|
||||
silk_memcpy( psCNG->CNG_synth_state, &CNG_sig_Q14[ length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
|
||||
} else {
|
||||
silk_memset( psCNG->CNG_synth_state, 0, psDec->LPC_order * sizeof( opus_int32 ) );
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue