// file: $isip/class/sp/AudioFrontEnd/afnd_05.cc
// version: $Id: afnd_05.cc 10562 2006-04-21 04:18:55Z srinivas $
//

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

// method: resetBuffer
//
// arguments:
//  
// return: a boolean value indicating status
//
// this method clears out CircularBuffer since we have no good
// data.
//
boolean AudioFrontEnd::resetBuffer() {

  // clear the component itself
  //
  coef_components_d.clear(Integral::RELEASE);

  // clear the buffers, but don't delete them
  //
  buf_d.resetBuffer();
  
  // reset flag
  //
  end_of_data_d = false;
  
  // exit gracefully
  //
  return true;
}

// method: makeBuffers
//
// arguments:
//  SingleLinkedList<Component>& temp_list: (input) components to make buffer
//  
// return: a boolean value indicating status
//
// this method makes sure we have buffers for each of the needed data
// elements in the given component list
//
boolean AudioFrontEnd::makeBuffers(SingleLinkedList<Component>& temp_list_a) {

  // loop over all elements in the list
  //
  for (boolean more_nodes = temp_list_a.gotoFirst();
       more_nodes;
       more_nodes = temp_list_a.gotoNext()) {
    
    Component* algo = temp_list_a.getCurr();
    
    buf_d.addOrInitBuffer(algo->getOutputName(), 1);
  }

  long nchan = 1;
  
  // now add the inputs
  //
  if (!input_flag_d) {
    buf_d.addOrInitBuffer(SAMPLED_DATA_NAME, nchan);
  }

  else if (audio_input_d.isOpen()) {
    nchan = audio_input_d.getNumChannels();

    if(channel_index_d != DEF_CHANNEL_INDEX) nchan = 1;
    
    buf_d.addOrInitBuffer(SAMPLED_DATA_NAME, nchan);
  }
  
  else if (feature_input_d.isOpen()) {
    String str(Recipe::INPUT_PREFIX);
    str.concat(feature_input_d.getName());
    nchan = feature_input_d.getNumChannels();

    if(channel_index_d != DEF_CHANNEL_INDEX) nchan = 1;
    
    buf_d.addOrInitBuffer(str, nchan);
  }

  buf_d.setLeftoverSamps(0);
  
  // exit gracefully
  //
  return true;
}

// method: getNumFrames
//
// arguments: none
//
// return: a long number
//
// this method gets the number of frames
//
long AudioFrontEnd::getNumFrames() {

  // get the number of inputs
  //
  double num_frames = 0;
  long number_of_frames = 0;
  
  if (!input_flag_d) {
     num_frames = signal_duration_d / frame_duration_d;
  }
  else if (partial_process_d && (audio_input_d.isOpen())) {
    num_frames = (double)audio_input_d.getNumSamples();
    num_frames /= audio_input_d.getSampleFrequency();
    if ((num_frames < end_time_d) ||
	(end_time_d == DEF_END_TIME)) {
      end_time_d = num_frames;
    }

    num_frames = end_time_d - start_time_d;
    num_frames /= frame_duration_d;
  }

  else if (partial_process_d && (feature_input_d.isOpen())) {

    num_frames = (double)end_time_d;
    num_frames /= frame_duration_d;

    // changed from round to floor
    //
    long frames = (long)Integral::floor(num_frames);

    num_frames = frames - offset_frame_d;
    
    if (num_frames > feature_input_d.getNumFrames()) {
      num_frames =feature_input_d.getNumFrames() - offset_frame_d ;
    }
  }
  
  else if (audio_input_d.isOpen()) {
    num_frames = (double)audio_input_d.getNumSamples();
    num_frames /= frame_duration_d;

    num_frames /= audio_input_d.getSampleFrequency();
  }
  else if (feature_input_d.isOpen()) {
    num_frames = feature_input_d.getNumFrames();
  }
  else {
    return Error::handle(name(), L"getNumFrames", Error::ARG, __FILE__,
			 __LINE__);
  }

  if (data_mode_d == AlgorithmBase::SAMPLE_BASED) {
    number_of_frames = (long)Integral::ceil(num_frames);

    // this code is ugly, but this is to make sure to eliminate the
    // float point error when num_frames is exactly calculate to be
    // integer
    //
    if ((double)number_of_frames - num_frames >= 0.8 &&
	Integral::almostEqual((number_of_frames - num_frames), (double)1.0,
			      0.1)) {
      number_of_frames = number_of_frames - 1;
    }
  }
  else {
    // changed from round to floor
    //
    number_of_frames = (long)Integral::floor(num_frames);
  }

  if (debug_level_d >= Integral::DETAILED) {
    //changed from round to floor
    //
    Long((long)Integral::floor(num_frames)).debug(L"num_frames");
  }
  
  return number_of_frames;
}

