/* Copyright (c) 2002 Speech and Acoustics Processing Lab., NAIST */
/*  All rights reserved */

/*
 * mkss --- compute average spectrum of mic input for SS in Julius
 *
 * $Id: mkss.c,v 1.2 2002/09/11 22:07:05 ri Exp $
 *
 */

#include <sent/config.h> /* for WORDS_BIGENDIAN */
#include <sent/stddefs.h>
#include <sent/speech.h>
#include <sent/adin.h>
#include <sent/mfcc.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 slen  = 3000;	/* record length in msec */
static int fsize = 400;		/* frame size: 400 = 25ms in 16kHz */
static int fshift = 160;	/* frameshift: 160 = 10ms in 16khz */

/* parameter for SS */
static Value para;

/* print help and exit */
void
usage()
{
  fprintf(stderr, "mkss --- compute averate spectrum of mic input for SS\n");
  fprintf(stderr, "Usage: mkss [options..] filename\n");
  fprintf(stderr, "    [-freq frequency]    sampling freq in Hz   (%d)\n", sfreq);
  fprintf(stderr, "    [-len msec]          record length in msec (%d)\n", slen);
  fprintf(stderr, "    [-fsize samplenum]   window size           (%d)\n", fsize);
  fprintf(stderr, "    [-fshift samplenum]  frame shift           (%d)\n", fshift);
  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], "-len")) {
	i++;
	if (i >= argc) usage();
	slen = atoi(argv[i]);
      } else if (!strcmp(argv[i], "-fsize")) {
	i++;
	if (i >= argc) usage();
	fsize = atoi(argv[i]);
      } else if (!strcmp(argv[i], "-fshift")) {
	i++;
	if (i >= argc) usage();
	fshift = atoi(argv[i]);
      } 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];
    }
  }
}

int
main(int argc, char *argv[])
{
  int samples;
  SP16 *speech;
  float *ss;
  int sslen;

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

  /* ready the microphone (arg is dummy) */
  if (adin_mic_standby(sfreq, NULL) == FALSE) {
    j_printerr("Error: failed to ready input\n");
    return(1);
  }
  /* 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("mkss");
	return(1);
      }
    }
  }
  /* record mic input */
  samples = sfreq * slen / 1000;
  speech = (SP16 *)mymalloc(sizeof(SP16) * samples);
  fprintf(stderr, "recording %.2f second...", (float)slen /(float)1000);
  {
    int n = 0;
    int n_want, n_got;
    adin_mic_start();
    while(n < samples) {
      n_want = samples - n;
      n_got = adin_mic_read(&(speech[n]), n_want);
      if (n_got < 0) return(1);	/* mic read error */
      n += n_got;
    }
    adin_mic_stop();
  }
  fprintf(stderr, "%d samples (%d bytes) recorded\n", samples, samples * sizeof(SP16), (float)samples / (float)sfreq);

  /* compute SS */
  fprintf(stderr, "compute SS:\n");
  fprintf(stderr, "  fsize : %4d samples (%.1f msec)\n", fsize, (float)fsize * 1000.0/ (float)sfreq);
  fprintf(stderr, "  fshift: %4d samples (%.1f msec)\n", fshift, (float)fshift * 1000.0/ (float)sfreq);
  para.framesize  = fsize;
  para.frameshift = fshift;
  para.preEmph    = DEF_PREENPH;
  ss = new_SS_calculate(speech, samples, para, &sslen);
  
  /* open file for recording */
  fprintf(stderr, "writing result to [%s]...", filename);
  if (stout) {
    fd = 1;
  } else {
    if ((fd = creat(filename, 0644)) == -1) {
      perror("mkss");
      return(1);
    }
  }
  {
    int x;
    x = sslen;
#ifndef WORDS_BIGENDIAN
    swap_bytes((char *)&x, sizeof(int), 1);
#endif
    if (write(fd, &x, sizeof(int)) < 0) {
      perror("mkss");
      return(1);
    }
  }
#ifndef WORDS_BIGENDIAN
  swap_bytes((char *)ss, sizeof(float), sslen);
#endif
  if (write(fd, ss, sslen * sizeof(float)) < 0) {
    perror("mkss");
    return(1);
  }
  if (!stout) {
    if (close(fd) < 0) {
      perror("mkss");
      return(1);
    }
  }
  fprintf(stderr, "done\n");
  return 0;
}

