From cc76f70dfa60119cdc491be9e71d39bdf9d4c7f9 Mon Sep 17 00:00:00 2001 From: Tapani Pihlajakuja Date: Mon, 20 Oct 2025 15:26:05 +0300 Subject: [PATCH 1/3] Port float MR 1917 to ivas-float-update. Object editing file interface. --- Workspace_msvc/lib_util.vcxproj | 2 + apps/decoder.c | 207 ++++++++++++++++++++++-- lib_com/ivas_error.h | 7 + lib_com/options.h | 2 + lib_dec/ivas_init_dec.c | 9 +- lib_dec/lib_dec.c | 56 ++++--- lib_util/obj_edit_file_reader.c | 278 ++++++++++++++++++++++++++++++++ lib_util/obj_edit_file_reader.h | 112 +++++++++++++ readme.txt | 21 +++ 9 files changed, 657 insertions(+), 37 deletions(-) create mode 100644 lib_util/obj_edit_file_reader.c create mode 100644 lib_util/obj_edit_file_reader.h diff --git a/Workspace_msvc/lib_util.vcxproj b/Workspace_msvc/lib_util.vcxproj index 12dfa7610..01c90aadd 100644 --- a/Workspace_msvc/lib_util.vcxproj +++ b/Workspace_msvc/lib_util.vcxproj @@ -120,6 +120,7 @@ + @@ -145,6 +146,7 @@ + diff --git a/apps/decoder.c b/apps/decoder.c index e0a57f0c4..bbc4c050a 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -32,6 +32,9 @@ #include "lib_dec.h" #include +#ifdef FIX_1217_OBJECT_EDIT_FILE_INTERFACE +#include +#endif #include "cmdl_tools.h" #include "audio_file_writer.h" #include "bitstream_reader.h" @@ -47,6 +50,9 @@ #include "aeid_file_reader.h" #endif #include "split_render_file_read_write.h" +#ifdef FIX_1217_OBJECT_EDIT_FILE_INTERFACE +#include "obj_edit_file_reader.h" +#endif #ifdef VARIABLE_SPEED_DECODING #include "tsm_scale_file_reader.h" #include @@ -156,6 +162,9 @@ typedef struct #ifdef OBJ_EDITING_COMMANDLINE bool objEditEnabled; #endif +#ifdef FIX_1217_OBJECT_EDIT_FILE_INTERFACE + char *objEditFileName; +#endif } DecArguments; @@ -184,8 +193,13 @@ typedef struct static bool parseCmdlIVAS_dec( int16_t argc, char **argv, DecArguments *arg ); static void usage_dec( void ); +#ifdef FIX_1217_OBJECT_EDIT_FILE_INTERFACE +static ivas_error decodeG192( DecArguments arg, BS_READER_HANDLE hBsReader, IVAS_DEC_HRTF_BINARY_WRAPPER *hHrtfBinary, RotFileReader *headRotReader, RotFileReader *externalOrientationFileReader, RotFileReader *refRotReader, Vector3PairFileReader *referenceVectorReader, ObjectEditFileReader *objectEditFileReader, ISAR_SPLIT_REND_BITS_DATA *splitRendBits, IVAS_DEC_HANDLE hIvasDec, int16_t *pcmBuf ); +static ivas_error decodeVoIP( DecArguments arg, BS_READER_HANDLE hBsReader, IVAS_DEC_HRTF_BINARY_WRAPPER *hHrtfBinary, RotFileReader *headRotReader, RotFileReader *externalOrientationFileReader, RotFileReader *refRotReader, Vector3PairFileReader *referenceVectorReader, ObjectEditFileReader *objectEditFileReader, IVAS_DEC_HANDLE hIvasDec ); +#else static ivas_error decodeG192( DecArguments arg, BS_READER_HANDLE hBsReader, IVAS_DEC_HRTF_BINARY_WRAPPER *hHrtfBinary, RotFileReader *headRotReader, RotFileReader *externalOrientationFileReader, RotFileReader *refRotReader, Vector3PairFileReader *referenceVectorReader, ISAR_SPLIT_REND_BITS_DATA *splitRendBits, IVAS_DEC_HANDLE hIvasDec, int16_t *pcmBuf ); static ivas_error decodeVoIP( DecArguments arg, BS_READER_HANDLE hBsReader, IVAS_DEC_HRTF_BINARY_WRAPPER *hHrtfBinary, RotFileReader *headRotReader, RotFileReader *externalOrientationFileReader, RotFileReader *refRotReader, Vector3PairFileReader *referenceVectorReader, IVAS_DEC_HANDLE hIvasDec ); +#endif static ivas_error load_hrtf_from_file( IVAS_DEC_HRTF_BINARY_WRAPPER *hHrtfBinary, IVAS_DEC_HANDLE hIvasDec, const IVAS_AUDIO_CONFIG OutputConfig, const int32_t output_Fs ); #ifdef DEBUGGING static ivas_error printBitstreamInfoVoip( DecArguments arg, BS_READER_HANDLE hBsReader, IVAS_DEC_HANDLE hIvasDec ); @@ -193,8 +207,12 @@ static int16_t app_own_random( int16_t *seed ); static IVAS_DEC_FORCED_REND_MODE parseForcedRendModeDec( char *forcedRendModeChar ); #endif #ifdef OBJ_EDITING_EXAMPLE +#ifdef FIX_1217_OBJECT_EDIT_FILE_INTERFACE +static void do_object_editing( IVAS_EDITABLE_PARAMETERS *editableParameters, ObjectEditFileReader *objectEditFileReader ); +#else static void do_object_editing( IVAS_EDITABLE_PARAMETERS *editableParameters ); #endif +#endif /*------------------------------------------------------------------------------------------* @@ -226,6 +244,9 @@ int main( int16_t *pcmBuf = NULL; IVAS_RENDER_FRAMESIZE asked_frame_size; IVAS_DEC_HRTF_BINARY_WRAPPER hHrtfBinary; +#ifdef FIX_1217_OBJECT_EDIT_FILE_INTERFACE + ObjectEditFileReader *objectEditFileReader = NULL; +#endif #ifdef DEBUGGING int32_t noClipping; int32_t cnt_frames_limited; @@ -429,6 +450,21 @@ int main( } } +#ifdef FIX_1217_OBJECT_EDIT_FILE_INTERFACE + /*------------------------------------------------------------------------------------------* + * Open object editing instruction file + *------------------------------------------------------------------------------------------*/ + + if ( arg.objEditFileName != NULL ) + { + if ( ( error = ObjectEditFileReader_open( arg.objEditFileName, &objectEditFileReader ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError: Can't open Object editing instruction file %s \n\n", arg.objEditFileName ); + goto cleanup; + } + } +#endif + /*------------------------------------------------------------------------------------------* * Configure the decoder *------------------------------------------------------------------------------------------*/ @@ -765,11 +801,19 @@ int main( if ( arg.voipMode ) { +#ifdef FIX_1217_OBJECT_EDIT_FILE_INTERFACE + error = decodeVoIP( arg, hBsReader, &hHrtfBinary, headRotReader, externalOrientationFileReader, refRotReader, referenceVectorReader, objectEditFileReader, hIvasDec ); +#else error = decodeVoIP( arg, hBsReader, &hHrtfBinary, headRotReader, externalOrientationFileReader, refRotReader, referenceVectorReader, hIvasDec ); +#endif } else { +#ifdef FIX_1217_OBJECT_EDIT_FILE_INTERFACE + error = decodeG192( arg, hBsReader, &hHrtfBinary, headRotReader, externalOrientationFileReader, refRotReader, referenceVectorReader, objectEditFileReader, &splitRendBits, hIvasDec, pcmBuf ); +#else error = decodeG192( arg, hBsReader, &hHrtfBinary, headRotReader, externalOrientationFileReader, refRotReader, referenceVectorReader, &splitRendBits, hIvasDec, pcmBuf ); +#endif } if ( error == IVAS_ERR_OK || error == IVAS_ERR_END_OF_FILE ) @@ -834,6 +878,9 @@ cleanup: RotationFileReader_close( &refRotReader ); Vector3PairFileReader_close( &referenceVectorReader ); RenderConfigReader_close( &renderConfigReader ); +#ifdef FIX_1217_OBJECT_EDIT_FILE_INTERFACE + ObjectEditFileReader_close( &objectEditFileReader ); +#endif if ( BS_Reader_Close( &hBsReader ) != IVAS_ERR_OK ) { @@ -1034,6 +1081,9 @@ static bool parseCmdlIVAS_dec( #ifdef OBJ_EDITING_COMMANDLINE arg->objEditEnabled = false; #endif +#ifdef FIX_1217_OBJECT_EDIT_FILE_INTERFACE + arg->objEditFileName = NULL; +#endif /*-----------------------------------------------------------------* * Initialization @@ -1568,6 +1618,24 @@ static bool parseCmdlIVAS_dec( { arg->objEditEnabled = true; i++; +#ifdef FIX_1217_OBJECT_EDIT_FILE_INTERFACE + if ( argc - i <= 3 || argv[i][0] == '-' ) + { + fprintf( stderr, "Error: Object editing instruction filename not specified!\n\n" ); + usage_dec(); + return false; + } + + if ( strcmp( argv[i], "NULL" ) == 0 || strcmp( argv[i], "null" ) == 0 ) + { + arg->objEditFileName = NULL; /* use the built-in editing function */ + } + else + { + arg->objEditFileName = argv[i]; /* read edit instructions from this file */ + } + i++; +#endif } #endif @@ -1751,7 +1819,7 @@ static void usage_dec( void ) fprintf( stdout, " works only in combination with '-otr ref_vec' and 'ref_vec_lev' modes\n" ); fprintf( stdout, "-render_config File : Renderer configuration File\n" ); fprintf( stdout, "-om File : Metadata output File for BINAURAL_SPLIT_PCM OutputConf (only for Fs = 48 kHz)\n" ); - fprintf( stdout, "-non_diegetic_pan P : panning mono non-diegetic sound to stereo with paning P, -90<= P <=90,\n" ); + fprintf( stdout, "-non_diegetic_pan P : panning mono non-diegetic sound to stereo with panning P, -90<= P <=90,\n" ); fprintf( stdout, " left or l or 90->left, right or r or -90->right, center or c or 0->middle\n" ); #ifdef DEBUGGING fprintf( stdout, "-FEC X : Insert frame erasures, X = 0-10 is the percentage\n" ); @@ -1778,7 +1846,11 @@ static void usage_dec( void ) #endif fprintf( stdout, " for BINAURAL_ROOM_REVERB output configuration.\n" ); #ifdef OBJ_EDITING_COMMANDLINE +#ifndef FIX_1217_OBJECT_EDIT_FILE_INTERFACE fprintf( stdout, "-obj_edit : Enable objects editing\n" ); +#else + fprintf( stdout, "-obj_edit File : Object editing instructions file or NULL for built-in example\n" ); +#endif #endif fprintf( stdout, "-level level : Complexity level, level = (1, 2, 3), will be defined after characterisation. \n" ); fprintf( stdout, " Currently, all values default to level 3 (full functionality).\n" ); @@ -2136,6 +2208,9 @@ static ivas_error decodeG192( RotFileReader *externalOrientationFileReader, RotFileReader *refRotReader, Vector3PairFileReader *referenceVectorReader, +#ifdef FIX_1217_OBJECT_EDIT_FILE_INTERFACE + ObjectEditFileReader *objectEditFileReader, +#endif ISAR_SPLIT_REND_BITS_DATA *splitRendBits, IVAS_DEC_HANDLE hIvasDec, int16_t *pcmBuf ) @@ -2545,10 +2620,24 @@ static ivas_error decodeG192( return error; } +#ifdef FIX_1217_OBJECT_EDIT_FILE_INTERFACE + if ( arg.objEditFileName != NULL ) + { + if ( ( error = ObjectEditFileReader_readNextFrame( objectEditFileReader ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError: could not read object editing instructions from file: %s\n\n", IVAS_DEC_GetErrorMessage( error ) ); + return error; + } + } +#endif + /* Do object metadata editing here ... */ #ifdef OBJ_EDITING_EXAMPLE +#ifdef FIX_1217_OBJECT_EDIT_FILE_INTERFACE + do_object_editing( &editableParameters, objectEditFileReader ); +#else do_object_editing( &editableParameters ); - +#endif #endif /* set new object parameters*/ @@ -3076,6 +3165,9 @@ static ivas_error decodeVoIP( RotFileReader *externalOrientationFileReader, RotFileReader *refRotReader, Vector3PairFileReader *referenceVectorReader, +#ifdef FIX_1217_OBJECT_EDIT_FILE_INTERFACE + ObjectEditFileReader *objectEditFileReader, +#endif IVAS_DEC_HANDLE hIvasDec ) { bool decodingFailed = true; /* Assume failure until cleanup is reached without errors */ @@ -3356,6 +3448,17 @@ static ivas_error decodeVoIP( } } +#ifdef FIX_1217_OBJECT_EDIT_FILE_INTERFACE + if ( arg.objEditEnabled && ( arg.objEditFileName != NULL ) ) + { + if ( ( error = ObjectEditFileReader_readNextFrame( objectEditFileReader ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError: could not read object editing instructions from file: %s\n\n", IVAS_DEC_GetErrorMessage( error ) ); + return error; + } + } +#endif + /* read all packets with a receive time smaller than the system time */ while ( nextPacketRcvTime_ms <= systemTime_ms ) { @@ -3466,7 +3569,11 @@ static ivas_error decodeVoIP( /* Do object metadata editing here ... */ #ifdef OBJ_EDITING_EXAMPLE +#ifdef FIX_1217_OBJECT_EDIT_FILE_INTERFACE + do_object_editing( &editableParameters, objectEditFileReader ); +#else do_object_editing( &editableParameters ); +#endif #endif /* set new object parameters */ @@ -3776,7 +3883,12 @@ cleanup: *---------------------------------------------------------------------*/ static void do_object_editing( +#ifdef FIX_1217_OBJECT_EDIT_FILE_INTERFACE + IVAS_EDITABLE_PARAMETERS *editableParameters, + ObjectEditFileReader *objectEditFileReader ) +#else IVAS_EDITABLE_PARAMETERS *editableParameters ) +#endif { /* put the objects equally spaced at the horizontal plane */ /* and play a little bit with the gains... */ @@ -3792,29 +3904,92 @@ static void do_object_editing( } } - if ( num_nondiegetic_objects ) + #ifdef FIX_1217_OBJECT_EDIT_FILE_INTERFACE + if ( objectEditFileReader != NULL ) { - float start_angle, angle_inc; - angle_inc = 360.0f / (float) num_nondiegetic_objects; - start_angle = angle_inc / 2.0f; - for ( obj_idx = 0, non_diegetic_obj_idx = 0; obj_idx < editableParameters->num_obj; obj_idx++ ) + ReadObjectEditInfo *readInfo; + readInfo = objectEditFileReader->readInfo; + + if ( readInfo->bg_gain_edited ) + { + editableParameters->gain_bed = readInfo->bg_gain; + } + + for ( obj_idx = 0; obj_idx < editableParameters->num_obj; obj_idx++ ) { if ( !editableParameters->ism_metadata[obj_idx].non_diegetic_flag ) { - editableParameters->ism_metadata[obj_idx].elevation = 0.0f; - editableParameters->ism_metadata[obj_idx].azimuth = start_angle + (float) non_diegetic_obj_idx * angle_inc; - non_diegetic_obj_idx++; + /* object direction editing only for diegetic objects */ + if ( readInfo->obj_azi_edited[obj_idx] ) + { + if ( readInfo->obj_azi_relative[obj_idx] ) + { + /* azimuth: apply relative edit + wrap */ + editableParameters->ism_metadata[obj_idx].azimuth = fmodf( editableParameters->ism_metadata[obj_idx].azimuth + readInfo->obj_azi[obj_idx] + 540.f, 360.f ) - 180.f; + } + else + { + editableParameters->ism_metadata[obj_idx].azimuth = readInfo->obj_azi[obj_idx]; + } + } + if ( readInfo->obj_ele_edited[obj_idx] ) + { + if ( readInfo->obj_ele_relative[obj_idx] ) + { + /* elevation: apply relative edit + saturation */ + editableParameters->ism_metadata[obj_idx].elevation = fmaxf( fminf( editableParameters->ism_metadata[obj_idx].elevation + readInfo->obj_ele[obj_idx], 90.f ), -90.f ); + } + else + { + editableParameters->ism_metadata[obj_idx].elevation = readInfo->obj_ele[obj_idx]; + } + } + } + + /* gain editing for all objects */ + if ( readInfo->obj_gain_edited[obj_idx] ) + { + if ( readInfo->obj_gain_relative[obj_idx] ) + { + /* gain: apply relative edit + saturation */ + editableParameters->ism_metadata[obj_idx].gain = fmaxf( fminf( editableParameters->ism_metadata[obj_idx].gain * readInfo->obj_gain[obj_idx], OBJ_EDIT_GAIN_MAX ), OBJ_EDIT_GAIN_MIN ); + } + else + { + editableParameters->ism_metadata[obj_idx].gain = readInfo->obj_gain[obj_idx]; + } } } } - - /* breakover object gains */ - for ( obj_idx = 0; obj_idx < editableParameters->num_obj; obj_idx++ ) + else { - editableParameters->ism_metadata[obj_idx].gain = 0.5f + (float) ( ( frame + obj_idx * 50 ) % 250 ) / 250.0f; - } +#endif + if ( num_nondiegetic_objects ) + { + float start_angle, angle_inc; + angle_inc = 360.0f / (float) num_nondiegetic_objects; + start_angle = angle_inc / 2.0f; + for ( obj_idx = 0, non_diegetic_obj_idx = 0; obj_idx < editableParameters->num_obj; obj_idx++ ) + { + if ( !editableParameters->ism_metadata[obj_idx].non_diegetic_flag ) + { + editableParameters->ism_metadata[obj_idx].elevation = 0.0f; + editableParameters->ism_metadata[obj_idx].azimuth = start_angle + (float) non_diegetic_obj_idx * angle_inc; + non_diegetic_obj_idx++; + } + } + } + + /* breakover object gains */ + for ( obj_idx = 0; obj_idx < editableParameters->num_obj; obj_idx++ ) + { + editableParameters->ism_metadata[obj_idx].gain = 0.5f + (float) ( ( frame + obj_idx * 50 ) % 250 ) / 250.0f; + } - editableParameters->gain_bed = 0.5f; + editableParameters->gain_bed = 0.5f; +#ifdef FIX_1217_OBJECT_EDIT_FILE_INTERFACE + } +#endif return; diff --git a/lib_com/ivas_error.h b/lib_com/ivas_error.h index 90c8605f4..e766962bd 100644 --- a/lib_com/ivas_error.h +++ b/lib_com/ivas_error.h @@ -79,6 +79,9 @@ typedef enum IVAS_ERR_ACOUSTIC_ENVIRONMENT_NOT_SUPPORTED, #ifdef OBJ_EDITING_API IVAS_ERR_OBJECTS_EDITING_NOT_SUPPORTED, +#endif +#ifdef FIX_1217_OBJECT_EDIT_FILE_INTERFACE + IVAS_ERR_OBJECTS_EDITING_AND_PANNING_NOT_SUPPORTED, #endif IVAS_ERR_INVALID_HRTF, IVAS_ERR_INVALID_HRTF_SAMPLING_RATE, @@ -261,6 +264,10 @@ static inline const char *ivas_error_to_string( ivas_error error_code ) #ifdef OBJ_EDITING_API case IVAS_ERR_OBJECTS_EDITING_NOT_SUPPORTED: return "Objects editing not supported"; +#endif +#ifdef FIX_1217_OBJECT_EDIT_FILE_INTERFACE + case IVAS_ERR_OBJECTS_EDITING_AND_PANNING_NOT_SUPPORTED: + return "Wrong use of both Object editing and Non-diegetic panning"; #endif case IVAS_ERR_INVALID_HRTF: return "Unsupported HRTF filter set"; diff --git a/lib_com/options.h b/lib_com/options.h index cefe5e842..3a04226ba 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -220,6 +220,8 @@ #define FIX_BRATE_SWITCHING /* VA: fix bitrate switching cases in OMASA and OSBA */ #define NONBE_1217_INIT_OBJ_EDIT /* VA: issue 1217: do object editing only when objects metadata is available */ #endif +#define FIX_1217_OBJECT_EDIT_FILE_INTERFACE /* Nokia: issue #1217: add decoder functionality to read object edit instructions from a file */ +#define NONBE_1217_OBJ_EDIT_FOA /* VA/Nokia: isse 1217: fix crash in object editing to FOA output in ParamISM */ /* #################### End BASOP porting switches ############################ */ diff --git a/lib_dec/ivas_init_dec.c b/lib_dec/ivas_init_dec.c index 8f5b5fe44..5e972172c 100644 --- a/lib_dec/ivas_init_dec.c +++ b/lib_dec/ivas_init_dec.c @@ -3259,10 +3259,17 @@ static ivas_error doSanityChecks_IVAS( if ( !( st_ivas->ivas_format == ISM_FORMAT || st_ivas->ivas_format == SBA_ISM_FORMAT || st_ivas->ivas_format == MASA_ISM_FORMAT ) ) #endif { - return IVAS_ERROR( IVAS_ERR_OBJECTS_EDITING_NOT_SUPPORTED, "Wrong set-up: Obect editing is not supported in this IVAS format." ); + return IVAS_ERROR( IVAS_ERR_OBJECTS_EDITING_NOT_SUPPORTED, "Wrong set-up: Object editing is not supported in this IVAS format." ); } } #endif + +#ifdef FIX_1217_OBJECT_EDIT_FILE_INTERFACE + if ( st_ivas->hDecoderConfig->Opt_ObjEdit_on && st_ivas->hDecoderConfig->Opt_non_diegetic_pan ) + { + return IVAS_ERROR( IVAS_ERR_OBJECTS_EDITING_AND_PANNING_NOT_SUPPORTED, "Wrong set-up: Only object editing or Non-diegetic panning can be used." ); + } +#endif #ifdef DEBUGGING if ( ( st_ivas->hDecoderConfig->force_rend == FORCE_TD_RENDERER ) && ( ( st_ivas->ivas_format != MC_FORMAT && st_ivas->ivas_format != ISM_FORMAT ) || ( output_config != IVAS_AUDIO_CONFIG_BINAURAL && output_config != IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) || ( st_ivas->ivas_format == ISM_FORMAT && st_ivas->ism_mode == ISM_MODE_PARAM ) || ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode != MC_MODE_MCT ) ) ) { diff --git a/lib_dec/lib_dec.c b/lib_dec/lib_dec.c index efddf70ce..67592f157 100644 --- a/lib_dec/lib_dec.c +++ b/lib_dec/lib_dec.c @@ -1712,34 +1712,50 @@ ivas_error IVAS_DEC_SetEditableParameters( #ifdef OBJ_EDITING_PARAMISM_BIN st_ivas->hParamIsmDec->edited_azimuth_values[obj] = hIvasEditableParameters.ism_metadata[obj].azimuth; st_ivas->hParamIsmDec->edited_elevation_values[obj] = hIvasEditableParameters.ism_metadata[obj].elevation; - st_ivas->hMasaIsmData->gain_ism_edited[obj] = hIvasEditableParameters.ism_metadata[obj].gain; - /* Detect direction editing in Param-ISM mode */ - if ( fabsf( st_ivas->hParamIsmDec->azimuth_values[obj] - hIvasEditableParameters.ism_metadata[obj].azimuth ) > OMASA_AZI_EDIT_THR || - fabsf( st_ivas->hParamIsmDec->elevation_values[obj] - hIvasEditableParameters.ism_metadata[obj].elevation ) > OMASA_ELE_EDIT_THR ) +#ifdef NONBE_1217_OBJ_EDIT_FOA + if ( st_ivas->hMasaIsmData != NULL ) { - st_ivas->hMasaIsmData->ism_dir_is_edited[obj] = 1u; - } - else - { - st_ivas->hMasaIsmData->ism_dir_is_edited[obj] = 0u; - } +#endif + st_ivas->hMasaIsmData->gain_ism_edited[obj] = hIvasEditableParameters.ism_metadata[obj].gain; - /* Detect gain editing in Param-ISM mode */ - if ( fabsf( 1.0f - hIvasEditableParameters.ism_metadata[obj].gain ) > OMASA_GAIN_EDIT_THR ) - { - st_ivas->hMasaIsmData->ism_gain_is_edited[obj] = 1u; - } - else - { - st_ivas->hMasaIsmData->ism_gain_is_edited[obj] = 0u; + /* Detect direction editing in Param-ISM mode */ + if ( fabsf( st_ivas->hParamIsmDec->azimuth_values[obj] - hIvasEditableParameters.ism_metadata[obj].azimuth ) > OMASA_AZI_EDIT_THR || + fabsf( st_ivas->hParamIsmDec->elevation_values[obj] - hIvasEditableParameters.ism_metadata[obj].elevation ) > OMASA_ELE_EDIT_THR ) + { + st_ivas->hMasaIsmData->ism_dir_is_edited[obj] = 1u; + } + else + { + st_ivas->hMasaIsmData->ism_dir_is_edited[obj] = 0u; + } + + /* Detect gain editing in Param-ISM mode */ + if ( fabsf( 1.0f - hIvasEditableParameters.ism_metadata[obj].gain ) > OMASA_GAIN_EDIT_THR ) + { + st_ivas->hMasaIsmData->ism_gain_is_edited[obj] = 1u; + } + else + { + st_ivas->hMasaIsmData->ism_gain_is_edited[obj] = 0u; + } +#ifdef NONBE_1217_OBJ_EDIT_FOA } +#endif #endif } #ifdef OBJ_EDITING_PARAMISM_BIN - /* MASA is not present with the ISM format */ - st_ivas->hMasaIsmData->masa_gain_is_edited = 0u; +#ifdef NONBE_1217_OBJ_EDIT_FOA + if ( st_ivas->hMasaIsmData != NULL ) + { +#endif + /* MASA is not present with the ISM format */ + st_ivas->hMasaIsmData->masa_gain_is_edited = 0u; +#ifdef NONBE_1217_OBJ_EDIT_FOA + } +#endif + #endif } else if ( ism_mode == ISM_MODE_NONE ) diff --git a/lib_util/obj_edit_file_reader.c b/lib_util/obj_edit_file_reader.c new file mode 100644 index 000000000..945645569 --- /dev/null +++ b/lib_util/obj_edit_file_reader.c @@ -0,0 +1,278 @@ +/****************************************************************************************************** + +(C) 2022-2024 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 +#include +#include "obj_edit_file_reader.h" +#include "prot.h" + + +#ifdef FIX_1217_OBJECT_EDIT_FILE_INTERFACE +/*-----------------------------------------------------------------------* + * ObjectEditFileReader_open() + * + * Allocate and initialize object editing reader + *-----------------------------------------------------------------------*/ + +ivas_error ObjectEditFileReader_open( + const char *fileName, /* i : path to object edit description file */ + ObjectEditFileReader **objEditReader /* o : ObjectEditFileReader handle */ +) +{ + ObjectEditFileReader *self; + FILE *fileHandle; + int16_t obj_idx; + + if ( fileName == NULL || objEditReader == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + /* Open file */ + if ( strlen( fileName ) < 1 ) + { + return IVAS_ERR_FAILED_FILE_OPEN; + } + + fileHandle = fopen( fileName, "r" ); + + if ( !fileHandle ) + { + return IVAS_ERR_FAILED_FILE_OPEN; + } + + self = (ObjectEditFileReader *) calloc( sizeof( ObjectEditFileReader ), 1 ); + + self->maxLineLen = 256; + self->editFileHandle = fileHandle; + self->inLine = (char *) calloc( sizeof( char ), self->maxLineLen ); + + self->readInfo = (ReadObjectEditInfo *) calloc( sizeof( ReadObjectEditInfo ), 1 ); + self->readInfo->bg_gain = 0.0f; + self->readInfo->bg_gain_edited = false; + + for ( obj_idx = 0; obj_idx < IVAS_MAX_NUM_OBJECTS; obj_idx++ ) + { + self->readInfo->obj_gain[obj_idx] = 0.0f; + self->readInfo->obj_gain_edited[obj_idx] = false; + self->readInfo->obj_gain_relative[obj_idx] = false; + self->readInfo->obj_azi[obj_idx] = 0.0f; + self->readInfo->obj_azi_edited[obj_idx] = false; + self->readInfo->obj_azi_relative[obj_idx] = false; + self->readInfo->obj_ele[obj_idx] = 0.0f; + self->readInfo->obj_ele_edited[obj_idx] = false; + self->readInfo->obj_ele_relative[obj_idx] = false; + } + + self->rewound = false; + + *objEditReader = self; + + return IVAS_ERR_OK; +} + + +/*---------------------------------------------------------------------* + * ObjectEditFileReader_readNextFrame() + * + * Read object editing parameters for current frame + *---------------------------------------------------------------------*/ + +ivas_error ObjectEditFileReader_readNextFrame( + ObjectEditFileReader *objEditReader /* i/o: ObjectEditFileReader handle */ +) +{ + if ( objEditReader == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + if ( fgets( objEditReader->inLine, objEditReader->maxLineLen, objEditReader->editFileHandle ) != NULL ) + { + char *token; + char *paramName; + char *paramValue; + int16_t obj_idx; + ReadObjectEditInfo *readEdits; + + readEdits = objEditReader->readInfo; + + objEditReader->rewound = false; + + readEdits->bg_gain_edited = false; + for ( obj_idx = 0; obj_idx < IVAS_MAX_NUM_OBJECTS; obj_idx++ ) + { + readEdits->obj_gain_edited[obj_idx] = false; + readEdits->obj_gain_relative[obj_idx] = false; + readEdits->obj_azi_edited[obj_idx] = false; + readEdits->obj_azi_relative[obj_idx] = false; + readEdits->obj_ele_edited[obj_idx] = false; + readEdits->obj_ele_relative[obj_idx] = false; + } + + /* tokenize the line by comma */ + /* {bg_gain=}[,obj__=]*N[,obj__=<0|1>]*N, param in ('gain', 'azi', 'ele'), relparam in ('relgain', 'relazi', 'relele') */ + token = strtok( objEditReader->inLine, "," ); + while ( token != NULL ) + { + paramName = token; + paramValue = strchr( token, '=' ); + if ( paramValue != NULL ) + { + *paramValue = '\0'; /* temporarily terminate the string at the equal sign */ + paramValue++; /* move to the value part */ + } + + if ( strcmp( paramName, "bg_gain" ) == 0 ) + { + readEdits->bg_gain = max( min( strtof( paramValue, NULL ), OBJ_EDIT_GAIN_MAX ), OBJ_EDIT_GAIN_MIN ); + readEdits->bg_gain_edited = true; + } + else + { + if ( strncmp( paramName, "obj_", 4 ) == 0 ) + { + char *param; + char *underscore_pos; + + underscore_pos = strchr( paramName + 4, '_' ); + if ( underscore_pos != NULL ) + { + /* temporarily terminate the string at the second underscore */ + *underscore_pos = '\0'; + + /* extract object index */ + obj_idx = (int16_t) atoi( paramName + 4 ); /* skip "obj_" and convert to integer */ + + if ( ( obj_idx < 0 ) || ( obj_idx >= IVAS_MAX_NUM_OBJECTS ) ) + { + return IVAS_ERR_FAILED_FILE_PARSE; + } + + /* restore the underscore and extract parameter name */ + *underscore_pos = '_'; + param = underscore_pos + 1; + if ( strcmp( param, "gain" ) == 0 ) + { + readEdits->obj_gain[obj_idx] = strtof( paramValue, NULL ); + readEdits->obj_gain_edited[obj_idx] = true; + } + else if ( strcmp( param, "azi" ) == 0 ) + { + readEdits->obj_azi[obj_idx] = strtof( paramValue, NULL ); + readEdits->obj_azi_edited[obj_idx] = true; + } + else if ( strcmp( param, "ele" ) == 0 ) + { + readEdits->obj_ele[obj_idx] = strtof( paramValue, NULL ); + readEdits->obj_ele_edited[obj_idx] = true; + } + else if ( strcmp( param, "relgain" ) == 0 ) + { + readEdits->obj_gain_relative[obj_idx] = ( strcmp( paramValue, "1" ) == 0 ); + } + else if ( strcmp( param, "relazi" ) == 0 ) + { + readEdits->obj_azi_relative[obj_idx] = ( strcmp( paramValue, "1" ) == 0 ); + } + else if ( strcmp( param, "relele" ) == 0 ) + { + readEdits->obj_ele_relative[obj_idx] = ( strcmp( paramValue, "1" ) == 0 ); + } + } + } + } + + /* get the next token */ + token = strtok( NULL, "," ); + } + + /* sanitize values for absolute edits. relative edit sanitation done on result when applying the delta */ + for ( obj_idx = 0; obj_idx < IVAS_MAX_NUM_OBJECTS; obj_idx++ ) + { + if ( readEdits->obj_gain_edited[obj_idx] && !readEdits->obj_gain_relative[obj_idx] ) + { + readEdits->obj_gain[obj_idx] = max( min( readEdits->obj_gain[obj_idx], OBJ_EDIT_GAIN_MAX ), OBJ_EDIT_GAIN_MIN ); + } + if ( readEdits->obj_azi_edited[obj_idx] && !readEdits->obj_azi_relative[obj_idx] ) + { + readEdits->obj_azi[obj_idx] = max( min( readEdits->obj_azi[obj_idx], 180.f ), -180.f ); + } + if ( readEdits->obj_ele_edited[obj_idx] && !readEdits->obj_ele_relative[obj_idx] ) + { + readEdits->obj_ele[obj_idx] = max( min( readEdits->obj_ele[obj_idx], 90.f ), -90.f ); + } + } + } + else + { + if ( !objEditReader->rewound ) + { + /* rewind file and try to read again */ + rewind( objEditReader->editFileHandle ); + objEditReader->rewound = true; + ObjectEditFileReader_readNextFrame( objEditReader ); + } + else + { + /* was already rewound and still failing to read */ + return IVAS_ERR_FAILED_FILE_READ; + } + } + + return IVAS_ERR_OK; +} + + +/*-----------------------------------------------------------------------* + * ObjectEditFileReader_close() + * + * Deallocates memory for the object edit file reader + *-----------------------------------------------------------------------*/ + +void ObjectEditFileReader_close( + ObjectEditFileReader **objEditReader /* i/o: ObjectEditFileReader handle */ +) +{ + if ( objEditReader == NULL || *objEditReader == NULL ) + { + return; + } + + fclose( ( *objEditReader )->editFileHandle ); + free( ( *objEditReader )->readInfo ); + free( *objEditReader ); + *objEditReader = NULL; + + return; +} +#endif diff --git a/lib_util/obj_edit_file_reader.h b/lib_util/obj_edit_file_reader.h new file mode 100644 index 000000000..bd4d0011d --- /dev/null +++ b/lib_util/obj_edit_file_reader.h @@ -0,0 +1,112 @@ +/****************************************************************************************************** + +(C) 2022-2024 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. + +*******************************************************************************************************/ + +#ifndef OBJ_EDIT_FILE_READER_H +#define OBJ_EDIT_FILE_READER_H + +#include +#include "common_api_types.h" + + +#ifdef FIX_1217_OBJECT_EDIT_FILE_INTERFACE +/*---------------------------------------------------------------------* + * Constants ans structures + *---------------------------------------------------------------------*/ + +#define OBJ_EDIT_GAIN_MIN 0.06309573f /* -24 dB */ +#define OBJ_EDIT_GAIN_MAX 15.84893f /* +24 dB */ + +typedef struct ObjectEditFileReader ObjectEditFileReader; +typedef struct ReadObjectEditInfo ReadObjectEditInfo; + +struct ReadObjectEditInfo +{ + float bg_gain; + bool bg_gain_edited; + + float obj_gain[IVAS_MAX_NUM_OBJECTS]; + bool obj_gain_edited[IVAS_MAX_NUM_OBJECTS]; + bool obj_gain_relative[IVAS_MAX_NUM_OBJECTS]; + + float obj_azi[IVAS_MAX_NUM_OBJECTS]; + bool obj_azi_edited[IVAS_MAX_NUM_OBJECTS]; + bool obj_azi_relative[IVAS_MAX_NUM_OBJECTS]; + + float obj_ele[IVAS_MAX_NUM_OBJECTS]; + bool obj_ele_edited[IVAS_MAX_NUM_OBJECTS]; + bool obj_ele_relative[IVAS_MAX_NUM_OBJECTS]; +}; + +struct ObjectEditFileReader +{ + FILE *editFileHandle; /* handle to the opened editing info file */ + int16_t maxLineLen; /* constant: max line length to read as once */ + char *inLine; /* working buffer for read input line */ + bool rewound; /* flag to note if file was restarted */ + ReadObjectEditInfo *readInfo; /* edit instructions read from the file */ +}; + +/*---------------------------------------------------------------------* + * ObjectEditFileReader_open() + * + * Allocate the ObjectEditFileReader. + *---------------------------------------------------------------------*/ + +/*! r: ObjectEditFileReader handle */ +ivas_error ObjectEditFileReader_open( + const char *fileName, /* i : path to object edit description file */ + ObjectEditFileReader **objEditReader /* o : ObjectEditFileReader handle */ +); + +/*---------------------------------------------------------------------* + * ObjectEditFileReader_readNextFrame() + * + * Read object editing parameters for current frame + *---------------------------------------------------------------------*/ + +/*! r: error code */ +ivas_error ObjectEditFileReader_readNextFrame( + ObjectEditFileReader *objEditReader /* i/o: ObjectEditFileReader handle */ +); + +/*---------------------------------------------------------------------* + * ObjectEditFileReader_close() + * + * Deallocate the ObjectEditFileReader. + *---------------------------------------------------------------------*/ + +void ObjectEditFileReader_close( + ObjectEditFileReader **objEditReader /* i/o: pointer to ObjectEditFileReader handle */ +); + +#endif +#endif /* OBJ_EDIT_FILE_READER_H */ diff --git a/readme.txt b/readme.txt index 36566e221..dbb85d7ab 100644 --- a/readme.txt +++ b/readme.txt @@ -246,6 +246,7 @@ EVS mono is default, for IVAS choose one of the following: -stereo, -ism, -sba, The encoder produces TS26.445 Annex.2.6 Mime Storage Format, (not RFC4867 Mime Format). default output bitstream file format is G.192 -pca : activate PCA in SBA format FOA at 256 kbps +-obj_edit File : Object editing instructions file or NULL for built-in example -level level : Complexity level, level = (1, 2, 3), will be defined after characterisation. Currently, all values default to level 3 (full functionality). -q : Quiet mode, limit printouts to terminal, default is deactivated @@ -638,3 +639,23 @@ rend_rend_config_hospital_patientroom.cfg rend_config_recreation.cfg rend_config_renderer.cfg + +Object editing file +------------------- +The parameters for the object editing in decoder for the supported formats can be provided via a text +parameter file. Each row of the file corresponds to one 20 ms IVAS frame. The row contains one or more +of the following parameters separated by a comma: + +bg_gain= linear gain to be applied on the SBA/MASA component in OSBA/OMASA, no effect for ISM +obj__gain= linear gain to be applied on object , 0-based indexing +obj__relgain=0|1 if 1, obj__gain is interpreted as a relative modification. default is absolute modification +obj__azi= azimuth angle in degrees to be applied on object , 0-based indexing +obj__relazi=0|1 if 1, obj__azi is interpreted as a relative modification. default is absolute modification +obj__ele= elevation angle in degrees to be applied on object , 0-based indexing +obj__relele=0|1 if 1, obj__ele is interpreted as a relative modification. default is absolute modification + +If a parameter is not specified, that parameter is not edited. An empty line in the file corresponds to +not editing any parameter in the item. +Example files are available in folder /scripts/object_edit. + + -- GitLab From 949e3061df21af0fa69f480691a0e07bad37b11e Mon Sep 17 00:00:00 2001 From: Tapani Pihlajakuja Date: Mon, 20 Oct 2025 15:29:14 +0300 Subject: [PATCH 2/3] Clang format --- apps/decoder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/decoder.c b/apps/decoder.c index bbc4c050a..82b40f9ec 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -3904,7 +3904,7 @@ static void do_object_editing( } } - #ifdef FIX_1217_OBJECT_EDIT_FILE_INTERFACE +#ifdef FIX_1217_OBJECT_EDIT_FILE_INTERFACE if ( objectEditFileReader != NULL ) { ReadObjectEditInfo *readInfo; -- GitLab From b3c3076abe74765f1870da1b1d8fa07b76c6ed09 Mon Sep 17 00:00:00 2001 From: Tapani Pihlajakuja Date: Tue, 21 Oct 2025 11:01:03 +0300 Subject: [PATCH 3/3] Change years --- lib_util/obj_edit_file_reader.c | 2 +- lib_util/obj_edit_file_reader.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib_util/obj_edit_file_reader.c b/lib_util/obj_edit_file_reader.c index 945645569..62c12bd3f 100644 --- a/lib_util/obj_edit_file_reader.c +++ b/lib_util/obj_edit_file_reader.c @@ -1,6 +1,6 @@ /****************************************************************************************************** -(C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, +(C) 2022-2025 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 diff --git a/lib_util/obj_edit_file_reader.h b/lib_util/obj_edit_file_reader.h index bd4d0011d..2eb6698d6 100644 --- a/lib_util/obj_edit_file_reader.h +++ b/lib_util/obj_edit_file_reader.h @@ -1,6 +1,6 @@ /****************************************************************************************************** -(C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, +(C) 2022-2025 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 -- GitLab