From 53cf3d7b3a392d09351404867ac77037b2e3ee71 Mon Sep 17 00:00:00 2001 From: Erik Norvell Date: Mon, 17 Jul 2023 14:41:16 +0200 Subject: [PATCH 1/2] Added directivity in binary format under CONTROL_METADATA_DIRECTIVITY and scripts/reverb/*.py --- apps/decoder.c | 7 ++ lib_com/options.h | 1 + lib_util/render_config_reader.c | 118 ++++++++++++++++++ ...ustic_environment_renderer_directivity.cfg | 34 +++++ ...generate_acoustic_environments_metadata.py | 21 +++- scripts/reverb/text_to_binary_payload.py | 29 +++-- .../rend_config_renderer_directivity.cfg | 31 +++++ .../rend_config_renderer_directivity.dat | 3 + 8 files changed, 229 insertions(+), 15 deletions(-) create mode 100644 scripts/reverb/acoustic_environment_renderer_directivity.cfg create mode 100644 scripts/testv/rend_config_renderer_directivity.cfg create mode 100644 scripts/testv/rend_config_renderer_directivity.dat diff --git a/apps/decoder.c b/apps/decoder.c index cb70713e59..54ea44416a 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -583,6 +583,13 @@ int main( fprintf( stderr, "Failed to get acoustic environment with ID: %d\n\n", ACOUSTIC_ENVIRONMENT_ID ); goto cleanup; } +#ifdef CONTROL_METADATA_DIRECTIVITY + if ( ( error = RenderConfigReader_getDirectivity( renderConfigReader, ACOUSTIC_ENVIRONMENT_ID, renderConfig.directivity ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Invalid directivity configuration parameters\n\n" ); + goto cleanup; + } +#endif #endif renderConfig.room_acoustics.override = true; diff --git a/lib_com/options.h b/lib_com/options.h index dc480c270b..7c9936973d 100755 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -145,6 +145,7 @@ #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 */ +#define CONTROL_METADATA_DIRECTIVITY /* Ericsson: Directivity renderer configuration */ #endif #define FIX_563_PARAMMC_LIMITER /* FhG: issue 563: fix ILD limiter when coming from silence w/o transient set */ #define FIX_560_VAD_FLAG /* Eri: Issue 560 - VAD flag issue for unified stereo */ diff --git a/lib_util/render_config_reader.c b/lib_util/render_config_reader.c index 833a508034..52864f6ef4 100644 --- a/lib_util/render_config_reader.c +++ b/lib_util/render_config_reader.c @@ -120,6 +120,9 @@ struct RenderConfigReader FrequencyGrid *pFG; /* Frequency grids */ uint32_t nAE; /* Number of acoustic environments */ AcousticEnv *pAE; /* Acoustic environments */ +#ifdef CONTROL_METADATA_DIRECTIVITY + float directivity[3]; /* Source directivity */ +#endif #endif }; @@ -916,6 +919,59 @@ static ivas_error get_absorption( return IVAS_ERR_OK; } +#ifdef CONTROL_METADATA_DIRECTIVITY +/*-----------------------------------------------------------------------------------------* + * Function get_angle() + * Gets an angle value in degrees [0,360] + *-----------------------------------------------------------------------------------------*/ + +static ivas_error get_angle( + RenderConfigReader *this, /* i/o : Render config reader handle */ + float *pResult /* o : Angle value */ +) +{ + ivas_error error; + uint32_t value; + + if ( ( error = read_bits( this, &value, 5 ) ) != IVAS_ERR_OK ) + { + return error; + } + + *pResult = usdequant( (int16_t) value, 0.0f, 20.0f ); + + return IVAS_ERR_OK; +} + +/*-----------------------------------------------------------------------------------------* + * Function get_outer_attenuation () + * Gets an outer attenuation value [3.1623e-05,1.0], or in dB: [-90,0] + *-----------------------------------------------------------------------------------------*/ + +static ivas_error get_outer_attenuation( + RenderConfigReader *this, /* i/o : Render config reader handle */ + float *pResult /* o : Attenuation value */ +) +{ + ivas_error error; + uint32_t value; + float logval, att; + + if ( ( error = read_bits( this, &value, 5 ) ) != IVAS_ERR_OK ) + { + return error; + } + + logval = usdequant( (int16_t) value, -90.0f, 3.0f ); + att = powf( 10, logval / 20.0f ); + + *pResult = att; + + return IVAS_ERR_OK; +} + +#endif + #else /*-----------------------------------------------------------------------------------------* * Function read_bool() @@ -1618,6 +1674,34 @@ static ivas_error RenderConfigReader_readReverb( } } } +#endif +#ifdef CONTROL_METADATA_DIRECTIVITY + /* Has source directivity */ + if ( ( error = read_bool( pRenderConfigReader, &value ) ) != IVAS_ERR_OK ) + { + return error; + } + if ( value == true ) + { + if ( ( error = get_angle( pRenderConfigReader, &pRenderConfigReader->directivity[0] ) ) != IVAS_ERR_OK ) + { + return error; + } + if ( ( error = get_angle( pRenderConfigReader, &pRenderConfigReader->directivity[1] ) ) != IVAS_ERR_OK ) + { + return error; + } + if ( ( error = get_outer_attenuation( pRenderConfigReader, &pRenderConfigReader->directivity[2] ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else + { + pRenderConfigReader->directivity[0] = 360.0f; + pRenderConfigReader->directivity[1] = 360.0f; + pRenderConfigReader->directivity[2] = 1.0f; + } #endif } @@ -1937,6 +2021,40 @@ ivas_error RenderConfigReader_getAcousticEnvironment( } return IVAS_ERR_ACOUSTIC_ENVIRONMENT_MISSING; } + +#ifdef CONTROL_METADATA_DIRECTIVITY +/*------------------------------------------------------------------------------------------* + * RenderConfigReader_getDirectivity() + * + * Gets Acoustic environment with a given ID + *------------------------------------------------------------------------------------------*/ + +ivas_error RenderConfigReader_getDirectivity( + RenderConfigReader *pRenderConfigReader, /* i : RenderConfigReader handle */ + uint16_t id, /* i : Acoustic environment ID */ + float *directivity /* o : directivity */ +) +{ + uint16_t n; + + if ( pRenderConfigReader == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + for ( n = 0; n < pRenderConfigReader->nAE; n++ ) + { + if ( id == pRenderConfigReader->pAE[n].id ) + { + mvr2r( pRenderConfigReader->directivity, directivity, 3 ); + return IVAS_ERR_OK; + } + } + return IVAS_ERR_ACOUSTIC_ENVIRONMENT_MISSING; +} +#endif + + #endif /*------------------------------------------------------------------------------------------* diff --git a/scripts/reverb/acoustic_environment_renderer_directivity.cfg b/scripts/reverb/acoustic_environment_renderer_directivity.cfg new file mode 100644 index 0000000000..04b99f7f3c --- /dev/null +++ b/scripts/reverb/acoustic_environment_renderer_directivity.cfg @@ -0,0 +1,34 @@ +[frequencyGrid:0] +method = individualFrequencies +frequencies = [ + 20.0, 25.0, 31.5, 40.0, + 50.0, 63.0, 80.0, 100.0, + 125.0, 160.0, 200.0, 250.0, + 315.0, 400.0, 500.0, 630.0, + 800.0, 1000.0, 1250.0, 1600.0, + 2000.0, 2500.0, 3150.0, 4000.0, + 5000.0, 6300.0, 8000.0, 10000.0, + 12500.0, 16000.0, 20000.0] + +[acousticEnvironment:0] +id = 0 +frequencyGridIndex = 0 +predelay = 0.1 +rt60 = [ + 1.3622, 1.4486, 1.3168, 1.5787, + 1.4766, 1.3954, 1.2889, 1.3462, + 1.0759, 1.0401, 1.0970, 1.0850, + 1.0910, 1.0404, 1.0499, 1.0699, + 1.1028, 1.1714, 1.1027, 1.0666, + 1.0550, 1.0553, 1.0521, 1.0569, + 1.0421, 0.97822, 0.80487, 0.75944, + 0.71945, 0.61682, 0.60031] + +dsr = [ + 1.9952632e-08, 1.9952632e-08, 1.2589251e-08, 1.5848926e-08, 1.2589251e-08, 1.9952632e-08, 2.511887e-08, 3.9810708e-08, 1e-07, 1.9952633e-07, + 3.981071e-07, 6.3095763e-07, 7.943284e-07, 6.3095763e-07, 5.01187e-07, 5.01187e-07, 6.3095763e-07, 6.3095763e-07, 7.943284e-07, 6.3095763e-07, + 5.01187e-07, 6.3095763e-07, 6.3095763e-07, 6.3095763e-07, 5.01187e-07, 2.511887e-07, 1.2589251e-07, 1e-07, 6.309576e-08, 3.1622776e-08, + 2.511887e-08] + +[directivity:0] +directivity = [0.0, 360.0, 0.2512] diff --git a/scripts/reverb/generate_acoustic_environments_metadata.py b/scripts/reverb/generate_acoustic_environments_metadata.py index 5394d0cece..f723ebb4de 100644 --- a/scripts/reverb/generate_acoustic_environments_metadata.py +++ b/scripts/reverb/generate_acoustic_environments_metadata.py @@ -244,6 +244,18 @@ def get_dsr_code(dsr): return dsrCode[d] +def usquant(x,qlow,delta,cbsize): + nbits = math.ceil(math.log2(cbsize)) # nextpow2 + index = max(0,min(cbsize-1, round( ( x - qlow ) / delta ))) + return format(index,'0'+ str(nbits) + 'b') + +def get_angle_code(angle): + assert 0 <= angle <= 360 + return usquant(angle, 0, 20, 19) + +def get_outer_attenuation_code(att): + assert 0 <= att <= 1 + return usquant(20 * math.log10(att), -90, 3, 31) class fgdMethod(Enum): Individual_Frequencies = '00' @@ -426,6 +438,7 @@ def generate_reverb_payload_equivalent_to_rend_config_renderer_cfg(): 5.01187e-07, 6.3095763e-07, 6.3095763e-07, 6.3095763e-07, 5.01187e-07, 2.511887e-07, 1.2589251e-07, 1e-07, 6.309576e-08, 3.1622776e-08, 2.511887e-08 ]) + '0' # hasEarlyReflections + + '0' # hasDirectivity , endian='big') file = open('rend_config_renderer.dat', 'wb') @@ -481,7 +494,7 @@ def generate_reverb_payload_equivalent_to_rend_config_renderer_cfg_plus_early_re [ 0.8, 0.8, 0.8, 0.8, 0.2, 0.6 ]) + '0' # hasListenerOrigin - + + '0' # hasDirectivity , endian='big') file = open('rend_config_renderer_cfg_plus_early_reflections_no_listener_origin.dat', 'wb') @@ -542,7 +555,7 @@ def generate_reverb_payload_equivalent_to_rend_config_renderer_cfg_plus_early_re + '0' # isPositiveY + concatenate(lambda d : get_distance_code(d, True), [ 0.5, 0.5, 1.5 ]) # erListenerOrigin (x, y, z) - + + '0' # hasDirectivity , endian='big') file = open('rend_config_renderer_cfg_plus_early_reflections_listener_origin.dat', 'wb') @@ -583,7 +596,7 @@ def generate_reverb_payload_equivalent_to_rend_config_hospital_patientroom_cfg() 6.3095763e-06, 6.3095763e-06, 6.3095763e-06, 6.3095763e-06, 6.3095763e-06, 3.1622776e-06, 3.1622776e-06, 3.1622776e-06, 6.3095763e-07, 3.1622776e-07, 3.1622776e-07 ]) + '0' # hasEarlyReflections - + + '0' # hasDirectivity , endian='big') file = open('rend_config_hospital_patientroom.dat', 'wb') @@ -624,7 +637,7 @@ def generate_reverb_payload_equivalent_to_rend_config_recreation_cfg(): 3.1622776e-06, 2.511887e-06, 7.943284e-07, 6.3095763e-07, 6.3095763e-07, 5.01187e-08, 1.2589251e-08, 1.2589251e-08, 1.2589265e-09, 1.2589266e-11, 3.981075e-12 ]) + '0' # hasEarlyReflections - + + '0' # hasDirectivity , endian='big') file = open('rend_config_recreation.dat', 'wb') diff --git a/scripts/reverb/text_to_binary_payload.py b/scripts/reverb/text_to_binary_payload.py index c42c845b2a..00a10ede85 100644 --- a/scripts/reverb/text_to_binary_payload.py +++ b/scripts/reverb/text_to_binary_payload.py @@ -73,8 +73,8 @@ def parse_reverb_text_configuration_and_generate_binary_payload(file): files_parsed = config.read(file) assert len(files_parsed) == 1, 'file {} not successfully parsed'.format(file) - # collect dicts of frequency grid and acoustic environment sections - sections = { key : {} for key in ['frequencyGrid', 'acousticEnvironment' ] } + # collect dicts of frequency grid, acoustic environment and directivity sections + sections = { key : {} for key in ['frequencyGrid', 'acousticEnvironment', 'directivity' ] } for section_name in config.sections(): section, index = section_name.split(':') assert section in sections, 'unknown section name' @@ -140,6 +140,16 @@ def parse_reverb_text_configuration_and_generate_binary_payload(file): + get_bool_code(xyz[1] >= 0) # isPositiveY + concatenate(lambda d : get_distance_code(d, True), [abs(v) for v in xyz])) # erListenerOrigin + # parse directivity + hasDirectivity = len(sections['directivity']) > 0 + data += get_bool_code(hasDirectivity) # hasDirectivity + if hasDirectivity: + for _, dir in sections['directivity'].items(): + dir_values = eval_option(dir['directivity']) + data += bitarray(get_angle_code(dir_values[0]) # Directivity inner angle + + get_angle_code(dir_values[1]) # Directivity outer angle + + get_outer_attenuation_code(dir_values[2])) # Directivity outer attenuation + # generate binary file data.tofile(open(file.split('.')[0] + '.dat', 'wb')) @@ -152,12 +162,9 @@ if __name__ == "__main__": parse_reverb_text_configuration_and_generate_binary_payload(args.configuration_file) print("\nNote: the conversion algorithm uses quantization, which may lead to quantization errors.") - - # print maximum quantization errors exceeding float32 resolution - epsilon = 2e-7 # slighly larger than float32 epsilon - text = '' - for name in max_quantization_error.keys(): - if max_quantization_error[name] > epsilon: - text += '\n {:10s}: {:.1e}'.format(name, max_quantization_error[name]) - if len(text) > 0: - print('Maximum relative quantization errors > {}:'.format(epsilon) + text) \ No newline at end of file + print('Maximum relative quantization errors:') + print(' duration : {:.1e}'.format(max_quantization_error['duration'])) + print(' frequency : {:.1e}'.format(max_quantization_error['frequency'])) + print(' DSR : {:.1e}'.format(max_quantization_error['dsr'])) + print(' distance : {:.1e}'.format(max_quantization_error['distance'])) + print(' absorption: {:.1e}'.format(max_quantization_error['absorption'])) diff --git a/scripts/testv/rend_config_renderer_directivity.cfg b/scripts/testv/rend_config_renderer_directivity.cfg new file mode 100644 index 0000000000..9b7afb8294 --- /dev/null +++ b/scripts/testv/rend_config_renderer_directivity.cfg @@ -0,0 +1,31 @@ +[roomAcoustics] +nBands = 31; + +fc = [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]; + +rt60 = [1.3622, 1.4486, 1.3168, 1.5787, + 1.4766, 1.3954, 1.2889, 1.3462, + 1.0759, 1.0401, 1.0970, 1.0850, + 1.0910, 1.0404, 1.0499, 1.0699, + 1.1028, 1.1714, 1.1027, 1.0666, + 1.0550, 1.0553, 1.0521, 1.0569, + 1.0421, 0.97822, 0.80487, 0.75944, + 0.71945, 0.61682, 0.60031]; + +dsr = [1.9952632e-08, 1.9952632e-08, 1.2589251e-08, 1.5848926e-08, 1.2589251e-08, 1.9952632e-08, 2.511887e-08, 3.9810708e-08, 1e-07, 1.9952633e-07, + 3.981071e-07, 6.3095763e-07, 7.943284e-07, 6.3095763e-07, 5.01187e-07, 5.01187e-07, 6.3095763e-07, 6.3095763e-07, 7.943284e-07, 6.3095763e-07, + 5.01187e-07, 6.3095763e-07, 6.3095763e-07, 6.3095763e-07, 5.01187e-07, 2.511887e-07, 1.2589251e-07, 1e-07, 6.309576e-08, 3.1622776e-08, + 2.511887e-08]; + +acousticPreDelay = 0.016; +inputPreDelay = 0.1; + +[general] +reverbFile = rend_config_renderer_directivity.dat; diff --git a/scripts/testv/rend_config_renderer_directivity.dat b/scripts/testv/rend_config_renderer_directivity.dat new file mode 100644 index 0000000000..b7008158e0 --- /dev/null +++ b/scripts/testv/rend_config_renderer_directivity.dat @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b3c9760da0e54e5114eeb6f63bbf30e3c86b4c0379b89bd67fb4f692325a94ac +size 133 -- GitLab From 38bafccc97cc90bd0d1c32f4975a6ca30ac87d06 Mon Sep 17 00:00:00 2001 From: Erik Norvell Date: Mon, 17 Jul 2023 15:05:32 +0200 Subject: [PATCH 2/2] Fix missing function declaration in lib_util/render_config_reader.h --- lib_util/render_config_reader.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib_util/render_config_reader.h b/lib_util/render_config_reader.h index 4facb5b9cd..252338526e 100644 --- a/lib_util/render_config_reader.h +++ b/lib_util/render_config_reader.h @@ -62,6 +62,13 @@ ivas_error RenderConfigReader_getAcousticEnvironment( ivas_error RenderConfigReader_checkValues( IVAS_RENDER_CONFIG_HANDLE hRenderConfig /* o : Renderer configuration handle */ ); +#ifdef CONTROL_METADATA_DIRECTIVITY +ivas_error RenderConfigReader_getDirectivity( + RenderConfigReader *pRenderConfigReader, /* i : RenderConfigReader handle */ + uint16_t id, /* i : Acoustic environment ID */ + float *directivity /* o : directivity */ +); +#endif #endif /* Reads a configuration */ -- GitLab