/*************************************************************************
 *
 * Normalizes logspectrum files.
 *
 *************************************************************************/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "VTS.h"

#define QUIT(x) {printf x; fflush(stdout); exit(-1);}

int main(int argc, char **argv)
{
	float *fbuff = NULL,	/* A temporary buffer */
	**z = NULL,		/* The observed logspectrum vectors */
	**x = NULL,		/* The compensated logspectrum */
	**xcep = NULL,		/* Cepstra computed from compensated logspectrum */
	**var = NULL,		/* Variance of gaussians */
	*prob = NULL,		/* Ratio of a-priori prob. of modes to mod variance */
	**mean = NULL,		/* The means */
	 nmean[256],		/* The noise mean */
	 nvar[256],		/* Noise variance */
	 chan[256];		/* The Channel/Tilt */

	int num_frames,		/* Number of frames in utterance */
	 num_gau,		/* Number of codewords in codebook */
	 num_utt,		/* Number of utterances in ctl-file */
	 Ndim,			/* Dimensionality of logspectra */
	 i;			/* Index for arguments */

	char ctl_file[1024],
	    code_file[1024],
	    buff[1024],
	    in_cepfile[1024], out_cepfile[1024], out_cepnoisefile[1024],
	    infileext[64], outfileext[64], inpath[512], outpath[512], sw;

	const char* logspec = "logspec"; // for logspec output
	int logspec_out = 0;
	int write_dim = -1;
	FILE *fp;

	/* Default */
	strcpy(ctl_file, "");
	strcpy(code_file, "");
	strcpy(infileext, "mfc");
	strcpy(outfileext, "vps.mfc");
	strcpy(inpath, "");
	strcpy(outpath, "");

	/* Input interface */

	if (argc <= 1) {
		printf(DESCRIPTION);
		QUIT((USAGE, argv[0]));
	}

	for (i = 1; i < argc; ++i) {
		if (argv[i][0] != '-')
			QUIT((USAGE, argv[0]));
		sw = argv[i][1];
		switch (sw) {
		case 'c':
		case 'C':
			{
				strcpy(ctl_file, argv[++i]);
				break;
			}
		case 'x':
		case 'X':
			{
				strcpy(infileext, argv[++i]);
				break;
			}
		case 'y':
		case 'Y':
			{
				strcpy(outfileext, argv[++i]);
				if(!strcmp(outfileext,logspec)){
					logspec_out = 1;
					printf("Logspec output turned on.\n");
				}
				break;
			}
		case 'i':
		case 'I':
			{
				strcpy(inpath, argv[++i]);
				break;
			}
		case 'o':
		case 'O':
			{
				strcpy(outpath, argv[++i]);
				break;
			}
		case 'd':
		case 'D':
			{
				strcpy(code_file, argv[++i]);
				break;
			}
		default:
			QUIT((USAGE, argv[0]));
		}
	}

	if (!strcmp(inpath, "") || !strcmp(outpath, "")
	    || !strcmp(code_file, "") || !strcmp(ctl_file, ""))
		QUIT((USAGE, argv[0]));

	/* Read distribution */
	readdistribution(code_file, &mean, &var, &prob, &num_gau, &Ndim);


	/* Read input log spectrum file and allocate memory */
	if ((fp = fopen(ctl_file, "r")) == NULL)
		QUIT(("Cannot open control file %s\n", ctl_file));

	for (num_utt = 0; fscanf(fp, "%s\n", buff) != EOF; num_utt++) {
		sprintf(in_cepfile, "%s/%s.%s", inpath, buff, infileext);
		sprintf(out_cepfile, "%s/%s.%s", outpath, buff,
			outfileext);
		sprintf(out_cepnoisefile, "%s/%s.%s.noise", outpath, buff,
			outfileext);

		fbuff = NULL;
		if (areadfloat(in_cepfile, &fbuff, &num_frames) < 0) {
			WARNING(("Unable to open %s\n", in_cepfile));
		} else {
			num_frames /= Ndim;
			z = (float **) two_D_ize(fbuff, num_frames, Ndim);
			x = (float **) alloc2d(num_frames, Ndim,
					       sizeof(float));

			initialize(chan, nmean, nvar, mean, var, prob, z,
				   num_frames, num_gau, Ndim);
			if (estimate
			    (z, prob, mean, var, nvar, chan, nmean,
			     num_frames, num_gau, Ndim)) {
				if (mmse
				    (x, z, prob, mean, var, nmean, nvar,
				     chan, num_frames, num_gau, Ndim)) {
#if 0
					FILE *nfile;
					nfile =
					    fopen(out_cepnoisefile, "w");
					if (nfile == NULL) {
						WARNING(("Unable to open %s for writing\n", out_cepnoisefile))
					} else {
						for (i = 0; i < Ndim; i++)
							fprintf(nfile,
								"%f ",
								nmean[i]);
						fprintf(nfile, "\n");
						fclose(nfile);
					}
#endif
					xcep = logspec_out ? x : logspec2cep(x, num_frames,Ndim, CEPDIM);
					write_dim = logspec_out ? Ndim : CEPDIM;
					if (write_cep
					    (out_cepfile, xcep, num_frames,
					     write_dim) == -1)
						WARNING(("Unable to write %s\n", out_cepfile));
					if(!logspec_out) free2d((void **) xcep);
				} else {
					WARNING(("Unable to run mmse on %s\n", out_cepfile))
				}
			} else {
				WARNING(("Unable to process %s\n",
					 in_cepfile))
			}
			free2d((void **) z);
			free2d((void **) x);
		}
	}
	printf("Totally, %d cepfiles have been processed (norm)\n",
	       num_utt);
	fflush(stdout);
	fclose(fp);
	free2d((void **) var);
	free2d((void **) mean);
	free(prob);

	return 0;
}
