/* * 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, s3mgauid_t mgau, int32 n_top, vector_t * obs, gauden_dist_t ** out_dist) { int32 f, t; assert((n_top > 0) && (n_top <= g->n_density)); /* Allocate temporary space for distance computation, if necessary */ if (n_dist < n_top) { if (n_dist > 0) ckd_free(dist); n_dist = n_top; dist = (dist_t *) ckd_calloc(n_dist, sizeof(dist_t)); } for (f = 0; f < g->n_feat; f++) { compute_dist(dist, n_top, obs[f], g->featlen[f], g->mean[mgau][f], g->var[mgau][f], g->det[mgau][f], g->n_density); /* * Convert distances to logs3 domain and return result. Remember that until now, * we've been computing log(DENOMINATOR) of the normal density function. * Check for underflow before converting to (int32)logs3 value. */ for (t = 0; t < n_top; t++) { out_dist[f][t].id = dist[t].id; dist[t].dist = -dist[t].dist; /* log(numerator) = -log(denom.) */ if (dist[t].dist < min_density) { #if 0 E_ERROR ("Density[%d][%d][%d] too small (%.3e); flooring it to %.3e\n", mgau, f, dist[t].id, dist[t].dist, min_density); #endif dist[t].dist = min_density; } out_dist[f][t].dist = (int32) logmath_ln_to_log(g->logmath, dist[t].dist); } } return 0; }
/* * 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 = (mfcc_t***)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; }
static int32 s3_precomp(s2_semi_mgau_t *s, logmath_t *lmath, float32 vFloor) { int feat; for (feat = 0; feat < s->n_feat; ++feat) { float32 *fmp; mfcc_t *mp; mfcc_t *vp, *dp; int32 vecLen, i; vecLen = s->veclen[feat]; fmp = (float32 *) s->means[feat]; mp = s->means[feat]; vp = s->vars[feat]; dp = s->dets[feat]; for (i = 0; i < s->n_density; ++i) { mfcc_t d; int32 j; d = 0; for (j = 0; j < vecLen; ++j, ++vp, ++mp, ++fmp) { float64 fvar; *mp = FLOAT2MFCC(*fmp); /* Always do these pre-calculations in floating point */ fvar = *(float32 *) vp; if (fvar < vFloor) fvar = vFloor; d += (mfcc_t)logmath_log(lmath, 1 / sqrt(fvar * 2.0 * M_PI)); *vp = (mfcc_t)logmath_ln_to_log(lmath, 1.0 / (2.0 * fvar)); } *dp++ = d; } } return 0; }