Commit cd0323e4 authored by Tapani Pihlajakuja's avatar Tapani Pihlajakuja
Browse files

Implements file interface for testing object editing and adds test cases.

parent 97140f25
Loading
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -120,6 +120,7 @@
    <ClCompile Include="..\lib_util\masa_file_reader.c" />
    <ClCompile Include="..\lib_util\masa_file_writer.c" />
    <ClCompile Include="..\lib_util\mime_io.c" />
    <ClCompile Include="..\lib_util\obj_edit_file_reader.c" />
    <ClCompile Include="..\lib_util\render_config_reader.c" />
    <ClCompile Include="..\lib_util\rotation_file_reader.c" />
    <ClCompile Include="..\lib_util\rtpdump.c" />
@@ -146,6 +147,7 @@
    <ClInclude Include="..\lib_util\jbm_file_writer.h" />
    <ClInclude Include="..\lib_util\ls_custom_file_reader.h" />
    <ClInclude Include="..\lib_util\mime_io.h" />
    <ClInclude Include="..\lib_util\obj_edit_file_reader.h" />
    <ClInclude Include="..\lib_util\masa_file_reader.h" />
    <ClInclude Include="..\lib_util\masa_file_writer.h" />
    <ClInclude Include="..\lib_util\render_config_reader.h" />
+6 −0
Original line number Diff line number Diff line
@@ -58,6 +58,9 @@
    <ClCompile Include="..\lib_util\mime_io.c">
      <Filter>util_c</Filter>
    </ClCompile>
    <ClCompile Include="..\lib_util\obj_edit_file_reader.c">
      <Filter>util_c</Filter>
    </ClCompile>
    <ClCompile Include="..\lib_util\render_config_reader.c">
      <Filter>util_c</Filter>
    </ClCompile>
@@ -138,6 +141,9 @@
    <ClInclude Include="..\lib_util\mime_io.h">
      <Filter>util_h</Filter>
    </ClInclude>
    <ClInclude Include="..\lib_util\obj_edit_file_reader.h">
      <Filter>util_h</Filter>
    </ClInclude>
    <ClInclude Include="..\lib_util\render_config_reader.h">
      <Filter>util_h</Filter>
    </ClInclude>
+157 −15
Original line number Diff line number Diff line
@@ -45,6 +45,9 @@
#include "rotation_file_reader.h"
#include "aeid_file_reader.h"
#include "split_render_file_read_write.h"
#ifdef OBJECT_EDIT_FILE_INTERFACE
#include "obj_edit_file_reader.h"
#endif
#ifdef VARIABLE_SPEED_DECODING
#include "tsm_scale_file_reader.h"
#include <math.h>
@@ -151,6 +154,9 @@ typedef struct
    bool dpidEnabled;
    uint16_t directivityPatternId[IVAS_MAX_NUM_OBJECTS];
    bool objEditEnabled;
#ifdef OBJECT_EDIT_FILE_INTERFACE
    char *objEditFileName;
#endif

} DecArguments;

@@ -179,16 +185,24 @@ typedef struct

static bool parseCmdlIVAS_dec( int16_t argc, char **argv, DecArguments *arg );
static void usage_dec( void );
#ifdef OBJECT_EDIT_FILE_INTERFACE
static ivas_error decodeG192( DecArguments arg, BS_READER_HANDLE hBsReader, IVAS_DEC_HRTF_BINARY_WRAPPER *hHrtf, 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 *hHrtf, 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 *hHrtf, 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 *hHrtf, 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 );
static int16_t app_own_random( int16_t *seed );
static IVAS_DEC_FORCED_REND_MODE parseForcedRendModeDec( char *forcedRendModeChar );
#endif
#ifdef 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

/*------------------------------------------------------------------------------------------*
 * main()
@@ -219,6 +233,9 @@ int main(
    int16_t *pcmBuf = NULL;
    IVAS_RENDER_FRAMESIZE asked_frame_size;
    IVAS_DEC_HRTF_BINARY_WRAPPER hHrtfBinary;
#ifdef OBJECT_EDIT_FILE_INTERFACE
    ObjectEditFileReader *objectEditFileReader = NULL;
#endif
#ifdef DEBUGGING
    int32_t noClipping;
    int32_t cnt_frames_limited;
@@ -422,6 +439,20 @@ int main(
        }
    }

#ifdef OBJECT_EDIT_FILE_INTERFACE
    /*------------------------------------------------------------------------------------------*
     * Open object editing instructions file
     *------------------------------------------------------------------------------------------*/

    if ( arg.objEditFileName != NULL )
    {
        if ( ( error = ObjectEditFileReader_open( arg.objEditFileName, &objectEditFileReader ) ) != IVAS_ERR_OK )
        {
            fprintf( stderr, "\nError: Can't open Object edit parameter file %s \n\n", arg.objEditFileName );
            goto cleanup;
        }
    }
