diff --git a/apps/decoder.c b/apps/decoder.c index 3868f2cffd9a5c8422093ccdbe8586f6d1c100e2..a38777f30e4aa833a0640794f06e9a824593fd79 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -41,6 +41,10 @@ #ifdef IVAS_RTPDUMP #include "ivas_rtp_file.h" #endif +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT +#include "ivas_cnst.h" +#endif + #include "jbm_file_writer.h" #include "hrtf_file_reader.h" #include "ls_custom_file_reader.h" @@ -229,6 +233,10 @@ int main( IVAS_RENDER_FRAMESIZE asked_frame_size; IVAS_DEC_HRTF_BINARY_WRAPPER hHrtfBinary; ObjectEditFileReader *objectEditFileReader = NULL; +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT + IVAS_ROOM_ACOUSTICS_CONFIG_DATA **pAE = NULL; + uint32_t aeCount = 0; +#endif #ifdef DEBUGGING int32_t noClipping; int32_t cnt_frames_limited; @@ -453,7 +461,11 @@ int main( *------------------------------------------------------------------------------------------*/ asked_frame_size = arg.renderFramesize; +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT + uint16_t aeID = arg.aeSequence.count > 0 ? arg.aeSequence.pID[0] : IVAS_DEFAULT_AEID; +#else uint16_t aeID = arg.aeSequence.count > 0 ? arg.aeSequence.pID[0] : 65535; +#endif #ifdef IVAS_RTPDUMP arg.enableHeadRotation = arg.enableHeadRotation || arg.outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || arg.outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM; @@ -634,6 +646,47 @@ int main( fprintf( stderr, "Failed to read renderer configuration from file %s\n\n", arg.renderConfigFilename ); goto cleanup; } +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT + aeCount = RenderConfigReader_getAcousticEnvironmentCount( renderConfigReader ); + if ( aeCount > 0 ) + { + uint32_t n; + + pAE = malloc( aeCount * sizeof( IVAS_ROOM_ACOUSTICS_CONFIG_DATA * ) ); + + if ( pAE == NULL ) + { + fprintf( stderr, "\nError: cannot allocate memory for acoustic environment array\n\n" ); + goto cleanup; + } + + for ( n = 0; n < aeCount; n++ ) + { + pAE[n] = NULL; + + if ( NULL == ( pAE[n] = malloc( sizeof( IVAS_ROOM_ACOUSTICS_CONFIG_DATA ) ) ) ) + { + fprintf( stderr, "\nError: cannot allocate memory for acoustic environment\n\n" ); + goto cleanup; + } + } + + if ( ( error = RenderConfigReader_getAcousticEnvironments( renderConfigReader, pAE ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error while getting acoustic environments\n\n" ); + goto cleanup; + } + + for ( n = 0; n < aeCount; n++ ) + { + if ( ( error = IVAS_DEC_AddAcousticEnvironment( hIvasDec, *pAE[n] ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Failed to add acoustic environments\n\n" ); + goto cleanup; + } + } + } +#endif if ( ( error = RenderConfigReader_getDirectivity( renderConfigReader, arg.directivityPatternId, renderConfig.directivity ) ) != IVAS_ERR_OK ) { @@ -672,7 +725,11 @@ int main( if ( arg.outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) { +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT + if ( ( error = IVAS_DEC_GetAcousticEnvironment( hIvasDec, aeID, &renderConfig.roomAcoustics ) ) == IVAS_ERR_OK ) +#else if ( ( error = RenderConfigReader_getAcousticEnvironment( renderConfigReader, aeID, &renderConfig.roomAcoustics ) ) == IVAS_ERR_OK ) +#endif { if ( RenderConfigReader_checkValues( &renderConfig ) != IVAS_ERR_OK ) { @@ -807,6 +864,19 @@ cleanup: free( pcmBuf ); +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT + if ( pAE != NULL ) + { + uint16_t n; + + for ( n = 0; n < aeCount; n++ ) + { + free( pAE[n] ); + } + + free( pAE ); + } +#endif if ( arg.aeSequence.count > 0 ) { free( arg.aeSequence.pID ); diff --git a/lib_com/common_api_types.h b/lib_com/common_api_types.h index 80c90d6b3152a5ace3ef0f0f205ac0c61784a356..506b155ef52418a2bf062fc6b50c373243a27a48 100644 --- a/lib_com/common_api_types.h +++ b/lib_com/common_api_types.h @@ -312,6 +312,9 @@ typedef enum #endif typedef struct _IVAS_ROOM_ACOUSTICS_CONFIG { +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT + uint16_t aeID; /* Acoustic environment ID*/ +#endif int16_t nBands; /* Number of frequency bands for which reverb properties are provided, integer, range [2..256] */ float pFc_input[IVAS_CLDFB_NO_CHANNELS_MAX]; /* Center frequencies for which following values are provided: */ float pAcoustic_rt60[IVAS_CLDFB_NO_CHANNELS_MAX]; /* - The room's T60 per center frequency */ diff --git a/lib_com/ivas_cnst.h b/lib_com/ivas_cnst.h index 6b29fb22b1cb1bdcc681a2b6fb3501e44248a723..7909d6959fdbe9d421c5627544359bb2cc96e544 100644 --- a/lib_com/ivas_cnst.h +++ b/lib_com/ivas_cnst.h @@ -1602,6 +1602,9 @@ typedef enum #define RV_LENGTH_NR_FC ( RV_FILTER_MAX_FFT_SIZE / 2 ) + 1 #define RV_LENGTH_NR_FC_16KHZ ( RV_FILTER_MAX_FFT_SIZE / 4 ) + 1 #define IVAS_REVERB_DEFAULT_N_BANDS 31 +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT +#define IVAS_DEFAULT_AEID ( 65535 ) +#endif #define LR_IAC_LENGTH_NR_FC ( RV_LENGTH_NR_FC ) #define LR_IAC_LENGTH_NR_FC_16KHZ ( RV_LENGTH_NR_FC_16KHZ ) diff --git a/lib_com/options.h b/lib_com/options.h index 2946557b0fd337390eaaa0fea67bd4d052256599..cfdbd147006279ba5cf9bd18c667e0be097812cb 100755 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -161,6 +161,7 @@ #define RTP_S4_251135_CR26253_0016_REV1 /* RTP Pack/Unpack API corresponding to CR 26253 */ #define IVAS_RTPDUMP /* RTPDUMP writing and reading for IVAS payloads */ +#define IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT /* RTPDUMP acoustic environment */ #define FIXED_RTP_SEQUENCE_NUM /* Remove random sequence number initialization */ /* ################### Start BE switches ################################# */ diff --git a/lib_dec/ivas_init_dec.c b/lib_dec/ivas_init_dec.c index 71d89e77da3299b93a1b3e62b25cdd0e5b3f9363..9c2783db3c946ec5655934f50ef4ecb3dffc4200 100644 --- a/lib_dec/ivas_init_dec.c +++ b/lib_dec/ivas_init_dec.c @@ -2649,6 +2649,10 @@ void ivas_initialize_handles_dec( st_ivas->hRenderConfig = NULL; st_ivas->hExtOrientationData = NULL; st_ivas->hCombinedOrientationData = NULL; +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT + st_ivas->acousticEnvironmentsCount = 0; + st_ivas->pAcousticEnvironments = NULL; +#endif st_ivas->hSplitBinRend = NULL; for ( i = 0; i < MAX_HEAD_ROT_POSES - 1; ++i ) @@ -2895,6 +2899,15 @@ void ivas_destroy_dec( st_ivas->p_output_f[i] = NULL; } +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT + /* Acoustic environments */ + if ( st_ivas->pAcousticEnvironments != NULL ) + { + free( st_ivas->pAcousticEnvironments ); + st_ivas->pAcousticEnvironments = NULL; + } +#endif + /* main IVAS handle */ free( st_ivas ); diff --git a/lib_dec/ivas_stat_dec.h b/lib_dec/ivas_stat_dec.h index f1efb32a1019670330be0bc7f647dbadc404a0d3..3214dc9dd037173400837ca4ed7712d705844b50 100644 --- a/lib_dec/ivas_stat_dec.h +++ b/lib_dec/ivas_stat_dec.h @@ -1128,6 +1128,10 @@ typedef struct Decoder_Struct MASA_ISM_DATA_HANDLE hMasaIsmData; /* OMASA rendering handle */ SBA_ISM_DATA_HANDLE hSbaIsmData; /* OSBA rendering handle */ +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT + IVAS_ROOM_ACOUSTICS_CONFIG_DATA *pAcousticEnvironments; /* Acoustic environment array */ + uint16_t acousticEnvironmentsCount; /* Number of acoustic environments in the array*/ +#endif int16_t flag_omasa_brate; ISAR_DEC_SPLIT_REND_WRAPPER_HANDLE hSplitBinRend; /* ISAR split binaural rendering handle */ diff --git a/lib_dec/lib_dec.c b/lib_dec/lib_dec.c index 442b0b2117782cc076418514e099e2bfad60a399..3e79ae72a5018db1b2b5db81fddcdc574bb722c3 100644 --- a/lib_dec/lib_dec.c +++ b/lib_dec/lib_dec.c @@ -3283,6 +3283,149 @@ ivas_error IVAS_DEC_HRTF_binary_close( return IVAS_ERR_OK; } +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT +/*---------------------------------------------------------------------* + * IVAS_DEC_AddAcousticEnvironment( ) + * + * Adds acoustic environment configuration + *---------------------------------------------------------------------*/ + +ivas_error IVAS_DEC_AddAcousticEnvironment( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + const IVAS_ROOM_ACOUSTICS_CONFIG_DATA roomAcousticsConfig /* i : Room acoustic configuration */ +) +{ + uint16_t n; + Decoder_Struct *st_ivas; + IVAS_ROOM_ACOUSTICS_CONFIG_DATA *pAE = NULL; + + if ( hIvasDec == NULL || hIvasDec->st_ivas == NULL || ( hIvasDec->st_ivas->acousticEnvironmentsCount > 0 && hIvasDec->st_ivas->pAcousticEnvironments == NULL ) ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + st_ivas = hIvasDec->st_ivas; + + /* Check if already there */ + for ( n = 0; n < st_ivas->acousticEnvironmentsCount; n++ ) + { + if ( st_ivas->pAcousticEnvironments[n].aeID == roomAcousticsConfig.aeID ) + { + pAE = &st_ivas->pAcousticEnvironments[n]; + break; + } + } + + /* If not found */ + if ( pAE == NULL ) + { + IVAS_ROOM_ACOUSTICS_CONFIG_DATA *ppAE = realloc( st_ivas->pAcousticEnvironments, ( st_ivas->acousticEnvironmentsCount + 1 ) * sizeof( IVAS_ROOM_ACOUSTICS_CONFIG_DATA ) ); + + if ( ppAE == NULL ) + { + return IVAS_ERR_FAILED_ALLOC; + } + st_ivas->pAcousticEnvironments = ppAE; + n = st_ivas->acousticEnvironmentsCount++; + pAE = &st_ivas->pAcousticEnvironments[n]; + } + + pAE->aeID = roomAcousticsConfig.aeID; + pAE->nBands = roomAcousticsConfig.nBands; + pAE->acousticPreDelay = roomAcousticsConfig.acousticPreDelay; + pAE->inputPreDelay = roomAcousticsConfig.inputPreDelay; + + mvr2r( roomAcousticsConfig.pFc_input, pAE->pFc_input, CLDFB_NO_CHANNELS_MAX ); + mvr2r( roomAcousticsConfig.pAcoustic_rt60, pAE->pAcoustic_rt60, CLDFB_NO_CHANNELS_MAX ); + mvr2r( roomAcousticsConfig.pAcoustic_dsr, pAE->pAcoustic_dsr, CLDFB_NO_CHANNELS_MAX ); + + pAE->use_er = roomAcousticsConfig.use_er; + + if ( pAE->use_er == 1 ) + { + pAE->lowComplexity = roomAcousticsConfig.lowComplexity; + pAE->dimensions.x = roomAcousticsConfig.dimensions.x; + pAE->dimensions.y = roomAcousticsConfig.dimensions.y; + pAE->dimensions.z = roomAcousticsConfig.dimensions.z; + pAE->ListenerOrigin.x = roomAcousticsConfig.ListenerOrigin.x; + pAE->ListenerOrigin.y = roomAcousticsConfig.ListenerOrigin.y; + pAE->ListenerOrigin.z = roomAcousticsConfig.ListenerOrigin.z; + + mvr2r( roomAcousticsConfig.AbsCoeff, pAE->AbsCoeff, IVAS_ROOM_ABS_COEFF ); + } + + return IVAS_ERR_OK; +} + +/*---------------------------------------------------------------------* + * IVAS_DEC_GetAcousticEnvironment( ) + * + * Gets acoustic environment configuration with a given ID + *---------------------------------------------------------------------*/ +ivas_error IVAS_DEC_GetAcousticEnvironment( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + uint16_t aeID, /* i : Acoustic environment ID */ + IVAS_ROOM_ACOUSTICS_CONFIG_DATA *pAcEnv /* o : Room acoustic environment data pointer */ +) +{ + uint16_t n, m; + uint16_t found = 0; + + Decoder_Struct *st_ivas; + + if ( hIvasDec == NULL || pAcEnv == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + st_ivas = hIvasDec->st_ivas; + + /* In case of default AE ID, select the first one available */ + if ( aeID == IVAS_DEFAULT_AEID && st_ivas->acousticEnvironmentsCount > 0 ) + { + aeID = (uint16_t) st_ivas->pAcousticEnvironments[0].aeID; + } + + for ( n = 0; n < st_ivas->acousticEnvironmentsCount; n++ ) + { + IVAS_ROOM_ACOUSTICS_CONFIG_DATA ae = st_ivas->pAcousticEnvironments[n]; + if ( aeID == ae.aeID ) + { + found = 1; + pAcEnv->aeID = aeID; + pAcEnv->nBands = ae.nBands; + pAcEnv->inputPreDelay = ae.inputPreDelay; + for ( m = 0; m < pAcEnv->nBands; m++ ) + { + pAcEnv->pFc_input[m] = ae.pFc_input[m]; + pAcEnv->pAcoustic_rt60[m] = ae.pAcoustic_rt60[m]; + pAcEnv->pAcoustic_dsr[m] = ae.pAcoustic_dsr[m]; + } + + /* If ER are allocated then propagate parameters */ + pAcEnv->use_er = ae.use_er; + if ( ae.use_er != 0 ) + { + pAcEnv->lowComplexity = ae.lowComplexity; + + pAcEnv->dimensions.x = ae.dimensions.x; + pAcEnv->dimensions.y = ae.dimensions.y; + pAcEnv->dimensions.z = ae.dimensions.z; + + pAcEnv->ListenerOrigin.x = ae.ListenerOrigin.x; + pAcEnv->ListenerOrigin.y = ae.ListenerOrigin.y; + pAcEnv->ListenerOrigin.z = ae.ListenerOrigin.z; + + for ( m = 0; m < IVAS_ROOM_ABS_COEFF; m++ ) + { + pAcEnv->AbsCoeff[m] = ae.AbsCoeff[m]; + } + } + } + } + + return found ? IVAS_ERR_OK : IVAS_ERR_ACOUSTIC_ENVIRONMENT_MISSING; +} +#endif /*---------------------------------------------------------------------* * copyRendererConfigStruct( ) @@ -3312,6 +3455,9 @@ static ivas_error copyRendererConfigStruct( hRCout->renderer_type_override = IVAS_RENDER_TYPE_OVERRIDE_NONE; break; } +#endif +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT + hRCout->roomAcoustics.aeID = hRCin->roomAcoustics.aeID; #endif hRCout->roomAcoustics.nBands = hRCin->roomAcoustics.nBands; hRCout->roomAcoustics.acousticPreDelay = hRCin->roomAcoustics.acousticPreDelay; @@ -3409,6 +3555,9 @@ ivas_error IVAS_DEC_FeedRenderConfig( { hRenderConfig->renderer_type_override = IVAS_RENDER_TYPE_OVERRIDE_CREND; } +#endif +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT + hRenderConfig->roomAcoustics.aeID = renderConfig.roomAcoustics.aeID; #endif hRenderConfig->roomAcoustics.nBands = renderConfig.roomAcoustics.nBands; hRenderConfig->roomAcoustics.acousticPreDelay = renderConfig.roomAcoustics.acousticPreDelay; @@ -3495,6 +3644,135 @@ ivas_error IVAS_DEC_FeedRenderConfig( return IVAS_ERR_OK; } +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT +/*---------------------------------------------------------------------* + * IVAS_DEC_FeedAcousticEnvPI( ) + * + * Set acoustic environment from the PI data + *---------------------------------------------------------------------*/ + +static ivas_error IVAS_DEC_FeedAcousticEnvPI( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + const IVAS_PIDATA_ACOUSTIC_ENV hAcoustEnvPI /* i : Render configuration struct */ +) +{ + RENDER_CONFIG_HANDLE hRenderConfig; + Decoder_Struct *st_ivas; + ivas_error error; + + if ( hIvasDec == NULL || hIvasDec->st_ivas == NULL || hIvasDec->st_ivas->hRenderConfig == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + hRenderConfig = hIvasDec->st_ivas->hRenderConfig; + st_ivas = hIvasDec->st_ivas; + +#ifdef DEBUGGING + hRenderConfig->renderer_type_override = IVAS_RENDER_TYPE_OVERRIDE_NONE; + if ( renderConfig.renderer_type_override == IVAS_RENDER_TYPE_OVERRIDE_FASTCONV ) + { + hRenderConfig->renderer_type_override = IVAS_RENDER_TYPE_OVERRIDE_FASTCONV; + } + if ( renderConfig.renderer_type_override == IVAS_RENDER_TYPE_OVERRIDE_CREND ) + { + hRenderConfig->renderer_type_override = IVAS_RENDER_TYPE_OVERRIDE_CREND; + } +#endif + /* Ignore if AE ID already in use */ + if ( hRenderConfig->roomAcoustics.aeID == hAcoustEnvPI.aeid ) + { + return IVAS_ERR_OK; + } + + /* Attempt to load the one already available */ + if ( ( error = IVAS_DEC_GetAcousticEnvironment( hIvasDec, hAcoustEnvPI.aeid, &hRenderConfig->roomAcoustics ) ) == IVAS_ERR_ACOUSTIC_ENVIRONMENT_MISSING ) + { + /* Add the new compact room environment */ + IVAS_ROOM_ACOUSTICS_CONFIG_DATA acEnv; + + acEnv.aeID = hAcoustEnvPI.aeid; + acEnv.nBands = IVAS_PI_AE_NUM_BANDS; + acEnv.pFc_input[IVAS_PI_AE_LOW] = IVAS_PI_AE_LOW_FREQ; + acEnv.pFc_input[IVAS_PI_AE_MID] = IVAS_PI_AE_MID_FREQ; + acEnv.pFc_input[IVAS_PI_AE_HIGH] = IVAS_PI_AE_HIGH_FREQ; + acEnv.pAcoustic_rt60[IVAS_PI_AE_LOW] = hAcoustEnvPI.rt60[IVAS_PI_AE_LOW]; + acEnv.pAcoustic_rt60[IVAS_PI_AE_MID] = hAcoustEnvPI.rt60[IVAS_PI_AE_MID]; + acEnv.pAcoustic_rt60[IVAS_PI_AE_HIGH] = hAcoustEnvPI.rt60[IVAS_PI_AE_HIGH]; + acEnv.inputPreDelay = (float) ( 0.1 * hRenderConfig->roomAcoustics.pAcoustic_rt60[IVAS_PI_AE_MID] ); + acEnv.pAcoustic_dsr[IVAS_PI_AE_LOW] = powf( 10.0f, hAcoustEnvPI.dsr[IVAS_PI_AE_LOW] / 10.0f ); + acEnv.pAcoustic_dsr[IVAS_PI_AE_MID] = powf( 10.0f, hAcoustEnvPI.dsr[IVAS_PI_AE_MID] / 10.0f ); + acEnv.pAcoustic_dsr[IVAS_PI_AE_HIGH] = powf( 10.0f, hAcoustEnvPI.dsr[IVAS_PI_AE_HIGH] / 10.0f ); + + acEnv.use_er = hAcoustEnvPI.availEarlyReflections; + + if ( hAcoustEnvPI.availEarlyReflections ) + { + hRenderConfig->roomAcoustics.dimensions.x = hAcoustEnvPI.roomDimensions.x; + hRenderConfig->roomAcoustics.dimensions.y = hAcoustEnvPI.roomDimensions.y; + hRenderConfig->roomAcoustics.dimensions.z = hAcoustEnvPI.roomDimensions.z; + mvr2r( hAcoustEnvPI.absorbCoeffs, hRenderConfig->roomAcoustics.AbsCoeff, IVAS_ROOM_ABS_COEFF ); + } + + if ( ( error = IVAS_DEC_AddAcousticEnvironment( hIvasDec, acEnv ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = IVAS_DEC_GetAcousticEnvironment( hIvasDec, hAcoustEnvPI.aeid, &hRenderConfig->roomAcoustics ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* Re-initialize reverb instance if already available */ + + /* TD renderer Jot reverberator */ + if ( st_ivas->hReverb != NULL ) + { + if ( ( error = ivas_reverb_open( &st_ivas->hReverb, st_ivas->hHrtfStatistics, hRenderConfig, st_ivas->hDecoderConfig->output_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* CREND Jot reverberator */ + if ( st_ivas->hCrendWrapper != NULL && st_ivas->hCrendWrapper->hCrend[0] != NULL && st_ivas->hCrendWrapper->hCrend[0]->hReverb != NULL ) + { + if ( ( error = ivas_reverb_open( &st_ivas->hCrendWrapper->hCrend[0]->hReverb, st_ivas->hHrtfStatistics, hRenderConfig, st_ivas->hDecoderConfig->output_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* Parametric renderer reverberator */ + if ( st_ivas->hDiracDecBin[0] != NULL && st_ivas->hDiracDecBin[0]->hReverb != NULL ) + { + ivas_binaural_reverb_close( &( st_ivas->hDiracDecBin[0]->hReverb ) ); + + if ( ( error = ivas_binaural_reverb_init( &( st_ivas->hDiracDecBin[0]->hReverb ), st_ivas->hHrtfStatistics, st_ivas->hSpatParamRendCom->num_freq_bands, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, + &( hRenderConfig->roomAcoustics ), st_ivas->hDecoderConfig->output_Fs, NULL, NULL, NULL ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* FastConv renderer reverberator */ + if ( st_ivas->hBinRenderer != NULL && st_ivas->hBinRenderer->hReverb != NULL ) + { + ivas_binaural_reverb_close( &( st_ivas->hBinRenderer->hReverb ) ); + + if ( ( error = ivas_binaural_reverb_init( &( st_ivas->hBinRenderer->hReverb ), st_ivas->hHrtfStatistics, st_ivas->hBinRenderer->conv_band, st_ivas->hBinRenderer->timeSlots, + &( hRenderConfig->roomAcoustics ), st_ivas->hDecoderConfig->output_Fs, NULL, NULL, NULL ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + return IVAS_ERR_OK; +} + +#endif /*---------------------------------------------------------------------* * IVAS_DEC_GetDelay( ) @@ -5778,6 +6056,22 @@ ivas_error IVAS_RTP_FeedPiDataToDecoder( IVAS_DEC_HANDLE hIvasDec, PIDATA_TS *pi } break; +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT + case IVAS_PI_ACOUSTIC_ENVIRONMENT: + { + uint16_t aeid = piData->data.acousticEnv.aeid; +#ifdef DEBUGGING + fprintf( stdout, "PI_ACOUSTIC_ENVIRONMENT : AEID : %d\n", aeid ); +#endif + + if ( piData->data.acousticEnv.availLateReverb && hIvasDec->st_ivas->hRenderConfig != NULL && aeid != hIvasDec->st_ivas->hRenderConfig->roomAcoustics.aeID ) + { + error = IVAS_DEC_FeedAcousticEnvPI( hIvasDec, piData->data.acousticEnv ); + } + } + break; +#endif + #ifdef RTP_S4_251135_CR26253_0016_REV1 case IVAS_PI_DIEGETIC_TYPE: { diff --git a/lib_dec/lib_dec.h b/lib_dec/lib_dec.h index d0d2b501d847425d71c701665cda87ba15f71d36..5fefb03f667e980ef8702d2b45b24822e77b6374 100644 --- a/lib_dec/lib_dec.h +++ b/lib_dec/lib_dec.h @@ -475,6 +475,19 @@ ivas_error IVAS_DEC_HRTF_binary_close( const IVAS_BIN_RENDERER_TYPE binaural_renderer_old /* i : previous binaural renderer type */ ); +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT +ivas_error IVAS_DEC_AddAcousticEnvironment( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + const IVAS_ROOM_ACOUSTICS_CONFIG_DATA roomAcousticsConfig /* i : Room acoustic configuration */ +); + +ivas_error IVAS_DEC_GetAcousticEnvironment( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + uint16_t aeID, /* i : Acoustic environment ID */ + IVAS_ROOM_ACOUSTICS_CONFIG_DATA *pAcEnv /* o : Room acoustic environment data pointer */ +); +#endif + /*! r: error code*/ ivas_error IVAS_DEC_GetRenderConfig( IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ diff --git a/lib_rend/ivas_render_config.c b/lib_rend/ivas_render_config.c index c3a39b426e39a0c1f372a5e0f88464c1c7e4c18b..63eaaf0227125765dd8f5889306083edd0050bb7 100644 --- a/lib_rend/ivas_render_config.c +++ b/lib_rend/ivas_render_config.c @@ -112,6 +112,9 @@ ivas_error ivas_render_config_init_from_rom( #ifdef DEBUGGING ( *hRenderConfig )->renderer_type_override = IVAS_RENDER_TYPE_OVERRIDE_NONE; +#endif +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT + ( *hRenderConfig )->roomAcoustics.aeID = (uint16_t) IVAS_DEFAULT_AEID; #endif ( *hRenderConfig )->roomAcoustics.nBands = IVAS_REVERB_DEFAULT_N_BANDS; ( *hRenderConfig )->roomAcoustics.acousticPreDelay = IVAS_REVERB_DEFAULT_PRE_DELAY; diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index b0435968b3db7ed6dde714ca9d98e8b7e5c42d69..b18b949607284f58276ff215f5fe87210a80c130 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -4541,6 +4541,9 @@ ivas_error IVAS_REND_GetRenderConfig( hRCout->renderer_type_override = IVAS_RENDER_TYPE_OVERRIDE_NONE; break; } +#endif +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT + hRCout->roomAcoustics.aeID = hRCin->roomAcoustics.aeID; #endif hRCout->roomAcoustics.nBands = hRCin->roomAcoustics.nBands; hRCout->roomAcoustics.acousticPreDelay = hRCin->roomAcoustics.acousticPreDelay; @@ -4597,6 +4600,9 @@ ivas_error IVAS_REND_FeedRenderConfig( hRenderConfig = hIvasRend->hRendererConfig; #ifdef DEBUGGING hRenderConfig->renderer_type_override = renderConfig.renderer_type_override; +#endif +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT + hRenderConfig->roomAcoustics.aeID = renderConfig.roomAcoustics.aeID; #endif hRenderConfig->roomAcoustics.nBands = renderConfig.roomAcoustics.nBands; hRenderConfig->roomAcoustics.acousticPreDelay = renderConfig.roomAcoustics.acousticPreDelay; diff --git a/lib_util/ivas_rtp_file.c b/lib_util/ivas_rtp_file.c index f7d6d5d86717a7caf5f416ae15513390a8a978de..2838cd641a42321fbe31dafad427dd998a24e694 100644 --- a/lib_util/ivas_rtp_file.c +++ b/lib_util/ivas_rtp_file.c @@ -158,7 +158,15 @@ void IVAS_RTP_LogPiData( return; } +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT +#ifdef _WIN32 + if ( ftell( f_piDataOut ) > 3 ) +#else if ( ftell( f_piDataOut ) > 2 ) +#endif +#else + if ( ftell( f_piDataOut ) > 2 ) +#endif { fprintf( f_piDataOut, ",\n" ); } diff --git a/lib_util/ivas_rtp_pi_data.h b/lib_util/ivas_rtp_pi_data.h index dc4c7f8bafd5eda274df74b419677fd28ec1c64a..a6292369e16f8c2106f18f1e51c81636f79f102d 100644 --- a/lib_util/ivas_rtp_pi_data.h +++ b/lib_util/ivas_rtp_pi_data.h @@ -124,6 +124,15 @@ typedef enum IVAS_PI_AE_NUM_BANDS /* number of ae bands */ } IVAS_PI_AE_BANDS; +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT +typedef enum +{ + IVAS_PI_AE_LOW_FREQ = 25, + IVAS_PI_AE_MID_FREQ = 250, + IVAS_PI_AE_HIGH_FREQ = 2500 +} IVAS_PI_AE_BANDS_FREQ; +#endif + typedef enum { IVAS_PI_AE_FRONT, diff --git a/lib_util/render_config_reader.c b/lib_util/render_config_reader.c index 7729efbc7cb0ffe9ca4174f7aa12ea7012c5a67c..761b203cb09e1b2fb3a1be65906a86a7c85bc100 100644 --- a/lib_util/render_config_reader.c +++ b/lib_util/render_config_reader.c @@ -36,7 +36,9 @@ #include #include #include "cmdl_tools.h" - +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT +#include "ivas_cnst.h" +#endif /*------------------------------------------------------------------------------------------* * PreProc Local Macros @@ -2957,8 +2959,90 @@ ivas_error RenderConfigReader_read( return IVAS_ERR_OK; } +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT +/*------------------------------------------------------------------------------------------* + * RenderConfigReader_getAcousticEnvironmentCount() + * + * Gets number of acoustic environments available + *------------------------------------------------------------------------------------------*/ +uint32_t RenderConfigReader_getAcousticEnvironmentCount( + RenderConfigReader *pRenderConfigReader /* i : RenderConfigReader handle */ +) +{ + return pRenderConfigReader->nAE; +} + +/*------------------------------------------------------------------------------------------* + * RenderConfigReader_getAcousticEnvironments() + * + * Gets all acoustic environments + *------------------------------------------------------------------------------------------*/ +ivas_error RenderConfigReader_getAcousticEnvironments( + RenderConfigReader *pRenderConfigReader, /* i : RenderConfigReader handle */ + IVAS_ROOM_ACOUSTICS_CONFIG_DATA **ppAcEnv /* o : Acoustic environment array pointer */ +) +{ + uint16_t n, m, j; + + if ( pRenderConfigReader == NULL || ppAcEnv == NULL || pRenderConfigReader->nAE == 0 || pRenderConfigReader->pAE == NULL ) + { + return 0; + } + + for ( n = 0; n < pRenderConfigReader->nAE; n++ ) + { + AcousticEnv pIn = pRenderConfigReader->pAE[n]; + IVAS_ROOM_ACOUSTICS_CONFIG_DATA *pOut = ppAcEnv[n]; + + pOut->aeID = (uint16_t) pIn.id; + pOut->nBands = (uint16_t) pIn.pFG->nrBands; + pOut->inputPreDelay = pIn.preDelay; + + for ( m = 0; m < pOut->nBands; m++ ) + { + pOut->pFc_input[m] = pIn.pFG->pFc[m]; + pOut->pAcoustic_rt60[m] = pIn.pRT60[m]; + pOut->pAcoustic_dsr[m] = pIn.pDSR[m]; + } + + /* If ER are allocated then propagate parameters */ + if ( pIn.pEarlyReflections != 0 ) + { + pOut->use_er = pIn.pEarlyReflections->use_er; /* ER activation flag */ + pOut->lowComplexity = pIn.pEarlyReflections->lowComplexity; /* Low complexity flag */ + pOut->dimensions = pIn.pEarlyReflections->dimensions; + + /* Use default listener origin position if non provided */ + if ( pIn.pEarlyReflections->pListenerOrigin != NULL ) + { + pOut->ListenerOrigin.x = pIn.pEarlyReflections->pListenerOrigin->x; + pOut->ListenerOrigin.y = pIn.pEarlyReflections->pListenerOrigin->y; + pOut->ListenerOrigin.z = pIn.pEarlyReflections->pListenerOrigin->z; + } + else + { + pOut->ListenerOrigin.x = IVAS_ER_LIST_ORIGIN_X; + pOut->ListenerOrigin.y = IVAS_ER_LIST_ORIGIN_Y; + pOut->ListenerOrigin.z = IVAS_ER_LIST_HEIGHT; + } + + for ( j = 0; j < IVAS_ROOM_ABS_COEFF; j++ ) + { + pOut->AbsCoeff[j] = pIn.pEarlyReflections->pAbsCoeff[j]; + } + } + else + { + pOut->use_er = false; + } + } + + return IVAS_ERR_OK; +} +#endif + /*------------------------------------------------------------------------------------------* - * RenderConfigReader_getEnvironment() + * RenderConfigReader_getAcousticEnvironment() * * Gets Acoustic environment with a given ID *------------------------------------------------------------------------------------------*/ @@ -2978,7 +3062,11 @@ ivas_error RenderConfigReader_getAcousticEnvironment( } /* case when -aeid is not specified, select first ID from config file */ +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT + if ( id == IVAS_DEFAULT_AEID && pRenderConfigReader->nAE > 0 ) +#else if ( id == 65535 && pRenderConfigReader->nAE > 0 ) +#endif { id = (uint16_t) pRenderConfigReader->pAE[0].id; } diff --git a/lib_util/render_config_reader.h b/lib_util/render_config_reader.h index 8edaecc2f4b6b1c6290010e0f8b2a23fb63ab141..d69249734fa01d8af45162f633ccb786caec8962 100644 --- a/lib_util/render_config_reader.h +++ b/lib_util/render_config_reader.h @@ -51,12 +51,26 @@ ivas_error RenderConfigReader_open( RenderConfigReader **ppRenderConfigReader /* o : RenderConfigReader handle */ ); +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT +/* Get number of acoustic environments */ +uint32_t RenderConfigReader_getAcousticEnvironmentCount( + RenderConfigReader *pRenderConfigReader /* i : RenderConfigReader handle */ +); + +/* Get all acoustic environments */ +ivas_error RenderConfigReader_getAcousticEnvironments( + RenderConfigReader *pRenderConfigReader, /* i : RenderConfigReader handle */ + IVAS_ROOM_ACOUSTICS_CONFIG_DATA **ppAcEnv /* o : Acoustic environment array pointer */ +); +#endif + /* Get an acoustic environment */ ivas_error RenderConfigReader_getAcousticEnvironment( RenderConfigReader *pRenderConfigReader, /* i : RenderConfigReader handle */ uint16_t id, /* i : Acoustic environment ID */ IVAS_ROOM_ACOUSTICS_CONFIG_DATA *pAcEnv /* o : Target acoustic environment pointer */ ); + ivas_error RenderConfigReader_getDirectivity( RenderConfigReader *pRenderConfigReader, /* i : RenderConfigReader handle */ uint16_t *pId, /* i : Directivity pattern ID */ diff --git a/tests/rtp/test_rtp.py b/tests/rtp/test_rtp.py index 44d08a91e16033ddae42c6859ce5858052535df1..2a37f01103e7cc8c82cced8001460c8f5d65344d 100644 --- a/tests/rtp/test_rtp.py +++ b/tests/rtp/test_rtp.py @@ -61,6 +61,7 @@ from tempfile import TemporaryDirectory from pathlib import Path from ivasrtp import * import numpy as np +import json from pyaudio3dtools.audiofile import readfile ROOT_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "../..")) @@ -228,6 +229,38 @@ def generatePiData(startTs: int, endTs: int) -> dict: someAuFocusLvl = lambda: AUDIO_FOCUS(level=AUDIO_FOCUS_LEVEL(random.randint(0, 15))) someAuFocusList = [someAuFocusDirLvl, someAuFocusDir, someAuFocusLvl] + someAcousticEnvAEID = lambda: ACOUSTIC_ENVIRONMENT( + aeid=random.randint(0, 127) + ) + someAcousticEnvLR = lambda: ACOUSTIC_ENVIRONMENT( + aeid=random.randint(0, 127), + rt60=(float(rt60Value[random.randint(0, len(rt60Value) - 1)]), + float(rt60Value[random.randint(0, len(rt60Value) - 1)]), + float(rt60Value[random.randint(0, len(rt60Value) - 1)])), + dsr=(float(dsrValue[random.randint(0, len(dsrValue) - 1)]), + float(dsrValue[random.randint(0, len(dsrValue) - 1)]), + float(dsrValue[random.randint(0, len(dsrValue) - 1)])), + ) + someAcousticEnvERLR = lambda: ACOUSTIC_ENVIRONMENT( + aeid=random.randint(0, 127), + rt60=(float(rt60Value[random.randint(0, len(rt60Value) - 1)]), + float(rt60Value[random.randint(0, len(rt60Value) - 1)]), + float(rt60Value[random.randint(0, len(rt60Value) - 1)])), + dsr=(float(dsrValue[random.randint(0, len(dsrValue) - 1)]), + float(dsrValue[random.randint(0, len(dsrValue) - 1)]), + float(dsrValue[random.randint(0, len(dsrValue) - 1)])), + dim=(float(roomDimensionValue[random.randint(0, len(roomDimensionValue) - 1)]), + float(roomDimensionValue[random.randint(0, len(roomDimensionValue) - 1)]), + float(roomDimensionValue[random.randint(0, len(roomDimensionValue) - 1)])), + abscoeff=(float(absorptionCoeffValues[random.randint(0, len(absorptionCoeffValues) - 1)]), + float(absorptionCoeffValues[random.randint(0, len(absorptionCoeffValues) - 1)]), + float(absorptionCoeffValues[random.randint(0, len(absorptionCoeffValues) - 1)]), + float(absorptionCoeffValues[random.randint(0, len(absorptionCoeffValues) - 1)]), + float(absorptionCoeffValues[random.randint(0, len(absorptionCoeffValues) - 1)]), + float(absorptionCoeffValues[random.randint(0, len(absorptionCoeffValues) - 1)])), + ) + someAcousticEnvList = [someAcousticEnvAEID, someAcousticEnvLR, someAcousticEnvERLR] + for ts in range(startTs, endTs, 320): pidata = dict() pidata["SCENE_ORIENTATION"] = someOrientation() @@ -240,9 +273,7 @@ def generatePiData(startTs: int, endTs: int) -> dict: pidata["DYNAMIC_AUDIO_SUPPRESSION_REQUEST"] = someDAS() pidata["AUDIO_DESCRIPTION"] = [someDesc() for n in range(random.randint(1, 5))] pidata["DIEGETIC_TYPE"] = someDIG() - pidata["ACOUSTIC_ENVIRONMENT"] = ACOUSTIC_ENVIRONMENT( - aeid=random.randint(0, 127) - ) + pidata["ACOUSTIC_ENVIRONMENT"] = random.choice(someAcousticEnvList)() data[str(ts)] = pidata return data @@ -311,7 +342,13 @@ def isEqualAcousticEnv(ref: ACOUSTIC_ENVIRONMENT, dut: ACOUSTIC_ENVIRONMENT): dut.abscoeff ), "Acoustic Env PI Data mismatch in len(abscoeff)" for r, d in zip(ref.rt60, dut.rt60): - assert r == d, f"Acoustic Env PI Data mismatch in rt60 {r} != {d}" + assert abs(r - d) < 0.0001, f"Acoustic Env PI Data mismatch in RT60 {r} != {d}" + for r, d in zip(ref.dsr, dut.dsr): + assert abs(r - d) < 0.0001, f"Acoustic Env PI Data mismatch in DSR {r} != {d}" + for r, d in zip(ref.dim, dut.dim): + assert abs(r - d) < 0.0001, f"Acoustic Env PI Data mismatch in room dimension {r} != {d}" + for r, d in zip(ref.abscoeff, dut.abscoeff): + assert abs(r - d) < 0.0001, f"Acoustic Env PI Data mismatch in absorption coefficient {r} != {d}" def isEqualAudioFocus(ref: AUDIO_FOCUS, dut: AUDIO_FOCUS):