// file: $isip/class/mmedia/FeatureFile/ftrf_05.cc
// version: $Id: ftrf_05.cc 10636 2007-01-26 22:18:09Z tm334 $
//

// isip include files
//
#include "FeatureFile.h"


// method: writeFeatureData
//
// arguments:
//  Vector<AlgorithmData>& data: (input) the feature data
//  long channel_tag: (input) the channel tag
//
// return: number of feature data read
//
// this is currently the only way to output data. it writes the
// entire input vector at the current location.
//
long FeatureFile::writeFeatureData(Vector<AlgorithmData>& data_a,
				   long channel_tag_a) {
  // branch on file format
  //
  if (file_format_d == RAW)
    return writeRawData(data_a, channel_tag_a);
  else if (file_format_d == SOF)
    return writeSofData(data_a, channel_tag_a);
  else
    return 0;
}

// method: writeFeatureData
//
// arguments:
//  Vector<VectorFloat>& data: (input) the feature data
//  long channel_tag: (input) the channel tag
//
// return: number of feature data read
//
// this is currently supported only for backward compatibility
// (especially for FeatureSelect and SegmentConcat classes)
// use Vector<AlgorithmData> output features instead
//
long FeatureFile::writeFeatureData(Vector<VectorFloat>& data_a,
				   long channel_tag_a) {
  if (data_type_d == VECTOR_FLOAT) {

    long len = data_a.length();
    Vector<AlgorithmData> temp(len);
    
    for (long i = 0; i < len; i++) {
      temp(i).makeVectorFloat() = data_a(i);
    }
    return writeFeatureData(temp, channel_tag_a);
  }
  
  else {
    return Error::handle(name(), L"writeFeatureData", Error::NOT_IMPLEM,
			 __FILE__, __LINE__);    
  }

  return -1;
}


// method: readFeatureData 
//
// arguments:
//  Vector<AlgorithmData>& data: (input) the feature data to read
//  long start_pos: (input) the start position of the feature data
//  long num_elem: (input) the number of the feature data read
//  
// return: the number of elements read
//
// this method reads the feature data from a file.
//
long FeatureFile::readFeatureData(Vector<AlgorithmData>& data_a,
				  long start_pos_a, long num_elem_a) {
  // branch on file format
  //
  if (file_format_d == RAW)
    return readRawData(data_a, start_pos_a, num_elem_a);
  else if (file_format_d == SOF)
    return readSofData(data_a, start_pos_a, num_elem_a);
  else
    return 0;
}

// method: readFeatureData
//
// arguments:
//  Vector<VectorFloat>& data: (output) the feature data
//  long ctag: (input) the channel to read
//  long start_pos: (input) the start pos from feature data
//  long num_elem: (input) the num of element read from feature data
//  
// return: number of frames read
//
// this is currently supported only for backward compatibility
// (especially for FeatureSelect and SegmentConcat classes)
// use Vector<AlgorithmData> input features instead
//
//
long FeatureFile::readFeatureData(Vector<VectorFloat>& data_a,
				  long ctag_a, long start_pos_a,
				  long num_elem_a) {

  if (data_type_d == VECTOR_FLOAT) {

    Vector<AlgorithmData> temp;
    long num_frames_read = readFeatureData(temp, start_pos_a, num_elem_a);

    for (long i  = 0; i < temp.length(); i++) {
      data_a(i) = temp(i).makeVectorFloat();
    }
    return num_frames_read;
  }

  else {
    return Error::handle(name(), L"readFeatureData", Error::NOT_IMPLEM,
			 __FILE__, __LINE__);    
  }
  
  return -1;
}  
  
