/*-----------------------------------------------------------------------------
        Routine to initialize channel, noise mean and noise variance.
        channel is initialized as the mean difference between clean
        speech and the noisy speech.
        Noise mean is initialized as the mean of the vectors below a
        threshold
        Noise var is set to the variance of the zeroth gaussian
-----------------------------------------------------------------------------*/
#include "VTS.h"

void initialize(float *chan,
		float *nmean,
		float *nvar,
		float **xmean,
		float **xvar,
		float *prob,
		float **z, int n_frames, int n_modes, int ndim)
{
	int i, j, nnoise;
	float global_mean[256], obsmean[256];
	float temp, min, threshold;
	float get_c0(float *, int);
	float min_chan = -5, min_noise = -5, min_nvar = 1.0e-15f;
	float max_chan = 20, max_noise = 20, max_nvar = 50;

	/*
	 * Initialize chan to the difference between clean speech mean and
	 * Observation mean
	 */

	for (j = 0; j < ndim; ++j)
		global_mean[j] = obsmean[j] = nmean[j] = 0;

	for (i = 0; i < n_modes; ++i)
		for (j = 0; j < ndim; ++j)
			global_mean[j] += prob[i] * xmean[i][j];

	for (i = 0; i < n_frames; ++i)
		for (j = 0; j < ndim; ++j)
			obsmean[j] += z[i][j];

	for (j = 0; j < ndim; ++j)
		chan[j] = obsmean[j] / n_frames - global_mean[j];

	/*
	 * Initialize noise variance to the variance of the zeroth mode
	 */
	for (j = 0; j < ndim; ++j)
		nvar[j] = xvar[0][j];
//nvar[j] = 1.0;

	/*
	 * Initialize noise mean to the average of all frames below a threshold
	 */
	min = get_c0(z[0], ndim);
	for (i = 1; i < n_frames; ++i)
		if ((temp = get_c0(z[i], ndim)) < min)
			min = temp;

	threshold = min + SPEECH_THRESHOLD;
	nnoise = 0;
	for (i = 0; i < n_frames; ++i) {
		if (get_c0(z[i], ndim) < threshold) {
			for (j = 0; j < ndim; ++j)
				nmean[j] += z[i][j];
			++nnoise;
		}
	}
	for (j = 0; j < ndim; ++j)
		nmean[j] /= nnoise;

	for (j = 0; j < ndim; j++) {
		if (nmean[j] < min_noise)
			nmean[j] = min_noise;
		if (nmean[j] > max_noise)
			nmean[j] = max_noise;
		if (chan[j] < min_chan)
			chan[j] = min_chan;
		if (chan[j] > max_chan)
			chan[j] = max_chan;
		if (nvar[j] < min_nvar)
			nvar[j] = min_nvar;
		if (nvar[j] > max_nvar)
			nvar[j] = max_nvar;
	}

	return;
}



/*
 * We compute thresholds on c[0].
 * This routine computes cep[0] from logspectral vectors
 */

float get_c0(float *vector, int dim)
{
	int i;
	float total = 0;

	for (i = 0; i < dim; ++i)
		total += vector[i];

	return (total);
}
