|
@@ -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 );
|
|
|
-
|
|
|
- frame[ i ] = silk_ADD_SAT16( frame[ i ], silk_RSHIFT_ROUND( CNG_sig_Q10[ MAX_LPC_ORDER + i ], 10 ) );
|
|
|
+ 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 ) ) );
|
|
|
+
|
|
|
}
|
|
|
- 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 ) );
|
|
|
}
|