/* Copyright (c) 1991-2002 Doshita Lab. Speech Group, Kyoto University */
/* Copyright (c) 2000-2002 Speech and Acoustics Processing Lab., NAIST */
/*   All rights reserved   */
/*
 * adinrec --- record 1 speech segment from speech input
 *             and save to a file
 *
 * $Id: adinrec.c,v 1.4 2002/09/11 22:03:53 ri Exp $
 *
 */

/* libsent headers */
#include <sent/stddefs.h>
#include <sent/speech.h>
#include <sent/adin.h>
#include <sent/tcpip.h>

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


static int speechlen;		/* data length of recorded sample */
static int fd = -1;		/* file descriptor for output */

static char *filename = NULL;	/* output file name */
static boolean stout = FALSE;	/* true if output to stdout ("-") */
static int sfreq = 16000;	/* sampling frequency */
static int level_thres = 3000;	/* default level threshold */
static int zero_cross_num = 60; /* default zerocross num */
static int margin = 400;	/* default sample margin (in msec) */
static boolean strip_zero_sample = TRUE; /* strip zero sample (on by default) */

/* print help and exit */
void
usage()
{
  fprintf(stderr, "adinrec --- record one sentence input to a file\n");
  fprintf(stderr, "Usage: adinrec [options..] filename\n");
  fprintf(stderr, "    [-freq frequency]     sampling frequency in Hz        (%d)\n", sfreq);
  fprintf(stderr, "    [-lv unsignedshort]   silence cut level threshold (%d)\n", level_thres);
  fprintf(stderr, "    [-zc zerocrossnum]    silence cut zerocross num   (%d)\n", zero_cross_num);
  fprintf(stderr, "    [-margin msec]        head/tail margin length         (%d)\n", margin);
  fprintf(stderr, "    [-nostrip]            not strip off zero samples\n");
  exit(1);
}

/* read option argument and set values */
void
opt_parse(int argc, char *argv[])
{
  int i;
  /* option parsing */
  if (argc <= 1) usage();
  for (i=1;i<argc;i++) {
    if (argv[i][0] == '-') {
      if (!strcmp(argv[i], "-freq")) {
	i++;
	if (i >= argc) usage();
	sfreq = atoi(argv[i]);
      } else if (!strcmp(argv[i], "-lv")) {
	i++;
	if (i >= argc) usage();
	level_thres = atoi(argv[i]);
      } else if (!strcmp(argv[i], "-zc")) {
	i++;
	if (i >= argc) usage();
	zero_cross_num = atoi(argv[i]);
      } else if (!strcmp(argv[i], "-margin")) {
	i++;
	if (i >= argc) usage();
	margin = atoi(argv[i]);
      } else if (!strcmp(argv[i], "-nostrip")) {
	strip_zero_sample = FALSE;
      } else if (!strcmp(argv[i], "-h")) {
	usage();
      } else if (!strcmp(argv[i], "-help")) {
	usage();
      } else if (!strcmp(argv[i], "--help")) {
	usage();
      } else if (!strcmp(argv[i], "-")) {
	stout = TRUE;
      } else {
	fprintf(stderr,"Unknown option: \"%s\"\n\n", argv[i]);
	usage();
      }
    } else {
      filename = argv[i];
    }
  }
}


/* callback handler of recorded sample fragments */
/* return value:
   -1 ... error -> exit, terminate 
   0  ... continue
   1  ... segmented -> exit, resume (not drop buffer)
*/
static int
adin_callback_file(SP16 *now, int len)
{
  int count;
  /* it may be safe to limit the maximum record len for disk space */
  /*if (speechlen + len > MAXSPEECHLEN) {
    fprintf(stderr, "Error: too long input (> %d samples)\n", MAXSPEECHLEN);
    return(FALSE);
    }*/
  /* open output file for the first time */
  if (fd == -1) {
    if (stout) {
      fd = 1;
    } else {
      if ((fd = creat(filename, 0644)) == -1) {
	perror("adinrec");
	return -1;
      }
    }
  }
  /* write recorded sample to file */
  count = wrsamp(fd, now, len);
  if (count < 0) perror("adinrec: cannot write");
  if (count < len * sizeof(SP16)) fprintf(stderr, "adinrec: cannot write more %d bytes\ncurrent length = %d\n", count, speechlen * sizeof(SP16));
  
  speechlen += len;
  
  /* progress bar in dots */
  fprintf(stderr, ".");		
  return(0);
}

int
main(int argc, char *argv[])
{
  int  size;
  int silence_cut = 1;	/* 0=disabled, 1=enabled, 2=undef */

  /* parse option */
  opt_parse(argc, argv);

  /* select microphone input */
  if (adin_select(SP_MIC) == FALSE) {
    j_printerr("Error: microphone input is not supported\n");
    return(1);
  }
  
  /* ready the microphone (arg is dummy) */
  if (adin_standby(sfreq, NULL) == FALSE) {
    j_printerr("Error: failed to standby input\n");
    return(1);
  }
  /* set device-independent param */
  adin_setup_param(silence_cut, strip_zero_sample, level_thres, zero_cross_num, margin, margin, sfreq);/* use same margin for head and tail */

  /* file check */
  if (!stout) {
    if (access(filename, F_OK) == 0) {
      if (access(filename, W_OK) == 0) {
	fprintf(stderr, "Warning: overwriting file \"%s\"\n", filename);
      } else {
	perror("adinrec");
	return(1);
      }
    }
  } /* output file will be opened when triggered (not here) */

  
  /* do recoding */
  speechlen = 0;
  
  adin_begin();
  adin_go(adin_callback_file, NULL);
  adin_end();

  /* end */
  size = sizeof(SP16) * speechlen;
  fprintf(stderr, "\n%d samples (%d bytes, %.2f sec.) recorded\n", speechlen, size, (float)speechlen / (float)sfreq);

  if (fd >= 0) {
    if (close(fd) == 0) {
      return 0;
    }
    perror("adinrec");
  }
  return -1;
}