// method: setCoefName
//
// arguments:
//  const String& name: (input) name of desired feature
//
// return: a boolean value indicating status
//
// this method sets the coefficient name
//
boolean AudioFrontEnd::setCoefName(const String& name_a) {

  // error check the name
  //
  if (name_a.firstChr(L'+') >= 0) {
    return Error::handle(name(), L"setCoefName",
			 Error::ARG, __FILE__, __LINE__);
  }
  
  // set the data
  //
  if (name_a.firstStr(Recipe::OUTPUT_PREFIX) == 0) {
    coef_name_d.assign(name_a);
  }
  else {
    coef_name_d.assign(Recipe::OUTPUT_PREFIX);
    coef_name_d.concat(name_a);
  }

  buf_d.setCoefName(coef_name_d);
  
  // first sort the graph and find the component
  //
  if (audio_input_d.isOpen() || (feature_input_d.isOpen())) {

    processTarget();    
    if (debug_level_d >= Integral::DETAILED) {
      coef_components_d.debug(L"delayed components");
    }
  }

  // exit gracefully
  //
  return true;
}



// method: getNumFeatures
//
// arguments: none
//
// return: a long number
//
// this method gets the number of features after processing a certain
// component
//
long AudioFrontEnd::getNumFeatures() {

  // create a raw file to process a component
  //
  String tmp_filename0(L".to_get_features_rawfile.raw");
  //  Integral::makeTemp(tmp_filename0);

  AudioFile temp_audio;

  temp_audio.setFileFormat(AudioFile::RAW);
  temp_audio.setFileType(AudioFile::BINARY);
  
  Filename temp(tmp_filename0);
  if (!temp_audio.open(temp, File::WRITE_ONLY)) {
    return Error::handle(name(), L"getNumFeatures", Error::ARG,
			 __FILE__, __LINE__);
  }
  
  // set the seed
  //
  Random rand_01;
  rand_01.seed(27);
    
  long total_numbers = 1000;  // just using this number to create data
  long total_dim = 5;  // set the dimension
  
  Vector <VectorFloat> sampled_data(total_dim);
  Float random = 1.0;

  for (long j = 0; j < total_dim; j++) {
    for (long i = 0; i < total_numbers; i++) {
      sampled_data(j).setLength(total_numbers);
      // take a random sample
      //
      random = rand_01.get() * 10.0;
      
      sampled_data(j)(i).assign(random);
    }
  }

  // write the data to a file
  //
  if (!temp_audio.writeAudioData(sampled_data)) {
    return Error::handle(name(), L"getNumFeatures", Error::WRITE,
			 __FILE__, __LINE__, Error::WARNING);
  }

  temp_audio.close();

  open(tmp_filename0);
  
  Vector<VectorFloat> data;
  
  if (!getVector(data, 0)) {
    return Error::handle(name(), L"getNumFeatures", ERR, __FILE__, __LINE__);
  }

  File::remove(tmp_filename0);
  
  return (long)data(0).length();
}
