diff --git a/lib_com/options.h b/lib_com/options.h index 6a91f6834a878d5b024289f633fd25e31697749d..ee12a4f188b2d39a21daea7e6509ec5fe5347478 100755 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -142,7 +142,10 @@ #define DISABLE_ADAP_RES_COD_TMP /* temporary fix for IVAS-403, disables adaptive residual coding */ /*#define FIX_I4_OL_PITCH*/ /* fix open-loop pitch used for EVS core switching */ -#define CONTROL_METADATA_REVERB /* Philips: renderer configuration change to binary format */ +#define CONTROL_METADATA_REVERB /* Philips: reverb configuration change to binary format */ +#ifdef CONTROL_METADATA_REVERB +#define CONTROL_METADATA_EARLY_REFLECTIONS /* Philips/Qualcomm: early reflections extension to reverb configuration */ +#endif #define COMMAND_LINE_OPTION_LATE_REVERB /* Philips: late reverb command line option */ #define USE_HRIR_128_METH5_IRC_53_Q10_SYML_ITRP1_48000 /* Dolby (Orange, FhG) : Contribution 36 - SBA HRIR update */ #define UPDATE_SBA_FILTER /* Dolby (Orange, FhG) : Contribution 36 - SBA HRIR update */ diff --git a/lib_util/render_config_reader.c b/lib_util/render_config_reader.c index d3802baf68b5eb19b67c7ffef5adb441b031a1e4..3e73f687bc6bcf5258bb12fe049e517579937b85 100644 --- a/lib_util/render_config_reader.c +++ b/lib_util/render_config_reader.c @@ -49,6 +49,8 @@ #define MAX_ITEM_LENGTH ( 64 ) #ifndef CONTROL_METADATA_REVERB #define N_REVERB_VECTORS ( 3 ) +#else +#define N_ABS_COEFFS ( 6 ) #endif #define SHORTEST_REV_DEL_LINE ( 0.015f ) @@ -85,13 +87,26 @@ typedef enum _FREQ_GRID_MODE FREQ_GRID_MODE_DEFAULT_BANDING = 2 } FREQ_GRID_MODE; +#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 */ +} EarlyReflectionsConfig; +#endif + typedef struct { uint32_t id; /* Acoustic environment ID */ - FrequencyGrid *pFG; /* Pointer into Frequency grids table */ + FrequencyGrid *pFG; /* Pointer into Frequency grids table for late reverb coeffs */ float *pRT60; /* RT60 table */ float *pDSR; /* DSR table */ float preDelay; /* Pre-delay */ +#ifdef CONTROL_METADATA_EARLY_REFLECTIONS + EarlyReflectionsConfig *pEarlyReflections; /* Early reflections configuration */ +#endif } AcousticEnv; struct RenderConfigReader @@ -122,6 +137,11 @@ typedef enum _RC_LUT RC_LUT_FREQ, RC_LUT_FREQ_HOP, RC_LUT_DSR, + RC_LUT_METERS, + RC_LUT_HECTOMETERS, + RC_LUT_KILOMETERS, + RC_LUT_CENTIMETERS, + RC_LUT_ABSORPTION } RC_LUT; /*------------------------------------------------------------------------------------------* @@ -224,9 +244,9 @@ const float lutFreq_Value[] = { const uint16_t lutFreq_Code[] = { 35, 14, 15, 9, 12, 13, 0, 26, 27, 1, 24, 25, 14, 30, 31, 15, 28, 29, 12, 18, 19, 13, 16, 17, 10, 22, 23, 11, 20, 21, 2, 16, 138, 139, 68 }; const uint8_t lutFreq_Len[] = { 6, 6, 6, 4, 6, 6, 4, 6, 6, 4, 6, 6, 4, 6, 6, 4, 6, 6, 4, 6, 6, 4, 6, 6, 4, 6, 6, 4, 6, 6, 4, 5, 8, 8, 7 }; -const float lutFreqHop_Value[] = { 1.090507733f, 1.104089514f, 1.122462048f, 1.148698355f, 1.189207115f, 1.25992105f, 1.414213562f, 2.0f, 4.0f }; -const uint16_t lutFreqHop_Code[] = { 12, 13, 2, 3, 0, 1, 1, 2, 7 }; -const uint8_t lutFreqHop_Len[] = { 4, 4, 4, 4, 4, 2, 4, 2, 3 }; +const float lutFreqHop_Value[] = { 1.059463094f, 1.122462048f, 1.189207115f, 1.259921050f, 1.414213562f, 2.0f, 4.0f }; +const uint16_t lutFreqHop_Code[] = { 2, 3, 0, 1, 1, 3, 2 }; +const uint8_t lutFreqHop_Len[] = { 4, 4, 4, 2, 4, 2, 2 }; const float lutDsr_Value[] = { -150.0f, -149.0f, -148.0f, -147.0f, -146.0f, -145.0f, -144.0f, -143.0f, -142.0f, -141.0f, @@ -266,6 +286,96 @@ const uint8_t lutDsr_Len[] = { 8 }; +const float lutMeters_Value[] = { + 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, + 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f, 18.0f, 19.0f, + 20.0f, 21.0f, 22.0f, 23.0f, 24.0f, 25.0f, 26.0f, 27.0f, 28.0f, 29.0f, + 30.0f, 31.0f, 32.0f, 33.0f, 34.0f, 35.0f, 36.0f, 37.0f, 38.0f, 39.0f, + 40.0f, 41.0f, 42.0f, 43.0f, 44.0f, 45.0f, 46.0f, 47.0f, 48.0f, 49.0f, + 50.0f, 51.0f, 52.0f, 53.0f, 54.0f, 55.0f, 56.0f, 57.0f, 58.0f, 59.0f, + 60.0f, 61.0f, 62.0f, 63.0f, 64.0f, 65.0f, 66.0f, 67.0f, 68.0f, 69.0f, + 70.0f, 71.0f, 72.0f, 73.0f, 74.0f, 75.0f, 76.0f, 77.0f, 78.0f, 79.0f, + 80.0f, 81.0f, 82.0f, 83.0f, 84.0f, 85.0f, 86.0f, 87.0f, 88.0f, 89.0f, + 90.0f, 91.0f, 92.0f, 93.0f, 94.0f, 95.0f, 96.0f, 97.0f, 98.0f, 99.0f +}; + +const uint16_t lutMeters_Code[] = { + 61, 50, 51, 48, 49, 54, 55, 52, 53, 10, + 11, 8, 9, 14, 15, 12, 13, 2, 3, 0, + 1, 6, 7, 4, 5, 26, 27, 24, 25, 30, + 31, 28, 29, 18, 19, 16, 17, 22, 23, 20, + 21, 42, 43, 40, 41, 46, 47, 44, 45, 16, + 68, 69, 142, 143, 140, 141, 154, 155, 152, 153, + 158, 159, 156, 157, 146, 147, 144, 145, 150, 151, + 148, 149, 234, 235, 232, 233, 238, 239, 236, 237, + 226, 227, 224, 225, 230, 231, 228, 229, 250, 251, + 248, 249, 254, 255, 252, 253, 242, 243, 240, 241 +}; + +const uint8_t lutMeters_Len[] = { + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, + 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 +}; + +const float lutHectometers_Value[] = { 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f }; +const uint16_t lutHectometers_Code[] = { 0, 1, 6, 7, 4, 5, 6, 7, 4, 5 }; +const uint8_t lutHectometers_Len[] = { 3, 3, 3, 3, 3, 3, 4, 4, 4, 4 }; + +const float lutKilometers_Value[] = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f }; +const uint16_t lutKilometers_Code[] = { 2, 3, 1, 0, 7, 5, 4, 13, 25, 24 }; +const uint8_t lutKilometers_Len[] = { 2, 3, 3, 3, 3, 4, 4, 4, 5, 5 }; + +const float lutCentimeters_Value[] = { + 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, + 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f, 18.0f, 19.0f, + 20.0f, 21.0f, 22.0f, 23.0f, 24.0f, 25.0f, 26.0f, 27.0f, 28.0f, 29.0f, + 30.0f, 31.0f, 32.0f, 33.0f, 34.0f, 35.0f, 36.0f, 37.0f, 38.0f, 39.0f, + 40.0f, 41.0f, 42.0f, 43.0f, 44.0f, 45.0f, 46.0f, 47.0f, 48.0f, 49.0f, + 50.0f, 51.0f, 52.0f, 53.0f, 54.0f, 55.0f, 56.0f, 57.0f, 58.0f, 59.0f, + 60.0f, 61.0f, 62.0f, 63.0f, 64.0f, 65.0f, 66.0f, 67.0f, 68.0f, 69.0f, + 70.0f, 71.0f, 72.0f, 73.0f, 74.0f, 75.0f, 76.0f, 77.0f, 78.0f, 79.0f, + 80.0f, 81.0f, 82.0f, 83.0f, 84.0f, 85.0f, 86.0f, 87.0f, 88.0f, 89.0f, + 90.0f, 91.0f, 92.0f, 93.0f, 94.0f, 95.0f, 96.0f, 97.0f, 98.0f, 99.0f +}; + +const uint16_t lutCentimeters_Code[] = { + 50, 51, 48, 49, 54, 55, 52, 53, 42, 43, + 40, 41, 46, 47, 44, 45, 34, 35, 32, 33, + 38, 39, 36, 37, 58, 59, 56, 57, 62, 63, + 60, 61, 50, 51, 48, 49, 54, 55, 52, 53, + 10, 11, 8, 9, 14, 15, 12, 13, 2, 3, + 0, 1, 6, 7, 4, 5, 26, 27, 24, 25, + 30, 31, 28, 29, 18, 19, 16, 17, 22, 23, + 20, 21, 42, 43, 40, 41, 46, 47, 44, 45, + 34, 35, 32, 33, 38, 39, 36, 37, 122, 123, + 120, 121, 126, 127, 124, 125, 58, 59, 56, 57 +}; + +const uint8_t lutCentimeters_Len[] = { + 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, + 7, 7, 7, 7, 7, 7, 6, 6, 6, 6 +}; + +const float lutAbsorption_Value[] = { 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f }; +const uint16_t lutAbsorption_Code[] = { 6, 4, 5, 6, 7, 7, 4, 5, 2, 3, 0 }; +const uint8_t lutAbsorption_Len[] = { 3, 3, 3, 4, 4, 3, 4, 4, 4, 4, 3 }; + /*------------------------------------------------------------------------------------------* * Default frequency grids *------------------------------------------------------------------------------------------*/ @@ -302,7 +412,7 @@ const float defaultFrequencyGrid_8[] = { *-----------------------------------------------------------------------------------------*/ static ivas_error read_bits( RenderConfigReader *this, /* i/o : Renderer config reader handle */ - uint32_t *pTarget, /* i/o : Target read data pointer */ + uint32_t *pTarget, /* o : Target read data pointer */ const size_t nBits /* i : Number of bits to read */ ) { @@ -320,6 +430,7 @@ static ivas_error read_bits( return IVAS_ERR_INVALID_RENDER_CONFIG; } + *pTarget = 0; for ( n = 0; n < nBits; n++ ) { nByte = ( this->readOffset + n ) >> 3; @@ -341,7 +452,6 @@ static ivas_error read_bool( uint32_t *pResult /* o : Target read data pointer */ ) { - *pResult = false; return read_bits( this, pResult, 1 ); } @@ -403,10 +513,14 @@ static ivas_error read_code_word( uint8_t size; uint8_t n; uint32_t code; + uint32_t bits; + uint32_t nr_bits; uint8_t len; minLen = 255; maxLen = 0; + bits = 0; + nr_bits = 0; code = 0; if ( pResult == NULL ) @@ -471,6 +585,36 @@ static ivas_error read_code_word( pLengths = lutDsr_Len; size = sizeof lutDsr_Len / sizeof( uint8_t ); break; + case RC_LUT_METERS: + pValues = lutMeters_Value; + pCodes = lutMeters_Code; + pLengths = lutMeters_Len; + size = sizeof lutMeters_Len / sizeof( uint8_t ); + break; + case RC_LUT_HECTOMETERS: + pValues = lutHectometers_Value; + pCodes = lutHectometers_Code; + pLengths = lutHectometers_Len; + size = sizeof lutHectometers_Len / sizeof( uint8_t ); + break; + case RC_LUT_KILOMETERS: + pValues = lutKilometers_Value; + pCodes = lutKilometers_Code; + pLengths = lutKilometers_Len; + size = sizeof lutKilometers_Len / sizeof( uint8_t ); + break; + case RC_LUT_CENTIMETERS: + pValues = lutCentimeters_Value; + pCodes = lutCentimeters_Code; + pLengths = lutCentimeters_Len; + size = sizeof lutCentimeters_Len / sizeof( uint8_t ); + break; + case RC_LUT_ABSORPTION: + pValues = lutAbsorption_Value; + pCodes = lutAbsorption_Code; + pLengths = lutAbsorption_Len; + size = sizeof lutAbsorption_Len / sizeof( uint8_t ); + break; case RC_LUT_INVALID: default: return IVAS_ERR_INVALID_RENDER_CONFIG; @@ -484,11 +628,12 @@ static ivas_error read_code_word( } for ( len = minLen; len <= maxLen; len++ ) { - if ( ( error = read_bits( this, &code, ( len == minLen ) ? minLen : 1 ) ) != IVAS_ERR_OK ) + nr_bits = ( len == minLen ) ? minLen : 1; + if ( ( error = read_bits( this, &bits, nr_bits ) ) != IVAS_ERR_OK ) { return error; } - + code = ( code << nr_bits ) | bits; for ( n = 0; n < size; n++ ) { if ( code == pCodes[n] && len == pLengths[n] ) @@ -672,6 +817,105 @@ static ivas_error get_dsr( return IVAS_ERR_OK; } +/*-----------------------------------------------------------------------------------------* + * Function get_distance() + * Gets a distance value (in meters) + *-----------------------------------------------------------------------------------------*/ + +static ivas_error get_distance( + RenderConfigReader *this, /* i/o : Render config reader handle */ + uint16_t isSmall, /* i : Flag indicating a small distance */ + float *pResult /* o : Distance value */ +) +{ + ivas_error error; + float value; + uint32_t flag; + + if ( ( error = read_code_word( this, RC_LUT_METERS, pResult ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( isSmall == false ) + { + /* addHectometers flag */ + if ( ( error = read_bool( this, &flag ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( flag == true ) + { + /* Hectometers */ + if ( ( error = read_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 ) + { + return error; + } + + while ( flag == true ) + { + /* Kilometers */ + if ( ( error = read_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 ) + { + return error; + } + } + } + } + + /* addCentimeters flag */ + if ( ( error = read_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 ) + { + return error; + } + *pResult += value * 0.01f; + } + + return IVAS_ERR_OK; +} + +/*-----------------------------------------------------------------------------------------* + * Function get_absorption() + * Gets an absorption value + *-----------------------------------------------------------------------------------------*/ + +static ivas_error get_absorption( + RenderConfigReader *this, /* i/o : Render config reader handle */ + float *pResult /* o : Distance value */ +) +{ + ivas_error error; + + if ( ( error = read_code_word( this, RC_LUT_ABSORPTION, pResult ) ) != IVAS_ERR_OK ) + { + return error; + } + + return IVAS_ERR_OK; +} + #else /*-----------------------------------------------------------------------------------------* * Function read_bool() @@ -964,7 +1208,10 @@ static ivas_error RenderConfigReader_readReverb( { uint32_t file_size; uint32_t value; - uint32_t i, n, m; +#ifdef CONTROL_METADATA_EARLY_REFLECTIONS + uint32_t signx, signy, k; +#endif + uint32_t i, m, n; ivas_error error; float freqHop; uint32_t gridLen; @@ -994,6 +1241,20 @@ static ivas_error RenderConfigReader_readReverb( fread( pRenderConfigReader->pBitstream, sizeof( uint8_t ), file_size, pReverbConfigFile ); pRenderConfigReader->length = file_size; + /****************************/ + /* Read the presence flag */ + /****************************/ + if ( ( error = read_bool( pRenderConfigReader, &value ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Just return in case no acoustic environment data available */ + if ( value == false ) + { + return IVAS_ERR_OK; + } + /****************************/ /* Read the frequency grids */ /****************************/ @@ -1188,6 +1449,9 @@ static ivas_error RenderConfigReader_readReverb( { pRenderConfigReader->pAE[n].pRT60 = 0; pRenderConfigReader->pAE[n].pDSR = 0; +#ifdef CONTROL_METADATA_EARLY_REFLECTIONS + pRenderConfigReader->pAE[n].pEarlyReflections = 0; +#endif } for ( n = 0; n < pRenderConfigReader->nAE; n++ ) @@ -1243,6 +1507,102 @@ static ivas_error RenderConfigReader_readReverb( return IVAS_ERR_INVALID_RENDER_CONFIG; } } + +#ifdef CONTROL_METADATA_EARLY_REFLECTIONS + /* Has early reflections */ + if ( ( error = read_bool( pRenderConfigReader, &value ) ) != IVAS_ERR_OK ) + { + return error; + } + if ( value == true ) + { + if ( ( pRenderConfigReader->pAE[n].pEarlyReflections = (EarlyReflectionsConfig *) malloc( sizeof( EarlyReflectionsConfig ) ) ) == NULL ) + { + return IVAS_ERR_FAILED_ALLOC; + } + + /* Room sizes */ + if ( ( error = get_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 ) + { + return error; + } + if ( ( error = get_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 ) + { + 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_absorption( pRenderConfigReader, &pRenderConfigReader->pAE[n].pEarlyReflections->pAbsCoeff[m][k] ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + + /* Has listener origin */ + if ( ( error = read_bool( pRenderConfigReader, &value ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( value == true ) + { + if ( ( pRenderConfigReader->pAE[n].pEarlyReflections->pListenerOrigin = malloc( sizeof( IVAS_VECTOR3 ) ) ) == NULL ) + { + return IVAS_ERR_FAILED_ALLOC; + } + + if ( ( error = read_bits( pRenderConfigReader, &signx, 1 ) ) != IVAS_ERR_OK ) + { + return error; + } + if ( ( error = read_bits( pRenderConfigReader, &signy, 1 ) ) != IVAS_ERR_OK ) + { + return error; + } + if ( ( error = get_distance( pRenderConfigReader, true, &pRenderConfigReader->pAE[n].pEarlyReflections->pListenerOrigin->x ) ) != IVAS_ERR_OK ) + { + return error; + } + if ( signx == 0 ) + { + pRenderConfigReader->pAE[n].pEarlyReflections->pListenerOrigin->x *= -1.0f; + } + if ( ( error = get_distance( pRenderConfigReader, true, &pRenderConfigReader->pAE[n].pEarlyReflections->pListenerOrigin->y ) ) != IVAS_ERR_OK ) + { + return error; + } + if ( signy == 0 ) + { + pRenderConfigReader->pAE[n].pEarlyReflections->pListenerOrigin->y *= -1.0f; + } + if ( ( error = get_distance( pRenderConfigReader, true, &pRenderConfigReader->pAE[n].pEarlyReflections->pListenerOrigin->z ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } +#endif } /* Cleanup */ @@ -1484,13 +1844,11 @@ ivas_error RenderConfigReader_read( errorHandler( item, ERROR_VALUE_INVALID ); } } -#ifdef DEBUGGING else { fprintf( stderr, "Unsupported configuration property %s\n", item ); } #endif -#endif #ifdef CONTROL_METADATA_REVERB params_idx += params_length; #endif @@ -1581,7 +1939,7 @@ void RenderConfigReader_close( ) { #ifdef CONTROL_METADATA_REVERB - uint16_t n; + uint32_t n; #endif if ( ppRenderConfigReader == NULL || *ppRenderConfigReader == NULL ) @@ -1593,6 +1951,14 @@ void RenderConfigReader_close( /* Free the acoustic environments */ for ( n = 0; n < ( *ppRenderConfigReader )->nAE; n++ ) { +#ifdef CONTROL_METADATA_EARLY_REFLECTIONS + if ( ( *ppRenderConfigReader )->pAE[n].pEarlyReflections != NULL ) + { + free( ( *ppRenderConfigReader )->pAE[n].pEarlyReflections->pListenerOrigin ); + free( ( *ppRenderConfigReader )->pAE[n].pEarlyReflections->pAbsCoeff ); + free( ( *ppRenderConfigReader )->pAE[n].pEarlyReflections ); + } +#endif free( ( *ppRenderConfigReader )->pAE[n].pRT60 ); free( ( *ppRenderConfigReader )->pAE[n].pDSR ); } diff --git a/scripts/reverb/generate_reverb_metadata.py b/scripts/reverb/generate_acoustic_environments_metadata.py similarity index 61% rename from scripts/reverb/generate_reverb_metadata.py rename to scripts/reverb/generate_acoustic_environments_metadata.py index a05bbeb2d8b5e319accc4e4d20dff3f6028d64e8..9fc9c6a3ca6f010d4fac034978a40183e8d97053 100644 --- a/scripts/reverb/generate_reverb_metadata.py +++ b/scripts/reverb/generate_acoustic_environments_metadata.py @@ -117,9 +117,9 @@ def get_duration_code(duration): '110100000', '111010', '110100001', '111011', '110100110', '111000', '110100111', '111001', '110100100', '111110', '110100101', '111111', '110111010', '111100', '110111011', '111101', '110111000', '11000', '110111001' ] - duration_dus = int(round(np.float32(duration) * np.float32(100000))) # [deca us] + duration_dus = round(np.float32(duration) * np.float32(100000)) # [deca us] if print_cfg: - print('duration: ', duration_dus) + print('duration: ', duration_dus, 'dus') dus = duration_dus # [deca us] s = dus // 100000 # 0, 1, ... 30 [s] @@ -168,7 +168,7 @@ def get_frequency_code(f): assert 16 <= f <= 40000 if f in frequencyCode.keys(): if print_cfg: - print('frequency:', f) + print('frequency:', f, 'Hz') return frequencyCode[f] + '0' else: # exact frequency not found, use frequency refinement to aproximate @@ -185,27 +185,24 @@ def get_frequency_code(f): if refinement >= 16: # choose next higer frequency if print_cfg: - print('frequency:', list(frequencyCode)[f_high]) + print('frequency:', list(frequencyCode)[f_high], 'Hz') return frequencyCode[f_high] + '0' else: if print_cfg: - print('frequency:', list(frequencyCode)[f_low], ', refined: ', f_low * 2 ** ((refinement + 1) / 51)) + print('frequency:', list(frequencyCode)[f_low], ', Hz, refined: ', f_low * 2 ** ((refinement + 1) / 51), 'Hz') return frequencyCode[f_low] + '1' + format(refinement, '04b') def get_frequency_hop_code(index): - assert 0 <= index < 9 + assert 0 <= index < 7 return [ - '1100', # 2^(1/8) - '1101', # 2^(1/7) - '0010', # 2^(1/6) - '0011', # 2^(1/5) - '0000', # 2^(1/4) - '01', # 2^(1/3) - '0001', # 2^(1/2) - '10', # 2^1 - '111'][index] # 2^2 - + '0010', # 2^(1/12) + '0011', # 2^(1/6) + '0000', # 2^(1/4) + '01', # 2^(1/3) + '0001', # 2^(1/2) + '11', # 2^1 + '10'][index] # 2^2 def get_dsr_code(dsr): @@ -241,6 +238,93 @@ class fgdMethod(Enum): Default_Banding = '10' +def get_distance_code(distance, isSmallScene = True): + # 0, 1, ... 99 + metersCode = [ + '111101', '110010', '110011', '110000', '110001', '110110', '110111', '110100', '110101', '001010', + '001011', '001000', '001001', '001110', '001111', '001100', '001101', '000010', '000011', '000000', + '000001', '000110', '000111', '000100', '000101', '011010', '011011', '011000', '011001', '011110', + '011111', '011100', '011101', '010010', '010011', '010000', '010001', '010110', '010111', '010100', + '010101', '101010', '101011', '101000', '101001', '101110', '101111', '101100', '101101', '10000', + '1000100', '1000101', '10001110', '10001111', '10001100', '10001101', '10011010', '10011011', '10011000', '10011001', + '10011110', '10011111', '10011100', '10011101', '10010010', '10010011', '10010000', '10010001', '10010110', '10010111', + '10010100', '10010101', '11101010', '11101011', '11101000', '11101001', '11101110', '11101111', '11101100', '11101101', + '11100010', '11100011', '11100000', '11100001', '11100110', '11100111', '11100100', '11100101', '11111010', '11111011', + '11111000', '11111001', '11111110', '11111111', '11111100', '11111101', '11110010', '11110011', '11110000', '11110001' ] + + # 0, 1, ... 9 + hectometersCode = [ + '000', '001', '110', '111', '100', '101', '0110', '0111', '0100', '0101' ] + + # 1, 2, ... 10 + kilometersCode = [ + '10', '011', '001', '000', '111', '0101', '0100', '1101', '11001', '11000' ] + + # 0, 1, ... 99 + centimetersCode = [ + '110010', '110011', '110000', '110001', '110110', '110111', '110100', '110101', '0101010', '0101011', + '0101000', '0101001', '0101110', '0101111', '0101100', '0101101', '0100010', '0100011', '0100000', '0100001', + '0100110', '0100111', '0100100', '0100101', '0111010', '0111011', '0111000', '0111001', '0111110', '0111111', + '0111100', '0111101', '0110010', '0110011', '0110000', '0110001', '0110110', '0110111', '0110100', '0110101', + '0001010', '0001011', '0001000', '0001001', '0001110', '0001111', '0001100', '0001101', '0000010', '0000011', + '0000000', '0000001', '0000110', '0000111', '0000100', '0000101', '0011010', '0011011', '0011000', '0011001', + '0011110', '0011111', '0011100', '0011101', '0010010', '0010011', '0010000', '0010001', '0010110', '0010111', + '0010100', '0010101', '101010', '101011', '101000', '101001', '101110', '101111', '101100', '101101', + '100010', '100011', '100000', '100001', '100110', '100111', '100100', '100101', '1111010', '1111011', + '1111000', '1111001', '1111110', '1111111', '1111100', '1111101', '111010', '111011', '111000', '111001' ] + + distance_cm = round(np.float32(distance) * np.float32(100)) # distance in cm + if print_cfg: + print('distance: ', distance_cm, 'cm') + + cm = distance_cm # [cm] + m = cm // 100 # [m] + hm = m // 100 # [hm] + km = hm // 10 # [km] + + cm = (cm % 100) # 0, 1, ... 99 [cm] + m = (m % 100) # 0, 1, ... 99 [m] + hm = (hm % 10) # 0, 1, ... 9 [hm] + + assert 0 <= cm <= 99 + assert 0 <= m <= 99 + assert 0 <= hm <= 9 + assert distance_cm == km * 100000 + hm * 10000 + m * 100 + cm + + code = metersCode[m] + + if isSmallScene: + assert(hm == km == 0) + else: + # large scenes + if hm > 0 or km > 0: + # hectometers + code += '1' + hectometersCode[hm] + while km > 0: + # kilometers + code += '1' + kilometersCode[min(km, 10) - 1] + km = km - 10 + code += '0' + else: + code += '0' + + # centimeters + if cm > 0: + code += '1' + centimetersCode[cm] + else: + code += '0' + + return code + + +def get_absorption_code(absorption): + assert 0.0 <= absorption <= 1.0 + + index = round(absorption * 10.0) + + return ['110', '100', '101', '0110', '0111', '111', '0100', '0101', '0010', '0011', '000' ][index] + + # apply function to elements of list and concatenate the resulting strings def concatenate(function, data): return ''.join([function(d) for d in data]) @@ -251,12 +335,12 @@ def test(): string = '' # count or index encoding - string += concatenate(get_count_or_index_code, [n for n in range(0, 16 * 64)]) + string += concatenate(get_count_or_index_code, [n for n in range(16 * 64)]) # duration encoding - string += concatenate(get_duration_code, [d / 1000 for d in range(0, 30 * 1000)]) - string += concatenate(get_duration_code, [d / 10000 for d in range(0, 30 * 1000)]) - string += concatenate(get_duration_code, [d / 100000 for d in range(0, 30 * 1000)]) + string += concatenate(get_duration_code, [d / 1000 for d in range(30 * 1000)]) + string += concatenate(get_duration_code, [d / 10000 for d in range(30 * 1000)]) + string += concatenate(get_duration_code, [d / 100000 for d in range(30 * 1000)]) # frequency encoding string += concatenate(get_frequency_code, @@ -266,11 +350,20 @@ def test(): 16000, 20000, 25000, 31500, 40000]) # frequency hop encoding - string += concatenate(get_frequency_hop_code, [index for index in range(0, 9)]) + string += concatenate(get_frequency_hop_code, [index for index in range(7)]) # DSR encoding string += concatenate(get_dsr_code, [math.pow(10, dsr / 10) for dsr in range(-150, -10 + 1)]) + # distance encoding + string += concatenate(lambda d : get_distance_code(d, False), [d for d in range(20 * 1000)]) + string += concatenate(lambda d : get_distance_code(d, False), [d / 10 for d in range(20 * 1000)]) + string += concatenate(lambda d : get_distance_code(d, False), [d / 100 for d in range(20 * 1000)]) + string += concatenate(lambda d : get_distance_code(d, True), [d / 100 for d in range(10 * 1000)]) + + # absorption encoding + string += concatenate(get_absorption_code, [a / 100 for a in range(100 + 1)]) + data = bitarray(string, endian='big') file = open('test_python.dat', 'wb') @@ -282,7 +375,8 @@ def generate_reverb_payload_equivalent_to_rend_config_renderer_cfg(): # based on config_renderer.cfg # note that because of encoding, resolution is lost and behaviour may not be bit-exact compared to .cfg file based values data = bitarray( - get_count_or_index_code(1) # fgdNrGrids + '1' # hasAcEnv + + get_count_or_index_code(1) # fgdNrGrids + fgdMethod.Individual_Frequencies.value # fgdMethod + get_count_or_index_code(31) # fgdNrBands @@ -308,19 +402,137 @@ def generate_reverb_payload_equivalent_to_rend_config_renderer_cfg(): 3.702e-07, 6.1341e-07, 7.1432e-07, 6.5331e-07, 4.6094e-07, 5.4683e-07, 7.0134e-07, 6.856e-07, 7.114e-07, 6.9604e-07, 5.2939e-07, 5.699e-07, 6.1773e-07, 5.7488e-07, 4.7748e-07, 2.7213e-07, 1.3681e-07, 1.0941e-07, 6.2001e-08, 2.8483e-08, 2.6267e-08 ]) - + + '0' # hasEarlyReflections , endian='big') file = open('rend_config_renderer.dat', 'wb') data.tofile(file) file.close() +def generate_reverb_payload_equivalent_to_rend_config_renderer_cfg_plus_early_reflections_no_listener_origin(): + # based on config_renderer.cfg + # note that because of encoding, resolution is lost and behaviour may not be bit-exact compared to .cfg file based values + data = bitarray( + '1' # hasAcEnv + + get_count_or_index_code(2) # fgdNrGrids + # frequency grid #1 + + fgdMethod.Individual_Frequencies.value # fgdMethod + + get_count_or_index_code(1) # fgdNrBands + + + concatenate(get_frequency_code, # fgdCenterFreq + [ 10000.0 ]) + + # frequency grid #2 + + fgdMethod.Individual_Frequencies.value # fgdMethod + + get_count_or_index_code(31) # fgdNrBands + + + concatenate(get_frequency_code, # fgdCenterFreq + [ 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 ]) + + + get_count_or_index_code(1) # AcousticEnvCount + + get_id_code(0) # ID + + get_count_or_index_code(1) # FreqGridID + + get_duration_code(0.1) # (input)Predelay + + + concatenate(get_duration_code, # 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 ]) + + + concatenate(get_dsr_code, # DSR + [ 1.8811e-08, 2.1428e-08, 1.3972e-08, 1.51e-08, 1.287e-08, 1.8747e-08, 2.413e-08, 3.9927e-08, 8.9719e-08, 1.902e-07, + 3.702e-07, 6.1341e-07, 7.1432e-07, 6.5331e-07, 4.6094e-07, 5.4683e-07, 7.0134e-07, 6.856e-07, 7.114e-07, 6.9604e-07, + 5.2939e-07, 5.699e-07, 6.1773e-07, 5.7488e-07, 4.7748e-07, 2.7213e-07, 1.3681e-07, 1.0941e-07, 6.2001e-08, 2.8483e-08, + 2.6267e-08 ]) + + + '1' # hasEarlyReflections + + concatenate(lambda d : get_distance_code(d, True), + [ 3.0, 4.0, 2.5 ]) # room dimensions + + + get_count_or_index_code(0) # FreqGridID + + concatenate(get_absorption_code, # absorptionCode + [ 0.8, 0.8, 0.8, 0.8, 0.2, 0.6 ]) + + + '0' # listener origin flag + + , endian='big') + + file = open('rend_config_renderer_cfg_plus_early_reflections_no_listener_origin.dat', 'wb') + data.tofile(file) + file.close() + + +def generate_reverb_payload_equivalent_to_rend_config_renderer_cfg_plus_early_reflections_listener_origin(): + # based on config_renderer.cfg + # note that because of encoding, resolution is lost and behaviour may not be bit-exact compared to .cfg file based values + data = bitarray( + '1' # hasAcEnv + + get_count_or_index_code(2) # fgdNrGrids + # frequency grid #1 + + fgdMethod.Individual_Frequencies.value # fgdMethod + + get_count_or_index_code(1) # fgdNrBands + + + concatenate(get_frequency_code, # fgdCenterFreq + [ 10000.0 ]) + + # frequency grid #2 + + fgdMethod.Individual_Frequencies.value # fgdMethod + + get_count_or_index_code(31) # fgdNrBands + + + concatenate(get_frequency_code, # fgdCenterFreq + [ 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 ]) + + + get_count_or_index_code(1) # AcousticEnvCount + + get_id_code(0) # ID + + get_count_or_index_code(1) # FreqGridID + + get_duration_code(0.1) # (input)Predelay + + + concatenate(get_duration_code, # 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 ]) + + + concatenate(get_dsr_code, # DSR + [ 1.8811e-08, 2.1428e-08, 1.3972e-08, 1.51e-08, 1.287e-08, 1.8747e-08, 2.413e-08, 3.9927e-08, 8.9719e-08, 1.902e-07, + 3.702e-07, 6.1341e-07, 7.1432e-07, 6.5331e-07, 4.6094e-07, 5.4683e-07, 7.0134e-07, 6.856e-07, 7.114e-07, 6.9604e-07, + 5.2939e-07, 5.699e-07, 6.1773e-07, 5.7488e-07, 4.7748e-07, 2.7213e-07, 1.3681e-07, 1.0941e-07, 6.2001e-08, 2.8483e-08, + 2.6267e-08 ]) + + + '1' # hasEarlyReflections + + concatenate(lambda code : get_distance_code(code, True), + [ 3.0, 4.0, 2.5 ]) # room dimensions + + + get_count_or_index_code(0) # FreqGridID + + concatenate(get_absorption_code, # absorptionCode + [ 0.8, 0.8, 0.8, 0.8, 0.2, 0.6 ]) + + + '1' # listener origin flag + + '1' # is possitive x + + '0' # is possitive y + + concatenate(lambda d : get_distance_code(d, True), + [ 0.5, 0.5, 1.5 ]) # listener origin (x, y, z) + + , endian='big') + + file = open('rend_config_renderer_cfg_plus_early_reflections_listener_origin.dat', 'wb') + data.tofile(file) + file.close() + def generate_reverb_payload_equivalent_to_rend_config_hospital_patientroom_cfg(): # based on config_hospital_patientroom.cfg # note that because of encoding, resolution is lost and behaviour may not be bit-exact compared to .cfg file based values data = bitarray( - get_count_or_index_code(1) # fgdNrGrids + '1' # hasAcEnv + + get_count_or_index_code(1) # fgdNrGrids + fgdMethod.Individual_Frequencies.value # fgdMethod + get_count_or_index_code(31) # fgdNrBands @@ -348,6 +560,8 @@ def generate_reverb_payload_equivalent_to_rend_config_hospital_patientroom_cfg() 6.379496e-06, 6.358105e-06, 6.6696e-06, 6.369334e-06, 6.378474e-06, 3.339913e-06, 3.129318e-06, 2.892564e-06, 6.00202e-07, 3.40124e-07, 3.37705e-07 ]) + + '0' # hasEarlyReflections + , endian='big') file = open('rend_config_hospital_patientroom.dat', 'wb') @@ -359,7 +573,8 @@ def generate_reverb_payload_equivalent_to_rend_config_recreation_cfg(): # based on config_recreation.cfg # note that because of encoding, resolution is lost and behaviour may not be bit-exact compared to .cfg file based values data = bitarray( - get_count_or_index_code(1) # fgdNrGrids + '1' # hasAcEnv + + get_count_or_index_code(1) # fgdNrGrids + fgdMethod.Individual_Frequencies.value # fgdMethod + get_count_or_index_code(31) # fgdNrBands @@ -387,6 +602,8 @@ def generate_reverb_payload_equivalent_to_rend_config_recreation_cfg(): 2.958383e-06, 2.725911e-06, 7.94912e-07, 6.20198e-07, 5.71181e-07, 5.5546e-08, 1.3987e-08, 1.338e-08, 1.322e-09, 1.3e-11, 4e-12 ]) + + '0' # hasEarlyReflections + , endian='big') file = open('rend_config_recreation.dat', 'wb') @@ -398,3 +615,6 @@ def generate_reverb_payload_equivalent_to_rend_config_recreation_cfg(): generate_reverb_payload_equivalent_to_rend_config_renderer_cfg() generate_reverb_payload_equivalent_to_rend_config_hospital_patientroom_cfg() generate_reverb_payload_equivalent_to_rend_config_recreation_cfg() + +#generate_reverb_payload_equivalent_to_rend_config_renderer_cfg_plus_early_reflections_listener_origin() +#generate_reverb_payload_equivalent_to_rend_config_renderer_cfg_plus_early_reflections_no_listener_origin() diff --git a/scripts/testv/rend_config_hospital_patientroom.dat b/scripts/testv/rend_config_hospital_patientroom.dat index 20455a95b70b5cd6781d96aef45502efe5afcc53..dd09f2ddb4c5f05e4e3103b0b6ba701c8bd7a601 100644 --- a/scripts/testv/rend_config_hospital_patientroom.dat +++ b/scripts/testv/rend_config_hospital_patientroom.dat @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a3b4cf6b770f85bc82129901324078afc0953661b3ff753796d7d4bd15d8c468 +oid sha256:84321b26550df78456eea5595f8e7d99cca2b558117cddf117b738f1d8c2e316 size 136 diff --git a/scripts/testv/rend_config_recreation.dat b/scripts/testv/rend_config_recreation.dat index 456eedbbf72def1bb1995fc6e72f6b37e6350149..d17f39b2f1148f59d747bc2df485e72583f958f5 100644 --- a/scripts/testv/rend_config_recreation.dat +++ b/scripts/testv/rend_config_recreation.dat @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6cb9adc877960d2a7e827126c2f44612569e5554e974b5bb98d3be92cb1ee14a -size 149 +oid sha256:6329e3e202458bfae10c8811f4018e8df2c7f2dc8789850ef2d17b72e490f23d +size 150 diff --git a/scripts/testv/rend_config_renderer.dat b/scripts/testv/rend_config_renderer.dat index 6ea8ed4f1dc5dd1b02f2dbd5ef3e05b2dcdd1ee9..979bbf9a875ed6b395d792f9e4ca074e8dce0c1d 100644 --- a/scripts/testv/rend_config_renderer.dat +++ b/scripts/testv/rend_config_renderer.dat @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7941266900de8753e847cfef95298b5ee529e3f8f90ca5421ba46d71bc353821 -size 130 +oid sha256:24a7142edde4f689273970edc73f0ed5c9ac0bbdcc75736ce3c1604e925a6fbf +size 131