summaryrefslogtreecommitdiffstats
path: root/media/pocketsphinx/src/ms_gauden.c
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /media/pocketsphinx/src/ms_gauden.c
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'media/pocketsphinx/src/ms_gauden.c')
-rw-r--r--media/pocketsphinx/src/ms_gauden.c617
1 files changed, 617 insertions, 0 deletions
diff --git a/media/pocketsphinx/src/ms_gauden.c b/media/pocketsphinx/src/ms_gauden.c
new file mode 100644
index 000000000..7c3527480
--- /dev/null
+++ b/media/pocketsphinx/src/ms_gauden.c
@@ -0,0 +1,617 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* ====================================================================
+ * Copyright (c) 1999-2004 Carnegie Mellon University. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * This work was supported in part by funding from the Defense Advanced
+ * Research Projects Agency and the National Science Foundation of the
+ * United States of America, and the CMU Sphinx Speech Consortium.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY ``AS IS'' AND
+ * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY
+ * NOR ITS EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ====================================================================
+ *
+ */
+/*
+ * gauden.c -- gaussian density module.
+ *
+ ***********************************************
+ * CMU ARPA Speech Project
+ *
+ * Copyright (c) 1996 Carnegie Mellon University.
+ * ALL RIGHTS RESERVED.
+ ***********************************************
+ *
+ * HISTORY
+ * $Log$
+ * Revision 1.7 2006/02/22 17:09:55 arthchan2003
+ * Merged from SPHINX3_5_2_RCI_IRII_BRANCH: 1, Followed Dave's change, keep active to be uint8 instead int8 in gauden_dist_norm.\n 2, Introdued gauden_dump and gauden_dump_ind. This allows debugging of ms_gauden routine. \n 3, Introduced gauden_free, this fixed some minor memory leaks. \n 4, gauden_init accept an argument precompute to specify whether the distance is pre-computed or not.\n 5, Added license. \n 6, Fixed dox-doc.
+ *
+ *
+ * Revision 1.5.4.7 2006/01/16 19:45:59 arthchan2003
+ * Change the gaussian density dumping routine to a function.
+ *
+ * Revision 1.5.4.6 2005/10/09 19:51:05 arthchan2003
+ * Followed Dave's changed in the trunk.
+ *
+ * Revision 1.5.4.5 2005/09/25 18:54:20 arthchan2003
+ * Added a flag to turn on and off precomputation.
+ *
+ * Revision 1.6 2005/10/05 00:31:14 dhdfu
+ * Make int8 be explicitly signed (signedness of 'char' is
+ * architecture-dependent). Then make a bunch of things use uint8 where
+ * signedness is unimportant, because on the architecture where 'char' is
+ * unsigned, it is that way for a reason (signed chars are slower).
+ *
+ * Revision 1.5.4.4 2005/09/07 23:29:07 arthchan2003
+ * Added FIXME warning.
+ *
+ * Revision 1.5.4.3 2005/09/07 23:25:10 arthchan2003
+ * 1, Behavior changes of cont_mgau, instead of remove Gaussian with zero variance vector before flooring, now remove Gaussian with zero mean and variance before flooring. Notice that this is not yet synchronize with ms_mgau. 2, Added warning message in multi-stream gaussian distribution.
+ *
+ * Revision 1.5.4.2 2005/08/03 18:53:44 dhdfu
+ * Add memory deallocation functions. Also move all the initialization
+ * of ms_mgau_model_t into ms_mgau_init (duh!), which entails removing it
+ * from decode_anytopo and friends.
+ *
+ * Revision 1.5.4.1 2005/07/20 19:39:01 arthchan2003
+ * Added licences in ms_* series of code.
+ *
+ * Revision 1.5 2005/06/21 18:55:09 arthchan2003
+ * 1, Add comments to describe this modules, 2, Fixed doxygen documentation. 3, Added $ keyword.
+ *
+ * Revision 1.3 2005/03/30 01:22:47 archan
+ * Fixed mistakes in last updates. Add
+ *
+ *
+ * 20-Dec-96 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University.
+ * Changed gauden_param_read to use the new libio/bio_fread functions.
+ *
+ * 26-Sep-96 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University.
+ * Added gauden_mean_reload() for application of MLLR; and correspondingly
+ * made gauden_param_read allocate memory for parameter only if not
+ * already allocated.
+ *
+ * 09-Sep-96 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University.
+ * Interleaved two density computations for speed improvement.
+ *
+ * 19-Aug-96 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University.
+ * Added compute_dist_all special case for improving speed.
+ *
+ * 26-Jan-96 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University.
+ * Added check for underflow and floor insertion in gauden_dist.
+ *
+ * 20-Jan-96 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University.
+ * Added active argument to gauden_dist_norm and gauden_dist_norm_global,
+ * and made the latter a static function.
+ *
+ * 07-Nov-95 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University.
+ * Initial version created.
+ * Very liberally borrowed/adapted from Eric's S3 trainer implementation.
+ */
+
+/* System headers. */
+#include <assert.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+
+/* SphinxBase headers. */
+#include <sphinxbase/bio.h>
+#include <sphinxbase/err.h>
+#include <sphinxbase/ckd_alloc.h>
+
+/* Local headesr. */
+#include "ms_gauden.h"
+
+#define GAUDEN_PARAM_VERSION "1.0"
+
+#ifndef M_PI
+#define M_PI 3.1415926535897932385e0
+#endif
+
+#define WORST_DIST (int32)(0x80000000)
+
+void
+gauden_dump(const gauden_t * g)
+{
+ int32 c;
+
+ for (c = 0; c < g->n_mgau; c++)
+ gauden_dump_ind(g, c);
+}
+
+
+void
+gauden_dump_ind(const gauden_t * g, int senidx)
+{
+ int32 f, d, i;
+
+ for (f = 0; f < g->n_feat; f++) {
+ E_INFO("Codebook %d, Feature %d (%dx%d):\n",
+ senidx, f, g->n_density, g->featlen[f]);
+
+ for (d = 0; d < g->n_density; d++) {
+ printf("m[%3d]", d);
+ for (i = 0; i < g->featlen[f]; i++)
+ printf(" %7.4f", MFCC2FLOAT(g->mean[senidx][f][d][i]));
+ printf("\n");
+ }
+ printf("\n");
+
+ for (d = 0; d < g->n_density; d++) {
+ printf("v[%3d]", d);
+ for (i = 0; i < g->featlen[f]; i++)
+ printf(" %d", (int)g->var[senidx][f][d][i]);
+ printf("\n");
+ }
+ printf("\n");
+
+ for (d = 0; d < g->n_density; d++)
+ printf("d[%3d] %d\n", d, (int)g->det[senidx][f][d]);
+ }
+ fflush(stderr);
+}
+
+static int32
+gauden_param_read(float32 ***** out_param, /* Alloc space iff *out_param == NULL */
+ int32 * out_n_mgau,
+ int32 * out_n_feat,
+ int32 * out_n_density,
+ int32 ** out_veclen, const char *file_name)
+{
+ char tmp;
+ FILE *fp;
+ int32 i, j, k, l, n, blk;
+ int32 n_mgau;
+ int32 n_feat;
+ int32 n_density;
+ int32 *veclen;
+ int32 byteswap, chksum_present;
+ float32 ****out;
+ float32 *buf;
+ char **argname, **argval;
+ uint32 chksum;
+
+ E_INFO("Reading mixture gaussian parameter: %s\n", file_name);
+
+ if ((fp = fopen(file_name, "rb")) == NULL)
+ E_FATAL_SYSTEM("Failed to open file '%s' for reading", file_name);
+
+ /* Read header, including argument-value info and 32-bit byteorder magic */
+ if (bio_readhdr(fp, &argname, &argval, &byteswap) < 0)
+ E_FATAL("Failed to read header from file '%s'\n", file_name);
+
+ /* Parse argument-value list */
+ chksum_present = 0;
+ for (i = 0; argname[i]; i++) {
+ if (strcmp(argname[i], "version") == 0) {
+ if (strcmp(argval[i], GAUDEN_PARAM_VERSION) != 0)
+ E_WARN("Version mismatch(%s): %s, expecting %s\n",
+ file_name, argval[i], GAUDEN_PARAM_VERSION);
+ }
+ else if (strcmp(argname[i], "chksum0") == 0) {
+ chksum_present = 1; /* Ignore the associated value */
+ }
+ }
+ bio_hdrarg_free(argname, argval);
+ argname = argval = NULL;
+
+ chksum = 0;
+
+ /* #Codebooks */
+ if (bio_fread(&n_mgau, sizeof(int32), 1, fp, byteswap, &chksum) != 1)
+ E_FATAL("fread(%s) (#codebooks) failed\n", file_name);
+ *out_n_mgau = n_mgau;
+
+ /* #Features/codebook */
+ if (bio_fread(&n_feat, sizeof(int32), 1, fp, byteswap, &chksum) != 1)
+ E_FATAL("fread(%s) (#features) failed\n", file_name);
+ *out_n_feat = n_feat;
+
+ /* #Gaussian densities/feature in each codebook */
+ if (bio_fread(&n_density, sizeof(int32), 1, fp, byteswap, &chksum) != 1)
+ E_FATAL("fread(%s) (#density/codebook) failed\n", file_name);
+ *out_n_density = n_density;
+
+ /* #Dimensions in each feature stream */
+ veclen = ckd_calloc(n_feat, sizeof(uint32));
+ *out_veclen = veclen;
+ if (bio_fread(veclen, sizeof(int32), n_feat, fp, byteswap, &chksum) !=
+ n_feat)
+ E_FATAL("fread(%s) (feature-lengths) failed\n", file_name);
+
+ /* blk = total vector length of all feature streams */
+ for (i = 0, blk = 0; i < n_feat; i++)
+ blk += veclen[i];
+
+ /* #Floats to follow; for the ENTIRE SET of CODEBOOKS */
+ if (bio_fread(&n, sizeof(int32), 1, fp, byteswap, &chksum) != 1)
+ E_FATAL("fread(%s) (total #floats) failed\n", file_name);
+ if (n != n_mgau * n_density * blk) {
+ E_FATAL
+ ("%s: #mfcc_ts(%d) doesn't match dimensions: %d x %d x %d\n",
+ file_name, n, n_mgau, n_density, blk);
+ }
+
+ /* Allocate memory for mixture gaussian densities if not already allocated */
+ if (!(*out_param)) {
+ out = (float32 ****) ckd_calloc_3d(n_mgau, n_feat, n_density,
+ sizeof(float32 *));
+ buf = (float32 *) ckd_calloc(n, sizeof(float32));
+ for (i = 0, l = 0; i < n_mgau; i++) {
+ for (j = 0; j < n_feat; j++) {
+ for (k = 0; k < n_density; k++) {
+ out[i][j][k] = &buf[l];
+ l += veclen[j];
+ }
+ }
+ }
+ }
+ else {
+ out = (float32 ****) *out_param;
+ buf = out[0][0][0];
+ }
+
+ /* Read mixture gaussian densities data */
+ if (bio_fread(buf, sizeof(float32), n, fp, byteswap, &chksum) != n)
+ E_FATAL("fread(%s) (densitydata) failed\n", file_name);
+
+ if (chksum_present)
+ bio_verify_chksum(fp, byteswap, chksum);
+
+ if (fread(&tmp, 1, 1, fp) == 1)
+ E_FATAL("More data than expected in %s\n", file_name);
+
+ fclose(fp);
+
+ *out_param = out;
+
+ E_INFO("%d codebook, %d feature, size: \n", n_mgau, n_feat);
+ for (i = 0; i < n_feat; i++)
+ E_INFO(" %dx%d\n", n_density, veclen[i]);
+
+ return 0;
+}
+
+static void
+gauden_param_free(mfcc_t **** p)
+{
+ ckd_free(p[0][0][0]);
+ ckd_free_3d(p);
+}
+
+/*
+ * Some of the gaussian density computation can be carried out in advance:
+ * log(determinant) calculation,
+ * 1/(2*var) in the exponent,
+ * NOTE; The density computation is performed in log domain.
+ */
+static int32
+gauden_dist_precompute(gauden_t * g, logmath_t *lmath, float32 varfloor)
+{
+ int32 i, m, f, d, flen;
+ mfcc_t *meanp;
+ mfcc_t *varp;
+ mfcc_t *detp;
+ int32 floored;
+
+ floored = 0;
+ /* Allocate space for determinants */
+ g->det = ckd_calloc_3d(g->n_mgau, g->n_feat, g->n_density, sizeof(***g->det));
+
+ for (m = 0; m < g->n_mgau; m++) {
+ for (f = 0; f < g->n_feat; f++) {
+ flen = g->featlen[f];
+
+ /* Determinants for all variance vectors in g->[m][f] */
+ for (d = 0, detp = g->det[m][f]; d < g->n_density; d++, detp++) {
+ *detp = 0;
+ for (i = 0, varp = g->var[m][f][d], meanp = g->mean[m][f][d];
+ i < flen; i++, varp++, meanp++) {
+ float32 *fvarp = (float32 *)varp;
+
+#ifdef FIXED_POINT
+ float32 *fmp = (float32 *)meanp;
+ *meanp = FLOAT2MFCC(*fmp);
+#endif
+ if (*fvarp < varfloor) {
+ *fvarp = varfloor;
+ ++floored;
+ }
+ *detp += (mfcc_t)logmath_log(lmath,
+ 1.0 / sqrt(*fvarp * 2.0 * M_PI));
+ /* Precompute this part of the exponential */
+ *varp = (mfcc_t)logmath_ln_to_log(lmath,
+ (1.0 / (*fvarp * 2.0)));
+ }
+ }
+ }
+ }
+
+ E_INFO("%d variance values floored\n", floored);
+
+ return 0;
+}
+
+
+gauden_t *
+gauden_init(char const *meanfile, char const *varfile, float32 varfloor, logmath_t *lmath)
+{
+ int32 i, m, f, d, *flen;
+ float32 ****fgau;
+ gauden_t *g;
+
+ assert(meanfile != NULL);
+ assert(varfile != NULL);
+ assert(varfloor > 0.0);
+
+ g = (gauden_t *) ckd_calloc(1, sizeof(gauden_t));
+ g->lmath = lmath;
+
+ /* Read means and (diagonal) variances for all mixture gaussians */
+ fgau = NULL;
+ gauden_param_read(&fgau, &g->n_mgau, &g->n_feat, &g->n_density,
+ &g->featlen, meanfile);
+ g->mean = (mfcc_t ****)fgau;
+ fgau = NULL;
+ gauden_param_read(&fgau, &m, &f, &d, &flen, varfile);
+ g->var = (mfcc_t ****)fgau;
+
+ /* Verify mean and variance parameter dimensions */
+ if ((m != g->n_mgau) || (f != g->n_feat) || (d != g->n_density))
+ E_FATAL
+ ("Mixture-gaussians dimensions for means and variances differ\n");
+ for (i = 0; i < g->n_feat; i++)
+ if (g->featlen[i] != flen[i])
+ E_FATAL("Feature lengths for means and variances differ\n");
+ ckd_free(flen);
+
+ /* Floor variances and precompute variance determinants */
+ gauden_dist_precompute(g, lmath, varfloor);
+
+ return g;
+}
+
+void
+gauden_free(gauden_t * g)
+{
+ if (g == NULL)
+ return;
+ if (g->mean)
+ gauden_param_free(g->mean);
+ if (g->var)
+ gauden_param_free(g->var);
+ if (g->det)
+ ckd_free_3d(g->det);
+ if (g->featlen)
+ ckd_free(g->featlen);
+ ckd_free(g);
+}
+
+/* See compute_dist below */
+static int32
+compute_dist_all(gauden_dist_t * out_dist, mfcc_t* obs, int32 featlen,
+ mfcc_t ** mean, mfcc_t ** var, mfcc_t * det,
+ int32 n_density)
+{
+ int32 i, d;
+
+ for (d = 0; d < n_density; ++d) {
+ mfcc_t *m;
+ mfcc_t *v;
+ mfcc_t dval;
+
+ m = mean[d];
+ v = var[d];
+ dval = det[d];
+
+ for (i = 0; i < featlen; i++) {
+ mfcc_t diff;
+#ifdef FIXED_POINT
+ /* Have to check for underflows here. */
+ mfcc_t pdval = dval;
+ diff = obs[i] - m[i];
+ dval -= MFCCMUL(MFCCMUL(diff, diff), v[i]);
+ if (dval > pdval) {
+ dval = WORST_SCORE;
+ break;
+ }
+#else
+ diff = obs[i] - m[i];
+ /* The compiler really likes this to be a single
+ * expression, for whatever reason. */
+ dval -= diff * diff * v[i];
+#endif
+ }
+
+ out_dist[d].dist = dval;
+ out_dist[d].id = d;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Compute the top-N closest gaussians from the chosen set (mgau,feat)
+ * for the given input observation vector.
+ */
+static int32
+compute_dist(gauden_dist_t * out_dist, int32 n_top,
+ mfcc_t * obs, int32 featlen,
+ mfcc_t ** mean, mfcc_t ** var, mfcc_t * det,
+ int32 n_density)
+{
+ int32 i, j, d;
+ gauden_dist_t *worst;
+
+ /* Special case optimization when n_density <= n_top */
+ if (n_top >= n_density)
+ return (compute_dist_all
+ (out_dist, obs, featlen, mean, var, det, n_density));
+
+ for (i = 0; i < n_top; i++)
+ out_dist[i].dist = WORST_DIST;
+ worst = &(out_dist[n_top - 1]);
+
+ for (d = 0; d < n_density; d++) {
+ mfcc_t *m;
+ mfcc_t *v;
+ mfcc_t dval;
+
+ m = mean[d];
+ v = var[d];
+ dval = det[d];
+
+ for (i = 0; (i < featlen) && (dval >= worst->dist); i++) {
+ mfcc_t diff;
+#ifdef FIXED_POINT
+ /* Have to check for underflows here. */
+ mfcc_t pdval = dval;
+ diff = obs[i] - m[i];
+ dval -= MFCCMUL(MFCCMUL(diff, diff), v[i]);
+ if (dval > pdval) {
+ dval = WORST_SCORE;
+ break;
+ }
+#else
+ diff = obs[i] - m[i];
+ /* The compiler really likes this to be a single
+ * expression, for whatever reason. */
+ dval -= diff * diff * v[i];
+#endif
+ }
+
+ if ((i < featlen) || (dval < worst->dist)) /* Codeword d worse than worst */
+ continue;
+
+ /* Codeword d at least as good as worst so far; insert in the ordered list */
+ for (i = 0; (i < n_top) && (dval < out_dist[i].dist); i++);
+ assert(i < n_top);
+ for (j = n_top - 1; j > i; --j)
+ out_dist[j] = out_dist[j - 1];
+ out_dist[i].dist = dval;
+ out_dist[i].id = d;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Compute distances of the input observation from the top N codewords in the given
+ * codebook (g->{mean,var}[mgau]). The input observation, obs, includes vectors for
+ * all features in the codebook.
+ */
+int32
+gauden_dist(gauden_t * g,
+ int mgau, int32 n_top, mfcc_t** obs, gauden_dist_t ** out_dist)
+{
+ int32 f;
+
+ assert((n_top > 0) && (n_top <= g->n_density));
+
+ for (f = 0; f < g->n_feat; f++) {
+ compute_dist(out_dist[f], n_top,
+ obs[f], g->featlen[f],
+ g->mean[mgau][f], g->var[mgau][f], g->det[mgau][f],
+ g->n_density);
+ E_DEBUG(3, ("Top CW(%d,%d) = %d %d\n", mgau, f, out_dist[f][0].id,
+ (int)out_dist[f][0].dist >> SENSCR_SHIFT));
+ }
+
+ return 0;
+}
+
+int32
+gauden_mllr_transform(gauden_t *g, ps_mllr_t *mllr, cmd_ln_t *config)
+{
+ int32 i, m, f, d, *flen;
+ float32 ****fgau;
+
+ /* Free data if already here */
+ if (g->mean)
+ gauden_param_free(g->mean);
+ if (g->var)
+ gauden_param_free(g->var);
+ if (g->det)
+ ckd_free_3d(g->det);
+ if (g->featlen)
+ ckd_free(g->featlen);
+ g->mean = NULL;
+ g->var = NULL;
+ g->det = NULL;
+ g->featlen = NULL;
+
+ /* Reload means and variances (un-precomputed). */
+ fgau = NULL;
+ gauden_param_read(&fgau, &g->n_mgau, &g->n_feat, &g->n_density,
+ &g->featlen, cmd_ln_str_r(config, "-mean"));
+ g->mean = (mfcc_t ****)fgau;
+ fgau = NULL;
+ gauden_param_read(&fgau, &m, &f, &d, &flen, cmd_ln_str_r(config, "-var"));
+ g->var = (mfcc_t ****)fgau;
+
+ /* Verify mean and variance parameter dimensions */
+ if ((m != g->n_mgau) || (f != g->n_feat) || (d != g->n_density))
+ E_FATAL
+ ("Mixture-gaussians dimensions for means and variances differ\n");
+ for (i = 0; i < g->n_feat; i++)
+ if (g->featlen[i] != flen[i])
+ E_FATAL("Feature lengths for means and variances differ\n");
+ ckd_free(flen);
+
+ /* Transform codebook for each stream s */
+ for (i = 0; i < g->n_mgau; ++i) {
+ for (f = 0; f < g->n_feat; ++f) {
+ float64 *temp;
+ temp = (float64 *) ckd_calloc(g->featlen[f], sizeof(float64));
+ /* Transform each density d in selected codebook */
+ for (d = 0; d < g->n_density; d++) {
+ int l;
+ for (l = 0; l < g->featlen[f]; l++) {
+ temp[l] = 0.0;
+ for (m = 0; m < g->featlen[f]; m++) {
+ /* FIXME: For now, only one class, hence the zeros below. */
+ temp[l] += mllr->A[f][0][l][m] * g->mean[i][f][d][m];
+ }
+ temp[l] += mllr->b[f][0][l];
+ }
+
+ for (l = 0; l < g->featlen[f]; l++) {
+ g->mean[i][f][d][l] = (float32) temp[l];
+ g->var[i][f][d][l] *= mllr->h[f][0][l];
+ }
+ }
+ ckd_free(temp);
+ }
+ }
+
+ /* Re-precompute (if we aren't adapting variances this isn't
+ * actually necessary...) */
+ gauden_dist_precompute(g, g->lmath, cmd_ln_float32_r(config, "-varfloor"));
+ return 0;
+}