From fe73e133ee45dedf417edf5600a649abf1b85607 Mon Sep 17 00:00:00 2001 From: Jan Kiene Date: Wed, 22 Oct 2025 16:07:01 +0200 Subject: [PATCH 1/7] port MR 2302 from float repo --- lib_com/bitstream_fx.c | 3 +- lib_com/fd_cng_com_fx.c | 5 + lib_com/ivas_cnst.h | 5 + lib_com/ivas_prot_fx.h | 2 + lib_com/ivas_rom_com.h | 6 + lib_com/ivas_rom_com_fx.c | 10 + lib_com/options.h | 1 + lib_com/stat_com.h | 9 +- lib_dec/fd_cng_dec_fx.c | 232 ++++++++++++++++++++++- lib_dec/ivas_decision_matrix_dec_fx.c | 9 +- lib_dec/ivas_ism_metadata_dec_fx.c | 31 ++- lib_dec/ivas_ism_param_dec_fx.c | 6 +- lib_dec/ivas_stereo_mdct_stereo_dec_fx.c | 4 + lib_enc/fd_cng_enc_fx.c | 133 +++++++++++++ lib_enc/stat_enc.h | 5 + 15 files changed, 450 insertions(+), 11 deletions(-) diff --git a/lib_com/bitstream_fx.c b/lib_com/bitstream_fx.c index b1c7a2efd..d2f3a61f6 100644 --- a/lib_com/bitstream_fx.c +++ b/lib_com/bitstream_fx.c @@ -5235,7 +5235,7 @@ void evs_dec_previewFrame( return; } - +#ifndef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG void dtx_read_padding_bits_fx( DEC_CORE_HANDLE st, const Word16 num_bits ) @@ -5253,3 +5253,4 @@ void dtx_read_padding_bits_fx( return; } +#endif diff --git a/lib_com/fd_cng_com_fx.c b/lib_com/fd_cng_com_fx.c index 47e3df91e..c8f0c31ac 100644 --- a/lib_com/fd_cng_com_fx.c +++ b/lib_com/fd_cng_com_fx.c @@ -2,6 +2,7 @@ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 ====================================================================================*/ +#include "ivas_cnst.h" #include #include #include "options.h" @@ -161,8 +162,12 @@ void ivas_initFdCngCom_fx( HANDLE_FD_CNG_COM hFdCngCom, Word16 scale ) hFdCngCom->exp_cldfb_periodog = 0; move16(); +#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG + set16_fx( hFdCngCom->coherence_fx, 16384 /* 0.5 in Q15 */, MDCT_ST_DTX_NUM_COHERENCE_BANDS ); +#else hFdCngCom->coherence_fx = 16384; /* 0.5 in Q15 */ move16(); +#endif set32_fx( hFdCngCom->olapBufferSynth_fx, 0, FFTLEN ); set32_fx( hFdCngCom->olapBufferSynth2_fx, 0, FFTLEN ); diff --git a/lib_com/ivas_cnst.h b/lib_com/ivas_cnst.h index bb61171a8..29a0c2592 100644 --- a/lib_com/ivas_cnst.h +++ b/lib_com/ivas_cnst.h @@ -884,6 +884,11 @@ enum fea_names #define MDCT_ST_PLC_FADEOUT_TO_ZERO_LEN 20 #define MDCT_ST_PLC_FADEOUT_DELAY_4_LSP_FADE 3 +#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG +#define MDCT_ST_DTX_NUM_COHERENCE_BANDS 5 +#define MDCT_ST_DTX_FIRST_BAND_OFFSET 2 +#endif + typedef enum { NOISE_GEN_MODE_UNDEF = -1, EQUAL_CORES = 0, diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index a88c13583..1ef6abc7e 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -1552,11 +1552,13 @@ ivas_error ivas_dirac_config_fx( void *st_ivas, /* i/o: IVAS encoder/decoder state structure */ const Word16 enc_dec /* i : encoder or decoder flag */ ); +#ifndef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG void dtx_read_padding_bits_fx( DEC_CORE_HANDLE st, const Word16 num_bits ); +#endif void FdCngEncodeMDCTStereoSID_fx( CPE_ENC_HANDLE hCPE /* i/o: CPE encoder state structure */ diff --git a/lib_com/ivas_rom_com.h b/lib_com/ivas_rom_com.h index 5072e385f..2a2a8de63 100644 --- a/lib_com/ivas_rom_com.h +++ b/lib_com/ivas_rom_com.h @@ -133,6 +133,12 @@ extern const SpectrumWarping sw32000Hz[]; /* PsychLPC */ extern const MDCTStereoBands_config mdctStereoBands_32000_640[]; +#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG +extern const Word16 mdct_stereo_dtx_coherence_bandlengths[MDCT_ST_DTX_NUM_COHERENCE_BANDS]; +extern const Word16 get_next_index_4_by_15[16]; +#endif + + /*----------------------------------------------------------------------------------* * Stereo DTX ROM tables *----------------------------------------------------------------------------------*/ diff --git a/lib_com/ivas_rom_com_fx.c b/lib_com/ivas_rom_com_fx.c index 4b14f6d5a..b0de18d94 100644 --- a/lib_com/ivas_rom_com_fx.c +++ b/lib_com/ivas_rom_com_fx.c @@ -546,6 +546,16 @@ const MDCTStereoBands_config mdctStereoBands_32000_640[] = {33, 29, 26, 18}/*number of bands for frame lengths 480, 320, 256, 160 respectively*/ }}; +#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG +const Word16 mdct_stereo_dtx_coherence_bandlengths[MDCT_ST_DTX_NUM_COHERENCE_BANDS] = { + 6, /* 8 - MDCT_ST_DTX_FIRST_BAND_OFFSET */ 8, 16, 16, 80 +}; +/* dequantization table for coherence */ +const Word16 get_next_index_4_by_15[16] = { + 0, 2184, 4369, 6553, 8738, 10922, 13107, 15291, 17476, 19660, 21845, 24029, 26214, 28398, 30583, 32767 +}; +#endif + const Word16 dft_cng_coh_u2i[9] = { 4, 5, 3, 6, 2, 7, 1, 8, 0 }; /* Coherence unary codeword -> residual codeword conversion table */ const Word16 dft_cng_coh_i2u[9] = { 8, 6, 4, 2, 0, 1, 3, 5, 7 }; /* Coherence residual codeword -> unary codeword conversion table */ diff --git a/lib_com/options.h b/lib_com/options.h index fefc866d6..068948b0a 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -115,6 +115,7 @@ #define FIX_1388_MSAN_ivas_init_decoder /* VA: issue 1388: fix use-of-uninitialized value in ivas_init_decoder() */ #define FIX_1288_SPLIT_REND_XSAN /* Dlb: Fix asan, msan and usan issues in split rendering mode*/ #define LIB_DEC_REVISION /* VA: cleaning and simplification of lib_dec.c */ +#define NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG /* FhG: Fix MDCT-Stereo comfort noise for certain noise types */ // object-editing feature porting #define TMP_FIX_SPLIT_REND // temporary fix to split-rendering (it follows the later state of the framework but it is needed now because of current test-conditions) diff --git a/lib_com/stat_com.h b/lib_com/stat_com.h index 7b5c9fd10..5309e7ad7 100644 --- a/lib_com/stat_com.h +++ b/lib_com/stat_com.h @@ -38,6 +38,7 @@ #ifndef STAT_COM_H #define STAT_COM_H +#include "ivas_cnst.h" #include #include "options.h" #include "typedef.h" @@ -443,8 +444,12 @@ typedef struct Word16 flag_noisy_speech; Word16 likelihood_noisy_speech; /* Q15 */ - Word16 coherence_fx; /* inter-channel coherence of noise Q15 */ - Word16 no_side_flag; /* indicates whether the side noise shape should be zeroed-out or not */ +#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG + Word16 coherence_fx[MDCT_ST_DTX_NUM_COHERENCE_BANDS]; /* inter-channel coherence of noise Q15 */ +#else + Word16 coherence_fx; /* inter-channel coherence of noise Q15 */ +#endif + Word16 no_side_flag; /* indicates whether the side noise shape should be zeroed-out or not */ } FD_CNG_COM, *HANDLE_FD_CNG_COM; diff --git a/lib_dec/fd_cng_dec_fx.c b/lib_dec/fd_cng_dec_fx.c index d8805c4f2..f79766af3 100644 --- a/lib_dec/fd_cng_dec_fx.c +++ b/lib_dec/fd_cng_dec_fx.c @@ -3,6 +3,13 @@ ====================================================================================*/ +#include "basop32.h" +#include "cnst.h" +#include "enh1632.h" +#include "ivas_cnst.h" +#include "ivas_rom_com.h" +#include "move.h" +#include "wmc_auto.h" #include #include "typedef.h" #include @@ -2924,12 +2931,21 @@ void generate_comfort_noise_dec_ivas_fx( temp = 0; move16(); +#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG + c1 = Sqrt16( hFdCngCom->coherence_fx[0], &temp ); /*Q15 - temp*/ +#else c1 = Sqrt16( hFdCngCom->coherence_fx, &temp ); /*Q15 - temp*/ - c1 = shl( c1, temp ); /*Q15*/ +#endif + c1 = shl( c1, temp ); /*Q15*/ temp = 0; move16(); +#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG + // TODO: float is "sqrt(1 - coherence)". Here MAX_16 is used for 1. coherence_fx is in Q15. Why isn't ONE_IN_Q15 used here? (which is different from MAX_16) + c2 = Sqrt16( sub( MAX_16, hFdCngCom->coherence_fx[0] ), &temp ); /*Q15 - temp*/ +#else c2 = Sqrt16( sub( MAX_16, hFdCngCom->coherence_fx ), &temp ); /*Q15 - temp*/ - c2 = shl( c2, temp ); /*Q15*/ +#endif + c2 = shl( c2, temp ); /*Q15*/ temp = getScaleFactor32( fftBuffer, FFTLEN ); scale_sig32( fftBuffer, FFTLEN, temp ); /*Q31 - hFdCngCom->fftBuffer_exp + temp*/ @@ -2956,7 +2972,12 @@ void generate_comfort_noise_dec_ivas_fx( { test(); test(); +#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG + test(); + IF( ( EQ_16( st->element_mode, IVAS_CPE_MDCT && NE_16( nchan_out, 1 ) ) ) || ( EQ_16( st->element_mode, IVAS_SCE ) && st->cng_ism_flag ) ) +#else IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) || ( EQ_16( st->element_mode, IVAS_SCE ) && st->cng_ism_flag ) ) +#endif { rand_gauss_fx( &tmp1, seed, Q15 ); rand_gauss_fx( &tmp2, seed2, Q15 ); @@ -2992,6 +3013,157 @@ void generate_comfort_noise_dec_ivas_fx( } ptr_i = ptr_r + 1; /*Q31 - fftBuffer_exp*/ +#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG + test(); + IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) && NE_16( nchan_out, 1 ) ) + { + Word16 band_len_accu, b; + + band_len_accu = 0; + move16(); + i = 0; + move16(); + + FOR( b = 0; b < MDCT_ST_DTX_NUM_COHERENCE_BANDS; b++ ) + { + band_len_accu = add( band_len_accu, mdct_stereo_dtx_coherence_bandlengths[b] ); + + /* First band needs to be shortened. The offset from encoder-side estimation is already in, so add it back here */ + IF( EQ_16( b, 0 ) ) + { + band_len_accu = add( band_len_accu, sub( MDCT_ST_DTX_FIRST_BAND_OFFSET, hFdCngCom->startBand ) ); + } + + /* + * for last band, we need to keep going until the end of the fft section - if there is still any + * this way, the coherence value of the last band is used for eveyrthing above as well + */ + IF( EQ_16( b, sub( MDCT_ST_DTX_NUM_COHERENCE_BANDS, 1 ) ) ) + { + band_len_accu = s_max( band_len_accu, sub( hFdCngCom->stopFFTbin, hFdCngCom->startBand ) ); + } + + /* mixing values for coherence is now frequency-dependent */ + temp = 0; + move16(); + c1 = Sqrt16( hFdCngCom->coherence_fx[b], &temp ); /*Q15 - temp*/ + c1 = shl( c1, temp ); /*Q15*/ + temp = 0; + move16(); + // TODO: float is "sqrt(1 - coherence)". Here MAX_16 is used for 1. coherence_fx is in Q15. Why isn't ONE_IN_Q15 used here? (which is different from MAX_16) + c2 = Sqrt16( sub( MAX_16, hFdCngCom->coherence_fx[b] ), &temp ); /*Q15 - temp*/ + c2 = shl( c2, temp ); /*Q15*/ + + FOR( ; i < band_len_accu; i++ ) + { + sqrtNoiseLevel_exp = sub( cngNoiseLevel_exp, 1 ); + sqrtNoiseLevel = Sqrt32( *ptr_level, &sqrtNoiseLevel_exp ); /*Q31 - sqrtNoiseLevel_exp*/ + + /* Real part in FFT bins */ + rand_gauss_fx( &tmp1, seed, Q15 ); + rand_gauss_fx( &tmp2, seed2, Q15 ); + *ptr_r = L_add( Mpy_32_16_1( tmp1, c1 ), Mpy_32_16_1( tmp2, c2 ) ); /*Q15*/ + move32(); + fftBuffer_temp_exp[idx] = Q16; + move16(); + ( *ptr_r ) = Mpy_32_32( ( *ptr_r ), sqrtNoiseLevel ); /*Q15 - sqrtNoiseLevel_exp*/ + move32(); + fftBuffer_temp_exp[idx] = add( fftBuffer_temp_exp[idx], sqrtNoiseLevel_exp ); + move16(); + idx = add( idx, 1 ); + + /* Imaginary part in FFT bins */ + rand_gauss_fx( &tmp1, seed, Q15 ); /*Q15*/ + rand_gauss_fx( &tmp2, seed2, Q15 ); /*Q15*/ + *ptr_i = L_add( Mpy_32_16_1( tmp1, c1 ), Mpy_32_16_1( tmp2, c2 ) ); /*Q15*/ + move32(); + fftBuffer_temp_exp[idx] = Q16; + move16(); + ( *ptr_i ) = Mpy_32_32( ( *ptr_i ), sqrtNoiseLevel ); /*Q15 - sqrtNoiseLevel_exp*/ + move32(); + fftBuffer_temp_exp[idx] = add( fftBuffer_temp_exp[idx], sqrtNoiseLevel_exp ); + move16(); + idx = add( idx, 1 ); + + /* advance all pointers together here */ + ptr_r += 2; + ptr_i += 2; + ptr_level++; + } + } + } + ELSE + { + FOR( ; ptr_level < cngNoiseLevel + sub( hFdCngCom->stopFFTbin, hFdCngCom->startBand ); ptr_level++ ) + { + /* Real part in FFT bins */ + test(); + test(); +#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG + test(); + IF( ( EQ_16( st->element_mode, IVAS_CPE_MDCT ) && NE_16( nchan_out, 1 ) ) || ( EQ_16( st->element_mode, IVAS_SCE ) && st->cng_ism_flag ) ) +#else + IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) || ( EQ_16( st->element_mode, IVAS_SCE ) && st->cng_ism_flag ) ) +#endif + { + rand_gauss_fx( &tmp1, seed, Q15 ); /*Q15*/ + rand_gauss_fx( &tmp2, seed2, Q15 ); /*Q15*/ + *ptr_r = L_add( Mpy_32_16_1( tmp1, c1 ), Mpy_32_16_1( tmp2, c2 ) ); /*Q15*/ + move32(); + fftBuffer_temp_exp[idx] = Q16; + move16(); + } + ELSE + { + rand_gauss_fx( ptr_r, seed, Q15 ); /*Q15*/ + fftBuffer_temp_exp[idx] = Q16; + move16(); + } + + sqrtNoiseLevel_exp = sub( cngNoiseLevel_exp, 1 ); + sqrtNoiseLevel = Sqrt32( *ptr_level, &sqrtNoiseLevel_exp ); /*Q31 - sqrtNoiseLevel_exp*/ + ( *ptr_r ) = Mpy_32_32( ( *ptr_r ), sqrtNoiseLevel ); /*Q15 - sqrtNoiseLevel_exp*/ + move32(); + fftBuffer_temp_exp[idx] = add( fftBuffer_temp_exp[idx], sqrtNoiseLevel_exp ); + move16(); + idx = add( idx, 1 ); + ptr_r += 2; + + /* Imaginary part in FFT bins */ + test(); + test(); +#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG + test(); + IF( ( EQ_16( st->element_mode, IVAS_CPE_MDCT ) && NE_16( nchan_out, 1 ) ) || ( EQ_16( st->element_mode, IVAS_SCE ) && st->cng_ism_flag ) ) +#else + IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) || ( EQ_16( st->element_mode, IVAS_SCE ) && st->cng_ism_flag ) ) +#endif + { + rand_gauss_fx( &tmp1, seed, Q15 ); /*Q15*/ + rand_gauss_fx( &tmp2, seed2, Q15 ); /*Q15*/ + *ptr_i = L_add( Mpy_32_16_1( tmp1, c1 ), Mpy_32_16_1( tmp2, c2 ) ); /*Q15*/ + move32(); + fftBuffer_temp_exp[idx] = Q16; + move16(); + } + ELSE + { + rand_gauss_fx( ptr_i, seed, Q15 ); /*Q15*/ + fftBuffer_temp_exp[idx] = Q16; + move16(); + } + sqrtNoiseLevel_exp = sub( cngNoiseLevel_exp, 1 ); + sqrtNoiseLevel = Sqrt32( *ptr_level, &sqrtNoiseLevel_exp ); /*Q31 - sqrtNoiseLevel_exp*/ + ( *ptr_i ) = Mpy_32_32( ( *ptr_i ), sqrtNoiseLevel ); /*Q15 - sqrtNoiseLevel_exp*/ + move32(); + fftBuffer_temp_exp[idx] = add( fftBuffer_temp_exp[idx], sqrtNoiseLevel_exp ); + move16(); + idx = add( idx, 1 ); + ptr_i += 2; + } + } + +#else FOR( ; ptr_level < cngNoiseLevel + sub( hFdCngCom->stopFFTbin, hFdCngCom->startBand ); ptr_level++ ) { /* Real part in FFT bins */ @@ -3049,6 +3221,7 @@ void generate_comfort_noise_dec_ivas_fx( idx = add( idx, 1 ); ptr_i += 2; } +#endif /* Remaining FFT bins are set to zero */ set32_fx( fftBuffer + shl( hFdCngCom->stopFFTbin, 1 ), 0, sub( hFdCngCom->fftlen, shl( hFdCngCom->stopFFTbin, 1 ) ) ); @@ -3159,6 +3332,13 @@ void generate_comfort_noise_dec_ivas_fx( /* Generate Gaussian random noise in real and imaginary parts of the CLDFB bands Amplitudes are adjusted to the estimated noise level cngNoiseLevel_flt in each band */ +#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG + /* + * Note: for the stereo DTX noise mixing, c1 and c2 at this point are set to the value calculated for the last band + * as all the coherence bands are in the FFT region, we do not need the special handling here + */ +#endif + test(); IF( bufferReal != NULL && ( LT_16( hFdCngCom->numCoreBands, hFdCngCom->regularStopBand ) ) ) { @@ -3174,7 +3354,12 @@ void generate_comfort_noise_dec_ivas_fx( FOR( i = 0; i < hFdCngCom->numSlots; i++ ) { /* Real part in CLDFB band */ +#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG + test(); + IF( ( EQ_16( st->element_mode, IVAS_CPE_MDCT ) && NE_16( nchan_out, 1 ) ) || ( EQ_16( st->element_mode, IVAS_SCE ) && st->cng_ism_flag ) ) +#else IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) || ( EQ_16( st->element_mode, IVAS_SCE ) && st->cng_ism_flag ) ) +#endif { rand_gauss_fx( &tmp1, seed, Q15 ); /*Q15*/ rand_gauss_fx( &tmp2, seed2, Q15 ); /*Q15*/ @@ -3197,7 +3382,12 @@ void generate_comfort_noise_dec_ivas_fx( move16(); /* Imaginary part in CLDFB band */ +#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG + test(); + IF( ( EQ_16( st->element_mode, IVAS_CPE_MDCT ) && NE_16( nchan_out, 1 ) ) || ( EQ_16( st->element_mode, IVAS_SCE ) && st->cng_ism_flag ) ) +#else IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) || ( EQ_16( st->element_mode, IVAS_SCE ) && st->cng_ism_flag ) ) +#endif { rand_gauss_fx( &tmp1, seed, Q15 ); /*Q15*/ rand_gauss_fx( &tmp2, seed2, Q15 ); /*Q15*/ @@ -3544,13 +3734,21 @@ void generate_comfort_noise_dec_hf_ivas_fx( s = 0; move16(); +#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG + c1 = Sqrt16( hFdCngCom->coherence_fx[sub( MDCT_ST_DTX_NUM_COHERENCE_BANDS, 1 )], &s ); /*Q15 - s*/ +#else c1 = Sqrt16( hFdCngCom->coherence_fx, &s ); /*Q15 - s*/ - c1 = shl( c1, s ); // Q15 +#endif + c1 = shl( c1, s ); // Q15 s = 0; move16(); +#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG + c2 = Sqrt16( sub( MAX16B, hFdCngCom->coherence_fx[sub( MDCT_ST_DTX_NUM_COHERENCE_BANDS, 1 )] ), &s ); /*Q15 - s*/ +#else c2 = Sqrt16( sub( MAX16B, hFdCngCom->coherence_fx ), &s ); /*Q15 - s*/ - c2 = shl( c2, s ); // Q15 +#endif + c2 = shl( c2, s ); // Q15 } sn = 0; @@ -5222,7 +5420,22 @@ void FdCngDecodeMDCTStereoSID_fx( Scale_sig32( ms_ptr_fx[ch], N, shift ); // Q20 } +#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG + tmp32 = sts[1]->total_brate; + sts[1]->total_brate = L_add( sts[1]->total_brate, 800 /* 16 * FRAMES_PER_SEC */ ); + /* read the four additional coherence values */ + FOR( Word16 b = 1; b < MDCT_ST_DTX_NUM_COHERENCE_BANDS; b++ ) + { + UWord16 idx; + + idx = get_next_indice_fx( sts[1], 4 ); + sts[0]->hFdCngDec->hFdCngCom->coherence_fx[b] = get_next_index_4_by_15[idx]; + sts[1]->hFdCngDec->hFdCngCom->coherence_fx[b] = sts[0]->hFdCngDec->hFdCngCom->coherence_fx[b]; + } + sts[1]->total_brate = tmp32; +#else dtx_read_padding_bits_fx( sts[1], mult( sub( IVAS_SID_5k2, 4400 ), ONE_BY_FRAMES_PER_SEC_Q15 ) ); +#endif IF( sts[0]->hFdCngDec->hFdCngCom->no_side_flag ) { @@ -5407,10 +5620,21 @@ void FdCngDecodeDiracMDCTStereoSID_fx( lpc_from_spectrum( hFdCngCom, hFdCngCom->startBand, hFdCngCom->stopFFTbin, sts[ch]->preemph_fac ); } +#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG + FOR( i = 0; i < MDCT_ST_DTX_NUM_COHERENCE_BANDS; i++ ) + { + sts[0]->hFdCngDec->hFdCngCom->coherence_fx[i] = 0; + move16(); + sts[1]->hFdCngDec->hFdCngCom->coherence_fx[i] = 0; + move16(); + } + +#else sts[0]->hFdCngDec->hFdCngCom->coherence_fx = 0; move16(); sts[1]->hFdCngDec->hFdCngCom->coherence_fx = 0; move16(); +#endif IF( EQ_16( hCPE->nchan_out, 1 ) ) { diff --git a/lib_dec/ivas_decision_matrix_dec_fx.c b/lib_dec/ivas_decision_matrix_dec_fx.c index 717bb3b93..3eac102a3 100644 --- a/lib_dec/ivas_decision_matrix_dec_fx.c +++ b/lib_dec/ivas_decision_matrix_dec_fx.c @@ -33,7 +33,7 @@ #include #include "options.h" #include "stat_dec.h" -#include "rom_com.h" +#include "ivas_rom_com.h" #include "prot_fx.h" #include "ivas_cnst.h" #include "wmc_auto.h" @@ -46,9 +46,11 @@ * Read ACELP signaling bits from the bitstream * Set extension layers *-----------------------------------------------------------------*/ +#ifndef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG static Word16 get_next_index_4_by_15[16] = { 0, 2184, 4369, 6553, 8738, 10922, 13107, 15291, 17476, 19660, 21845, 24029, 26214, 28398, 30583, 32767 }; +#endif void ivas_decision_matrix_dec_fx( Decoder_State *st, /* i/o: decoder state structure */ Word16 *sharpFlag, /* o : formant sharpening flag */ @@ -129,10 +131,13 @@ void ivas_decision_matrix_dec_fx( /* read channel coherence */ Word16 index; index = get_next_indice_fx( st, 4 ); +#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG + st->hFdCngDec->hFdCngCom->coherence_fx[0] = get_next_index_4_by_15[index]; +#else st->hFdCngDec->hFdCngCom->coherence_fx = get_next_index_4_by_15[index]; +#endif move16(); - /* read flag for no side noise shape */ st->hFdCngDec->hFdCngCom->no_side_flag = get_next_indice_fx( st, 1 ); move16(); diff --git a/lib_dec/ivas_ism_metadata_dec_fx.c b/lib_dec/ivas_ism_metadata_dec_fx.c index 2c13e25c8..3e1883220 100644 --- a/lib_dec/ivas_ism_metadata_dec_fx.c +++ b/lib_dec/ivas_ism_metadata_dec_fx.c @@ -30,6 +30,7 @@ *******************************************************************************************************/ +#include "move.h" #include #include "options.h" #include "ivas_cnst.h" @@ -1247,21 +1248,49 @@ void ivas_ism_metadata_sid_dec_fx( { IF( EQ_16( ch, *sce_id_dtx ) ) { +#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG + FOR( i = 0; i < MDCT_ST_DTX_NUM_COHERENCE_BANDS; i++ ) + { + // TODO: why not ONE_IN_Q15 ? (value there is different) + hSCE[ch]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence_fx[i] = 32767; + } + +#else hSCE[ch]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence_fx = 32767; // 1.0f in Q15 move16(); +#endif CONTINUE; } idx = get_next_indice_fx( st0, nBits_coh ); +#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG + // TODO: why is this different from the dequantization in ivas_decision_matrix_dec()? There, a table is used. Is this doing the same thing? + hSCE[ch]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence_fx[0] = div_s( idx, sub( ( shl( 1, nBits_coh ) ), 1 ) ); // Q15 + move16(); + FOR( i = 1; i < MDCT_ST_DTX_NUM_COHERENCE_BANDS; i++ ) + { + hSCE[ch]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence_fx[i] = hSCE[ch]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence_fx[0]; + move16(); + } +#else hSCE[ch]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence_fx = div_s( idx, sub( ( shl( 1, nBits_coh ) ), 1 ) ); // Q15 move16(); +#endif } } - if ( EQ_32( ism_mode, ISM_MODE_PARAM ) ) + IF( EQ_32( ism_mode, ISM_MODE_PARAM ) ) { +#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG + FOR( i = 0; i < MDCT_ST_DTX_NUM_COHERENCE_BANDS; i++ ) + { + hSCE[*sce_id_dtx]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence_fx[i] = hSCE[!*sce_id_dtx]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence_fx[i]; + move16(); + } +#else hSCE[*sce_id_dtx]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence_fx = hSCE[!*sce_id_dtx]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence_fx; move16(); +#endif } /*----------------------------------------------------------------* diff --git a/lib_dec/ivas_ism_param_dec_fx.c b/lib_dec/ivas_ism_param_dec_fx.c index d2243feb2..b029cdcfa 100644 --- a/lib_dec/ivas_ism_param_dec_fx.c +++ b/lib_dec/ivas_ism_param_dec_fx.c @@ -1837,8 +1837,12 @@ void ivas_param_ism_params_to_masa_param_mapping_fx( IF( st_ivas->hISMDTX.dtx_flag ) { - Word32 energy_ratio_fx; /* Q30 */ + Word32 energy_ratio_fx; /* Q30 */ +#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG + energy_ratio_fx = L_mult0( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence_fx[0], st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence_fx[0] ); /* Q15 + Q15 -> Q30 */ +#else energy_ratio_fx = L_mult0( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence_fx, st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence_fx ); /* Q15 + Q15 -> Q30 */ +#endif hSpatParamRendCom->numSimultaneousDirections = 1; move16(); diff --git a/lib_dec/ivas_stereo_mdct_stereo_dec_fx.c b/lib_dec/ivas_stereo_mdct_stereo_dec_fx.c index 43dc48edf..efea57f4d 100644 --- a/lib_dec/ivas_stereo_mdct_stereo_dec_fx.c +++ b/lib_dec/ivas_stereo_mdct_stereo_dec_fx.c @@ -634,7 +634,11 @@ void synchonize_channels_mdct_sid_fx( move16(); sts[1]->bwidth = sts[0]->bwidth; move16(); +#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG + sts[0]->hFdCngDec->hFdCngCom->coherence_fx[0] = sts[1]->hFdCngDec->hFdCngCom->coherence_fx[0]; /* coherence is stored in sts[1] - see ivas_decision_matrix_dec() */ +#else sts[0]->hFdCngDec->hFdCngCom->coherence_fx = sts[1]->hFdCngDec->hFdCngCom->coherence_fx; /* coherence is stored in sts[1] - see ivas_decision_matrix_dec() */ +#endif move16(); sts[0]->hFdCngDec->hFdCngCom->no_side_flag = sts[1]->hFdCngDec->hFdCngCom->no_side_flag; move16(); diff --git a/lib_enc/fd_cng_enc_fx.c b/lib_enc/fd_cng_enc_fx.c index 6834958d1..1a74fb616 100644 --- a/lib_enc/fd_cng_enc_fx.c +++ b/lib_enc/fd_cng_enc_fx.c @@ -2,12 +2,17 @@ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 ====================================================================================*/ +#include "wmc_auto.h" #include #include "stl.h" #include "options.h" #include "cnst.h" +#include "ivas_cnst.h" #include "stl.h" #include "rom_com.h" +#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG +#include "ivas_rom_com.h" +#endif #include "rom_enc.h" #include "prot_fx.h" #include "prot_fx_enc.h" @@ -144,8 +149,16 @@ void initFdCngEnc_fx( hsEnc->msPeriodogBufPtr = 0; move16(); set32_fx( hsEnc->msPsdSecondMoment_fx, 0, NPART ); +#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG + FOR( Word16 i = 0; i < MDCT_ST_DTX_NUM_COHERENCE_BANDS; i++ ) + { + set32_fx( hsEnc->mem_coherence_fx[i], EPSILON_FX, 4 ); + set16_fx( hsEnc->mem_coherence_exp[i], 0, 4 ); + } +#else set32_fx( hsEnc->mem_coherence_fx, EPSILON_FX, 4 ); set16_fx( hsEnc->mem_coherence_exp, 0, 4 ); +#endif return; } @@ -2660,8 +2673,16 @@ void stereoFdCngCoherence_fx( IF( NE_16( last_element_mode, IVAS_CPE_MDCT ) ) { +#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG + FOR( i = 0; i < MDCT_ST_DTX_NUM_COHERENCE_BANDS; i++ ) + { + set32_fx( sts[0]->hFdCngEnc->mem_coherence_fx[i], EPSILON_FX, 4 ); + set16_fx( sts[0]->hFdCngEnc->mem_coherence_exp[i], 0, 4 ); + } +#else set32_fx( sts[0]->hFdCngEnc->mem_coherence_fx, EPSILON_FX, 4 ); set16_fx( sts[0]->hFdCngEnc->mem_coherence_exp, 0, 4 ); +#endif } test(); test(); @@ -2726,8 +2747,96 @@ void stereoFdCngCoherence_fx( pt_fftL = fft_buf_fx[0]; pt_fftR = fft_buf_fx[1]; +#ifndef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG mem = sts[0]->hFdCngEnc->mem_coherence_fx; /* exp(sts[0]->hFdCngEnc->mem_coherence_exp) */ mem_exp = sts[0]->hFdCngEnc->mem_coherence_exp; +#endif + + /* only estimate coherence in inactive frames (or in the first 50 frames to build an initial value) */ + test(); + test(); + // TODO: is there a BASOP for the ! ? + IF( !( LE_32( sts[0]->ini_frame, 50 ) || ( sts[0]->vad_flag == 0 && sts[1]->vad_flag == 0 ) ) ) + { + return; + } + +#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG + FOR( i_subfr = 0; i_subfr < 2; i_subfr++ ) + { + Word16 band_len_cum; + + band_len_cum = 0; + move16(); + i = MDCT_ST_DTX_FIRST_BAND_OFFSET; + move16(); + + FOR( Word16 b = 0; b < MDCT_ST_DTX_NUM_COHERENCE_BANDS; b++ ) + { + Word16 sqr_inp, temp, sqr_out, sqr_inp_exp; + Word32 sqr_inp32; + band_len_cum += mdct_stereo_dtx_coherence_bandlengths[b]; + move16(); + cr = ci = eL = eR = EPSILON_FX; + move32(); + move32(); + move32(); + move32(); + cr_exp = ci_exp = eL_exp = eR_exp = 0; + move16(); + move16(); + move16(); + move16(); + + mem = sts[0]->hFdCngEnc->mem_coherence_fx[b]; + mem_exp = sts[0]->hFdCngEnc->mem_coherence_exp[b]; + + /* for last band, we need to make adjustments to fit with the FFT buffer layout */ + /* do the calculations for fftbin 0 (not anymore as it is skipped - we only calculate coherence above the 2nd bin) and L_FFT/2 outside the loop - imaginary part is always zero there, but not part of the buffer */ + IF( EQ_16( b, sub( MDCT_ST_DTX_NUM_COHERENCE_BANDS, 1 ) ) ) + { + /* this calculates values for fft bin at L_FFT/2 - no imaginary value there, not even part of the array */ + cr = BASOP_Util_Add_Mant32Exp( cr, cr_exp, L_mult( pt_fftL[L_FFT / 2], pt_fftR[L_FFT / 2] ), shl( fft_exp, 1 ), &cr_exp ); /* exp(cr_exp) */ + eL = BASOP_Util_Add_Mant32Exp( eL, eL_exp, L_mult( pt_fftL[L_FFT / 2], pt_fftL[L_FFT / 2] ), shl( fft_exp, 1 ), &eL_exp ); /* exp(eL_exp) */ + eR = BASOP_Util_Add_Mant32Exp( eR, eR_exp, L_mult( pt_fftR[L_FFT / 2], pt_fftR[L_FFT / 2] ), shl( fft_exp, 1 ), &eR_exp ); /* exp(eR_exp) */ + + /* skip last fft bin (fs/2 Hz) bin in the loop later */ + band_len_cum = sub( band_len_cum, 1 ); + } + + FOR( ; i < band_len_cum; i++ ) + { + cr = BASOP_Util_Add_Mant32Exp( cr, cr_exp, L_add( L_mult( pt_fftL[i], pt_fftR[i] ), L_mult( pt_fftL[L_FFT - i], pt_fftR[L_FFT - i] ) ), shl( fft_exp, 1 ), &cr_exp ); /* exp(cr_exp) */ + ci = BASOP_Util_Add_Mant32Exp( ci, ci_exp, L_add( L_mult( -pt_fftL[i], pt_fftR[L_FFT - i] ), L_mult( pt_fftL[L_FFT - i], pt_fftR[i] ) ), shl( fft_exp, 1 ), &ci_exp ); /* exp(ci_exp) */ + eL = BASOP_Util_Add_Mant32Exp( eL, eL_exp, L_add( L_mult( pt_fftL[i], pt_fftL[i] ), L_mult( pt_fftL[L_FFT - i], pt_fftL[L_FFT - i] ) ), shl( fft_exp, 1 ), &eL_exp ); /* exp(eL_exp) */ + eR = BASOP_Util_Add_Mant32Exp( eR, eR_exp, L_add( L_mult( pt_fftR[i], pt_fftR[i] ), L_mult( pt_fftR[L_FFT - i], pt_fftR[L_FFT - i] ) ), shl( fft_exp, 1 ), &eR_exp ); /* exp(eR_exp) */ + } + + mem[0] = BASOP_Util_Add_Mant32Exp( Mpy_32_16_1( mem[0], 31129 /*0.95f*/ ), mem_exp[0], Mpy_32_16_1( cr, 1638 /*0.05f*/ ), cr_exp, &mem_exp[0] ); /* exp(mem_exp[0]) */ + move32(); + mem[1] = BASOP_Util_Add_Mant32Exp( Mpy_32_16_1( mem[1], 31129 /*0.95f*/ ), mem_exp[1], Mpy_32_16_1( ci, 1638 /*0.05f*/ ), ci_exp, &mem_exp[1] ); /* exp(mem_exp[1]) */ + move32(); + mem[2] = BASOP_Util_Add_Mant32Exp( Mpy_32_16_1( mem[2], 31129 /*0.95f*/ ), mem_exp[2], Mpy_32_16_1( eL, 1638 /*0.05f*/ ), eL_exp, &mem_exp[2] ); /* exp(mem_exp[2]) */ + move32(); + mem[3] = BASOP_Util_Add_Mant32Exp( Mpy_32_16_1( mem[3], 31129 /*0.95f*/ ), mem_exp[3], Mpy_32_16_1( eR, 1638 /*0.05f*/ ), eR_exp, &mem_exp[3] ); /* exp(mem_exp[3]) */ + move32(); + + /* could be done outside the loop, as the second assignment overwrites the first, but this would mean a second loop over bands */ + /* For orientation, in float, this is "sts[0]->hFdCngEnc->hFdCngCom->coherence[b] = sqrtf( ( mem[0] * mem[0] + mem[1] * mem[1] ) / ( mem[2] * mem[3] ) );" */ + sqr_inp32 = BASOP_Util_Add_Mant32Exp( Mpy_32_32( mem[0], mem[0] ), shl( mem_exp[0], 1 ), Mpy_32_32( mem[1], mem[1] ), shl( mem_exp[1], 1 ), &sqr_inp_exp ); /* exp(sqr_inp_exp) */ + sqr_inp = BASOP_Util_Divide3232_Scale( sqr_inp32, Mpy_32_32( mem[2], mem[3] ), &temp ); + sqr_inp_exp = add( temp, sub( sqr_inp_exp, add( mem_exp[2], mem_exp[3] ) ) ); + sqr_out = Sqrt16( sqr_inp, &sqr_inp_exp ); + + sts[0]->hFdCngEnc->hFdCngCom->coherence_fx[b] = shl_sat( sqr_out, sqr_inp_exp ); // Q15 expected. + move16(); + } + + pt_fftL += L_FFT; + pt_fftR += L_FFT; + } + +#else FOR( i_subfr = 0; i_subfr < 2; i_subfr++ ) { cr = ci = eL = eR = EPSILON_FX; @@ -2769,7 +2878,9 @@ void stereoFdCngCoherence_fx( pt_fftL += L_FFT; pt_fftR += L_FFT; } +#endif +#ifndef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG Word16 sqr_inp, temp, sqr_out, sqr_inp_exp; Word32 sqr_inp32 = BASOP_Util_Add_Mant32Exp( Mpy_32_32( mem[0], mem[0] ), shl( mem_exp[0], 1 ), Mpy_32_32( mem[1], mem[1] ), shl( mem_exp[1], 1 ), &sqr_inp_exp ); /* exp(sqr_inp_exp) */ sqr_inp = BASOP_Util_Divide3232_Scale( sqr_inp32, Mpy_32_32( mem[2], mem[3] ), &temp ); @@ -2777,6 +2888,7 @@ void stereoFdCngCoherence_fx( sqr_out = Sqrt16( sqr_inp, &sqr_inp_exp ); sts[0]->hFdCngEnc->hFdCngCom->coherence_fx = shl_sat( sqr_out, sqr_inp_exp ); // Q15 expected. move16(); +#endif return; } @@ -3050,7 +3162,11 @@ void FdCngEncodeMDCTStereoSID_fx( } /* quantize channel coherence */ +#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG + coh_idx = mult_r( sts[0]->hFdCngEnc->hFdCngCom->coherence_fx[0], 15 ); +#else coh_idx = mult_r( sts[0]->hFdCngEnc->hFdCngCom->coherence_fx, 15 ); +#endif coh_idx = s_max( 0, s_min( coh_idx, 15 ) ); /* ---- Write SID bitstream ---- */ @@ -3084,8 +3200,18 @@ void FdCngEncodeMDCTStereoSID_fx( push_indice( sts[ch]->hBstr, IND_ENERGY, gain_idx[ch], 7 ); } +#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG + /* write the four additional coherence values */ + FOR( Word16 b = 1; b < MDCT_ST_DTX_NUM_COHERENCE_BANDS; b++ ) + { + coh_idx = mult_r( sts[0]->hFdCngEnc->hFdCngCom->coherence_fx[b], 15 ); + coh_idx = s_max( 0, s_min( coh_idx, 15 ) ); + push_indice( sts[1]->hBstr, IND_ENERGY, coh_idx, 4 ); + } +#else /* pad with zeros to reach common SID frame size */ push_indice( sts[1]->hBstr, IND_ENERGY, 0, ( IVAS_SID_5k2 - 4400 ) / FRAMES_PER_SEC ); +#endif return; } @@ -3289,10 +3415,17 @@ void FdCngEncodeDiracMDCTStereoSID_fx( lpc_from_spectrum( hFdCngCom, hFdCngEnc->startBandDec, hFdCngEnc->stopFFTbinDec, sts[ch]->preemph_fac ); sts[ch]->hDtxEnc->last_CNG_L_frame = sts[ch]->L_frame; } +#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG + sts[0]->hFdCngEnc->hFdCngCom->coherence_fx[0] = 0; + move16(); + sts[1]->hFdCngEnc->hFdCngCom->coherence_fx[0] = 0; + move16(); +#else sts[0]->hFdCngEnc->hFdCngCom->coherence_fx = 0; move16(); sts[1]->hFdCngEnc->hFdCngCom->coherence_fx = 0; move16(); +#endif /* ---- Write SID bitstream ---- */ diff --git a/lib_enc/stat_enc.h b/lib_enc/stat_enc.h index e20c06fd4..44125a717 100644 --- a/lib_enc/stat_enc.h +++ b/lib_enc/stat_enc.h @@ -397,8 +397,13 @@ typedef struct fd_cng_enc_structure Word16 msLogPeriodog_fx[NPART]; Word16 msLogNoiseEst_fx[NPART]; Word32 msLogNoiseEst_32fx[NPART]; /*IVAS: Q25*/ +#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG + Word32 mem_coherence_fx[MDCT_ST_DTX_NUM_COHERENCE_BANDS][4]; + Word16 mem_coherence_exp[MDCT_ST_DTX_NUM_COHERENCE_BANDS][4]; +#else Word32 mem_coherence_fx[4]; Word16 mem_coherence_exp[4]; +#endif } FD_CNG_ENC, *HANDLE_FD_CNG_ENC; -- GitLab From fe30503151ba136db73fa6bd5e03d08ec163d558 Mon Sep 17 00:00:00 2001 From: Jan Kiene Date: Thu, 23 Oct 2025 14:09:27 +0200 Subject: [PATCH 2/7] run clang-format --- lib_dec/fd_cng_dec_fx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib_dec/fd_cng_dec_fx.c b/lib_dec/fd_cng_dec_fx.c index f79766af3..6759e0145 100644 --- a/lib_dec/fd_cng_dec_fx.c +++ b/lib_dec/fd_cng_dec_fx.c @@ -2934,7 +2934,7 @@ void generate_comfort_noise_dec_ivas_fx( #ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG c1 = Sqrt16( hFdCngCom->coherence_fx[0], &temp ); /*Q15 - temp*/ #else - c1 = Sqrt16( hFdCngCom->coherence_fx, &temp ); /*Q15 - temp*/ + c1 = Sqrt16( hFdCngCom->coherence_fx, &temp ); /*Q15 - temp*/ #endif c1 = shl( c1, temp ); /*Q15*/ temp = 0; @@ -3737,7 +3737,7 @@ void generate_comfort_noise_dec_hf_ivas_fx( #ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG c1 = Sqrt16( hFdCngCom->coherence_fx[sub( MDCT_ST_DTX_NUM_COHERENCE_BANDS, 1 )], &s ); /*Q15 - s*/ #else - c1 = Sqrt16( hFdCngCom->coherence_fx, &s ); /*Q15 - s*/ + c1 = Sqrt16( hFdCngCom->coherence_fx, &s ); /*Q15 - s*/ #endif c1 = shl( c1, s ); // Q15 -- GitLab From 117cfdb20d017ad2908f3c1c171ccf2dee0cfdbc Mon Sep 17 00:00:00 2001 From: Jan Kiene Date: Tue, 28 Oct 2025 14:20:49 +0100 Subject: [PATCH 3/7] convert outstanding IF --- lib_enc/fd_cng_enc_fx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib_enc/fd_cng_enc_fx.c b/lib_enc/fd_cng_enc_fx.c index 1a74fb616..0bbbdcbd7 100644 --- a/lib_enc/fd_cng_enc_fx.c +++ b/lib_enc/fd_cng_enc_fx.c @@ -2755,8 +2755,8 @@ void stereoFdCngCoherence_fx( /* only estimate coherence in inactive frames (or in the first 50 frames to build an initial value) */ test(); test(); - // TODO: is there a BASOP for the ! ? - IF( !( LE_32( sts[0]->ini_frame, 50 ) || ( sts[0]->vad_flag == 0 && sts[1]->vad_flag == 0 ) ) ) + test(); + IF( NE_16( ( LE_32( sts[0]->ini_frame, 50 ) || ( EQ_16( sts[0]->vad_flag, 0 ) && EQ_16( sts[1]->vad_flag, 0 ) ) ), 0 ) ) { return; } -- GitLab From 29b183a6918c671e197b65d0ea24ccd51a6dd2b0 Mon Sep 17 00:00:00 2001 From: Jan Kiene Date: Tue, 28 Oct 2025 15:37:14 +0100 Subject: [PATCH 4/7] remove obsolete comments after they were clarified --- lib_dec/fd_cng_dec_fx.c | 6 ++---- lib_dec/ivas_ism_metadata_dec_fx.c | 1 - 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/lib_dec/fd_cng_dec_fx.c b/lib_dec/fd_cng_dec_fx.c index 6759e0145..e8cf26bd4 100644 --- a/lib_dec/fd_cng_dec_fx.c +++ b/lib_dec/fd_cng_dec_fx.c @@ -2934,13 +2934,12 @@ void generate_comfort_noise_dec_ivas_fx( #ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG c1 = Sqrt16( hFdCngCom->coherence_fx[0], &temp ); /*Q15 - temp*/ #else - c1 = Sqrt16( hFdCngCom->coherence_fx, &temp ); /*Q15 - temp*/ + c1 = Sqrt16( hFdCngCom->coherence_fx, &temp ); /*Q15 - temp*/ #endif c1 = shl( c1, temp ); /*Q15*/ temp = 0; move16(); #ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG - // TODO: float is "sqrt(1 - coherence)". Here MAX_16 is used for 1. coherence_fx is in Q15. Why isn't ONE_IN_Q15 used here? (which is different from MAX_16) c2 = Sqrt16( sub( MAX_16, hFdCngCom->coherence_fx[0] ), &temp ); /*Q15 - temp*/ #else c2 = Sqrt16( sub( MAX_16, hFdCngCom->coherence_fx ), &temp ); /*Q15 - temp*/ @@ -3050,7 +3049,6 @@ void generate_comfort_noise_dec_ivas_fx( c1 = shl( c1, temp ); /*Q15*/ temp = 0; move16(); - // TODO: float is "sqrt(1 - coherence)". Here MAX_16 is used for 1. coherence_fx is in Q15. Why isn't ONE_IN_Q15 used here? (which is different from MAX_16) c2 = Sqrt16( sub( MAX_16, hFdCngCom->coherence_fx[b] ), &temp ); /*Q15 - temp*/ c2 = shl( c2, temp ); /*Q15*/ @@ -3737,7 +3735,7 @@ void generate_comfort_noise_dec_hf_ivas_fx( #ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG c1 = Sqrt16( hFdCngCom->coherence_fx[sub( MDCT_ST_DTX_NUM_COHERENCE_BANDS, 1 )], &s ); /*Q15 - s*/ #else - c1 = Sqrt16( hFdCngCom->coherence_fx, &s ); /*Q15 - s*/ + c1 = Sqrt16( hFdCngCom->coherence_fx, &s ); /*Q15 - s*/ #endif c1 = shl( c1, s ); // Q15 diff --git a/lib_dec/ivas_ism_metadata_dec_fx.c b/lib_dec/ivas_ism_metadata_dec_fx.c index 3e1883220..449eb51cc 100644 --- a/lib_dec/ivas_ism_metadata_dec_fx.c +++ b/lib_dec/ivas_ism_metadata_dec_fx.c @@ -1251,7 +1251,6 @@ void ivas_ism_metadata_sid_dec_fx( #ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG FOR( i = 0; i < MDCT_ST_DTX_NUM_COHERENCE_BANDS; i++ ) { - // TODO: why not ONE_IN_Q15 ? (value there is different) hSCE[ch]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence_fx[i] = 32767; } -- GitLab From daf4c5d67eb5d791bcd21ae2ce8fc113dc306b71 Mon Sep 17 00:00:00 2001 From: Jan Kiene Date: Tue, 28 Oct 2025 15:51:48 +0100 Subject: [PATCH 5/7] align coherence value reading between files --- lib_dec/ivas_ism_metadata_dec_fx.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib_dec/ivas_ism_metadata_dec_fx.c b/lib_dec/ivas_ism_metadata_dec_fx.c index 449eb51cc..54cc5da15 100644 --- a/lib_dec/ivas_ism_metadata_dec_fx.c +++ b/lib_dec/ivas_ism_metadata_dec_fx.c @@ -1263,8 +1263,7 @@ void ivas_ism_metadata_sid_dec_fx( idx = get_next_indice_fx( st0, nBits_coh ); #ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG - // TODO: why is this different from the dequantization in ivas_decision_matrix_dec()? There, a table is used. Is this doing the same thing? - hSCE[ch]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence_fx[0] = div_s( idx, sub( ( shl( 1, nBits_coh ) ), 1 ) ); // Q15 + hSCE[ch]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence_fx[0] = get_next_index_4_by_15[idx]; // Q15 move16(); FOR( i = 1; i < MDCT_ST_DTX_NUM_COHERENCE_BANDS; i++ ) { -- GitLab From 35a5238402d02a1dc28a8668045be506d8e0d35c Mon Sep 17 00:00:00 2001 From: Jan Kiene Date: Wed, 29 Oct 2025 09:15:01 +0100 Subject: [PATCH 6/7] simplify if condition by removing irrelevant part --- lib_dec/fd_cng_dec_fx.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/lib_dec/fd_cng_dec_fx.c b/lib_dec/fd_cng_dec_fx.c index e8cf26bd4..8e20941f9 100644 --- a/lib_dec/fd_cng_dec_fx.c +++ b/lib_dec/fd_cng_dec_fx.c @@ -3096,13 +3096,7 @@ void generate_comfort_noise_dec_ivas_fx( { /* Real part in FFT bins */ test(); - test(); -#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG - test(); - IF( ( EQ_16( st->element_mode, IVAS_CPE_MDCT ) && NE_16( nchan_out, 1 ) ) || ( EQ_16( st->element_mode, IVAS_SCE ) && st->cng_ism_flag ) ) -#else - IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) || ( EQ_16( st->element_mode, IVAS_SCE ) && st->cng_ism_flag ) ) -#endif + IF( EQ_16( st->element_mode, IVAS_SCE ) && st->cng_ism_flag ) { rand_gauss_fx( &tmp1, seed, Q15 ); /*Q15*/ rand_gauss_fx( &tmp2, seed2, Q15 ); /*Q15*/ @@ -3129,13 +3123,7 @@ void generate_comfort_noise_dec_ivas_fx( /* Imaginary part in FFT bins */ test(); - test(); -#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG - test(); - IF( ( EQ_16( st->element_mode, IVAS_CPE_MDCT ) && NE_16( nchan_out, 1 ) ) || ( EQ_16( st->element_mode, IVAS_SCE ) && st->cng_ism_flag ) ) -#else - IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) || ( EQ_16( st->element_mode, IVAS_SCE ) && st->cng_ism_flag ) ) -#endif + IF( EQ_16( st->element_mode, IVAS_SCE ) && st->cng_ism_flag ) { rand_gauss_fx( &tmp1, seed, Q15 ); /*Q15*/ rand_gauss_fx( &tmp2, seed2, Q15 ); /*Q15*/ -- GitLab From 2ae89b033f0a4a4996330a34cb4c44f6f2c2e03f Mon Sep 17 00:00:00 2001 From: Jan Kiene Date: Wed, 29 Oct 2025 09:21:25 +0100 Subject: [PATCH 7/7] apply clang-format --- lib_dec/fd_cng_dec_fx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib_dec/fd_cng_dec_fx.c b/lib_dec/fd_cng_dec_fx.c index 8e20941f9..756a39e9b 100644 --- a/lib_dec/fd_cng_dec_fx.c +++ b/lib_dec/fd_cng_dec_fx.c @@ -2934,7 +2934,7 @@ void generate_comfort_noise_dec_ivas_fx( #ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG c1 = Sqrt16( hFdCngCom->coherence_fx[0], &temp ); /*Q15 - temp*/ #else - c1 = Sqrt16( hFdCngCom->coherence_fx, &temp ); /*Q15 - temp*/ + c1 = Sqrt16( hFdCngCom->coherence_fx, &temp ); /*Q15 - temp*/ #endif c1 = shl( c1, temp ); /*Q15*/ temp = 0; @@ -3723,7 +3723,7 @@ void generate_comfort_noise_dec_hf_ivas_fx( #ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG c1 = Sqrt16( hFdCngCom->coherence_fx[sub( MDCT_ST_DTX_NUM_COHERENCE_BANDS, 1 )], &s ); /*Q15 - s*/ #else - c1 = Sqrt16( hFdCngCom->coherence_fx, &s ); /*Q15 - s*/ + c1 = Sqrt16( hFdCngCom->coherence_fx, &s ); /*Q15 - s*/ #endif c1 = shl( c1, s ); // Q15 -- GitLab