diff --git a/lib_com/options.h b/lib_com/options.h index 926960226d1e20bb1c86d359f936e3174c39a9e6..0d67f8497fdb633786ab29686e2f4802e102f848 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -184,6 +184,8 @@ #define NONBE_FIX_1174_MCMASA_LBR_LOOP_ERROR /* Nokia: Fix issue 1174 by removing the unnecessary inner loop causing problems. */ #define NONBE_FIX_1176_OSBA_REVERB_JBM_ASAN_ERROR /* Ericsson: Issue 1176, fix in TDREND_firfilt for subframes shorter than the filter length */ +#define FIX_1139_REV_COLORATION_SHORT_T60 /* Nokia,FhG: Fix issue 1139, prevent sound coloration artefacts at very low reverberation times */ + /* ##################### End NON-BE switches ########################### */ /* ################## End DEVELOPMENT switches ######################### */ diff --git a/lib_dec/ivas_binRenderer_internal.c b/lib_dec/ivas_binRenderer_internal.c index 7bab860ae7d847696013a3f89593a416840ad3fc..fdf9f8ed8af94d499b49294a150a95832d9c4efd 100644 --- a/lib_dec/ivas_binRenderer_internal.c +++ b/lib_dec/ivas_binRenderer_internal.c @@ -1219,9 +1219,33 @@ ivas_error ivas_binRenderer_open( { #ifdef FIX_587_DEFAULT_REVERB pRoomAcoustics = ( st_ivas->hOutSetup.output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ? &( st_ivas->hRenderConfig->roomAcoustics ) : NULL; - if ( ( error = ivas_binaural_reverb_init( &( hBinRenderer->hReverb ), st_ivas->hHrtfStatistics, hBinRenderer->conv_band, hBinRenderer->timeSlots, pRoomAcoustics, st_ivas->hDecoderConfig->output_Fs, st_ivas->hHrtfFastConv->fastconvReverberationTimes, st_ivas->hHrtfFastConv->fastconvReverberationEneCorrections ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_binaural_reverb_init( &( hBinRenderer->hReverb ), + st_ivas->hHrtfStatistics, + hBinRenderer->conv_band, + hBinRenderer->timeSlots, + pRoomAcoustics, + st_ivas->hDecoderConfig->output_Fs, + st_ivas->hHrtfFastConv->fastconvReverberationTimes, + st_ivas->hHrtfFastConv->fastconvReverberationEneCorrections +#ifdef FIX_1139_REV_COLORATION_SHORT_T60 + , + hBinRenderer->earlyPartEneCorrection +#endif + ) ) != IVAS_ERR_OK ) #else - if ( ( error = ivas_binaural_reverb_init( &( hBinRenderer->hReverb ), st_ivas->hHrtfStatistics, hBinRenderer->conv_band, hBinRenderer->timeSlots, &( st_ivas->hRenderConfig->roomAcoustics ), st_ivas->hDecoderConfig->output_Fs, st_ivas->hHrtfFastConv->fastconvReverberationTimes, st_ivas->hHrtfFastConv->fastconvReverberationEneCorrections ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_binaural_reverb_init( &( hBinRenderer->hReverb ), + st_ivas->hHrtfStatistics, + hBinRenderer->conv_band, + hBinRenderer->timeSlots, + &( st_ivas->hRenderConfig->roomAcoustics ), + st_ivas->hDecoderConfig->output_Fs, + st_ivas->hHrtfFastConv->fastconvReverberationTimes, + st_ivas->hHrtfFastConv->fastconvReverberationEneCorrections +#ifdef FIX_1139_REV_COLORATION_SHORT_T60 + , + hBinRenderer->earlyPartEneCorrection +#endif + ) ) != IVAS_ERR_OK ) #endif { return error; diff --git a/lib_dec/lib_dec.c b/lib_dec/lib_dec.c index fdfb1ab55ba3962143c0f7bf0dd229344837ed9e..a67b3bc9a370770df9b89ad54d3ad6c82c39220d 100644 --- a/lib_dec/lib_dec.c +++ b/lib_dec/lib_dec.c @@ -2877,7 +2877,19 @@ ivas_error IVAS_DEC_FeedRenderConfig( if ( hIvasDec->st_ivas->hDiracDecBin[0] != NULL && hIvasDec->st_ivas->hDiracDecBin[0]->hReverb != NULL ) { ivas_binaural_reverb_close( &( hIvasDec->st_ivas->hDiracDecBin[0]->hReverb ) ); - if ( ( error = ivas_binaural_reverb_init( &( hIvasDec->st_ivas->hDiracDecBin[0]->hReverb ), hIvasDec->st_ivas->hHrtfStatistics, hIvasDec->st_ivas->hSpatParamRendCom->num_freq_bands, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, &( hRenderConfig->roomAcoustics ), hIvasDec->st_ivas->hDecoderConfig->output_Fs, NULL, NULL ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_binaural_reverb_init( &( hIvasDec->st_ivas->hDiracDecBin[0]->hReverb ), + hIvasDec->st_ivas->hHrtfStatistics, + hIvasDec->st_ivas->hSpatParamRendCom->num_freq_bands, + CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, + &( hRenderConfig->roomAcoustics ), + hIvasDec->st_ivas->hDecoderConfig->output_Fs, + NULL, + NULL +#ifdef FIX_1139_REV_COLORATION_SHORT_T60 + , + NULL +#endif + ) ) != IVAS_ERR_OK ) { return error; } @@ -2886,7 +2898,19 @@ ivas_error IVAS_DEC_FeedRenderConfig( if ( hIvasDec->st_ivas->hBinRenderer != NULL && hIvasDec->st_ivas->hBinRenderer->hReverb != NULL ) { ivas_binaural_reverb_close( &( hIvasDec->st_ivas->hBinRenderer->hReverb ) ); - if ( ( error = ivas_binaural_reverb_init( &( hIvasDec->st_ivas->hBinRenderer->hReverb ), hIvasDec->st_ivas->hHrtfStatistics, hIvasDec->st_ivas->hBinRenderer->conv_band, hIvasDec->st_ivas->hBinRenderer->timeSlots, &( hRenderConfig->roomAcoustics ), hIvasDec->st_ivas->hDecoderConfig->output_Fs, NULL, NULL ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_binaural_reverb_init( &( hIvasDec->st_ivas->hBinRenderer->hReverb ), + hIvasDec->st_ivas->hHrtfStatistics, + hIvasDec->st_ivas->hBinRenderer->conv_band, + hIvasDec->st_ivas->hBinRenderer->timeSlots, + &( hRenderConfig->roomAcoustics ), + hIvasDec->st_ivas->hDecoderConfig->output_Fs, + NULL, + NULL +#ifdef FIX_1139_REV_COLORATION_SHORT_T60 + , + NULL +#endif + ) ) != IVAS_ERR_OK ) { return error; } diff --git a/lib_rend/ivas_dirac_dec_binaural_functions.c b/lib_rend/ivas_dirac_dec_binaural_functions.c index 4e23dc51e98ead33f08b8f6d0e8553c5e7bc04e2..34e8b4555e96cc8c34314a47cc58d848f1ae7760 100644 --- a/lib_rend/ivas_dirac_dec_binaural_functions.c +++ b/lib_rend/ivas_dirac_dec_binaural_functions.c @@ -245,9 +245,33 @@ ivas_error ivas_dirac_dec_init_binaural_data( if ( hDiracDecBin->hReverb == NULL && pos_idx == 0 ) /* open reverb only for the main direction */ { #ifdef FIX_587_DEFAULT_REVERB - if ( ( error = ivas_binaural_reverb_init( &hDiracDecBin->hReverb, st_ivas->hHrtfStatistics, nBins, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, pRoomAcoustics, output_Fs, ( *phHrtfParambin )->parametricReverberationTimes, ( *phHrtfParambin )->parametricReverberationEneCorrections ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_binaural_reverb_init( &hDiracDecBin->hReverb, + st_ivas->hHrtfStatistics, + nBins, + CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, + pRoomAcoustics, + output_Fs, + ( *phHrtfParambin )->parametricReverberationTimes, + ( *phHrtfParambin )->parametricReverberationEneCorrections +#ifdef FIX_1139_REV_COLORATION_SHORT_T60 + , + hDiracDecBin->earlyPartEneCorrection +#endif + ) ) != IVAS_ERR_OK ) #else - if ( ( error = ivas_binaural_reverb_init( &hDiracDecBin->hReverb, st_ivas->hHrtfStatistics, nBins, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, &( st_ivas->hRenderConfig->roomAcoustics ), output_Fs, ( *phHrtfParambin )->parametricReverberationTimes, ( *phHrtfParambin )->parametricReverberationEneCorrections ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_binaural_reverb_init( &hDiracDecBin->hReverb, + st_ivas->hHrtfStatistics, + nBins, + CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, + &( st_ivas->hRenderConfig->roomAcoustics ), + output_Fs, + ( *phHrtfParambin )->parametricReverberationTimes, + ( *phHrtfParambin )->parametricReverberationEneCorrections +#ifdef FIX_1139_REV_COLORATION_SHORT_T60 + , + hDiracDecBin->earlyPartEneCorrection +#endif + ) ) != IVAS_ERR_OK ) #endif { return error; diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h index 8e6980b0548fda0ab1a9c66dc70c00b7c2b01446..32f7246ef5c79c4ce398ddf738a11ff22ef5d1ad 100644 --- a/lib_rend/ivas_prot_rend.h +++ b/lib_rend/ivas_prot_rend.h @@ -938,9 +938,12 @@ ivas_error ivas_binaural_reverb_init( const int32_t sampling_rate, /* i : sampling rate */ const float *defaultTimes, /* i : default reverberation times */ const float *defaultEne /* i : default reverberation energies */ + #ifdef FIX_1139_REV_COLORATION_SHORT_T60 + , + float *earlyEne /* i/o: Early part energies to be modified */ + #endif ); - void ivas_binaural_reverb_close( REVERB_STRUCT_HANDLE *hReverb /* i/o: binaural reverb handle */ ); diff --git a/lib_rend/ivas_reverb.c b/lib_rend/ivas_reverb.c index eb3c05a0ccb8c2313a807f50b6f86874bc1ac963..bc3bd4c6054ec5ea6758f1dfd6466e783544f9d8 100644 --- a/lib_rend/ivas_reverb.c +++ b/lib_rend/ivas_reverb.c @@ -56,6 +56,10 @@ #define CLDFB_SLOTS_PER_SECOND 800 /* Used for initializing reverb */ +#ifdef FIX_1139_REV_COLORATION_SHORT_T60 +#define REV_TIME_THRESHOLD ( 0.2f ) +#endif + #define INNER_BLK_SIZE 80 /* size of data blocks used for more efficient delay line and IIR filter processing */ /* should be a divisor of the frame length at any sampling rate and an even number*/ #define FFT_FILTER_WND_FLAT_REGION ( 0.40f ) /* flat section (==1) length of FFT filter window, in proportion to overlap */ @@ -254,6 +258,19 @@ static void ivas_binaural_reverb_setReverbTimes( } currentEnergy *= attenuationFactorPerSampleSq; } +#ifdef FIX_1139_REV_COLORATION_SHORT_T60 + /* In some configurations with small T60s it is possible the number of taps randomizes to zero. + Ensure at least 1 filter tap. */ + if ( tap == 0 ) + { + hReverb->tapPhaseShiftType[bin][ch][0] = (int16_t) ( binRend_rand( hReverb ) % 4 ); + hReverb->tapPointersReal[bin][ch][0] = &( hReverb->loopBufReal[bin][0] ); + hReverb->tapPointersImag[bin][ch][0] = &( hReverb->loopBufImag[bin][0] ); + tap = 1; + actualizedEnergy = 1; + } +#endif + hReverb->taps[bin][ch] = tap; /* Number of taps determined at the above random procedure */ } @@ -1864,14 +1881,24 @@ ivas_error ivas_binaural_reverb_init( const int32_t sampling_rate, /* i : sampling rate */ const float *defaultTimes, /* i : default reverberation times */ const float *defaultEne /* i : default reverberation energies */ +#ifdef FIX_1139_REV_COLORATION_SHORT_T60 + , + float *earlyEne /* i/o: Early part energies to be modified */ +#endif ) { ivas_error error; +#ifdef FIX_1139_REV_COLORATION_SHORT_T60 + int16_t preDelay, bin; + float revTimes[CLDFB_NO_CHANNELS_MAX]; + float revEne[CLDFB_NO_CHANNELS_MAX]; +#else const float *revTimes; const float *revEne; float t60[CLDFB_NO_CHANNELS_MAX]; float ene[CLDFB_NO_CHANNELS_MAX]; int16_t preDelay; +#endif error = IVAS_ERR_OK; @@ -1881,10 +1908,22 @@ ivas_error ivas_binaural_reverb_init( if ( ( roomAcoustics != NULL ) && roomAcoustics->override ) #endif { +#ifndef FIX_1139_REV_COLORATION_SHORT_T60 revTimes = t60; revEne = ene; +#endif - if ( ( error = ivas_reverb_prepare_cldfb_params( roomAcoustics, hHrtfStatistics, sampling_rate, t60, ene ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_reverb_prepare_cldfb_params( roomAcoustics, + hHrtfStatistics, + sampling_rate, +#ifdef FIX_1139_REV_COLORATION_SHORT_T60 + revTimes, + revEne +#else + t60, + ene +#endif + ) ) != IVAS_ERR_OK ) { return error; } @@ -1892,11 +1931,47 @@ ivas_error ivas_binaural_reverb_init( } else { +#ifdef FIX_1139_REV_COLORATION_SHORT_T60 + for ( bin = 0; bin < CLDFB_NO_CHANNELS_MAX; bin++ ) + { + revTimes[bin] = defaultTimes[bin]; + revEne[bin] = defaultEne[bin]; + } +#else revTimes = defaultTimes; revEne = defaultEne; +#endif preDelay = 10; } +#ifdef FIX_1139_REV_COLORATION_SHORT_T60 + for ( bin = 0; bin < CLDFB_NO_CHANNELS_MAX; bin++ ) + { + /* Adjust the room effect parameters when the reverberation time is less than a threshold value, to avoid + spectral artefacts with the synthetic reverberator. */ + if ( revTimes[bin] < REV_TIME_THRESHOLD ) + { + float adjustedEarlyEne, adjustedLateEne, adjustedRevTime; + float revTimeModifier, energyModifier; + + /* Adjust reverberation times, higher towards a threshold */ + revTimeModifier = fmaxf( 0.0f, 1.0f - ( revTimes[bin] / REV_TIME_THRESHOLD ) ); + adjustedRevTime = ( 1.0f - revTimeModifier ) * revTimes[bin]; + adjustedRevTime += revTimeModifier * ( revTimes[bin] + REV_TIME_THRESHOLD ) * 0.5f; + energyModifier = ( adjustedRevTime - revTimes[bin] ) / adjustedRevTime; + + /* Adjust early and late energies, by moving late energy to early energy */ + adjustedEarlyEne = earlyEne[bin] + revEne[bin] * energyModifier; + adjustedLateEne = revEne[bin] * ( 1.0f - energyModifier ); + + /* Store adjusted room effect parameters to be used in reverb processing */ + revTimes[bin] = adjustedRevTime; + revEne[bin] = adjustedLateEne; + earlyEne[bin] = adjustedEarlyEne; + } + } +#endif + error = ivas_binaural_reverb_open( hReverbPr, numBins, numCldfbSlotsPerFrame, sampling_rate, revTimes, revEne, preDelay ); return error; diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 264b68bf1278ec5498756121e0f2b58c3d13a59b..64c2009f101a296d60a73aafd83651aa02ae3c21 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -4312,7 +4312,19 @@ ivas_error IVAS_REND_FeedRenderConfig( if ( pMasaInput->hMasaExtRend->hDiracDecBin[0] != NULL && pMasaInput->hMasaExtRend->hDiracDecBin[0]->hReverb != NULL ) { ivas_binaural_reverb_close( &pMasaInput->hMasaExtRend->hDiracDecBin[0]->hReverb ); - if ( ( error = ivas_binaural_reverb_init( &pMasaInput->hMasaExtRend->hDiracDecBin[0]->hReverb, hIvasRend->hHrtfs.hHrtfStatistics, pMasaInput->hMasaExtRend->hSpatParamRendCom->num_freq_bands, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, &( hRenderConfig->roomAcoustics ), *pMasaInput->base.ctx.pOutSampleRate, NULL, NULL ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_binaural_reverb_init( &pMasaInput->hMasaExtRend->hDiracDecBin[0]->hReverb, + hIvasRend->hHrtfs.hHrtfStatistics, + pMasaInput->hMasaExtRend->hSpatParamRendCom->num_freq_bands, + CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, + &( hRenderConfig->roomAcoustics ), + *pMasaInput->base.ctx.pOutSampleRate, + NULL, + NULL +#ifdef FIX_1139_REV_COLORATION_SHORT_T60 + , + NULL +#endif + ) ) != IVAS_ERR_OK ) { return error; } @@ -4321,7 +4333,19 @@ ivas_error IVAS_REND_FeedRenderConfig( if ( pMasaInput->hMasaExtRend->hReverb != NULL ) { ivas_binaural_reverb_close( &pMasaInput->hMasaExtRend->hReverb ); - if ( ( error = ivas_binaural_reverb_init( &pMasaInput->hMasaExtRend->hReverb, hIvasRend->hHrtfs.hHrtfStatistics, pMasaInput->hMasaExtRend->hSpatParamRendCom->num_freq_bands, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, &( hRenderConfig->roomAcoustics ), *pMasaInput->base.ctx.pOutSampleRate, NULL, NULL ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_binaural_reverb_init( &pMasaInput->hMasaExtRend->hReverb, + hIvasRend->hHrtfs.hHrtfStatistics, + pMasaInput->hMasaExtRend->hSpatParamRendCom->num_freq_bands, + CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, + &( hRenderConfig->roomAcoustics ), + *pMasaInput->base.ctx.pOutSampleRate, + NULL, + NULL +#ifdef FIX_1139_REV_COLORATION_SHORT_T60 + , + NULL +#endif + ) ) != IVAS_ERR_OK ) { return error; } @@ -8408,9 +8432,33 @@ static ivas_error ivas_masa_ext_rend_parambin_init( if ( hDiracDecBin->hReverb == NULL && pos_idx == 0 ) /* open reverb only for the main direction */ { #ifdef FIX_587_DEFAULT_REVERB - if ( ( error = ivas_binaural_reverb_init( &hDiracDecBin->hReverb, hHrtfStatistics, nBins, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, pRoomAcoustics, output_Fs, ( *phHrtfParambin )->parametricReverberationTimes, ( *phHrtfParambin )->parametricReverberationEneCorrections ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_binaural_reverb_init( &hDiracDecBin->hReverb, + hHrtfStatistics, + nBins, + CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, + pRoomAcoustics, + output_Fs, + ( *phHrtfParambin )->parametricReverberationTimes, + ( *phHrtfParambin )->parametricReverberationEneCorrections +#ifdef FIX_1139_REV_COLORATION_SHORT_T60 + , + hDiracDecBin->earlyPartEneCorrection +#endif + ) ) != IVAS_ERR_OK ) #else - if ( ( error = ivas_binaural_reverb_init( &hDiracDecBin->hReverb, hHrtfStatistics, nBins, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, &( hRendCfg->roomAcoustics ), output_Fs, ( *phHrtfParambin )->parametricReverberationTimes, ( *phHrtfParambin )->parametricReverberationEneCorrections ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_binaural_reverb_init( &hDiracDecBin->hReverb, + hHrtfStatistics, + nBins, + CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, + &( hRendCfg->roomAcoustics ), + output_Fs, + ( *phHrtfParambin )->parametricReverberationTimes, + ( *phHrtfParambin )->parametricReverberationEneCorrections +#ifdef FIX_1139_REV_COLORATION_SHORT_T60 + , + hDiracDecBin->earlyPartEneCorrection +#endif + ) ) != IVAS_ERR_OK ) #endif { return error;