diff --git a/lib_dec/ivas_dirac_dec.c b/lib_dec/ivas_dirac_dec.c index 2f7c925d5e8bae1bd76577cc27db20c15be7dfa7..1e01abb01514be63c9742e9d15cbd7d5fb0ad76e 100644 --- a/lib_dec/ivas_dirac_dec.c +++ b/lib_dec/ivas_dirac_dec.c @@ -868,7 +868,7 @@ ivas_error ivas_dirac_dec_config( { if ( st_ivas->renderer_type != RENDERER_STEREO_PARAMETRIC ) { - if ( ( error = ivas_dirac_dec_binaural_copy_hrtfs( &st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_dirac_dec_binaural_copy_hrtfs( &st_ivas->hHrtfParambin, output_Fs ) ) != IVAS_ERR_OK ) { return error; } diff --git a/lib_dec/ivas_init_dec.c b/lib_dec/ivas_init_dec.c index 7ed132c87b2ec8745260b72e9e9b46280b4bd219..386edd1806129fae7f61077cfc3360c3857d0abe 100644 --- a/lib_dec/ivas_init_dec.c +++ b/lib_dec/ivas_init_dec.c @@ -1955,7 +1955,7 @@ ivas_error ivas_init_decoder( { if ( st_ivas->renderer_type != RENDERER_STEREO_PARAMETRIC ) { - if ( ( error = ivas_dirac_dec_binaural_copy_hrtfs( &st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_dirac_dec_binaural_copy_hrtfs( &st_ivas->hHrtfParambin, st_ivas->hDecoderConfig->output_Fs ) ) != IVAS_ERR_OK ) { return error; } diff --git a/lib_dec/ivas_ism_dec.c b/lib_dec/ivas_ism_dec.c index 7d22eb50ba182052bd1709003d9d67bf83d4dc37..56950040da1762d13174798524ff75de7d4b4d40 100644 --- a/lib_dec/ivas_ism_dec.c +++ b/lib_dec/ivas_ism_dec.c @@ -261,7 +261,7 @@ static ivas_error ivas_ism_bitrate_switching_dec( ) { /* open the parametric binaural renderer */ - if ( ( error = ivas_dirac_dec_binaural_copy_hrtfs( &st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_dirac_dec_binaural_copy_hrtfs( &st_ivas->hHrtfParambin, st_ivas->hDecoderConfig->output_Fs ) ) != IVAS_ERR_OK ) { return error; } @@ -292,7 +292,7 @@ static ivas_error ivas_ism_bitrate_switching_dec( if ( st_ivas->hOutSetup.output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) { /* open the parametric binaural renderer */ - if ( ( error = ivas_dirac_dec_binaural_copy_hrtfs( &st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_dirac_dec_binaural_copy_hrtfs( &st_ivas->hHrtfParambin, st_ivas->hDecoderConfig->output_Fs ) ) != 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 6636f08060e01db8de1d22ed7f60622de7747c94..543138929e7874da7849adfdb04480c141917f33 100644 --- a/lib_rend/ivas_dirac_dec_binaural_functions.c +++ b/lib_rend/ivas_dirac_dec_binaural_functions.c @@ -241,8 +241,7 @@ ivas_error ivas_dirac_dec_init_binaural_data( if ( hDiracDecBin->hReverb == NULL ) #endif { - /* Todo Philips: Room acoustics should be passed here once the underlying part works. Probably enough to pick it from st_ivas but you know best. */ - if ( ( error = ivas_binaural_reverb_open_parambin( &hDiracDecBin->hReverb, nBins, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, NULL, output_Fs, st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_binaural_reverb_open_parambin( &hDiracDecBin->hReverb, nBins, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, &( st_ivas->hRenderConfig->roomAcoustics ), output_Fs, st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) { return error; } @@ -411,8 +410,8 @@ void ivas_dirac_dec_close_binaural_data( *------------------------------------------------------------------------*/ ivas_error ivas_dirac_dec_binaural_copy_hrtfs( - HRTFS_PARAMBIN_HANDLE *hHrtfParambin /* i/o: HRTF structure for rendering */ -) + HRTFS_PARAMBIN_HANDLE *hHrtfParambin, /* i/o: HRTF structure for rendering */ + const int32_t output_Fs /* output sampling rate */ ) { int16_t i, j; if ( hHrtfParambin != NULL && *hHrtfParambin != NULL ) @@ -443,6 +442,25 @@ ivas_error ivas_dirac_dec_binaural_copy_hrtfs( mvr2r( parametricReverberationEneCorrections, hrtfParambin->parametricReverberationEneCorrections, CLDFB_NO_CHANNELS_MAX ); mvr2r( parametricEarlyPartEneCorrection, hrtfParambin->parametricEarlyPartEneCorrection, CLDFB_NO_CHANNELS_MAX ); + switch ( output_Fs ) + { + case 48000: + hrtfParambin->lr_energy_and_iac[0] = defaultHRIR_left_avg_power_48kHz; + hrtfParambin->lr_energy_and_iac[1] = defaultHRIR_right_avg_power_48kHz; + hrtfParambin->lr_energy_and_iac[2] = defaultHRIR_coherence_48kHz; + break; + case 32000: + hrtfParambin->lr_energy_and_iac[0] = defaultHRIR_left_avg_power_32kHz; + hrtfParambin->lr_energy_and_iac[1] = defaultHRIR_right_avg_power_32kHz; + hrtfParambin->lr_energy_and_iac[2] = defaultHRIR_coherence_32kHz; + break; + case 16000: + hrtfParambin->lr_energy_and_iac[0] = defaultHRIR_left_avg_power_16kHz; + hrtfParambin->lr_energy_and_iac[1] = defaultHRIR_right_avg_power_16kHz; + hrtfParambin->lr_energy_and_iac[2] = defaultHRIR_coherence_16kHz; + break; + } + *hHrtfParambin = hrtfParambin; } diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h index 1cb9e5adfc13c9944fca1fce9e64b247515383e2..034c5aaf0b6e7c63fd3e80a3ad00d55f089224ec 100644 --- a/lib_rend/ivas_prot_rend.h +++ b/lib_rend/ivas_prot_rend.h @@ -225,7 +225,8 @@ void ivas_dirac_dec_close_binaural_data( ); ivas_error ivas_dirac_dec_binaural_copy_hrtfs( - HRTFS_PARAMBIN_HANDLE *hHrtfParambin /* i/o: HRTF structure for rendering */ + HRTFS_PARAMBIN_HANDLE *hHrtfParambin, /* i/o: HRTF structure for rendering */ + const int32_t output_Fs /* output sampling rate */ ); /*! r: Configured reqularization factor value */ @@ -1166,6 +1167,14 @@ ivas_error ivas_reverb_prepare_cldfb_params( float *pOutput_t60, float *pOutput_ene ); +ivas_error ivas_reverb_prepare_cldfb_params_parametric( + IVAS_ROOM_ACOUSTICS_CONFIG_DATA *pInput_params, + const int32_t output_Fs, + const float *avg_pwr_l, + const float *avg_pwr_r, + float *pOutput_t60, + float *pOutput_ene ); + void ivas_reverb_interpolate_acoustic_data( const int16_t input_table_size, const float *pInput_fc, diff --git a/lib_rend/ivas_reverb.c b/lib_rend/ivas_reverb.c index 537ecde2c294e90f1f6f071000ad4f6fc24cb1c1..1e5ea9f2ccf0b1b8e76bf5883c5db892a96fcbf1 100644 --- a/lib_rend/ivas_reverb.c +++ b/lib_rend/ivas_reverb.c @@ -1957,11 +1957,12 @@ ivas_error ivas_binaural_reverb_open_parambin( { revTimes = t60; revEne = ene; - /* Todo Philips: This needs a suitable function for ParamBin here. */ - // if ( ( error = ivas_reverb_prepare_cldfb_params( roomAcoustics, hHrtfFastConv, internal_config, false, sampling_rate, t60, ene ) ) != IVAS_ERR_OK ) - // { - // return error; - // } + + if ( ( error = ivas_reverb_prepare_cldfb_params_parametric( roomAcoustics, sampling_rate, hHrtfParambin->lr_energy_and_iac[0], hHrtfParambin->lr_energy_and_iac[1], t60, ene ) ) != IVAS_ERR_OK ) + { + return error; + } + preDelay = (int16_t) roundf( 48000.0f * roomAcoustics->acousticPreDelay / CLDFB_NO_CHANNELS_MAX ); } else diff --git a/lib_rend/ivas_reverb_utils.c b/lib_rend/ivas_reverb_utils.c index 23d7592ce6a219c6ec2d153b512fa3e46cf9b11a..96202c891e21ff0c903fb8c3680eefd8ead4f024 100644 --- a/lib_rend/ivas_reverb_utils.c +++ b/lib_rend/ivas_reverb_utils.c @@ -127,6 +127,85 @@ ivas_error ivas_reverb_prepare_cldfb_params( } +/*-----------------------------------------------------------------------------------------* + * Function ivas_reverb_parametric_set_energies() + * + * Function gets the precalculated left/right energies in FFT spectrum and computes avarage + * left/right energies to CLDFB bin center frequencies. + *-----------------------------------------------------------------------------------------*/ + +static void ivas_reverb_parametric_set_energies( const float *avg_pwr_l, const float *avg_pwr_r, const int32_t sampling_rate, float *avg_pwr_l_out, float *avg_pwr_r_out ) +{ + int16_t freq_idx; + const int16_t cldfb_freq_halfstep = MAX_SAMPLING_RATE / ( 4 * CLDFB_NO_CHANNELS_MAX ); + float input_fc[FFT_SPECTRUM_SIZE]; + float output_fc[CLDFB_NO_CHANNELS_MAX]; + + for ( freq_idx = 0; freq_idx < FFT_SPECTRUM_SIZE; freq_idx++ ) + { + input_fc[freq_idx] = freq_idx * ( 0.5f * sampling_rate / (float) ( FFT_SPECTRUM_SIZE - 1 ) ); + } + + for ( freq_idx = 0; freq_idx < CLDFB_NO_CHANNELS_MAX; freq_idx++ ) + { + output_fc[freq_idx] = (float) ( ( 2 * freq_idx + 1 ) * cldfb_freq_halfstep ); + } + + ivas_reverb_interpolate_acoustic_data( FFT_SPECTRUM_SIZE, input_fc, avg_pwr_l, avg_pwr_r, CLDFB_NO_CHANNELS_MAX, output_fc, avg_pwr_l_out, avg_pwr_r_out ); +} + +/*-----------------------------------------------------------------------------------------* + * Function ivas_reverb_prepare_cldfb_params_parametric() + * + * Prepares reverb parameters for CLDFB-based parametric reverberator + *-----------------------------------------------------------------------------------------*/ + +ivas_error ivas_reverb_prepare_cldfb_params_parametric( + IVAS_ROOM_ACOUSTICS_CONFIG_DATA *pInput_params, + const int32_t output_Fs, + const float *avg_pwr_l, + const float *avg_pwr_r, + float *pOutput_t60, + float *pOutput_ene ) +{ + int16_t idx; + float fc[CLDFB_NO_CHANNELS_MAX]; + float avg_pwr_l_out[CLDFB_NO_CHANNELS_MAX]; + float avg_pwr_r_out[CLDFB_NO_CHANNELS_MAX]; + float delay_diff, ln_1e6_inverted, exp_argument; + const float dist = DEFAULT_SRC_DIST; + const float dmx_gain_2 = 4.0f * EVS_PI * dist * dist / 0.001f; + + for ( idx = 0; idx < CLDFB_NO_CHANNELS_MAX; idx++ ) + { + fc[idx] = ( (float) idx + 0.5f ) * ( (float) MAX_SAMPLING_RATE / (float) ( 2 * CLDFB_NO_CHANNELS_MAX ) ); + } + + ivas_reverb_interpolate_acoustic_data( pInput_params->nBands, pInput_params->pFc_input, pInput_params->pAcoustic_rt60, pInput_params->pAcoustic_dsr, CLDFB_NO_CHANNELS_MAX, fc, pOutput_t60, pOutput_ene ); + + /* adjust DSR for the delay difference */ + delay_diff = pInput_params->inputPreDelay - pInput_params->acousticPreDelay; + ln_1e6_inverted = 1.0f / logf( 1e06f ); + for ( idx = 0; idx < CLDFB_NO_CHANNELS_MAX; idx++ ) + { + exp_argument = delay_diff / ( pOutput_t60[idx] * ln_1e6_inverted ); + /* Limit exponent to approx +/-100 dB in case of incoherent value of delay_diff, to prevent overflow */ + exp_argument = min( exp_argument, 23.0f ); + exp_argument = max( exp_argument, -23.0f ); + pOutput_ene[idx] *= expf( exp_argument ); + } + + ivas_reverb_parametric_set_energies( avg_pwr_l, avg_pwr_r, output_Fs, avg_pwr_l_out, avg_pwr_r_out ); + + for ( idx = 0; idx < CLDFB_NO_CHANNELS_MAX; idx++ ) + { + pOutput_ene[idx] *= 0.5f * ( avg_pwr_l_out[idx] + avg_pwr_r_out[idx] ) * dmx_gain_2; + } + + return IVAS_ERR_OK; +} + + /*-----------------------------------------------------------------------------------------* * Function ivas_cldfb_convolver() * diff --git a/lib_rend/ivas_stat_rend.h b/lib_rend/ivas_stat_rend.h index 634025e11e645d9151ede17ca14f8fb521377d9e..e08ac8b970f48e656c6129b42a67639a1e5fb8a6 100644 --- a/lib_rend/ivas_stat_rend.h +++ b/lib_rend/ivas_stat_rend.h @@ -1298,6 +1298,8 @@ typedef struct ivas_hrtfs_parambin_struct float parametricReverberationEneCorrections[CLDFB_NO_CHANNELS_MAX]; float parametricEarlyPartEneCorrection[CLDFB_NO_CHANNELS_MAX]; + const float *lr_energy_and_iac[3]; /* left/right energy and interaural coherence for late reverb */ + } HRTFS_PARAMBIN, *HRTFS_PARAMBIN_HANDLE; diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 7451583b65cc27bf9f848cb1809dd73c9e23c725..d270cbd3b790b7bca44ed6142dd459b82b3e14c4 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -3135,7 +3135,7 @@ static ivas_error initMasaDummyDecForBinauralOut( } decDummy->hSpatParamRendCom->dirac_bs_md_write_idx = 0; - if ( ( error = ivas_dirac_dec_binaural_copy_hrtfs( &decDummy->hHrtfParambin ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_dirac_dec_binaural_copy_hrtfs( &decDummy->hHrtfParambin, decDummy->hDecoderConfig->output_Fs ) ) != IVAS_ERR_OK ) { return error; } @@ -9930,7 +9930,7 @@ static ivas_error initMasaExtRenderer( { if ( hMasaExtRend->renderer_type != RENDERER_STEREO_PARAMETRIC ) { - if ( ( error = ivas_dirac_dec_binaural_copy_hrtfs( &inputMasa->hMasaExtRend->hHrtfParambin ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_dirac_dec_binaural_copy_hrtfs( &inputMasa->hMasaExtRend->hHrtfParambin, *inputMasa->base.ctx.pOutSampleRate ) ) != IVAS_ERR_OK ) { return error; }