diff --git a/Workspace_msvc/lib_util.vcxproj b/Workspace_msvc/lib_util.vcxproj index 12dfa7610686a14b0f6fb63967747c6ddd745173..01c90aadd5e0ba9b0c84d7802389f75963953d4c 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 e0a57f0c46e2fcff385fc2e76854dabc11c17a8c..82b40f9ec9f073d0aaf9e74acf6ba625503bb668 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 90c8605f42d6e57007b398c3e57b450bdc68733d..e766962bd2e2b2a1fb0418b9241ad19da501d2e6 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 cefe5e84222aa5aa089df4ba4a3926eacd0fa03f..3a04226ba6b224a83d8f83e3e65acec147ce6290 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 8f5b5fe44e71bb9c791259a3957461e00373192b..5e972172c0ffe991b2924d474df1e3f879899dc7 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 efddf70cee6bd0d091a4261877aa04f5eba62ab2..67592f157b5654a042b9d8be5be3e0ce10cc5355 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 0000000000000000000000000000000000000000..62c12bd3f722f3117564b61c5d67d211caa92f30 --- /dev/null +++ b/lib_util/obj_edit_file_reader.c @@ -0,0 +1,278 @@ +/****************************************************************************************************** + +(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 +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 0000000000000000000000000000000000000000..2eb6698d63189cb640b9551c2b6202b7fcf4a471 --- /dev/null +++ b/lib_util/obj_edit_file_reader.h @@ -0,0 +1,112 @@ +/****************************************************************************************************** + +(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 +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 36566e2219aadeeda08a489e90b41a31f2922c62..dbb85d7ab0f4bf301cea8b6f5a71ac8280e1c234 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. + +