diff --git a/lib_com/options.h b/lib_com/options.h index 3a6ea645db98a0b2ea1ca4ff0987a362409d763d..0e77976572902dd1feedb3854e4da9a003f87f99 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -217,6 +217,7 @@ #define NONBE_1293_SR_HRTF /* VA: issue 1293: add support of external HRTFs in split rendering */ #define NONBE_1220_OMASA_JBM_BRATE_SW_FLUSH /* VA: issue 1220: fix bug in renderer flush in OMASA 1ISM JBM bitrate switching */ #define FIX_1369_HQ_LR_OVERFLOW /* FhG: fix BASOP overflow in hq_lr_enc(), brings floating-point code inline with FX */ +#define FIX_1139_REV_COLORATION_SHORT_T60 /* Nokia,FhG: Fix issue 1139, prevent sound coloration artefacts at very low reverberation times */ /* #################### End BASOP porting switches ############################ */ diff --git a/lib_dec/ivas_binRenderer_internal.c b/lib_dec/ivas_binRenderer_internal.c index 2a3f3a36f6ecc4fbd92dfc926bce1685a1058604..0c37769c3a2f841a4722676bf3662797653cfbe7 100644 --- a/lib_dec/ivas_binRenderer_internal.c +++ b/lib_dec/ivas_binRenderer_internal.c @@ -1200,7 +1200,19 @@ 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 + , + NULL +#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 ) #endif diff --git a/lib_dec/lib_dec.c b/lib_dec/lib_dec.c index 17b86c6b420dc0204e8bff212be5c67982b0d177..868fc4e06df67fa59773683beb0336e6b29a4610 100644 --- a/lib_dec/lib_dec.c +++ b/lib_dec/lib_dec.c @@ -2289,7 +2289,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; } @@ -2299,7 +2311,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 0aab6f6604032ccfb05ccf3381b625515cc8b289..85f265da33a2137816cf8e20ba2f498a87db5738 100644 --- a/lib_rend/ivas_dirac_dec_binaural_functions.c +++ b/lib_rend/ivas_dirac_dec_binaural_functions.c @@ -266,7 +266,19 @@ ivas_error ivas_dirac_dec_init_binaural_data( { #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF #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 ) #endif diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h index f9e3a1a2d31a09f15749a2a481c769a07d87f5de..df8e8a85326d6caffb1ea452ad26d8799d5475b9 100644 --- a/lib_rend/ivas_prot_rend.h +++ b/lib_rend/ivas_prot_rend.h @@ -935,6 +935,10 @@ 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 ); diff --git a/lib_rend/ivas_reverb.c b/lib_rend/ivas_reverb.c index 5c3a4d645d442f72ef21e07fcc20236c9e6096b6..e54b75cabc92c342f2d52defc35a574c2a58c43e 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 */ @@ -259,6 +263,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 */ } @@ -1958,14 +1975,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; @@ -1975,10 +2002,16 @@ ivas_error ivas_binaural_reverb_init( if ( ( roomAcoustics != NULL ) && roomAcoustics->override ) #endif { +#ifndef FIX_1139_REV_COLORATION_SHORT_T60 revTimes = t60; revEne = ene; +#endif +#ifdef FIX_1139_REV_COLORATION_SHORT_T60 + if ( ( error = ivas_reverb_prepare_cldfb_params( roomAcoustics, hHrtfStatistics, sampling_rate, revTimes, revEne ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_reverb_prepare_cldfb_params( roomAcoustics, hHrtfStatistics, sampling_rate, t60, ene ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -1986,11 +2019,53 @@ 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 */ + IF( earlyEne != NULL ) + { + 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; + IF( earlyEne != NULL ) + { + 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 5b6a2230f2f73fd28cc18fea6610e5d51eb313f0..81fba46f1ca18bc1bddef21421c133a9c6725f44 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -4335,7 +4335,19 @@ int16_t 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, // Todo 1892 + 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; } @@ -4343,7 +4355,19 @@ int16_t 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, // Todo 1892 + 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; } @@ -8476,7 +8500,19 @@ static ivas_error ivas_masa_ext_rend_parambin_init( { #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF #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 ) #endif