name: FeatureFile
synopsis:

>     g++ [flags ...] file ... -l /isip/tools/lib/$ISIP_BINARY/lib_mmedia.a

>     #include <FeatureFile.h>

>     FeatureFile();
>     long getBufferedData(Vector<AlgorithmData>& data,
>     	             long start_pos = DEF_START_POS,
>     	             long num_elem = DEF_NUM_ELEM);
>     long getBufferedData(VectorFloat& data, long channel_tag,
>     	             long start_pos, long num_elem);
>     boolean setFileType(FILE_TYPE file_type);

quick start:

>     FeatureFile src;
>     src.open(L"/tmp/input.sof");

>     Vector <VectorFloat> data(1);
>     src.getBufferedData(data(0), 0, 50, 10);

>     Filename output(L"/tmp/output.sof");

>     FeatureFile dst;
>     dst.open(output, File::WRITE_ONLY);
>     dst.writeFeatureData(data, 0);

description:
The FeatureFile class is used to manage feature data. This class provides an interface to files containing feature data generated by isip_transform. Several convenient file formats are supported to facilitate interfacing to external sources of features. Binary and text-based formats are also supported to simplify interfaces to tools such as Matlab.
The feature stream can be a multichannel stream. Each frame of data for each channel is treated as a vector. Support is provided to operate on channels independently.
dependencies:

- Filename
- Double
- String
- Long
- Float
- File
- Sof
- AlgorithmData
- Vector
- CircularBuffer
- VectorFloat
- Filename
- NameMap
- MemoryManager

public constants:

- define the class name:

      static const String CLASS_NAME = L"FeatureFile";

- define the supported file types, compression modes and channel tags:

      enum FILE_TYPE {  TEXT = 0, BINARY, DEF_FILE_TYPE = TEXT };

      enum FILE_FORMAT { SOF = 0, RAW, DEF_FILE_FORMAT = SOF };

      enum COMP_TYPE { LINEAR = 0, ULAW, ALAW, DEF_COMP_TYPE = LINEAR };

      enum SAMPLE_PRECISION { NONE = 0, USE_SIZE, EIGHT_BITS, TWELVE_BITS, SIXTEEN_BITS, TWENTY_BITS, TWENTY_FOUR_BITS, THIRTY_TWO_BITS, DEF_SAMPLE_PRECISION = NONE };

      enum DATA_TYPE { VECTOR_FLOAT = 0, DEF_DATA_TYPE = VECTOR_FLOAT };

- define the names for each of the enumerated values:

      static NameMap FILE_TYPE_MAP;

      static NameMap FILE_FORMAT_MAP;

      static NameMap COMP_TYPE_MAP;

      static NameMap SAMPLE_PRECISION_MAP;

      static NameMap DATA_TYPE_MAP;

- i/o related constants:

      static const String PARAM_NAME = L"name";

      static const String PARAM_FILE_TYPE = L"file_type";

      static const String PARAM_FILE_FORMAT = L"file_format";

      static const String PARAM_COMP_TYPE = L"compression_type";

      static const String PARAM_RANGE = L"amplitude_range";

      static const String PARAM_NUM_CHANNELS = L"num_channels";

      static const String PARAM_ID = L"id";

      static const String PARAM_NUM_FEATURES = L"num_features";

      static const String PARAM_DATA_TYPE = L"data_type";

      static const String PARAM_COEF_TYPE = L"coef_type";

      static const String PARAM_TAG = L"tag";

      static const String PARAM_BLOCK_SIZE = L"block_size";

      static const String PARAM_BUF_SIZE = L"buf_size";

      static const String PARAM_FRAME_DURATION = L"frame_duration";

      static const String PARAM_SAMPLE_FREQUENCY = L"sample_frequency";

      static const String PARAM_DATA = L"values";

- default values and arguments: channel related constants

      static const long CHANNEL_TAG_RIGHT = 1;

      static const long CHANNEL_TAG_LEFT = 0;

      static const long CHANNEL_TAG_ALL = -2;

      static const long DEF_CHANNEL_TAG = CHANNEL_TAG_ALL;

