// file: dec_input_0.cc
//
 
// isip include files
//
#include "decoder.h"
#include "decoder_constants.h"

// method: read_features_cc
//
// arguments:
//  FILE* fp: (input) file pointer
//  logical_1& start: (input) flag indicating start of utterance to
//                    intialize the circular buffer implemented in
//                    the compute_delta_cc method
//  
// return: a logical_1 indicating status
//
// this method reads in the input feature vector from file
//
logical_1 Decoder::read_features_cc(FILE* fp_a, logical_1& start) {

  // check file
  //
  if (fp_a == (FILE*)NULL) {
    error_handler_cc((char_1*)"read_features_cc",
		     (char_1*)"NULL input file pointer");
  }
  
  // initialize features if not done so
  //
  if (features_d == (float_4*)NULL) {
    features_d = new float_4[num_feat_d];
    memset(features_d, 0, sizeof(float_4)*num_feat_d);
  }

  for (int_4 i = 0; i < num_feat_d; i++) {
    features_d[i] = (int_4)0;
  }
  
  float_8* tmp_features = new float_8[num_feat_d];
  memset(tmp_features, 0, sizeof(float_8)*num_feat_d);
  
  for (int_4 i = 0; i < num_feat_d; i++){
    tmp_features[i] = (int_4)0;
  }

  float_4* features_float = new float_4[num_feat_d];
  memset(features_float, 0, sizeof(float_4)*num_feat_d);
  
  for (int_4 i = 0; i < num_feat_d; i++){
    features_float[i] = (int_4)0;
  }
  
  // local variables
  //
  logical_1 flag = ISIP_FALSE;
  int_4 i = 0;
  int_4 time = (int_4)0;
  int_4 temp_num_feat = (int_4)0;

  // if this is ascii format data
  //
  if (input_format_d == DEC_ASCII_FORMAT) {
    
    // if this is input format is HTK
    // error
    if (input_feature_format_d == DEC_HTK_FORMAT) {
      error_handler_cc((char_1*)"dec_input_0.cc", (char_1*)"HTK feature file should be in binary and not ascii");
    }
    
    // read values one at a time
    //
    while (fscanf(fp_a, "%lf", &tmp_features[i]) != EOF) {
      
      // copy the data to the float buffer
      //
      features_d[i] = tmp_features[i++];
      
      // error message if input feature value is NaN
      //
      if (isnan(features_d[i-1])) {
	error_handler_cc((char_1*)"dec_input_0.cc", (char_1*)"Input feature value is NaN");
      }
      
      // if data is read
      //
      if (i == num_feat_d) {
	flag = ISIP_TRUE;
	break;
      }
    }
  }
  
  // otherwise this is binary format data
  //
  else {

    // compute deltas or accelerations on the fly if required
    // if the input feature format is HTK read features as floats
    //
    if (acc_d == ISIP_TRUE) {
      temp_num_feat = num_feat_d/3;
    }
    else if (delta_d == ISIP_TRUE) {
      temp_num_feat = num_feat_d/2;
    }
    else temp_num_feat = num_feat_d;
    
    if (((delta_d || acc_d) == ISIP_TRUE)
	&& (input_feature_format_d == DEC_HTK_FORMAT) ) {
      
      // read vector at once
      //
      if ((int_4)fread(features_float, sizeof(float_4), temp_num_feat, fp_a)
	  == temp_num_feat) {
	for (int_4 j = 0; j < temp_num_feat; j++) {
	  features_d[j] = features_float[j];
	  tmp_features[j] = (float_8)features_float[j];
	}

	// if first utterence
	//
	if (start) {
	  time = DEC_UTT_START;
	}
	
	else {
	  time = DEC_UTT_DURING;
	}
	
	// compute only deltas on the fly if required
	//
	if (delta_d == ISIP_TRUE) {
	  while(!Extract_feature::compute_delta_cc(tmp_features,
						   temp_num_feat, delta_win_d,
						   acc_d, time)) {
	    start = ISIP_FALSE;
	    time = DEC_UTT_DURING;
	    
	    if ((int_4)fread(features_float, sizeof(float_4),
			     temp_num_feat, fp_a)
		!= temp_num_feat) {
	      for (int_4 k = 0; k < temp_num_feat; k++) {
		tmp_features[k] = (float_8)features_float[k];
	      }
	      break;
	    }
	  }
	}

	for (int_4 j = 0; j < num_feat_d; j++) {
	  features_d[j] = (float_4)tmp_features[j];
	}
	
	// error message if input feature value is NaN
	//
	for (int_4 j = 0; j < num_feat_d; j++) {
	  if (isnan(features_d[j])) {
	    error_handler_cc((char_1*)"dec_input_0.cc", (char_1*)"Input feature value is NaN");
	  }
	}
	flag = ISIP_TRUE;
      }
      
      else {
	
	// last frames
	//
	time = DEC_UTT_END;
	
	// compute deltas and accelerations on the fly if required
	//
	if (delta_d == ISIP_TRUE) {
	  if (Extract_feature::compute_delta_cc(tmp_features, temp_num_feat,
						delta_win_d, acc_d, time)) {
	    flag = ISIP_TRUE;
	  }
	}
	
	for (int_4 j = 0; j < num_feat_d; j++) {
	  features_d[j] = (float_4)tmp_features[j];
	}
	
	// error message if input feature value is NaN
	//
	for (int_4 j = 0; j < num_feat_d; j++) {
	  if (isnan(features_d[j])) {
	    error_handler_cc((char_1*)"dec_input_0.cc", (char_1*)"Input feature value is NaN");
	  }
	}
      }
    }

    // read features as doubles if not HTK format
    //
    else if (((delta_d || acc_d) == ISIP_TRUE)
	&& (input_feature_format_d == DEC_ISIP_PROTO_FORMAT)) {
     
      // read vector at once
      //
      if ((int_4)fread(tmp_features, sizeof(float_8), temp_num_feat, fp_a)
	  == temp_num_feat) {
	for (int_4 j = 0; j < temp_num_feat; j++) {
	  features_d[j] = (float_4)tmp_features[j];
	}

	// if first utterence
	//
	if (start) {
	  time = DEC_UTT_START;
	}
	
	else {
	  time = DEC_UTT_DURING;
	}
	
	// compute only deltas on the fly if required
	//
	if (delta_d == ISIP_TRUE) {
	  while(!Extract_feature::compute_delta_cc(tmp_features,
						   temp_num_feat, delta_win_d,
						   acc_d, time)) {
	    start = ISIP_FALSE;
	    time = DEC_UTT_DURING;
	    
	    if ((int_4)fread(tmp_features, sizeof(float_8), temp_num_feat,
			     fp_a) != temp_num_feat) {
	      break;
	    }
	  }
	}

	for (int_4 j = 0; j < num_feat_d; j++) {
	  features_d[j] = (float_4)tmp_features[j];
	}
	
	// error message if input feature value is NaN
	//
	for (int_4 j = 0; j < num_feat_d; j++) {
	  if (isnan(features_d[j])) {
	    error_handler_cc((char_1*)"dec_input_0.cc", (char_1*)"Input feature value is NaN");
	  }
	}
	flag = ISIP_TRUE;
      }
      
      else {
	
	// last frames
	//
	time = DEC_UTT_END;
	
	// compute deltas and accelerations on the fly if required
	//
	if (delta_d == ISIP_TRUE) {
	  if (Extract_feature::compute_delta_cc(tmp_features, temp_num_feat,
						delta_win_d, acc_d, time)) {
	    flag = ISIP_TRUE;
	  }
	}
	
	for (int_4 j = 0; j < num_feat_d; j++) {
	  features_d[j] = (float_4)tmp_features[j];
	}
	
	// error message if input feature value is NaN
	//
	for (int_4 j = 0; j < num_feat_d; j++) {
	  if (isnan(features_d[j])) {
	    error_handler_cc((char_1*)"dec_input_0.cc", (char_1*)"Input feature value is NaN");
	  }
	}
      }
    }
    
    // read vector at once as doubles (ISIP format)
    //
    else if (input_feature_format_d == DEC_ISIP_PROTO_FORMAT) {
      if ((int_4)fread(tmp_features, sizeof(float_8), num_feat_d, fp_a)
	  == num_feat_d) {
	for (int_4 j = 0; j < num_feat_d; j++) {
	  features_d[j] = (float_4)tmp_features[j];
	  
	  // error message if input feature value is NaN
	  //
	  if (isnan(features_d[j])) {
	    error_handler_cc((char_1*)"dec_input_0.cc", (char_1*)"Input feature value is NaN");
	  }
	}
	flag = ISIP_TRUE;      
      }
    }
    
    // read vector at once as float (htk format)
    //
    else if (input_feature_format_d == DEC_HTK_FORMAT) {
      if ((int_4)fread(features_float, sizeof(float_4), num_feat_d, fp_a)
	  == num_feat_d) {
	for (int_4 j = 0; j < num_feat_d; j++) {
	  features_d[j] = features_float[j];
	  
	  // error message if input feature value is NaN
	  //
	  if (isnan(features_d[j])) {
	    error_handler_cc((char_1*)"dec_input_0.cc", (char_1*)"Input feature value is NaN");
	  }
	}
	flag = ISIP_TRUE;      
      }
    }
    
    else {
      flag = ISIP_FALSE;
      
    }
  }
  
  // clean up
  //
  delete [] tmp_features;
  delete [] features_float;
  
  // exit gracefully
  //
  return flag;
}
