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.