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.
+
+