// file: $isip/class/algo/FilterBank/fb_00.cc
// version: $Id: fb_00.cc 8318 2002-07-10 00:53:25Z picone $
//

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

//------------------------------------------------------------------------
//
// required public methods
//
//-----------------------------------------------------------------------

// method: assign
//
// arguments:
//  const FilterBank& arg: (input) object to be assigned
//
// return: a boolean value indicating status
//
// this method assigns the input object to the current object
//
boolean FilterBank::assign(const FilterBank& arg_a) {

  // assign the algorithm name
  //
  algorithm_d = arg_a.algorithm_d;
  implementation_d = arg_a.implementation_d;

  // assign the parameters related to the algorithm specification:
  //
  input_mode_d = arg_a.input_mode_d;
  filters_d.assign(arg_a.filters_d);
  fsmp_d = arg_a.fsmp_d;
  scale_d = arg_a.scale_d;
  order_d = arg_a.order_d;
  bandwidth_d = arg_a.bandwidth_d;
  filters_pfile_d.assign(arg_a.filters_pfile_d);
    
  // assign temporary buffers related to filter bank computation
  //
  warp_freq_d.assign(arg_a.warp_freq_d);
  lin_freq_d.assign(arg_a.lin_freq_d);
  cen_freq_d.assign(arg_a.cen_freq_d);

  // assign valid flag
  //
  is_valid_d = arg_a.is_valid_d;
  
  // call the base assign method
  //
  return AlgorithmBase::assign(arg_a);
}

// method: eq
//
// arguments:
//  const FilterBank& arg: (input) object to be compared
//
// return: a boolean value indicating status
//
// this method checks whether the current object is identical to the
// input object
//
boolean FilterBank::eq(const FilterBank& arg_a) const {

  // compare the data members
  //
  return ((algorithm_d == arg_a.algorithm_d) &&
	  (implementation_d == arg_a.implementation_d) &&
	  (filters_d.eq(arg_a.filters_d)) &&
	  (filters_pfile_d.eq(arg_a.filters_pfile_d)) &&
	  (scale_d == arg_a.scale_d) &&
	  (fsmp_d == arg_a.fsmp_d) &&
	  (input_mode_d == arg_a.input_mode_d) &&
	  ((fsmp_d != ORDER) || (order_d == arg_a.order_d)) &&
	  ((fsmp_d != BANDWIDTH) || (bandwidth_d == arg_a.bandwidth_d)) &&
	  (is_valid_d == arg_a.is_valid_d));
}

// method: clear
//
// arguments:
//  Integral::CMODE ctype: (input) clear mode
//
// return: a boolean value indicating status
//
// this method resets the data members to the default values
//
boolean FilterBank::clear(Integral::CMODE ctype_a) {

  if (ctype_a != Integral::RETAIN) {

    // reset the parameters related to the algorithm specification to
    // default values
    //
    algorithm_d = DEF_ALGORITHM;
    implementation_d = DEF_IMPLEMENTATION;
    input_mode_d = DEF_INPUT_MODE;
    scale_d = DEF_SCALE;
    fsmp_d = DEF_FREQUENCY_SAMPLING;
    order_d = DEF_ORDER;
    bandwidth_d = DEF_BANDWIDTH;
    filters_pfile_d.assign(DEF_FILTERS_PFILE);
    filters_d.clear(ctype_a);
  }
  
  // clear the temporary buffers related to filter bank amplitude
  //
  warp_freq_d.clear(ctype_a);
  lin_freq_d.clear(ctype_a);
  cen_freq_d.clear(ctype_a);

  // call the base clear method
  //
  return AlgorithmBase::clear(ctype_a);
}

//---------------------------------------------------------------------------
//
// class-specific public methods:
//  public methods required by the AlgorithmBase interface contract
//
//---------------------------------------------------------------------------

// method: assign
//
// arguments:
//  const AlgorithmBase& arg: (input) object to be assigned
//
// return: a boolean value indicating status
//
// this method assigns the input algorithm object to the current object.
//
boolean FilterBank::assign(const AlgorithmBase& arg_a) {

  // case: input is an FilterBank object
  //
  if (typeid(arg_a) == typeid(FilterBank)) {
    return assign((FilterBank&)arg_a);
  }

  // case: other
  //  if the input algorithm object is not an FilterBank object, return
  //  an error.
  //
  else {
    return Error::handle(name(), L"assign", Error::ARG, __FILE__, __LINE__);
  }
}

