From 2679897570cdb44e6d7e7ca2beaa810aae2d849d Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Mon, 20 Jan 2025 20:53:10 +0530 Subject: [PATCH 1/2] Fix for 3GPP issue 1192: Energy bursts in BWE region for MDCT-stereo @80kbps FB Link #1192 --- lib_enc/ivas_stereo_mdct_core_enc.c | 35 ++++++++++------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/lib_enc/ivas_stereo_mdct_core_enc.c b/lib_enc/ivas_stereo_mdct_core_enc.c index d8dcf5653..8f28da767 100644 --- a/lib_enc/ivas_stereo_mdct_core_enc.c +++ b/lib_enc/ivas_stereo_mdct_core_enc.c @@ -416,7 +416,7 @@ void stereo_mdct_core_enc_fx( FOR( i = 0; i < L_subframeTCX; i++ ) { W_tmp = W_mac_32_32( W_mult_32_32( mdst_spectrum_fx[ch][n][i], mdst_spectrum_fx[ch][n][i] ), sts[ch]->hTcxEnc->spectrum_fx[n][i], sts[ch]->hTcxEnc->spectrum_fx[n][i] ); /* 2*q_spec+1 */ - tmp_s = sub( W_norm( W_tmp ), 1 ); + tmp_s = W_norm( W_tmp ); W_tmp = W_shl( W_tmp, tmp_s ); /* 2*q_spec+1+tmp_s */ powerSpec_fx[ch][( i + ( n * L_subframeTCX ) )] = W_extract_h( W_tmp ); /* 2*q_spec+1+tmp_s-32 */ tmp_q_powSpec[( i + ( n * L_subframeTCX ) )] = sub( add( imult1616( q_spec, 2 ), tmp_s ), 31 ); // Q = 2 * q_spec + 1 + tmp_s - 32 @@ -424,7 +424,7 @@ void stereo_mdct_core_enc_fx( move16(); W_tmp = W_mac_32_32( W_mult_32_32( inv_mdst_spectrum_fx[ch][n][i], inv_mdst_spectrum_fx[ch][n][i] ), inv_spectrum_fx[ch][n][i], inv_spectrum_fx[ch][n][i] ); /* 2*q_spec+1 */ - tmp_s = sub( W_norm( W_tmp ), 1 ); + tmp_s = W_norm( W_tmp ); W_tmp = W_shl( W_tmp, tmp_s ); /* 2*q_spec+1+tmp_s */ powerSpecMsInv_fx[ch][n][i] = W_extract_h( W_tmp ); /* 2*q_spec+1+tmp_s-32 */ tmp_q_psi[n][i] = sub( add( imult1616( q_spec, 2 ), tmp_s ), 31 ); // Q = 2 * q_spec + 1 + tmp_s - 32 @@ -438,7 +438,7 @@ void stereo_mdct_core_enc_fx( { /* power spectrum: MDCT^2 + MDST^2 */ W_tmp = W_mult_32_32( inv_spectrum_fx[ch][n][0], inv_spectrum_fx[ch][n][0] ); /* 2*q_spec+1 */ - tmp_s = sub( W_norm( W_tmp ), 1 ); + tmp_s = W_norm( W_tmp ); W_tmp = W_shl( W_tmp, tmp_s ); /* 2*q_spec+1+tmp_s */ powerSpecMsInv_fx[ch][n][0] = W_extract_h( W_tmp ); /* 2*q_spec+1+tmp_s-32 */ tmp_q_psi[n][0] = sub( add( imult1616( q_spec, 2 ), tmp_s ), 31 ); // Q = 2 * q_spec + 1 + tmp_s - 32 @@ -450,7 +450,7 @@ void stereo_mdct_core_enc_fx( Word32 mdst_fx = L_sub( inv_spectrum_fx[ch][n][i + 1], inv_spectrum_fx[ch][n][i - 1] ); /* An MDST estimate q_spec*/ W_tmp = W_mac_32_32( W_mult_32_32( mdst_fx, mdst_fx ), inv_spectrum_fx[ch][n][i], inv_spectrum_fx[ch][n][i] ); /* 2*q_spec+1 */ - tmp_s = sub( W_norm( W_tmp ), 1 ); + tmp_s = W_norm( W_tmp ); W_tmp = W_shl( W_tmp, tmp_s ); /* 2*q_spec+1+tmp_s */ powerSpecMsInv_fx[ch][n][i] = W_extract_h( W_tmp ); /* 2*q_spec+1+tmp_s-32 */ tmp_q_psi[n][i] = sub( add( imult1616( q_spec, 2 ), tmp_s ), 31 ); // Q = 2 * q_spec + 1 + tmp_s - 32 @@ -459,7 +459,7 @@ void stereo_mdct_core_enc_fx( } W_tmp = W_mult_32_32( inv_spectrum_fx[ch][n][L_subframeTCX - 1], inv_spectrum_fx[ch][n][L_subframeTCX - 1] ); /* 2*q_spec+1 */ - tmp_s = sub( W_norm( W_tmp ), 1 ); + tmp_s = W_norm( W_tmp ); W_tmp = W_shl( W_tmp, tmp_s ); /* 2*q_spec+1+tmp_s */ powerSpecMsInv_fx[ch][n][L_subframeTCX - 1] = W_extract_h( W_tmp ); /* 2*q_spec+1+tmp_s-32 */ tmp_q_psi[n][L_subframeTCX - 1] = sub( add( imult1616( q_spec, 2 ), tmp_s ), 31 ); // Q = 2 * q_spec + 1 + tmp_s - 32 @@ -469,7 +469,7 @@ void stereo_mdct_core_enc_fx( /* power spectrum: MDCT^2 + MDST^2 */ W_tmp = W_mult_32_32( sts[ch]->hTcxEnc->spectrum_fx[n][0], sts[ch]->hTcxEnc->spectrum_fx[n][0] ); /* 2*q_spec+1 */ - tmp_s = sub( W_norm( W_tmp ), 1 ); + tmp_s = W_norm( W_tmp ); W_tmp = W_shl( W_tmp, tmp_s ); /* 2*q_spec+1+tmp_s */ powerSpec_fx[ch][n * L_subframeTCX] = W_extract_h( W_tmp ); /* 2*q_spec+1+tmp_s-32 */ tmp_q_powSpec[n * L_subframeTCX] = sub( add( imult1616( q_spec, 2 ), tmp_s ), 31 ); // Q = 2 * q_spec + 1 + tmp_s - 32 @@ -481,7 +481,7 @@ void stereo_mdct_core_enc_fx( Word32 mdst_fx = L_sub( sts[ch]->hTcxEnc->spectrum_fx[n][i + 1], sts[ch]->hTcxEnc->spectrum_fx[n][i - 1] ); /* An MDST estimate q_spec*/ W_tmp = W_mac_32_32( W_mult_32_32( mdst_fx, mdst_fx ), sts[ch]->hTcxEnc->spectrum_fx[n][i], sts[ch]->hTcxEnc->spectrum_fx[n][i] ); /* 2*q_spec+1 */ - tmp_s = sub( W_norm( W_tmp ), 1 ); + tmp_s = W_norm( W_tmp ); W_tmp = W_shl( W_tmp, tmp_s ); /* 2*q_spec+1+tmp_s */ powerSpec_fx[ch][( i + ( n * L_subframeTCX ) )] = W_extract_h( W_tmp ); /* 2*q_spec+1+tmp_s-32 */ tmp_q_powSpec[( i + ( n * L_subframeTCX ) )] = sub( add( imult1616( q_spec, 2 ), tmp_s ), 31 ); // Q = 2 * q_spec + 1 + tmp_s - 32 @@ -490,7 +490,7 @@ void stereo_mdct_core_enc_fx( } W_tmp = W_mult_32_32( sts[ch]->hTcxEnc->spectrum_fx[n][L_subframeTCX - 1], sts[ch]->hTcxEnc->spectrum_fx[n][L_subframeTCX - 1] ); /* 2*q_spec+1 */ - tmp_s = sub( W_norm( W_tmp ), 1 ); + tmp_s = W_norm( W_tmp ); W_tmp = W_shl( W_tmp, tmp_s ); /* 2*q_spec+1+tmp_s */ powerSpec_fx[ch][( ( L_subframeTCX - 1 ) + ( n * L_subframeTCX ) )] = W_extract_h( W_tmp ); /* 2*q_spec+1+tmp_s-32 */ tmp_q_powSpec[( ( L_subframeTCX - 1 ) + ( n * L_subframeTCX ) )] = sub( add( imult1616( q_spec, 2 ), tmp_s ), 31 ); // Q = 2 * q_spec + 1 + tmp_s - 32 @@ -501,31 +501,20 @@ void stereo_mdct_core_enc_fx( /* Aligning the Q-factors */ { + q_powSpec[ch] = Q31; FOR( i = 0; i < N_MAX; i++ ) { - if ( powerSpec_fx[ch][i] == 0 ) + if ( powerSpec_fx[ch][i] != 0 ) { - tmp_q_powSpec[i] = 63; - move16(); - } - if ( powerSpecMsInv_fx[ch][0][i] == 0 ) - { - tmp_q_powSpecInv[i] = 63; - move16(); + q_powSpec[ch] = s_min( q_powSpec[ch], tmp_q_powSpec[i] ); } } - minimum_s( tmp_q_powSpec, N_MAX, &q_powSpec[ch] ); - minimum_s( tmp_q_powSpecInv, N_MAX, &tmp_s ); - q_powSpec[ch] = s_min( q_powSpec[ch], tmp_s ); - move16(); FOR( n = 0; n < nSubframes; n++ ) { FOR( i = 0; i < L_subframeTCX; i++ ) { - powerSpecMsInv_fx[ch][n][i] = L_shr( powerSpecMsInv_fx[ch][n][i], sub( tmp_q_psi[n][i], q_powSpec[ch] ) ); /* q_powSpec */ - powerSpec_fx[ch][( i + ( n * L_subframeTCX ) )] = L_shr( powerSpec_fx[ch][( i + ( n * L_subframeTCX ) )], sub( tmp_q_powSpec[i], q_powSpec[ch] ) ); /* q_powSpec */ - move32(); + powerSpec_fx[ch][( i + ( n * L_subframeTCX ) )] = L_shr( powerSpec_fx[ch][( i + ( n * L_subframeTCX ) )], sub( tmp_q_powSpec[i + ( n * L_subframeTCX )], q_powSpec[ch] ) ); /* q_powSpec */ move32(); } } -- GitLab From f694d57b7dca3644e5390e44fd1e7d6032f1eeb3 Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Thu, 23 Jan 2025 10:41:30 +0530 Subject: [PATCH 2/2] Fix for spectral holes observed --- lib_enc/ivas_stereo_mdct_core_enc.c | 49 ++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/lib_enc/ivas_stereo_mdct_core_enc.c b/lib_enc/ivas_stereo_mdct_core_enc.c index 8f28da767..d525dad12 100644 --- a/lib_enc/ivas_stereo_mdct_core_enc.c +++ b/lib_enc/ivas_stereo_mdct_core_enc.c @@ -154,7 +154,7 @@ void stereo_mdct_core_enc_fx( Word32 *p_mdst_spectrum_long_fx[CPE_CHANNELS]; Word32 mdst_spectrum_long_fx[CPE_CHANNELS][N_MAX]; Word32 *mdst_spectrum_fx[CPE_CHANNELS][NB_DIV]; - Word16 q_powSpec[MCT_MAX_CHANNELS], q_spec, tmp_s; + Word16 q_powSpec[MCT_MAX_CHANNELS], q_powSpecMsInv[MCT_MAX_CHANNELS], q_spec, tmp_s; Word16 tmp_q_powSpec[N_MAX], tmp_q_powSpecInv[N_MAX], *tmp_q_psi[2]; Word64 W_tmp; Encoder_State *st, **sts; @@ -189,8 +189,10 @@ void stereo_mdct_core_enc_fx( orig_spectrum_fx[ch][1] = orig_spectrum_long_fx[ch] + N_TCX10_MAX; } - set16_fx( tmp_q_powSpecInv, 63, L_FRAME48k ); - set16_fx( tmp_q_powSpec, 63, L_FRAME48k ); + set16_fx( tmp_q_powSpecInv, 63, N_MAX ); + set16_fx( tmp_q_powSpec, 63, N_MAX ); + set16_fx( q_powSpec, 31, MCT_MAX_CHANNELS ); + set16_fx( q_powSpecMsInv, 31, MCT_MAX_CHANNELS ); tmp_q_psi[0] = tmp_q_powSpecInv; tmp_q_psi[1] = &tmp_q_powSpecInv[N_TCX10_MAX]; @@ -502,11 +504,26 @@ void stereo_mdct_core_enc_fx( /* Aligning the Q-factors */ { q_powSpec[ch] = Q31; + q_powSpecMsInv[ch] = Q31; + move16(); + move16(); FOR( i = 0; i < N_MAX; i++ ) { - if ( powerSpec_fx[ch][i] != 0 ) + IF( powerSpec_fx[ch][i] != 0 ) { q_powSpec[ch] = s_min( q_powSpec[ch], tmp_q_powSpec[i] ); + move16(); + } + } + FOR( n = 0; n < nSubframes; n++ ) + { + FOR( i = 0; i < L_subframeTCX; i++ ) + { + IF( powerSpecMsInv_fx[ch][n][i] != 0 ) + { + q_powSpecMsInv[ch] = s_min( q_powSpecMsInv[ch], tmp_q_psi[n][i] ); + move16(); + } } } @@ -514,8 +531,10 @@ void stereo_mdct_core_enc_fx( { FOR( i = 0; i < L_subframeTCX; i++ ) { + powerSpecMsInv_fx[ch][n][i] = L_shr_sat( powerSpecMsInv_fx[ch][n][i], sub( tmp_q_psi[n][i], q_powSpecMsInv[ch] ) ); powerSpec_fx[ch][( i + ( n * L_subframeTCX ) )] = L_shr( powerSpec_fx[ch][( i + ( n * L_subframeTCX ) )], sub( tmp_q_powSpec[i + ( n * L_subframeTCX )], q_powSpec[ch] ) ); /* q_powSpec */ move32(); + move32(); } } } @@ -592,6 +611,7 @@ void stereo_mdct_core_enc_fx( FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) { q_spec = sub( Q31, sts[ch]->hTcxEnc->spectrum_e[n] ); + Word16 q_comm = s_min( sub( Q31, sts[ch]->hTcxEnc->spectrum_e[n] ), s_min( q_powSpec[ch], q_powSpecMsInv[ch] ) ); Word16 n_sb = NB_DIV; move16(); if ( EQ_16( sts[ch]->hTcxEnc->tcxMode, TCX_20 ) ) @@ -600,17 +620,24 @@ void stereo_mdct_core_enc_fx( move16(); } length = idiv1616( sts[ch]->hTcxEnc->L_frameTCX, n_sb ); /* Q0 */ - IF( GT_16( q_spec, q_powSpec[ch] ) ) + IF( NE_16( q_spec, q_comm ) ) { - Scale_sig32( sts[ch]->hTcxEnc->spectrum_fx[n], length, sub( q_powSpec[ch], q_spec ) ); /* q_powSpec */ - Scale_sig32( inv_spectrum_fx[ch][n], length, sub( q_powSpec[ch], q_spec ) ); /* q_powSpec */ - sts[ch]->hTcxEnc->spectrum_e[n] = sub( Q31, q_powSpec[ch] ); + Scale_sig32( sts[ch]->hTcxEnc->spectrum_fx[n], length, sub( q_comm, q_spec ) ); /* q_powSpec */ + Scale_sig32( inv_spectrum_fx[ch][n], length, sub( q_comm, q_spec ) ); /* q_powSpec */ + sts[ch]->hTcxEnc->spectrum_e[n] = sub( Q31, q_comm ); move16(); } - ELSE + IF( NE_16( q_powSpec[ch], q_comm ) ) { - Scale_sig32( &p_powerSpec_fx[ch][0], L_subframeTCX, sub( q_spec, q_powSpec[ch] ) ); /* q_spec */ - Scale_sig32( powerSpecMsInv_fx[ch][0], L_subframeTCX, sub( q_spec, q_powSpec[ch] ) ); /* q_spec */ + Scale_sig32( &p_powerSpec_fx[ch][0], L_subframeTCX, sub( q_comm, q_powSpec[ch] ) ); /* q_spec */ + q_powSpec[ch] = q_comm; + move16(); + } + IF( NE_16( q_powSpecMsInv[ch], q_comm ) ) + { + Scale_sig32( powerSpecMsInv_fx[ch][0], L_subframeTCX, sub( q_comm, q_powSpecMsInv[ch] ) ); /* q_spec */ + q_powSpecMsInv[ch] = q_comm; + move16(); } } hIGFEnc[0]->spec_be_igf_e = p_orig_spectrum_e[0]; -- GitLab