From 0d47aa8edd2143480c4c989b7202724d3afa7bdf Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Wed, 12 Feb 2025 12:30:48 +0530 Subject: [PATCH] Fix for 3GPP issue 1192: areas of reduced energy observed Link #1192 --- lib_enc/tcx_utils_enc_fx.c | 193 ++++++++++++------------------------- 1 file changed, 62 insertions(+), 131 deletions(-) diff --git a/lib_enc/tcx_utils_enc_fx.c b/lib_enc/tcx_utils_enc_fx.c index bafd932a3..4d8f26031 100644 --- a/lib_enc/tcx_utils_enc_fx.c +++ b/lib_enc/tcx_utils_enc_fx.c @@ -2399,6 +2399,7 @@ void tcx_noise_factor_fx( *fac_ns = extract_l( L_mult0( *quantized_fac_ns, shr( 24576 /*0.75f Q15*/, NBITS_NOISE_FILL_LEVEL ) ) ); } + void tcx_noise_factor_ivas_fx( Word32 *x_orig, /* i: unquantized mdct coefficients */ Word16 x_orig_e, /* i: exponent */ @@ -2415,8 +2416,9 @@ void tcx_noise_factor_ivas_fx( Word16 element_mode /* i: element mode */ ) { - Word16 i, k = 0, maxK, segmentOffset; + Word16 i, k, win, segmentOffset; Word32 sqErrorNrg, n; + Word64 sqErrorNrg64; Word16 inv_gain2, inv_gain2_e, tilt_factor, nTransWidth_1; Word32 accu1, accu2, tmp32; Word16 tmp1, tmp2, s; @@ -2427,7 +2429,6 @@ void tcx_noise_factor_ivas_fx( Flag Overflow = 0; move32(); #endif - move16(); assert( nTransWidth <= 16 ); @@ -2436,8 +2437,10 @@ void tcx_noise_factor_ivas_fx( nTransWidth_1 = sub( nTransWidth, 1 ); /*Adjust noise filling level*/ - sqErrorNrg = L_deposit_l( 0 ); - n = L_deposit_l( 0 ); + sqErrorNrg64 = 0; + move64(); + n = 0; + move32(); /* get inverse frame length */ tmp1 = getInvFrameLen( L_frame ); @@ -2463,15 +2466,13 @@ void tcx_noise_factor_ivas_fx( IF( EQ_16( element_mode, IVAS_CPE_MDCT ) ) /* ... but only in mono or parametric stereo since it may cause binaural unmasking in discrete stereo */ { segmentOffset = i; - maxK = 1; - move16(); move16(); } ELSE { /* find last nonzero line below iFirstLine, use it as start offset */ tmp1 = shr( iFirstLine, 1 ); - FOR( i = iFirstLine; i > tmp1; i-- ) + FOR( ; i > tmp1; i-- ) { IF( sqQ[i] != 0 ) { @@ -2484,16 +2485,6 @@ void tcx_noise_factor_ivas_fx( inv_gain2 = shl( mult( inv_gain2, tilt_factor ), 1 ); } - /* initialize left (k) and right (maxK) non-zero neighbor pointers */ - k = 0; - move16(); - FOR( maxK = 1; maxK < nTransWidth; maxK++ ) - { - IF( sqQ[i + maxK] != 0 ) - { - BREAK; - } - } i = add( i, 1 ); segmentOffset = i; move16(); @@ -2501,17 +2492,20 @@ void tcx_noise_factor_ivas_fx( IF( LE_16( nTransWidth, 3 ) ) { - accu1 = L_deposit_l( 0 ); - accu2 = L_deposit_l( 0 ); - xMax = L_deposit_l( 0 ); + accu1 = 0; + move32(); + accu2 = 0; + move32(); + xMax = 0; + move32(); - FOR( k = s_and( i, (Word16) 0xFFFE ); k < lowpassLine; k++ ) + FOR( k = i & 0xFFFE; k < lowpassLine; k++ ) { xMax = L_max( xMax, L_abs( x_orig[k] ) ); } s = sub( norm_l( xMax ), 4 ); - FOR( k = s_and( i, (Word16) 0xFFFE ); k < lowpassLine; k += 2 ) + FOR( k = i & 0xFFFE; k < lowpassLine; k += 2 ) { /* even-index bins, left sub-win */ tmp1 = round_fx( L_shl( x_orig[k], s ) ); @@ -2524,13 +2518,15 @@ void tcx_noise_factor_ivas_fx( k = 0; move16(); - IF( accu1 == 0 ) + if ( accu1 == 0 ) { - accu1 = L_deposit_l( 1 ); + accu1 = 1; + move32(); } - IF( accu2 == 0 ) + if ( accu2 == 0 ) { - accu2 = L_deposit_l( 1 ); + accu2 = 1; + move32(); } att = BASOP_Util_Divide3232_Scale( L_shl( L_min( accu1, accu2 ), 1 ), L_add( accu1, accu2 ), &s ); @@ -2545,19 +2541,19 @@ void tcx_noise_factor_ivas_fx( move16(); } - accu1 = L_deposit_l( 0 ); + win = 0; + move16(); - tmp1 = sub( lowpassLine, nTransWidth ); - FOR( ; i <= tmp1; i++ ) + FOR( ; i < lowpassLine; i++ ) { inv_gain2 = shl( mult( inv_gain2, tilt_factor ), 1 ); - IF( EQ_16( maxK, 1 ) ) /* current line is not zero, so reset pointers */ + IF( sqQ[i] != 0 ) /* current line is not zero, so reset pointers */ { - k = sub( i, segmentOffset ); - - IF( k > 0 ) /* add segment sum to sum of segment magnitudes */ + IF( win > 0 ) { + k = sub( i, segmentOffset ); + IF( LE_16( nTransWidth, 3 ) ) { tmp2 = sub( k, c1 ); @@ -2590,115 +2586,35 @@ void tcx_noise_factor_ivas_fx( n = L_mac( n, int_sqr[k], 1152 /*0.03515625f Q15*/ ); } } - sqErrorNrg = L_add( sqErrorNrg, accu1 ); - accu1 = L_deposit_l( 0 ); /* segment ended here, so reset segment sum */ - k = 0; - move16(); - } - - FOR( ; maxK < nTransWidth; maxK++ ) - { - IF( sqQ[i + maxK] != 0 ) + FOR( k = segmentOffset; k < i - win; k++ ) { - BREAK; - } - } - segmentOffset = add( i, 1 ); /* new segment might start at next line */ - } - ELSE /* current line is zero, so update pointers & segment sum */ - { - IF( LT_16( k, nTransWidth ) ) - { - k = add( k, 1 ); - } - - tmp2 = sub( maxK, nTransWidth ); - test(); - IF( tmp2 < 0 && NE_16( element_mode, IVAS_CPE_MDCT ) ) - { - maxK = sub( maxK, 1 ); - } - - test(); - IF( ( tmp2 >= 0 ) && ( sqQ[i + sub( nTransWidth, 1 )] != 0 ) ) - { - maxK = sub( nTransWidth, 1 ); - } - - /* update segment sum: magnitudes scaled by smoothing function */ - /*accu1 += (float)fabs(x_orig[i]) * inv_gain2 * (float)(k * maxK);*/ - tmp2 = mult( inv_gain2, shl( imult1616( k, maxK ), 8 ) ); - accu1 = L_add( accu1, L_abs( Mpy_32_16_1( x_orig[i], tmp2 ) ) ); - } - } - - FOR( ; i < lowpassLine; i++ ) - { - inv_gain2 = shl( mult( inv_gain2, tilt_factor ), 1 ); - - IF( EQ_16( maxK, 1 ) ) /* current line is not zero, so reset pointers */ - { - k = sub( i, segmentOffset ); - - IF( k > 0 ) /* add segment sum to sum of segment magnitudes */ - { - IF( LE_16( nTransWidth, 3 ) ) - { - tmp2 = sub( k, c1 ); - IF( tmp2 > 0 ) - { - n = L_msu( n, k, (Word16) 0x8000 ); - } - IF( tmp2 > 0 ) - { - n = L_mac( n, nTransWidth_1, (Word16) 0x8000 ); - } - IF( tmp2 <= 0 ) - { - n = L_mac( n, int_sqr[k], c2 ); - } + sqErrorNrg64 = W_add( sqErrorNrg64, W_mult_32_16( sqQ[k], nTransWidth ) ); + sqQ[k] = 0; + move32(); } - ELSE + FOR( ; win > 0; win-- ) { - tmp2 = sub( k, 12 ); - IF( tmp2 > 0 ) - { - n = L_msu( n, k, (Word16) 0x8000 ); - } - IF( tmp2 > 0 ) - { - n = L_sub( n, 0x70000 ); - } - IF( tmp2 <= 0 ) - { - n = L_mac( n, int_sqr[k], 1152 /*0.03515625f Q15*/ ); - } + sqErrorNrg64 = W_add( sqErrorNrg64, W_mult_32_16( sqQ[k], win ) ); + sqQ[k++] = 0; + move32(); } - sqErrorNrg = L_add( sqErrorNrg, accu1 ); } - segmentOffset = add( i, 1 ); /* no new segments since maxK remains 1 */ + segmentOffset = add( i, 1 ); /* new segment might start at next line */ } - ELSE /* current line is zero, so update pointers & energy sum */ + ELSE /* current line is zero, so update pointers & segment sum */ { - IF( LT_16( k, nTransWidth ) ) + IF( LT_16( win, nTransWidth ) ) { - k = add( k, 1 ); - } - IF( LT_16( maxK, nTransWidth ) ) - { - maxK = sub( maxK, 1 ); + win = add( win, 1 ); } - /* update segment sum: magnitudes scaled by smoothing function */ - /*accu1 += (float)fabs(x_orig[i]) * inv_gain2 * (float)(k * maxK);*/ - tmp2 = mult( inv_gain2, shl( imult1616( k, maxK ), 8 ) ); - accu1 = L_add( accu1, L_abs( Mpy_32_16_1( x_orig[i], tmp2 ) ) ); + sqQ[i] = L_shl( Mpy_32_16_1( imult3216( L_abs( x_orig[i] ), win ), inv_gain2 ), inv_gain2_e ); + move32(); } } - - k = sub( i, segmentOffset ); - IF( k > 0 ) /* add last segment sum to sum of segment magnitudes */ + IF( win > 0 ) /* add last segment sum to sum of segment magnitudes */ { + k = sub( i, segmentOffset ); IF( LE_16( nTransWidth, 3 ) ) { tmp2 = sub( k, c1 ); @@ -2731,14 +2647,27 @@ void tcx_noise_factor_ivas_fx( n = L_mac( n, int_sqr[k], 1152 /*0.03515625f Q15*/ ); } } - sqErrorNrg = L_add( sqErrorNrg, accu1 ); + FOR( k = segmentOffset; k < i - win; k++ ) + { + sqErrorNrg64 = W_add( sqErrorNrg64, W_mult_32_16( sqQ[k], nTransWidth ) ); + sqQ[k] = 0; + move32(); + } + FOR( ; win > 0; win-- ) + { + sqErrorNrg64 = W_add( sqErrorNrg64, W_mult_32_16( sqQ[k], win ) ); + sqQ[k++] = 0; + move32(); + } } /* noise level factor: average of segment magnitudes of noise bins */ IF( n > 0 ) { + tmp2 = W_norm( sqErrorNrg64 ); + sqErrorNrg = W_extract_l( W_shr( sqErrorNrg64, sub( 32, tmp2 ) ) ); // 31 - (x_orig_e - 1) - 32 + tmp2 tmp1 = BASOP_Util_Divide3232_Scale( Mpy_32_16_1( sqErrorNrg, att ), n, &s ); - s = add( add( add( s, x_orig_e ), inv_gain2_e ), 7 - 15 ); + s = add( add( add( x_orig_e, sub( 31, tmp2 ) ), -15 ), s ); BASOP_SATURATE_WARNING_OFF_EVS; tmp1 = shl_o( tmp1, s, &Overflow ); BASOP_SATURATE_WARNING_ON_EVS; @@ -2762,8 +2691,10 @@ void tcx_noise_factor_ivas_fx( move16(); *fac_ns = extract_l( L_mult0( *quantized_fac_ns, shr( 24576 /*0.75f Q15*/, NBITS_NOISE_FILL_LEVEL ) ) ); + move16(); } + void tcx_encoder_memory_update_fx( Word16 *wsig, /* i : target weighted signal */ Word16 *xn_buf, /* i/o: mdct output buffer/time domain weigthed synthesis */ -- GitLab