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

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

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

extern int vv_clean_frontend();

// static variables
//
Trace_projector tp_1;
char_1* hypotheses_1 = NULL;
char_1* alignment_1 = NULL;

Trace_projector tp_2;
char_1* hypotheses_2 = NULL;
char_1* alignment_2 = NULL;

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

  // open parameter file
  //
  FILE* fp_1 = (FILE*)NULL;
  fp_1 = fopen(params_1_a, "r");

  // open parameter file
  //
  FILE* fp_2 = (FILE*)NULL;
  fp_2 = fopen(params_2_a, "r");  
  
  // read parameters
  //
  tp_1.read_params_cc(fp_1);
  printf("Parameters #1 read.\n");
  tp_2.read_params_cc(fp_2);
  printf("Parameters #2 read.\n");
 
  // initialize frontend
  //
  vv_init_frontend((char*)tp_1.get_frontend_params(),
		   (char*)tp_2.get_frontend_params());
  
  printf("Frontend initialized.\n");

  // configure the decoder according to these parameter and load
  // models
  //
  tp_1.config_decoder_cc(ISIP_FALSE, ISIP_TRUE);
  printf("Decoder #1 configured.\n");
  tp_2.config_decoder_cc(ISIP_FALSE, ISIP_TRUE);  
  printf("Decoder #2 configured.\n");
  
  // 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 vv_uttproc_mfcdata(double *data, int num_samples) {

  // perform viterbi search
  //
  if (data != NULL && num_samples != 0) {
    tp_1.decoder_d->decode_cc(data, num_samples);
    tp_2.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 vv_uttproc_begin() {

  // reset the decoder
  //
  tp_1.decoder_d->reset_cc();
  tp_2.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 vv_uttproc_end() {

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

  // perform viterbi search
  //
  tp_1.get_hypo_cc((char_1 *&)hypotheses_1, (char_1 *&)alignment_1);
  tp_2.get_hypo_cc((char_1 *&)hypotheses_2, (char_1 *&)alignment_2);  

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

  // cleanup the frontend before processing a new utterance
  //
  vv_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 vv_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_1.decoder_d->clean_cc(ISIP_TRUE);
  tp_2.decoder_d->clean_cc(ISIP_TRUE);  
  
  // cleanup the frontend before processing a new utterance
  //
  vv_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 vv_uttproc_result(char** hypo_1, char** hypo_2) {

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

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

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

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

  return ISIP_TRUE;
}

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

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

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

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

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

  return ISIP_TRUE;
}

// method: load_again_models
//
// arguments:
//  char* params: (input) parameter file
//
// return: bool indicating status
//
// this method loads the recognition models
//
int vv_load_again_models(char* params_1_a, char* params_2_a) {

  // open parameter file
  //
  FILE* fp_1 = (FILE*)NULL;
  fp_1 = fopen(params_1_a, "r");

  // open parameter file
  //
  FILE* fp_2 = (FILE*)NULL;
  fp_2 = fopen(params_2_a, "r");  
  
  // read parameters
  //
  tp_1.read_params_cc(fp_1);
  printf("Parameters #1 read.\n");
  tp_2.read_params_cc(fp_2);
  printf("Parameters #2 read.\n");
 
  // initialize frontend
  //
  //vv_init_frontend((char*)tp_1.get_frontend_params(),
  //	   (char*)tp_2.get_frontend_params());
  
  // printf("Frontend initialized.\n");

  // configure the decoder according to these parameter and load
  // models
  //
  tp_1.config_decoder_cc(ISIP_FALSE, ISIP_TRUE);
  printf("Decoder #1 configured.\n");
  tp_2.config_decoder_cc(ISIP_FALSE, ISIP_TRUE);  
  printf("Decoder #2 configured.\n");
  
  // exit gracefully
  //
  return ISIP_TRUE;
}
  
