/* Copyright (c) 1991-2002 Doshita Lab. Speech Group, Kyoto University */
/* Copyright (c) 2000-2002 Speech and Acoustics Processing Lab., NAIST */
/*   All rights reserved   */

/* paramtypes.c --- HTK Parameter type utility functions */
/*                  convert string like "MFCC_E_D" with internal code */

/* $Id: paramtypes.c,v 1.2 2002/09/11 22:01:50 ri Exp $ */

#include <sent/stddefs.h>
#include <sent/htk_defs.h>
#include <sent/htk_param.h>


/* below are used both in HMM and in ParameterFile */
static OptionStr pbase[] = {	/* parameter base types */
  {"WAVEFORM", F_WAVEFORM, "sampled waveform", FALSE},
  {"DISCRETE", F_DISCRETE, "Discrete", FALSE},
  {"LPC", F_LPC, "LPC", TRUE},
  {"LPCEPSTRA", F_LPCEPSTRA, "LPC cepstral", TRUE},
  {"MFCC", F_MFCC, "mel-frequency cepstral", TRUE},
  {"FBANK", F_FBANK, "log mel-filter bank", TRUE},
  {"MELSPEC", F_MELSPEC, "linear mel-filter bank", TRUE},
  {"LPREFC", F_LPREFC, "LPC(reflection)", TRUE},
  {"LPDELCEP", F_LPDELCEP, "LPC+Delta", TRUE},
  {"USER", F_USER, "user defined sample kind", TRUE},
  {NULL,0,NULL,FALSE}
};
static OptionStr pqual[] = {	/* parameter qualifier */
  {"_E", F_ENERGY, "log energy coef.", TRUE},
  {"_N", F_ENERGY_SUP, "uppress absolute energy", TRUE},
  {"_D", F_DELTA, "delta coef.", TRUE},
  {"_A", F_ACCL, "acceleration coef.", TRUE},
  {"_C", F_COMPRESS, "compressed", TRUE},
  {"_Z", F_CEPNORM, "cepstral mean normalization", TRUE},
  {"_K", F_CHECKSUM, "CRC checksum added", TRUE},
  {"_0", F_ZEROTH, "0'th cepstral parameter", TRUE},
  {NULL,0,NULL,FALSE}
};


/* from string to code */

short				/* returns param_type code for qualifiers */
param_qualstr2code(char *s)
{
  int i, qlen;
  char *p;
  short qual_type;

  qual_type = 0;
  p = s;

  /* parse qualifiers */
  while (*p == '_') {
    for (i=0;pqual[i].name!=NULL;i++) {
      qlen = strlen(pqual[i].name);
      if (strncasecmp(p, pqual[i].name, qlen) == 0) {
	qual_type |= pqual[i].type;
	break;
      }
    }
    if (pqual[i].name == NULL) {	/* qualifier not found */
      j_printerr("ERROR: unknown parameter qualifier: %2s\n", p);
      return(F_ERR_INVALID);
    }
    p += 2;
  }

  return(qual_type);
}

short				/* returns param_type code */
param_str2code(char *s)
{
  int i;
  short param_type, qual_type;
  char *p, *buf;

  /* determine base type */
  /* cutout base part to *buf */
  buf = strcpy((char *)mymalloc(strlen(s)+1), s);
  p = strchr(buf, '_');
  if (p != NULL) *p = '\0';
  
  for (i=0;pbase[i].name!=NULL;i++) {
    if (strcasecmp(buf, pbase[i].name) == 0) {
      param_type = pbase[i].type;
      /* qualifiers */
      qual_type = param_qualstr2code(s + strlen(buf));
      if (qual_type == F_ERR_INVALID) {
	free(buf);
	return(F_ERR_INVALID);
      } else {
	param_type |= qual_type;
	free(buf);
	return(param_type);
      }
    }
  }
  /* base type not found */
  free(buf);
  return(F_ERR_INVALID);
}


/* from code to str */
char *				/* return pointer to given buffer (NULL on err)*/
param_qualcode2str(
     char *buf,			/* buffer to store result (must have enough length) */
     short type,		/* qualifier type code */
     boolean descflag)		/* set TRUE if want detailed description */
{
  int i;

  /* qualifier */
  for (i=0;pqual[i].name!=NULL;i++) {
    if (type & pqual[i].type) {
      if (descflag) {
	sprintf(buf, " %s %s\n", pqual[i].desc,
		(pqual[i].supported ? "" : "(not supported)"));
      } else {
	strcat(buf, pqual[i].name);
      }
    }
  }
  return(buf);
}


char *				/* return pointer to given buffer (NULL on err)*/
param_code2str(
     char *buf,			/* buffer to store result (must have enough length) */
     short type,		/* parameter type code */
     boolean descflag)		/* set TRUE if want detailed description */
{
  int i;
  short btype;

  /* basetype */
  btype = type & F_BASEMASK;
  for (i = 0; pbase[i].name != NULL; i++) {
    if (pbase[i].type == btype) {
      if (descflag) {
	sprintf(buf, "%s %s with:\n", pbase[i].desc,
		(pbase[i].supported ? "" : "(not supported)"));
      } else {
	strcpy(buf, pbase[i].name);
      }
      break;
    }
  }
  if (pbase[i].name  == NULL) {	/* not found */
    sprintf(buf, "ERROR: unknown basetype ID: %d\n", btype);
    return(buf);
  }

  /* add qualifier string to buf */
  param_qualcode2str(buf, type, descflag);

  return(buf);
}