- define some buffer management constants: a buffer contains DEF_BUF_SIZE * DEF_BLOCK_SIZE elements

      static const long DEF_BLOCK_SIZE = 8192;

      static const long DEF_BUF_SIZE = 4;

      static const long DEF_NUMBER_OF_FEATURES = 39;

      static const long DEF_START_POS = 0;

      static const long DEF_NUM_ELEM = 4000;

      static const long DEF_TAG = 0;

- define a default name for feature data:

      static const String DEF_FEATURE_NAME = L"FEATURES";

- define signal related parameters:

      static const long DEF_NUM_CHANNELS = 1;

      static const double DEF_FRAME_DURATION = 0.01;

      static const double DEF_SAMPLE_FREQ = 8000.0;

      static const double DEF_AMPLITUDE_RANGE = 1.0;

      static const long DEF_SAMPLE_NUM_BYTES = 2;

      static const double DEF_START_TIME = 0.0;

      static const double DEF_CENTER_TIME = 0.25;

      static const double DEF_DURATION = 0.5;

error codes:

- general error codes:

      static const long ERR = 50400;

protected data:

- define file format-related parameters

      FILE_TYPE file_type_d;

      FILE_FORMAT file_format_d;

      COMP_TYPE compression_type_d;

      Double amplitude_range__d;

- define signal-related parameters:

      Double amplitude_range_d;

      Long num_channels_d;

      String id_d;

      Long num_features_d;

      DATA_TYPE data_type_d;

      AlgorithmData::COEF_TYPE coef_type_d;

- define Sof file-related parameters:

      Long tag_d;

      Sof in_sof_d;

- define buffer-related variables:

      Long block_size_d;

      Long buf_size_d;

- signal processing-related parameters:

      Float frame_duration_d;

      Float sample_frequency_d;

- define a variable to hold the data:

      Vector v_d;

- raw feature file-related parameters:

      File raw_features_d;

      Vector<CircularBuffer<VectorFloat> > buffers_d;

      Vector buf_end_ftr_d;

- define a flag to keep track of the presence of data: since the FeatureFile class can either hold configuration information for auxiliary file types (RAW FEATURES) or the actual features data, this flag lets the class keep track of whether data is actually present in the file.

      boolean no_data_d;

- define an end of file flag:

      boolean end_of_file_d;

- define a variable to keep track of file position: if we are writing to a binary Sof file we need to keep track of where we write the FeatureFile object's size and the vector's length

      long sof_length_pos_d;

- declare a static debug level for all class instantiations

      static Integral::DEBUG debug_level_d;

- define a static memory manager

      static MemoryManager mgr_d;

required public methods:

- static methods:

      inline static const String& name();

      static boolean diagnose(Integral::DEBUG debug_level);

- debug methods:

      boolean debug(const unichar* message) const;

      inline boolean setDebug(Integral::DEBUG debug_level);

- destructor/constructor(s):

      ~FeatureFile();

      FeatureFile(FILE_TYPE ftype = DEF_FILE_TYPE, FILE_FORMAT fformat = DEF_FILE_FORMAT, DATA_TYPE dtype = DEF_DATA_TYPE);

      FeatureFile(const FeatureFile& copy_feature_file);

- assign methods:

      boolean assign(const FeatureFile& copy_ftrf);

- operator= methods:

      inline FeatureFile& operator= (const FeatureFile& arg);

- i/o methods:

      long sofSize() const;

      boolean read(Sof& sof, long tag, const String& name);

      boolean write(Sof& sof, long tag, const String& name) const;

      boolean readData(Sof& sof, const String& pname = String::getEmptyString(), long size = SofParser::FULL_OBJECT, boolean param = true, boolean nested = false);

      boolean writeData(Sof& sof, const String& pname = String::getEmptyString()) const;

- equality methods:

      boolean eq(const FeatureFile& arg) const;

