00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116 #include <assert.h>
00117 #include <string.h>
00118 #include <math.h>
00119 #include <float.h>
00120
00121
00122 #include <bio.h>
00123 #include <err.h>
00124 #include <ckd_alloc.h>
00125
00126
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,
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("fopen(%s,rb) failed\n", file_name);
00202
00203
00204 if (bio_readhdr(fp, &argname, &argval, &byteswap) < 0)
00205 E_FATAL("bio_readhdr(%s) failed\n", file_name);
00206
00207
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;
00217 }
00218 }
00219 bio_hdrarg_free(argname, argval);
00220 argname = argval = NULL;
00221
00222 chksum = 0;
00223
00224
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
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
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
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
00247 for (i = 0, blk = 0; i < n_feat; i++)
00248 blk += veclen[i];
00249
00250
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
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
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 printf(" %dx%d", n_density, veclen[i]);
00295 printf("\n");
00296 fflush(stdout);
00297
00298 return 0;
00299 }
00300
00301 static void
00302 gauden_param_free(mfcc_t **** p)
00303 {
00304 ckd_free(p[0][0][0]);
00305 ckd_free_3d(p);
00306 }
00307
00308
00309
00310
00311
00312
00313
00314 static int32
00315 gauden_dist_precompute(gauden_t * g, logmath_t *lmath, float32 varfloor)
00316 {
00317 int32 i, m, f, d, flen;
00318 mfcc_t *meanp;
00319 mfcc_t *varp;
00320 mfcc_t *detp;
00321 int32 floored;
00322
00323 floored = 0;
00324
00325 g->det = ckd_calloc_3d(g->n_mgau, g->n_feat, g->n_density, sizeof(***g->det));
00326
00327 for (m = 0; m < g->n_mgau; m++) {
00328 for (f = 0; f < g->n_feat; f++) {
00329 flen = g->featlen[f];
00330
00331
00332 for (d = 0, detp = g->det[m][f]; d < g->n_density; d++, detp++) {
00333 *detp = 0;
00334 for (i = 0, varp = g->var[m][f][d], meanp = g->mean[m][f][d];
00335 i < flen; i++, varp++, meanp++) {
00336 float32 *fvarp = (float32 *)varp;
00337
00338 #ifdef FIXED_POINT
00339 float32 *fmp = (float32 *)meanp;
00340 *meanp = FLOAT2MFCC(*fmp);
00341 #endif
00342 if (*fvarp < varfloor) {
00343 *fvarp = varfloor;
00344 ++floored;
00345 }
00346 *detp += (mfcc_t)logmath_log(lmath,
00347 1.0 / sqrt(*fvarp * 2.0 * M_PI));
00348
00349 *varp = (mfcc_t)logmath_ln_to_log(lmath,
00350 (1.0 / (*fvarp * 2.0)));
00351 }
00352 }
00353 }
00354 }
00355
00356 E_INFO("%d variance values floored\n", floored);
00357
00358 return 0;
00359 }
00360
00361
00362 gauden_t *
00363 gauden_init(char const *meanfile, char const *varfile, float32 varfloor, logmath_t *lmath)
00364 {
00365 int32 i, m, f, d, *flen;
00366 float32 ****fgau;
00367 gauden_t *g;
00368
00369 assert(meanfile != NULL);
00370 assert(varfile != NULL);
00371 assert(varfloor > 0.0);
00372
00373 g = (gauden_t *) ckd_calloc(1, sizeof(gauden_t));
00374 g->lmath = lmath;
00375
00376
00377 fgau = NULL;
00378 gauden_param_read(&fgau, &g->n_mgau, &g->n_feat, &g->n_density,
00379 &g->featlen, meanfile);
00380 g->mean = (mfcc_t ****)fgau;
00381 fgau = NULL;
00382 gauden_param_read(&fgau, &m, &f, &d, &flen, varfile);
00383 g->var = (mfcc_t ****)fgau;
00384
00385
00386 if ((m != g->n_mgau) || (f != g->n_feat) || (d != g->n_density))
00387 E_FATAL
00388 ("Mixture-gaussians dimensions for means and variances differ\n");
00389 for (i = 0; i < g->n_feat; i++)
00390 if (g->featlen[i] != flen[i])
00391 E_FATAL("Feature lengths for means and variances differ\n");
00392 ckd_free(flen);
00393
00394
00395 gauden_dist_precompute(g, lmath, varfloor);
00396
00397 return g;
00398 }
00399
00400 void
00401 gauden_free(gauden_t * g)
00402 {
00403 if (g == NULL)
00404 return;
00405 if (g->mean)
00406 gauden_param_free(g->mean);
00407 if (g->var)
00408 gauden_param_free((mfcc_t ****)g->var);
00409 if (g->det)
00410 ckd_free_3d(g->det);
00411 if (g->featlen)
00412 ckd_free(g->featlen);
00413 ckd_free(g);
00414 }
00415
00416
00417 static int32
00418 compute_dist_all(gauden_dist_t * out_dist, mfcc_t* obs, int32 featlen,
00419 mfcc_t ** mean, mfcc_t ** var, mfcc_t * det,
00420 int32 n_density)
00421 {
00422 int32 i, d;
00423
00424 for (d = 0; d < n_density; ++d) {
00425 mfcc_t *m;
00426 mfcc_t *v;
00427 mfcc_t dval;
00428
00429 m = mean[d];
00430 v = var[d];
00431 dval = det[d];
00432
00433 for (i = 0; i < featlen; i++) {
00434 mfcc_t diff;
00435 #ifdef FIXED_POINT
00436
00437 mfcc_t pdval = dval;
00438 diff = obs[i] - m[i];
00439 dval -= MFCCMUL(MFCCMUL(diff, diff), v[i]);
00440 if (dval > pdval) {
00441 dval = WORST_SCORE;
00442 break;
00443 }
00444 #else
00445 diff = obs[i] - m[i];
00446
00447
00448 dval -= diff * diff * v[i];
00449 #endif
00450 }
00451
00452 out_dist[d].dist = dval;
00453 out_dist[d].id = d;
00454 }
00455
00456 return 0;
00457 }
00458
00459
00460
00461
00462
00463
00464 static int32
00465 compute_dist(gauden_dist_t * out_dist, int32 n_top,
00466 mfcc_t * obs, int32 featlen,
00467 mfcc_t ** mean, mfcc_t ** var, mfcc_t * det,
00468 int32 n_density)
00469 {
00470 int32 i, j, d;
00471 gauden_dist_t *worst;
00472
00473
00474 if (n_top >= n_density)
00475 return (compute_dist_all
00476 (out_dist, obs, featlen, mean, var, det, n_density));
00477
00478 for (i = 0; i < n_top; i++)
00479 out_dist[i].dist = WORST_DIST;
00480 worst = &(out_dist[n_top - 1]);
00481
00482 for (d = 0; d < n_density; d++) {
00483 mfcc_t *m;
00484 mfcc_t *v;
00485 mfcc_t dval;
00486
00487 m = mean[d];
00488 v = var[d];
00489 dval = det[d];
00490
00491 for (i = 0; (i < featlen) && (dval >= worst->dist); i++) {
00492 mfcc_t diff;
00493 #ifdef FIXED_POINT
00494
00495 mfcc_t pdval = dval;
00496 diff = obs[i] - m[i];
00497 dval -= MFCCMUL(MFCCMUL(diff, diff), v[i]);
00498 if (dval > pdval) {
00499 dval = WORST_SCORE;
00500 break;
00501 }
00502 #else
00503 diff = obs[i] - m[i];
00504
00505
00506 dval -= diff * diff * v[i];
00507 #endif
00508 }
00509
00510 if ((i < featlen) || (dval < worst->dist))
00511 continue;
00512
00513
00514 for (i = 0; (i < n_top) && (dval < out_dist[i].dist); i++);
00515 assert(i < n_top);
00516 for (j = n_top - 1; j > i; --j)
00517 out_dist[j] = out_dist[j - 1];
00518 out_dist[i].dist = dval;
00519 out_dist[i].id = d;
00520 }
00521
00522 return 0;
00523 }
00524
00525
00526
00527
00528
00529
00530
00531 int32
00532 gauden_dist(gauden_t * g,
00533 int mgau, int32 n_top, mfcc_t** obs, gauden_dist_t ** out_dist)
00534 {
00535 int32 f;
00536
00537 assert((n_top > 0) && (n_top <= g->n_density));
00538
00539 for (f = 0; f < g->n_feat; f++) {
00540 compute_dist(out_dist[f], n_top,
00541 obs[f], g->featlen[f],
00542 g->mean[mgau][f], g->var[mgau][f], g->det[mgau][f],
00543 g->n_density);
00544 E_DEBUG(3, ("Top CW(%d,%d) = %d %d\n", mgau, f, out_dist[f][0].id,
00545 (int)out_dist[f][0].dist >> SENSCR_SHIFT));
00546 }
00547
00548 return 0;
00549 }
00550
00551 int32
00552 gauden_mllr_transform(gauden_t *g, ps_mllr_t *mllr, cmd_ln_t *config)
00553 {
00554 int32 i, m, f, d, *flen;
00555 float32 ****fgau;
00556
00557
00558 fgau = NULL;
00559 gauden_param_read(&fgau, &g->n_mgau, &g->n_feat, &g->n_density,
00560 &g->featlen, cmd_ln_str_r(config, "-mean"));
00561 g->mean = (mfcc_t ****)fgau;
00562 fgau = NULL;
00563 gauden_param_read(&fgau, &m, &f, &d, &flen, cmd_ln_str_r(config, "-var"));
00564 g->var = (mfcc_t ****)fgau;
00565
00566
00567 if ((m != g->n_mgau) || (f != g->n_feat) || (d != g->n_density))
00568 E_FATAL
00569 ("Mixture-gaussians dimensions for means and variances differ\n");
00570 for (i = 0; i < g->n_feat; i++)
00571 if (g->featlen[i] != flen[i])
00572 E_FATAL("Feature lengths for means and variances differ\n");
00573 ckd_free(flen);
00574
00575
00576 for (i = 0; i < g->n_mgau; ++i) {
00577 for (f = 0; f < g->n_feat; ++f) {
00578 float64 *temp;
00579 temp = (float64 *) ckd_calloc(g->featlen[f], sizeof(float64));
00580
00581 for (d = 0; d < g->n_density; d++) {
00582 int l;
00583 for (l = 0; l < g->featlen[f]; l++) {
00584 temp[l] = 0.0;
00585 for (m = 0; m < g->featlen[f]; m++) {
00586
00587 temp[l] += mllr->A[f][0][l][m] * g->mean[i][f][d][m];
00588 }
00589 temp[l] += mllr->b[f][0][l];
00590 }
00591
00592 for (l = 0; l < g->featlen[f]; l++) {
00593 g->mean[i][f][d][l] = (float32) temp[l];
00594 g->var[i][f][d][l] *= mllr->h[f][0][l];
00595 }
00596 }
00597 ckd_free(temp);
00598 }
00599 }
00600
00601
00602
00603 gauden_dist_precompute(g, g->lmath, cmd_ln_float32_r(config, "-varfloor"));
00604 return 0;
00605 }