PocketSphinx
0.6
|
00001 /* -*- c-basic-offset: 4; indent-tabs-mode: nil -*- */ 00002 /* ==================================================================== 00003 * Copyright (c) 1999-2004 Carnegie Mellon University. All rights 00004 * reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions 00008 * are met: 00009 * 00010 * 1. Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * 00013 * 2. Redistributions in binary form must reproduce the above copyright 00014 * notice, this list of conditions and the following disclaimer in 00015 * the documentation and/or other materials provided with the 00016 * distribution. 00017 * 00018 * This work was supported in part by funding from the Defense Advanced 00019 * Research Projects Agency and the National Science Foundation of the 00020 * United States of America, and the CMU Sphinx Speech Consortium. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY ``AS IS'' AND 00023 * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 00024 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00025 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY 00026 * NOR ITS EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00027 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00028 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00029 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00030 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00031 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00032 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00033 * 00034 * ==================================================================== 00035 * 00036 */ 00037 /* 00038 * gauden.c -- gaussian density module. 00039 * 00040 *********************************************** 00041 * CMU ARPA Speech Project 00042 * 00043 * Copyright (c) 1996 Carnegie Mellon University. 00044 * ALL RIGHTS RESERVED. 00045 *********************************************** 00046 * 00047 * HISTORY 00048 * $Log$ 00049 * Revision 1.7 2006/02/22 17:09:55 arthchan2003 00050 * 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. 00051 * 00052 * 00053 * Revision 1.5.4.7 2006/01/16 19:45:59 arthchan2003 00054 * Change the gaussian density dumping routine to a function. 00055 * 00056 * Revision 1.5.4.6 2005/10/09 19:51:05 arthchan2003 00057 * Followed Dave's changed in the trunk. 00058 * 00059 * Revision 1.5.4.5 2005/09/25 18:54:20 arthchan2003 00060 * Added a flag to turn on and off precomputation. 00061 * 00062 * Revision 1.6 2005/10/05 00:31:14 dhdfu 00063 * Make int8 be explicitly signed (signedness of 'char' is 00064 * architecture-dependent). Then make a bunch of things use uint8 where 00065 * signedness is unimportant, because on the architecture where 'char' is 00066 * unsigned, it is that way for a reason (signed chars are slower). 00067 * 00068 * Revision 1.5.4.4 2005/09/07 23:29:07 arthchan2003 00069 * Added FIXME warning. 00070 * 00071 * Revision 1.5.4.3 2005/09/07 23:25:10 arthchan2003 00072 * 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. 00073 * 00074 * Revision 1.5.4.2 2005/08/03 18:53:44 dhdfu 00075 * Add memory deallocation functions. Also move all the initialization 00076 * of ms_mgau_model_t into ms_mgau_init (duh!), which entails removing it 00077 * from decode_anytopo and friends. 00078 * 00079 * Revision 1.5.4.1 2005/07/20 19:39:01 arthchan2003 00080 * Added licences in ms_* series of code. 00081 * 00082 * Revision 1.5 2005/06/21 18:55:09 arthchan2003 00083 * 1, Add comments to describe this modules, 2, Fixed doxygen documentation. 3, Added $ keyword. 00084 * 00085 * Revision 1.3 2005/03/30 01:22:47 archan 00086 * Fixed mistakes in last updates. Add 00087 * 00088 * 00089 * 20-Dec-96 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University. 00090 * Changed gauden_param_read to use the new libio/bio_fread functions. 00091 * 00092 * 26-Sep-96 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University. 00093 * Added gauden_mean_reload() for application of MLLR; and correspondingly 00094 * made gauden_param_read allocate memory for parameter only if not 00095 * already allocated. 00096 * 00097 * 09-Sep-96 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University. 00098 * Interleaved two density computations for speed improvement. 00099 * 00100 * 19-Aug-96 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University. 00101 * Added compute_dist_all special case for improving speed. 00102 * 00103 * 26-Jan-96 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University. 00104 * Added check for underflow and floor insertion in gauden_dist. 00105 * 00106 * 20-Jan-96 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University. 00107 * Added active argument to gauden_dist_norm and gauden_dist_norm_global, 00108 * and made the latter a static function. 00109 * 00110 * 07-Nov-95 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University. 00111 * Initial version created. 00112 * Very liberally borrowed/adapted from Eric's S3 trainer implementation. 00113 */ 00114 00115 /* System headers. */ 00116 #include <assert.h> 00117 #include <string.h> 00118 #include <math.h> 00119 #include <float.h> 00120 00121 /* SphinxBase headers. */ 00122 #include <sphinxbase/bio.h> 00123 #include <sphinxbase/err.h> 00124 #include <sphinxbase/ckd_alloc.h> 00125 00126 /* Local headesr. */ 00127 #include "ms_gauden.h" 00128 00129 #define GAUDEN_PARAM_VERSION "1.0" 00130 00131 #ifndef M_PI 00132 #define M_PI 3.1415926535897932385e0 00133 #endif 00134 00135 #define WORST_DIST (int32)(0x80000000) 00136 00137 void 00138 gauden_dump(const gauden_t * g) 00139 { 00140 int32 c; 00141 00142 for (c = 0; c < g->n_mgau; c++) 00143 gauden_dump_ind(g, c); 00144 } 00145 00146 00147 void 00148 gauden_dump_ind(const gauden_t * g, int senidx) 00149 { 00150 int32 f, d, i; 00151 00152 for (f = 0; f < g->n_feat; f++) { 00153 E_INFO("Codebook %d, Feature %d (%dx%d):\n", 00154 senidx, f, g->n_density, g->featlen[f]); 00155 00156 for (d = 0; d < g->n_density; d++) { 00157 printf("m[%3d]", d); 00158 for (i = 0; i < g->featlen[f]; i++) 00159 printf(" %7.4f", MFCC2FLOAT(g->mean[senidx][f][d][i])); 00160 printf("\n"); 00161 } 00162 printf("\n"); 00163 00164 for (d = 0; d < g->n_density; d++) { 00165 printf("v[%3d]", d); 00166 for (i = 0; i < g->featlen[f]; i++) 00167 printf(" %d", (int)g->var[senidx][f][d][i]); 00168 printf("\n"); 00169 } 00170 printf("\n"); 00171 00172 for (d = 0; d < g->n_density; d++) 00173 printf("d[%3d] %d\n", d, (int)g->det[senidx][f][d]); 00174 } 00175 fflush(stderr); 00176 } 00177 00178 static int32 00179 gauden_param_read(float32 ***** out_param, /* Alloc space iff *out_param == NULL */ 00180 int32 * out_n_mgau, 00181 int32 * out_n_feat, 00182 int32 * out_n_density, 00183 int32 ** out_veclen, const char *file_name) 00184 { 00185 char tmp; 00186 FILE *fp; 00187 int32 i, j, k, l, n, blk; 00188 int32 n_mgau; 00189 int32 n_feat; 00190 int32 n_density; 00191 int32 *veclen; 00192 int32 byteswap, chksum_present; 00193 float32 ****out; 00194 float32 *buf; 00195 char **argname, **argval; 00196 uint32 chksum; 00197 00198 E_INFO("Reading mixture gaussian parameter: %s\n", file_name); 00199 00200 if ((fp = fopen(file_name, "rb")) == NULL) 00201 E_FATAL_SYSTEM("Failed to open file '%s' for reading", file_name); 00202 00203 /* Read header, including argument-value info and 32-bit byteorder magic */ 00204 if (bio_readhdr(fp, &argname, &argval, &byteswap) < 0) 00205 E_FATAL("Failed to read header from file '%s'\n", file_name); 00206 00207 /* Parse argument-value list */ 00208 chksum_present = 0; 00209 for (i = 0; argname[i]; i++) { 00210 if (strcmp(argname[i], "version") == 0) { 00211 if (strcmp(argval[i], GAUDEN_PARAM_VERSION) != 0) 00212 E_WARN("Version mismatch(%s): %s, expecting %s\n", 00213 file_name, argval[i], GAUDEN_PARAM_VERSION); 00214 } 00215 else if (strcmp(argname[i], "chksum0") == 0) { 00216 chksum_present = 1; /* Ignore the associated value */ 00217 } 00218 } 00219 bio_hdrarg_free(argname, argval); 00220 argname = argval = NULL; 00221 00222 chksum = 0; 00223 00224 /* #Codebooks */ 00225 if (bio_fread(&n_mgau, sizeof(int32), 1, fp, byteswap, &chksum) != 1) 00226 E_FATAL("fread(%s) (#codebooks) failed\n", file_name); 00227 *out_n_mgau = n_mgau; 00228 00229 /* #Features/codebook */ 00230 if (bio_fread(&n_feat, sizeof(int32), 1, fp, byteswap, &chksum) != 1) 00231 E_FATAL("fread(%s) (#features) failed\n", file_name); 00232 *out_n_feat = n_feat; 00233 00234 /* #Gaussian densities/feature in each codebook */ 00235 if (bio_fread(&n_density, sizeof(int32), 1, fp, byteswap, &chksum) != 1) 00236 E_FATAL("fread(%s) (#density/codebook) failed\n", file_name); 00237 *out_n_density = n_density; 00238 00239 /* #Dimensions in each feature stream */ 00240 veclen = ckd_calloc(n_feat, sizeof(uint32)); 00241 *out_veclen = veclen; 00242 if (bio_fread(veclen, sizeof(int32), n_feat, fp, byteswap, &chksum) != 00243 n_feat) 00244 E_FATAL("fread(%s) (feature-lengths) failed\n", file_name); 00245 00246 /* blk = total vector length of all feature streams */ 00247 for (i = 0, blk = 0; i < n_feat; i++) 00248 blk += veclen[i]; 00249 00250 /* #Floats to follow; for the ENTIRE SET of CODEBOOKS */ 00251 if (bio_fread(&n, sizeof(int32), 1, fp, byteswap, &chksum) != 1) 00252 E_FATAL("fread(%s) (total #floats) failed\n", file_name); 00253 if (n != n_mgau * n_density * blk) { 00254 E_FATAL 00255 ("%s: #mfcc_ts(%d) doesn't match dimensions: %d x %d x %d\n", 00256 file_name, n, n_mgau, n_density, blk); 00257 } 00258 00259 /* Allocate memory for mixture gaussian densities if not already allocated */ 00260 if (!(*out_param)) { 00261 out = (float32 ****) ckd_calloc_3d(n_mgau, n_feat, n_density, 00262 sizeof(float32 *)); 00263 buf = (float32 *) ckd_calloc(n, sizeof(float32)); 00264 for (i = 0, l = 0; i < n_mgau; i++) { 00265 for (j = 0; j < n_feat; j++) { 00266 for (k = 0; k < n_density; k++) { 00267 out[i][j][k] = &buf[l]; 00268 l += veclen[j]; 00269 } 00270 } 00271 } 00272 } 00273 else { 00274 out = (float32 ****) *out_param; 00275 buf = out[0][0][0]; 00276 } 00277 00278 /* Read mixture gaussian densities data */ 00279 if (bio_fread(buf, sizeof(float32), n, fp, byteswap, &chksum) != n) 00280 E_FATAL("fread(%s) (densitydata) failed\n", file_name); 00281 00282 if (chksum_present) 00283 bio_verify_chksum(fp, byteswap, chksum); 00284 00285 if (fread(&tmp, 1, 1, fp) == 1) 00286 E_FATAL("More data than expected in %s\n", file_name); 00287 00288 fclose(fp); 00289 00290 *out_param = out; 00291 00292 E_INFO("%d codebook, %d feature, size: \n", n_mgau, n_feat); 00293 for (i = 0; i < n_feat; i++) 00294 E_INFO(" %dx%d\n", n_density, veclen[i]); 00295 00296 return 0; 00297 } 00298 00299 static void 00300 gauden_param_free(mfcc_t **** p) 00301 { 00302 ckd_free(p[0][0][0]); 00303 ckd_free_3d(p); 00304 } 00305 00306 /* 00307 * Some of the gaussian density computation can be carried out in advance: 00308 * log(determinant) calculation, 00309 * 1/(2*var) in the exponent, 00310 * NOTE; The density computation is performed in log domain. 00311 */ 00312 static int32 00313 gauden_dist_precompute(gauden_t * g, logmath_t *lmath, float32 varfloor) 00314 { 00315 int32 i, m, f, d, flen; 00316 mfcc_t *meanp; 00317 mfcc_t *varp; 00318 mfcc_t *detp; 00319 int32 floored; 00320 00321 floored = 0; 00322 /* Allocate space for determinants */ 00323 g->det = ckd_calloc_3d(g->n_mgau, g->n_feat, g->n_density, sizeof(***g->det)); 00324 00325 for (m = 0; m < g->n_mgau; m++) { 00326 for (f = 0; f < g->n_feat; f++) { 00327 flen = g->featlen[f]; 00328 00329 /* Determinants for all variance vectors in g->[m][f] */ 00330 for (d = 0, detp = g->det[m][f]; d < g->n_density; d++, detp++) { 00331 *detp = 0; 00332 for (i = 0, varp = g->var[m][f][d], meanp = g->mean[m][f][d]; 00333 i < flen; i++, varp++, meanp++) { 00334 float32 *fvarp = (float32 *)varp; 00335 00336 #ifdef FIXED_POINT 00337 float32 *fmp = (float32 *)meanp; 00338 *meanp = FLOAT2MFCC(*fmp); 00339 #endif 00340 if (*fvarp < varfloor) { 00341 *fvarp = varfloor; 00342 ++floored; 00343 } 00344 *detp += (mfcc_t)logmath_log(lmath, 00345 1.0 / sqrt(*fvarp * 2.0 * M_PI)); 00346 /* Precompute this part of the exponential */ 00347 *varp = (mfcc_t)logmath_ln_to_log(lmath, 00348 (1.0 / (*fvarp * 2.0))); 00349 } 00350 } 00351 } 00352 } 00353 00354 E_INFO("%d variance values floored\n", floored); 00355 00356 return 0; 00357 } 00358 00359 00360 gauden_t * 00361 gauden_init(char const *meanfile, char const *varfile, float32 varfloor, logmath_t *lmath) 00362 { 00363 int32 i, m, f, d, *flen; 00364 float32 ****fgau; 00365 gauden_t *g; 00366 00367 assert(meanfile != NULL); 00368 assert(varfile != NULL); 00369 assert(varfloor > 0.0); 00370 00371 g = (gauden_t *) ckd_calloc(1, sizeof(gauden_t)); 00372 g->lmath = lmath; 00373 00374 /* Read means and (diagonal) variances for all mixture gaussians */ 00375 fgau = NULL; 00376 gauden_param_read(&fgau, &g->n_mgau, &g->n_feat, &g->n_density, 00377 &g->featlen, meanfile); 00378 g->mean = (mfcc_t ****)fgau; 00379 fgau = NULL; 00380 gauden_param_read(&fgau, &m, &f, &d, &flen, varfile); 00381 g->var = (mfcc_t ****)fgau; 00382 00383 /* Verify mean and variance parameter dimensions */ 00384 if ((m != g->n_mgau) || (f != g->n_feat) || (d != g->n_density)) 00385 E_FATAL 00386 ("Mixture-gaussians dimensions for means and variances differ\n"); 00387 for (i = 0; i < g->n_feat; i++) 00388 if (g->featlen[i] != flen[i]) 00389 E_FATAL("Feature lengths for means and variances differ\n"); 00390 ckd_free(flen); 00391 00392 /* Floor variances and precompute variance determinants */ 00393 gauden_dist_precompute(g, lmath, varfloor); 00394 00395 return g; 00396 } 00397 00398 void 00399 gauden_free(gauden_t * g) 00400 { 00401 if (g == NULL) 00402 return; 00403 if (g->mean) 00404 gauden_param_free(g->mean); 00405 if (g->var) 00406 gauden_param_free((mfcc_t ****)g->var); 00407 if (g->det) 00408 ckd_free_3d(g->det); 00409 if (g->featlen) 00410 ckd_free(g->featlen); 00411 ckd_free(g); 00412 } 00413 00414 /* See compute_dist below */ 00415 static int32 00416 compute_dist_all(gauden_dist_t * out_dist, mfcc_t* obs, int32 featlen, 00417 mfcc_t ** mean, mfcc_t ** var, mfcc_t * det, 00418 int32 n_density) 00419 { 00420 int32 i, d; 00421 00422 for (d = 0; d < n_density; ++d) { 00423 mfcc_t *m; 00424 mfcc_t *v; 00425 mfcc_t dval; 00426 00427 m = mean[d]; 00428 v = var[d]; 00429 dval = det[d]; 00430 00431 for (i = 0; i < featlen; i++) { 00432 mfcc_t diff; 00433 #ifdef FIXED_POINT 00434 /* Have to check for underflows here. */ 00435 mfcc_t pdval = dval; 00436 diff = obs[i] - m[i]; 00437 dval -= MFCCMUL(MFCCMUL(diff, diff), v[i]); 00438 if (dval > pdval) { 00439 dval = WORST_SCORE; 00440 break; 00441 } 00442 #else 00443 diff = obs[i] - m[i]; 00444 /* The compiler really likes this to be a single 00445 * expression, for whatever reason. */ 00446 dval -= diff * diff * v[i]; 00447 #endif 00448 } 00449 00450 out_dist[d].dist = dval; 00451 out_dist[d].id = d; 00452 } 00453 00454 return 0; 00455 } 00456 00457 00458 /* 00459 * Compute the top-N closest gaussians from the chosen set (mgau,feat) 00460 * for the given input observation vector. 00461 */ 00462 static int32 00463 compute_dist(gauden_dist_t * out_dist, int32 n_top, 00464 mfcc_t * obs, int32 featlen, 00465 mfcc_t ** mean, mfcc_t ** var, mfcc_t * det, 00466 int32 n_density) 00467 { 00468 int32 i, j, d; 00469 gauden_dist_t *worst; 00470 00471 /* Special case optimization when n_density <= n_top */ 00472 if (n_top >= n_density) 00473 return (compute_dist_all 00474 (out_dist, obs, featlen, mean, var, det, n_density)); 00475 00476 for (i = 0; i < n_top; i++) 00477 out_dist[i].dist = WORST_DIST; 00478 worst = &(out_dist[n_top - 1]); 00479 00480 for (d = 0; d < n_density; d++) { 00481 mfcc_t *m; 00482 mfcc_t *v; 00483 mfcc_t dval; 00484 00485 m = mean[d]; 00486 v = var[d]; 00487 dval = det[d]; 00488 00489 for (i = 0; (i < featlen) && (dval >= worst->dist); i++) { 00490 mfcc_t diff; 00491 #ifdef FIXED_POINT 00492 /* Have to check for underflows here. */ 00493 mfcc_t pdval = dval; 00494 diff = obs[i] - m[i]; 00495 dval -= MFCCMUL(MFCCMUL(diff, diff), v[i]); 00496 if (dval > pdval) { 00497 dval = WORST_SCORE; 00498 break; 00499 } 00500 #else 00501 diff = obs[i] - m[i]; 00502 /* The compiler really likes this to be a single 00503 * expression, for whatever reason. */ 00504 dval -= diff * diff * v[i]; 00505 #endif 00506 } 00507 00508 if ((i < featlen) || (dval < worst->dist)) /* Codeword d worse than worst */ 00509 continue; 00510 00511 /* Codeword d at least as good as worst so far; insert in the ordered list */ 00512 for (i = 0; (i < n_top) && (dval < out_dist[i].dist); i++); 00513 assert(i < n_top); 00514 for (j = n_top - 1; j > i; --j) 00515 out_dist[j] = out_dist[j - 1]; 00516 out_dist[i].dist = dval; 00517 out_dist[i].id = d; 00518 } 00519 00520 return 0; 00521 } 00522 00523 00524 /* 00525 * Compute distances of the input observation from the top N codewords in the given 00526 * codebook (g->{mean,var}[mgau]). The input observation, obs, includes vectors for 00527 * all features in the codebook. 00528 */ 00529 int32 00530 gauden_dist(gauden_t * g, 00531 int mgau, int32 n_top, mfcc_t** obs, gauden_dist_t ** out_dist) 00532 { 00533 int32 f; 00534 00535 assert((n_top > 0) && (n_top <= g->n_density)); 00536 00537 for (f = 0; f < g->n_feat; f++) { 00538 compute_dist(out_dist[f], n_top, 00539 obs[f], g->featlen[f], 00540 g->mean[mgau][f], g->var[mgau][f], g->det[mgau][f], 00541 g->n_density); 00542 E_DEBUG(3, ("Top CW(%d,%d) = %d %d\n", mgau, f, out_dist[f][0].id, 00543 (int)out_dist[f][0].dist >> SENSCR_SHIFT)); 00544 } 00545 00546 return 0; 00547 } 00548 00549 int32 00550 gauden_mllr_transform(gauden_t *g, ps_mllr_t *mllr, cmd_ln_t *config) 00551 { 00552 int32 i, m, f, d, *flen; 00553 float32 ****fgau; 00554 00555 /* Reload means and variances (un-precomputed). */ 00556 fgau = NULL; 00557 gauden_param_read(&fgau, &g->n_mgau, &g->n_feat, &g->n_density, 00558 &g->featlen, cmd_ln_str_r(config, "-mean")); 00559 g->mean = (mfcc_t ****)fgau; 00560 fgau = NULL; 00561 gauden_param_read(&fgau, &m, &f, &d, &flen, cmd_ln_str_r(config, "-var")); 00562 g->var = (mfcc_t ****)fgau; 00563 00564 /* Verify mean and variance parameter dimensions */ 00565 if ((m != g->n_mgau) || (f != g->n_feat) || (d != g->n_density)) 00566 E_FATAL 00567 ("Mixture-gaussians dimensions for means and variances differ\n"); 00568 for (i = 0; i < g->n_feat; i++) 00569 if (g->featlen[i] != flen[i]) 00570 E_FATAL("Feature lengths for means and variances differ\n"); 00571 ckd_free(flen); 00572 00573 /* Transform codebook for each stream s */ 00574 for (i = 0; i < g->n_mgau; ++i) { 00575 for (f = 0; f < g->n_feat; ++f) { 00576 float64 *temp; 00577 temp = (float64 *) ckd_calloc(g->featlen[f], sizeof(float64)); 00578 /* Transform each density d in selected codebook */ 00579 for (d = 0; d < g->n_density; d++) { 00580 int l; 00581 for (l = 0; l < g->featlen[f]; l++) { 00582 temp[l] = 0.0; 00583 for (m = 0; m < g->featlen[f]; m++) { 00584 /* FIXME: For now, only one class, hence the zeros below. */ 00585 temp[l] += mllr->A[f][0][l][m] * g->mean[i][f][d][m]; 00586 } 00587 temp[l] += mllr->b[f][0][l]; 00588 } 00589 00590 for (l = 0; l < g->featlen[f]; l++) { 00591 g->mean[i][f][d][l] = (float32) temp[l]; 00592 g->var[i][f][d][l] *= mllr->h[f][0][l]; 00593 } 00594 } 00595 ckd_free(temp); 00596 } 00597 } 00598 00599 /* Re-precompute (if we aren't adapting variances this isn't 00600 * actually necessary...) */ 00601 gauden_dist_precompute(g, g->lmath, cmd_ln_float32_r(config, "-varfloor")); 00602 return 0; 00603 }