- memory management methods:

      static void* operator new(size_t size);

      static void* operator new[](size_t size);

      static void operator delete(void* ptr);

      static void operator delete[](void* ptr);

      static boolean setGrowSize(long grow_size);

      boolean clear();

class-specific public methods:

- additional I/O methods:

      boolean open(const Filename& filename, MODE mode = READ_ONLY);

      boolean open(const unichar* filename, MODE mode = READ_ONLY);

      boolean close();

      boolean isOpen() const;

- methods that get raw data from files:

      long getBufferedData(Vector<AlgorithmData>& data, long start_pos = DEF_START_POS, long num_elem = DEF_NUM_ELEM);

      long getBufferedData(Vector<VectorFloat>& data, long start_pos = DEF_START_POS);

      long getBufferedData(VectorFloat& data, long channel_tag, long start_pos = DEF_START_POS, long num_elem = DEF_NUM_ELEM);

      long readFeatureData(Vector<VectorFloat>& data, long ctag, long start_pos, long num_elem);

- methods that write feature data to files:

      long writeFeatureData(Vector<AlgorithmData>& data, long channel_tag = DEF_CHANNEL_TAG);

      long writeFeatureData(Vector<VectorFloat>& data, long channel_tag = DEF_CHANNEL_TAG);

- indexing methods:

      AlgorithmData& operator()(long index);

      AlgorithmData& operator()(long index) const;

      AlgorithmData& operator()(long ctag, long frame);

      AlgorithmData& operator()(long ctag, long frame) const;

- set methods:

      boolean setName(const String& arg);

      boolean setFileType(FILE_TYPE file_type);

      boolean setFileFormat(FILE_FORMAT file_format);

      boolean setCompType(COMP_TYPE comp_type);

      boolean setAmplitudeRange(double range_threshold);

      boolean setNumChannels(long num_channels);

      boolean setID(const String& arg);

      boolean setNumFeatures(long arg);

      boolean setDataType(DATA_TYPE dtype);

      boolean setCoefType(AlgorithmData::COEF_TYPE type);

      boolean setFrameDuration(float arg);

      boolean setSampleFrequency(float arg);

      boolean setLength(long arg);

      boolean setBufferSize(long nblocks);

- get methods:

      const String& getName() const;

      FILE_TYPE getFileType() const;

      FILE_FORMAT getFileFormat() const;

      COMP_TYPE getCompType() const;

      double getAmplitudeRange() const;

      long getNumChannels() const;

      String& getID() const;

      long getNumFeatures() const;

      DMODE getDataType() const;

      AlgorithmData::COEF_TYPE getCoefType() const;

      float getFrameDuration() const;

      float getSampleFrequency() const;

      long getNumFrames(const Sof& sof) const;

      long getNumFrames() const;

- partial i/o methods: read

      boolean readStart(const String& pname = String::EMPTY, long size = SofParser::FULL_OBJECT, boolean param = true,  boolean nested = true);

      boolean readTerminate() const;

      boolean readPartialData(long start_pos, long num_elem);

- partial i/o methods: write

      boolean writeStart(const String& pname = String::EMPTY) const;

      boolean writeTerminate(const String& pname = String::EMPTY) const;

      boolean writePartialData(long start_pos, long num_elem);

private methods:

- methods to manipulate the feature stream:

      long getStartFeature(long channel_tag = DEF_CHANNEL_TAG) const;

      long getEndFeature(long channel_tag = DEF_CHANNEL_TAG) const;

- append methods:

      boolean appendData();

- configuration i/o methods:

      boolean readConfig(Sof& sof, SofParser& parser);

      boolean writeConfig(Sof& sof) const;

