/* file = real.c */
/* this basically does grab | feat | match, but in realtime */
/* Nigel Ward, University of Tokyo, April 1994 */

/* 1. read in command-line arguments
   2. initialize everything
   3. prompt the user
   4. process the input as it comes in
   5. end when silence detected
   6. output results
   7. clean-up */

/*-----------------------------------------------------------------------------*/
#include "cheap.h"
#define INTERVAL 512   /* samples per chunk */

/*-----------------------------------------------------------------------------*/
int verbosep = FALSE;
int normalizep = TRUE;
int prunep = TRUE;
int realtime_winp = FALSE;

static int echop = TRUE;
static int monitorp = FALSE;
static int write_fep = FALSE;
static int write_aup = FALSE;
static float threshold;

static FILE *output_fp;

/*-----------------------------------------------------------------------------*/
real_usage()    
{
  fprintf(stderr, "usage: \n");
  fprintf(stderr, "   real [options] output_file.wh [template_file]*\n");
  fprintf(stderr, "Options \n");
  fprintf(stderr, "  -    pipe mode (writes to standard output)\n");
  fprintf(stderr, "  -v   run verbosely \n");
  fprintf(stderr, "  -s   silent (don't echo recorded input to speaker)\n");
  fprintf(stderr, "  -m   continually show monitor result (signal or noise)\n");
  fprintf(stderr, "  -a   write recorded input to /tmp/real.au\n");
  fprintf(stderr, "  -f   write featurized version of input to /tmp/real.fe\n");
  fprintf(stderr, "  -r   show realtime word hypothesis scores in a window\n");
  fprintf(stderr, "  -u   match unnormalized (w/o energy-based normalization) \n");
  fprintf(stderr, "  -t <ratio> set threshold for signal detection (default = %.2f) \n",
	  DEFAULT_THRESHOLD);
}
 
/*-----------------------------------------------------------------------------*/
int process_real_args(argc, argv)    int argc;      char *argv[];
{
  int i;
  threshold = DEFAULT_THRESHOLD;
  i = 1;
  while(i < argc && argv[i][0] == '-') {
    switch(argv[i][1]) {
    case NULL:       /* pipe mode: use std output */
      output_fp = stdout;
      break;
    case 'v': verbosep = TRUE;  break;
    case 'a': write_aup = TRUE;     break;
    case 's': echop = FALSE;     break;
    case 'u': normalizep = FALSE;   break;
    case 'm': monitorp = TRUE;  break;
    case 'r': 
      /* pruing makes realtime result graphs misleading, so don't prune */
      realtime_winp = TRUE; prunep = FALSE; break;
    case 'f': write_fep = TRUE; break;
    case 't':       
      i++;
      sscanf(argv[i], "%f", &threshold);
      fprintf(stderr,"  threshold set to %.2f\n", threshold);
      break;
    case 'h':   real_usage(); exit(NORMAL);    break;
    default:  
      fprintf(stderr, "   (%c is not a known option)\n", argv[i][0]);
      real_usage(); exit(STRANGE); break;
    } 
    i++;
  }
  return(i - 1);
}

/*-----------------------------------------------------------------------------*/
main(argc, argv)      int argc;      char *argv[];
{
  int start_arg, use_logp; 
  int finished, signal_start, signal_end;
  char raw_data[MAX_SAMPLES];
  struct signature input;     
  int last_frame;
  char wh_file_name[MAX_PATH_LEN];  

  /*** process arguments ***/
  start_arg = 1 + process_real_args(argc, argv);
  if (output_fp != stdout) {
    if(start_arg >= argc) {fprintf(stderr, "real: no output file\n"); exit(STRANGE);}
    make_new_path(wh_file_name, argv[start_arg], ".wh");
    output_fp = fopen_or_exit(wh_file_name, "w"); 
    start_arg++;}
  use_logp = process_template_filenames(argc, argv, start_arg);

  /*** initialize ***/
  fprintf(stderr, " real: initializing ... ");
  measure_noise_level(TRUE, threshold);
  init_grab(MAX_SAMPLES, INTERVAL);
  init_input_sig(&input);
  input.logp = use_logp;    /* logify input iff templates logified */
  init_featurize_some();
  init_match(&input);
  finished = FALSE;
  /* beep();     /* prompt user */

  /*** the loop ***/
  while(!finished) {
    finished = grab_some(raw_data, &signal_start, &signal_end, monitorp);
    if (signal_start > -1) {
      last_frame = featurize_some(raw_data, signal_start, signal_end, FALSE, &input);
      if (last_frame > -1) {
	match_some(last_frame, &input); } } }

  /*** finish up ***/
  /* write, play, and display data; clean up windows, file pointers */
  clean_up_grab();
  finish_match_display(&input, output_fp);
  if (echop) {echo_signal(raw_data, signal_start, signal_end - signal_start);}
  if (write_aup) {save_to_au_file(raw_data, signal_start, signal_end);}
  if (write_fep) {save_to_fe_file(&input);}
  match_cleanup();
  exit(NORMAL);
}

/*-----------------------------------------------------------------------------*/
save_to_au_file(raw_data, signal_start, signal_end)      
     char raw_data[]; int signal_start, signal_end;
{
  int bytes_written;     int out_fd;

  out_fd = open("/tmp/real.au", O_WRONLY | O_CREAT | O_TRUNC, 0644);
  bytes_written = write(out_fd, raw_data + signal_start, signal_end - signal_start); 
  fprintf(stderr, " bytes written to file = %d\n", bytes_written);
  close(out_fd);
}
/*-----------------------------------------------------------------------------*/
save_to_fe_file(s_ptr)        struct signature *s_ptr;
{
  FILE *out_fp;

  out_fp = (FILE *) fopen("/tmp/real.fe", "w");
  write_fe_header(out_fp, s_ptr);
  write_fe_data(out_fp, s_ptr);
  close(out_fp);
}

/*-----------------------------------------------------------------------------*/
