diff --git a/Workspace_msvc/lib_util.vcxproj b/Workspace_msvc/lib_util.vcxproj index bae9cde5b779a981218ca951b862e89bdc83e178..7b793cc4c70b861dc4a0b0bfa0fa129c278f8926 100644 --- a/Workspace_msvc/lib_util.vcxproj +++ b/Workspace_msvc/lib_util.vcxproj @@ -120,6 +120,7 @@ + @@ -144,6 +145,7 @@ + diff --git a/apps/decoder.c b/apps/decoder.c index 24aa2d1629642e5b3001ffcb00b82da5197d3f59..049b000f0d1892a082277930b800a57971dc259a 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -47,6 +47,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 #include "vector3_pair_file_reader.h" #include "wmc_auto.h" #include "options.h" @@ -138,6 +141,9 @@ typedef struct #ifdef OBJ_EDITING_COMMANDLINE bool objEditEnabled; #endif +#ifdef FIX_1217_OBJECT_EDIT_FILE_INTERFACE + char *objEditFileName; +#endif } DecArguments; @@ -166,12 +172,21 @@ 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 OBJ_EDITING_EXAMPLE +#ifdef FIX_1217_OBJECT_EDIT_FILE_INTERFACE +static void do_object_editing_fx( IVAS_EDITABLE_PARAMETERS *editableParameters, ObjectEditFileReader *objectEditFileReader ); +#else static void do_object_editing_fx( IVAS_EDITABLE_PARAMETERS *editableParameters ); #endif +#endif /*------------------------------------------------------------------------------------------* @@ -203,6 +218,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 WMOPS reset_wmops(); @@ -396,6 +414,20 @@ 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 @@ -641,11 +673,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 ) @@ -703,6 +743,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 ) { @@ -882,6 +925,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 @@ -1355,6 +1401,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 @@ -1532,7 +1596,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" ); fprintf( stdout, "-exof File : External orientation File for external orientation trajectory\n" ); fprintf( stdout, "-dpid ID : Directivity pattern ID(s) = [ID1, ID2, ID3, ID4]. Space-separated list of up\n" ); @@ -1546,7 +1610,11 @@ static void usage_dec( void ) fprintf( stdout, " ID and duration pairs, where duration is specified in frames\n" ); 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" ); @@ -1883,6 +1951,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 ) @@ -2212,9 +2283,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 + #ifdef OBJ_EDITING_EXAMPLE /* Do object metadata editing here ... */ +#ifdef FIX_1217_OBJECT_EDIT_FILE_INTERFACE + do_object_editing_fx( &editableParameters, objectEditFileReader ); +#else do_object_editing_fx( &editableParameters ); +#endif #else /* edit object parameters...*/ @@ -2676,6 +2762,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 */ @@ -2956,6 +3045,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 ) { @@ -3066,7 +3166,11 @@ static ivas_error decodeVoIP( /* Do object metadata editing here ... */ #ifdef OBJ_EDITING_EXAMPLE +#ifdef FIX_1217_OBJECT_EDIT_FILE_INTERFACE + do_object_editing_fx( &editableParameters, objectEditFileReader ); +#else do_object_editing_fx( &editableParameters ); +#endif #endif /* set new object parameters */ @@ -3369,13 +3473,18 @@ cleanup: #ifdef OBJ_EDITING_EXAMPLE /*---------------------------------------------------------------------* - * do_object_editing() + * do_object_editing_fx() * * Example function to edit objects parameters *---------------------------------------------------------------------*/ static void do_object_editing_fx( +#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... */ @@ -3391,29 +3500,92 @@ static void do_object_editing_fx( } } - 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_fx = (Word32) readInfo->bg_gain * 536870912; /* Q29 */ + } + + 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_fx = 0; - editableParameters->ism_metadata[obj_idx].azimuth_fx = (Word32) ( ( start_angle + (float) non_diegetic_obj_idx * angle_inc ) * 4194304 /* Q22 */ ); - 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_fx = ( ( editableParameters->ism_metadata[obj_idx].azimuth_fx + (Word32) readInfo->obj_azi[obj_idx] * 4194304 + 2264924160 ) % 1509949440 ) - 754974720; /* Q22 */ + } + else + { + editableParameters->ism_metadata[obj_idx].azimuth_fx = (Word32) readInfo->obj_azi[obj_idx] * 4194304; /* Q22 */ + } + } + 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_fx = L_max( L_min( editableParameters->ism_metadata[obj_idx].elevation_fx + (Word32) readInfo->obj_ele[obj_idx] * 4194304, 377487360 ), -377487360 ); /* Q22 */ + } + else + { + editableParameters->ism_metadata[obj_idx].elevation_fx = (Word32) readInfo->obj_ele[obj_idx] * 4194304; /* Q22 */ + } + } + } + + /* 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_fx = L_max( L_min( editableParameters->ism_metadata[obj_idx].gain_fx * (Word32) readInfo->obj_gain[obj_idx] * 536870912, OBJ_EDIT_GAIN_MAX_FX ), OBJ_EDIT_GAIN_MIN_FX ); /* Q29 */ + } + else + { + editableParameters->ism_metadata[obj_idx].gain_fx = (Word32) readInfo->obj_gain[obj_idx] * 536870912; /* Q29 */ + } } } } - - /* breakover object gains */ - for ( obj_idx = 0; obj_idx < editableParameters->num_obj; obj_idx++ ) + else { - editableParameters->ism_metadata[obj_idx].gain_fx = (Word32) ( ( 0.5f + (float) ( ( frame + obj_idx * 50 ) % 250 ) / 250.0f ) * 536870912 /*Q29*/ ); - } +#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_fx = 0; + editableParameters->ism_metadata[obj_idx].azimuth_fx = (Word32) ( ( start_angle + (float) non_diegetic_obj_idx * angle_inc ) * 4194304 /* Q22 */ ); + non_diegetic_obj_idx++; + } + } + } + + /* breakover object gains */ + for ( obj_idx = 0; obj_idx < editableParameters->num_obj; obj_idx++ ) + { + editableParameters->ism_metadata[obj_idx].gain_fx = (Word32) ( ( 0.5f + (float) ( ( frame + obj_idx * 50 ) % 250 ) / 250.0f ) * 536870912 /*Q29*/ ); + } - editableParameters->gain_bed_fx = ( 1 << 28 ); // 0.5 in Q29 + editableParameters->gain_bed_fx = ( 1 << 28 ); // 0.5 in Q29 +#ifdef FIX_1217_OBJECT_EDIT_FILE_INTERFACE + } +#endif return; } diff --git a/lib_com/ivas_error.h b/lib_com/ivas_error.h index 76ad34aa471db0ac96b27ef26e3b8135f660e4c3..d94bb0f53629c705fb5deda2a0bab5b3ab08850c 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, @@ -255,6 +258,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 ae33093a8861df02f379fcf84a13cbea993d57aa..53ed5eb38fd90678393695ef7904a4b99ed404bd 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -140,6 +140,8 @@ #define OBJ_EDIT_BASOP #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_fx.c b/lib_dec/ivas_init_dec_fx.c index 2d99433194d43f7a6e3934a9415cb987c876c1f2..52049a0641d8c57681b9b9970493d47152981420 100644 --- a/lib_dec/ivas_init_dec_fx.c +++ b/lib_dec/ivas_init_dec_fx.c @@ -3893,5 +3893,13 @@ static ivas_error doSanityChecks_IVAS( } #endif +#ifdef FIX_1217_OBJECT_EDIT_FILE_INTERFACE + test(); + 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 + return IVAS_ERR_OK; } diff --git a/lib_dec/lib_dec_fx.c b/lib_dec/lib_dec_fx.c index b6e3ee48b0bc1118a983361f259d97a4598189d7..091c2779d8c123ebc89e9f7e0e3ea8d2ff34d33c 100644 --- a/lib_dec/lib_dec_fx.c +++ b/lib_dec/lib_dec_fx.c @@ -4567,38 +4567,52 @@ ivas_error IVAS_DEC_SetEditableParameters( move32(); st_ivas->hParamIsmDec->edited_elevation_values_fx[obj] = hIvasEditableParameters.ism_metadata[obj].elevation_fx; move32(); - st_ivas->hMasaIsmData->gain_ism_edited_fx[obj] = shr( extract_h( hIvasEditableParameters.ism_metadata[obj].gain_fx ), Q1 ); // Q29 -> Q12 - move32(); - - /* Detect direction editing in Param-ISM mode */ - IF( GT_32( L_abs( L_sub( st_ivas->hParamIsmDec->azimuth_values_fx[obj], hIvasEditableParameters.ism_metadata[obj].azimuth_fx ) ), OMASA_AZI_EDIT_THR_FX ) || - GT_32( L_abs( L_sub( st_ivas->hParamIsmDec->elevation_values_fx[obj], hIvasEditableParameters.ism_metadata[obj].elevation_fx ) ), OMASA_ELE_EDIT_THR_FX ) ) - { - st_ivas->hMasaIsmData->ism_dir_is_edited[obj] = 1; - } - ELSE +#ifdef NONBE_1217_OBJ_EDIT_FOA + IF( st_ivas->hMasaIsmData != NULL ) { - st_ivas->hMasaIsmData->ism_dir_is_edited[obj] = 0; - } - move16(); +#endif + st_ivas->hMasaIsmData->gain_ism_edited_fx[obj] = shr( extract_h( hIvasEditableParameters.ism_metadata[obj].gain_fx ), Q1 ); // Q29 -> Q12 + move32(); - /* Detect gain editing in Param-ISM mode */ - IF( GT_16( abs_s( sub( ONE_IN_Q12, shr( extract_h( hIvasEditableParameters.ism_metadata[obj].gain_fx ), Q1 ) ) ), OMASA_GAIN_EDIT_THR_FX ) ) // TODO: check Q values - { - st_ivas->hMasaIsmData->ism_gain_is_edited[obj] = 1; - } - ELSE - { - st_ivas->hMasaIsmData->ism_gain_is_edited[obj] = 0; + /* Detect direction editing in Param-ISM mode */ + IF( GT_32( L_abs( L_sub( st_ivas->hParamIsmDec->azimuth_values_fx[obj], hIvasEditableParameters.ism_metadata[obj].azimuth_fx ) ), OMASA_AZI_EDIT_THR_FX ) || + GT_32( L_abs( L_sub( st_ivas->hParamIsmDec->elevation_values_fx[obj], hIvasEditableParameters.ism_metadata[obj].elevation_fx ) ), OMASA_ELE_EDIT_THR_FX ) ) + { + st_ivas->hMasaIsmData->ism_dir_is_edited[obj] = 1; + } + ELSE + { + st_ivas->hMasaIsmData->ism_dir_is_edited[obj] = 0; + } + move16(); + + /* Detect gain editing in Param-ISM mode */ + IF( GT_16( abs_s( sub( ONE_IN_Q12, shr( extract_h( hIvasEditableParameters.ism_metadata[obj].gain_fx ), Q1 ) ) ), OMASA_GAIN_EDIT_THR_FX ) ) // TODO: check Q values + { + st_ivas->hMasaIsmData->ism_gain_is_edited[obj] = 1; + } + ELSE + { + st_ivas->hMasaIsmData->ism_gain_is_edited[obj] = 0; + } + move16(); +#ifdef NONBE_1217_OBJ_EDIT_FOA } - move16(); +#endif #endif } #ifdef OBJ_EDITING_PARAMISM_BIN - /* MASA is not present with the ISM format */ - st_ivas->hMasaIsmData->masa_gain_is_edited = 0; - move16(); +#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 = 0; + move16(); +#ifdef NONBE_1217_OBJ_EDIT_FOA + } +#endif #endif } ELSE IF( EQ_32( 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..6ae9e4cc91ff5afeb96ab4466e1fbb51c6df304e --- /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_fx.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..d3aeb929b26d6f7335afc6b46f03d184bbfdb4be --- /dev/null +++ b/lib_util/obj_edit_file_reader.h @@ -0,0 +1,114 @@ +/****************************************************************************************************** + +(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_FX 33874262 /* Q29, 0.06309573f, -24 dB */ +#define OBJ_EDIT_GAIN_MAX_FX 2127207375 /* Q29, 3.9622325f, +12 dB, TODO: align with float */ +#define OBJ_EDIT_GAIN_MIN 0.06309573f /* -24 dB */ +#define OBJ_EDIT_GAIN_MAX 3.9622325f /* +12 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 91ddd31f7f415124d85467179f472000af6dc365..ef2b33f846d518420b24ad44cd243bc2a79129a9 100644 --- a/readme.txt +++ b/readme.txt @@ -290,7 +290,7 @@ Options: Format files, the magic word in the mime file is used to determine which of the two supported formats is in use. default bitstream file format is G.192 --fr L : render frame size in ms L=(5,10,20), default is 20 +-fr L : render frame size in ms L=(5,10,20), default is 20 -hrtf File : HRTF filter File used in BINAURAL rendering -T File : Head rotation specified by external trajectory File -otr tracking_type : Head orientation tracking type: 'none', 'ref', 'avg', 'ref_vec' @@ -306,7 +306,7 @@ Options: -dpid ID : Directivity pattern ID(s) (space-separated list of up to 4 numbers can be specified) for binaural output configuration -aeid ID : Acoustic environment ID (number >= 0) for BINAURAL_ROOM_REVERB output config. --obj_edit : Enable objects editing +-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. -om File : Coded metadata File for BINAURAL_SPLIT_PCM OutputConf Currently, all values default to level 3 (full functionality). @@ -637,4 +637,23 @@ Example renderer configuration files are available, e.g.: rend_rend_config_hospital_patientroom.cfg rend_config_recreation.cfg -rend_config_renderer.cfg \ No newline at end of file +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.