diff --git a/lib_com/common_api_types.h b/lib_com/common_api_types.h index 5b158d957fbb062f99105191ca8d803ec09d0825..6334a507954a374bcc274b33093ac690c606f6a5 100644 --- a/lib_com/common_api_types.h +++ b/lib_com/common_api_types.h @@ -351,7 +351,11 @@ typedef struct _IVAS_RENDER_CONFIG float directivity[IVAS_MAX_NUM_OBJECTS * 3]; Word16 directivity_fx[IVAS_MAX_NUM_OBJECTS * 3]; // has the following q-factor pattern: {6, 6, 15, 6, 6, 15, 6, 6, 15, 6, 6, 15} float distAtt[3]; +#ifdef FIX_2500_ISM4_BIN_REVERB_DISTORTION + Word32 distAtt_fx[3]; /* {Q27, Q27, Q30} */ +#else Word32 distAtt_fx[3]; /* {Q27, Q30, Q30} */ +#endif } IVAS_RENDER_CONFIG_DATA, *IVAS_RENDER_CONFIG_HANDLE; diff --git a/lib_com/options.h b/lib_com/options.h index 86adc4edcf481d1226beacbcaeaa5104e07e4ed3..272e7f4c8d7284d7c188ff74aa9730ce5c47afb8 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -116,6 +116,7 @@ #define FIX_BASOP_2497_MCMASA_LFE_WRONG_SF_INDEX /* Nokia: BASOP 2497: Fix wrong subframe index in McMASA LFE synth. */ #define FIX_BASOP_2496_OMASA_OBJ_EDIT_WRONG_ASSIGN /* Nokia: BASOP 2496: Fix wrong assignment in OMASA object edit code */ #define FIX_2495_Q_ALIGN_OSBA_RENDERER /* FhG: Basop issue #2495: Corrected exponent scaling of outAudio.data_fx before buffer accumulation in renderSbaToBinaural(). */ +#define FIX_2500_ISM4_BIN_REVERB_DISTORTION /* FhG: Basop issue #2500: Port the missing part of RenderConfigReader_checkValues() from float; fix RefDist_fx calculation. */ /* ##################### End NON-BE switches ########################### */ diff --git a/lib_rend/ivas_objectRenderer_fx.c b/lib_rend/ivas_objectRenderer_fx.c index 19e0d450a0ded186a8996ed4319a3eb881842d65..26f8445fda7fd2cafe30f7c5cfff396ded264d38 100644 --- a/lib_rend/ivas_objectRenderer_fx.c +++ b/lib_rend/ivas_objectRenderer_fx.c @@ -204,7 +204,11 @@ ivas_error ivas_td_binaural_open_unwrap_fx( move16(); DistAtten.MaxDist_fx = 2113929216; /* Maximum radius (2^ISM_RADIUS_NBITS-1)*0.25 */ /*15.75 in Q27*/ move32(); +#ifdef FIX_2500_ISM4_BIN_REVERB_DISTORTION + DistAtten.RefDist_fx = ONE_IN_Q27; // Q27 +#else DistAtten.RefDist_fx = ONE_IN_Q30; // Q30 +#endif move32(); DistAtten.RollOffFactor_fx = ONE_IN_Q30; // Q30 move32(); @@ -264,7 +268,11 @@ ivas_error ivas_td_binaural_open_unwrap_fx( move16(); DistAtten.MaxDist_fx = 2113929216; /* Maximum radius (2^ISM_RADIUS_NBITS-1)*0.25 */ /*15.75 in Q27*/ move32(); +#ifdef FIX_2500_ISM4_BIN_REVERB_DISTORTION + DistAtten.RefDist_fx = ONE_IN_Q27; // Q27 +#else DistAtten.RefDist_fx = ONE_IN_Q30; // Q30 +#endif move32(); DistAtten.RollOffFactor_fx = ONE_IN_Q30; // Q30 move32(); diff --git a/lib_rend/ivas_objectRenderer_sources_fx.c b/lib_rend/ivas_objectRenderer_sources_fx.c index 7a278a8bb75086e823400585a42c2d01282259c0..e95c529f09655c468dbac800513dc2a5679c31ab 100644 --- a/lib_rend/ivas_objectRenderer_sources_fx.c +++ b/lib_rend/ivas_objectRenderer_sources_fx.c @@ -653,7 +653,11 @@ static void TDREND_SRC_SPATIAL_Init_fx( move16(); SrcSpatial_p->DistAtten.DistAttenModel = TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED; // Q0 move16(); +#ifdef FIX_2500_ISM4_BIN_REVERB_DISTORTION + SrcSpatial_p->DistAtten.RefDist_fx = ONE_IN_Q27; // Q27 +#else SrcSpatial_p->DistAtten.RefDist_fx = ONE_IN_Q30; // Q30 +#endif move32(); SrcSpatial_p->DistAtten.MaxDist_fx = 2113929216; /* Maximum radius (2^ISM_RADIUS_NBITS-1)*0.25 */ /*15.75 in Q27*/ move32(); @@ -859,13 +863,30 @@ static Word16 TDREND_SRC_SPATIAL_GetDistGain_fx( { case TDREND_DIST_ATTEN_MODEL_INV_DIST: /* DistGain = powf( DistAtten_p->RefDist / Dist2, DistAtten_p->RollOffFactor ); */ +#ifdef FIX_2500_ISM4_BIN_REVERB_DISTORTION + tmp16 = BASOP_Util_Divide3232_Scale( DistAtten_p->RefDist_fx, Dist2_fx, &Dist_s ); /* tmp16 is Q(15 - Dist_s + Dist2_e - 4) */ + tmp32 = L_deposit_h( tmp16 ); /* tmp32 is Q(31 - Dist_s + Dist2_e - 4) */ + /* tmp32 exponent: 31 - (31 - Dist_s + Dist2_e - 4) = Dist_s - Dist2_e + 4, RollOffFactor_fx exponent: 31 - 30 = 1 */ + tmp32 = BASOP_Util_fPow( tmp32, add( sub( Dist_s, Dist2_e ), 4 ), DistAtten_p->RollOffFactor_fx, 1, &tmp_e ); /* Q(31 - tmp_e) */ +#else tmp16 = BASOP_Util_Divide3232_Scale( DistAtten_p->RefDist_fx, Dist2_fx, &Dist_s ); /* tmp16 is Q(15 - Dist_s + Dist2_e - 1) */ tmp32 = L_deposit_h( tmp16 ); /* tmp32 is Q(31 - Dist_s + Dist2_e - 1) */ /* tmp32 exponent: 31 - (31 - Dist_s + Dist2_e - 1) = Dist_s - Dist2_e + 1, RollOffFactor_fx exponent: 31 - 30 = 1 */ tmp32 = BASOP_Util_fPow( tmp32, add( sub( Dist_s, Dist2_e ), 1 ), DistAtten_p->RollOffFactor_fx, 1, &tmp_e ); /* Q(31 - tmp_e) */ +#endif BREAK; case TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED: +#ifdef FIX_2500_ISM4_BIN_REVERB_DISTORTION + flag = BASOP_Util_Cmp_Mant32Exp( Dist2_fx, Dist2_e, DistAtten_p->RefDist_fx, 4 ); + IF( flag < 0 ) + { + Dist2_fx = DistAtten_p->RefDist_fx; // Q27 + move32(); + Dist2_e = 4; + move16(); + } +#else flag = BASOP_Util_Cmp_Mant32Exp( Dist2_fx, Dist2_e, DistAtten_p->RefDist_fx, 1 ); IF( flag < 0 ) { @@ -874,6 +895,7 @@ static Word16 TDREND_SRC_SPATIAL_GetDistGain_fx( Dist2_e = 1; move16(); } +#endif flag = BASOP_Util_Cmp_Mant32Exp( Dist2_fx, Dist2_e, DistAtten_p->MaxDist_fx, 4 ); IF( flag > 0 ) { @@ -883,10 +905,17 @@ static Word16 TDREND_SRC_SPATIAL_GetDistGain_fx( move16(); } /* DistGain = powf( DistAtten_p->RefDist / Dist2, DistAtten_p->RollOffFactor ); */ +#ifdef FIX_2500_ISM4_BIN_REVERB_DISTORTION + tmp16 = BASOP_Util_Divide3232_Scale( DistAtten_p->RefDist_fx, Dist2_fx, &Dist_s ); /* tmp16 is Q(15 - Dist_s + Dist2_e - 4) */ + tmp32 = L_deposit_h( tmp16 ); /* tmp32 is Q(31 - Dist_s + Dist2_e - 4) */ + /* tmp32 exponent: 31 - (31 - Dist_s + Dist2_e - 4) = Dist_s - Dist2_e + 4, RollOffFactor_fx exponent: 31 - 30 = 1 */ + tmp32 = BASOP_Util_fPow( tmp32, add( sub( Dist_s, Dist2_e ), 4 ), DistAtten_p->RollOffFactor_fx, 1, &tmp_e ); /* Q(31 - tmp_e) */ +#else tmp16 = BASOP_Util_Divide3232_Scale( DistAtten_p->RefDist_fx, Dist2_fx, &Dist_s ); /* tmp16 is Q(15 - Dist_s + Dist2_e - 1) */ tmp32 = L_deposit_h( tmp16 ); /* tmp32 is Q(31 - Dist_s + Dist2_e - 1) */ /* tmp32 exponent: 31 - (31 - Dist_s + Dist2_e - 1) = Dist_s - Dist2_e + 1, RollOffFactor_fx exponent: 31 - 30 = 1 */ tmp32 = BASOP_Util_fPow( tmp32, add( sub( Dist_s, Dist2_e ), 1 ), DistAtten_p->RollOffFactor_fx, 1, &tmp_e ); /* Q(31 - tmp_e) */ +#endif BREAK; } diff --git a/lib_rend/ivas_render_config_fx.c b/lib_rend/ivas_render_config_fx.c index 81f66bf60af8e61e1eac8098d2204cde18c0265f..9a7d676149d60e2a7654ed4da258f56bdc482f8c 100644 --- a/lib_rend/ivas_render_config_fx.c +++ b/lib_rend/ivas_render_config_fx.c @@ -142,7 +142,11 @@ ivas_error ivas_render_config_init_from_rom_fx( } ( *hRenderConfig )->distAtt_fx[0] = 2113929216; /* Maximum radius (2^ISM_RADIUS_NBITS-1)*0.25 */ /*15.75 in Q27*/ /* Default max dist */ move32(); +#ifdef FIX_2500_ISM4_BIN_REVERB_DISTORTION + ( *hRenderConfig )->distAtt_fx[1] = ONE_IN_Q27; // Q27 /* Default ref dist */ +#else ( *hRenderConfig )->distAtt_fx[1] = ONE_IN_Q30; // Q30 /* Default ref dist */ +#endif move32(); ( *hRenderConfig )->distAtt_fx[2] = ONE_IN_Q30; // Q30 /* Default rolloff factor */ move32(); diff --git a/lib_rend/ivas_stat_rend.h b/lib_rend/ivas_stat_rend.h index ea5fbcd4ec65ee6fa1e0e2568a28a5fda26a4595..42002c272ec04e2c7aa133ee44d6df9aaf8f953a 100644 --- a/lib_rend/ivas_stat_rend.h +++ b/lib_rend/ivas_stat_rend.h @@ -1178,7 +1178,11 @@ typedef struct ivas_hrtf_TDREND_HRFILT_FiltSet_struct typedef struct { TDREND_DistAttenModel_t DistAttenModel; - Word32 RefDist_fx; /* Q30 */ +#ifdef FIX_2500_ISM4_BIN_REVERB_DISTORTION + Word32 RefDist_fx; /* Q27 */ +#else + Word32 RefDist_fx; /* Q30 */ +#endif Word32 MaxDist_fx; /* Q27 */ Word32 RollOffFactor_fx; /* Q30 */ diff --git a/lib_util/render_config_reader.c b/lib_util/render_config_reader.c index 318072fe8566da06ff6755c612e8f231b09868ed..c1538927d70f6b0c8c7f69e845a90068cc21652e 100644 --- a/lib_util/render_config_reader.c +++ b/lib_util/render_config_reader.c @@ -48,9 +48,21 @@ #define MAX_ITEM_LENGTH ( 64 ) #define N_ABS_COEFFS ( 6 ) -#define SHORTEST_REV_DEL_LINE ( 0.015f ) -#define N_BANDS_MIN ( 2 ) -#define N_BANDS_MAX ( 60 ) +#define SHORTEST_REV_DEL_LINE ( 0.015f ) +#define N_BANDS_MIN ( 2 ) +#define N_BANDS_MAX ( 60 ) + +#ifdef FIX_2500_ISM4_BIN_REVERB_DISTORTION +#define FC_INPUT_MIN_FX 0 // ( 0.0f ) +#define FC_INPUT_MAX_Q14 1638400000 // ( 1.0e+5f ) in Q14 +#define ACOUSTIC_RT60_MIN_Q26 67109 // ( 1.0e-3f ) in Q26 +#define ACOUSTIC_RT60_MAX_Q24 1677721600 // ( 1.0e+2f ) in Q24 +#define ACOUSTIC_DSR_MIN_FX 0 // ( 0.0f ) +#define ACOUSTIC_DSR_MAX_Q24 1677721600 // ( 1.0e+2f ) in Q24 +#define INPUTPREDELAY_MIN_FX 0 // ( 0.0f ) +#define INPUTPREDELAY_MAX_Q24 1677721600 // ( 1.0e+2f ) in Q24 +#endif + #define FC_INPUT_MIN ( 0.0f ) #define FC_INPUT_MAX ( 1.0e+5f ) #define ACOUSTIC_RT60_MIN ( 1.0e-3f ) @@ -1259,18 +1271,71 @@ ivas_error RenderConfigReader_checkValues( IVAS_RENDER_CONFIG_HANDLE hRenderConfig /* o : Renderer configuration handle */ ) { +#ifdef FIX_2500_ISM4_BIN_REVERB_DISTORTION + Word16 band_idx, tab_value_err_count; + IVAS_ROOM_ACOUSTICS_CONFIG_DATA *pRoom_acoustics; + pRoom_acoustics = &hRenderConfig->roomAcoustics; + Word16 wall_idx; + Word16 i; + + tab_value_err_count = 0; + move16(); +#else int16_t band_idx, tab_value_err_count; IVAS_ROOM_ACOUSTICS_CONFIG_DATA *pRoom_acoustics; pRoom_acoustics = &hRenderConfig->roomAcoustics; tab_value_err_count = 0; int16_t wall_idx; +#endif /* Verify the number of frequency bands in the config input data */ if ( ( pRoom_acoustics->nBands > N_BANDS_MAX ) || ( pRoom_acoustics->nBands < N_BANDS_MIN ) ) { return IVAS_ERR_WRONG_PARAMS; } +#ifdef FIX_2500_ISM4_BIN_REVERB_DISTORTION + /* Verify input pre-delay value */ + if ( GT_32( pRoom_acoustics->inputPreDelay_fx, INPUTPREDELAY_MAX_Q24 ) || LT_32( pRoom_acoustics->inputPreDelay_fx, INPUTPREDELAY_MIN_FX ) ) + { + return IVAS_ERR_WRONG_PARAMS; + } + /* Verify data per band in the acoustic properties table */ + FOR( band_idx = 0; band_idx < pRoom_acoustics->nBands; band_idx++ ) + { + /* Verify if the frequencies are in the ascending order (required for interpolation) */ + IF( band_idx != 0 ) + { + if ( LE_32( pRoom_acoustics->pFc_input_fx[band_idx], pRoom_acoustics->pFc_input_fx[band_idx - 1] ) ) + { + tab_value_err_count = add( tab_value_err_count, 1 ); + } + } + /* Check the input frequencies */ + if ( GT_32( L_shr( pRoom_acoustics->pFc_input_fx[band_idx], Q2 ), FC_INPUT_MAX_Q14 ) || LT_32( pRoom_acoustics->pFc_input_fx[band_idx], FC_INPUT_MIN_FX ) ) + { + tab_value_err_count = add( tab_value_err_count, 1 ); + } + + /* Check the input RT60 values */ + if ( GT_32( L_shr( pRoom_acoustics->pAcoustic_rt60_fx[band_idx], Q2 ), ACOUSTIC_RT60_MAX_Q24 ) || LT_32( pRoom_acoustics->pAcoustic_rt60_fx[band_idx], ACOUSTIC_RT60_MIN_Q26 ) ) + { + tab_value_err_count = add( tab_value_err_count, 1 ); + } + /* Check the input DSR values */ + if ( GT_32( L_shr( pRoom_acoustics->pAcoustic_dsr_fx[band_idx], Q6 ), ACOUSTIC_DSR_MAX_Q24 ) || LT_32( pRoom_acoustics->pAcoustic_dsr_fx[band_idx], ACOUSTIC_DSR_MIN_FX ) ) + { + tab_value_err_count = add( tab_value_err_count, 1 ); + } + + /* Replace zero DSR values with very small positive values, to avoid issues with coloration filter design */ + if ( LE_32( pRoom_acoustics->pAcoustic_dsr_fx[band_idx], 0 ) ) + { + pRoom_acoustics->pAcoustic_dsr_fx[band_idx] = ACOUSTIC_DSR_EPSILON_FX; + move32(); + } + } +#else /* Verify data per band in the acoustic properties table */ for ( band_idx = 0; band_idx < pRoom_acoustics->nBands; band_idx++ ) { @@ -1289,6 +1354,7 @@ ivas_error RenderConfigReader_checkValues( pRoom_acoustics->pAcoustic_dsr_fx[band_idx] = ACOUSTIC_DSR_EPSILON_FX; } } +#endif if ( tab_value_err_count != 0 ) { @@ -1296,46 +1362,93 @@ ivas_error RenderConfigReader_checkValues( } +#ifdef FIX_2500_ISM4_BIN_REVERB_DISTORTION + IF( pRoom_acoustics->use_er == 1 ) +#else if ( pRoom_acoustics->use_er == 1 ) +#endif { /* Room dimensions */ if ( pRoom_acoustics->dimensions.x_fx < ER_MIN_ROOM_DIMENSION_FX ) { pRoom_acoustics->dimensions.x_fx = ER_MIN_ROOM_DIMENSION_FX; +#ifdef FIX_2500_ISM4_BIN_REVERB_DISTORTION + move32(); +#endif } if ( pRoom_acoustics->dimensions.x_fx > ER_MAX_ROOM_DIMENSION_FX ) { pRoom_acoustics->dimensions.x_fx = ER_MAX_ROOM_DIMENSION_FX; +#ifdef FIX_2500_ISM4_BIN_REVERB_DISTORTION + move32(); +#endif } if ( pRoom_acoustics->dimensions.y_fx < ER_MIN_ROOM_DIMENSION_FX ) { pRoom_acoustics->dimensions.y_fx = ER_MIN_ROOM_DIMENSION_FX; +#ifdef FIX_2500_ISM4_BIN_REVERB_DISTORTION + move32(); +#endif } if ( pRoom_acoustics->dimensions.y_fx > ER_MAX_ROOM_DIMENSION_FX ) { pRoom_acoustics->dimensions.y_fx = ER_MAX_ROOM_DIMENSION_FX; +#ifdef FIX_2500_ISM4_BIN_REVERB_DISTORTION + move32(); +#endif } if ( pRoom_acoustics->dimensions.z_fx < ER_MIN_ROOM_DIMENSION_FX ) { pRoom_acoustics->dimensions.z_fx = ER_MIN_ROOM_DIMENSION_FX; +#ifdef FIX_2500_ISM4_BIN_REVERB_DISTORTION + move32(); +#endif } if ( pRoom_acoustics->dimensions.z_fx > ER_MAX_ROOM_DIMENSION_FX ) { pRoom_acoustics->dimensions.z_fx = ER_MAX_ROOM_DIMENSION_FX; +#ifdef FIX_2500_ISM4_BIN_REVERB_DISTORTION + move32(); +#endif } /* Abs Coeff */ +#ifdef FIX_2500_ISM4_BIN_REVERB_DISTORTION + FOR( wall_idx = 0; wall_idx < IVAS_ROOM_ABS_COEFF; wall_idx++ ) +#else for ( wall_idx = 0; wall_idx < IVAS_ROOM_ABS_COEFF; wall_idx++ ) +#endif { if ( pRoom_acoustics->AbsCoeff_fx[wall_idx] < ER_MIN_ABS_COEFF_FX ) { pRoom_acoustics->AbsCoeff_fx[wall_idx] = ER_MIN_ABS_COEFF_FX; +#ifdef FIX_2500_ISM4_BIN_REVERB_DISTORTION + move32(); +#endif } if ( pRoom_acoustics->AbsCoeff_fx[wall_idx] > ER_MAX_ABS_COEFF_FX ) { pRoom_acoustics->AbsCoeff_fx[wall_idx] = ER_MAX_ABS_COEFF_FX; +#ifdef FIX_2500_ISM4_BIN_REVERB_DISTORTION + move32(); +#endif } } +#ifdef FIX_2500_ISM4_BIN_REVERB_DISTORTION + /* Verify range of distance attenuation parameters: 0.1 <= distAtt[0] <= distAtt[1] */ + /* 0.0 <= distAtt[2] <= 10.0 */ + hRenderConfig->distAtt_fx[0] = L_max( 13421773 /* 0.1 in Q27 */, hRenderConfig->distAtt_fx[0] ); + hRenderConfig->distAtt_fx[1] = L_max( hRenderConfig->distAtt_fx[0], hRenderConfig->distAtt_fx[1] ); + hRenderConfig->distAtt_fx[2] = L_max( 0, hRenderConfig->distAtt_fx[2] ); // min( 10.0f, hRenderConfig->distAtt[2] ) is removed, because distAtt_fx[2] is always < 10.0f in Q30 format. + + /* Verify range of directivity patterns */ + FOR( i = 0; i < IVAS_MAX_NUM_OBJECTS; i++ ) + { + hRenderConfig->directivity_fx[imult1616( i, 3 )] = s_max( 0, s_min( 23040 /*360.0f in Q6*/, hRenderConfig->directivity_fx[imult1616( i, 3 )] ) ); + hRenderConfig->directivity_fx[add( imult1616( i, 3 ), 1 )] = s_max( 0, s_min( 23040 /*360.0f in Q6*/, hRenderConfig->directivity_fx[add( imult1616( i, 3 ), 1 )] ) ); + hRenderConfig->directivity_fx[add( imult1616( i, 3 ), 2 )] = s_max( 0, s_min( ONE_IN_Q15 - 1, hRenderConfig->directivity_fx[add( imult1616( i, 3 ), 2 )] ) ); + } +#endif } @@ -3132,7 +3245,11 @@ ivas_error RenderConfigReader_getDistanceAttenuation( /* Convert to Word32 */ distAtt_fx[0] = (Word32) ( distAtt[0] * ( 1u << 27 ) ); +#ifdef FIX_2500_ISM4_BIN_REVERB_DISTORTION + distAtt_fx[1] = (Word32) ( distAtt[1] * ( 1u << 27 ) ); +#else distAtt_fx[1] = (Word32) ( distAtt[1] * ( 1u << 30 ) ); +#endif distAtt_fx[2] = (Word32) ( distAtt[2] * ( 1u << 30 ) ); return IVAS_ERR_OK;