diff --git a/Workspace_msvc/lib_rend.vcxproj b/Workspace_msvc/lib_rend.vcxproj index 0ec9061cf82ff8774d6641e15ebf4d03f8d03bdc..852cb8f14bc40454a9cb9881ce16996d5991d428 100644 --- a/Workspace_msvc/lib_rend.vcxproj +++ b/Workspace_msvc/lib_rend.vcxproj @@ -239,6 +239,7 @@ + @@ -251,6 +252,7 @@ + diff --git a/lib_com/common_api_types.h b/lib_com/common_api_types.h index 1a2d7d77c3b397d939a67782ef4611ab0a6593a0..3cbc64e52a6e10bd17c97b853ae57853e617a96b 100644 --- a/lib_com/common_api_types.h +++ b/lib_com/common_api_types.h @@ -52,6 +52,9 @@ #define RENDERER_HEAD_POSITIONS_PER_FRAME 4 +#ifdef EARLY_REFLECTIONS +#define QC_ABS_COEFF 6 +#endif /*----------------------------------------------------------------------------------* * Common API structures @@ -184,6 +187,13 @@ typedef struct _IVAS_ROOM_ACOUSTICS_CONFIG float pAcoustic_dsr[IVAS_CLDFB_NO_CHANNELS_MAX]; /* - The room's Diffuse to Source Ratio per center frequency */ float acousticPreDelay; /* Time elapsed between input signal and late reverberation start, float, range [0.001..10] */ float inputPreDelay; /* Offset in seconds from where DSR is computed in the RIR (0 = at source), float, range [0.001..10] */ +#ifdef EARLY_REFLECTIONS + int16_t use_er; /* ER activation flag */ + int32_t lowComplexity; /* Low complexity ER flag */ + IVAS_VECTOR3 dimensions; /* Room dimensions [m] */ + float AbsCoeff[QC_ABS_COEFF]; /* Absorption coeffs */ + IVAS_VECTOR3 ListenerOrigin; /* Listener origin */ +#endif } IVAS_ROOM_ACOUSTICS_CONFIG_DATA; #ifdef SPLIT_REND_WITH_HEAD_ROT diff --git a/lib_com/ivas_cnst.h b/lib_com/ivas_cnst.h index 6d89e222ecc83cd3a1afe3fab60d16aa1f13a001..3d66723ecbcee9509c0913325a6dcc30a6f17e23 100644 --- a/lib_com/ivas_cnst.h +++ b/lib_com/ivas_cnst.h @@ -1891,6 +1891,36 @@ typedef enum #define IVAS_LIMITER_THRESHOLD 32729 /* -0.01 dBFS */ #define IVAS_LIMITER_ATTACK_SECONDS 0.005f + +#ifdef EARLY_REFLECTIONS +/*----------------------------------------------------------------------------------* + * Early Reflection constants + *----------------------------------------------------------------------------------*/ +#define ER_ABS_COEFF 6 +#define ER_MAX_SOURCES 25 +#define ER_REF_ORDER 1 +#define ER_NUM_REF 6 + +#define ER_AIR_COEFF (0.00137f) +#define ER_SOUND_SPEED (343.0f) +#define ER_MIN_WALL_DIST (0.1f) +#define ER_EUCLIDEAN_SCALE (1.29246971E-26f) + +#define ER_DEFAULT_ROOM_L (3.0f) +#define ER_DEFAULT_ROOM_W (4.0f) +#define ER_DEFAULT_ROOM_H (5.0f) +#define ER_RADIUS (1.0f) +#define ER_LIST_ORIGIN_X (0.0f) +#define ER_LIST_ORIGIN_Y (0.0f) +#define ER_LIST_HEIGHT (1.6f) + +#define ER_MIN_ROOM_DIMENSION (1.0f) +#define ER_MAX_ROOM_DIMENSION (999.0f) +#define ER_MIN_ABS_COEFF (0.0f) +#define ER_MAX_ABS_COEFF (1.0f) + +#endif + /*----------------------------------------------------------------------------------* * Stereo downmix EVS constants *----------------------------------------------------------------------------------*/ diff --git a/lib_com/ivas_error.h b/lib_com/ivas_error.h index 22dbfe69816739f816da2664fdcbb66e580353a0..09309416083b633297ad388dd347bc287e2fa2ee 100644 --- a/lib_com/ivas_error.h +++ b/lib_com/ivas_error.h @@ -138,6 +138,9 @@ typedef enum #ifdef CONTROL_METADATA_REVERB IVAS_ERR_INVALID_RENDER_CONFIG, IVAS_ERR_ACOUSTIC_ENVIRONMENT_MISSING, +#ifdef EARLY_REFLECTIONS + IVAS_ERR_INVALID_ER_PARAM, +#endif #ifdef CONTROL_METADATA_DIRECTIVITY IVAS_ERR_DIRECTIVITY_PATTERN_ID_MISSING, #endif diff --git a/lib_dec/lib_dec.c b/lib_dec/lib_dec.c index e88e6edd1b3c49df23b8ff2e705dc7af067eb7fd..4b2678ad4c4abe52754ed29d8e4e8508a1af87d2 100644 --- a/lib_dec/lib_dec.c +++ b/lib_dec/lib_dec.c @@ -1637,6 +1637,11 @@ ivas_error IVAS_DEC_GetRenderConfig( hRCout->split_rend_config.rendererSelection = hRCin->split_rend_config.rendererSelection; #endif +#ifdef EARLY_REFLECTIONS + hRCout->room_acoustics.use_er = hRCin->roomAcoustics.use_er; + hRCout->room_acoustics.lowComplexity = hRCin->roomAcoustics.lowComplexity; +#endif + return IVAS_ERR_OK; } @@ -1678,6 +1683,20 @@ ivas_error IVAS_DEC_FeedRenderConfig( hRenderConfig->roomAcoustics.nBands = renderConfig.room_acoustics.nBands; hRenderConfig->roomAcoustics.acousticPreDelay = renderConfig.room_acoustics.acousticPreDelay; hRenderConfig->roomAcoustics.inputPreDelay = renderConfig.room_acoustics.inputPreDelay; + +#ifdef EARLY_REFLECTIONS + hRenderConfig->roomAcoustics.use_er = 0; + if ( renderConfig.room_acoustics.use_er == 1 ) + { + hRenderConfig->roomAcoustics.use_er = renderConfig.room_acoustics.use_er; + hRenderConfig->roomAcoustics.lowComplexity = renderConfig.room_acoustics.lowComplexity; + hRenderConfig->roomAcoustics.dimensions = renderConfig.room_acoustics.dimensions; + hRenderConfig->roomAcoustics.ListenerOrigin = renderConfig.room_acoustics.ListenerOrigin; + + mvr2r( renderConfig.room_acoustics.AbsCoeff, hRenderConfig->roomAcoustics.AbsCoeff, ER_ABS_COEFF ); + } +#endif + mvr2r( renderConfig.room_acoustics.pFc_input, hRenderConfig->roomAcoustics.pFc_input, CLDFB_NO_CHANNELS_MAX ); mvr2r( renderConfig.room_acoustics.pAcoustic_rt60, hRenderConfig->roomAcoustics.pAcoustic_rt60, CLDFB_NO_CHANNELS_MAX ); mvr2r( renderConfig.room_acoustics.pAcoustic_dsr, hRenderConfig->roomAcoustics.pAcoustic_dsr, CLDFB_NO_CHANNELS_MAX ); diff --git a/lib_dec/rom_dec.c b/lib_dec/rom_dec.c index 6f0751dc56a154317a734c8617baa807e1e25300..ea78271f9ecef30d88055dbeb2b2fcecd6eb8d6f 100644 --- a/lib_dec/rom_dec.c +++ b/lib_dec/rom_dec.c @@ -247,5 +247,4 @@ const float w_hamm_sana16k_2[L_PROT_HAMM_LEN2_16k] = const float h_high3_32[L_FIR_FER2] = {-0.0517f, -0.0587f, -0.0820f, -0.1024f, -0.1164f, 0.8786f, -0.1164f, -0.1024f, -0.0820f, -0.0587f, -0.0517f}; const float h_high3_16[L_FIR_FER2] = { 0.f, -0.0205f, -0.0651f, -0.1256f, -0.1792f, 0.8028f, -0.1792f, -0.1256f, -0.0651f, -0.0205f, 0.f }; - /* clang-format on */ diff --git a/lib_dec/rom_dec.h b/lib_dec/rom_dec.h index 604bfc2fe0ce9ef7ad37db1daad5d009a5bf0ee8..4905ef8f3ab2c35b294a2f73fbe7fe4075da4f58 100644 --- a/lib_dec/rom_dec.h +++ b/lib_dec/rom_dec.h @@ -71,5 +71,4 @@ extern const float w_hamm_sana48k_2[L_PROT_HAMM_LEN2_48k]; extern const float h_high3_32[L_FIR_FER2]; extern const float h_high3_16[L_FIR_FER2]; - #endif diff --git a/lib_rend/ivas_crend.c b/lib_rend/ivas_crend.c index e33304356017dc0b89a9cbfdb1cc05dc2b83b518..33ca0ed1899a10b6919489ce8bb672b582ff1019 100644 --- a/lib_rend/ivas_crend.c +++ b/lib_rend/ivas_crend.c @@ -898,6 +898,195 @@ static ivas_error ivas_rend_initCrend( return IVAS_ERR_OK; } +#ifdef EARLY_REFLECTIONS +/*------------------------------------------------------------------------- + * ivas_shoebox_data_init() + * + * Initialize shoebox_data_t handle + *------------------------------------------------------------------------*/ + +static ivas_error ivas_shoebox_data_init( + shoebox_data_t *hShoeboxData /* i/o: shoebox_data_t handle */ +) +{ + int16_t i; + + if ( hShoeboxData == NULL ) + { + return IVAS_ERR_WRONG_PARAMS; + } + + for ( i = 0; i < 150; i++ ) + { + hShoeboxData->data[i] = 0.0f; + } + for ( i = 0; i < 1; i++ ) + { + hShoeboxData->size[i] = 0; + } + + return IVAS_ERR_OK; +} + +/*------------------------------------------------------------------------- + * ivas_shoebox_output_init() + * + * Initialize shoebox_output_t handle + *------------------------------------------------------------------------*/ + +static ivas_error ivas_shoebox_output_init( + shoebox_output_t *hShoeboxOutput /* i/o: shoebox_output_t handle */ +) +{ + if ( hShoeboxOutput == NULL ) + { + return IVAS_ERR_WRONG_PARAMS; + } + + hShoeboxOutput->n_sources = 0; + hShoeboxOutput->n_ref = 0; + + ivas_shoebox_data_init( &hShoeboxOutput->times ); + ivas_shoebox_data_init( &hShoeboxOutput->gains ); + ivas_shoebox_data_init( &hShoeboxOutput->az_angle ); + ivas_shoebox_data_init( &hShoeboxOutput->el_angle ); + + return IVAS_ERR_OK; +} + +/*------------------------------------------------------------------------- + * ivas_shoebox_config_init() + * + * Initialize shoebox_config_t handle + *------------------------------------------------------------------------*/ + +static ivas_error ivas_shoebox_config_init( + shoebox_config_t *hShoeboxConfig /* i/o: shoebox_config_t handle */ +) +{ + int16_t i; + + if ( hShoeboxConfig == NULL ) + { + return IVAS_ERR_WRONG_PARAMS; + } + + hShoeboxConfig->room_L = 0.0f; + hShoeboxConfig->room_W = 0.0f; + hShoeboxConfig->room_H = 0.0f; + + for ( i = 0; i < ER_ABS_COEFF; i++ ) + { + hShoeboxConfig->abs_coeff[i] = 0.0f; + } + for ( i = 0; i < 3; i++ ) + { + hShoeboxConfig->list_orig[i] = 0.0f; + } + + return IVAS_ERR_OK; +} + +/*------------------------------------------------------------------------- + * ivas_shoebox_obj_init() + * + * Initialize shoebox_obj_t handle + *------------------------------------------------------------------------*/ + +static ivas_error ivas_shoebox_obj_init( + shoebox_obj_t *hShoeboxObj /* i/o: shoebox_obj_t handle */ +) +{ + int16_t i; + + if ( hShoeboxObj == NULL ) + { + return IVAS_ERR_WRONG_PARAMS; + } + + hShoeboxObj->isCartesian = 0; + hShoeboxObj->isRelative = 0; + hShoeboxObj->isZHeight = 0; + hShoeboxObj->isRadians = 0; + hShoeboxObj->MAX_SOURCES = 0; + hShoeboxObj->max_bands = 0; + hShoeboxObj->REF_ORDER = 0; + + for ( i = 0; i < 75; i++ ) + { + hShoeboxObj->src_pos[i] = 0.0f; + } + for ( i = 0; i < 25; i++ ) + { + hShoeboxObj->src_dist[i] = 0.0f; + } + for ( i = 0; i < 3; i++ ) + { + hShoeboxObj->list_pos[i] = 0.0f; + } + + hShoeboxObj->nSrc = 0; + hShoeboxObj->radius = 0.0f; + hShoeboxObj->min_wall_dist = 0.0f; + hShoeboxObj->soundspeed = 0.0f; + hShoeboxObj->air_coeff = 0.0f; + + ivas_shoebox_config_init( &hShoeboxObj->cal ); + + return IVAS_ERR_OK; +} + +/*------------------------------------------------------------------------- + * ivas_er_init() + * + * Initialize early reflections handle + *------------------------------------------------------------------------*/ + +static ivas_error ivas_er_init( + er_struct_t *reflections /* i/o: early reflections handle */ +) +{ + int16_t i; + + if ( reflections == NULL ) + { + return IVAS_ERR_WRONG_PARAMS; + } + + reflections->mode = AUDIO_CONFIG_INVALID; + reflections->use_er = 0; + reflections->is_ready = 0; + reflections->circ_len = 0; + reflections->circ_insert = 0; + reflections->n_total_reflections = 0; + reflections->is_cartesian = 0; + reflections->is_relative = 0; + reflections->max_frame_size = 0; + reflections->output_Fs = 0.0f; + + for ( i = 0; i < 75; i++ ) + { + reflections->source_positions[i] = 0.0f; + } + for ( i = 0; i < 3; i++ ) + { + reflections->user_origin[i] = 0.0f; + if ( i == 2 ) + { + reflections->user_origin[i] = ER_LIST_HEIGHT; + } + } + + reflections->circ_buffers = NULL; + reflections->closest_ch_idx = NULL; + + ivas_shoebox_output_init( &reflections->shoebox_data ); + ivas_shoebox_obj_init( &reflections->shoebox_lib ); + + return IVAS_ERR_OK; +} +#endif + /*------------------------------------------------------------------------- * ivas_rend_initCrendWrapper() * @@ -957,6 +1146,9 @@ ivas_error ivas_rend_initCrendWrapper( hCrend->freq_buffer_re_diffuse = NULL; hCrend->freq_buffer_im_diffuse = NULL; hCrend->hReverb = NULL; +#ifdef EARLY_REFLECTIONS + hCrend->reflections = NULL; +#endif hCrend->delay_line_rw_index = 0; hCrend->diffuse_delay_line_rw_index = 0; hCrend->hTrack = NULL; @@ -1139,6 +1331,39 @@ ivas_error ivas_rend_openCrend( { return error; } + +#ifdef EARLY_REFLECTIONS + if ( hRendCfg->roomAcoustics.use_er == 1 ) + { + + /* Allocate memory for reflections */ + hCrend->reflections = (er_struct_t *) malloc( sizeof( er_struct_t ) ); + if ( !hCrend->reflections ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Early Reflections" ); + } + ivas_er_init( hCrend->reflections ); + hCrend->reflections->use_er = hRendCfg->roomAcoustics.use_er; + hCrend->reflections->lowComplexity = hRendCfg->roomAcoustics.lowComplexity; + + /* Set sample rate and frame size */ + hCrend->reflections->output_Fs = (float) output_Fs; + hCrend->reflections->max_frame_size = (int16_t) ( output_Fs / FRAMES_PER_SEC ); + + /* Init Shoebox */ + shoebox_config_init( &hCrend->reflections->shoebox_lib.cal, hRendCfg ); + + /* Init and compute Reflections */ + if ( ( error = er_init( hCrend->reflections, inConfig ) ) != IVAS_ERR_OK ) + { + return error; + }; + } + else + { + hCrend->reflections = NULL; + } +#endif } else { @@ -1246,6 +1471,26 @@ void ivas_rend_closeCrend( ivas_reverb_close( &hCrend->hReverb ); +#ifdef EARLY_REFLECTIONS + if ( hCrend->reflections != NULL ) + { + if ( hCrend->reflections->closest_ch_idx != NULL ) + { + free( hCrend->reflections->closest_ch_idx ); + hCrend->reflections->closest_ch_idx = NULL; + } + + if ( hCrend->reflections->circ_buffers != NULL ) + { + free( hCrend->reflections->circ_buffers ); + hCrend->reflections->circ_buffers = NULL; + } + + free( hCrend->reflections ); + hCrend->reflections = NULL; + } +#endif + free( hCrend ); hCrend = NULL; #ifdef SPLIT_REND_WITH_HEAD_ROT @@ -1513,6 +1758,24 @@ ivas_error ivas_rend_crendProcess( for ( subframe_idx = 0; subframe_idx < MAX_PARAM_SPATIAL_SUBFRAMES; subframe_idx++ ) { +#ifdef EARLY_REFLECTIONS + /* Early Reflections */ + if ( hCrend->reflections != NULL ) + { + if ( hCrend->reflections->use_er == 1 && hCrend->reflections->is_ready == 1 ) + { + if ( ( error = er_process( hCrend->reflections, + subframe_len, + subframe_idx, + output, + inRendConfig ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } +#endif + if ( hDecoderConfig && combinedOrientationEnabled ) { /* Orientation tracking */ @@ -1607,6 +1870,15 @@ ivas_error ivas_rend_crendProcessSubframe( IVAS_REND_AudioConfig outRendConfig; int8_t combinedOrientationEnabled; +#ifdef EARLY_REFLECTIONS + CREND_HANDLE hCrend; +#ifdef SPLIT_REND_WITH_HEAD_ROT + hCrend = pCrend->hCrend[0]; +#else + hCrend = pCrend->hCrend; +#endif +#endif + combinedOrientationEnabled = 0; if ( hCombinedOrientationData != NULL ) { @@ -1667,6 +1939,24 @@ ivas_error ivas_rend_crendProcessSubframe( { subframe_len = hTcBuffer->subframe_nbslots[subframe_idx] * hTcBuffer->n_samples_granularity; +#ifdef EARLY_REFLECTIONS + /* Early Reflections */ + if ( hCrend->reflections != NULL ) + { + if ( hCrend->reflections->use_er == 1 && hCrend->reflections->is_ready == 1 ) + { + if ( ( error = er_process( hCrend->reflections, + subframe_len, + subframe_idx, + output, + inRendConfig ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } +#endif + if ( hDecoderConfig && combinedOrientationEnabled ) { /* Rotation in SHD for: diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h index 50b363f192697fbbb2d5d216ec8053579ed19c9f..2ae5be6759580733454a932db3f87a7a4342c167 100644 --- a/lib_rend/ivas_prot_rend.h +++ b/lib_rend/ivas_prot_rend.h @@ -1204,6 +1204,69 @@ void ivas_reverb_get_hrtf_set_properties( ); +#ifdef EARLY_REFLECTIONS +/*---------------------------------------------------------------------------------* + * Shoebox Prototypes + *-----------------------------------------------------------------------------------*/ + +void shoebox_config_init( + shoebox_config_t *cal, + RENDER_CONFIG_HANDLE pConfig +); + +void shoebox_get_config( + const shoebox_obj_t *obj, + shoebox_config_t *s +); + +void shoebox_init( + shoebox_obj_t *obj, + shoebox_config_t *cal +); + +void shoebox_set_scene ( + shoebox_obj_t *obj, + shoebox_output_t *ER_PARAMS, + const float list_pos[3], + const float src_pos_data[], + uint16_t isCartesian, + uint16_t isRelative +); +#endif + +#ifdef EARLY_REFLECTIONS +/*---------------------------------------------------------------------------------* + * Reflections compute and process Prototypes + *-----------------------------------------------------------------------------------*/ + +ivas_error er_init( + er_struct_t *reflections, + AUDIO_CONFIG inConfig +); + +ivas_error er_set_reflections_mode( + er_struct_t *reflections, + AUDIO_CONFIG mode +); + +ivas_error er_compute_reflections( + er_struct_t *reflections +); + +ivas_error er_encoder_init( + er_struct_t *reflections +); + +ivas_error er_process( + er_struct_t *reflections, + int16_t frame_size, + int16_t subframe_idx, + float **io, + IVAS_REND_AudioConfig inConfig +); + +#endif + /*---------------------------------------------------------------------------------* * Rotation Prototypes *-----------------------------------------------------------------------------------*/ @@ -1225,7 +1288,9 @@ void Euler2Quat( float deg2rad( float degrees ); - +#ifdef EARLY_REFLECTIONS +float rad2deg( float radians ); +#endif void QuatToRotMat( const IVAS_QUATERNION quat, /* i : quaternion describing the rotation */ diff --git a/lib_rend/ivas_reflections.c b/lib_rend/ivas_reflections.c new file mode 100644 index 0000000000000000000000000000000000000000..bfeaf87ff0126dbe74862b36886c9f9196a6c009 --- /dev/null +++ b/lib_rend/ivas_reflections.c @@ -0,0 +1,548 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include "options.h" + +#ifdef EARLY_REFLECTIONS + +#include +#include +#include "prot.h" +#include "rom_dec.h" +#include "lib_rend.h" +#include "ivas_prot_rend.h" +#include "ivas_stat_rend.h" +#include "ivas_cnst.h" +#include "ivas_prot.h" +#include "ivas_rom_com.h" +#include "wmc_auto.h" +#ifdef DEBUGGING +#include "debug.h" +#endif + +uint16_t LC_mixing_5_1[5] = { 0, 1, 2, 0, 1 }; +uint16_t LC_mixing_7_1[7] = { 0, 1, 2, 3, 4, 3, 4 }; +uint16_t LC_mixing_5_1_2[7] = { 0, 1, 2, 3, 4, 0, 1 }; +uint16_t LC_mixing_5_1_4[9] = { 0, 1, 2, 3, 4, 0, 1, 2, 3 }; +uint16_t LC_mixing_7_1_4[11] = { 0, 1, 2, 3, 4, 3, 4, 0, 1, 2, 3 }; + +/*-----------------------------------------------------------------------------------------* + * Function er_init + * + * Initializes the reflections data structure according to the requested input config. + *-----------------------------------------------------------------------------------------*/ + + +ivas_error er_init( + er_struct_t *reflections, + AUDIO_CONFIG mode ) +{ + ivas_error error; + IVAS_REND_AudioConfig outRendConfig; + uint8_t i; + + /* Set to defaults for shoebox */ + reflections->is_ready = 0; + reflections->mode = AUDIO_CONFIG_INVALID; + reflections->is_cartesian = 0; + reflections->is_relative = 1; + reflections->shoebox_data.n_ref = ER_NUM_REF; + reflections->user_origin[0] = 0.0f; + reflections->user_origin[1] = 0.0f; + reflections->user_origin[2] = ER_LIST_HEIGHT; + + /* Store scene origin if present */ + for ( i = 0; i < 3; i++ ) + { + reflections->user_origin[i] = reflections->shoebox_lib.cal.list_orig[i]; + } + + /* Init Shoebox */ + shoebox_init( &reflections->shoebox_lib, &reflections->shoebox_lib.cal ); + + /* Set mode */ + if ( ( error = er_set_reflections_mode( reflections, mode ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Compute the static reflections (first frame) */ + if ( ( error = er_compute_reflections( reflections ) ) != IVAS_ERR_OK ) + { + return error; + } + + reflections->closest_ch_idx = (uint16_t *) malloc( reflections->n_total_reflections * sizeof( uint16_t ) ); + if ( !reflections->closest_ch_idx ) + { + return IVAS_ERR_FAILED_ALLOC; + } + set_s( (int16_t *) reflections->closest_ch_idx, 0, reflections->n_total_reflections ); + + outRendConfig = getRendAudioConfigFromIvasAudioConfig( reflections->mode ); + if ( ( error = getAudioConfigNumChannels( outRendConfig, &( reflections->nchan_out ) ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Initialize Encoder */ + if ( ( error = er_encoder_init( reflections ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Update flag to indicate that reflection module is ready to process */ + reflections->is_ready = 1; + + return error; +} +/*-----------------------------------------------------------------------------------------* + Function er_set_reflections_mode + + Function sets the ER source positions based on the audio config + *-----------------------------------------------------------------------------------------*/ + +ivas_error er_set_reflections_mode( + er_struct_t *reflections, + AUDIO_CONFIG mode ) +{ + ivas_error error; + uint16_t ch; + error = IVAS_ERR_OK; + + if ( reflections->mode == mode ) + { + return error; + } + + reflections->is_ready = 0; + reflections->mode = mode; + + switch ( reflections->mode ) + { + case AUDIO_CONFIG_MONO: + reflections->shoebox_data.n_sources = 1; + reflections->n_LC_sources = 1; + reflections->LC_mixing = LC_mixing_5_1; + reflections->source_positions[0] = 0; + reflections->source_positions[1] = 0; + reflections->source_positions[2] = ER_RADIUS; + break; + case AUDIO_CONFIG_STEREO: + reflections->shoebox_data.n_sources = 2; + reflections->n_LC_sources = 2; + reflections->LC_mixing = LC_mixing_5_1; + for ( ch = 0; ch < reflections->shoebox_data.n_sources; ch++ ) + { + reflections->source_positions[3 * ch] = deg2rad( ls_azimuth_CICP2[ch] ); + reflections->source_positions[1 + ( 3 * ch )] = deg2rad( ls_elevation_CICP2[ch] ); + reflections->source_positions[2 + ( 3 * ch )] = ER_RADIUS; + } + break; + case AUDIO_CONFIG_5_1: + reflections->shoebox_data.n_sources = 5; + reflections->n_LC_sources = 3; + reflections->LC_mixing = LC_mixing_5_1; + for ( ch = 0; ch < reflections->shoebox_data.n_sources; ch++ ) + { + reflections->source_positions[3 * ch] = deg2rad( ls_azimuth_CICP6[ch] ); + reflections->source_positions[1 + ( 3 * ch )] = deg2rad( ls_elevation_CICP6[ch] ); + reflections->source_positions[2 + ( 3 * ch )] = ER_RADIUS; + } + break; + case AUDIO_CONFIG_7_1: + reflections->shoebox_data.n_sources = 7; + reflections->n_LC_sources = 5; + reflections->LC_mixing = LC_mixing_7_1; + for ( ch = 0; ch < reflections->shoebox_data.n_sources; ch++ ) + { + reflections->source_positions[3 * ch] = deg2rad( ls_azimuth_CICP12[ch] ); + reflections->source_positions[1 + ( 3 * ch )] = deg2rad( ls_elevation_CICP12[ch] ); + reflections->source_positions[2 + ( 3 * ch )] = ER_RADIUS; + } + break; + case AUDIO_CONFIG_5_1_2: + reflections->shoebox_data.n_sources = 7; + reflections->n_LC_sources = 5; + reflections->LC_mixing = LC_mixing_5_1_2; + for ( ch = 0; ch < reflections->shoebox_data.n_sources; ch++ ) + { + reflections->source_positions[3 * ch] = deg2rad( ls_azimuth_CICP14[ch] ); + reflections->source_positions[1 + ( 3 * ch )] = deg2rad( ls_elevation_CICP14[ch] ); + reflections->source_positions[2 + ( 3 * ch )] = ER_RADIUS; + } + break; + case AUDIO_CONFIG_5_1_4: + reflections->shoebox_data.n_sources = 9; + reflections->n_LC_sources = 5; + reflections->LC_mixing = LC_mixing_5_1_4; + for ( ch = 0; ch < reflections->shoebox_data.n_sources; ch++ ) + { + reflections->source_positions[3 * ch] = deg2rad( ls_azimuth_CICP16[ch] ); + reflections->source_positions[1 + ( 3 * ch )] = deg2rad( ls_elevation_CICP16[ch] ); + reflections->source_positions[2 + ( 3 * ch )] = ER_RADIUS; + } + break; + case AUDIO_CONFIG_7_1_4: + reflections->shoebox_data.n_sources = 11; + reflections->n_LC_sources = 5; + reflections->LC_mixing = LC_mixing_7_1_4; + for ( ch = 0; ch < reflections->shoebox_data.n_sources; ch++ ) + { + reflections->source_positions[3 * ch] = deg2rad( ls_azimuth_CICP19[ch] ); + reflections->source_positions[1 + ( 3 * ch )] = deg2rad( ls_elevation_CICP19[ch] ); + reflections->source_positions[2 + ( 3 * ch )] = ER_RADIUS; + } + break; + case AUDIO_CONFIG_HOA3: + reflections->use_er = 0; + break; + case AUDIO_CONFIG_HOA2: + reflections->use_er = 0; + break; + case AUDIO_CONFIG_FOA: + reflections->use_er = 0; + break; + default: + reflections->mode = AUDIO_CONFIG_INVALID; + return IVAS_ERROR( IVAS_ERR_INVALID_ER_PARAM, "Unsupported reflections mode" ); + } + + return error; +} + + +/*-----------------------------------------------------------------------------------------* + Function er_encoder_init + + Function that initializes the er encoder + *-----------------------------------------------------------------------------------------*/ + +ivas_error er_encoder_init( + er_struct_t *reflections ) +{ + ivas_error error = IVAS_ERR_OK; + uint16_t i, j, src_idx; + uint16_t min_index = 0; + float p_x, p_y, p_z; + float p_x_src, p_y_src, p_z_src; + float tmp; + float dist, min_dist = 0; + + if ( !reflections ) + { + error = IVAS_ERR_FAILED_ALLOC; + return error; + } + + if ( getAudioConfigType( getRendAudioConfigFromIvasAudioConfig( reflections->mode ) ) == IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) + { + /* Compute MC-snap location (closest channel position to reflection direction) */ + for ( i = 0; i < reflections->n_total_reflections; i++ ) + { + /* Compute cartesian points for reflection (from degrees) */ + p_x = ER_RADIUS * ( (float) cos( deg2rad( reflections->shoebox_data.el_angle.data[i] ) ) * (float) cos( deg2rad( reflections->shoebox_data.az_angle.data[i] ) ) ); + p_y = ER_RADIUS * ( (float) cos( deg2rad( reflections->shoebox_data.el_angle.data[i] ) ) * (float) sin( deg2rad( reflections->shoebox_data.az_angle.data[i] ) ) ); + p_z = ER_RADIUS * ( (float) sin( deg2rad( reflections->shoebox_data.el_angle.data[i] ) ) ); + + /* Calculate the euclidean distance to each point in the config ls setup */ + for ( j = 0; j < reflections->nchan_out; j++ ) + { + /* Ignore LFE */ + if ( j != LFE_CHANNEL ) + { + src_idx = ( j > LFE_CHANNEL ) ? j - 1 : j; + + p_x_src = reflections->source_positions[src_idx * 3 + 2] * ( (float) cos( reflections->source_positions[src_idx * 3 + 1] ) * (float) cos( reflections->source_positions[src_idx * 3] ) ); + p_y_src = reflections->source_positions[src_idx * 3 + 2] * ( (float) cos( reflections->source_positions[src_idx * 3 + 1] ) * (float) sin( reflections->source_positions[src_idx * 3] ) ); + p_z_src = reflections->source_positions[src_idx * 3 + 2] * (float) sin( reflections->source_positions[src_idx * 3 + 1] ); + + tmp = ( p_x_src - p_x ) * ( p_x_src - p_x ); + tmp += ( p_y_src - p_y ) * ( p_y_src - p_y ); + tmp += ( p_z_src - p_z ) * ( p_z_src - p_z ); + dist = (float) sqrt( tmp ); + + /* Save index of closest channel */ + if ( src_idx == 0 ) + { + min_dist = dist; + min_index = j; + } + else + { + if ( dist < min_dist ) + { + min_dist = dist; + min_index = j; + } + } + } + } + + reflections->closest_ch_idx[i] = (uint16_t) min_index; + } + } + + + return error; +} + + +/*-----------------------------------------------------------------------------------------* + Function er_compute_reflections + + Function computes reflections using the shoebox library and sets up the circular buffers + structure for the early reflections process + *-----------------------------------------------------------------------------------------*/ + +ivas_error er_compute_reflections( + er_struct_t *reflections ) +{ + ivas_error error = IVAS_ERR_OK; + uint16_t circ_len, i, j; + float tmp; + + reflections->is_ready = 0; + + /* Disabled case */ + if ( reflections->mode == AUDIO_CONFIG_INVALID ) + { + return error; + } + + /* Run shoebox with current reflection parameters */ + shoebox_set_scene( &( reflections->shoebox_lib ), &( reflections->shoebox_data ), + reflections->shoebox_lib.cal.list_orig, reflections->source_positions, + reflections->is_cartesian, reflections->is_relative ); + + /* Convert reflection times in seconds to samples and keep track of max */ + circ_len = 0; + for ( i = 0; i < reflections->shoebox_data.n_sources; i++ ) + { + for ( j = 0; j < reflections->shoebox_data.n_ref; j++ ) + { + tmp = reflections->shoebox_data.times.data[j + ( i * (int) reflections->shoebox_data.n_ref )]; + tmp = (float) round( tmp * reflections->output_Fs ); + reflections->shoebox_data.times.data[j + ( i * (int) reflections->shoebox_data.n_ref )] = tmp; + circ_len = ( (uint16_t) tmp > circ_len ) ? (uint16_t) tmp : circ_len; + } + } + + /* If max delay is less than max frame size, use max frame size to compute circ buffer length */ + circ_len = ( circ_len > (uint16_t) reflections->max_frame_size ) ? circ_len : (uint16_t) reflections->max_frame_size; + circ_len += (uint16_t) reflections->max_frame_size; + + /* If circ buffers exist and size is the same, reset memory to all zeros */ + /* If size is different, reallocate circ buffers */ + /* Otherwise allocate new circ buffers */ + if ( reflections->circ_buffers ) + { + if ( reflections->circ_len == circ_len ) + { + /* circ buffers exist and size is the same */ + set_f( reflections->circ_buffers, 0.0f, + reflections->shoebox_data.n_sources * reflections->circ_len ); + } + else + { + /* circ buffers exist but size is different */ + reflections->circ_len = circ_len; + free( reflections->circ_buffers ); + reflections->circ_buffers = (float *) malloc( + reflections->shoebox_data.n_sources * reflections->circ_len * sizeof( float ) ); + set_f( reflections->circ_buffers, 0.0f, + reflections->shoebox_data.n_sources * reflections->circ_len ); + } + } + else + { + /* circ buffers do not exist */ + reflections->circ_len = circ_len; + reflections->circ_buffers = (float *) malloc( + reflections->shoebox_data.n_sources * reflections->circ_len * sizeof( float ) ); + set_f( reflections->circ_buffers, 0.0f, + reflections->shoebox_data.n_sources * reflections->circ_len ); + } + + /* Check that circ buffers were allocated */ + if ( !reflections->circ_buffers ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Early Reflections buffers" ); + } + + /* Initialize circular buffer insertion point */ + reflections->circ_insert = reflections->circ_len - (uint16_t) reflections->max_frame_size; + + /* Get total reflections number */ + reflections->n_total_reflections = reflections->shoebox_data.n_sources * reflections->shoebox_data.n_ref; + + /* Check that reflection buffers were allocated */ + if ( error != IVAS_ERR_OK ) + { + return error; + } + + return error; +} + +/*-----------------------------------------------------------------------------------------* +Function er_process + +Takes a buffer of N channels, returns a buffer of N*6 channels containing the early +reflections (one per wall). The process is a delay line architecture +*-----------------------------------------------------------------------------------------*/ + + +ivas_error er_process( + er_struct_t *reflections, + int16_t subframe_size, + int16_t subframe_idx, + float **io, + IVAS_REND_AudioConfig inConfig ) +{ + ivas_error error = IVAS_ERR_OK; + uint16_t i, j, k, subframe_offset; + uint16_t ref_no, ref_delay; + uint16_t n_ref_sources, n_ref; + int16_t samp_idx, in_ch_idx, buf_ch_idx, ref_out_idx; + float ref_gain; + float *buffer_ch; + + if ( !reflections ) + { + return IVAS_ERR_INIT_ERROR; + } + + /* should not arrive here if reflections are disabled but in case it does just do nothing */ + if ( reflections->use_er != 1 ) + { + return error; + } + + /* Ensure all reflection memory is allocated */ + if ( !reflections->circ_buffers || + !reflections->is_ready ) + { + return IVAS_ERR_INIT_ERROR; + } + + subframe_offset = subframe_idx * subframe_size; + n_ref = reflections->shoebox_data.n_ref; + + /* If low complexity ER are requested only compute ER for n_LC_sources */ + if ( reflections->lowComplexity ) + { + n_ref_sources = reflections->n_LC_sources; + } + else + { + n_ref_sources = reflections->shoebox_data.n_sources; + } + + /* Channel case, copy input into buffers panning for LC mode and skipping LFE */ + if ( getAudioConfigType( inConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) + { + /* Loop through all input sources filling circular buffers */ + for ( i = 0; i < reflections->shoebox_data.n_sources; i++ ) + { + /* Pull correct circular buffer depending on complexity mode */ + buf_ch_idx = ( reflections->lowComplexity == 1 ) ? reflections->LC_mixing[i] : i; + buffer_ch = &( reflections->circ_buffers[buf_ch_idx * reflections->circ_len] ); + + /* Skip LFE from input buffer */ + in_ch_idx = ( i >= LFE_CHANNEL ) ? i + 1 : i; + samp_idx = reflections->circ_insert; + + /* If less than number of reflection sources, overwrite buffer */ + if ( i == buf_ch_idx ) + { + for ( j = 0; j < subframe_size; j++ ) + { + buffer_ch[samp_idx++] = io[in_ch_idx][j + subframe_offset]; + samp_idx = samp_idx % reflections->circ_len; + } + } + /* Accumulate with buffer for low complexity mixed sources */ + else + { + for ( j = 0; j < subframe_size; j++ ) + { + buffer_ch[samp_idx++] += io[in_ch_idx][j + subframe_offset]; + samp_idx = samp_idx % reflections->circ_len; + } + } + } + } + else + { + return IVAS_ERR_INVALID_INPUT_FORMAT; + } + + /* Loop through sources retrieve reflections from circ buffers */ + for ( i = 0; i < n_ref_sources; i++ ) + { + /* Access correct row of input circ buffer */ + buffer_ch = &( reflections->circ_buffers[i * reflections->circ_len] ); + + /* Loop through reflections */ + for ( j = 0; j < n_ref; j++ ) + { + ref_no = j + ( i * n_ref ); + ref_gain = reflections->shoebox_data.gains.data[ref_no]; + ref_delay = (uint16_t) reflections->shoebox_data.times.data[ref_no]; + ref_out_idx = reflections->closest_ch_idx[ref_no]; + + /* Determine start idx of reflection in circ buffer based on + current insert idx and reflection delay */ + samp_idx = (int) reflections->circ_insert - ref_delay; + if ( samp_idx < 0 ) + { + samp_idx = (int) reflections->circ_len + samp_idx; + } + + /* Pull reflection from circ buffer and apply gain */ + for ( k = 0; k < subframe_size; k++ ) + { + io[ref_out_idx][k + subframe_offset] += buffer_ch[samp_idx++] * ref_gain; + samp_idx = samp_idx % reflections->circ_len; + } + } + } + + /* Increment circular buffer start index */ + reflections->circ_insert = ( reflections->circ_insert + subframe_size ) % reflections->circ_len; + + return error; +} + + +#endif diff --git a/lib_rend/ivas_render_config.c b/lib_rend/ivas_render_config.c index 2972b57f847e16140fc142dced8c92af88c56c17..8bb5a957e80af259e196fd371b016800179cbd8a 100644 --- a/lib_rend/ivas_render_config.c +++ b/lib_rend/ivas_render_config.c @@ -49,6 +49,10 @@ #define IVAS_REVERB_DEFAULT_PRE_DELAY 0.016f #define IVAS_REVERB_DEFAULT_INPUT_DELAY 0.1f +#ifdef EARLY_REFLECTIONS +#define IVAS_REVERB_DEFAULT_USE_ER 0 +#endif + /*-----------------------------------------------------------------------* * ivas_render_config_open() @@ -116,6 +120,9 @@ ivas_error ivas_render_config_init_from_rom( ( *hRenderConfig )->roomAcoustics.nBands = IVAS_REVERB_DEFAULT_N_BANDS; ( *hRenderConfig )->roomAcoustics.acousticPreDelay = IVAS_REVERB_DEFAULT_PRE_DELAY; ( *hRenderConfig )->roomAcoustics.inputPreDelay = IVAS_REVERB_DEFAULT_INPUT_DELAY; +#ifdef EARLY_REFLECTIONS + ( *hRenderConfig )->roomAcoustics.use_er = IVAS_REVERB_DEFAULT_USE_ER; +#endif set_zero( &( *hRenderConfig )->roomAcoustics.pFc_input[0], CLDFB_NO_CHANNELS_MAX ); set_zero( &( *hRenderConfig )->roomAcoustics.pAcoustic_rt60[0], CLDFB_NO_CHANNELS_MAX ); set_zero( &( *hRenderConfig )->roomAcoustics.pAcoustic_dsr[0], CLDFB_NO_CHANNELS_MAX ); diff --git a/lib_rend/ivas_reverb.c b/lib_rend/ivas_reverb.c index fd485ffbce7c504b055750bb4c532b9eec6dc980..b110cd372d50cd819c7a79521a2dbbd648a2d7b7 100644 --- a/lib_rend/ivas_reverb.c +++ b/lib_rend/ivas_reverb.c @@ -1182,6 +1182,14 @@ ivas_error ivas_reverb_open( pState->pConfig.roomAcoustics.override = hRenderConfig->roomAcoustics.override; pState->pConfig.roomAcoustics.nBands = hRenderConfig->roomAcoustics.nBands; +#ifdef EARLY_REFLECTIONS + if ( hRenderConfig->roomAcoustics.use_er == 1 ) + { + pState->pConfig.roomAcoustics.use_er = hRenderConfig->roomAcoustics.use_er; + pState->pConfig.roomAcoustics.lowComplexity = hRenderConfig->roomAcoustics.lowComplexity; + } +#endif + /* set up input downmix */ pState->dmx_gain = calc_dmx_gain(); diff --git a/lib_rend/ivas_rotation.c b/lib_rend/ivas_rotation.c index c7d372d65d5ae08c6bbd7103f35008dfed804224..324b88549a381e088dce1ff1a81ae1b3165ef180 100644 --- a/lib_rend/ivas_rotation.c +++ b/lib_rend/ivas_rotation.c @@ -272,6 +272,27 @@ float deg2rad( return PI_OVER_180 * degrees; } +#ifdef EARLY_REFLECTIONS +/*------------------------------------------------------------------------- + * rad2deg() + * + * Converts normalized radians to degrees + *------------------------------------------------------------------------*/ +float rad2deg( + float radians ) +{ + while ( radians >= EVS_PI ) + { + radians = radians - EVS_PI; + } + while ( radians <= -EVS_PI ) + { + radians = radians + EVS_PI; + } + return _180_OVER_PI * radians; +} +#endif + /*------------------------------------------------------------------------- * rotateAziEle() * diff --git a/lib_rend/ivas_shoebox.c b/lib_rend/ivas_shoebox.c new file mode 100644 index 0000000000000000000000000000000000000000..90db7575fdec414beae1ba5fb5075f1df08ca377 --- /dev/null +++ b/lib_rend/ivas_shoebox.c @@ -0,0 +1,458 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include "options.h" + +#ifdef EARLY_REFLECTIONS + +#include +#include +#include "ivas_prot_rend.h" +#include "ivas_stat_rend.h" +#include "ivas_cnst.h" +#include "prot.h" +#include "wmc_auto.h" + +/*-----------------------------------------------------------------------------------------* + * Function shoebox_config_init + * + * Function transfer the parameters from the reverb config handle to the shoebox + * calibration data structure. + *-----------------------------------------------------------------------------------------*/ + +void shoebox_config_init( + shoebox_config_t *cal, + RENDER_CONFIG_HANDLE hRenderConfig /* i : Renderer configuration handle */ +) +{ + int32_t wall_idx; + + cal->room_L = hRenderConfig->roomAcoustics.dimensions.x; + cal->room_W = hRenderConfig->roomAcoustics.dimensions.y; + cal->room_H = hRenderConfig->roomAcoustics.dimensions.z; + + /* Absorption Coefficients */ + /* Convention: [Front wall, Back wall, Left wall, Right wall, Ceiling, Floor] */ + for ( wall_idx = 0; wall_idx < 6; wall_idx++ ) + { + cal->abs_coeff[wall_idx] = hRenderConfig->roomAcoustics.AbsCoeff[wall_idx]; + } + + /* Listener position (only X and Y can be pos. or neg. ) */ + cal->list_orig[0] = hRenderConfig->roomAcoustics.ListenerOrigin.x; + cal->list_orig[1] = hRenderConfig->roomAcoustics.ListenerOrigin.y; + cal->list_orig[2] = hRenderConfig->roomAcoustics.ListenerOrigin.z; +} + +/*-----------------------------------------------------------------------------------------* + * Function shoebox_init + * + * Function initializes the shoebox operating parameters by setting limits and defaults, + * also contains the calibration structure. + *-----------------------------------------------------------------------------------------*/ + +void shoebox_init( + shoebox_obj_t *obj, + shoebox_config_t *cal ) +{ + uint16_t i; + + /* Add cal to obj struct */ + obj->cal = *cal; + /* Add defaults */ + obj->max_bands = 1; + obj->MAX_SOURCES = ER_MAX_SOURCES; + obj->REF_ORDER = ER_REF_ORDER; + + /* Positions */ + set_f( &obj->src_pos[0], 0.0f, 75U ); + set_f( &obj->src_dist[0], 0.0f, 25U ); + + for ( i = 0; i < 3; i++ ) + { + obj->list_pos[i] = cal->list_orig[i]; + } + + /* Pointer */ + obj->nSrc = 0; + + /* Flags */ + obj->isCartesian = 1; + obj->isRelative = 1; + obj->isZHeight = 1; + obj->isRadians = 1; + + /* Params */ + obj->radius = ER_RADIUS; + obj->min_wall_dist = ER_MIN_WALL_DIST; + obj->soundspeed = ER_SOUND_SPEED; + obj->air_coeff = ER_AIR_COEFF; +} + +/*-----------------------------------------------------------------------------------------* + * Function shoebox_bound + * + * SHOEBOX_BOUND takes in CARTESIAN coordinates of either a receiver or + * source and checks if it is within the virtual room boundaries established + * by the surface parameters. If object is out of bounds, then new cartesian + * coordinates are established to collapse the object position. + *-----------------------------------------------------------------------------------------*/ + + +static void shoebox_bound( + shoebox_obj_t *obj, + float *out_pos ) +{ + float out_tmp; + int32_t i; + + out_tmp = ( obj->cal.room_L / 2.0f ) - obj->min_wall_dist; + if ( ( out_pos[0] > out_tmp ) || ( out_pos[0] < ( ( ( -obj->cal.room_L ) / 2.0f ) + obj->min_wall_dist ) ) ) + { + if ( out_pos[0] < 0.0f ) + { + i = -1; + } + else + { + i = ( out_pos[0] > 0.0f ) ? ( (int32_t) 1 ) : ( (int32_t) 0 ); + } + out_pos[0] = out_tmp * ( (float) i ); + } + out_tmp = ( obj->cal.room_W / 2.0f ) - obj->min_wall_dist; + if ( ( out_pos[1] > out_tmp ) || ( out_pos[1] < ( ( ( -obj->cal.room_W ) / 2.0f ) + obj->min_wall_dist ) ) ) + { + if ( out_pos[1] < 0.0f ) + { + i = -1; + } + else + { + i = ( out_pos[1] > 0.0f ) ? ( (int32_t) 1 ) : ( (int32_t) 0 ); + } + out_pos[1] = out_tmp * ( (float) i ); + } + out_tmp = ( obj->cal.room_H / 2.0f ) - obj->min_wall_dist; + if ( ( out_pos[2] > out_tmp ) || ( out_pos[2] < ( ( ( -obj->cal.room_H ) / 2.0f ) + obj->min_wall_dist ) ) ) + { + if ( out_pos[2] < 0.0f ) + { + i = -1; + } + else + { + i = ( out_pos[2] > 0.0f ) ? ( (int32_t) 1 ) : ( (int32_t) 0 ); + } + out_pos[2] = out_tmp * ( (float) i ); + } +} + +/*-----------------------------------------------------------------------------------------* + * Function shoebox_get_coord + * + * Transform relative spherical coordinate to 3D cartesian point + *-----------------------------------------------------------------------------------------*/ + +static void shoebox_get_coord( + shoebox_obj_t *obj, + float *fcnOutput_data, + const float src_pos_data[], + float *tmp_pos, + float out_tmp, + int32_t coord, + int32_t loop_ub, + int32_t k, + uint16_t isRelative ) +{ + float tmp_data[75]; + float rcoselev; + int32_t tmp_size_idx_1; + int32_t n; + + tmp_size_idx_1 = 3; + if ( obj->isCartesian == 0 ) + { + /* Convert Spherical to Cartesian */ + if ( obj->isRadians == 0 ) + { + for ( n = 0; n < loop_ub; n++ ) + { + fcnOutput_data[n] = deg2rad( src_pos_data[k + n] ); + } + } + tmp_data[2] = fcnOutput_data[2] * sinf( fcnOutput_data[1] ); + rcoselev = fcnOutput_data[2] * cosf( fcnOutput_data[1] ); + tmp_data[0] = rcoselev * cosf( fcnOutput_data[0] ); + tmp_data[1] = rcoselev * sinf( fcnOutput_data[0] ); + } + else + { + /* CARTESIAN CASE */ + tmp_size_idx_1 = loop_ub; + for ( n = 0; n < loop_ub; n++ ) + { + tmp_data[n] = src_pos_data[k + n]; + } + if ( obj->isZHeight != 0.0f ) + { + /* FIX Z COORDINATE */ + tmp_data[2] = src_pos_data[k + 2] - ( obj->cal.room_H / 2.0f ); + } + } + for ( k = 0; k < tmp_size_idx_1; k++ ) + { + obj->src_pos[( coord + k ) - 1] = tmp_data[k]; + } + /* CENTER TO LISTENER */ + if ( ( out_tmp + 1.0f ) > ( ( out_tmp + 1.0f ) + 2.0f ) ) + { + k = 1; + } + else + { + k = (int32_t) ( (float) ( out_tmp + 1.0f ) ); + } + tmp_pos[0] = obj->src_pos[k - 1]; + tmp_pos[1] = obj->src_pos[k]; + tmp_pos[2] = obj->src_pos[k + 1]; + if ( isRelative != 0.0f ) + { + tmp_pos[0] += obj->list_pos[0]; + tmp_pos[1] += obj->list_pos[1]; + tmp_pos[2] += obj->list_pos[2]; + } +} + +/*-----------------------------------------------------------------------------------------* + * Function shoebox_get_euclidian_distance_internal + * + * Get 3D source distance from receiver + *-----------------------------------------------------------------------------------------*/ + +static float shoebox_get_euclidian_distance_internal( + shoebox_obj_t *obj, + float *tmp_pos, + float *scale ) +{ + float absxk, out_tmp, t; + + absxk = fabsf( obj->list_pos[0] - tmp_pos[0] ); + if ( absxk > ER_EUCLIDEAN_SCALE ) + { + out_tmp = 1.0f; + *scale = absxk; + } + else + { + t = absxk / ER_EUCLIDEAN_SCALE; + out_tmp = t * t; + } + absxk = fabsf( obj->list_pos[1] - tmp_pos[1] ); + if ( absxk > *scale ) + { + t = *scale / absxk; + out_tmp = ( ( out_tmp * t ) * t ) + 1.0f; + *scale = absxk; + } + else + { + t = absxk / *scale; + out_tmp += t * t; + } + absxk = fabsf( obj->list_pos[2] - tmp_pos[2] ); + if ( absxk > *scale ) + { + t = *scale / absxk; + out_tmp = ( ( out_tmp * t ) * t ) + 1.0f; + *scale = absxk; + } + else + { + t = absxk / *scale; + out_tmp += t * t; + } + return out_tmp; +} + + +/*-----------------------------------------------------------------------------------------* + * Function shoebox_set_scene + * + * Initial scene setup returning computed reflection (arrival times, DOA and gain). + *-----------------------------------------------------------------------------------------*/ + + +void shoebox_set_scene( + shoebox_obj_t *obj, + shoebox_output_t *ER_PARAMS, + const float list_pos[3], + const float src_pos_data[], + uint16_t isCartesian, + uint16_t isRelative ) +{ + float tmp_pos[3]; + float out_tmp; + int32_t i, j, k, n; + int32_t loop_ub; + /* ------------- SET FLAGS ------------- */ + obj->isCartesian = isCartesian; + obj->isRelative = isRelative; + /* ------------- CHECK DIMENSIONS ------------- */ + if ( ER_PARAMS->n_sources > obj->MAX_SOURCES ) + { + obj->nSrc = obj->MAX_SOURCES; + } + else + { + obj->nSrc = ER_PARAMS->n_sources; + } + /* ---------- RESET DATA HOLDERS ---------- */ + set_f( &obj->src_pos[0], 0.0f, 75U ); + obj->list_pos[0] = list_pos[0]; + obj->list_pos[1] = list_pos[1]; + obj->list_pos[2] = list_pos[2]; + /* ---------- ADJUST LISTENER ------------- */ + if ( obj->isZHeight != 0 ) + { + obj->list_pos[2] = list_pos[2] - ( obj->cal.room_H / 2.0f ); + } + tmp_pos[1] = obj->list_pos[1]; + tmp_pos[2] = obj->list_pos[2]; + + shoebox_bound( obj, obj->list_pos ); + + /* ---------- SOURCE LOOP ------------- */ + i = (int32_t) obj->nSrc; + for ( j = 0; j < i; j++ ) + { + float fcnOutput_data[75]; + float rcoselev; + float scale; + int32_t coord; + /* idx = single(i); */ + out_tmp = 3.0f * ( ( ( (float) j ) + 1.0f ) - 1.0f ); + /* GET COORDINATE IN CARTESIAN ABSOLUTE FORMAT */ + if ( ( out_tmp + 1.0f ) > ( ( out_tmp + 1.0f ) + 2.0f ) ) + { + k = 0; + n = 0; + coord = 1; + } + else + { + k = ( (int32_t) ( (float) ( out_tmp + 1.0f ) ) ) - 1; + n = (int32_t) ( (float) ( ( out_tmp + 1.0f ) + 2.0f ) ); + coord = (int32_t) ( (float) ( out_tmp + 1.0f ) ); + } + loop_ub = n - k; + for ( n = 0; n < loop_ub; n++ ) + { + fcnOutput_data[n] = src_pos_data[k + n]; + } + + + shoebox_get_coord( obj, fcnOutput_data, src_pos_data, tmp_pos, out_tmp, coord, loop_ub, k, isRelative ); + + shoebox_bound( obj, tmp_pos ); + + scale = ER_EUCLIDEAN_SCALE; + + out_tmp = shoebox_get_euclidian_distance_internal( obj, tmp_pos, &scale ); + + obj->src_dist[( (int32_t) ( (float) ( ( (float) j ) + 1.0f ) ) ) - 1] = scale * sqrtf( out_tmp ); + + /* COMPUTE PATTERNS */ + + /* SHOEBOX_COMPUTE: fills an input structure (4 array fields of length NxR ) with the */ + /* Early reflection metadata (time of arrival, gain, az, el). */ + /* */ + /* Input: */ + /* 1. obj : Module data holder */ + /* 2. ER_struct : Early reflection structure */ + /* 3. src_num : Index of source to compute patterns for */ + /* ------ */ + out_tmp = obj->src_dist[( (int32_t) ( (float) ( ( (float) j ) + 1.0f ) ) ) - 1]; + for ( loop_ub = 0; loop_ub < 6; loop_ub++ ) + { + float im_pos[3]; + float path_dist; + /* Retrieve coordinate and surface sign */ + coord = ( (int32_t) ceilf( ( ( (float) loop_ub ) + 1.0f ) / 2.0f ) ) - 1; + rcoselev = ( ( (float) loop_ub ) + 1.0f ) + ( ER_PARAMS->n_ref * ( ( ( (float) j ) + 1.0f ) - 1.0f ) ); + /* Initialize image position coordinates */ + im_pos[0] = tmp_pos[0]; + im_pos[1] = tmp_pos[1]; + im_pos[2] = tmp_pos[2]; + /* Calculate image projection coordinate based on current surface axis */ + if ( ( loop_ub + 1 ) < 3 ) + { + scale = obj->cal.room_L; + } + else if ( ( loop_ub + 1 ) < 5 ) + { + scale = obj->cal.room_W; + } + else + { + scale = obj->cal.room_H; + } + im_pos[coord] = + tmp_pos[coord] + + ( 2.0f * ( ( ( ( -( 1.0f - ( fmodf( ( (float) loop_ub ) + 1.0f, 2.0f ) * 2.0f ) ) ) * scale ) / 2.0f ) - tmp_pos[coord] ) ); + /* 0. Get euclidean distance from IMAGE SOURCE [N,W] to LIST */ + scale = ER_EUCLIDEAN_SCALE; + path_dist = shoebox_get_euclidian_distance_internal( obj, im_pos, &scale ); + + path_dist = scale * sqrtf( path_dist ); + /* 1. Compute time-of arrival (TOA) */ + ER_PARAMS->times.data[( (int32_t) rcoselev ) - 1] = path_dist / obj->soundspeed; + /* 2./3. DOA */ + ER_PARAMS->az_angle.data[( (int32_t) rcoselev ) - 1] = + rad2deg( + atan2f( im_pos[1] - obj->list_pos[1], im_pos[0] - obj->list_pos[0] ) ); + ER_PARAMS->el_angle.data[( (int32_t) rcoselev ) - 1] = + rad2deg( + asinf( ( im_pos[2] - obj->list_pos[2] ) / path_dist ) ); + /* 4. Compute gain taking into account air and surface absorption */ + /* and propagation loss */ + if ( path_dist < out_tmp ) + { + path_dist = out_tmp; + } + ER_PARAMS->gains.data[( (int32_t) rcoselev ) - 1] = + ( ( 1.0f - obj->cal.abs_coeff[loop_ub] ) * ( out_tmp / path_dist ) ) - ( path_dist * obj->air_coeff ); + } + } +} + + +#endif diff --git a/lib_rend/ivas_stat_rend.h b/lib_rend/ivas_stat_rend.h index e0818b20ae4a19e9544a1721a2e02948bcdfd6d9..6e78e069b4c0cf15ba3e1cf543eaf40485048244 100644 --- a/lib_rend/ivas_stat_rend.h +++ b/lib_rend/ivas_stat_rend.h @@ -924,6 +924,13 @@ typedef struct ivas_roomAcoustics_t float pAcoustic_dsr[CLDFB_NO_CHANNELS_MAX]; /* - The room's Diffuse to Source Ratio per center frequency */ float acousticPreDelay; /* Time elapsed between input signal and late reverberation start, float, range [0.001..10] */ float inputPreDelay; /* Offset in seconds from where DSR is computed in the RIR (0 = at source), float, range [0.001..10] */ +#ifdef EARLY_REFLECTIONS + int16_t use_er; /* ER activation flag */ + int32_t lowComplexity; /* Low complexity ER flag */ + IVAS_VECTOR3 dimensions; /* Room dimensions [m] */ + float AbsCoeff[ER_ABS_COEFF]; /* Absorption coeffs */ + IVAS_VECTOR3 ListenerOrigin; /* Listener origin */ +#endif } ivas_roomAcoustics_t; @@ -1023,6 +1030,96 @@ typedef struct ivas_reverb_state_t } REVERB_DATA, *REVERB_HANDLE; +#ifdef EARLY_REFLECTIONS +/*----------------------------------------------------------------------------------* + * Shoebox structure + *----------------------------------------------------------------------------------*/ + +/* This structure holds the original bitstream metadata */ + +typedef struct +{ + float room_L; + float room_W; + float room_H; + float abs_coeff[ER_ABS_COEFF]; + float list_orig[3]; +} shoebox_config_t; + +/* This structure holds the corrected( bounded ) source and listener positions */ + +typedef struct +{ + uint16_t isCartesian; + uint16_t isRelative; + uint16_t isZHeight; + uint16_t isRadians; + uint16_t MAX_SOURCES; + uint16_t max_bands; + uint16_t REF_ORDER; + float src_pos[75]; + float src_dist[25]; + float list_pos[3]; + uint16_t nSrc; + float radius; + float min_wall_dist; + float soundspeed; + float air_coeff; + shoebox_config_t cal; +} shoebox_obj_t; + + +typedef struct shoebox_data_t +{ + float data[150]; + int32_t size[1]; +} shoebox_data_t; + + +typedef struct +{ + uint16_t n_sources; + uint16_t n_ref; + shoebox_data_t times; + shoebox_data_t gains; + shoebox_data_t az_angle; + shoebox_data_t el_angle; +} shoebox_output_t; + +#endif + +#ifdef EARLY_REFLECTIONS +/*----------------------------------------------------------------------------------* + * Reflections structure + *----------------------------------------------------------------------------------*/ + +/* This structure holds the original source positions */ +typedef struct er_struct_t +{ + AUDIO_CONFIG mode; + int16_t nchan_out; + uint16_t use_er; + uint32_t lowComplexity; + uint16_t n_LC_sources; + uint16_t *LC_mixing; + uint16_t is_ready; + uint16_t circ_len; + uint16_t circ_insert; + uint16_t n_total_reflections; + uint16_t is_cartesian; + uint16_t is_relative; + uint32_t max_frame_size; + float output_Fs; + float source_positions[75]; + float user_origin[3]; + float *circ_buffers; + uint16_t *closest_ch_idx; + shoebox_output_t shoebox_data; + shoebox_obj_t shoebox_lib; +} er_struct_t; + +#endif + /*----------------------------------------------------------------------------------* * TD ISM Object Renderer structure *----------------------------------------------------------------------------------*/ @@ -1316,6 +1413,9 @@ typedef struct ivas_crend_state_t REVERB_HANDLE hReverb; int16_t delay_line_rw_index; int16_t diffuse_delay_line_rw_index; +#ifdef EARLY_REFLECTIONS + er_struct_t *reflections; +#endif } CREND_DATA, *CREND_HANDLE; diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index cbf6143e5e938f73924c4832fcb168351a414f94..253c1d84b6b5caa3c53f5093cd570fa91f2ed122 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -5003,6 +5003,11 @@ int16_t IVAS_REND_GetRenderConfig( hRCout->split_rend_config.rendererSelection = hRCin->split_rend_config.rendererSelection; #endif +#ifdef EARLY_REFLECTIONS + hRCout->room_acoustics.use_er = hRCin->roomAcoustics.use_er; + hRCout->room_acoustics.lowComplexity = hRCin->roomAcoustics.lowComplexity; +#endif + return IVAS_ERR_OK; } @@ -5053,6 +5058,19 @@ int16_t IVAS_REND_FeedRenderConfig( mvr2r( renderConfig.directivity, hRenderConfig->directivity, 3 ); #endif +#ifdef EARLY_REFLECTIONS + hRenderConfig->roomAcoustics.use_er = 0; + if ( renderConfig.room_acoustics.use_er == 1 ) + { + hRenderConfig->roomAcoustics.use_er = renderConfig.room_acoustics.use_er; + hRenderConfig->roomAcoustics.lowComplexity = renderConfig.room_acoustics.lowComplexity; + hRenderConfig->roomAcoustics.dimensions = renderConfig.room_acoustics.dimensions; + hRenderConfig->roomAcoustics.ListenerOrigin = renderConfig.room_acoustics.ListenerOrigin; + + mvr2r( renderConfig.room_acoustics.AbsCoeff, hRenderConfig->roomAcoustics.AbsCoeff, ER_ABS_COEFF ); + } +#endif + #ifdef SPLIT_REND_WITH_HEAD_ROT hRenderConfig->split_rend_config = renderConfig.split_rend_config; /* Overwrite any pose correction settings if 0 DOF (no pose correction) was selected */ diff --git a/lib_util/render_config_reader.c b/lib_util/render_config_reader.c index d83875466a05d98b81a7f0bbed4bbd8b80d65800..84991c871d47c47f03f9e6c275a34836870f8db9 100644 --- a/lib_util/render_config_reader.c +++ b/lib_util/render_config_reader.c @@ -96,6 +96,7 @@ typedef enum _FREQ_GRID_MODE #ifdef EARLY_REFLECTIONS typedef struct { + uint16_t use_er; /* Activation Flag */ IVAS_VECTOR3 dimensions; /* Room dimensions [m] */ float pAbsCoeff[N_ABS_COEFFS]; /* Absorption coeffs table */ IVAS_VECTOR3 *pListenerOrigin; /* Listener origin */ @@ -1251,6 +1252,10 @@ static ivas_error RenderConfigReader_checkValues( IVAS_ROOM_ACOUSTICS_CONFIG_DATA *pRoom_acoustics; pRoom_acoustics = &hRenderConfig->room_acoustics; tab_value_err_count = 0; +#ifdef EARLY_REFLECTIONS + int16_t wall_idx; +#endif + /* Verify the number of frequency bands in the config input data */ if ( ( pRoom_acoustics->nBands > N_BANDS_MAX ) || ( pRoom_acoustics->nBands < N_BANDS_MIN ) ) @@ -1326,6 +1331,52 @@ static ivas_error RenderConfigReader_checkValues( } #endif /* DEBUGGING */ + +#ifdef EARLY_REFLECTIONS + if ( pRoom_acoustics->use_er == 1 ) + { + /* Room dimensions */ + if ( pRoom_acoustics->dimensions.x < ER_MIN_ROOM_DIMENSION ) + { + pRoom_acoustics->dimensions.x = ER_MIN_ROOM_DIMENSION; + } + if ( pRoom_acoustics->dimensions.x > ER_MAX_ROOM_DIMENSION ) + { + pRoom_acoustics->dimensions.x = ER_MAX_ROOM_DIMENSION; + } + if ( pRoom_acoustics->dimensions.y < ER_MIN_ROOM_DIMENSION ) + { + pRoom_acoustics->dimensions.y = ER_MIN_ROOM_DIMENSION; + } + if ( pRoom_acoustics->dimensions.y > ER_MAX_ROOM_DIMENSION ) + { + pRoom_acoustics->dimensions.y = ER_MAX_ROOM_DIMENSION; + } + if ( pRoom_acoustics->dimensions.z < ER_MIN_ROOM_DIMENSION ) + { + pRoom_acoustics->dimensions.z = ER_MIN_ROOM_DIMENSION; + } + if ( pRoom_acoustics->dimensions.z > ER_MAX_ROOM_DIMENSION ) + { + pRoom_acoustics->dimensions.z = ER_MAX_ROOM_DIMENSION; + } + + /* Abs Coeff */ + for ( wall_idx = 0; wall_idx < ER_ABS_COEFF; wall_idx++ ) + { + if ( pRoom_acoustics->AbsCoeff[wall_idx] < ER_MIN_ABS_COEFF ) + { + pRoom_acoustics->AbsCoeff[wall_idx] = ER_MIN_ABS_COEFF; + } + if ( pRoom_acoustics->AbsCoeff[wall_idx] > ER_MAX_ABS_COEFF ) + { + pRoom_acoustics->AbsCoeff[wall_idx] = ER_MAX_ABS_COEFF; + } + } + } + +#endif + return IVAS_ERR_OK; } @@ -1734,6 +1785,10 @@ static ivas_error RenderConfigReader_readBinary( } #ifdef EARLY_REFLECTIONS + /*****************************************/ + /* Read the early reflections parameters */ + /*****************************************/ + /* Has early reflections */ if ( ( error = read_bin_bool( pRenderConfigReader, &value ) ) != IVAS_ERR_OK ) { @@ -1748,6 +1803,8 @@ static ivas_error RenderConfigReader_readBinary( /* Initialize memory pointers to allow safe freeing ico eg errors */ pRenderConfigReader->pAE[n].pEarlyReflections->pListenerOrigin = NULL; + pRenderConfigReader->pAE[n].pEarlyReflections->use_er = 1; + /* Room sizes */ if ( ( error = get_bin_distance( pRenderConfigReader, true, &pRenderConfigReader->pAE[n].pEarlyReflections->dimensions.x ) ) != IVAS_ERR_OK ) { @@ -1812,6 +1869,16 @@ static ivas_error RenderConfigReader_readBinary( return error; } } + else /* load defaults if origin is not specified in config */ + { + if ( ( pRenderConfigReader->pAE[n].pEarlyReflections->pListenerOrigin = malloc( sizeof( IVAS_VECTOR3 ) ) ) == NULL ) + { + return IVAS_ERR_FAILED_ALLOC; + } + pRenderConfigReader->pAE[n].pEarlyReflections->pListenerOrigin->x = ER_LIST_ORIGIN_X; + pRenderConfigReader->pAE[n].pEarlyReflections->pListenerOrigin->y = ER_LIST_ORIGIN_Y; + pRenderConfigReader->pAE[n].pEarlyReflections->pListenerOrigin->z = ER_LIST_HEIGHT; + } /* Low complexity mode */ if ( ( error = read_bin_bool( pRenderConfigReader, &pRenderConfigReader->pAE[n].pEarlyReflections->lowComplexity ) ) != IVAS_ERR_OK ) @@ -2557,6 +2624,10 @@ ivas_error RenderConfigReader_read( { return IVAS_ERR_INVALID_RENDER_CONFIG; } + else if ( aeHasERsize == TRUE && aeHasERabs == TRUE ) + { + pRenderConfigReader->pAE[acIdx].pEarlyReflections->use_er = 1; + } #endif free( pValue ); @@ -2973,6 +3044,9 @@ ivas_error RenderConfigReader_getAcousticEnvironment( ) { uint16_t n, m; +#ifdef EARLY_REFLECTIONS + uint16_t j; +#endif if ( pRenderConfigReader == NULL || pAcEnv == NULL ) { @@ -2985,13 +3059,38 @@ ivas_error RenderConfigReader_getAcousticEnvironment( { pAcEnv->nBands = (int16_t) pRenderConfigReader->pAE[n].pFG->nrBands; pAcEnv->inputPreDelay = pRenderConfigReader->pAE[n].preDelay; - for ( m = 0; m < pAcEnv->nBands; m++ ) { pAcEnv->pFc_input[m] = pRenderConfigReader->pAE[n].pFG->pFc[m]; pAcEnv->pAcoustic_rt60[m] = pRenderConfigReader->pAE[n].pRT60[m]; pAcEnv->pAcoustic_dsr[m] = pRenderConfigReader->pAE[n].pDSR[m]; } + +#ifdef EARLY_REFLECTIONS + /* If ER are allocated then propagate parameters */ + if ( pRenderConfigReader->pAE[n].pEarlyReflections != 0 ) + { + pAcEnv->use_er = pRenderConfigReader->pAE[n].pEarlyReflections->use_er; /* ER activation flag */ + pAcEnv->lowComplexity = pRenderConfigReader->pAE[n].pEarlyReflections->lowComplexity; /* Low complexity flag */ + pAcEnv->dimensions = pRenderConfigReader->pAE[n].pEarlyReflections->dimensions; + /* Use default listener origin position if non provided */ + if ( pRenderConfigReader->pAE[n].pEarlyReflections->pListenerOrigin == NULL ) + { + if ( ( pRenderConfigReader->pAE[n].pEarlyReflections->pListenerOrigin = malloc( sizeof( IVAS_VECTOR3 ) ) ) == NULL ) + { + return IVAS_ERR_FAILED_ALLOC; + } + pRenderConfigReader->pAE[n].pEarlyReflections->pListenerOrigin->x = ER_LIST_ORIGIN_X; + pRenderConfigReader->pAE[n].pEarlyReflections->pListenerOrigin->y = ER_LIST_ORIGIN_Y; + pRenderConfigReader->pAE[n].pEarlyReflections->pListenerOrigin->z = ER_LIST_HEIGHT; + } + pAcEnv->ListenerOrigin = *pRenderConfigReader->pAE[n].pEarlyReflections->pListenerOrigin; + for ( j = 0; j < QC_ABS_COEFF; j++ ) + { + pAcEnv->AbsCoeff[j] = pRenderConfigReader->pAE[n].pEarlyReflections->pAbsCoeff[j]; + } + } +#endif return IVAS_ERR_OK; } } diff --git a/scripts/config/self_test.prm b/scripts/config/self_test.prm index 205ff96f1868166aec0a20989cc952337e27f8ec..c6cca4696261a9e238d130dfdd62a3842b8f795b 100644 --- a/scripts/config/self_test.prm +++ b/scripts/config/self_test.prm @@ -1167,6 +1167,22 @@ ../IVAS_cod -mc 7_1_4 512000 48 testv/stv714MC48c.wav bit ../IVAS_dec -render_config testv/rend_config_renderer.cfg BINAURAL_ROOM_REVERB 48 bit testv/stv714MC48c.wav_MC714_512000_48-48_MC_Config_renderer.tst +// Multi-channel 7_1_4 at 512 kbps, 48kHz in, 48kHz out, BINAURAL_ROOM out Config early reflections +../IVAS_cod -mc 7_1_4 512000 48 testv/stv714MC48c.wav bit +../IVAS_dec -render_config testv/rend_config_ER_v1.cfg BINAURAL_ROOM_REVERB 48 bit testv/stv714MC48c.wav_MC714_512000_48-48_ER_v1.tst + +// Multi-channel 7_1_4 at 512 kbps, 48kHz in, 48kHz out, BINAURAL_ROOM out Config early reflections, listener origin +../IVAS_cod -mc 7_1_4 512000 48 testv/stv714MC48c.wav bit +../IVAS_dec -render_config testv/rend_config_ER_v2.cfg BINAURAL_ROOM_REVERB 48 bit testv/stv714MC48c.wav_MC714_512000_48-48_MC_ER_v2.tst + +// Multi-channel 7_1_4 at 512 kbps, 48kHz in, 48kHz out, BINAURAL_ROOM out Config early reflections, low complexity, listener origin +../IVAS_cod -mc 7_1_4 512000 48 testv/stv714MC48c.wav bit +../IVAS_dec -render_config testv/rend_config_ER_v3.cfg BINAURAL_ROOM_REVERB 48 bit testv/stv714MC48c.wav_MC714_512000_48-48_MC_ER_v3.tst + +// Multi-channel 5_1 at 512 kbps, 48kHz in, 48kHz out, BINAURAL_ROOM out Config early reflections, head rotation +../IVAS_cod -mc 5_1 512000 48 testv/stv51MC48c.wav bit +../IVAS_dec -render_config testv/rend_config_ER_v1.cfg -t testv/headrot_case00_3000_q.csv BINAURAL_ROOM_REVERB 48 bit testv/stv51MC48c.wav_MC51_512000_48-48_MC_ER_v1_hrot.tst + // Multi-channel 5_1 bitrate switching from 13.2 kbps to 512 kbps, 48kHz in, 48kHz out, 7_1_4 out ../IVAS_cod -mc 5_1 ../scripts/switchPaths/sw_mctech_5fr.bin 48 testv/stv51MC48c.wav bit ../IVAS_dec 7_1_4 48 bit testv/stv51MC48c.wav_sw_48-48_7_1_4.tst diff --git a/scripts/reverb/generate_acoustic_environments_metadata.py b/scripts/reverb/generate_acoustic_environments_metadata.py index 6c771319958276cadc67e132306689a87ddcf82e..5cd6195d03b8c46a9a744de3a443b84ad28f3876 100644 --- a/scripts/reverb/generate_acoustic_environments_metadata.py +++ b/scripts/reverb/generate_acoustic_environments_metadata.py @@ -499,13 +499,11 @@ def generate_reverb_payload_equivalent_to_rend_config_renderer_cfg_plus_early_re + '1' # hasEarlyReflections + concatenate(lambda d : get_distance_code(d, True), [ 3.0, 4.0, 2.5 ]) # erSize (room dimensions) - - + get_count_or_index_code(0) # erFreqGridIdx + concatenate(get_absorption_code, # erAbsCoeff [ 0.8, 0.8, 0.8, 0.8, 0.2, 0.6 ]) - + '0' # hasListenerOrigin + '0' # lowComplexity + + '0' # hasDirectivity , endian='big') @@ -557,8 +555,6 @@ def generate_reverb_payload_equivalent_to_rend_config_renderer_cfg_plus_early_re + '1' # hasEarlyReflections + concatenate(lambda code : get_distance_code(code, True), [ 3.0, 4.0, 2.5 ]) # erSize (room dimensions) - - + get_count_or_index_code(0) # erFreqGridIdx + concatenate(get_absorption_code, # erAbsCoeff [ 0.8, 0.8, 0.8, 0.8, 0.2, 0.6 ]) @@ -723,6 +719,233 @@ def generate_reverb_payload_equivalent_to_rend_config_recreation_cfg(): file.close() +def generate_reverb_payload_ER_v0(): + # 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(1) # fgdNrGrids + # frequency grid + + fgdMethod.Individual_Frequencies.value # fgdMethod + + get_count_or_index_code(24) # fgdNrBands + + + concatenate(get_frequency_code, # fgdCenterFreq + [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]) + + + get_count_or_index_code(1) # AcousticEnvCount + + get_id_code(0) # ID + + get_count_or_index_code(0) # FreqGridID + + get_duration_code(0.1) # (input)Predelay + + + concatenate(get_duration_code, # RT60 + [0.87, 0.66, 0.47, 0.41, + 0.32, 0.37, 0.28, 0.30, + 0.29, 0.29, 0.28, 0.30, + 0.31, 0.34, 0.34, 0.34, + 0.34, 0.33, 0.32, 0.29, + 0.28, 0.24, 0.24, 0.2]) + + + concatenate(get_dsr_code, # DSR + [2.511887e-07, 1e-07, 1.2589251e-07, 1e-07, + 5.01187e-08, 5.01187e-08, 7.9432844e-08, 1e-07, + 6.309576e-08, 5.01187e-08, 7.9432844e-08, 1e-07, + 5.01187e-08, 1e-07, 7.9432844e-08, 6.309576e-08, + 7.9432844e-08, 5.01187e-08, 6.309576e-08, 3.9810708e-08, + 3.9810708e-08, 2.511887e-08, 1.9952632e-08, 1.2589251e-08]) + + + '1' # hasEarlyReflections + + concatenate(lambda code : get_distance_code(code, True), + [ 2.0, 2.0, 3.0 ]) # room dimensions + + concatenate(get_absorption_code, # absorptionCode + [ 0.2, 0.1, 0.1, 0.1, 0.3, 0.1 ]) + + '1' # listener origin flag + + '1' # isPositiveX + + '1' # isPositiveY + + concatenate(lambda d : get_distance_code(d, True), + [ 0.0, 0.0, 1.5 ]) # listener origin (x, y, z) + + '1' # lowComplexity + + '0' # directivity + , endian='big') + + file = open('rend_config_ER_v0.dat', 'wb') + data.tofile(file) + file.close() + + +def generate_reverb_payload_ER_v1(): + # 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(1) # fgdNrGrids + # frequency grid + + fgdMethod.Individual_Frequencies.value # fgdMethod + + get_count_or_index_code(24) # fgdNrBands + + + concatenate(get_frequency_code, # fgdCenterFreq + [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]) + + + get_count_or_index_code(1) # AcousticEnvCount + + get_id_code(0) # ID + + get_count_or_index_code(0) # FreqGridID + + get_duration_code(0.1) # (input)Predelay + + + concatenate(get_duration_code, # RT60 + [0.87, 0.66, 0.47, 0.41, + 0.32, 0.37, 0.28, 0.30, + 0.29, 0.29, 0.28, 0.30, + 0.31, 0.34, 0.34, 0.34, + 0.34, 0.33, 0.32, 0.29, + 0.28, 0.24, 0.24, 0.2]) + + + concatenate(get_dsr_code, # DSR + [2.511887e-07, 1e-07, 1.2589251e-07, 1e-07, + 5.01187e-08, 5.01187e-08, 7.9432844e-08, 1e-07, + 6.309576e-08, 5.01187e-08, 7.9432844e-08, 1e-07, + 5.01187e-08, 1e-07, 7.9432844e-08, 6.309576e-08, + 7.9432844e-08, 5.01187e-08, 6.309576e-08, 3.9810708e-08, + 3.9810708e-08, 2.511887e-08, 1.9952632e-08, 1.2589251e-08]) + + + '1' # hasEarlyReflections + + concatenate(lambda code : get_distance_code(code, True), + [ 3.0, 3.0, 4.0 ]) # room dimensions + + concatenate(get_absorption_code, # absorptionCode + [ 0.3, 0.2, 0.2, 0.2, 0.3, 0.1 ]) + + '0' # listener origin flag + + '0' # lowComplexity + + '0' # directivity + , endian='big') + + file = open('rend_config_ER_v1.dat', 'wb') + data.tofile(file) + file.close() + +def generate_reverb_payload_ER_v2(): + # 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(1) # fgdNrGrids + # frequency grid + + fgdMethod.Individual_Frequencies.value # fgdMethod + + get_count_or_index_code(24) # fgdNrBands + + + concatenate(get_frequency_code, # fgdCenterFreq + [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]) + + + get_count_or_index_code(1) # AcousticEnvCount + + get_id_code(0) # ID + + get_count_or_index_code(0) # FreqGridID + + get_duration_code(0.1) # (input)Predelay + + + concatenate(get_duration_code, # RT60 + [0.87, 0.66, 0.47, 0.41, + 0.32, 0.37, 0.28, 0.30, + 0.29, 0.29, 0.28, 0.30, + 0.31, 0.34, 0.34, 0.34, + 0.34, 0.33, 0.32, 0.29, + 0.28, 0.24, 0.24, 0.2]) + + + concatenate(get_dsr_code, # DSR + [2.511887e-07, 1e-07, 1.2589251e-07, 1e-07, + 5.01187e-08, 5.01187e-08, 7.9432844e-08, 1e-07, + 6.309576e-08, 5.01187e-08, 7.9432844e-08, 1e-07, + 5.01187e-08, 1e-07, 7.9432844e-08, 6.309576e-08, + 7.9432844e-08, 5.01187e-08, 6.309576e-08, 3.9810708e-08, + 3.9810708e-08, 2.511887e-08, 1.9952632e-08, 1.2589251e-08]) + + + '1' # hasEarlyReflections + + concatenate(lambda code : get_distance_code(code, True), + [ 3.0, 3.0, 4.0 ]) # room dimensions + + concatenate(get_absorption_code, # absorptionCode + [ 0.3, 0.2, 0.3, 0.4, 0.3, 0.4 ]) + + '1' # listener origin flag + + '1' # isPositiveX + + '0' # isPositiveY + + concatenate(lambda d : get_distance_code(d, True), + [ 0.5, 0.5, 1.5]) # listener origin (x, y, z) + + '0' # lowComplexity + + '0' # directivity + , endian='big') + + file = open('rend_config_ER_v2.dat', 'wb') + data.tofile(file) + file.close() + + +def generate_reverb_payload_ER_v3(): + # 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(1) # fgdNrGrids + # frequency grid + + fgdMethod.Individual_Frequencies.value # fgdMethod + + get_count_or_index_code(24) # fgdNrBands + + + concatenate(get_frequency_code, # fgdCenterFreq + [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]) + + + get_count_or_index_code(1) # AcousticEnvCount + + get_id_code(0) # ID + + get_count_or_index_code(0) # FreqGridID + + get_duration_code(0.1) # (input)Predelay + + + concatenate(get_duration_code, # RT60 + [0.87, 0.66, 0.47, 0.41, + 0.32, 0.37, 0.28, 0.30, + 0.29, 0.29, 0.28, 0.30, + 0.31, 0.34, 0.34, 0.34, + 0.34, 0.33, 0.32, 0.29, + 0.28, 0.24, 0.24, 0.2]) + + + concatenate(get_dsr_code, # DSR + [2.511887e-07, 1e-07, 1.2589251e-07, 1e-07, + 5.01187e-08, 5.01187e-08, 7.9432844e-08, 1e-07, + 6.309576e-08, 5.01187e-08, 7.9432844e-08, 1e-07, + 5.01187e-08, 1e-07, 7.9432844e-08, 6.309576e-08, + 7.9432844e-08, 5.01187e-08, 6.309576e-08, 3.9810708e-08, + 3.9810708e-08, 2.511887e-08, 1.9952632e-08, 1.2589251e-08]) + + + '1' # hasEarlyReflections + + concatenate(lambda code : get_distance_code(code, True), + [4.0, 4.0, 5.0]) # room dimensions + + concatenate(get_absorption_code, # absorptionCode + [0.1, 0.2, 0.2, 0.2, 0.1, 0.1]) + + '1' # listener origin flag + + '0' # isPositiveX + + '1' # isPositiveY + + concatenate(lambda d : get_distance_code(d, True), + [ 1.0, 0.5, 1.5]) # listener origin (x, y, z) + + '1' # lowComplexity + + '0' # directivity + , endian='big') + + file = open('rend_config_ER_v3.dat', 'wb') + data.tofile(file) + file.close() + + if __name__ == "__main__": #test() generate_reverb_payload_equivalent_to_rend_config_renderer_cfg() @@ -731,6 +954,12 @@ if __name__ == "__main__": generate_reverb_payload_equivalent_to_rend_config_renderer_directivity_cfg() generate_reverb_payload_equivalent_to_config_directivity_cfg() + # generate_reverb_payload_aggressive_ER() + + generate_reverb_payload_ER_v0() + generate_reverb_payload_ER_v1() + generate_reverb_payload_ER_v2() + generate_reverb_payload_ER_v3() - #generate_reverb_payload_equivalent_to_rend_config_renderer_cfg_plus_early_reflections_no_listener_origin() - #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() + # generate_reverb_payload_equivalent_to_rend_config_renderer_cfg_plus_early_reflections_listener_origin() \ No newline at end of file diff --git a/scripts/testv/rend_config_ER_v0.cfg b/scripts/testv/rend_config_ER_v0.cfg new file mode 100644 index 0000000000000000000000000000000000000000..1d3e6fa4f828daa1c8699e9a3d195da4b87cfdd2 --- /dev/null +++ b/scripts/testv/rend_config_ER_v0.cfg @@ -0,0 +1,38 @@ +[roomAcoustics] +frequencyGridCount = 1; +acousticEnvironmentCount = 1; + +[frequencyGrid:0] +method = individualFrequencies; +nrBands = 24; +frequencies = [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]; + +[acousticEnvironment:0] +frequencyGridIndex = 0; +predelay = 0.108; +rt60 = [0.87, 0.66, 0.47, 0.41, + 0.32, 0.37, 0.28, 0.30, + 0.29, 0.29, 0.28, 0.30, + 0.31, 0.34, 0.34, 0.34, + 0.34, 0.33, 0.32, 0.29, + 0.28, 0.24, 0.24, 0.2]; + +dsr = [2.511887e-07, 1e-07, 1.2589251e-07, 1e-07, + 5.01187e-08, 5.01187e-08, 7.9432844e-08, 1e-07, + 6.309576e-08, 5.01187e-08, 7.9432844e-08, 1e-07, + 5.01187e-08, 1e-07, 7.9432844e-08, 6.309576e-08, + 7.9432844e-08, 5.01187e-08, 6.309576e-08, 3.9810708e-08, + 3.9810708e-08, 2.511887e-08, 1.9952632e-08, 1.2589251e-08]; + +earlyReflectionsSize = [ 2.0, 2.0, 3.0 ]; +absorptionCoeffs = [ 0.2, 0.1, 0.1, 0.1, 0.3, 0.1 ]; +lowComplexity = TRUE; +listenerOrigin = [ 0.0, 0.0, 1.5 ]; + +#[general] +#binaryConfig = rend_config_ER_v0.dat; \ No newline at end of file diff --git a/scripts/testv/rend_config_ER_v0.dat b/scripts/testv/rend_config_ER_v0.dat new file mode 100644 index 0000000000000000000000000000000000000000..af1e7ffa16110a821969c2ea24c546d561f0eff3 --- /dev/null +++ b/scripts/testv/rend_config_ER_v0.dat @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a0e5cdb59fa93168feb1d4b973b1b2c2128fe103db5422b5ac4249f51bbf45a0 +size 84 diff --git a/scripts/testv/rend_config_ER_v1.cfg b/scripts/testv/rend_config_ER_v1.cfg new file mode 100644 index 0000000000000000000000000000000000000000..3a6228e863af293bc936b389b475edaa70f4e6b6 --- /dev/null +++ b/scripts/testv/rend_config_ER_v1.cfg @@ -0,0 +1,37 @@ +[roomAcoustics] +frequencyGridCount = 1; +acousticEnvironmentCount = 1; + +[frequencyGrid:0] +method = individualFrequencies; +nrBands = 24; +frequencies = [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]; + +[acousticEnvironment:0] +frequencyGridIndex = 0; +predelay = 0.108; +rt60 = [0.87, 0.66, 0.47, 0.41, + 0.32, 0.37, 0.28, 0.30, + 0.29, 0.29, 0.28, 0.30, + 0.31, 0.34, 0.34, 0.34, + 0.34, 0.33, 0.32, 0.29, + 0.28, 0.24, 0.24, 0.2]; + +dsr = [2.511887e-07, 1e-07, 1.2589251e-07, 1e-07, + 5.01187e-08, 5.01187e-08, 7.9432844e-08, 1e-07, + 6.309576e-08, 5.01187e-08, 7.9432844e-08, 1e-07, + 5.01187e-08, 1e-07, 7.9432844e-08, 6.309576e-08, + 7.9432844e-08, 5.01187e-08, 6.309576e-08, 3.9810708e-08, + 3.9810708e-08, 2.511887e-08, 1.9952632e-08, 1.2589251e-08]; + +earlyReflectionsSize = [3.0, 3.0, 4.0]; +absorptionCoeffs = [ 0.3, 0.2, 0.2, 0.2, 0.3, 0.1 ]; +lowComplexity = FALSE; + +#[general] +#binaryConfig = rend_config_ER_v1.dat; \ No newline at end of file diff --git a/scripts/testv/rend_config_ER_v1.dat b/scripts/testv/rend_config_ER_v1.dat new file mode 100644 index 0000000000000000000000000000000000000000..187af6705809c39800245499f319764f78d05693 --- /dev/null +++ b/scripts/testv/rend_config_ER_v1.dat @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4a92c702caf083634ffbcbd013d5c7fe2ad5bf09ebd4440c1021e9b56b3f33ae +size 80 diff --git a/scripts/testv/rend_config_ER_v2.cfg b/scripts/testv/rend_config_ER_v2.cfg new file mode 100644 index 0000000000000000000000000000000000000000..2d504af6ba2105df3fb012a87c480a604f211f78 --- /dev/null +++ b/scripts/testv/rend_config_ER_v2.cfg @@ -0,0 +1,38 @@ +[roomAcoustics] +frequencyGridCount = 1; +acousticEnvironmentCount = 1; + +[frequencyGrid:0] +method = individualFrequencies; +nrBands = 24; +frequencies = [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]; + +[acousticEnvironment:0] +frequencyGridIndex = 0; +predelay = 0.108; +rt60 = [0.87, 0.66, 0.47, 0.41, + 0.32, 0.37, 0.28, 0.30, + 0.29, 0.29, 0.28, 0.30, + 0.31, 0.34, 0.34, 0.34, + 0.34, 0.33, 0.32, 0.29, + 0.28, 0.24, 0.24, 0.2]; + +dsr = [2.511887e-07, 1e-07, 1.2589251e-07, 1e-07, + 5.01187e-08, 5.01187e-08, 7.9432844e-08, 1e-07, + 6.309576e-08, 5.01187e-08, 7.9432844e-08, 1e-07, + 5.01187e-08, 1e-07, 7.9432844e-08, 6.309576e-08, + 7.9432844e-08, 5.01187e-08, 6.309576e-08, 3.9810708e-08, + 3.9810708e-08, 2.511887e-08, 1.9952632e-08, 1.2589251e-08]; + +earlyReflectionsSize = [3.0, 3.0, 4.0]; +absorptionCoeffs = [ 0.3, 0.2, 0.3, 0.4, 0.3, 0.4 ]; +lowComplexity = FALSE; +listenerOrigin = [0.5, -0.5, 1.5]; + +#[general] +#binaryConfig = rend_config_ER_v2.dat; \ No newline at end of file diff --git a/scripts/testv/rend_config_ER_v2.dat b/scripts/testv/rend_config_ER_v2.dat new file mode 100644 index 0000000000000000000000000000000000000000..57cc0ca3118d23a7e6d74ff8b23e6fe0bd6011e6 --- /dev/null +++ b/scripts/testv/rend_config_ER_v2.dat @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:75503e1e51276c3980f4bcf1a31a9fe632e3b14e88fe18652c7f17697aa580e5 +size 86 diff --git a/scripts/testv/rend_config_ER_v3.cfg b/scripts/testv/rend_config_ER_v3.cfg new file mode 100644 index 0000000000000000000000000000000000000000..a70c644a8a372e000caf3c69715821bdacda90c7 --- /dev/null +++ b/scripts/testv/rend_config_ER_v3.cfg @@ -0,0 +1,38 @@ +[roomAcoustics] +frequencyGridCount = 1; +acousticEnvironmentCount = 1; + +[frequencyGrid:0] +method = individualFrequencies; +nrBands = 24; +frequencies = [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]; + +[acousticEnvironment:0] +frequencyGridIndex = 0; +predelay = 0.108; +rt60 = [0.87, 0.66, 0.47, 0.41, + 0.32, 0.37, 0.28, 0.30, + 0.29, 0.29, 0.28, 0.30, + 0.31, 0.34, 0.34, 0.34, + 0.34, 0.33, 0.32, 0.29, + 0.28, 0.24, 0.24, 0.2]; + +dsr = [2.511887e-07, 1e-07, 1.2589251e-07, 1e-07, + 5.01187e-08, 5.01187e-08, 7.9432844e-08, 1e-07, + 6.309576e-08, 5.01187e-08, 7.9432844e-08, 1e-07, + 5.01187e-08, 1e-07, 7.9432844e-08, 6.309576e-08, + 7.9432844e-08, 5.01187e-08, 6.309576e-08, 3.9810708e-08, + 3.9810708e-08, 2.511887e-08, 1.9952632e-08, 1.2589251e-08]; + +earlyReflectionsSize = [4.0, 4.0, 5.0]; +absorptionCoeffs = [ 0.1, 0.2, 0.2, 0.2, 0.1, 0.1 ]; +lowComplexity = TRUE; +listenerOrigin = [-1, 0.5, 1.5]; + +#[general] +#binaryConfig = rend_config_ER_v3.dat; \ No newline at end of file diff --git a/scripts/testv/rend_config_ER_v3.dat b/scripts/testv/rend_config_ER_v3.dat new file mode 100644 index 0000000000000000000000000000000000000000..280cf26d0d9b2b24f827be29002505f179283392 --- /dev/null +++ b/scripts/testv/rend_config_ER_v3.dat @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:425e97bd84110a35bd204a5d7f60e2e01cc2e1e96611ed3bca4b5877380194d3 +size 85 diff --git a/scripts/testv/rend_config_renderer_cfg_plus_early_reflections_listener_origin.cfg b/scripts/testv/rend_config_renderer_cfg_plus_early_reflections_listener_origin.cfg new file mode 100644 index 0000000000000000000000000000000000000000..ead63890b5b0f400b4876679d314ca90fa968384 --- /dev/null +++ b/scripts/testv/rend_config_renderer_cfg_plus_early_reflections_listener_origin.cfg @@ -0,0 +1,2 @@ +[general] +binaryConfig = rend_config_renderer_cfg_plus_early_reflections_listener_origin.dat; \ No newline at end of file diff --git a/scripts/testv/rend_config_renderer_cfg_plus_early_reflections_listener_origin.dat b/scripts/testv/rend_config_renderer_cfg_plus_early_reflections_listener_origin.dat new file mode 100644 index 0000000000000000000000000000000000000000..4d16889420b92e61443e943ad8147c0ea4fbb244 --- /dev/null +++ b/scripts/testv/rend_config_renderer_cfg_plus_early_reflections_listener_origin.dat @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ff2025be8627eeaa88a58417ebf4a8bc02ef648e87897a63ef2e45a88e67565b +size 145 diff --git a/scripts/testv/rend_config_renderer_cfg_plus_early_reflections_no_listener_origin.cfg b/scripts/testv/rend_config_renderer_cfg_plus_early_reflections_no_listener_origin.cfg new file mode 100644 index 0000000000000000000000000000000000000000..2f122473c67ac7e57e5bf8c2a8f8a9cec21320df --- /dev/null +++ b/scripts/testv/rend_config_renderer_cfg_plus_early_reflections_no_listener_origin.cfg @@ -0,0 +1,2 @@ +[general] +binaryConfig = rend_config_renderer_cfg_plus_early_reflections_no_listener_origin.dat; \ No newline at end of file diff --git a/scripts/testv/rend_config_renderer_cfg_plus_early_reflections_no_listener_origin.dat b/scripts/testv/rend_config_renderer_cfg_plus_early_reflections_no_listener_origin.dat new file mode 100644 index 0000000000000000000000000000000000000000..39b5aaf89a866eac6309a4580152814ea03586a2 --- /dev/null +++ b/scripts/testv/rend_config_renderer_cfg_plus_early_reflections_no_listener_origin.dat @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5bab8146537e4d7051a727587d950ac73e857764cb5fa1a09fdb1c4323f470ea +size 139