- feature file format i/o methods:

      long readFeatureData(Vector<VectorFloat>& data, long channel_tag = DEF_CHANNEL_TAG, long start_pos = DEF_START_POS, long num_elem = DEF_NUM_ELEM);

      long readRawData(Vector<AlgorithmData>& data, long start_samp = DEF_START_SAMP, long num_samp = DEF_NUM_SAMP);

      long readRawData(Vector<VectorFloat>& data, long channel_tag = DEF_CHANNEL_TAG, long start_samp = DEF_START_SAMP, long num_samp = DEF_NUM_SAMP);

      long writeRawData(Vector<AlgorithmData>& data, long channel_tag = DEF_CHANNEL_TAG);

      long writeRawData(Vector<VectorFloat>& data, long channel_tag = DEF_CHANNEL_TAG);

      long readSofData(Vector<VectorFloat>& data, long channel_tag = DEF_CHANNEL_TAG, long start_samp = DEF_START_SAMP, long num_samp = DEF_NUM_SAMP);

      long readSofData(Vector<AlgorithmData>& data, long start_pos = DEF_START_POS, long num_elem = DEF_NUM_ELEM);

      long writeSofData(Vector<AlgorithmData>& data, long channel_tag = DEF_CHANNEL_TAG);

      long writeSofData(Vector<VectorFloat>& data, long channel_tag = DEF_CHANNEL_TAG);

      boolean readSofStart();

      boolean writeSofStart();

- partial i/o methods:

      boolean readStart(Sof& sof, const String& pname = String::EMPTY, long size = SofParser::FULL_OBJECT, boolean param = true,  boolean nested = true);

      boolean writeStart(Sof& sof, const String& pname = String::EMPTY) const;

      boolean writeTerminate(Sof& sof, const String& pname = String::EMPTY) const;

- reset methods:

      boolean resetBuffer(long channel_tag);

examples:

- This example demonstrates how to use read data from a FeatureFile and write this data to another FeatureFile.

      // isip include files
      //
      #include <FeatureFile.h>

      // main program starts here
      //
      int main() {
        // declare FeatureFile objects for read and write
        //
        FeatureFile ftr_in;
        FeatureFile ftr_out;

        // define local variable to hold data
        //
        Vector<AlgorithmData> data;

        // define input and output file name
        //
        Filename ftr_filename(L"$ISIP_DEVEL/doc/examples/data/features/AD.sof");;
        Filename ftr_text(L"AD_text.sof");;

        // prepare parameters for input file
        //
        ftr_in.setNumChannels(1);                  // set number of channel
        ftr_in.setFileType(FeatureFile::BINARY);   // set file type
        ftr_in.setFileFormat(FeatureFile::SOF);    // set file format
        ftr_in.setID(L"AD");                       // set id
        ftr_in.setName(L"FEATURES");               // set feature name

        // prepare parameters for output file
        ftr_out.setNumChannels(1);                 // set number of channel
        ftr_out.setFileType(FeatureFile::TEXT);    // set file type
        ftr_out.setFileFormat(FeatureFile::SOF);   // set file format
        ftr_out.setID(L"AD");                      // set id
        ftr_out.setName(L"FEATURES");              // set feature name

        // open input and output file
        //
        ftr_in.open(ftr_filename);
        ftr_out.open(ftr_text, File::WRITE_ONLY);

        // define local variable
        //
        long num_input=0;
        data.setLength(1);

        // get number of frames stored in file
        //
        long len = ftr_in.getNumFrames();

        // loop for read data from a input file and write data out to a file
        //
        for(long i=0; i<(long)len; i++) {

          // get feature data from the input file
          //
          num_input = ftr_in.getBufferedData(data, i, (long)1);

          // write feature data to the output file
          //
          ftr_out.writeFeatureData(data);
        }

        // close input and output file
        //
        ftr_in.close();
        ftr_out.close();

        // exit gracefully
        //
        Integral::exit();
      }

notes:

- FeatureFile provides two interfaces for most of its methods: one uses AlgorithmData, the other uses VectorFloat. The reason for these are:
  - VectorFloat is the most popular data type currently in use for features;
  - AlgorithmData is a wrapper that handles most data types supported in the IFCs.
  Though using the AlgorithmData interface is more powerful, for application programmers focused on basic DSP operations, it might be a little cumbersome. Hence, we provide a simpler alternative in the form of VectorFloat.