// method: eq
//
// arguments:
//  const AlgorithmBase& arg: (input) object to be compared
//
// return: a boolean value indicating status
//
// this method checks whether the current FilterBank object is identical
// to the input algorithm object.
//
boolean FilterBank::eq(const AlgorithmBase& arg_a) const {
  
  // case: input is a FilterBank object
  //
  if (typeid(arg_a) == typeid(FilterBank)) {
    return eq((FilterBank&)arg_a);
  }

  // case: other
  //  if the input algorithm object is not a FilterBank object, return
  //  an error.
  //
  else {
    return Error::handle(name(), L"eq", Error::ARG, __FILE__, __LINE__);
  }
}

// method: init
//
// arguments: none
//
// return: a boolean value indicating status
//
// this method reads in the ma and ar coefficients for filters from
// the parameter file for TIME algorithm
// 
boolean FilterBank::init() {
  
  // check algorithm: TIME
  //
  if (algorithm_d == TIME) {

    // declare the local variables
    //
    Sof param_file;
    long tag;
    long index = (long)0;
    long num = (long)0;
      
    // open the sof file in the read mode
    //
    param_file.open(filters_pfile_d, File::READ_ONLY, File::TEXT);

    // get the number of filters
    //
    num = param_file.getCount(Filter::CLASS_NAME);

    // set the length of the vector of filters
    //
    filters_d.setLength(num);

    // read all the instances of the object Filter from the Sof file
    //
    for (tag = param_file.first(filters_d(0).name()); tag != Sof::NO_TAG;
	 tag = param_file.next(filters_d(0).name(), tag)) {
      filters_d(index).read(param_file, tag);
      index++;
    }        

    // close the filters parameter file
    //
    param_file.close();
  }   	   

  // check algorithm: FREQUENCY
  //
  else if (algorithm_d == FREQUENCY) {
    // no initialization needed
  }
  
  // set the initialization flag
  //
  is_valid_d = true;
  
  // exit gracefully
  //
  return true;
}

//-----------------------------------------------------------------------------
//
// we define non-integral constants in the default constructor
//      
//-----------------------------------------------------------------------------

// constants: class name
//
const String FilterBank::CLASS_NAME(L"FilterBank");

// constants: i/o related constants
//
const String FilterBank::DEF_PARAM(L"");
const String FilterBank::PARAM_ALGORITHM(L"algorithm");
const String FilterBank::PARAM_IMPLEMENTATION(L"implementation");
const String FilterBank::PARAM_FILTERS_PFILE(L"filters_param_file");
const String FilterBank::PARAM_SCALE(L"scale");
const String FilterBank::PARAM_FREQUENCY_SAMPLING(L"frequency_sampling");
const String FilterBank::PARAM_INPUT_MODE(L"input_mode");
const String FilterBank::PARAM_ORDER(L"order");
const String FilterBank::PARAM_BANDWIDTH(L"bandwidth");
const String FilterBank::PARAM_CMODE(L"compute_mode");
const String FilterBank::PARAM_DMODE(L"data_mode");

// constants: default constants for each algorithm
//
const String FilterBank::DEF_FILTERS_PFILE(L"filters.sof");

// constants: NameMap(s) for the enumerated values
//
const NameMap FilterBank::ALGO_MAP(L"FREQUENCY, TIME");
const NameMap FilterBank::IMPL_MAP(L"UNIFORM, TRIANGULAR, RAISED_COSINE, CCDE");
const NameMap FilterBank::SCALE_MAP(L"LINEAR, MEL, BARK");
const NameMap FilterBank::FREQUENCY_SAMPLING_MAP(L"ORDER, BANDWIDTH");
const NameMap FilterBank::INPUT_MODE_MAP(L"FULL, SYMMETRIC");

// static instantiations: memory manager
//
MemoryManager FilterBank::mgr_d(sizeof(FilterBank), FilterBank::name());
