// file: $isip_ifc/class/sp/SignalDetector/sigd_07.cc
// version: $Id: sigd_07.cc 10214 2005-08-15 05:01:23Z stanley $
//

// isip include files
//
# include "SignalDetector.h"

// method: stateMachineReset
//
// arguments:
//  long channel_index: (input) audio channel index
//
// return: a boolean value indicating the status
//
// this method resets the state machine to the "noise" state
//
boolean SignalDetector::stateMachineReset(long channel_index_a) {
  
  // set to a noise state
  //
  states_d(channel_index_a)(0) = SM_STATE_NOIS;
  states_d(channel_index_a)(1) = SM_STATE_NOIS;
  states_d(channel_index_a)(2) = SM_STATE_NOIS;
  
  // clear the durations
  //
  for (long ns = (long)0; ns < SM_NSTATES; ns++) {
    durations_d(channel_index_a)(ns) = (long)0;
  }
  
  // exit gracefully
  //
  return true;
}

// method: stateMachineAdvance
//
// arguments:
//  float egy: (input) energy value to be considered
//  long channel_index: (input) audio channel index
//
// return: an long value indicating the current file state
//
// this method advanced the state machine by one input value. this is
// really the crucial method in this class.
//
// there are four states in this machine, and 12 types of transitions
// that can be made:
//
//  trans 00:		nois -> sign
//  trans 01:		nois -> ntos
//  trans 02:		nois -> nois
//  trans 03:		ntos -> ntos
//  trans 04:		ntos -> nois
//  trans 05:		ntos -> sign
//  trans 06:		sign -> sign
//  trans 07:		sign -> ston
//  trans 08:		sign -> nois
//  trans 09:		ston -> ston
//  trans 10:		ston -> nois
//  trans 11:		ston -> sign
// 
// Each of these is treated seperately below.
// 

long SignalDetector::stateMachineAdvance(float egy_a, long channel_index_a) {
  
  // shift contents
  //
  states_d(channel_index_a)(2) = states_d(channel_index_a)(1);
  states_d(channel_index_a)(1) = states_d(channel_index_a)(0);
  
  // treat the states emanating from the noise state (00 to 02)
  //
  if (states_d(channel_index_a)(1) == SM_STATE_NOIS) {
    
    // trans #00
    //
    if (egy_a > (signal_threshold_d - utterance_delta_d)) {
      states_d(channel_index_a)(0) = SM_STATE_SIGN;
      durations_d(channel_index_a)(SM_STATE_SIGN) = 1;
    }
    
    // trans # 01
    //
    else if (egy_a > (noise_threshold_d + utterance_delta_d)) {
      states_d(channel_index_a)(0) = SM_STATE_NTOS;
      durations_d(channel_index_a)(SM_STATE_NTOS) = durations_d(channel_index_a)(SM_STATE_NOIS) + (long)1;
    }
    
    // trans # 02
    //
    else if (egy_a <= (noise_threshold_d + utterance_delta_d)) {
      states_d(channel_index_a)(0) = SM_STATE_NOIS;
      durations_d(channel_index_a)(SM_STATE_NOIS) += 1;
    }
    
    
  }
  
  // treat the states emanating from the noise to signal state (03 to 05)
  //
  else if (states_d(channel_index_a)(1) == SM_STATE_NTOS) {
    
    // trans #03
    //
    if ((egy_a > (noise_threshold_d + utterance_delta_d)) &&
	(egy_a < (signal_threshold_d - utterance_delta_d))) {
      states_d(channel_index_a)(0) = SM_STATE_NTOS;
      durations_d(channel_index_a)(SM_STATE_NTOS) += 1;
    }
    
    // trans # 04
    //
    else if (egy_a <= (noise_threshold_d + utterance_delta_d)) {
      states_d(channel_index_a)(0) = SM_STATE_NOIS;
      durations_d(channel_index_a)(SM_STATE_NOIS) = durations_d(channel_index_a)(SM_STATE_NTOS) + (long)1;
    }
    
    // trans # 05
    //
    else if (egy_a >= (signal_threshold_d - utterance_delta_d)) {
      states_d(channel_index_a)(0) = SM_STATE_SIGN;
      durations_d(channel_index_a)(SM_STATE_SIGN) = 1;
    }
  }
  
  // treat the states emanating from the signal state (06 to 08)
  //
  else if (states_d(channel_index_a)(1) == SM_STATE_SIGN) {
    
    // trans #06
    //
    if (egy_a >= (signal_threshold_d - utterance_delta_d)) {
      states_d(channel_index_a)(0) = SM_STATE_SIGN;
      durations_d(channel_index_a)(SM_STATE_SIGN) += 1;
    }
    
    // trans # 07
    //
    else if ((egy_a < (signal_threshold_d - utterance_delta_d)) &&
	     (egy_a > (noise_threshold_d + utterance_delta_d))) {
      states_d(channel_index_a)(0) = SM_STATE_STON;
      durations_d(channel_index_a)(SM_STATE_STON) = durations_d(channel_index_a)(SM_STATE_SIGN) + (long)1;
    }
    
    // trans # 08
    //
    else if (egy_a <= (noise_threshold_d + utterance_delta_d)) {
      states_d(channel_index_a)(0) = SM_STATE_NOIS;
      durations_d(channel_index_a)(SM_STATE_NOIS) = 1;
    }
  }
  
  // treat the states emanating from the signal to noise state (09 to 11)
  //
  else if (states_d(channel_index_a)(1) == SM_STATE_STON) {
    
    // trans #09
    //
    if ((egy_a < (signal_threshold_d - utterance_delta_d)) &&
	(egy_a > (noise_threshold_d + utterance_delta_d))) {
      states_d(channel_index_a)(0) = SM_STATE_STON;
      durations_d(channel_index_a)(SM_STATE_STON) += 1;
    }
    
    // trans # 10
    //
    else if (egy_a <= (noise_threshold_d + utterance_delta_d)) {
      states_d(channel_index_a)(0) = SM_STATE_NOIS;
      durations_d(channel_index_a)(SM_STATE_NOIS) = 1;
    }
    
    // trans # 11
    //
    else if (egy_a >= (signal_threshold_d - utterance_delta_d)) {
      states_d(channel_index_a)(0) = SM_STATE_SIGN;
      durations_d(channel_index_a)(SM_STATE_SIGN) = durations_d(channel_index_a)(SM_STATE_STON) + (long)1;
    }
  }
  
  // exit gracefully
  //
  return states_d(channel_index_a)(0);
}
