/*      K L A T T . C                                  */
/*      program to drive Klatt's PARWAVE routine       */
/*      25 July 1987                                   */
/*      L. Goldstein, S. Levy                          */
/*      version with no graphics                       */
/*******************************************************/

#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>

#include "multimedia/libaudio.h"
#include "multimedia/audio_filehdr.h"
#include "multimedia/ulaw2linear.h"

#include "proto.h"
#include "parwave.h"
#include "hplay.h"

#define MAX_FRAMES      10000
#define NUM_SET_PARS 20

#define SAMP_RATE 8000

#define NMSPF_DEF 10
static int nmsec_per_frame = NMSPF_DEF;

#define NF_DEF 20
#define MAX_SAM 500
#define NFRAMES 20
#define NFRAMES_PER_PAGE 20
#define NSAMP_PER_BLOCK 256
#define MIDSCALE 2048
#define MAX_PLA 100000
#define NCHANGE 20
#define SWITCH 5
#define BADVAL 99
#define CR 13
#define ZERO 48
#define NINE 57
#define BACKSPACE 8
#define NPARTOT 47

/****************************************************************************/

/* default values for pars array from .doc file */
long def_pars[NPAR] =
{
 1000,  /* F0        */
 60,    /* AV        */
 500,   /* F1        */
 60,    /* BW1       */
 1500,  /* F2        */
 90,    /* BW2       */
 2800,  /* F3        */
 150,   /* BW3       */
 3250,  /* F4        */
 200,   /* BW4       */
 3700,  /* F5        */
 200,   /* BW5       */
 4990,  /* F6        */
 500,   /* BW6       */
 280,   /* Fnz       */
 90,    /* BWnz      */
 280,   /* Fnp       */
 90,    /* BWnp      */
 0,     /* Aasp      */
 30,    /* Nopn      */
 0,     /* Atur      */
 0,     /* tilt      */
 0,     /* Afrc      */
 0,     /* skew      */
 0,     /* A1        */
 80,    /* BWp1      */
 0,     /* A2        */
 200,   /* BWp2      */
 0,     /* A3        */
 350,   /* BWp3      */
 0,     /* A4        */
 500,   /* BWp4      */
 0,     /* A5        */
 600,   /* BWp5      */
 0,     /* A6        */
 800,   /* BWp6      */
 0,     /* AN        */
 0,     /* AB        */
 0,     /* AVpa      */
 66     /* G0        */
};

/****************************************************************************/

#if 0
/*  index array = pointers to items in def_pars sorted by order in con_file */
static int index[] =
{7, 8, 14, 22, 15, 23, 16, 24, 17, 25,
 18, 26, 19, 27, 20, 28, 21, 29, 9, 11,
 10, 12, 30, 13, 31, 38, 32, 39, 33, 40,
 34, 41, 35, 42, 36, 43, 45, 37, 44, 46};
#endif

/* header for parameter listing */

char *par_header[] =
{
 "#", "F0", "F1", "F2", "F3",
 "B1", "B2", "B3",
 "FNZ", "FNP",
 "AV",
 "TL",
 "AH", "AF", "A1", "A2", "A3", "A4", "A5", "A6",
 "AB"};

#if 0
/*    Speaker Definition */
long spkrdef[] =
{
 0,                  /* OUTSELECT (Select which output waveform to save)  */
 SAMP_RATE,          /* SAMRAT                                            */
 80,                 /* NSAMP_PER_FRAME (= SAMRAT * N_MSEC_FRAME) / 1000) */
 900, /* Not used */ /* FLPHZ dwnsampling low-pass filter, glottal source */
 600, /* Not used */ /* BLPHZ dwnsampling low-pass filter, glottal source */
 1,                  /* RANSEED (Initial value for variable "nrand")      */
 3,                  /* NFCASC (Number formants in cascade vocal tract)   */
 1,                  /* SOURCE_SELECT (1->impulse, 2-> natural            */
};
#endif

int synthesis_model = CASCADE_PARALLEL;
long nfcascade      = 4;          
long samrate        = SAMP_RATE;
long nspfr          = (SAMP_RATE * NMSPF_DEF)/1000;



long sigmx;
static short iwave[MAX_SAM];
static int isam, totsam;
static int icount, par_count;
static short par_array[NPAR][MAX_FRAMES];          /* parameter buffer */

/* Mapping table - indexed by "gen" parameter number as
   written to .par file, gives index of corresponding "klatt"
   parameter.
*/
static const int change[NUM_SET_PARS] =
{0, 2, 4, 6, 3, 5, 7, 14, 16, 1, 21, 18, 22, 24, 26, 28, 30, 32, 34, 37};
long pars[NPAR];
long initsw, warnsw, dispt, disptcum;
static int nframes, dur_of_stim;

int bDebug = 0;
FILE *debug1, *debug2;

/* initialize the array of user-modified parameters to the defaults in
   the parameter buffer */

void
init_par_array()
{
 int i;
 for (i = 0; i < NPAR; ++i)
  {int j;
   pars[i] = def_pars[i];
   for (j = 0; j < MAX_FRAMES; ++j)
    par_array[i][j] = pars[i];
  }
}

/* read parameter values from a file into the parameter array */

int
read_pars(name)
char *name;
{int i = 0;
 FILE *f = fopen(name,"r");
 if (f)
  {
   int numread;
   do
    {int j;
     for (j = 0; j < NUM_SET_PARS; j++)
      {int dummy;
       numread = fscanf(f, "%d", (int *) &dummy);
       par_array[change[j]][i] = dummy;
      }
     ++i;
    }
   while (numread != -1);
   fclose(f);
  }
 else
  {
   perror(name);
  }
 return i;
}

int
main(argc,argv)
int argc;
char *argv[];
{
#if 0
 900, /* Not used */ /* FLPHZ dwnsampling low-pass filter, glottal source */
 600, /* Not used */ /* BLPHZ dwnsampling low-pass filter, glottal source */
 1,                  /* RANSEED (Initial value for variable "nrand")      */
#endif
 nmsec_per_frame = NMSPF_DEF;

 /* Set up parwave variables
    These differ from those of klatt.c but make new
    parwave.c compatible with the old one.
 */
 outsl           = 0;
 glsource        = IMPULSIVE;
 synthesis_model = CASCADE_PARALLEL;
 nfcascade       = 3;
 init_par_array();
 nframes = read_pars(argv[1]);
 if (nframes)
  {
   int ibuf = 0;
   unsigned char plabuf[MAX_PLA];
   dur_of_stim = nframes * nmsec_per_frame - nmsec_per_frame;
   initsw = 0;
   warnsw = 0;
   dispt = 0;
   disptcum = 0;

   for (icount = 0; icount < nframes; icount++)
    {
     for (par_count = 0; par_count < NPAR; ++par_count)
      pars[par_count] = par_array[par_count][icount];
     parwav(&iwave[0]);
     /* This next bit converts to u-law and should be in
        hplay() so that that can be made device specific
        leaving this module generic
     */
     for (isam = 0; isam < nspfr; ++isam)
      {
       plabuf[ibuf] = audio_s2u(iwave[isam]);
       ibuf++;
      }
     totsam = ibuf;
    }
   hplay(totsam, 0, plabuf);
  }
 return 0;
}