// method: readPartialData
//
// arguments:
//  long start_pos: (input) first entry to read
//  long num_elem: (input) number of elements to read
//
// return: the number of elements read
//
// this method has the object read itself from an Sof file. it assumes
// that the Sof file is already positioned correctly.
//
boolean FeatureFile::readPartialData(long start_pos_a, long num_elem_a) {
  
  if (data_type_d == ALGORITHM_DATA) {
    // create a temporary buffer
    //
    Vector<AlgorithmData> temp;
    
    temp.readPartialData(in_sof_d, start_pos_a, num_elem_a,
			 String::EMPTY, 0, false, false);
    
    v_d = temp;
  }

  else if (data_type_d == VECTOR_FLOAT) {
    // create a temporary buffer
    //
    Vector<VectorFloat> temp;
    
    temp.readPartialData(in_sof_d, start_pos_a, num_elem_a,
			 String::EMPTY, 0, false, false);
    
    // loop over all elements
    //
    long len = temp.length();
    v_d.setLength(len);
    
    for (long i = 0; i < len; i++) {
      
      // transfer the data
      //
      v_d(i).makeVectorFloat() = temp(i);
    }
  }
  else {
    return Error::handle(name(), L"readPartialData", Error::NOT_IMPLEM,
			 __FILE__, __LINE__);
  }

  // exit gracefully
  //
  return true;    
}

// method: writePartialData
//
// arguments:
//  long start_pos: (input) the index of the Vector to start to write
//  long num_elem: (input) the number of elements to write
//
// return: a boolean value indicating status
//
// this method writes a portion of a feature stream to a file.
//
boolean FeatureFile::writePartialData(long start_pos_a, long num_elem_a) {

  if (data_type_d == ALGORITHM_DATA) {
    // create a temporary buffer
    //
    Vector<AlgorithmData> temp;
    
    temp = v_d;
    
    // write the data
    //
    if (!temp.writePartialData(in_sof_d, start_pos_a, num_elem_a)) {
      return Error::handle(name(), L"writePartialData", Error::IO,
			   __FILE__, __LINE__);
    }
  }
  
  else if (data_type_d == VECTOR_FLOAT) {
    // create a temporary buffer
    //
    Vector<VectorFloat> temp;
    
    // loop over all elements
    //
    long len = v_d.length();
    temp.setLength(len);
    
    for (long i = 0; i < len; i++) {
      
      // transfer the data
      //
      temp(i).setLength(v_d(i).getVectorFloat().length());
      temp(i) = v_d(i).getVectorFloat();
    }
    
    // write the data
    //
    if (!temp.writePartialData(in_sof_d, start_pos_a, num_elem_a)) {
      return Error::handle(name(), L"writePartialData", Error::IO,
			   __FILE__, __LINE__);
    }
  }
  else {
    return Error::handle(name(), L"writePartialData", Error::NOT_IMPLEM,
			 __FILE__, __LINE__);
  }
  
  // exit gracefully
  //
  return true;
}

// method: getBufferedData 
//
// arguments:
//  Vector<AlgorithmData>& data: (input) the feature data to read
//  long start_pos: (input) the start position of the feature data
//  long num_elem: (input) the number of the feature data read
//  
// return: the number of elements read
//
// this method reads feature data from a file.
//
long FeatureFile::getBufferedData(Vector<AlgorithmData>& data_a,
				  long start_pos_a, long num_elem_a) {
  // branch on file format
  //
  if (file_format_d == RAW)
    return readRawData(data_a, start_pos_a, num_elem_a);
  else if (file_format_d == SOF)
    return readSofData(data_a, start_pos_a, num_elem_a);
  else
    return 0;
}

// method: setBufferSize
//
// arguments:
//  long nblocks: (input) number of blocks per buffer
//
// return: a boolean value indicating status
//
// this method sets capacity of the buffer.
//
boolean FeatureFile::setBufferSize(long nblocks_a) {

  //  if (data_type_d == VECTOR_FLOAT) {
    
    // save the value to class data
    //
    long block_num_samp = block_size_d;
    
    for (long i = 0; i < num_channels_d; i++) {
      buffers_d(i).setCapacity(nblocks_a * block_num_samp);
    }
    
    //  }

  
  // exit gracefully
  //
  return true;
}
