diff --git a/apps/decoder.c b/apps/decoder.c index 31c61c5d04d00d3c6f4328fe770388ad8588ff46..9480d37389c1163b183172277281765279283940 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -92,10 +92,6 @@ static #define IVAS_PUBLIC_ORIENT_TRK_REF_VEC ( 3 ) #define IVAS_PUBLIC_ORIENT_TRK_REF_VEC_LEV ( 4 ) -#ifdef CONTROL_METADATA_REVERB -#define ACOUSTIC_ENVIRONMENT_ID ( 0 ) -#endif - #ifdef VARIABLE_SPEED_DECODING #define VARIABLE_SPEED_FETCH_FRAMESIZE_MS 20 #endif @@ -161,6 +157,10 @@ typedef struct #endif #endif +#ifdef CONTROL_METADATA_REVERB + uint16_t acousticEnvironmentId; +#endif + } DecArguments; @@ -617,22 +617,24 @@ int main( } #ifdef CONTROL_METADATA_REVERB - if ( ( error = RenderConfigReader_getAcousticEnvironment( renderConfigReader, ACOUSTIC_ENVIRONMENT_ID, &renderConfig.room_acoustics ) ) == IVAS_ERR_OK ) + if ( arg.outputFormat == IVAS_DEC_OUTPUT_BINAURAL_ROOM_REVERB ) { - if ( RenderConfigReader_checkValues( &renderConfig ) != IVAS_ERR_OK ) + if ( ( error = RenderConfigReader_getAcousticEnvironment( renderConfigReader, arg.acousticEnvironmentId, &renderConfig.room_acoustics ) ) == IVAS_ERR_OK ) { - fprintf( stderr, "Invalid reverberation configuration parameters\n\n" ); + if ( RenderConfigReader_checkValues( &renderConfig ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Invalid reverberation configuration parameters\n\n" ); + goto cleanup; + } + } + else if ( error != IVAS_ERR_ACOUSTIC_ENVIRONMENT_MISSING ) + { + fprintf( stderr, "Failed to get acoustic environment with ID: %d\n\n", arg.acousticEnvironmentId ); goto cleanup; } - } - else if ( error != IVAS_ERR_ACOUSTIC_ENVIRONMENT_MISSING ) - { - fprintf( stderr, "Failed to get acoustic environment with ID: %d\n\n", ACOUSTIC_ENVIRONMENT_ID ); - goto cleanup; + renderConfig.room_acoustics.override = true; } #endif - renderConfig.room_acoustics.override = true; - if ( ( error = IVAS_DEC_FeedRenderConfig( hIvasDec, renderConfig ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nIVAS_DEC_FeedRenderConfig failed: %s\n\n", IVAS_DEC_GetErrorMessage( error ) ); @@ -988,6 +990,10 @@ static bool parseCmdlIVAS_dec( #endif #endif +#ifdef CONTROL_METADATA_REVERB + arg->acousticEnvironmentId = 0; +#endif + /*-----------------------------------------------------------------* * Initialization *-----------------------------------------------------------------*/ @@ -1348,7 +1354,13 @@ static bool parseCmdlIVAS_dec( fprintf( stdout, "Complexity levels 1 and 2 will be defined after characterisation - default to level 3 (full functionality).\n" ); } } - +#ifdef CONTROL_METADATA_REVERB + else if ( strcmp( argv_to_upper, "-AEID" ) == 0 ) + { + ++i; + arg->acousticEnvironmentId = (int16_t) atoi( argv[i++] ); + } +#endif /*-----------------------------------------------------------------* * Option not recognized *-----------------------------------------------------------------*/ @@ -1533,6 +1545,9 @@ static void usage_dec( void ) fprintf( stdout, " Currently, all values default to level 3 (full functionality).\n" ); #endif fprintf( stdout, "-exof File : External orientation file for external orientation trajectory\n" ); +#ifdef CONTROL_METADATA_REVERB + fprintf( stdout, "-aeid ID : Acoustic environment ID (number >= 0) for BINAURAL_ROOM_REVERB output configuration\n" ); +#endif #ifdef DEBUG_MODE_INFO #ifdef DEBUG_MODE_INFO_TWEAK fprintf( stdout, "-info : specify subfolder name for debug output\n" ); diff --git a/apps/renderer.c b/apps/renderer.c index b3664f8595998b8b3a3fc2897d9fbaba8e5c2193..348a012360810ca4b11a9b9e8ceb263442f60be9 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -65,9 +65,6 @@ #define RENDERER_MAX_METADATA_LENGTH 8192 #define RENDERER_MAX_METADATA_LINE_LENGTH 1024 -#ifdef CONTROL_METADATA_REVERB -#define ACOUSTIC_ENVIRONMENT_ID 0 -#endif #ifdef SPLIT_REND_WITH_HEAD_ROT #define SPLIT_REND_BITS_BUFF_SIZE ( ( ( ( (int32_t) SPLIT_REND_MAX_BRATE / FRAMES_PER_SEC ) + 7 ) >> 3 ) + SPLIT_REND_ADDITIONAL_BYTES_TO_READ ) #endif @@ -178,6 +175,9 @@ typedef struct float lfeConfigElevation; bool lfeCustomRoutingEnabled; char inLfePanningMatrixFile[RENDERER_MAX_CLI_ARG_LENGTH]; +#ifdef CONTROL_METADATA_REVERB + uint16_t acousticEnvironmentId; +#endif #ifdef FIX_488_SYNC_DELAY float syncMdDelay; #endif @@ -209,6 +209,9 @@ typedef enum #endif CmdLnOptionId_referenceVectorFile, CmdLnOptionId_exteriorOrientationFile, +#ifdef CONTROL_METADATA_REVERB + CmdLnOptionId_acousticEnvironmentId, +#endif #ifdef FIX_488_SYNC_DELAY CmdLnOptionId_syncMdDelay, #endif @@ -351,6 +354,14 @@ static const CmdLnParser_Option cliOptions[] = { .matchShort = "exof", .description = "External orientation trajectory file for simulation of external orientations", }, +#ifdef CONTROL_METADATA_REVERB + { + .id = CmdLnOptionId_acousticEnvironmentId, + .match = "acoustic_environment_id", + .matchShort = "aeid", + .description = "Acoustic environment ID (number >= 0) for BINAURAL_ROOM_REVERB output configuration", + }, +#endif #ifdef FIX_488_SYNC_DELAY { .id = CmdLnOptionId_syncMdDelay, @@ -1084,6 +1095,21 @@ int main( if ( args.outConfig.audioConfig == IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) { +#ifdef CONTROL_METADATA_REVERB + if ( ( error = RenderConfigReader_getAcousticEnvironment( renderConfigReader, args.acousticEnvironmentId, &renderConfig.room_acoustics ) ) == IVAS_ERR_OK ) + { + if ( RenderConfigReader_checkValues( &renderConfig ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Invalid room acoustics configuration parameters\n\n" ); + exit( -1 ); + } + } + else + { + fprintf( stderr, "Failed to get acoustic environment with ID: %d\n\n", args.acousticEnvironmentId ); + exit( -1 ); + } +#endif renderConfig.room_acoustics.override = TRUE; } @@ -2516,7 +2542,9 @@ static CmdlnArgs defaultArgs( args.lfeCustomRoutingEnabled = false; clearString( args.inLfePanningMatrixFile ); - +#ifdef CONTROL_METADATA_REVERB + args.acousticEnvironmentId = 0; +#endif #ifdef FIX_488_SYNC_DELAY args.syncMdDelay = 0; #endif @@ -2659,6 +2687,12 @@ static void parseOption( exit( -1 ); } break; +#ifdef CONTROL_METADATA_REVERB + case CmdLnOptionId_acousticEnvironmentId: + assert( numOptionValues == 1 ); + args->acousticEnvironmentId = (int16_t) strtol( optionValues[0], NULL, 10 ); + break; +#endif #ifdef FIX_488_SYNC_DELAY case CmdLnOptionId_syncMdDelay: assert( numOptionValues == 1 ); diff --git a/lib_util/render_config_reader.c b/lib_util/render_config_reader.c index 9918f790e37bd4f7f3404cde3bbd9a27109fc1f8..61b9e3c17e16733b5b7bf5d2b60f549f76d802b9 100644 --- a/lib_util/render_config_reader.c +++ b/lib_util/render_config_reader.c @@ -47,10 +47,10 @@ #define MAX_LINE_LENGTH ( 1024 ) #endif #define MAX_ITEM_LENGTH ( 64 ) -#ifndef CONTROL_METADATA_REVERB -#define N_REVERB_VECTORS ( 3 ) -#else +#ifdef CONTROL_METADATA_REVERB #define N_ABS_COEFFS ( 6 ) +#else +#define N_REVERB_VECTORS ( 3 ) #endif #define SHORTEST_REV_DEL_LINE ( 0.015f ) @@ -80,20 +80,23 @@ typedef struct float *pFc; /* Center frequencies */ } FrequencyGrid; +#ifdef CONTROL_METADATA_REVERB typedef enum _FREQ_GRID_MODE { + FREQ_GRID_MODE_UNKNOWN = -1, FREQ_GRID_MODE_INDIVIDUAL_FREQUENCIES = 0, FREQ_GRID_MODE_START_HOP_AMOUNT = 1, FREQ_GRID_MODE_DEFAULT_BANDING = 2 } FREQ_GRID_MODE; +#endif #ifdef CONTROL_METADATA_EARLY_REFLECTIONS typedef struct { - IVAS_VECTOR3 dimensions; /* Room dimensions [m] */ - FrequencyGrid *pFG; /* Pointer to a frequency grid for absorption coeffs */ - float ( *pAbsCoeff )[N_ABS_COEFFS]; /* Absorption coeffs table pointer */ - IVAS_VECTOR3 *pListenerOrigin; /* Listener origin */ + IVAS_VECTOR3 dimensions; /* Room dimensions [m] */ + float pAbsCoeff[N_ABS_COEFFS]; /* Absorption coeffs table */ + IVAS_VECTOR3 *pListenerOrigin; /* Listener origin */ + uint32_t lowComplexity; /* Low complexity mode flag */ } EarlyReflectionsConfig; #endif @@ -410,10 +413,10 @@ const float defaultFrequencyGrid_8[] = { }; /*-----------------------------------------------------------------------------------------* - * Function read_bits() + * Function read_bin_bits() * Reads a given number of bits from the bitstream *-----------------------------------------------------------------------------------------*/ -static ivas_error read_bits( +static ivas_error read_bin_bits( RenderConfigReader *this, /* i/o : Renderer config reader handle */ uint32_t *pTarget, /* o : Target read data pointer */ const size_t nBits /* i : Number of bits to read */ @@ -447,22 +450,22 @@ static ivas_error read_bits( } /*-----------------------------------------------------------------------------------------* - * Function read_bool() + * Function read_bin_bool() * Reads a boolean value from a bitstream *-----------------------------------------------------------------------------------------*/ -static ivas_error read_bool( +static ivas_error read_bin_bool( RenderConfigReader *this, /* i/o : Renderer config reader handle */ uint32_t *pResult /* o : Target read data pointer */ ) { - return read_bits( this, pResult, 1 ); + return read_bin_bits( this, pResult, 1 ); } /*-----------------------------------------------------------------------------------------* - * Function get_id() + * Function get_bin_id() * Reads an ID from a bitstream *-----------------------------------------------------------------------------------------*/ -static ivas_error get_id( +static ivas_error get_bin_id( RenderConfigReader *this, /* i/o : Renderer config reader handle */ uint32_t *pResult /* o : Target read data pointer */ ) @@ -482,13 +485,13 @@ static ivas_error get_id( while ( cont ) { - if ( ( error = read_bits( this, &id, 7 ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_bits( this, &id, 7 ) ) != IVAS_ERR_OK ) { return error; } *pResult = ( *pResult << 7 ) | id; - if ( ( error = read_bool( this, &cont ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_bool( this, &cont ) ) != IVAS_ERR_OK ) { return error; } @@ -498,10 +501,10 @@ static ivas_error get_id( } /*-----------------------------------------------------------------------------------------* - * Function read_code_word() + * Function read_bin_code_word() * Reads a code word from a LUT *-----------------------------------------------------------------------------------------*/ -static ivas_error read_code_word( +static ivas_error read_bin_code_word( RenderConfigReader *this, /* i/o : Renderer config reader handle */ const RC_LUT table, /* i : Table enum */ float *pResult /* o : Code value */ @@ -632,7 +635,7 @@ static ivas_error read_code_word( for ( len = minLen; len <= maxLen; len++ ) { nr_bits = ( len == minLen ) ? minLen : 1; - if ( ( error = read_bits( this, &bits, nr_bits ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_bits( this, &bits, nr_bits ) ) != IVAS_ERR_OK ) { return error; } @@ -650,10 +653,10 @@ static ivas_error read_code_word( } /*-----------------------------------------------------------------------------------------* - * Function get_count_or_index() + * Function get_bin_count_or_index() * Gets a count or index *-----------------------------------------------------------------------------------------*/ -static ivas_error get_count_or_index( +static ivas_error get_bin_count_or_index( RenderConfigReader *this, /* i/o : Renderer config reader handle */ uint32_t *pResult /* o : Count or index value */ ) @@ -667,20 +670,20 @@ static ivas_error get_count_or_index( return IVAS_ERR_UNEXPECTED_NULL_POINTER; } - if ( ( error = read_code_word( this, RC_LUT_COUNT_IDX_LO, &value ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_code_word( this, RC_LUT_COUNT_IDX_LO, &value ) ) != IVAS_ERR_OK ) { return error; } *pResult = (uint32_t) value; - if ( ( error = read_bool( this, &isLarge ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_bool( this, &isLarge ) ) != IVAS_ERR_OK ) { return error; } if ( isLarge ) { - if ( ( error = read_code_word( this, RC_LUT_COUNT_IDX_HI, &value ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_code_word( this, RC_LUT_COUNT_IDX_HI, &value ) ) != IVAS_ERR_OK ) { return error; } @@ -691,10 +694,10 @@ static ivas_error get_count_or_index( } /*-----------------------------------------------------------------------------------------* - * Function get_duration() + * Function get_bin_duration() * Gets a duration value *-----------------------------------------------------------------------------------------*/ -static ivas_error get_duration( +static ivas_error get_bin_duration( RenderConfigReader *this, /* i/o : Renderer config reader handle */ float *pResult /* o : Duration value */ ) @@ -704,35 +707,35 @@ static ivas_error get_duration( uint32_t addFlag; /* Deciseconds */ - if ( ( error = read_code_word( this, RC_LUT_DECI_SEC, &value ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_code_word( this, RC_LUT_DECI_SEC, &value ) ) != IVAS_ERR_OK ) { return error; } *pResult = value; /* Milliseconds */ - if ( ( error = read_bool( this, &addFlag ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_bool( this, &addFlag ) ) != IVAS_ERR_OK ) { return error; } if ( addFlag ) { - if ( ( error = read_code_word( this, RC_LUT_MILLI_SEC, &value ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_code_word( this, RC_LUT_MILLI_SEC, &value ) ) != IVAS_ERR_OK ) { return error; } *pResult += value; /* Microseconds */ - if ( ( error = read_bool( this, &addFlag ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_bool( this, &addFlag ) ) != IVAS_ERR_OK ) { return error; } if ( addFlag ) { - if ( ( error = read_code_word( this, RC_LUT_MICRO_SEC, &value ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_code_word( this, RC_LUT_MICRO_SEC, &value ) ) != IVAS_ERR_OK ) { return error; } @@ -741,14 +744,14 @@ static ivas_error get_duration( } /* Seconds */ - if ( ( error = read_bool( this, &addFlag ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_bool( this, &addFlag ) ) != IVAS_ERR_OK ) { return error; } if ( addFlag ) { - if ( ( error = read_code_word( this, RC_LUT_SEC, &value ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_code_word( this, RC_LUT_SEC, &value ) ) != IVAS_ERR_OK ) { return error; } @@ -762,10 +765,10 @@ static ivas_error get_duration( } /*-----------------------------------------------------------------------------------------* - * Function get_frequency() + * Function get_bin_frequency() * Gets a frequency value *-----------------------------------------------------------------------------------------*/ -static ivas_error get_frequency( +static ivas_error get_bin_frequency( RenderConfigReader *this, /* i/o : Renderer config reader handle */ float *pResult /* o : Frequency value */ ) @@ -777,19 +780,19 @@ static ivas_error get_frequency( hiRes = 0; refine = 0; - if ( ( error = read_code_word( this, RC_LUT_FREQ, pResult ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_code_word( this, RC_LUT_FREQ, pResult ) ) != IVAS_ERR_OK ) { return error; } - if ( ( error = read_bool( this, &hiRes ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_bool( this, &hiRes ) ) != IVAS_ERR_OK ) { return error; } if ( hiRes ) { - if ( ( error = read_bits( this, &refine, 4 ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_bits( this, &refine, 4 ) ) != IVAS_ERR_OK ) { return error; } @@ -800,10 +803,10 @@ static ivas_error get_frequency( } /*-----------------------------------------------------------------------------------------* - * Function get_dsr() + * Function get_bin_dsr() * Gets a DSR value *-----------------------------------------------------------------------------------------*/ -static ivas_error get_dsr( +static ivas_error get_bin_dsr( RenderConfigReader *this, /* i/o : Renderer config reader handle */ float *pResult /* o : DSR value */ ) @@ -811,7 +814,7 @@ static ivas_error get_dsr( ivas_error error; float value; - if ( ( error = read_code_word( this, RC_LUT_DSR, &value ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_code_word( this, RC_LUT_DSR, &value ) ) != IVAS_ERR_OK ) { return error; } @@ -821,11 +824,11 @@ static ivas_error get_dsr( } /*-----------------------------------------------------------------------------------------* - * Function get_distance() + * Function get_bin_distance() * Gets a distance value (in meters) *-----------------------------------------------------------------------------------------*/ -static ivas_error get_distance( +static ivas_error get_bin_distance( RenderConfigReader *this, /* i/o : Render config reader handle */ uint16_t isSmall, /* i : Flag indicating a small distance */ float *pResult /* o : Distance value */ @@ -835,7 +838,7 @@ static ivas_error get_distance( float value; uint32_t flag; - if ( ( error = read_code_word( this, RC_LUT_METERS, pResult ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_code_word( this, RC_LUT_METERS, pResult ) ) != IVAS_ERR_OK ) { return error; } @@ -843,7 +846,7 @@ static ivas_error get_distance( if ( isSmall == false ) { /* addHectometers flag */ - if ( ( error = read_bool( this, &flag ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_bool( this, &flag ) ) != IVAS_ERR_OK ) { return error; } @@ -851,14 +854,14 @@ static ivas_error get_distance( if ( flag == true ) { /* Hectometers */ - if ( ( error = read_code_word( this, RC_LUT_HECTOMETERS, &value ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_code_word( this, RC_LUT_HECTOMETERS, &value ) ) != IVAS_ERR_OK ) { return error; } *pResult += value * 100.0f; /* addKilometers flag */ - if ( ( error = read_bool( this, &flag ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_bool( this, &flag ) ) != IVAS_ERR_OK ) { return error; } @@ -866,14 +869,14 @@ static ivas_error get_distance( while ( flag == true ) { /* Kilometers */ - if ( ( error = read_code_word( this, RC_LUT_KILOMETERS, &value ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_code_word( this, RC_LUT_KILOMETERS, &value ) ) != IVAS_ERR_OK ) { return error; } *pResult += value * 1000.0f; /* addKilometers flag */ - if ( ( error = read_bool( this, &flag ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_bool( this, &flag ) ) != IVAS_ERR_OK ) { return error; } @@ -882,14 +885,14 @@ static ivas_error get_distance( } /* addCentimeters flag */ - if ( ( error = read_bool( this, &flag ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_bool( this, &flag ) ) != IVAS_ERR_OK ) { return error; } if ( flag == true ) { /* Centimeters */ - if ( ( error = read_code_word( this, RC_LUT_CENTIMETERS, &value ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_code_word( this, RC_LUT_CENTIMETERS, &value ) ) != IVAS_ERR_OK ) { return error; } @@ -900,18 +903,18 @@ static ivas_error get_distance( } /*-----------------------------------------------------------------------------------------* - * Function get_absorption() + * Function get_bin_absorption() * Gets an absorption value *-----------------------------------------------------------------------------------------*/ -static ivas_error get_absorption( +static ivas_error get_bin_absorption( RenderConfigReader *this, /* i/o : Render config reader handle */ float *pResult /* o : Absorption value */ ) { ivas_error error; - if ( ( error = read_code_word( this, RC_LUT_ABSORPTION, pResult ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_code_word( this, RC_LUT_ABSORPTION, pResult ) ) != IVAS_ERR_OK ) { return error; } @@ -919,13 +922,41 @@ static ivas_error get_absorption( return IVAS_ERR_OK; } +/*-----------------------------------------------------------------------------------------* + * Function read_txt_bool() + * Reads a boolean value from a line + *-----------------------------------------------------------------------------------------*/ +static ivas_error read_txt_bool( + const char *pLine, /* i : String to read from */ + uint32_t *pTarget /* o : Output pointer */ +) +{ + char value[8]; + + if ( sscanf( pLine, "%8s", (char *) &value ) != 1 ) + { + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + + if ( strcmp( value, "TRUE" ) == 0 ) + { + *pTarget = TRUE; + return IVAS_ERR_OK; + } + if ( strcmp( value, "FALSE" ) == 0 ) + { + *pTarget = FALSE; + return IVAS_ERR_OK; + } + return IVAS_ERR_INVALID_RENDER_CONFIG; +} #ifdef CONTROL_METADATA_DIRECTIVITY /*-----------------------------------------------------------------------------------------* - * Function get_angle() + * Function get_bin_angle() * Gets an angle value in degrees [0,360] *-----------------------------------------------------------------------------------------*/ -static ivas_error get_angle( +static ivas_error get_bin_angle( RenderConfigReader *this, /* i/o : Render config reader handle */ float *pResult /* o : Angle value */ ) @@ -933,7 +964,7 @@ static ivas_error get_angle( ivas_error error; uint32_t value; - if ( ( error = read_bits( this, &value, 5 ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_bits( this, &value, 5 ) ) != IVAS_ERR_OK ) { return error; } @@ -944,11 +975,11 @@ static ivas_error get_angle( } /*-----------------------------------------------------------------------------------------* - * Function get_outer_attenuation () + * Function get_bin_outer_attenuation () * Gets an outer attenuation value [3.1623e-05,1.0], or in dB: [-90,0] *-----------------------------------------------------------------------------------------*/ -static ivas_error get_outer_attenuation( +static ivas_error get_bin_outer_attenuation( RenderConfigReader *this, /* i/o : Render config reader handle */ float *pResult /* o : Attenuation value */ ) @@ -957,7 +988,7 @@ static ivas_error get_outer_attenuation( uint32_t value; float logval, att; - if ( ( error = read_bits( this, &value, 5 ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_bits( this, &value, 5 ) ) != IVAS_ERR_OK ) { return error; } @@ -1006,6 +1037,60 @@ static int16_t read_bool( } #endif +#ifdef CONTROL_METADATA_REVERB +/*-----------------------------------------------------------------------------------------* + * Function read_txt_vector() + * + * Reads a vector value from a line + *-----------------------------------------------------------------------------------------*/ + +static int16_t read_txt_vector( + char *pLine, /* i : String to read from */ + const uint32_t length, /* i : Number of expected vector elements */ + float *pTarget /* o : Output vector pointer */ +) +{ + char *tmp; + uint16_t n; + uint16_t count; + + n = (int16_t) sscanf( pLine, "[%s", pLine ); + if ( n == 0 ) + { + return true; + } + + /* Additional comma to make parsing easier */ + pLine[strlen( pLine ) - 1] = ','; + + tmp = pLine; + /* Count # of commas to determine vector length */ + for ( n = 0; tmp[n]; tmp[n] == ',' ? n++ : *tmp++ ) + ; + + count = n; + + tmp = pLine; + + /* Check for maximum vector length */ + if ( n != length ) + { + return true; + } + + for ( n = 0; n < count; n++ ) + { + if ( (int16_t) sscanf( tmp, "%f,", &pTarget[n] ) != 1 ) + { + return true; + } + + tmp = strchr( tmp, ',' ) + 1; + } + + return false; +} +#else /*-----------------------------------------------------------------------------------------* * Function read_vector() * @@ -1014,7 +1099,7 @@ static int16_t read_bool( static int16_t read_vector( char *pLine, /* i : String to read from */ - const int16_t length, /* i : Number of expected vector elements */ + const int32_t length, /* i : Number of expected vector elements */ float *pTarget /* o : Output vector pointer */ ) { @@ -1058,7 +1143,7 @@ static int16_t read_vector( return false; } - +#endif #ifdef CONTROL_METADATA_REVERB /*-----------------------------------------------------------------------------------------* @@ -1122,11 +1207,11 @@ static int32_t errorHandler( break; case ERROR_ITEM_UNKNOWN: numErrors++; - fprintf( stderr, "Unknown variable %s in renderer configuration file.\n\n", badStr ); + fprintf( stderr, "Unexpected variable %s in renderer configuration file.\n\n", badStr ); break; case ERROR_VALUE_INVALID: numErrors++; - fprintf( stderr, "Invalid value %s in renderer configuration file.\n\n", badStr ); + fprintf( stderr, "Unexpected value %s in renderer configuration file.\n\n", badStr ); break; default: numErrors++; @@ -1261,6 +1346,12 @@ ivas_error RenderConfigReader_open( pSelf = calloc( sizeof( RenderConfigReader ), 1 ); pSelf->pConfigFile = pConfigFile; +#ifdef CONTROL_METADATA_REVERB + pSelf->nFG = 0; + pSelf->pFG = NULL; + pSelf->nAE = 0; + pSelf->pAE = NULL; +#endif *ppRenderConfigReader = pSelf; return IVAS_ERR_OK; @@ -1268,15 +1359,15 @@ ivas_error RenderConfigReader_open( /*------------------------------------------------------------------------------------------* - * RenderConfigReader_readReverb() + * RenderConfigReader_readBinary() * - * Reads the binary reverb configuration from a file + * Reads the binary configuration from a file *------------------------------------------------------------------------------------------*/ #ifdef CONTROL_METADATA_REVERB -static ivas_error RenderConfigReader_readReverb( - const char *pReverbConfigPath, /* i : Reverb configuration file path */ - RenderConfigReader *pRenderConfigReader /* i/o : RenderConfigReader handle */ +static ivas_error RenderConfigReader_readBinary( + const char *pReverbConfigPath, /* i : Configuration file path */ + RenderConfigReader *pRenderConfigReader /* i/o : RenderConfigReader handle */ ) { uint32_t file_size; @@ -1285,6 +1376,7 @@ static ivas_error RenderConfigReader_readReverb( uint32_t signx, signy, k; #endif uint32_t i, m, n; + uint32_t nFG, nAE; ivas_error error; float freqHop; uint32_t gridLen; @@ -1317,7 +1409,7 @@ static ivas_error RenderConfigReader_readReverb( /****************************/ /* Read the presence flag */ /****************************/ - if ( ( error = read_bool( pRenderConfigReader, &value ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_bool( pRenderConfigReader, &value ) ) != IVAS_ERR_OK ) { return error; } @@ -1333,28 +1425,39 @@ static ivas_error RenderConfigReader_readReverb( /****************************/ /* Number of frequency grids */ - if ( ( error = get_count_or_index( pRenderConfigReader, &pRenderConfigReader->nFG ) ) != IVAS_ERR_OK ) + if ( ( error = get_bin_count_or_index( pRenderConfigReader, &nFG ) ) != IVAS_ERR_OK ) { return error; } /* Allocate memory for the frequency grids */ - if ( ( pRenderConfigReader->pFG = (FrequencyGrid *) malloc( pRenderConfigReader->nFG * sizeof( FrequencyGrid ) ) ) == NULL ) + if ( nFG > 0 ) { - return IVAS_ERR_FAILED_ALLOC; - } + for ( n = 0; n < pRenderConfigReader->nFG; n++ ) + { + free( pRenderConfigReader->pFG[n].pFc ); + } + free( pRenderConfigReader->pFG ); - /* Initialize memory pointers to allow safe freeing ico errors */ - for ( n = 0; n < pRenderConfigReader->nFG; n++ ) - { - pRenderConfigReader->pFG[n].pFc = 0; + pRenderConfigReader->nFG = nFG; + + if ( ( pRenderConfigReader->pFG = (FrequencyGrid *) malloc( pRenderConfigReader->nFG * sizeof( FrequencyGrid ) ) ) == NULL ) + { + return IVAS_ERR_FAILED_ALLOC; + } + for ( n = 0; n < nFG; n++ ) + { + /* Initialize memory pointers to allow safe freeing ico errors */ + pRenderConfigReader->pFG[n].pFc = NULL; + } } - for ( n = 0; n < pRenderConfigReader->nFG; n++ ) + /* Loop through the frequency grids read from the binary stream */ + for ( n = 0; n < nFG; n++ ) { /* Read the representation method */ value = 0; - if ( ( error = read_bits( pRenderConfigReader, &value, 2 ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_bits( pRenderConfigReader, &value, 2 ) ) != IVAS_ERR_OK ) { return error; } @@ -1363,7 +1466,7 @@ static ivas_error RenderConfigReader_readReverb( switch ( value ) { case FREQ_GRID_MODE_INDIVIDUAL_FREQUENCIES: - if ( ( error = get_count_or_index( pRenderConfigReader, &pRenderConfigReader->pFG[n].nrBands ) ) != IVAS_ERR_OK ) + if ( ( error = get_bin_count_or_index( pRenderConfigReader, &pRenderConfigReader->pFG[n].nrBands ) ) != IVAS_ERR_OK ) { return error; } @@ -1375,14 +1478,14 @@ static ivas_error RenderConfigReader_readReverb( /* Read the individual frequencies */ for ( m = 0; m < pRenderConfigReader->pFG[n].nrBands; m++ ) { - if ( ( error = get_frequency( pRenderConfigReader, &pRenderConfigReader->pFG[n].pFc[m] ) ) != IVAS_ERR_OK ) + if ( ( error = get_bin_frequency( pRenderConfigReader, &pRenderConfigReader->pFG[n].pFc[m] ) ) != IVAS_ERR_OK ) { return error; } } break; case FREQ_GRID_MODE_START_HOP_AMOUNT: - if ( ( error = get_count_or_index( pRenderConfigReader, &pRenderConfigReader->pFG[n].nrBands ) ) != IVAS_ERR_OK ) + if ( ( error = get_bin_count_or_index( pRenderConfigReader, &pRenderConfigReader->pFG[n].nrBands ) ) != IVAS_ERR_OK ) { return error; } @@ -1392,12 +1495,12 @@ static ivas_error RenderConfigReader_readReverb( return IVAS_ERR_FAILED_ALLOC; } /* Read the first frequency */ - if ( ( error = get_frequency( pRenderConfigReader, &pRenderConfigReader->pFG[n].pFc[0] ) ) != IVAS_ERR_OK ) + if ( ( error = get_bin_frequency( pRenderConfigReader, &pRenderConfigReader->pFG[n].pFc[0] ) ) != IVAS_ERR_OK ) { return error; } /* Read frequency hop from LUT */ - if ( ( error = read_code_word( pRenderConfigReader, RC_LUT_FREQ_HOP, &freqHop ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_code_word( pRenderConfigReader, RC_LUT_FREQ_HOP, &freqHop ) ) != IVAS_ERR_OK ) { return error; } @@ -1410,7 +1513,7 @@ static ivas_error RenderConfigReader_readReverb( case FREQ_GRID_MODE_DEFAULT_BANDING: /* Read the default grid ID */ value = 0; - if ( ( error = read_bits( pRenderConfigReader, &value, 4 ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_bits( pRenderConfigReader, &value, 4 ) ) != IVAS_ERR_OK ) { return error; } @@ -1458,21 +1561,21 @@ static ivas_error RenderConfigReader_readReverb( m = 0; /* Read sub-grid flag */ - if ( ( error = read_bool( pRenderConfigReader, &value ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_bool( pRenderConfigReader, &value ) ) != IVAS_ERR_OK ) { return error; } if ( value != false ) { /* Read the sub-grid offset */ - if ( ( error = read_bits( pRenderConfigReader, &m, 3 ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_bits( pRenderConfigReader, &m, 3 ) ) != IVAS_ERR_OK ) { return error; } /* Read the sub-grid length */ subGridLen = 0; - if ( ( error = read_bits( pRenderConfigReader, &subGridLen, 6 ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_bits( pRenderConfigReader, &subGridLen, 6 ) ) != IVAS_ERR_OK ) { return error; } @@ -1506,37 +1609,56 @@ static ivas_error RenderConfigReader_readReverb( /**********************************/ /* Number of acoustic environments */ - if ( ( error = get_count_or_index( pRenderConfigReader, &pRenderConfigReader->nAE ) ) != IVAS_ERR_OK ) + if ( ( error = get_bin_count_or_index( pRenderConfigReader, &nAE ) ) != IVAS_ERR_OK ) { return IVAS_ERR_INVALID_RENDER_CONFIG; } /* Allocate memory for the acoustic environments array */ - if ( ( pRenderConfigReader->pAE = (AcousticEnv *) malloc( pRenderConfigReader->nAE * sizeof( AcousticEnv ) ) ) == NULL ) + if ( nAE > 0 ) { - return IVAS_ERR_FAILED_ALLOC; - } + for ( n = 0; n < pRenderConfigReader->nAE; n++ ) + { + free( pRenderConfigReader->pAE[n].pRT60 ); + free( pRenderConfigReader->pAE[n].pDSR ); +#ifdef CONTROL_METADATA_EARLY_REFLECTIONS + if ( pRenderConfigReader->pAE[n].pEarlyReflections != NULL ) + { + free( pRenderConfigReader->pAE[n].pEarlyReflections->pListenerOrigin ); + free( pRenderConfigReader->pAE[n].pEarlyReflections ); + } +#endif + } + free( pRenderConfigReader->pAE ); - /* Initialize memory pointers to allow safe freeing ico errors */ - for ( n = 0; n < pRenderConfigReader->nAE; n++ ) - { - pRenderConfigReader->pAE[n].pRT60 = 0; - pRenderConfigReader->pAE[n].pDSR = 0; + pRenderConfigReader->nAE = nAE; + + if ( ( pRenderConfigReader->pAE = (AcousticEnv *) malloc( pRenderConfigReader->nAE * sizeof( AcousticEnv ) ) ) == NULL ) + { + return IVAS_ERR_FAILED_ALLOC; + } + /* Initialize memory pointers to allow safe freeing ico errors */ + for ( n = 0; n < nAE; n++ ) + { + pRenderConfigReader->pAE[n].pRT60 = NULL; + pRenderConfigReader->pAE[n].pDSR = NULL; #ifdef CONTROL_METADATA_EARLY_REFLECTIONS - pRenderConfigReader->pAE[n].pEarlyReflections = 0; + pRenderConfigReader->pAE[n].pEarlyReflections = NULL; #endif + } } - for ( n = 0; n < pRenderConfigReader->nAE; n++ ) + /* Loop through the acoustic environments from the binary stream */ + for ( n = 0; n < nAE; n++ ) { /* Read the AE ID */ - if ( ( error = get_id( pRenderConfigReader, &pRenderConfigReader->pAE[n].id ) ) != IVAS_ERR_OK ) + if ( ( error = get_bin_id( pRenderConfigReader, &pRenderConfigReader->pAE[n].id ) ) != IVAS_ERR_OK ) { return error; } /* Read the frequency grid ID */ - if ( ( error = get_count_or_index( pRenderConfigReader, &value ) ) != IVAS_ERR_OK ) + if ( ( error = get_bin_count_or_index( pRenderConfigReader, &value ) ) != IVAS_ERR_OK ) { return error; } @@ -1561,21 +1683,21 @@ static ivas_error RenderConfigReader_readReverb( } /* Read the values */ - if ( ( error = get_duration( pRenderConfigReader, &pRenderConfigReader->pAE[n].preDelay ) ) != IVAS_ERR_OK ) + if ( ( error = get_bin_duration( pRenderConfigReader, &pRenderConfigReader->pAE[n].preDelay ) ) != IVAS_ERR_OK ) { return error; } for ( m = 0; m < pRenderConfigReader->pAE[n].pFG->nrBands; m++ ) { - if ( ( error = get_duration( pRenderConfigReader, &pRenderConfigReader->pAE[n].pRT60[m] ) ) != IVAS_ERR_OK ) + if ( ( error = get_bin_duration( pRenderConfigReader, &pRenderConfigReader->pAE[n].pRT60[m] ) ) != IVAS_ERR_OK ) { return IVAS_ERR_INVALID_RENDER_CONFIG; } } for ( m = 0; m < pRenderConfigReader->pAE[n].pFG->nrBands; m++ ) { - if ( ( error = get_dsr( pRenderConfigReader, &pRenderConfigReader->pAE[n].pDSR[m] ) ) != IVAS_ERR_OK ) + if ( ( error = get_bin_dsr( pRenderConfigReader, &pRenderConfigReader->pAE[n].pDSR[m] ) ) != IVAS_ERR_OK ) { return IVAS_ERR_INVALID_RENDER_CONFIG; } @@ -1583,7 +1705,7 @@ static ivas_error RenderConfigReader_readReverb( #ifdef CONTROL_METADATA_EARLY_REFLECTIONS /* Has early reflections */ - if ( ( error = read_bool( pRenderConfigReader, &value ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_bool( pRenderConfigReader, &value ) ) != IVAS_ERR_OK ) { return error; } @@ -1594,49 +1716,32 @@ static ivas_error RenderConfigReader_readReverb( return IVAS_ERR_FAILED_ALLOC; } /* Initialize memory pointers to allow safe freeing ico eg errors */ - pRenderConfigReader->pAE[n].pEarlyReflections->pAbsCoeff = 0; - pRenderConfigReader->pAE[n].pEarlyReflections->pListenerOrigin = 0; + pRenderConfigReader->pAE[n].pEarlyReflections->pListenerOrigin = NULL; /* Room sizes */ - if ( ( error = get_distance( pRenderConfigReader, true, &pRenderConfigReader->pAE[n].pEarlyReflections->dimensions.x ) ) != IVAS_ERR_OK ) + if ( ( error = get_bin_distance( pRenderConfigReader, true, &pRenderConfigReader->pAE[n].pEarlyReflections->dimensions.x ) ) != IVAS_ERR_OK ) { return error; } - if ( ( error = get_distance( pRenderConfigReader, true, &pRenderConfigReader->pAE[n].pEarlyReflections->dimensions.y ) ) != IVAS_ERR_OK ) + if ( ( error = get_bin_distance( pRenderConfigReader, true, &pRenderConfigReader->pAE[n].pEarlyReflections->dimensions.y ) ) != IVAS_ERR_OK ) { return error; } - if ( ( error = get_distance( pRenderConfigReader, true, &pRenderConfigReader->pAE[n].pEarlyReflections->dimensions.z ) ) != IVAS_ERR_OK ) + if ( ( error = get_bin_distance( pRenderConfigReader, true, &pRenderConfigReader->pAE[n].pEarlyReflections->dimensions.z ) ) != IVAS_ERR_OK ) { return error; } - /* Frequency grid ID */ - if ( ( error = get_count_or_index( pRenderConfigReader, &value ) ) != IVAS_ERR_OK ) + for ( k = 0; k < N_ABS_COEFFS; k++ ) { - return error; - } - pRenderConfigReader->pAE[n].pEarlyReflections->pFG = &pRenderConfigReader->pFG[value]; - - /* Absorption coefficients */ - if ( ( pRenderConfigReader->pAE[n].pEarlyReflections->pAbsCoeff = malloc( pRenderConfigReader->pAE[n].pEarlyReflections->pFG->nrBands * sizeof( float[N_ABS_COEFFS] ) ) ) == NULL ) - { - return IVAS_ERR_FAILED_ALLOC; - } - - for ( m = 0; m < pRenderConfigReader->pAE[n].pEarlyReflections->pFG->nrBands; m++ ) - { - for ( k = 0; k < N_ABS_COEFFS; k++ ) + if ( ( error = get_bin_absorption( pRenderConfigReader, &pRenderConfigReader->pAE[n].pEarlyReflections->pAbsCoeff[k] ) ) != IVAS_ERR_OK ) { - if ( ( error = get_absorption( pRenderConfigReader, &pRenderConfigReader->pAE[n].pEarlyReflections->pAbsCoeff[m][k] ) ) != IVAS_ERR_OK ) - { - return error; - } + return error; } } /* Has listener origin */ - if ( ( error = read_bool( pRenderConfigReader, &value ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_bool( pRenderConfigReader, &value ) ) != IVAS_ERR_OK ) { return error; } @@ -1648,15 +1753,15 @@ static ivas_error RenderConfigReader_readReverb( return IVAS_ERR_FAILED_ALLOC; } - if ( ( error = read_bits( pRenderConfigReader, &signx, 1 ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_bits( pRenderConfigReader, &signx, 1 ) ) != IVAS_ERR_OK ) { return error; } - if ( ( error = read_bits( pRenderConfigReader, &signy, 1 ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_bits( pRenderConfigReader, &signy, 1 ) ) != IVAS_ERR_OK ) { return error; } - if ( ( error = get_distance( pRenderConfigReader, true, &pRenderConfigReader->pAE[n].pEarlyReflections->pListenerOrigin->x ) ) != IVAS_ERR_OK ) + if ( ( error = get_bin_distance( pRenderConfigReader, true, &pRenderConfigReader->pAE[n].pEarlyReflections->pListenerOrigin->x ) ) != IVAS_ERR_OK ) { return error; } @@ -1664,7 +1769,7 @@ static ivas_error RenderConfigReader_readReverb( { pRenderConfigReader->pAE[n].pEarlyReflections->pListenerOrigin->x *= -1.0f; } - if ( ( error = get_distance( pRenderConfigReader, true, &pRenderConfigReader->pAE[n].pEarlyReflections->pListenerOrigin->y ) ) != IVAS_ERR_OK ) + if ( ( error = get_bin_distance( pRenderConfigReader, true, &pRenderConfigReader->pAE[n].pEarlyReflections->pListenerOrigin->y ) ) != IVAS_ERR_OK ) { return error; } @@ -1672,30 +1777,36 @@ static ivas_error RenderConfigReader_readReverb( { pRenderConfigReader->pAE[n].pEarlyReflections->pListenerOrigin->y *= -1.0f; } - if ( ( error = get_distance( pRenderConfigReader, true, &pRenderConfigReader->pAE[n].pEarlyReflections->pListenerOrigin->z ) ) != IVAS_ERR_OK ) + if ( ( error = get_bin_distance( pRenderConfigReader, true, &pRenderConfigReader->pAE[n].pEarlyReflections->pListenerOrigin->z ) ) != IVAS_ERR_OK ) { return error; } } + + /* Low complexity mode */ + if ( ( error = read_bin_bool( pRenderConfigReader, &pRenderConfigReader->pAE[n].pEarlyReflections->lowComplexity ) ) != IVAS_ERR_OK ) + { + return error; + } } #endif #ifdef CONTROL_METADATA_DIRECTIVITY /* Has source directivity */ - if ( ( error = read_bool( pRenderConfigReader, &value ) ) != IVAS_ERR_OK ) + if ( ( error = read_bin_bool( pRenderConfigReader, &value ) ) != IVAS_ERR_OK ) { return error; } if ( value == true ) { - if ( ( error = get_angle( pRenderConfigReader, &pRenderConfigReader->directivity[0] ) ) != IVAS_ERR_OK ) + if ( ( error = get_bin_angle( pRenderConfigReader, &pRenderConfigReader->directivity[0] ) ) != IVAS_ERR_OK ) { return error; } - if ( ( error = get_angle( pRenderConfigReader, &pRenderConfigReader->directivity[1] ) ) != IVAS_ERR_OK ) + if ( ( error = get_bin_angle( pRenderConfigReader, &pRenderConfigReader->directivity[1] ) ) != IVAS_ERR_OK ) { return error; } - if ( ( error = get_outer_attenuation( pRenderConfigReader, &pRenderConfigReader->directivity[2] ) ) != IVAS_ERR_OK ) + if ( ( error = get_bin_outer_attenuation( pRenderConfigReader, &pRenderConfigReader->directivity[2] ) ) != IVAS_ERR_OK ) { return error; } @@ -1712,7 +1823,6 @@ static ivas_error RenderConfigReader_readReverb( /* Cleanup */ free( pRenderConfigReader->pBitstream ); - // TODO: Check the values, apply DSR epsilon return IVAS_ERR_OK; } @@ -1721,8 +1831,11 @@ static ivas_error RenderConfigReader_readReverb( ivas_error RenderConfigReader_read( #ifdef CONTROL_METADATA_REVERB RenderConfigReader *pRenderConfigReader, /* i : RenderConfigReader handle */ - const char *pRenderConfigPath, /* i : Renderer configuration file path */ - IVAS_RENDER_CONFIG_HANDLE hRenderConfig /* o : Renderer configuration handle */ + const char *pRenderConfigPath /* i : Renderer configuration file path */ +#if ( defined SPLIT_REND_WITH_HEAD_ROT ) || ( defined DEBUGGING ) + , + IVAS_RENDER_CONFIG_HANDLE hRenderConfig /* o : Renderer configuration handle */ +#endif #else RenderConfigReader *pRenderConfigReader, /* i : RenderConfigReader handle */ IVAS_RENDER_CONFIG_HANDLE hRenderConfig /* o : Renderer configuration handle */ @@ -1742,6 +1855,21 @@ ivas_error RenderConfigReader_read( ivas_error error; int32_t params_length; int32_t length; + uint32_t i, idx; + uint32_t nFG, nAE; + char *pToken; + FREQ_GRID_MODE fgMode; + float freqHop; + uint32_t acIdx; + uint32_t defGridId, defGridLen, defGridOffset, defGridNrBands; + const float *pDefGrid; + float erTemp[N_ABS_COEFFS]; + uint32_t roomAcHasFgCount, roomAcHasAcEnvCount; + uint32_t fgHasMethod, fgHasNBands, fgHasFreqs, fgHasDefaultGrid, fgHasStartFreq, fgHasFreqHop; + uint32_t aeHasFgIdx, aeHasPredelay, aeHasRt60, aeHasDsr; +#ifdef CONTROL_METADATA_EARLY_REFLECTIONS + uint32_t aeHasERsize, aeHasERabs; +#endif #else int16_t nBandsInput; int16_t nVectorsMissing; @@ -1757,7 +1885,10 @@ ivas_error RenderConfigReader_read( pConfig_str = (char *) calloc( file_size + 1, sizeof( char ) ); pParams = (char *) calloc( file_size + 1, sizeof( char ) ); pTemp = (char *) calloc( file_size + 1, sizeof( char ) ); -#ifndef CONTROL_METADATA_REVERB +#ifdef CONTROL_METADATA_REVERB + acIdx = 0; + roomAcHasFgCount = roomAcHasAcEnvCount = FALSE; +#else nBandsInput = hRenderConfig->room_acoustics.nBands; nVectorsMissing = N_REVERB_VECTORS; #endif @@ -1799,7 +1930,563 @@ ivas_error RenderConfigReader_read( to_upper( chapter ); /* interpret params */ -#ifndef CONTROL_METADATA_REVERB +#ifdef CONTROL_METADATA_REVERB + pToken = strtok( chapter, ":" ); + if ( strcmp( chapter, "ROOMACOUSTICS" ) == 0 && strlen( pParams ) != 0 ) + { + params_idx = 0; + pValue = (char *) calloc( strlen( pParams ), sizeof( char ) ); + + while ( sscanf( pParams + params_idx, "%64[^=]=%[^;];", item, pValue ) == 2 ) + { + params_idx += (int32_t) ( strlen( item ) + strlen( pValue ) + 2 ); +#ifdef DEBUGGING + fprintf( stderr, " PARAM: %s -> %s\n", item, pValue ); +#endif + if ( strcmp( item, "FREQUENCYGRIDCOUNT" ) == 0 ) + { + /* Read the number of frequency grids */ + if ( !sscanf( pValue, "%u", &nFG ) ) + { + errorHandler( item, ERROR_VALUE_INVALID ); + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + if ( nFG > 0 ) + { + for ( idx = 0; idx < pRenderConfigReader->nFG; idx++ ) + { + free( pRenderConfigReader->pFG[idx].pFc ); + } + free( pRenderConfigReader->pFG ); + + pRenderConfigReader->nFG = nFG; + + /* Allocate memory for the frequency grids */ + if ( ( pRenderConfigReader->pFG = (FrequencyGrid *) malloc( pRenderConfigReader->nFG * sizeof( FrequencyGrid ) ) ) == NULL ) + { + return IVAS_ERR_FAILED_ALLOC; + } + for ( idx = 0; idx < nFG; idx++ ) + { + pRenderConfigReader->pFG[idx].nrBands = 0; + pRenderConfigReader->pFG[idx].pFc = NULL; + } + } + roomAcHasFgCount = TRUE; + } + else if ( strcmp( item, "ACOUSTICENVIRONMENTCOUNT" ) == 0 ) + { + /* Read the number of acoustic environments */ + if ( !sscanf( pValue, "%u", &nAE ) ) + { + errorHandler( item, ERROR_VALUE_INVALID ); + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + if ( nAE > 0 ) + { + for ( idx = 0; idx < pRenderConfigReader->nAE; idx++ ) + { + free( pRenderConfigReader->pAE[idx].pRT60 ); + free( pRenderConfigReader->pAE[idx].pDSR ); +#ifdef CONTROL_METADATA_EARLY_REFLECTIONS + if ( pRenderConfigReader->pAE[idx].pEarlyReflections != NULL ) + { + free( pRenderConfigReader->pAE[idx].pEarlyReflections->pListenerOrigin ); + free( pRenderConfigReader->pAE[idx].pEarlyReflections ); + } +#endif + } + free( pRenderConfigReader->pAE ); + + pRenderConfigReader->nAE = nAE; + + /* Allocate memory for the acoustic environments array */ + if ( ( pRenderConfigReader->pAE = (AcousticEnv *) malloc( pRenderConfigReader->nAE * sizeof( AcousticEnv ) ) ) == NULL ) + { + return IVAS_ERR_FAILED_ALLOC; + } + /* Initialize memory pointers to allow for safe freeing */ + for ( acIdx = 0; acIdx < pRenderConfigReader->nAE; acIdx++ ) + { + pRenderConfigReader->pAE[acIdx].pRT60 = NULL; + pRenderConfigReader->pAE[acIdx].pDSR = NULL; +#ifdef CONTROL_METADATA_EARLY_REFLECTIONS + pRenderConfigReader->pAE[acIdx].pEarlyReflections = NULL; +#endif + } + } + acIdx = 0; + roomAcHasAcEnvCount = TRUE; + } +#ifdef DEBUGGING + else + { + fprintf( stderr, "Rendering configuration: unsupported property %s\n", item ); + } +#endif + } +#ifdef DEBUGGING + if ( roomAcHasFgCount == FALSE ) + { + fprintf( stderr, "Renderer configuration: frequencyGridCount missing from 'roomAcoustics' chapter.\n\n" ); + } + if ( roomAcHasAcEnvCount == FALSE ) + { + fprintf( stderr, "Renderer configuration: acousticEnvironmentCount missing from 'roomAcoustics' chapter.\n\n" ); + } +#endif + if ( roomAcHasFgCount == FALSE || roomAcHasAcEnvCount == FALSE ) + { + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + free( pValue ); + } + else if ( strcmp( pToken, "FREQUENCYGRID" ) == 0 ) + { + if ( pRenderConfigReader->pFG == NULL ) + { + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + + idx = strtol( strtok( NULL, ":" ), NULL, 0 ); + if ( idx >= pRenderConfigReader->nFG ) + { +#ifdef DEBUGGING + fprintf( stderr, "Rendering configuration: frequency grid with index %d does not fit into the frequency grid array of %d elements.\n", idx, pRenderConfigReader->nFG ); +#endif + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + + fgHasMethod = fgHasNBands = fgHasFreqs = fgHasDefaultGrid = fgHasStartFreq = fgHasFreqHop = FALSE; + fgMode = FREQ_GRID_MODE_UNKNOWN; + params_idx = 0; + pValue = (char *) calloc( strlen( pParams ), sizeof( char ) ); + while ( sscanf( pParams + params_idx, "%64[^=]=%[^;];", item, pValue ) == 2 ) + { + params_idx += (int32_t) ( strlen( item ) + strlen( pValue ) + 2 ); +#ifdef DEBUGGING + fprintf( stderr, " PARAM: %s -> %s\n", item, pValue ); +#endif + if ( strcmp( item, "METHOD" ) == 0 ) + { + if ( strcmp( pValue, "INDIVIDUALFREQUENCIES" ) == 0 ) + { + fgMode = FREQ_GRID_MODE_INDIVIDUAL_FREQUENCIES; + } + else if ( strcmp( pValue, "STARTHOPAMOUNT" ) == 0 ) + { + fgMode = FREQ_GRID_MODE_START_HOP_AMOUNT; + } + else if ( strcmp( pValue, "DEFAULTBANDING" ) == 0 ) + { + fgMode = FREQ_GRID_MODE_DEFAULT_BANDING; + } + fgHasMethod = TRUE; + } + /* Read number of bands for individual frequency, start-hop-amount mode */ + else if ( strcmp( item, "NRBANDS" ) == 0 ) + { + if ( fgMode != FREQ_GRID_MODE_INDIVIDUAL_FREQUENCIES && fgMode != FREQ_GRID_MODE_START_HOP_AMOUNT ) + { + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + if ( !sscanf( pValue, "%u", &pRenderConfigReader->pFG[idx].nrBands ) ) + { + errorHandler( item, ERROR_VALUE_INVALID ); + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + /* Allocate memory for the center frequency array */ + if ( ( pRenderConfigReader->pFG[idx].pFc = (float *) malloc( pRenderConfigReader->pFG[idx].nrBands * sizeof( float ) ) ) == NULL ) + { + return IVAS_ERR_FAILED_ALLOC; + } + fgHasNBands = TRUE; + } + else if ( strcmp( item, "FREQUENCIES" ) == 0 ) + { + if ( fgMode != FREQ_GRID_MODE_INDIVIDUAL_FREQUENCIES || pRenderConfigReader->pFG[idx].nrBands == 0 || pRenderConfigReader->pFG[idx].pFc == NULL ) + { + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + /* Read the individual frequencies */ + if ( read_txt_vector( pValue, pRenderConfigReader->pFG[idx].nrBands, pRenderConfigReader->pFG[idx].pFc ) ) + { + errorHandler( item, ERROR_VALUE_INVALID ); + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + fgHasFreqs = TRUE; + } + else if ( strcmp( item, "STARTFREQUENCY" ) == 0 ) + { + if ( fgMode != FREQ_GRID_MODE_START_HOP_AMOUNT || pRenderConfigReader->pFG[idx].nrBands == 0 || pRenderConfigReader->pFG[idx].pFc == NULL ) + { + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + if ( !sscanf( pValue, "%f", &pRenderConfigReader->pFG[idx].pFc[0] ) ) + { + errorHandler( item, ERROR_VALUE_INVALID ); + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + fgHasStartFreq = TRUE; + } + else if ( strcmp( item, "FREQUENCYHOP" ) == 0 ) + { + if ( fgMode != FREQ_GRID_MODE_START_HOP_AMOUNT || pRenderConfigReader->pFG[idx].nrBands == 0 || pRenderConfigReader->pFG[idx].pFc == NULL || pRenderConfigReader->pFG[idx].pFc[0] == 0.0f ) + { + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + if ( !sscanf( pValue, "%f", &freqHop ) ) + { + errorHandler( item, ERROR_VALUE_INVALID ); + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + /* Fill up the center frequency array */ + for ( i = 1; i < pRenderConfigReader->pFG[idx].nrBands; i++ ) + { + pRenderConfigReader->pFG[idx].pFc[i] = pRenderConfigReader->pFG[idx].pFc[i - 1] * freqHop; + } + fgHasFreqHop = TRUE; + } + /* Handle default grids, with optional sub-grids */ + else if ( strcmp( item, "DEFAULTGRID" ) == 0 ) + { + if ( !sscanf( pValue, "%u", &defGridId ) ) + { + errorHandler( item, ERROR_VALUE_INVALID ); + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + + switch ( defGridId ) + { + case 0: + defGridLen = sizeof( defaultFrequencyGrid_0 ) / sizeof( defaultFrequencyGrid_0[0] ); + pDefGrid = defaultFrequencyGrid_0; + break; + case 1: + defGridLen = sizeof( defaultFrequencyGrid_1 ) / sizeof( defaultFrequencyGrid_1[0] ); + pDefGrid = defaultFrequencyGrid_1; + break; + case 2: + defGridLen = sizeof( defaultFrequencyGrid_2 ) / sizeof( defaultFrequencyGrid_2[0] ); + pDefGrid = defaultFrequencyGrid_2; + break; + case 3: + defGridLen = sizeof( defaultFrequencyGrid_3 ) / sizeof( defaultFrequencyGrid_3[0] ); + pDefGrid = defaultFrequencyGrid_3; + break; + case 4: + defGridLen = sizeof( defaultFrequencyGrid_4 ) / sizeof( defaultFrequencyGrid_4[0] ); + pDefGrid = defaultFrequencyGrid_4; + break; + case 5: + defGridLen = sizeof( defaultFrequencyGrid_5 ) / sizeof( defaultFrequencyGrid_5[0] ); + pDefGrid = defaultFrequencyGrid_5; + break; + case 6: + defGridLen = sizeof( defaultFrequencyGrid_6 ) / sizeof( defaultFrequencyGrid_6[0] ); + pDefGrid = defaultFrequencyGrid_6; + break; + case 7: + defGridLen = sizeof( defaultFrequencyGrid_7 ) / sizeof( defaultFrequencyGrid_7[0] ); + pDefGrid = defaultFrequencyGrid_7; + break; + case 8: + defGridLen = sizeof( defaultFrequencyGrid_8 ) / sizeof( defaultFrequencyGrid_8[0] ); + pDefGrid = defaultFrequencyGrid_8; + break; + default: + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + fgHasDefaultGrid = TRUE; + + /* Handle sub-grids */ + defGridOffset = 0; + defGridNrBands = defGridLen; + + while ( sscanf( pParams + params_idx, "%64[^=]=%[^;];", item, pValue ) == 2 ) + { + if ( strcmp( item, "DEFAULTGRIDOFFSET" ) == 0 ) + { + if ( !sscanf( pValue, "%u", &defGridOffset ) ) + { + errorHandler( item, ERROR_VALUE_INVALID ); + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + } + else if ( strcmp( item, "DEFAULTGRIDNRBANDS" ) == 0 ) + { + if ( !sscanf( pValue, "%u", &defGridNrBands ) ) + { + errorHandler( item, ERROR_VALUE_INVALID ); + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + } + else + { +#ifdef DEBUGGING + fprintf( stderr, "Rendering configuration: unsupported property %s\n", item ); +#endif + break; + } + params_idx += (int32_t) ( strlen( item ) + strlen( pValue ) + 2 ); + } + + if ( defGridOffset + defGridNrBands > defGridLen ) + { +#ifdef DEBUGGING + fprintf( stderr, "Rendering configuration: invalid default banding selection.\n\n" ); +#endif + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + pRenderConfigReader->pFG[idx].nrBands = defGridNrBands; + + /* Allocate memory for the center frequency array */ + if ( ( pRenderConfigReader->pFG[idx].pFc = (float *) malloc( defGridNrBands * sizeof( float ) ) ) == NULL ) + { + return IVAS_ERR_FAILED_ALLOC; + } + + /* Copy the ROM content to the frequency grid*/ + for ( i = 0; i < defGridNrBands; i++ ) + { + pRenderConfigReader->pFG[idx].pFc[i] = pDefGrid[defGridOffset + i]; + } + } +#ifdef DEBUGGING + else + { + fprintf( stderr, "Rendering configuration: unsupported configuration property %s\n", item ); + } +#endif + } + if ( fgHasMethod == FALSE || + ( fgMode == FREQ_GRID_MODE_INDIVIDUAL_FREQUENCIES && ( fgHasFreqs == FALSE || fgHasNBands == FALSE ) ) || + ( fgMode == FREQ_GRID_MODE_DEFAULT_BANDING && fgHasDefaultGrid == FALSE ) || + ( fgMode == FREQ_GRID_MODE_START_HOP_AMOUNT && ( fgHasStartFreq == FALSE || fgHasFreqHop == FALSE || fgHasNBands == FALSE ) ) ) + { +#ifdef DEBUGGING + fprintf( stderr, "Rendering configuration: inconsistent default frequency band configuration.\n\n" ); +#endif + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + free( pValue ); + } + /* Handle multiple acoustic environments */ + else if ( strcmp( pToken, "ACOUSTICENVIRONMENT" ) == 0 ) + { + if ( pRenderConfigReader->pAE == NULL || acIdx >= pRenderConfigReader->nAE ) + { + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + idx = strtol( strtok( NULL, ":" ), NULL, 0 ); + pRenderConfigReader->pAE->id = idx; + + aeHasFgIdx = aeHasPredelay = aeHasRt60 = aeHasDsr = FALSE; +#ifdef CONTROL_METADATA_EARLY_REFLECTIONS + aeHasERsize = aeHasERabs = FALSE; +#endif + params_idx = 0; + pValue = (char *) calloc( strlen( pParams ), sizeof( char ) ); + while ( sscanf( pParams + params_idx, "%64[^=]=%[^;];", item, pValue ) == 2 ) + { + params_idx += (int32_t) ( strlen( item ) + strlen( pValue ) + 2 ); +#ifdef DEBUGGING + fprintf( stderr, " PARAM: %s -> %s\n", item, pValue ); +#endif + /* Frequency grid index */ + if ( strcmp( item, "FREQUENCYGRIDINDEX" ) == 0 ) + { + if ( !sscanf( pValue, "%u", &i ) ) + { + errorHandler( item, ERROR_VALUE_INVALID ); + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + if ( i > pRenderConfigReader->nFG || &pRenderConfigReader->pFG[i] == NULL ) + { + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + pRenderConfigReader->pAE[acIdx].pFG = &pRenderConfigReader->pFG[i]; + + /* Allocate memory for RT60 and DSR arrays */ + if ( ( pRenderConfigReader->pAE[acIdx].pRT60 = (float *) malloc( pRenderConfigReader->pAE[acIdx].pFG->nrBands * sizeof( float ) ) ) == NULL ) + { + return IVAS_ERR_FAILED_ALLOC; + } + + if ( ( pRenderConfigReader->pAE[acIdx].pDSR = (float *) malloc( pRenderConfigReader->pAE[acIdx].pFG->nrBands * sizeof( float ) ) ) == NULL ) + { + return IVAS_ERR_FAILED_ALLOC; + } + aeHasFgIdx = TRUE; + } + + /* Acoustic pre-delay */ + else if ( strcmp( item, "ACOUSTICPREDELAY" ) == 0 ) + { + if ( !sscanf( pValue, "%f", &hRenderConfig->room_acoustics.acousticPreDelay ) ) + { + errorHandler( item, ERROR_VALUE_INVALID ); + } + } + /* Pre-delay */ + else if ( strcmp( item, "PREDELAY" ) == 0 ) + { + if ( !sscanf( pValue, "%f", &pRenderConfigReader->pAE[acIdx].preDelay ) ) + { + errorHandler( item, ERROR_VALUE_INVALID ); + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + aeHasPredelay = TRUE; + } + /* RT60 */ + else if ( strcmp( item, "RT60" ) == 0 ) + { + if ( read_txt_vector( pValue, pRenderConfigReader->pFG[idx].nrBands, pRenderConfigReader->pAE[acIdx].pRT60 ) ) + { + errorHandler( item, ERROR_VALUE_INVALID ); + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + aeHasRt60 = TRUE; + } + /* DSR */ + else if ( strcmp( item, "DSR" ) == 0 ) + { + if ( read_txt_vector( pValue, pRenderConfigReader->pFG[idx].nrBands, pRenderConfigReader->pAE[acIdx].pDSR ) ) + { + errorHandler( item, ERROR_VALUE_INVALID ); + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + aeHasDsr = TRUE; + } +#ifdef CONTROL_METADATA_EARLY_REFLECTIONS + else if ( strcmp( item, "EARLYREFLECTIONSSIZE" ) == 0 ) + { + if ( pRenderConfigReader->pAE[acIdx].pEarlyReflections == NULL ) + { + if ( ( pRenderConfigReader->pAE[acIdx].pEarlyReflections = (EarlyReflectionsConfig *) malloc( sizeof( EarlyReflectionsConfig ) ) ) == NULL ) + { + return IVAS_ERR_FAILED_ALLOC; + } + pRenderConfigReader->pAE[acIdx].pEarlyReflections->pListenerOrigin = NULL; + pRenderConfigReader->pAE[acIdx].pEarlyReflections->lowComplexity = FALSE; + } + if ( strcmp( item, "EARLYREFLECTIONSSIZE" ) == 0 ) + { + if ( read_txt_vector( pValue, 3, erTemp ) ) + { + errorHandler( item, ERROR_VALUE_INVALID ); + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + pRenderConfigReader->pAE[acIdx].pEarlyReflections->dimensions.x = erTemp[0]; + pRenderConfigReader->pAE[acIdx].pEarlyReflections->dimensions.y = erTemp[1]; + pRenderConfigReader->pAE[acIdx].pEarlyReflections->dimensions.z = erTemp[2]; + aeHasERsize = TRUE; + } + } + else if ( strcmp( item, "ABSORPTIONCOEFFS" ) == 0 ) + { + if ( pRenderConfigReader->pAE[acIdx].pEarlyReflections == NULL ) + { +#ifdef DEBUGGING + fprintf( stderr, "Rendering configuration: early reflections absorption coefficients specified without room size preceding.\n\n" ); +#endif + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + if ( read_txt_vector( pValue, N_ABS_COEFFS, erTemp ) ) + { + errorHandler( item, ERROR_VALUE_INVALID ); + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + for ( i = 0; i < N_ABS_COEFFS; i++ ) + { + pRenderConfigReader->pAE[acIdx].pEarlyReflections->pAbsCoeff[i] = erTemp[i]; + } + aeHasERabs = TRUE; + } + else if ( strcmp( item, "LISTENERORIGIN" ) == 0 ) + { + if ( pRenderConfigReader->pAE[acIdx].pEarlyReflections == NULL ) + { +#ifdef DEBUGGING + fprintf( stderr, "Rendering configuration: early reflections listener origin specified without room size preceding.\n\n" ); +#endif + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + if ( read_txt_vector( pValue, 3, erTemp ) ) + { + errorHandler( item, ERROR_VALUE_INVALID ); + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + if ( ( pRenderConfigReader->pAE[acIdx].pEarlyReflections->pListenerOrigin = malloc( sizeof( IVAS_VECTOR3 ) ) ) == NULL ) + { + return IVAS_ERR_FAILED_ALLOC; + } + pRenderConfigReader->pAE[acIdx].pEarlyReflections->pListenerOrigin->x = erTemp[0]; + pRenderConfigReader->pAE[acIdx].pEarlyReflections->pListenerOrigin->y = erTemp[1]; + pRenderConfigReader->pAE[acIdx].pEarlyReflections->pListenerOrigin->z = erTemp[2]; + } + else if ( strcmp( item, "LOWCOMPLEXITY" ) == 0 ) + { + if ( pRenderConfigReader->pAE[acIdx].pEarlyReflections == NULL ) + { +#ifdef DEBUGGING + fprintf( stderr, "Rendering configuration: early reflections low complexity flag specified without room size preceding.\n\n" ); +#endif + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + if ( read_txt_bool( pValue, &pRenderConfigReader->pAE[acIdx].pEarlyReflections->lowComplexity ) ) + { + errorHandler( item, ERROR_VALUE_INVALID ); + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + } +#endif +#ifdef DEBUGGING + else + { + fprintf( stderr, "Rendering configuration: unsupported configuration property %s\n", item ); + } +#endif + } +#ifdef DEBUGGING + if ( aeHasFgIdx == FALSE ) + { + fprintf( stderr, "Renderer configuration: frequencyGridIndex missing from 'acousticEnvironment' %d.\n\n", acIdx ); + } + if ( aeHasPredelay == FALSE ) + { + fprintf( stderr, "Renderer configuration: predelay missing from 'acousticEnvironment' %d.\n\n", acIdx ); + } + if ( aeHasRt60 == FALSE ) + { + fprintf( stderr, "Renderer configuration: RT60 missing from 'acousticEnvironment' %d.\n\n", acIdx ); + } + if ( aeHasDsr == FALSE ) + { + fprintf( stderr, "Renderer configuration: DSR missing from 'acousticEnvironment' %d.\n\n", acIdx ); + } +#ifdef CONTROL_METADATA_EARLY_REFLECTIONS + if ( aeHasERsize == TRUE && aeHasERabs == FALSE ) + { + fprintf( stderr, "Renderer configuration: early reflections absorption coefficients missing from 'acousticEnvironment' %d.\n\n", acIdx ); + } +#endif +#endif + if ( aeHasFgIdx == FALSE || aeHasPredelay == FALSE || aeHasRt60 == FALSE || aeHasDsr == FALSE ) + { + return IVAS_ERR_INVALID_RENDER_CONFIG; + } +#ifdef CONTROL_METADATA_EARLY_REFLECTIONS + if ( aeHasERsize == TRUE && aeHasERabs == FALSE ) + { + return IVAS_ERR_INVALID_RENDER_CONFIG; + } +#endif + + free( pValue ); + acIdx++; + } +#else if ( strcmp( chapter, "ROOMACOUSTICS" ) == 0 ) { params_idx = 0; @@ -1874,11 +2561,8 @@ ivas_error RenderConfigReader_read( } } #endif -#if ( !defined CONTROL_METADATA_REVERB ) && ( defined SPLIT_REND_WITH_HEAD_ROT ) - else -#endif #ifdef SPLIT_REND_WITH_HEAD_ROT - if ( strcmp( chapter, "SPLITREND" ) == 0 && strlen( pParams ) != 0 ) + else if ( strcmp( chapter, "SPLITREND" ) == 0 && strlen( pParams ) != 0 ) { params_idx = 0; pValue = (char *) calloc( strlen( pParams ), sizeof( char ) ); @@ -1973,7 +2657,7 @@ ivas_error RenderConfigReader_read( free( pValue ); } #endif -#if ( defined DEBUGGING ) || ( defined SPLIT_REND_WITH_HEAD_ROT ) +#if ( defined DEBUGGING ) || ( defined SPLIT_REND_WITH_HEAD_ROT || defined CONTROL_METADATA_REVERB ) else if ( strcmp( chapter, "GENERAL" ) == 0 && strlen( pParams ) != 0 ) #else if ( strcmp( chapter, "GENERAL" ) == 0 && strlen( pParams ) != 0 ) @@ -1992,7 +2676,7 @@ ivas_error RenderConfigReader_read( fprintf( stderr, " PARAM: %s -> %s\n", item, pValue ); #endif #ifdef CONTROL_METADATA_REVERB - if ( strcmp( item, "REVERBFILE" ) == 0 ) + if ( strcmp( item, "BINARYCONFIG" ) == 0 ) { /* get correct case reverb configuration file path */ sscanf( pTemp + params_idx, "%*[^=] = %[^;];", pValue ); @@ -2015,14 +2699,20 @@ ivas_error RenderConfigReader_read( strncpy( pCombinedName, pRenderConfigPath, length ); strcpy( pCombinedName + length, pValue ); - if ( ( error = RenderConfigReader_readReverb( pCombinedName, pRenderConfigReader ) ) != IVAS_ERR_OK ) + if ( ( error = RenderConfigReader_readBinary( pCombinedName, pRenderConfigReader ) ) != IVAS_ERR_OK ) { errorHandler( item, ERROR_VALUE_INVALID ); + return IVAS_ERR_INVALID_RENDER_CONFIG; } +#ifdef CONTROL_METADATA_DIRECTIVITY + mvr2r( pRenderConfigReader->directivity, hRenderConfig->directivity, 3 ); +#endif free( pCombinedName ); } +#ifdef DEBUGGING else #endif +#endif #ifdef DEBUGGING if ( strcmp( item, "RENDERER" ) == 0 ) { @@ -2037,13 +2727,20 @@ ivas_error RenderConfigReader_read( else { errorHandler( pValue, ERROR_VALUE_INVALID ); +#ifdef CONTROL_METADATA_REVERB + return IVAS_ERR_INVALID_RENDER_CONFIG; +#endif } } else #endif if ( strcmp( item, "DIRECTIVITY" ) == 0 ) { +#ifdef CONTROL_METADATA_REVERB + if ( read_txt_vector( pValue, 3, hRenderConfig->directivity ) ) +#else if ( read_vector( pValue, 3, hRenderConfig->directivity ) ) +#endif { errorHandler( item, ERROR_VALUE_INVALID ); } @@ -2130,7 +2827,6 @@ ivas_error RenderConfigReader_getAcousticEnvironment( return IVAS_ERR_ACOUSTIC_ENVIRONMENT_MISSING; } - #endif /*------------------------------------------------------------------------------------------* @@ -2160,7 +2856,6 @@ void RenderConfigReader_close( if ( ( *ppRenderConfigReader )->pAE[n].pEarlyReflections != NULL ) { free( ( *ppRenderConfigReader )->pAE[n].pEarlyReflections->pListenerOrigin ); - free( ( *ppRenderConfigReader )->pAE[n].pEarlyReflections->pAbsCoeff ); free( ( *ppRenderConfigReader )->pAE[n].pEarlyReflections ); } #endif diff --git a/lib_util/render_config_reader.h b/lib_util/render_config_reader.h index 4facb5b9cd42832a2ae78a105a54be89739cfbed..16d2f67a8f6f6fa8eb81edd3d0dd7ec15a9cf5d3 100644 --- a/lib_util/render_config_reader.h +++ b/lib_util/render_config_reader.h @@ -68,8 +68,11 @@ ivas_error RenderConfigReader_checkValues( ivas_error RenderConfigReader_read( #ifdef CONTROL_METADATA_REVERB RenderConfigReader *pRenderConfigReader, /* i : RenderConfigReader handle */ - const char *pRenderConfigPath, /* i : Renderer configuration file path */ - IVAS_RENDER_CONFIG_HANDLE hRenderConfig /* o : Renderer configuration handle */ + const char *pRenderConfigPath /* i : Renderer configuration file path */ +#if ( defined SPLIT_REND_WITH_HEAD_ROT ) || ( defined DEBUGGING ) + , + IVAS_RENDER_CONFIG_HANDLE hRenderConfig /* o : Renderer configuration handle */ +#endif #else RenderConfigReader *pRenderConfigReader, /* i : RenderConfigReader handle */ IVAS_RENDER_CONFIG_HANDLE hRenderConfig /* o : Renderer configuration handle */ diff --git a/scripts/reverb/acoustic_environment_hospital_patientroom.cfg b/scripts/reverb/acoustic_environment_hospital_patientroom.cfg index 62a4462477f34e42334b5bef9312d9d2c66d7e00..cc7747cd1baabb7ac5cd1877d5da22eb2b458b04 100644 --- a/scripts/reverb/acoustic_environment_hospital_patientroom.cfg +++ b/scripts/reverb/acoustic_environment_hospital_patientroom.cfg @@ -1,5 +1,9 @@ +[roomAcoustics] +frequencyGridCount = 1; +acousticEnvironmentCount = 1; + [frequencyGrid:0] -method = individualFrequencies +method = individualFrequencies; frequencies = [ 20.0, 25.0, 31.5, 40.0, 50.0, 63.0, 80.0, 100.0, @@ -8,21 +12,21 @@ frequencies = [ 800.0, 1000.0, 1250.0, 1600.0, 2000.0, 2500.0, 3150.0, 4000.0, 5000.0, 6300.0, 8000.0, 10000.0, - 12500.0, 16000.0, 20000.0] + 12500.0, 16000.0, 20000.0]; [acousticEnvironment:0] -id = 0 -frequencyGridIndex = 0 -predelay = 0.08163 +id = 0; +frequencyGridIndex = 0; +predelay = 0.08163; rt60 = [ 0.81275, 0.61888, 0.45111, 0.34672, 0.46683, 0.53987, 0.61874, 0.70291, 0.66657, 0.73037, 0.75090, 0.72470, 0.75486, 0.75857, 0.76844, 0.74999, 0.77622, 0.78227, 0.77441, 0.74688, 0.73521, 0.73782, 0.71928, 0.71708, 0.71465, 0.60592, 0.52031, 0.51768, 0.52102, 0.37956, - 0.30786] + 0.30786]; dsr = [ 0.00019952621, 0.00019952621, 7.9432844e-05, 5.0118702e-05, 7.943284e-06, 6.3095763e-06, 6.3095763e-06, 7.943284e-06, 1e-05, 1e-05, 7.943284e-06, 1e-05, 1e-05, 1e-05, 7.943284e-06, 1e-05, 1e-05, 7.943284e-06, 7.943284e-06, 6.3095763e-06, 6.3095763e-06, 6.3095763e-06, 6.3095763e-06, 6.3095763e-06, 6.3095763e-06, 3.1622776e-06, 3.1622776e-06, 3.1622776e-06, 6.3095763e-07, 3.1622776e-07, - 3.1622776e-07] + 3.1622776e-07]; diff --git a/scripts/reverb/acoustic_environment_recreation.cfg b/scripts/reverb/acoustic_environment_recreation.cfg index 02a9c722e76f0c6cdec06fd2265a115aa7c9bcf1..ec1ee14b7ac1953554724e1c10665c62de963645 100644 --- a/scripts/reverb/acoustic_environment_recreation.cfg +++ b/scripts/reverb/acoustic_environment_recreation.cfg @@ -1,6 +1,10 @@ +[roomAcoustics] +frequencyGridCount = 1; +acousticEnvironmentCount = 1; + [frequencyGrid:0] -nBands = 31 -method = individualFrequencies +nBands = 31; +method = individualFrequencies; frequencies = [ 20.0, 25.0, 31.5, 40.0, 50.0, 63.0, 80.0, 100.0, @@ -9,20 +13,20 @@ frequencies = [ 800.0, 1000.0, 1250.0, 1600.0, 2000.0, 2500.0, 3150.0, 4000.0, 5000.0, 6300.0, 8000.0, 10000.0, - 12500.0, 16000.0, 20000.0] + 12500.0, 16000.0, 20000.0]; [acousticEnvironment:0] -id = 0 -frequencyGridIndex = 0 -predelay = 0.43031 +id = 0; +frequencyGridIndex = 0; +predelay = 0.43031; rt60 = [ 4.51916, 4.89553, 4.83276, 5.00198, 5.34468, 5.76026, 6.36818, 6.95503, 7.27557, 7.62559, 8.08892, 8.16002, 8.13900, 8.17919, 8.16280, 8.46226, 9.61806, 9.93048, 9.81353, 8.59340, 8.38885, 8.36823, 6.51845, 3.76089, 3.75374, 3.57451, 1.28724, 1.22174, 1.22448, 1.71631, - 2.14343] + 2.14343]; dsr = [ 1e-06, 7.943284e-07, 1e-06, 1e-06, 1.5848925e-06, 1.9952631e-06, 3.1622776e-06, 3.9810707e-06, 6.3095763e-06, 7.943284e-06, 1e-05, 7.943284e-06, 7.943284e-06, 7.943284e-06, 7.943284e-06, 7.943284e-06, 5.01187e-06, 5.01187e-06, 3.9810707e-06, 3.1622776e-06, 3.1622776e-06, 2.511887e-06, 7.943284e-07, 6.3095763e-07, 6.3095763e-07, 5.01187e-08, 1.2589251e-08, 1.2589251e-08, 1.2589265e-09, 1.2589266e-11, - 3.981075e-12] + 3.981075e-12]; diff --git a/scripts/reverb/acoustic_environment_renderer.cfg b/scripts/reverb/acoustic_environment_renderer.cfg index e56f1bd9a8e2d5b961df34a7fdb9c0833c8e89a6..fffa8d0f2642ddb561d2d056040ecfa8718c27d7 100644 --- a/scripts/reverb/acoustic_environment_renderer.cfg +++ b/scripts/reverb/acoustic_environment_renderer.cfg @@ -1,5 +1,9 @@ +[roomAcoustics] +frequencyGridCount = 1; +acousticEnvironmentCount = 1; + [frequencyGrid:0] -method = individualFrequencies +method = individualFrequencies; frequencies = [ 20.0, 25.0, 31.5, 40.0, 50.0, 63.0, 80.0, 100.0, @@ -8,12 +12,12 @@ frequencies = [ 800.0, 1000.0, 1250.0, 1600.0, 2000.0, 2500.0, 3150.0, 4000.0, 5000.0, 6300.0, 8000.0, 10000.0, - 12500.0, 16000.0, 20000.0] + 12500.0, 16000.0, 20000.0]; [acousticEnvironment:0] -id = 0 -frequencyGridIndex = 0 -predelay = 0.1 +id = 0; +frequencyGridIndex = 0; +predelay = 0.1; rt60 = [ 1.3622, 1.4486, 1.3168, 1.5787, 1.4766, 1.3954, 1.2889, 1.3462, @@ -22,12 +26,12 @@ rt60 = [ 1.1028, 1.1714, 1.1027, 1.0666, 1.0550, 1.0553, 1.0521, 1.0569, 1.0421, 0.97822, 0.80487, 0.75944, - 0.71945, 0.61682, 0.60031] + 0.71945, 0.61682, 0.60031]; dsr = [ 1.9952632e-08, 1.9952632e-08, 1.2589251e-08, 1.5848926e-08, 1.2589251e-08, 1.9952632e-08, 2.511887e-08, 3.9810708e-08, 1e-07, 1.9952633e-07, 3.981071e-07, 6.3095763e-07, 7.943284e-07, 6.3095763e-07, 5.01187e-07, 5.01187e-07, 6.3095763e-07, 6.3095763e-07, 7.943284e-07, 6.3095763e-07, 5.01187e-07, 6.3095763e-07, 6.3095763e-07, 6.3095763e-07, 5.01187e-07, 2.511887e-07, 1.2589251e-07, 1e-07, 6.309576e-08, 3.1622776e-08, - 2.511887e-08] + 2.511887e-08]; diff --git a/scripts/reverb/acoustic_environment_renderer_directivity.cfg b/scripts/reverb/acoustic_environment_renderer_directivity.cfg index 04b99f7f3cd6641700e086ecc9255a73607bcd1d..9d15adb547c45608deaa43b8cecfd69740ba70cc 100644 --- a/scripts/reverb/acoustic_environment_renderer_directivity.cfg +++ b/scripts/reverb/acoustic_environment_renderer_directivity.cfg @@ -1,5 +1,9 @@ +[roomAcoustics] +frequencyGridCount = 1; +acousticEnvironmentCount = 1; + [frequencyGrid:0] -method = individualFrequencies +method = individualFrequencies; frequencies = [ 20.0, 25.0, 31.5, 40.0, 50.0, 63.0, 80.0, 100.0, @@ -8,12 +12,12 @@ frequencies = [ 800.0, 1000.0, 1250.0, 1600.0, 2000.0, 2500.0, 3150.0, 4000.0, 5000.0, 6300.0, 8000.0, 10000.0, - 12500.0, 16000.0, 20000.0] + 12500.0, 16000.0, 20000.0]; [acousticEnvironment:0] -id = 0 -frequencyGridIndex = 0 -predelay = 0.1 +id = 0; +frequencyGridIndex = 0; +predelay = 0.1; rt60 = [ 1.3622, 1.4486, 1.3168, 1.5787, 1.4766, 1.3954, 1.2889, 1.3462, @@ -22,13 +26,13 @@ rt60 = [ 1.1028, 1.1714, 1.1027, 1.0666, 1.0550, 1.0553, 1.0521, 1.0569, 1.0421, 0.97822, 0.80487, 0.75944, - 0.71945, 0.61682, 0.60031] + 0.71945, 0.61682, 0.60031]; dsr = [ 1.9952632e-08, 1.9952632e-08, 1.2589251e-08, 1.5848926e-08, 1.2589251e-08, 1.9952632e-08, 2.511887e-08, 3.9810708e-08, 1e-07, 1.9952633e-07, 3.981071e-07, 6.3095763e-07, 7.943284e-07, 6.3095763e-07, 5.01187e-07, 5.01187e-07, 6.3095763e-07, 6.3095763e-07, 7.943284e-07, 6.3095763e-07, 5.01187e-07, 6.3095763e-07, 6.3095763e-07, 6.3095763e-07, 5.01187e-07, 2.511887e-07, 1.2589251e-07, 1e-07, 6.309576e-08, 3.1622776e-08, - 2.511887e-08] + 2.511887e-08]; -[directivity:0] -directivity = [0.0, 360.0, 0.2512] +[directivity] +directivity = [0.0, 360.0, 0.2512]; diff --git a/scripts/reverb/generate_acoustic_environments_metadata.py b/scripts/reverb/generate_acoustic_environments_metadata.py index f723ebb4deab9ea14671bf3f0a6cfc34eeaa3634..f450d8e5c4224d377e0a909850eaf0ec39925faf 100644 --- a/scripts/reverb/generate_acoustic_environments_metadata.py +++ b/scripts/reverb/generate_acoustic_environments_metadata.py @@ -57,9 +57,13 @@ max_quantization_error = { def update_quantization_error(name, quantized_value, value): - max_quantization_error[name] = max(abs(quantized_value - value) / value, max_quantization_error[name]) - if print_quantized: - print(' {}: {}'.format(name, quantized_value)) + if value == 0: + if quantized_value != 0: + print(' {}: value = 0, quantized value = {}'.format(name, quantized_value)) + else: + max_quantization_error[name] = max(abs(quantized_value - value) / value, max_quantization_error[name]) + if print_quantized: + print(' {}: {}'.format(name, quantized_value)) def get_id_code(id): @@ -204,7 +208,14 @@ def get_frequency_code(frequency): return code -def get_frequency_hop_code(index): +def get_frequency_hop_code(value): + index = -1 + tolerance = 1e-5 + hop_sizes = [2 ** (1/12), 2 ** (1/6), 2 ** (1/4), 2 ** (1/3), 2 ** (1/2), 2 ** (1), 2 ** (2)] + for idx, hop in enumerate(hop_sizes): + if math.isclose(value, hop, rel_tol = tolerance): + index = idx + break assert 0 <= index <= 6 return [ '0010', # 2^(1/12) @@ -494,6 +505,7 @@ def generate_reverb_payload_equivalent_to_rend_config_renderer_cfg_plus_early_re [ 0.8, 0.8, 0.8, 0.8, 0.2, 0.6 ]) + '0' # hasListenerOrigin + + '0' # lowComplexity + '0' # hasDirectivity , endian='big') @@ -555,6 +567,7 @@ def generate_reverb_payload_equivalent_to_rend_config_renderer_cfg_plus_early_re + '0' # isPositiveY + concatenate(lambda d : get_distance_code(d, True), [ 0.5, 0.5, 1.5 ]) # erListenerOrigin (x, y, z) + + '1' # lowComplexity + '0' # hasDirectivity , endian='big') diff --git a/scripts/reverb/test.cfg b/scripts/reverb/test.cfg new file mode 100644 index 0000000000000000000000000000000000000000..7c670056b6140967072b6bcca3562c3a5db4dfa4 --- /dev/null +++ b/scripts/reverb/test.cfg @@ -0,0 +1,47 @@ +[roomAcoustics] +frequencyGridCount = 3; +acousticEnvironmentCount = 1; + +[frequencyGrid:0] +method = individualFrequencies; +nrBands = 31; +frequencies = [20.0, 25.0, 31.5, 40.0, + 50.0, 63.0, 80.0, 100.0, + 125.0, 160.0, 200.0, 250.0, + 315.0, 400.0, 500.0, 630.0, + 800.0, 1000.0, 1250.0, 1600.0, + 2000.0, 2500.0, 3150.0, 4000.0, + 5000.0, 6300.0, 8000.0, 10000.0, + 12500.0, 16000.0, 20000.0]; + +[frequencyGrid:1] +method = defaultBanding; +defaultGrid = 2; + +[frequencyGrid:2] +method = startHopAmount; +nrBands = 31; +startFrequency = 20; +frequencyHop = 1.259921050; + +[acousticEnvironment:0] +frequencyGridIndex = 1; +predelay = 0.1; +rt60 = [1.3622, 1.4486, 1.3168, 1.5787, + 1.4766, 1.3954, 1.2889, 1.3462, + 1.0759, 1.0401, 1.0970, 1.0850, + 1.0910, 1.0404, 1.0499, 1.0699, + 1.1028, 1.1714, 1.1027, 1.0666, + 1.0550, 1.0553, 1.0521, 1.0569, + 1.0421, 0.97822, 0.80487, 0.75944, + 0.71945, 0.61682, 0.60031]; + +dsr = [1.9952632e-08, 1.9952632e-08, 1.2589251e-08, 1.5848926e-08, 1.2589251e-08, 1.9952632e-08, 2.511887e-08, 3.9810708e-08, 1e-07, 1.9952633e-07, + 3.981071e-07, 6.3095763e-07, 7.943284e-07, 6.3095763e-07, 5.01187e-07, 5.01187e-07, 6.3095763e-07, 6.3095763e-07, 7.943284e-07, 6.3095763e-07, + 5.01187e-07, 6.3095763e-07, 6.3095763e-07, 6.3095763e-07, 5.01187e-07, 2.511887e-07, 1.2589251e-07, 1e-07, 6.309576e-08, 3.1622776e-08, + 2.511887e-08]; + +hasEarlyReflections = true; +earlyReflectionsSize = [4.0, 3.0, 2.5]; +absorptionCoeffs = [0.2, 0.2, 0.2, 0.2, 0.3, 0.8]; + diff --git a/scripts/reverb/text_to_binary_payload.py b/scripts/reverb/text_to_binary_payload.py index 00a10ede85df0d485bd38c2bdeac9c1e4170ad75..cb9537b1306ffe227e1e56fdab6a6cd3df90cfc7 100644 --- a/scripts/reverb/text_to_binary_payload.py +++ b/scripts/reverb/text_to_binary_payload.py @@ -40,9 +40,9 @@ #