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 mean_t *meanp;
00319 var_t *varp;
00320 var_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 += (var_t)logmath_log(lmath, 1.0 / sqrt(*fvarp * 2.0 * M_PI));
00347
00348 *varp = (var_t)logmath_ln_to_log(lmath, (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
00375 fgau = NULL;
00376 gauden_param_read(&fgau, &g->n_mgau, &g->n_feat, &g->n_density,
00377 &g->featlen, meanfile);
00378 g->mean = (mean_t ****)fgau;
00379 fgau = NULL;
00380 gauden_param_read(&fgau, &m, &f, &d, &flen, varfile);
00381 g->var = (var_t ****)fgau;
00382
00383
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
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
00415 static int32
00416 compute_dist_all(gauden_dist_t * out_dist, mfcc_t* obs, int32 featlen,
00417 mean_t ** mean, var_t ** var, var_t * det,
00418 int32 n_density)
00419 {
00420 int32 i, d;
00421
00422 for (d = 0; d < n_density; ++d) {
00423 mean_t *m;
00424 var_t *v;
00425 var_t dval;
00426
00427 m = mean[d];
00428 v = var[d];
00429 dval = det[d];
00430
00431 for (i = 0; i < featlen; i++) {
00432 mean_t diff;
00433 #ifdef FIXED_POINT
00434
00435 var_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
00445
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
00460
00461
00462 static int32
00463 compute_dist(gauden_dist_t * out_dist, int32 n_top,
00464 mfcc_t * obs, int32 featlen,
00465 mean_t ** mean, var_t ** var, var_t * det,
00466 int32 n_density)
00467 {
00468 int32 i, j, d;
00469 gauden_dist_t *worst;
00470
00471
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 mean_t *m;
00482 var_t *v;
00483 var_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 mean_t diff;
00491 #ifdef FIXED_POINT
00492
00493 var_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
00503
00504 dval -= diff * diff * v[i];
00505 #endif
00506 }
00507
00508 if ((i < featlen) || (dval < worst->dist))
00509 continue;
00510
00511
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
00526
00527
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 }
00543
00544 return 0;
00545 }