#endif

    /*------------------------------------------------------------------------------------------*
     * Configure the decoder
@@ -741,11 +772,19 @@ int main(

    if ( arg.voipMode )
    {
#ifdef 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 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 )
@@ -809,6 +848,9 @@ cleanup:
    RotationFileReader_close( &refRotReader );
    Vector3PairFileReader_close( &referenceVectorReader );
    RenderConfigReader_close( &renderConfigReader );
#ifdef OBJECT_EDIT_FILE_INTERFACE
    ObjectEditFileReader_close( &objectEditFileReader );
#endif

    if ( BS_Reader_Close( &hBsReader ) != IVAS_ERR_OK )
    {
@@ -1007,6 +1049,9 @@ static bool parseCmdlIVAS_dec(
    }

    arg->objEditEnabled = false;
#ifdef OBJECT_EDIT_FILE_INTERFACE
    arg->objEditFileName = NULL;
#endif

    /*-----------------------------------------------------------------*
     * Initialization
@@ -1465,6 +1510,22 @@ static bool parseCmdlIVAS_dec(
            arg->objEditEnabled = true;
            i++;
        }
#ifdef OBJECT_EDIT_FILE_INTERFACE
        else if ( strcmp( argv_to_upper, "-OBJ_EDIT_FILE" ) == 0 )
        {
            i++;
            if ( argc - i <= 3 || argv[i][0] == '-' )
            {
                fprintf( stderr, "Error: Object editing instruction filename not specified!\n\n" );
                usage_dec();
                return false;
            }

            arg->objEditFileName = argv[i];
            arg->objEditEnabled = true;
            i++;
        }
#endif

        /*-----------------------------------------------------------------*
         * Option not recognized
@@ -1667,6 +1728,9 @@ static void usage_dec( void )
    fprintf( stdout, "                      alternatively, it can be a text file where each line contains \"ID duration\"\n" );
    fprintf( stdout, "                      for BINAURAL_ROOM_REVERB output configuration.\n" );
    fprintf( stdout, "-obj_edit           : Enable objects editing\n" );
#ifdef OBJECT_EDIT_FILE_INTERFACE
    fprintf( stdout, "-obj_edit_file File : Name of file from which object editing instructions are read\n" );
#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" );
    fprintf( stdout, "-q                  : Quiet mode, no frame counter\n" );
@@ -1988,6 +2052,9 @@ static ivas_error decodeG192(
    RotFileReader *externalOrientationFileReader,
    RotFileReader *refRotReader,
    Vector3PairFileReader *referenceVectorReader,
#ifdef OBJECT_EDIT_FILE_INTERFACE
    ObjectEditFileReader *objectEditFileReader,
#endif
    ISAR_SPLIT_REND_BITS_DATA *splitRendBits,
    IVAS_DEC_HANDLE hIvasDec,
    int16_t *pcmBuf )
@@ -2385,8 +2452,22 @@ static ivas_error decodeG192(
                        return error;
                    }

#ifdef OBJECT_EDIT_FILE_INTERFACE
                    if ( arg.objEditFileName != NULL )
                    {
                        if ( ( error = ObjectEditFileReader_readNextFrame( objectEditFileReader ) ) != IVAS_ERR_OK )
                        {
                            fprintf( stderr, "\nError: could not read object edit information from file: %s\n\n", IVAS_DEC_GetErrorMessage( error ) );
                            return error;
                        }
                    }
#endif
                    /* Do object metadata editing here ... */
#ifdef OBJECT_EDIT_FILE_INTERFACE
                    do_object_editing( &editableParameters, objectEditFileReader );
#else
                    do_object_editing( &editableParameters );
#endif

                    /* set new object parameters */
                    if ( ( error = IVAS_DEC_SetEditableParameters( hIvasDec, editableParameters ) ) != IVAS_ERR_OK )
@@ -2909,6 +2990,9 @@ static ivas_error decodeVoIP(
    RotFileReader *externalOrientationFileReader,
    RotFileReader *refRotReader,
    Vector3PairFileReader *referenceVectorReader,
#ifdef OBJECT_EDIT_FILE_INTERFACE
    ObjectEditFileReader *objectEditFileReader,
#endif
    IVAS_DEC_HANDLE hIvasDec )
{
    bool decodingFailed = true; /* Assume failure until cleanup is reached without errors */
@@ -3188,6 +3272,17 @@ static ivas_error decodeVoIP(
            }
        }

