diff --git a/lib_com/bitstream_fx.c b/lib_com/bitstream_fx.c index b1c7a2efd07b91b3507671caf6a2b54ed18c92af..d2f3a61f6e6acba27e341a8037e60605126b1333 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 47e3df91ea423c8419b251649ef145603c7f901a..c8f0c31ac302487225d1f72345932585afb59c7e 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 41ffda19f3e461c6c90339092008762fc8dff3c9..c445d0299fa3acf3d7256648074877f853ad9c96 100644 --- a/lib_com/ivas_cnst.h +++ b/lib_com/ivas_cnst.h @@ -889,6 +889,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 a01dedfbab4b4c97d98a09940b9fbb47eec1291f..ca39a3138bba37476a01f35d7fad695b1bcf9b62 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -1506,11 +1506,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 44bc336d8abd7168bdfba669944e04bc8b1b2469..9773d0715db6cd47bb27636649ea460ce60daf37 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 bd0dba245c6b67aae7b771c0cc9f69e2af5aaa32..dd99410ace5508d25b478f98e1b5a84e1af30823 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 8171bdec930d790d42d6918da7c559b591170fed..2b5fe5729be45e2792a16589add08d1176b07490 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -132,6 +132,7 @@ #define FIX_1383_HEAD_TRACK_SANITIZER /* Nok: issue 1383: Fix head tracking struc values reading in renderer */ #define FIX_1330_JBM_MEMORY /* VA: issue 1330: memory savings in the JBM decoder */ #define FIX_1411_IGF_CRASH_BW_SWITCHING /* FhG: Fix for issue 1411: fixes crash that can happen for IGF with BW switching and DTX*/ +#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 7b5c9fd104ab5458a2676b909691b5a492bff1ac..5309e7ad777915352c43affb12246db259cdf68a 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 d8805c4f268703c5b33ae3d35f456b6e61aa3a6a..756a39e9b1d8b54f76c911ecaafeab3d8efaa845 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,20 @@ void generate_comfort_noise_dec_ivas_fx( temp = 0; move16(); - c1 = Sqrt16( hFdCngCom->coherence_fx, &temp ); /*Q15 - temp*/ - c1 = shl( c1, temp ); /*Q15*/ +#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*/ +#endif + c1 = shl( c1, temp ); /*Q15*/ temp = 0; move16(); +#ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG + 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 +2971,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 +3012,144 @@ 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(); + 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(); + 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*/ + *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(); + 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*/ + *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 +3207,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 +3318,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 +3340,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 +3368,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 +3720,21 @@ void generate_comfort_noise_dec_hf_ivas_fx( s = 0; move16(); - c1 = Sqrt16( hFdCngCom->coherence_fx, &s ); /*Q15 - s*/ - c1 = shl( c1, s ); // Q15 +#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*/ +#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 +5406,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 +5606,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 717bb3b93512bdd8818088c6a585e9a2376d71b6..3eac102a3dc4106b994df9b258ab6eb37d4a4f25 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 2c13e25c8a82c193a3011c50d6e41ca0da6fe483..54cc5da15e24d25f025530478d84a4674a0c5ad2 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,47 @@ 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++ ) + { + 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 + 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++ ) + { + 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 1c94fbe394e3fba0e037800d8b1b54b06ef322bb..430e087130f0f45f4ea51f03ff0e18ef0204ea29 100644 --- a/lib_dec/ivas_ism_param_dec_fx.c +++ b/lib_dec/ivas_ism_param_dec_fx.c @@ -1818,8 +1818,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 43dc48edfad2aa4e00376d17c73518e183879561..efea57f4daaf084e5dcd8fe0f32c14a8d9bd9340 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 6834958d1b0937c9e8590b4c2a97a335fe0474db..0bbbdcbd7ea7b30f7e379e0bb65d68f48999bec5 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(); + 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; + } + +#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 e20c06fd45eee9b8b8b1158c0df4b16d9722d4a7..44125a717ff581be9d35dd2ce4b17b263ef06afb 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;