// file: comm_decode_0.cc
//
// this utility does trace projection decoding
//

// isip include files
//
#include "trace_projector.h"
#include <time.h>

// Communicator API
//
#include "communicator.h"

extern int clean_frontend();

// static variables
//
Trace_projector tp;
char_1* hypotheses = NULL;
char_1* alignment = NULL;

// method: load_models
//
// arguments:
//  char* params: (input) parameter file
//
// return: bool indicating status
//
// this method loads the recognition models
//
int load_models(char* params_a) {

  // open parameter file
  //
  FILE* fp = (FILE*)NULL;
  fp = fopen(params_a, "r");
  
  // read parameters
  //
  tp.read_params_cc(fp);
  
  // initialize frontend
  //
  init_frontend((char*)tp.get_frontend_params());

  // configure the decoder according to these parameter and load
  // models
  //
  tp.config_decoder_cc(ISIP_FALSE, ISIP_TRUE);

  // exit gracefully
  //
  return ISIP_TRUE;
}
  
// method: uttproc_mfcdata
//
// arguments:
//  double* data: (input) feature input buffer
//  int* num_samples: (input) number of feature data
//  int block: (input) pending blocks (currently unused)
//
// return: bool indicating status
//
// this method decodes an utterance specified by the input mfc data.
//
int uttproc_mfcdata(double *data, int num_samples) {

  // perform viterbi search
  //
  if (data != NULL && num_samples != 0) {
    tp.decoder_d->decode_cc(data, num_samples);
  }
  else {
    fprintf(stderr, "Communicator: No data for decoder to process!");
    return ISIP_FALSE;
  }
	
  // exit gracefully
  //
  return ISIP_TRUE;
}

// method: uttproc_begin
//
// arguments: none
//
// return: bool indicating status
//
// this method resets and re-allocates if necessary the decoder
// contents that need to be cleaned up before decoding a new utterance.
// this is called at the beginning of each utterance.
//
int uttproc_begin() {

  // reset the decoder
  //
  tp.decoder_d->reset_cc();

  // exit gracefully
  //
  return ISIP_TRUE;
}

// method: uttproc_end
//
// arguments: none
//
// return: bool indicating status
//
// this method marks that no more data is forthcoming in the current
// utterance. It processes the pending data and obtain the final
// recogition result.
//
int uttproc_end() {

  // process the pending frames
  //
  uttproc_rawdata(NULL, 0, 0);

  // perform viterbi search
  //
  tp.get_hypo_cc((char_1 *&)hypotheses, (char_1 *&)alignment);

  // clean up memory used for this utterance
  //
  tp.decoder_d->clean_cc();

  // cleanup the frontend before processing a new utterance
  //
  clean_frontend();
  
  return ISIP_TRUE;
}

// method: uttproc_abort
//
// arguments: none
//
// return: bool indicating status
//
// this method abort the current utterance immediately without final
// recognition result.
//
int uttproc_abort() {

  // clean up memory used for this utterance
  //
  fprintf(stdout, "Abort procedure, and clean up memory used for current utternace\n");
  fflush(stdout);
  tp.decoder_d->clean_cc();
  
  // cleanup the frontend before processing a new utterance
  //
  clean_frontend();

  return ISIP_TRUE;
}

// method: uttproc_result
//
// arguments: none
//
// return: bool indicating status
//
// this method obtains the final hypothesis for the current utterance
//
int uttproc_result(char** hypo) {

  if (hypo != NULL) {
    delete *hypo;
  }

  *hypo = new char[strlen((char*)hypotheses) + 1];
  sprintf(*hypo, "%s", hypotheses);

  return ISIP_TRUE;
}

// method: uttproc_alignment
//
// arguments: none
//
// return: bool indicating status
//
// this method obtains the final hypothesis for the current utterance
//
int uttproc_alignment(char** align) {

  if (align != NULL) {
    delete *align;
  }

  *align = new char[strlen((char*)alignment) + 1];
  sprintf(*align, "%s", alignment);

  return ISIP_TRUE;
}
