From cd92a07b48764d9894942c70519c1e073c76a149 Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Tue, 5 Nov 2024 14:04:33 +0530 Subject: [PATCH 1/2] Fix for 3GPP issue 784: BASOP decoder without JBM not BE to BASOP decoder with zero-delay profile [x] Changed implementation of apa_exec to take 32 bit input and changed intermediate processing to take variable Q. [x] Validated changes for 3GPP issues #979 and #980. --- lib_dec/jbm_pcmdsp_apa.c | 44 +++++++++++++++++++++++++++++++--------- lib_dec/jbm_pcmdsp_apa.h | 2 +- lib_dec/lib_dec_fx.c | 26 ++---------------------- 3 files changed, 37 insertions(+), 35 deletions(-) diff --git a/lib_dec/jbm_pcmdsp_apa.c b/lib_dec/jbm_pcmdsp_apa.c index 1ddb7fee6..942a5a906 100644 --- a/lib_dec/jbm_pcmdsp_apa.c +++ b/lib_dec/jbm_pcmdsp_apa.c @@ -76,6 +76,7 @@ struct apa_state_t bool evs_compat_mode; Word16 *buf_out_fx; + Word16 Q_buf_out; UWord16 buf_out_capacity; UWord16 l_buf_out; @@ -183,6 +184,8 @@ ivas_error apa_init( { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for JBM\n" ) ); } + ps->Q_buf_out = Q15; + move16(); ps->evs_compat_mode = false; move16(); @@ -262,6 +265,8 @@ UWord8 apa_reconfigure( free( ps->buf_out_fx ); ps->buf_out_fx = (Word16 *) malloc( sizeof( Word16 ) * ps->buf_out_capacity ); + ps->Q_buf_out = Q15; + move16(); IF( !ps->buf_out_fx ) { return 2; @@ -871,10 +876,10 @@ UWord8 apa_exec_fx( UWord8 apa_exec_ivas_fx( apa_state_t *ps, /* i/o: state struct */ - const Word16 a_in[], /* i : input samples Q(-1) */ + const Word32 a_in[], /* i : input samples Q(-1) */ UWord16 l_in, /* i : number of input samples */ UWord16 maxScaling, /* i : allowed number of inserted/removed samples */ - Word16 a_out[], /* o : output samples Q(-1) */ + Word32 a_out[], /* o : output samples Q(-1) */ UWord16 *l_out /* o : number of output samples */ ) { @@ -885,7 +890,9 @@ UWord8 apa_exec_ivas_fx( Word32 dl_scaled, dl_copied, l_frm_out_target; Word32 expScaling, actScaling; UWord32 statsResetThreshold, statsResetShift; + Word16 Q_a_out; + Q_a_out = add( getScaleFactor32( a_in, i_mult( ps->num_channels, APA_BUF_PER_CHANNEL ) ), Q11 - Q16 ); statsResetThreshold = 1637; move32(); statsResetShift = 2; @@ -942,16 +949,25 @@ UWord8 apa_exec_ivas_fx( FOR( i = 0; i < ps->l_frm; i++ ) { a_out[i] = a_in[i]; - move16(); + move32(); } l_frm_out = ps->l_frm; move16(); } ELSE { + Word16 a_tmp[APA_BUF]; Word16 *buf_out_ptr = &( ps->buf_out_fx[ps->l_buf_out - ps->l_frm] ); Word16 *frm_in_ptr = &( frm_in[ps->l_frm] ); + Q_a_out = s_min( Q_a_out, ps->Q_buf_out ); + FOR( i = 0; i < ps->num_channels * APA_BUF_PER_CHANNEL; i++ ) + { + a_tmp[i] = extract_h( L_shl( a_in[i], add( Q_a_out, Q5 ) ) ); // Q_a_out + move16(); + } + Scale_sig( ps->buf_out_fx, ps->buf_out_capacity, sub( Q_a_out, ps->Q_buf_out ) ); // Q_buf_out -> Q_a_out + /* fill input frame */ /* 1st input frame: previous output samples */ FOR( i = 0; i < ps->l_frm; i++ ) @@ -962,23 +978,23 @@ UWord8 apa_exec_ivas_fx( /* 2nd input frame: new input samples */ FOR( i = 0; i < ps->l_frm; i++ ) { - frm_in_ptr[i] = a_in[i]; + frm_in_ptr[i] = a_tmp[i]; move16(); } /* no scaling */ IF( EQ_32( ps->scale, 100 ) ) { - copy_frm_fx( ps, frm_in, a_out, &l_frm_out ); + copy_frm_fx( ps, frm_in, a_tmp, &l_frm_out ); } /* shrink */ ELSE IF( LT_32( ps->scale, 100 ) ) { - shrink_frm_fx( ps, frm_in, maxScaling, a_out, &l_frm_out ); + shrink_frm_fx( ps, frm_in, maxScaling, a_tmp, &l_frm_out ); } /* extend */ ELSE { - extend_frm_fx( ps, frm_in, a_out, &l_frm_out ); + extend_frm_fx( ps, frm_in, a_tmp, &l_frm_out ); } /* control the amount/frequency of scaling */ IF( NE_32( l_frm_out, ps->l_frm ) ) @@ -988,7 +1004,7 @@ UWord8 apa_exec_ivas_fx( GT_32( abs_s( extract_l( L_sub( ps->l_frm, l_frm_out ) ) ), maxScaling ) ) { /* maxScaling exceeded -> discard scaled frame */ - copy_frm_fx( ps, frm_in, a_out, &l_frm_out ); + copy_frm_fx( ps, frm_in, a_tmp, &l_frm_out ); } ELSE IF( GT_32( L_abs( l_frm_out_target ), ps->l_frm ) ) /* ignore small difference */ { @@ -997,10 +1013,16 @@ UWord8 apa_exec_ivas_fx( /* discard scaled frame if copied frame is closer to target length */ IF( LT_32( L_abs( dl_copied ), L_abs( dl_scaled ) ) ) { - copy_frm_fx( ps, frm_in, a_out, &l_frm_out ); + copy_frm_fx( ps, frm_in, a_tmp, &l_frm_out ); } } } + + FOR( i = 0; i < ps->num_channels * APA_BUF_PER_CHANNEL; i++ ) + { + a_out[i] = L_shl( a_tmp[i], sub( Q11, Q_a_out ) ); // Q0 -> Q11 + move32(); + } } /* copy output to internal buffer */ @@ -1035,9 +1057,11 @@ UWord8 apa_exec_ivas_fx( Word16 *buf_out_ptr = &( ps->buf_out_fx[ps->l_buf_out] ); FOR( i = 0; i < l_frm_out; i++ ) { - buf_out_ptr[i] = a_out[i]; + buf_out_ptr[i] = extract_h( L_shl( a_out[i], add( Q_a_out, Q16 - Q11 ) ) ); // Q_a_out move16(); } + ps->Q_buf_out = Q_a_out; + move16(); } ps->l_buf_out = (UWord16) L_add( ps->l_buf_out, l_frm_out ); move16(); diff --git a/lib_dec/jbm_pcmdsp_apa.h b/lib_dec/jbm_pcmdsp_apa.h index 42215ba16..33edf411a 100644 --- a/lib_dec/jbm_pcmdsp_apa.h +++ b/lib_dec/jbm_pcmdsp_apa.h @@ -147,7 +147,7 @@ bool apa_exit( apa_state_t **s ); #ifndef IVAS_FLOAT_FIXED uint8_t apa_exec( apa_state_t *s, const float a_in[], uint16_t l_in, uint16_t maxScaling, float a_out[], uint16_t *l_out ); #else -uint8_t apa_exec_ivas_fx( apa_state_t *s, const Word16 a_in[], UWord16 l_in, UWord16 maxScaling, Word16 a_out[], UWord16 *l_out ); +UWord8 apa_exec_ivas_fx( apa_state_t *s, const Word32 a_in[], UWord16 l_in, UWord16 maxScaling, Word32 a_out[], UWord16 *l_out ); uint8_t apa_exec_fx( apa_state_t *s, const Word16 a_in[], UWord16 l_in, UWord16 maxScaling, Word16 a_out[], UWord16 *l_out ); #endif #endif /* JBM_PCMDSP_APA_H */ diff --git a/lib_dec/lib_dec_fx.c b/lib_dec/lib_dec_fx.c index 90b3eb4d8..77cc8710f 100644 --- a/lib_dec/lib_dec_fx.c +++ b/lib_dec/lib_dec_fx.c @@ -1087,9 +1087,9 @@ ivas_error IVAS_DEC_GetSamples( } // tmp apaExecBuffer - Word16 tmp_apaExecBuffer[APA_BUF]; IF( EQ_16( (Word16) hIvasDec->mode, IVAS_DEC_MODE_EVS ) ) { + Word16 tmp_apaExecBuffer[APA_BUF]; FOR( Word32 i = 0; i < APA_BUF_PER_CHANNEL * nTransportChannels; ++i ) { tmp_apaExecBuffer[i] = extract_l( L_shr( hIvasDec->apaExecBuffer_fx[i], Q11 ) ); // Q0 @@ -1105,32 +1105,10 @@ ivas_error IVAS_DEC_GetSamples( } ELSE { - Word32 max_val; - Word16 max_shift; - - maximum_32_fx( hIvasDec->apaExecBuffer_fx, APA_BUF_PER_CHANNEL * nTransportChannels, &max_val ); - IF( max_val ) - { - max_shift = s_max( Q12, sub( 31 - 3, norm_l( L_shr( max_val, 11 ) ) ) ); - } - ELSE - { - max_shift = Q12; - move16(); - } - FOR( Word32 i = 0; i < APA_BUF_PER_CHANNEL * nTransportChannels; ++i ) - { - tmp_apaExecBuffer[i] = extract_l( L_shr( hIvasDec->apaExecBuffer_fx[i], max_shift ) ); // Q(-1) - } - IF( apa_exec_ivas_fx( hIvasDec->hTimeScaler, tmp_apaExecBuffer, (UWord16) imult3216( hIvasDec->nSamplesFrame, nTransportChannels ), (UWord16) hIvasDec->tsm_max_scaling, tmp_apaExecBuffer, &nTimeScalerOutSamples ) != 0 ) + IF( apa_exec_ivas_fx( hIvasDec->hTimeScaler, hIvasDec->apaExecBuffer_fx, (UWord16) imult3216( hIvasDec->nSamplesFrame, nTransportChannels ), (UWord16) hIvasDec->tsm_max_scaling, hIvasDec->apaExecBuffer_fx, &nTimeScalerOutSamples ) != 0 ) { return IVAS_ERR_UNKNOWN; } - - FOR( Word32 i = 0; i < APA_BUF_PER_CHANNEL * nTransportChannels; ++i ) - { - hIvasDec->apaExecBuffer_fx[i] = L_shl( tmp_apaExecBuffer[i], max_shift ); // Q11 - } } assert( LE_32( (Word32) nTimeScalerOutSamples, APA_BUF ) ); nSamplesTcsScaled = idiv1616U( extract_l( nTimeScalerOutSamples ), nTransportChannels ); -- GitLab From 167d9b1f3473a247bc92421020874e5b08e614c1 Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Tue, 5 Nov 2024 17:59:17 +0530 Subject: [PATCH 2/2] Fix for crash issue Multi-channel 7_1_4 at 256 kbps, 48kHz in, 48kHz out, 7_1_4 out, JBM Prof 5 --- lib_com/basop_util.c | 38 ++++++++++++++++++++++++++++++++++++++ lib_com/basop_util.h | 3 +++ lib_dec/jbm_pcmdsp_apa.c | 2 +- 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/lib_com/basop_util.c b/lib_com/basop_util.c index 71f324f98..1a2ef14f8 100644 --- a/lib_com/basop_util.c +++ b/lib_com/basop_util.c @@ -804,6 +804,44 @@ Word16 getScaleFactor32( /* o: measured headroom in range [ return i; } +Word16 getScaleFactor32_copy( /* o: measured headroom in range [0..31], 0 if all x[i] == 0 */ + const Word32 *x, /* i: array containing 32-bit data */ + const Word32 len_x ) /* i: length of the array to scan */ +{ + Word32 i; + Word16 i_min, i_max; + Word32 x_min, x_max; + + + x_max = 0; + move32(); + x_min = 0; + move32(); + FOR( i = 0; i < len_x; i++ ) + { + if ( x[i] >= 0 ) + x_max = L_max( x_max, x[i] ); + if ( x[i] < 0 ) + x_min = L_min( x_min, x[i] ); + } + + i_max = 0x20; + move16(); + i_min = 0x20; + move16(); + + if ( x_max != 0 ) + i_max = norm_l( x_max ); + + if ( x_min != 0 ) + i_min = norm_l( x_min ); + + i_max = s_and( s_min( i_max, i_min ), 0x1F ); + + + return i_max; +} + Word16 normalize16( Word16 mantissa, Word16 *pexponent ) { Word16 tmp; diff --git a/lib_com/basop_util.h b/lib_com/basop_util.h index 3549f7d5c..92994542e 100644 --- a/lib_com/basop_util.h +++ b/lib_com/basop_util.h @@ -235,6 +235,9 @@ Word16 getScaleFactor32( const Word32 *x, /* i : array containing 32-bit data */ const Word16 len_x ); /* i : length of the array to scan */ +Word16 getScaleFactor32_copy( /* o: measured headroom in range [0..31], 0 if all x[i] == 0 */ + const Word32 *x, /* i: array containing 32-bit data */ + const Word32 len_x ); /* i: length of the array to scan */ /** * \brief normalize mantissa and update the exponent accordingly. diff --git a/lib_dec/jbm_pcmdsp_apa.c b/lib_dec/jbm_pcmdsp_apa.c index 942a5a906..9b94503da 100644 --- a/lib_dec/jbm_pcmdsp_apa.c +++ b/lib_dec/jbm_pcmdsp_apa.c @@ -892,7 +892,7 @@ UWord8 apa_exec_ivas_fx( UWord32 statsResetThreshold, statsResetShift; Word16 Q_a_out; - Q_a_out = add( getScaleFactor32( a_in, i_mult( ps->num_channels, APA_BUF_PER_CHANNEL ) ), Q11 - Q16 ); + Q_a_out = add( getScaleFactor32_copy( a_in, L_mult0( ps->num_channels, APA_BUF_PER_CHANNEL ) ), Q11 - Q16 ); statsResetThreshold = 1637; move32(); statsResetShift = 2; -- GitLab