From fb008411952dd55eff328a352a92617e987c9abb Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Thu, 12 Jun 2025 14:54:52 +0530 Subject: [PATCH] Fix for 3GPP issue 1732: Accuracy of spatial metadata in ivas_omasa_enc_fx compared to the floating point equivalent Link #1732 --- lib_com/cldfb_fx.c | 76 ++++++++++++++++++----- lib_com/ivas_dirac_com_fx.c | 120 +++++++++++++++++++++++++++++++++++- lib_com/options.h | 2 + lib_enc/ivas_omasa_enc_fx.c | 43 ++++++++++++- 4 files changed, 224 insertions(+), 17 deletions(-) diff --git a/lib_com/cldfb_fx.c b/lib_com/cldfb_fx.c index ede4be78b..299b27a70 100644 --- a/lib_com/cldfb_fx.c +++ b/lib_com/cldfb_fx.c @@ -662,7 +662,7 @@ void cldfbAnalysis_ts_fx_var_q( const Word16 *ptr_pf_fx; Word16 ptr_pf_sf; Word32 *timeBuffer_fx, buffer_fx[( CLDFB_NO_CHANNELS_MAX * CLDFB_NO_COL_MAX ) + ( 9 * CLDFB_NO_CHANNELS_MAX )]; - Word16 offset, frameSize; + Word16 offset, frameSize, gb, hr, shift; offset = sub( h_cldfb->p_filter_length, h_cldfb->no_channels ); frameSize = i_mult( h_cldfb->no_channels, h_cldfb->no_col ); @@ -836,32 +836,80 @@ void cldfbAnalysis_ts_fx_var_q( move16(); /* FFT of DST IV */ + gb = find_guarded_bits_fx( M1 ); + hr = L_norm_arr( rBuffer_fx, M1 ); + + IF( LT_16( hr, gb ) ) + { + scale_sig32( rBuffer_fx, M1, sub( hr, gb ) ); + } + fft_cldfb_fx( rBuffer_fx, M2 ); /* post modulation of DST IV */ - FOR( k = 0; k < M2; k++ ) + IF( LT_16( hr, gb ) ) { - /*cplxMult(&realBuffer[M1-1-(2*k)],&realBuffer[2*k],rBuffer[2*k],rBuffer[2*k+1],rot_vctr_re[k],rot_vctr_im[k]);*/ - realBuffer_fx[( M1 - 1 ) - ( k * 2 )] = Msub_32_32( Mpy_32_32( rBuffer_fx[2 * k], rot_vctr_re_fx[k] ), rBuffer_fx[2 * k + 1], rot_vctr_im_fx[k] ); // q - 5 - realBuffer_fx[2 * k] = Madd_32_32( Mpy_32_32( rBuffer_fx[2 * k], rot_vctr_im_fx[k] ), rBuffer_fx[2 * k + 1], rot_vctr_re_fx[k] ); // q - 5 - move32(); - move32(); + shift = sub( gb, hr ); + + FOR( k = 0; k < M2; k++ ) + { + /*cplxMult(&realBuffer[M1-1-(2*k)],&realBuffer[2*k],rBuffer[2*k],rBuffer[2*k+1],rot_vctr_re[k],rot_vctr_im[k]);*/ + realBuffer_fx[( M1 - 1 ) - ( k * 2 )] = L_shl( Msub_32_32( Mpy_32_32( rBuffer_fx[2 * k], rot_vctr_re_fx[k] ), rBuffer_fx[2 * k + 1], rot_vctr_im_fx[k] ), shift ); // q - 5 + realBuffer_fx[2 * k] = L_shl( Madd_32_32( Mpy_32_32( rBuffer_fx[2 * k], rot_vctr_im_fx[k] ), rBuffer_fx[2 * k + 1], rot_vctr_re_fx[k] ), shift ); // q - 5 + move32(); + move32(); + } + } + ELSE + { + FOR( k = 0; k < M2; k++ ) + { + /*cplxMult(&realBuffer[M1-1-(2*k)],&realBuffer[2*k],rBuffer[2*k],rBuffer[2*k+1],rot_vctr_re[k],rot_vctr_im[k]);*/ + realBuffer_fx[( M1 - 1 ) - ( k * 2 )] = Msub_32_32( Mpy_32_32( rBuffer_fx[2 * k], rot_vctr_re_fx[k] ), rBuffer_fx[2 * k + 1], rot_vctr_im_fx[k] ); // q - 5 + realBuffer_fx[2 * k] = Madd_32_32( Mpy_32_32( rBuffer_fx[2 * k], rot_vctr_im_fx[k] ), rBuffer_fx[2 * k + 1], rot_vctr_re_fx[k] ); // q - 5 + move32(); + move32(); + } } *q_cldfb = sub( *q_cldfb, 2 ); move16(); + gb = find_guarded_bits_fx( M1 ); + hr = L_norm_arr( iBuffer_fx, M1 ); + + IF( LT_16( hr, gb ) ) + { + scale_sig32( iBuffer_fx, M1, sub( hr, gb ) ); + } + /* FFT of DCT IV */ fft_cldfb_fx( iBuffer_fx, M2 ); /* post modulation of DCT IV */ - FOR( k = 0; k < M2; k++ ) + IF( LT_16( hr, gb ) ) { - /* do it inplace */ - /*cplxMult(&imagBuffer[2*k],&imagBuffer[M1-1-(2*k)],iBuffer[2*k],iBuffer[2*k+1],rot_vctr_re[k],rot_vctr_im[k]);*/ - imagBuffer_fx[2 * k] = Msub_32_32( Mpy_32_32( iBuffer_fx[2 * k], rot_vctr_re_fx[k] ), iBuffer_fx[2 * k + 1], rot_vctr_im_fx[k] ); // q - 5 - imagBuffer_fx[( M1 - 1 ) - ( k * 2 )] = Madd_32_32( Mpy_32_32( iBuffer_fx[2 * k], rot_vctr_im_fx[k] ), iBuffer_fx[2 * k + 1], rot_vctr_re_fx[k] ); // q - 5 - move32(); - move32(); + shift = sub( gb, hr ); + FOR( k = 0; k < M2; k++ ) + { + /* do it inplace */ + /*cplxMult(&imagBuffer[2*k],&imagBuffer[M1-1-(2*k)],iBuffer[2*k],iBuffer[2*k+1],rot_vctr_re[k],rot_vctr_im[k]);*/ + imagBuffer_fx[2 * k] = L_shl( Msub_32_32( Mpy_32_32( iBuffer_fx[2 * k], rot_vctr_re_fx[k] ), iBuffer_fx[2 * k + 1], rot_vctr_im_fx[k] ), shift ); // q - 5 + imagBuffer_fx[( M1 - 1 ) - ( k * 2 )] = L_shl( Madd_32_32( Mpy_32_32( iBuffer_fx[2 * k], rot_vctr_im_fx[k] ), iBuffer_fx[2 * k + 1], rot_vctr_re_fx[k] ), shift ); // q - 5 + move32(); + move32(); + } + } + ELSE + { + FOR( k = 0; k < M2; k++ ) + { + /* do it inplace */ + /*cplxMult(&imagBuffer[2*k],&imagBuffer[M1-1-(2*k)],iBuffer[2*k],iBuffer[2*k+1],rot_vctr_re[k],rot_vctr_im[k]);*/ + imagBuffer_fx[2 * k] = Msub_32_32( Mpy_32_32( iBuffer_fx[2 * k], rot_vctr_re_fx[k] ), iBuffer_fx[2 * k + 1], rot_vctr_im_fx[k] ); // q - 5 + imagBuffer_fx[( M1 - 1 ) - ( k * 2 )] = Madd_32_32( Mpy_32_32( iBuffer_fx[2 * k], rot_vctr_im_fx[k] ), iBuffer_fx[2 * k + 1], rot_vctr_re_fx[k] ); // q - 5 + move32(); + move32(); + } } IF( EQ_32( h_cldfb->prototype, CLDFB_PROTOTYPE_5_00MS ) ) diff --git a/lib_com/ivas_dirac_com_fx.c b/lib_com/ivas_dirac_com_fx.c index 14dd6c148..6d074a4ff 100644 --- a/lib_com/ivas_dirac_com_fx.c +++ b/lib_com/ivas_dirac_com_fx.c @@ -782,6 +782,123 @@ void computeDirectionVectors_fx( * * *------------------------------------------------------------------------*/ +#ifdef ITTIAM_FIX_FOR_ISSUE_1732 +void computeDiffuseness_fixed( + Word32 *buffer_intensity[DIRAC_NUM_DIMS][DIRAC_NO_COL_AVG_DIFF], // i: Q(q_factor_intensity) + const Word32 *buffer_energy, // i: Q(q_factor_energy) + const Word16 num_freq_bands, + Word32 *diffuseness, // o: exp(out_exp) + Word16 *q_factor_intensity, + Word16 *q_factor_energy, + Word16 *q_diffuseness /*Ouput Q*/ +) +{ + Word32 intensity_slow[DIRAC_NUM_DIMS * CLDFB_NO_CHANNELS_MAX]; + Word16 exp_intensity_slow[DIRAC_NUM_DIMS * CLDFB_NO_CHANNELS_MAX]; + Word32 intensity_slow_abs[CLDFB_NO_CHANNELS_MAX]; + Word16 exp_intensity_slow_abs[CLDFB_NO_CHANNELS_MAX]; + Word32 energy_slow[CLDFB_NO_CHANNELS_MAX]; + Word16 exp_energy_slow[CLDFB_NO_CHANNELS_MAX]; + Word16 i, j, k; + Word32 tmp = 0; + move32(); + Word32 *p_tmp; + Word16 *p_tmp_exp; + const Word32 *p_tmp_c; + Word16 exp1, exp2, q_tmp; + + /* Compute Intensity slow and energy slow buffer_intensity and buffer_energy */ + + set_zero_fx( intensity_slow, i_mult( DIRAC_NUM_DIMS, CLDFB_NO_CHANNELS_MAX ) ); + set_zero_fx( intensity_slow_abs, CLDFB_NO_CHANNELS_MAX ); + set_zero_fx( energy_slow, CLDFB_NO_CHANNELS_MAX ); + set16_fx( exp_energy_slow, 0, CLDFB_NO_CHANNELS_MAX ); + + FOR( i = 0; i < DIRAC_NO_COL_AVG_DIFF; ++i ) + { + /* Energy slow */ + p_tmp_c = buffer_energy + i_mult( i, num_freq_bands ); + FOR( k = 0; k < num_freq_bands; k++ ) + { + energy_slow[k] = BASOP_Util_Add_Mant32Exp( energy_slow[k], exp_energy_slow[k], *( p_tmp_c++ ), sub( 31, q_factor_energy[i] ), &exp_energy_slow[k] ); + move32(); + } + + /* Intensity slow */ + FOR( j = 0; j < DIRAC_NUM_DIMS; ++j ) + { + p_tmp = buffer_intensity[j][i]; + + FOR( k = 0; k < num_freq_bands; k++ ) + { + intensity_slow[j * num_freq_bands + k] = BASOP_Util_Add_Mant32Exp( intensity_slow[j * num_freq_bands + k], exp_intensity_slow[j * num_freq_bands + k], *( p_tmp++ ), sub( 31, q_factor_intensity[i] ), &exp_intensity_slow[j * num_freq_bands + k] ); + move32(); + } + } + } + + /* intensity_slow.^2 + intensity_slow_abs*/ + FOR( j = 0; j < DIRAC_NUM_DIMS; ++j ) + { + p_tmp = intensity_slow + j * num_freq_bands; + p_tmp_exp = exp_intensity_slow + j * num_freq_bands; + FOR( k = 0; k < num_freq_bands; k++ ) + { + intensity_slow_abs[k] = BASOP_Util_Add_Mant32Exp( intensity_slow_abs[k], exp_intensity_slow_abs[k], Mpy_32_32( *p_tmp, *p_tmp ), shl( *p_tmp_exp, 1 ), &exp_intensity_slow_abs[k] ); + move32(); + p_tmp_exp++; + p_tmp++; + } + } + + /* Compute Diffuseness */ + p_tmp = intensity_slow_abs; + FOR( i = 0; i < num_freq_bands; ++i ) + { + diffuseness[i] = ONE_IN_Q30; + move32(); + IF( p_tmp[i] ) + { + + exp1 = exp_intensity_slow_abs[i]; + move16(); + tmp = Sqrt32( p_tmp[i], &exp1 ); + + tmp = BASOP_Util_Divide3232_Scale_newton( tmp, L_add( energy_slow[i], EPSILLON_FX ), &exp2 ); + q_tmp = sub( 31, add( exp2, sub( exp1, exp_energy_slow[i] ) ) ); + + IF( LT_16( q_tmp, Q30 ) ) + { + tmp = L_sub( L_shr( ONE_IN_Q30, sub( Q30, q_tmp ) ), tmp ); + } + ELSE + { + tmp = L_sub( ONE_IN_Q30, L_shr( tmp, sub( q_tmp, Q30 ) ) ); + q_tmp = Q30; + move16(); + } + + IF( GE_32( tmp, L_shl( 1, q_tmp ) ) ) + { + diffuseness[i] = ONE_IN_Q30; + } + ELSE IF( tmp <= 0 ) + { + diffuseness[i] = 0; + } + ELSE + { + diffuseness[i] = L_shl( tmp, sub( Q30, q_tmp ) ); + } + move32(); + } + } + *q_diffuseness = Q30; + move16(); + + return; +} +#else void computeDiffuseness_fixed( Word32 *buffer_intensity[DIRAC_NUM_DIMS][DIRAC_NO_COL_AVG_DIFF], // i: Q(q_factor_intensity) const Word32 *buffer_energy, // i: Q(q_factor_energy) @@ -959,12 +1076,13 @@ void computeDiffuseness_fixed( move32(); } } + *q_diffuseness = Q30; move16(); return; } - +#endif Word32 deindex_azimuth_fx( /* o : output Q22 */ Word16 id_phi, /* i : index */ const Word16 no_bits, /* i : number of bits for the spherical grid */ diff --git a/lib_com/options.h b/lib_com/options.h index 9dc7e7fd1..248bfbc7f 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -111,4 +111,6 @@ #define FIX_1733_CLDFB_BUG #define FIX_1740_MISING_POP_WMOPS /* VA: fix issue 1740: missing pop_wmops() */ +#define ITTIAM_FIX_FOR_ISSUE_1732 /*ITTIAM: Fix for Issue 1732 : Accuracy of spatial metadata in ivas_omasa_enc_fx compared to the floating point equivalent*/ + #endif diff --git a/lib_enc/ivas_omasa_enc_fx.c b/lib_enc/ivas_omasa_enc_fx.c index 0b0aa90c5..aba6ce570 100644 --- a/lib_enc/ivas_omasa_enc_fx.c +++ b/lib_enc/ivas_omasa_enc_fx.c @@ -1040,7 +1040,11 @@ static void ivas_omasa_param_est_enc_fx( Word32 temp; Word16 temp_e; Word16 q_intensity_real_fx[MASA_FREQUENCY_BANDS], q_reference_power_fx[CLDFB_NO_CHANNELS_MAX]; - +#ifdef ITTIAM_FIX_FOR_ISSUE_1732 + Word32 tmp_data_fx[MCMASA_MAX_ANA_CHANS][L_FRAME48k]; + Word16 q_data_fx[MCMASA_MAX_ANA_CHANS]; + Word16 tmp_q[MCMASA_MAX_ANA_CHANS]; +#endif ref_exp = 0; norm_buff = MAX16B; dir_v_e = MIN_16; @@ -1065,6 +1069,20 @@ static void ivas_omasa_param_est_enc_fx( { set_zero_fx( Chnl_RealBuffer_fx[i], 60 ); set_zero_fx( Chnl_ImagBuffer_fx[i], 60 ); +#ifdef ITTIAM_FIX_FOR_ISSUE_1732 + IF( is_zero_arr( data[i], L_FRAME48k ) == 0 ) + { + q = sub( L_norm_arr( data[i], L_FRAME48k ), find_guarded_bits_fx( hOMasa->cldfbAnaEnc[i]->no_channels ) ); + Copy_Scale_sig32( data[i], tmp_data_fx[i], L_FRAME48k, q ); + q_data_fx[i] = add( q_data, q ); + } + ELSE + { + Copy32( data[i], tmp_data_fx[i], L_FRAME48k ); + q_data_fx[i] = MAX_16; + } + move16(); +#endif } /* Compute ISM to FOA matrices */ FOR( i = 0; i < nchan_ism; i++ ) @@ -1080,9 +1098,10 @@ static void ivas_omasa_param_est_enc_fx( move32(); move32(); } - +#ifdef ITTIAM_FIX_FOR_ISSUE_1732 q = q_data; move16(); +#endif /* do processing over all CLDFB time slots */ FOR( block_m_idx = 0; block_m_idx < hOMasa->nSubframes; block_m_idx++ ) { @@ -1114,11 +1133,21 @@ static void ivas_omasa_param_est_enc_fx( move16(); FOR( i = 0; i < nchan_ism; i++ ) { +#ifdef ITTIAM_FIX_FOR_ISSUE_1732 + q = q_data_fx[i]; + move16(); + cldfbAnalysis_ts_fx_var_q( &( tmp_data_fx[i][l_ts * ts] ), Chnl_RealBuffer_fx[i], Chnl_ImagBuffer_fx[i], l_ts, hOMasa->cldfbAnaEnc[i], &q ); /*q_data-5*/ + norm_buff = s_min( norm_buff, add( q, L_norm_arr( Chnl_RealBuffer_fx[i], CLDFB_NO_CHANNELS_MAX ) ) ); + norm_buff = s_min( norm_buff, add( q, L_norm_arr( Chnl_ImagBuffer_fx[i], CLDFB_NO_CHANNELS_MAX ) ) ); + tmp_q[i] = q; + move16(); +#else q = q_data; move16(); cldfbAnalysis_ts_fx_var_q( &( data[i][l_ts * ts] ), Chnl_RealBuffer_fx[i], Chnl_ImagBuffer_fx[i], l_ts, hOMasa->cldfbAnaEnc[i], &q ); /*q_data-5*/ norm_buff = s_min( norm_buff, L_norm_arr( Chnl_RealBuffer_fx[i], 60 ) ); norm_buff = s_min( norm_buff, L_norm_arr( Chnl_ImagBuffer_fx[i], 60 ) ); +#endif } /* Compute energy */ FOR( i = 0; i < num_freq_bands; i++ ) @@ -1131,10 +1160,20 @@ static void ivas_omasa_param_est_enc_fx( norm_buff = sub( norm_buff, guard_bits ); FOR( i = 0; i < nchan_ism; i++ ) { +#ifdef ITTIAM_FIX_FOR_ISSUE_1732 + scale_sig32( Chnl_RealBuffer_fx[i], CLDFB_NO_CHANNELS_MAX, sub( norm_buff, tmp_q[i] ) ); + scale_sig32( Chnl_ImagBuffer_fx[i], CLDFB_NO_CHANNELS_MAX, sub( norm_buff, tmp_q[i] ) ); +#else scale_sig32( Chnl_RealBuffer_fx[i], 60, norm_buff ); scale_sig32( Chnl_ImagBuffer_fx[i], 60, norm_buff ); +#endif } +#ifdef ITTIAM_FIX_FOR_ISSUE_1732 + q = norm_buff; + move16(); +#else q = add( q, norm_buff ); +#endif FOR( i = 0; i < num_freq_bands; i++ ) { brange[0] = hOMasa->band_grouping[i]; -- GitLab