// file: $isip_ifc/util/speech/isip_verify/isip_verify.cc
// version: $Id: isip_verify.cc 10627 2006-08-24 16:05:54Z dom5 $
//
// isip include files
//
#include "isip_verify.h"
#include "HierarchicalSearch.h"

// isip_verify: core part of speaker verification system,
// outputs binary decision
//
// it will be used for
//    speaker verification
//    speaker enrollment
//
int main(int argc, const char** argv) {

  // setup the command line
  //
  Sdb sdb;
  CommandLine cmdl(sdb);
  cmdl.setUsage(
#include "usage_message.text"
                );
  cmdl.setHelp(
#include "help_message.text"
               );

  cmdl.setIdent("$Revision: 10627 $",
		"$Name: $",
		"$Date: 2006-08-24 11:05:54 -0500 (Thu, 24 Aug 2006) $");
  
  // add a command line option for the parameters file
  //
  Filename params_file;
  cmdl.addOptionParam(params_file, OPTION_PARAMS_FILE, (Filename)EMPTY);

  // add a command line option for the algorithm type
  //
  String algo_type;
  cmdl.addOptionParam(algo_type, OPTION_ALGO_TYPE, EMPTY);
  
  // add a command line option for the mode
  //
  String mode;
  cmdl.addOptionParam(mode, OPTION_MODE, EMPTY);
  
  // add a command line option for the positive example list
  //
  Filename pos_example_list;
  cmdl.addOptionParam(pos_example_list, OPTION_POS_EXAMPLE_LIST, (Filename)EMPTY);

  // add a command line option for the negative example list
  //
  Filename neg_example_list;
  cmdl.addOptionParam(neg_example_list, OPTION_NEG_EXAMPLE_LIST, (Filename)EMPTY);
  
  // add a command line option for the model file
  //
  Filename model_file;
  cmdl.addOptionParam(model_file, OPTION_MODEL_FILE, (Filename)EMPTY);

  // add a command line option for the audio database file
  //  
  Filename audio_db_file;
  cmdl.addOptionParam(audio_db_file, OPTION_AUDIO_DB_FILE, (Filename)EMPTY);

  // add a command line option for the output file
  //
  Filename output_file;
  cmdl.addOptionParam(output_file, OPTION_OUTPUT_FILE, (Filename)EMPTY);

   // add a command line option for the debug level
  //
  DebugLevel debug_level;
  cmdl.addOptionParam(debug_level, OPTION_DEBUG_LEVEL,
		      DEBUG_LEVEL_DEFAULT);

  // add a command line option for the log verbosity level
  //
  DebugLevel verbosity;
  cmdl.addOptionParam(verbosity, OPTION_VERBOSITY_LEVEL,
		      VERBOSITY_LEVEL_DEFAULT);

  // add a command line option for the log file
  //
  Filename log_file;
  cmdl.addOptionParam(log_file, OPTION_LOG_FILE, (Filename)LOG_FILE_DEFAULT);
						  
  String decision_thresholds;
  cmdl.addOptionParam(decision_thresholds, OPTION_DECISION_THRESHOLDS, EMPTY);
  
  // parse the command line
  //
  if (!cmdl.parse(argc, argv)) {
    cmdl.printUsage();
  }

  // open the log file
  //
  if (log_file.ne(L"-")) {
    Console::open(log_file);
    Console::setLineWrap(File::NO_WRAP);
  }
  
  // print the command line
  //
  if (verbosity >= Integral::BRIEF) {
    cmdl.printCommandLine();
    cmdl.printVersion();
  }
  
  //default algo_type = HMM
  //
  if (algo_type.eq((String)EMPTY)) {
    algo_type.assign(DEF_HMM_ALGO);
  }

  // make algo_type and mode lower character
  //
  algo_type.toLower();
  mode.toLower();

  // check algo_type parameter
  //
  if (algo_type.eq(DEF_HMM_ALGO)) {

    // check the param file argument
    //		    
    if (params_file.eq((Filename)EMPTY)) {
      cmdl.printUsage();
    }
  }
  else if (algo_type.eq(DEF_SVM_ALGO) || algo_type.eq(DEF_RVM_ALGO)) {

    // check mode parameter
    //
    if (mode.eq((String)EMPTY)) {
      cmdl.printUsage();
    }

    if (mode.eq(DEF_TRAIN_MODE)) {
      
      // check the param file parameter
      //
      if (params_file.eq((Filename)EMPTY)) {
        cmdl.printUsage();
      }

      // check the positive examples list
      //
      if (pos_example_list.eq((Filename)EMPTY)) {
	cmdl.printUsage();
      }

      // check the negative examples list
      //
      if (neg_example_list.eq((Filename)EMPTY)) {
	cmdl.printUsage();
      }
    } 
    else if (mode.eq(DEF_TEST_MODE)) {

      // check the model file argument
      //
      if (model_file.eq((Filename)EMPTY)) {
        cmdl.printUsage();
      }

      // check the output file
      //
      if (output_file.eq((Filename)EMPTY)) {
        cmdl.printUsage();
      }

      // check the audio database file argument
      //
      if (audio_db_file.eq((Filename)EMPTY)) {
	cmdl.printUsage();
      }
      
    }
    else {

      // if mode option is not correct, then exit
      //
      cmdl.printUsage();
    }

  }
  else {	   

    // if algo_type option is not correct, then exit
    //
    cmdl.printUsage();
  }
  
  // set up the speaker verifier
  //
  SpeakerVerifier sv;
 
  // set algorithm 
  //
  sv.setAlgorithm(algo_type);

  // set parameters from the command line
  //
  sv.setDebug(debug_level);
  sv.setVerbosity(verbosity);

  if (algo_type.eq(DEF_HMM_ALGO)) {

    //set parameters from the command line
    //
    sv.setParam(params_file);
    
    // decision thresholds
    //
    sv.setDecisionThresholds(decision_thresholds);
    
    // run the speech recognizer
    //
    sv.run(sdb);
    
  }
  else if (mode.eq(DEF_TRAIN_MODE)) {

    String output;
    
    //set parameters from the command line
    //
    sv.setParam(params_file);
    
    // open the positive examples file
    //  
    Sof pos_sof;
    if (!pos_sof.open(pos_example_list, File::READ_ONLY)) {
      output.assign(L"\ncannot open file: ");
      output.concat(pos_example_list);
      output.concat(L", bailing out...");
      Console::put(output);
      Integral::exit();
    }

    // read the list of positive examples
    //
    Sdb pos_sdb;
    if (!pos_sdb.read(pos_sof, (long)0)) {
      output.assign(L"\ncannot read file: ");
      output.concat(pos_example_list);
      output.concat(L", bailing out...");
      Console::put(output);
      Integral::exit();
   }

    // open the negative examples file
    //  
    Sof neg_sof;
    if (!neg_sof.open(neg_example_list, File::READ_ONLY)) {
      output.assign(L"\ncannot open file: ");
      output.concat(neg_example_list);
      output.concat(L", bailing out...");
      Console::put(output);
      Integral::exit();
    }    

    // read the list of negative examples
    //
    Sdb neg_sdb;
    if (!neg_sdb.read(neg_sof, (long)0)) {
      output.assign(L"\ncannot read file: ");
      output.concat(neg_example_list);
      output.concat(L", bailing out...");
      Console::put(output);
      Integral::exit();
    }

    if (verbosity >= Integral::BRIEF) {
      Console::increaseIndention();    
      output.assign(L"\nloading parameter file: ");
      output.concat(params_file);
      Console::put(output);
      Console::decreaseIndention();    
    }
    
    // run the speech recognizer
    //
    sv.run(pos_sdb,neg_sdb);

    // close the file descriptor
    //
    pos_sof.close();
    neg_sof.close();
  
  }
  else if (mode.eq(DEF_TEST_MODE)) {

    // set output file
    //
    sv.setOutputFile(output_file);

    // set model file and audio file
    //
    sv.setModelFile(model_file);
    sv.setAudioDbFile(audio_db_file);
    
    // run the speech recognizer
    //
    sv.run(sdb);
    
  }
  
  // close the log file
  //
  if (log_file.ne(L"-")) {
    Console::close();
  }

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