#ifdef 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 edit information 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 )
        {
@@ -3288,7 +3383,11 @@ static ivas_error decodeVoIP(
                }

                /* Do object metadata editing here ... */
#ifdef OBJECT_EDIT_FILE_INTERFACE
                do_object_editing( &editableParameters, objectEditFileReader );
#else
                do_object_editing( &editableParameters );
#endif

                /* set new object parameters */
                if ( ( error = IVAS_DEC_SetEditableParameters( hIvasDec, editableParameters ) ) != IVAS_ERR_OK )
@@ -3588,7 +3687,12 @@ cleanup:
 *---------------------------------------------------------------------*/

static void do_object_editing(
#ifdef 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... */
@@ -3604,6 +3708,42 @@ static void do_object_editing(
        }
    }

#ifdef OBJECT_EDIT_FILE_INTERFACE
    if ( objectEditFileReader != NULL )
    {
        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 )
            {
                /* object direction editing only for diegetic objects */
                if ( readInfo->obj_azi_edited[obj_idx] )
                {
                    editableParameters->ism_metadata[obj_idx].azimuth = readInfo->obj_azi[obj_idx];
                }
                if ( readInfo->obj_ele_edited[obj_idx] )
                {
                    editableParameters->ism_metadata[obj_idx].elevation = readInfo->obj_ele[obj_idx];
                }
            }

            /* gain editing for all objects */
            if ( readInfo->obj_gain_edited[obj_idx] )
            {
                editableParameters->ism_metadata[obj_idx].gain = readInfo->obj_gain[obj_idx];
            }
        }
    }
    else
    {
#endif
        if ( num_nondiegetic_objects )
        {
            float start_angle, angle_inc;
@@ -3627,7 +3767,9 @@ static void do_object_editing(
        }

        editableParameters->gain_bed = 0.5f;

#ifdef OBJECT_EDIT_FILE_INTERFACE
    }
#endif

    return;
}
+1 −0
Original line number Diff line number Diff line
@@ -162,6 +162,7 @@
#define TMP_FIX_1119_SPLIT_RENDERING_VOIP               /* FhG: Add error check for unsupported config: split rendering with VoIP mode */
#define FIX_1228_SAMPLING_RATE_MISMATCH_IN_HRTF_FILE    /* VA: issue 1228: Exit the processing when a HRTF binary file with wrong sampling rate is provided */
#define FIX_1225_DISCLAIMER                             /* VA: issue 1225: Add disclaimer for external renderer + Add info about IVAS reference version */
#define OBJECT_EDIT_FILE_INTERFACE                      /* Nokia: add decoder functionality to read object edit instructions from a file */

/* #################### End BE switches ################################## */

+228 −0
Original line number Diff line number Diff line
/******************************************************************************************************

(C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
contributors to this repository. All Rights Reserved.

This software is protected by copyright law and by international treaties.
The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
contributors to this repository retain full ownership rights in their respective contributions in
the software. This notice grants no license of any kind, including but not limited to patent
license, nor is any license granted by implication, estoppel or otherwise.

Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
contributions.

This software is provided "AS IS", without any express or implied warranties. The software is in the
development stage. It is intended exclusively for experts who have experience with such software and
solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
and fitness for a particular purpose are hereby disclaimed and excluded.

Any dispute, controversy or claim arising under or in relation to providing this software shall be
submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
the United Nations Convention on Contracts on the International Sales of Goods.

*******************************************************************************************************/

#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "obj_edit_file_reader.h"
#include "prot.h"

#define OBJ_EDIT_GAIN_MIN 0.06309573f /* -24 dB */
#define OBJ_EDIT_GAIN_MAX 15.84893f   /* +24 dB */

/*-----------------------------------------------------------------------*
 * 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;

    /* 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_azi[obj_idx] = 0.0f;
        self->readInfo->obj_azi_edited[obj_idx] = false;
        self->readInfo->obj_ele[obj_idx] = 0.0f;
        self->readInfo->obj_ele_edited[obj_idx] = false;
    }

    self->rewound = false;

    *objEditReader = self;

    return IVAS_ERR_OK;
}

/*---------------------------------------------------------------------*
 * ObjectEditFileReader_readNextFrame()
 *
 *
 *---------------------------------------------------------------------*/
ivas_error ObjectEditFileReader_readNextFrame(
    ObjectEditFileReader *objEditReader /* i/o: ObjectEditFileReader handle     */
)
{
    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_azi_edited[obj_idx] = false;
            readEdits->obj_ele_edited[obj_idx] = false;
        }

        /* tokenize the line by comma */
        /* {bg_gain=<float>}[,obj_<int>_<param>=<float>]*N, param in ('gain', 'azi', 'ele') */
        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] = max( min( strtof( paramValue, NULL ), OBJ_EDIT_GAIN_MAX ), OBJ_EDIT_GAIN_MIN );
                            readEdits->obj_gain_edited[obj_idx] = true;
                        }
                        else if ( strcmp( param, "azi" ) == 0 )
                        {
                            readEdits->obj_azi[obj_idx] = max( min( strtof( paramValue, NULL ), 180.f ), -180.f );
                            readEdits->obj_azi_edited[obj_idx] = true;
                        }
                        else if ( strcmp( param, "ele" ) == 0 )
                        {
                            readEdits->obj_ele[obj_idx] = max( min( strtof( paramValue, NULL ), 90.f ), -90.f );
                            readEdits->obj_ele_edited[obj_idx] = true;
                        }
                    }
                }
            }

            /* get the next token */
            token = strtok( NULL, "," );
        }
    }
    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;
}
Loading