// file: $isip/class/sp/FrontEnd/fe_02.cc
// version: $Id: fe_02.cc 10601 2006-08-16 19:10:56Z sl346 $
//

// isip include files
//
#include "FrontEnd.h"
#include <AudioFrontEnd.h>

// method: diagnose
//
// arguments:
//  Integral::DEBUG level: (input) debug level for diagnostics
//
// return: a boolean value indicating status
//
boolean FrontEnd::diagnose(Integral::DEBUG level_a) {

  //---------------------------------------------------------------------------
  //
  // 0. preliminaries
  //
  //---------------------------------------------------------------------------
  
  // output the class name
  //
  if (level_a > Integral::NONE) {
    SysString output(L"diagnosing class ");
    output.concat(CLASS_NAME);
    output.concat(L": ");
    Console::put(output);
    Console::increaseIndention();
  }

  //---------------------------------------------------------------------------
  //
  // 1. required public methods
  //
  //---------------------------------------------------------------------------

  // set indentation
  //
  if (level_a > Integral::NONE) {
    Console::put(L"testing required public methods...\n");
    Console::increaseIndention();
  }

  // test constructors
  //
  FrontEnd val0;
  val0.setType(AUDIO);
  String target0(L"my_target");
  String target1(L"my_other_target");
  val0.setCoefName(target0);
   
  FrontEnd val1(val0);
  
  if (!val0.eq(val1)) {
    val0.debug(L"val0");
    val1.debug(L"val1");
    return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
  }

  // change val1 so it has a  different value
  //
  val1.setCoefName(target1);

  // test the debug methods
  //
  setDebug(debug_level_d);

  if (level_a > Integral::BRIEF) {
    val0.debug(L"debug");
  }
  
  // test the i/o methods
  //
  String tmp_filename0;
  Integral::makeTemp(tmp_filename0);
  String tmp_filename1;
  Integral::makeTemp(tmp_filename1);

  // open files in write mode
  //
  Sof tmp_file0;
  tmp_file0.open(tmp_filename0, File::WRITE_ONLY, File::TEXT);
  Sof tmp_file1;
  tmp_file1.open(tmp_filename1, File::WRITE_ONLY, File::BINARY);

  // write the values
  //
  val0.write(tmp_file0, (long)0);
  val0.write(tmp_file1, (long)0);
  
  val1.write(tmp_file0, (long)1);
  val1.write(tmp_file1, (long)1);

  // close the files
  //
  tmp_file0.close();
  tmp_file1.close();

  // open the files in read mode
  //
  tmp_file0.open(tmp_filename0);
  tmp_file1.open(tmp_filename1);

  // read the values back in
  //
  FrontEnd val2;
  FrontEnd val3;

  if ((!val2.read(tmp_file0, (long)0)) || (!val0.eq(val2))) {
    return Error::handle(name(), L"read", Error::TEST, __FILE__, __LINE__);
  }

  if ((!val2.read(tmp_file1, (long)0)) || (!val0.eq(val2))) {
    return Error::handle(name(), L"read", Error::TEST, __FILE__, __LINE__);
  }

  if ((!val3.read(tmp_file0, (long)1)) || (!val1.eq(val3))) {
    return Error::handle(name(), L"read", Error::TEST, __FILE__, __LINE__);
  }

  if ((!val3.read(tmp_file1, (long)1)) || (!val1.eq(val3))) {
    return Error::handle(name(), L"read", Error::TEST, __FILE__, __LINE__);
  }

  // close and delete the temporary files
  //
  tmp_file0.close();
  tmp_file1.close();
  File::remove(tmp_filename0);
  File::remove(tmp_filename1);
  
  // test memory-management methods
  //
  FrontEnd* ptr;

  FrontEnd::setGrowSize((long)73);
  
  for (long j = 1; j <= 100; j++) {
    ptr = new FrontEnd();
    delete ptr;

    ptr = new FrontEnd[10];
    delete [] ptr;
  }
  
  // reset indentation
  //
  if (level_a > Integral::NONE) {
    Console::decreaseIndention();
  }
  
  //---------------------------------------------------------------------------
  //
  // 2. class-specific methods:
  //     public methods required by the FrontEnd interface contract
  //
  //---------------------------------------------------------------------------

  // set indentation
  //
  if (level_a > Integral::NONE) {
    Console::put(L"testing class-specific methods: FrontEnd interface contract...\n");
    Console::increaseIndention();
  }

  // test the interaction with the FrontEndBase type
  //
  FrontEnd fe;
  AudioFrontEnd afe;
  afe.setCoefName(target0);

  fe.assign(afe);

  if (!fe.eq(afe)) {
    return Error::handle(name(), L"eq", Error::TEST, __FILE__, __LINE__);
  }

  fe.setCoefName(target1);
  
  if (fe.eq(afe)) {
    return Error::handle(name(), L"eq", Error::TEST, __FILE__, __LINE__);
  }

  if (fe.className().ne(L"AudioFrontEnd")) {
    return Error::handle(name(), L"className", Error::TEST,
			 __FILE__, __LINE__);
  }

  // test set/get verbosity
  //
  fe.setVerbosity(Integral::ALL);
  if (fe.getVerbosity() != Integral::ALL) {
    return Error::handle(name(), L"getVerbosity", Error::TEST,
			 __FILE__, __LINE__);
  }

  if (fe.getType() != AUDIO) {
    return Error::handle(name(), L"getType", Error::TEST, __FILE__, __LINE__);
  }
  
  // reset indentation
  //
  if (level_a > Integral::NONE) {
    Console::decreaseIndention();
  }
  
  //---------------------------------------------------------------------------
  //
  // 3. class-specific methods:
  //     test front-end data processing
  //
  //---------------------------------------------------------------------------

  // set indentation
  //
  if (level_a > Integral::NONE) {
    Console::put(L"testing class-specific methods: FrontEnd data processing...\n");
    Console::increaseIndention();
  }

  // load expected results for the first file from a parameter
  // file. they were generated with this command line to
  //
  // extract_feature -delta -acc -energy -swap_bytes -mfcc 12
  // -delta_win 2 -lifter_coeff 22 -window_dur 25 -frame_dur 10
  // -num_fbanks 24 -sf 8000.0 -window_type hamming
  //
  //  for the file in $ISIP_DEVEL/doc/examples/data/audio/bg_119oo39a.raw
  //
  Sof sof;  

  sof.open(L"diagnose_proto_features.sof");
  Vector<VectorFloat> proto;
  proto.read(sof, 0);
  sof.close();
  
  Filename f1(L"$ISIP_DEVEL/doc/examples/data/audio/bg_119oo39a.raw");
  Filename f2(L"$ISIP_DEVEL/doc/examples/data/audio/bg_1647a.raw");
  Filename f3(L"$ISIP_DEVEL/doc/examples/data/audio/bg_17z68a.raw");
  
  AudioFrontEnd afe0;
  AudioFile aufin, aufout;
  aufin.setFileFormat(AudioFile::RAW);
  aufin.setFileType(AudioFile::BINARY);
  afe0.setAudioInput(aufin);
  
  fe.assign(afe0);

  // load the configuration from a parameter file
  //
  sof.open(L"diagnose_params.sof");
  fe.read(sof, sof.first(FrontEnd::name()));
  sof.close();
  
  fe.open(f1);

  if (fe.getID().ne(L"bg_119oo39a")) {
    return Error::handle(name(), L"getID", Error::TEST, __FILE__, __LINE__);
  }

  VectorFloat coeff;
  Long num = -1;
  while (fe.getVector(coeff, 0, ++num)) {
  }

  if (num != (long)373) {
    return Error::handle(name(), L"run", Error::TEST, __FILE__, __LINE__);
  }
  
  fe.close();

  // for the other two files, just make sure they process the correct number
  // of frames
  //
  fe.open(f2);

  num = 0;
  while (fe.getVector(coeff, 0, num++)) {
  }
  
  if (num != (long)217) {
    Long(num).debug(L"num");
    return Error::handle(name(), L"run", Error::TEST, __FILE__, __LINE__);
  }
  
  fe.close();
  
  fe.open(f3);

  num = 0;
  while (fe.getVector(coeff, 0, num++)) {
  }
  
  if (num != (long)265) {
    return Error::handle(name(), L"run", Error::TEST, __FILE__, __LINE__);
  }

  if (fe.getNumFrames() != 264) {
    return Error::handle(name(), L"getNumFrames", Error::TEST,
			 __FILE__, __LINE__);
  }
  fe.close();
  
  // reset indentation
  //
  if (level_a > Integral::NONE) {
    Console::decreaseIndention();
  }

  // --------------------------------------------------------------------
  //
  // 3. print completion message
  //
  // --------------------------------------------------------------------

  // reset indentation
  //
  if (level_a > Integral::NONE) {
    Console::decreaseIndention();
  }
  
  if (level_a > Integral::NONE) {
    String output(L"diagnostics passed for class ");
    output.concat(name());
    output.concat(L"\n");
    Console::put(output);
  }

  // exit gracefully
  //
  return true;
}


