• Main Page
  • Data Structures
  • Files
  • File List
  • Globals

src/libpocketsphinx/s2_semi_mgau.c

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 /* System headers */
00039 #include <stdio.h>
00040 #include <stdlib.h>
00041 #include <string.h>
00042 #include <assert.h>
00043 #include <limits.h>
00044 #include <math.h>
00045 #if defined(__ADSPBLACKFIN__)
00046 #elif !defined(_WIN32_WCE)
00047 #include <sys/types.h>
00048 #endif
00049 
00050 #ifndef M_PI 
00051 #define M_PI 3.14159265358979323846 
00052 #endif
00053 
00054 /* SphinxBase headers */
00055 #include <sphinx_config.h>
00056 #include <cmd_ln.h>
00057 #include <fixpoint.h>
00058 #include <ckd_alloc.h>
00059 #include <bio.h>
00060 #include <err.h>
00061 #include <prim_type.h>
00062 
00063 /* Local headers */
00064 #include "s2_semi_mgau.h"
00065 #include "tied_mgau_common.h"
00066 #include "posixwin32.h"
00067 
00068 static ps_mgaufuncs_t s2_semi_mgau_funcs = {
00069     "s2_semi",
00070     &s2_semi_mgau_frame_eval,      /* frame_eval */
00071     &s2_semi_mgau_mllr_transform,  /* transform */
00072     &s2_semi_mgau_free             /* free */
00073 };
00074 
00075 struct vqFeature_s {
00076     int32 score; /* score or distance */
00077     int32 codeword; /* codeword (vector index) */
00078 };
00079 
00080 static void
00081 eval_topn(s2_semi_mgau_t *s, int32 feat, mfcc_t *z)
00082 {
00083     int i, ceplen;
00084     vqFeature_t *topn;
00085 
00086     topn = s->f[feat];
00087     ceplen = s->veclen[feat];
00088 
00089     for (i = 0; i < s->max_topn; i++) {
00090         mfcc_t *mean, diff, sqdiff, compl; /* diff, diff^2, component likelihood */
00091         vqFeature_t vtmp;
00092         mfcc_t *var, d;
00093         mfcc_t *obs;
00094         int32 cw, j;
00095 
00096         cw = topn[i].codeword;
00097         mean = s->means[feat][0] + cw * ceplen;
00098         var = s->vars[feat][0] + cw * ceplen;
00099         d = s->dets[feat][cw];
00100         obs = z;
00101         for (j = 0; j < ceplen; j++) {
00102             diff = *obs++ - *mean++;
00103             sqdiff = MFCCMUL(diff, diff);
00104             compl = MFCCMUL(sqdiff, *var);
00105             d = GMMSUB(d, compl);
00106             ++var;
00107         }
00108         topn[i].score = (int32)d;
00109         if (i == 0)
00110             continue;
00111         vtmp = topn[i];
00112         for (j = i - 1; j >= 0 && (int32)d > topn[j].score; j--) {
00113             topn[j + 1] = topn[j];
00114         }
00115         topn[j + 1] = vtmp;
00116     }
00117 }
00118 
00119 static void
00120 eval_cb(s2_semi_mgau_t *s, int32 feat, mfcc_t *z)
00121 {
00122     vqFeature_t *worst, *best, *topn;
00123     mfcc_t *mean;
00124     mfcc_t *var, *det, *detP, *detE;
00125     int32 i, ceplen;
00126 
00127     best = topn = s->f[feat];
00128     worst = topn + (s->max_topn - 1);
00129     mean = s->means[feat][0];
00130     var = s->vars[feat][0];
00131     det = s->dets[feat];
00132     detE = det + s->n_density;
00133     ceplen = s->veclen[feat];
00134 
00135     for (detP = det; detP < detE; ++detP) {
00136         mfcc_t diff, sqdiff, compl; /* diff, diff^2, component likelihood */
00137         mfcc_t d;
00138         mfcc_t *obs;
00139         vqFeature_t *cur;
00140         int32 cw, j;
00141 
00142         d = *detP;
00143         obs = z;
00144         cw = detP - det;
00145         for (j = 0; (j < ceplen) && (d >= worst->score); ++j) {
00146             diff = *obs++ - *mean++;
00147             sqdiff = MFCCMUL(diff, diff);
00148             compl = MFCCMUL(sqdiff, *var);
00149             d = GMMSUB(d, compl);
00150             ++var;
00151         }
00152         if (j < ceplen) {
00153             /* terminated early, so not in topn */
00154             mean += (ceplen - j);
00155             var += (ceplen - j);
00156             continue;
00157         }
00158         if ((int32)d < worst->score)
00159             continue;
00160         for (i = 0; i < s->max_topn; i++) {
00161             /* already there, so don't need to insert */
00162             if (topn[i].codeword == cw)
00163                 break;
00164         }
00165         if (i < s->max_topn)
00166             continue;       /* already there.  Don't insert */
00167         /* remaining code inserts codeword and dist in correct spot */
00168         for (cur = worst - 1; cur >= best && (int32)d >= cur->score; --cur)
00169             memcpy(cur + 1, cur, sizeof(vqFeature_t));
00170         ++cur;
00171         cur->codeword = cw;
00172         cur->score = (int32)d;
00173     }
00174 }
00175 
00176 static void
00177 mgau_dist(s2_semi_mgau_t * s, int32 frame, int32 feat, mfcc_t * z)
00178 {
00179     eval_topn(s, feat, z);
00180 
00181     /* If this frame is skipped, do nothing else. */
00182     if (frame % s->ds_ratio)
00183         return;
00184 
00185     /* Evaluate the rest of the codebook (or subset thereof). */
00186     eval_cb(s, feat, z);
00187 }
00188 
00189 static int
00190 mgau_norm(s2_semi_mgau_t *s, int feat)
00191 {
00192     int32 norm;
00193     int j;
00194 
00195     /* Compute quantized normalizing constant. */
00196     norm = s->f[feat][0].score >> SENSCR_SHIFT;
00197 
00198     /* Normalize the scores, negate them, and clamp their dynamic range. */
00199     for (j = 0; j < s->max_topn; ++j) {
00200         s->f[feat][j].score = -((s->f[feat][j].score >> SENSCR_SHIFT) - norm);
00201         if (s->f[feat][j].score > MAX_NEG_ASCR)
00202             s->f[feat][j].score = MAX_NEG_ASCR;
00203         if (s->topn_beam[feat] && s->f[feat][j].score > s->topn_beam[feat])
00204             break;
00205     }
00206     return j;
00207 }
00208 
00209 static int32
00210 get_scores_8b_feat_6(s2_semi_mgau_t * s, int i,
00211                      int16 *senone_scores, uint8 *senone_active,
00212                      int32 n_senone_active)
00213 {
00214     int32 j, l;
00215     uint8 *pid_cw0, *pid_cw1, *pid_cw2, *pid_cw3, *pid_cw4, *pid_cw5;
00216 
00217     pid_cw0 = s->mixw[i][s->f[i][0].codeword];
00218     pid_cw1 = s->mixw[i][s->f[i][1].codeword];
00219     pid_cw2 = s->mixw[i][s->f[i][2].codeword];
00220     pid_cw3 = s->mixw[i][s->f[i][3].codeword];
00221     pid_cw4 = s->mixw[i][s->f[i][4].codeword];
00222     pid_cw5 = s->mixw[i][s->f[i][5].codeword];
00223 
00224     for (l = j = 0; j < n_senone_active; j++) {
00225         int sen = senone_active[j] + l;
00226         int32 tmp = pid_cw0[sen] + s->f[i][0].score;
00227 
00228         tmp = fast_logmath_add(s->lmath_8b, tmp,
00229                                pid_cw1[sen] + s->f[i][1].score);
00230         tmp = fast_logmath_add(s->lmath_8b, tmp,
00231                                pid_cw2[sen] + s->f[i][2].score);
00232         tmp = fast_logmath_add(s->lmath_8b, tmp,
00233                                pid_cw3[sen] + s->f[i][3].score);
00234         tmp = fast_logmath_add(s->lmath_8b, tmp,
00235                                pid_cw4[sen] + s->f[i][4].score);
00236         tmp = fast_logmath_add(s->lmath_8b, tmp,
00237                                pid_cw5[sen] + s->f[i][5].score);
00238 
00239         senone_scores[sen] += tmp;
00240         l = sen;
00241     }
00242     return 0;
00243 }
00244 
00245 static int32
00246 get_scores_8b_feat_5(s2_semi_mgau_t * s, int i,
00247                      int16 *senone_scores, uint8 *senone_active,
00248                      int32 n_senone_active)
00249 {
00250     int32 j, l;
00251     uint8 *pid_cw0, *pid_cw1, *pid_cw2, *pid_cw3, *pid_cw4;
00252 
00253     pid_cw0 = s->mixw[i][s->f[i][0].codeword];
00254     pid_cw1 = s->mixw[i][s->f[i][1].codeword];
00255     pid_cw2 = s->mixw[i][s->f[i][2].codeword];
00256     pid_cw3 = s->mixw[i][s->f[i][3].codeword];
00257     pid_cw4 = s->mixw[i][s->f[i][4].codeword];
00258 
00259     for (l = j = 0; j < n_senone_active; j++) {
00260         int sen = senone_active[j] + l;
00261         int32 tmp = pid_cw0[sen] + s->f[i][0].score;
00262 
00263         tmp = fast_logmath_add(s->lmath_8b, tmp,
00264                                pid_cw1[sen] + s->f[i][1].score);
00265         tmp = fast_logmath_add(s->lmath_8b, tmp,
00266                                pid_cw2[sen] + s->f[i][2].score);
00267         tmp = fast_logmath_add(s->lmath_8b, tmp,
00268                                pid_cw3[sen] + s->f[i][3].score);
00269         tmp = fast_logmath_add(s->lmath_8b, tmp,
00270                                pid_cw4[sen] + s->f[i][4].score);
00271 
00272         senone_scores[sen] += tmp;
00273         l = sen;
00274     }
00275     return 0;
00276 }
00277 
00278 static int32
00279 get_scores_8b_feat_4(s2_semi_mgau_t * s, int i,
00280                      int16 *senone_scores, uint8 *senone_active,
00281                      int32 n_senone_active)
00282 {
00283     int32 j, l;
00284     uint8 *pid_cw0, *pid_cw1, *pid_cw2, *pid_cw3;
00285 
00286     pid_cw0 = s->mixw[i][s->f[i][0].codeword];
00287     pid_cw1 = s->mixw[i][s->f[i][1].codeword];
00288     pid_cw2 = s->mixw[i][s->f[i][2].codeword];
00289     pid_cw3 = s->mixw[i][s->f[i][3].codeword];
00290 
00291     for (l = j = 0; j < n_senone_active; j++) {
00292         int sen = senone_active[j] + l;
00293         int32 tmp = pid_cw0[sen] + s->f[i][0].score;
00294 
00295         tmp = fast_logmath_add(s->lmath_8b, tmp,
00296                                pid_cw1[sen] + s->f[i][1].score);
00297         tmp = fast_logmath_add(s->lmath_8b, tmp,
00298                                pid_cw2[sen] + s->f[i][2].score);
00299         tmp = fast_logmath_add(s->lmath_8b, tmp,
00300                                pid_cw3[sen] + s->f[i][3].score);
00301 
00302         senone_scores[sen] += tmp;
00303         l = sen;
00304     }
00305     return 0;
00306 }
00307 
00308 static int32
00309 get_scores_8b_feat_3(s2_semi_mgau_t * s, int i,
00310                      int16 *senone_scores, uint8 *senone_active,
00311                      int32 n_senone_active)
00312 {
00313     int32 j, l;
00314     uint8 *pid_cw0, *pid_cw1, *pid_cw2;
00315 
00316     pid_cw0 = s->mixw[i][s->f[i][0].codeword];
00317     pid_cw1 = s->mixw[i][s->f[i][1].codeword];
00318     pid_cw2 = s->mixw[i][s->f[i][2].codeword];
00319 
00320     for (l = j = 0; j < n_senone_active; j++) {
00321         int sen = senone_active[j] + l;
00322         int32 tmp = pid_cw0[sen] + s->f[i][0].score;
00323 
00324         tmp = fast_logmath_add(s->lmath_8b, tmp,
00325                                pid_cw1[sen] + s->f[i][1].score);
00326         tmp = fast_logmath_add(s->lmath_8b, tmp,
00327                                pid_cw2[sen] + s->f[i][2].score);
00328 
00329         senone_scores[sen] += tmp;
00330         l = sen;
00331     }
00332     return 0;
00333 }
00334 
00335 static int32
00336 get_scores_8b_feat_2(s2_semi_mgau_t * s, int i,
00337                      int16 *senone_scores, uint8 *senone_active,
00338                      int32 n_senone_active)
00339 {
00340     int32 j, l;
00341     uint8 *pid_cw0, *pid_cw1;
00342 
00343     pid_cw0 = s->mixw[i][s->f[i][0].codeword];
00344     pid_cw1 = s->mixw[i][s->f[i][1].codeword];
00345 
00346     for (l = j = 0; j < n_senone_active; j++) {
00347         int sen = senone_active[j] + l;
00348         int32 tmp = pid_cw0[sen] + s->f[i][0].score;
00349 
00350         tmp = fast_logmath_add(s->lmath_8b, tmp,
00351                                pid_cw1[sen] + s->f[i][1].score);
00352 
00353         senone_scores[sen] += tmp;
00354         l = sen;
00355     }
00356     return 0;
00357 }
00358 
00359 static int32
00360 get_scores_8b_feat_1(s2_semi_mgau_t * s, int i,
00361                      int16 *senone_scores, uint8 *senone_active,
00362                      int32 n_senone_active)
00363 {
00364     int32 j, l;
00365     uint8 *pid_cw0;
00366 
00367     pid_cw0 = s->mixw[i][s->f[i][0].codeword];
00368     for (l = j = 0; j < n_senone_active; j++) {
00369         int sen = senone_active[j] + l;
00370         int32 tmp = pid_cw0[sen] + s->f[i][0].score;
00371         senone_scores[sen] += tmp;
00372         l = sen;
00373     }
00374     return 0;
00375 }
00376 
00377 static int32
00378 get_scores_8b_feat_any(s2_semi_mgau_t * s, int i, int topn,
00379                        int16 *senone_scores, uint8 *senone_active,
00380                        int32 n_senone_active)
00381 {
00382     int32 j, k, l;
00383 
00384     for (l = j = 0; j < n_senone_active; j++) {
00385         int sen = senone_active[j] + l;
00386         uint8 *pid_cw;
00387         int32 tmp;
00388         pid_cw = s->mixw[i][s->f[i][0].codeword];
00389         tmp = pid_cw[sen] + s->f[i][0].score;
00390         for (k = 1; k < topn; ++k) {
00391             pid_cw = s->mixw[i][s->f[i][k].codeword];
00392             tmp = fast_logmath_add(s->lmath_8b, tmp,
00393                                    pid_cw[sen] + s->f[i][k].score);
00394         }
00395         senone_scores[sen] += tmp;
00396         l = sen;
00397     }
00398     return 0;
00399 }
00400 
00401 static int32
00402 get_scores_8b_feat(s2_semi_mgau_t * s, int i, int topn,
00403                    int16 *senone_scores, uint8 *senone_active, int32 n_senone_active)
00404 {
00405     switch (topn) {
00406     case 6:
00407         return get_scores_8b_feat_6(s, i, senone_scores,
00408                                     senone_active, n_senone_active);
00409     case 5:
00410         return get_scores_8b_feat_5(s, i, senone_scores,
00411                                     senone_active, n_senone_active);
00412     case 4:
00413         return get_scores_8b_feat_4(s, i, senone_scores,
00414                                     senone_active, n_senone_active);
00415     case 3:
00416         return get_scores_8b_feat_3(s, i, senone_scores,
00417                                     senone_active, n_senone_active);
00418     case 2:
00419         return get_scores_8b_feat_2(s, i, senone_scores,
00420                                     senone_active, n_senone_active);
00421     case 1:
00422         return get_scores_8b_feat_1(s, i, senone_scores,
00423                                     senone_active, n_senone_active);
00424     default:
00425         return get_scores_8b_feat_any(s, i, topn, senone_scores,
00426                                       senone_active, n_senone_active);
00427     }
00428 }
00429 
00430 static int32
00431 get_scores_8b_feat_all(s2_semi_mgau_t * s, int i, int topn, int16 *senone_scores)
00432 {
00433     int32 j, k;
00434 
00435     for (j = 0; j < s->n_sen; j++) {
00436         uint8 *pid_cw;
00437         int32 tmp;
00438         pid_cw = s->mixw[i][s->f[i][0].codeword];
00439         tmp = pid_cw[j] + s->f[i][0].score;
00440         for (k = 1; k < topn; ++k) {
00441             pid_cw = s->mixw[i][s->f[i][k].codeword];
00442             tmp = fast_logmath_add(s->lmath_8b, tmp,
00443                                    pid_cw[j] + s->f[i][k].score);
00444         }
00445         senone_scores[j] += tmp;
00446     }
00447     return 0;
00448 }
00449 
00450 static int32
00451 get_scores_4b_feat_6(s2_semi_mgau_t * s, int i,
00452                      int16 *senone_scores, uint8 *senone_active,
00453                      int32 n_senone_active)
00454 {
00455     int32 j, l;
00456     uint8 *pid_cw0, *pid_cw1, *pid_cw2, *pid_cw3, *pid_cw4, *pid_cw5;
00457     uint8 w_den[6][16];
00458 
00459     /* Precompute scaled densities. */
00460     for (j = 0; j < 16; ++j) {
00461         w_den[0][j] = s->mixw_cb[j] + s->f[i][0].score;
00462         w_den[1][j] = s->mixw_cb[j] + s->f[i][1].score;
00463         w_den[2][j] = s->mixw_cb[j] + s->f[i][2].score;
00464         w_den[3][j] = s->mixw_cb[j] + s->f[i][3].score;
00465         w_den[4][j] = s->mixw_cb[j] + s->f[i][4].score;
00466         w_den[5][j] = s->mixw_cb[j] + s->f[i][5].score;
00467     }
00468 
00469     pid_cw0 = s->mixw[i][s->f[i][0].codeword];
00470     pid_cw1 = s->mixw[i][s->f[i][1].codeword];
00471     pid_cw2 = s->mixw[i][s->f[i][2].codeword];
00472     pid_cw3 = s->mixw[i][s->f[i][3].codeword];
00473     pid_cw4 = s->mixw[i][s->f[i][4].codeword];
00474     pid_cw5 = s->mixw[i][s->f[i][5].codeword];
00475 
00476     for (l = j = 0; j < n_senone_active; j++) {
00477         int n = senone_active[j] + l;
00478         int tmp, cw;
00479 
00480         if (n & 1) {
00481             cw = pid_cw0[n/2] >> 4;
00482             tmp = w_den[0][cw];
00483             cw = pid_cw1[n/2] >> 4;
00484             tmp = fast_logmath_add(s->lmath_8b, tmp, w_den[1][cw]);
00485             cw = pid_cw2[n/2] >> 4;
00486             tmp = fast_logmath_add(s->lmath_8b, tmp, w_den[2][cw]);
00487             cw = pid_cw3[n/2] >> 4;
00488             tmp = fast_logmath_add(s->lmath_8b, tmp, w_den[3][cw]);
00489             cw = pid_cw4[n/2] >> 4;
00490             tmp = fast_logmath_add(s->lmath_8b, tmp, w_den[4][cw]);
00491             cw = pid_cw5[n/2] >> 4;
00492             tmp = fast_logmath_add(s->lmath_8b, tmp, w_den[5][cw]);
00493         }
00494         else {
00495             cw = pid_cw0[n/2] & 0x0f;
00496             tmp = w_den[0][cw];
00497             cw = pid_cw1[n/2] & 0x0f;
00498             tmp = fast_logmath_add(s->lmath_8b, tmp, w_den[1][cw]);
00499             cw = pid_cw2[n/2] & 0x0f;
00500             tmp = fast_logmath_add(s->lmath_8b, tmp, w_den[2][cw]);
00501             cw = pid_cw3[n/2] & 0x0f;
00502             tmp = fast_logmath_add(s->lmath_8b, tmp, w_den[3][cw]);
00503             cw = pid_cw4[n/2] & 0x0f;
00504             tmp = fast_logmath_add(s->lmath_8b, tmp, w_den[4][cw]);
00505             cw = pid_cw5[n/2] & 0x0f;
00506             tmp = fast_logmath_add(s->lmath_8b, tmp, w_den[5][cw]);
00507         }
00508         senone_scores[n] += tmp;
00509         l = n;
00510     }
00511     return 0;
00512 }
00513 
00514 static int32
00515 get_scores_4b_feat_5(s2_semi_mgau_t * s, int i,
00516                      int16 *senone_scores, uint8 *senone_active,
00517                      int32 n_senone_active)
00518 {
00519     int32 j, l;
00520     uint8 *pid_cw0, *pid_cw1, *pid_cw2, *pid_cw3, *pid_cw4;
00521     uint8 w_den[5][16];
00522 
00523     /* Precompute scaled densities. */
00524     for (j = 0; j < 16; ++j) {
00525         w_den[0][j] = s->mixw_cb[j] + s->f[i][0].score;
00526         w_den[1][j] = s->mixw_cb[j] + s->f[i][1].score;
00527         w_den[2][j] = s->mixw_cb[j] + s->f[i][2].score;
00528         w_den[3][j] = s->mixw_cb[j] + s->f[i][3].score;
00529         w_den[4][j] = s->mixw_cb[j] + s->f[i][4].score;
00530     }
00531 
00532     pid_cw0 = s->mixw[i][s->f[i][0].codeword];
00533     pid_cw1 = s->mixw[i][s->f[i][1].codeword];
00534     pid_cw2 = s->mixw[i][s->f[i][2].codeword];
00535     pid_cw3 = s->mixw[i][s->f[i][3].codeword];
00536     pid_cw4 = s->mixw[i][s->f[i][4].codeword];
00537 
00538     for (l = j = 0; j < n_senone_active; j++) {
00539         int n = senone_active[j] + l;
00540         int tmp, cw;
00541 
00542         if (n & 1) {
00543             cw = pid_cw0[n/2] >> 4;
00544             tmp = w_den[0][cw];
00545             cw = pid_cw1[n/2] >> 4;
00546             tmp = fast_logmath_add(s->lmath_8b, tmp, w_den[1][cw]);
00547             cw = pid_cw2[n/2] >> 4;
00548             tmp = fast_logmath_add(s->lmath_8b, tmp, w_den[2][cw]);
00549             cw = pid_cw3[n/2] >> 4;
00550             tmp = fast_logmath_add(s->lmath_8b, tmp, w_den[3][cw]);
00551             cw = pid_cw4[n/2] >> 4;
00552             tmp = fast_logmath_add(s->lmath_8b, tmp, w_den[4][cw]);
00553         }
00554         else {
00555             cw = pid_cw0[n/2] & 0x0f;
00556             tmp = w_den[0][cw];
00557             cw = pid_cw1[n/2] & 0x0f;
00558             tmp = fast_logmath_add(s->lmath_8b, tmp, w_den[1][cw]);
00559             cw = pid_cw2[n/2] & 0x0f;
00560             tmp = fast_logmath_add(s->lmath_8b, tmp, w_den[2][cw]);
00561             cw = pid_cw3[n/2] & 0x0f;
00562             tmp = fast_logmath_add(s->lmath_8b, tmp, w_den[3][cw]);
00563             cw = pid_cw4[n/2] & 0x0f;
00564             tmp = fast_logmath_add(s->lmath_8b, tmp, w_den[4][cw]);
00565         }
00566         senone_scores[n] += tmp;
00567         l = n;
00568     }
00569     return 0;
00570 }
00571 
00572 static int32
00573 get_scores_4b_feat_4(s2_semi_mgau_t * s, int i,
00574                      int16 *senone_scores, uint8 *senone_active,
00575                      int32 n_senone_active)
00576 {
00577     int32 j, l;
00578     uint8 *pid_cw0, *pid_cw1, *pid_cw2, *pid_cw3;
00579     uint8 w_den[4][16];
00580 
00581     /* Precompute scaled densities. */
00582     for (j = 0; j < 16; ++j) {
00583         w_den[0][j] = s->mixw_cb[j] + s->f[i][0].score;
00584         w_den[1][j] = s->mixw_cb[j] + s->f[i][1].score;
00585         w_den[2][j] = s->mixw_cb[j] + s->f[i][2].score;
00586         w_den[3][j] = s->mixw_cb[j] + s->f[i][3].score;
00587     }
00588 
00589     pid_cw0 = s->mixw[i][s->f[i][0].codeword];
00590     pid_cw1 = s->mixw[i][s->f[i][1].codeword];
00591     pid_cw2 = s->mixw[i][s->f[i][2].codeword];
00592     pid_cw3 = s->mixw[i][s->f[i][3].codeword];
00593 
00594     for (l = j = 0; j < n_senone_active; j++) {
00595         int n = senone_active[j] + l;
00596         int tmp, cw;
00597 
00598         if (n & 1) {
00599             cw = pid_cw0[n/2] >> 4;
00600             tmp = w_den[0][cw];
00601             cw = pid_cw1[n/2] >> 4;
00602             tmp = fast_logmath_add(s->lmath_8b, tmp, w_den[1][cw]);
00603             cw = pid_cw2[n/2] >> 4;
00604             tmp = fast_logmath_add(s->lmath_8b, tmp, w_den[2][cw]);
00605             cw = pid_cw3[n/2] >> 4;
00606             tmp = fast_logmath_add(s->lmath_8b, tmp, w_den[3][cw]);
00607         }
00608         else {
00609             cw = pid_cw0[n/2] & 0x0f;
00610             tmp = w_den[0][cw];
00611             cw = pid_cw1[n/2] & 0x0f;
00612             tmp = fast_logmath_add(s->lmath_8b, tmp, w_den[1][cw]);
00613             cw = pid_cw2[n/2] & 0x0f;
00614             tmp = fast_logmath_add(s->lmath_8b, tmp, w_den[2][cw]);
00615             cw = pid_cw3[n/2] & 0x0f;
00616             tmp = fast_logmath_add(s->lmath_8b, tmp, w_den[3][cw]);
00617         }
00618         senone_scores[n] += tmp;
00619         l = n;
00620     }
00621     return 0;
00622 }
00623 
00624 static int32
00625 get_scores_4b_feat_3(s2_semi_mgau_t * s, int i,
00626                      int16 *senone_scores, uint8 *senone_active,
00627                      int32 n_senone_active)
00628 {
00629     int32 j, l;
00630     uint8 *pid_cw0, *pid_cw1, *pid_cw2;
00631     uint8 w_den[3][16];
00632 
00633     /* Precompute scaled densities. */
00634     for (j = 0; j < 16; ++j) {
00635         w_den[0][j] = s->mixw_cb[j] + s->f[i][0].score;
00636         w_den[1][j] = s->mixw_cb[j] + s->f[i][1].score;
00637         w_den[2][j] = s->mixw_cb[j] + s->f[i][2].score;
00638     }
00639 
00640     pid_cw0 = s->mixw[i][s->f[i][0].codeword];
00641     pid_cw1 = s->mixw[i][s->f[i][1].codeword];
00642     pid_cw2 = s->mixw[i][s->f[i][2].codeword];
00643 
00644     for (l = j = 0; j < n_senone_active; j++) {
00645         int n = senone_active[j] + l;
00646         int tmp, cw;
00647 
00648         if (n & 1) {
00649             cw = pid_cw0[n/2] >> 4;
00650             tmp = w_den[0][cw];
00651             cw = pid_cw1[n/2] >> 4;
00652             tmp = fast_logmath_add(s->lmath_8b, tmp, w_den[1][cw]);
00653             cw = pid_cw2[n/2] >> 4;
00654             tmp = fast_logmath_add(s->lmath_8b, tmp, w_den[2][cw]);
00655         }
00656         else {
00657             cw = pid_cw0[n/2] & 0x0f;
00658             tmp = w_den[0][cw];
00659             cw = pid_cw1[n/2] & 0x0f;
00660             tmp = fast_logmath_add(s->lmath_8b, tmp, w_den[1][cw]);
00661             cw = pid_cw2[n/2] & 0x0f;
00662             tmp = fast_logmath_add(s->lmath_8b, tmp, w_den[2][cw]);
00663         }
00664         senone_scores[n] += tmp;
00665         l = n;
00666     }
00667     return 0;
00668 }
00669 
00670 static int32
00671 get_scores_4b_feat_2(s2_semi_mgau_t * s, int i,
00672                      int16 *senone_scores, uint8 *senone_active,
00673                      int32 n_senone_active)
00674 {
00675     int32 j, l;
00676     uint8 *pid_cw0, *pid_cw1;
00677     uint8 w_den[2][16];
00678 
00679     /* Precompute scaled densities. */
00680     for (j = 0; j < 16; ++j) {
00681         w_den[0][j] = s->mixw_cb[j] + s->f[i][0].score;
00682         w_den[1][j] = s->mixw_cb[j] + s->f[i][1].score;
00683     }
00684 
00685     pid_cw0 = s->mixw[i][s->f[i][0].codeword];
00686     pid_cw1 = s->mixw[i][s->f[i][1].codeword];
00687 
00688     for (l = j = 0; j < n_senone_active; j++) {
00689         int n = senone_active[j] + l;
00690         int tmp, cw;
00691 
00692         if (n & 1) {
00693             cw = pid_cw0[n/2] >> 4;
00694             tmp = w_den[0][cw];
00695             cw = pid_cw1[n/2] >> 4;
00696             tmp = fast_logmath_add(s->lmath_8b, tmp, w_den[1][cw]);
00697         }
00698         else {
00699             cw = pid_cw0[n/2] & 0x0f;
00700             tmp = w_den[0][cw];
00701             cw = pid_cw1[n/2] & 0x0f;
00702             tmp = fast_logmath_add(s->lmath_8b, tmp, w_den[1][cw]);
00703         }
00704         senone_scores[n] += tmp;
00705         l = n;
00706     }
00707     return 0;
00708 }
00709 
00710 static int32
00711 get_scores_4b_feat_1(s2_semi_mgau_t * s, int i,
00712                      int16 *senone_scores, uint8 *senone_active,
00713                      int32 n_senone_active)
00714 {
00715     int32 j, l;
00716     uint8 *pid_cw0;
00717     uint8 w_den[16];
00718 
00719     /* Precompute scaled densities. */
00720     for (j = 0; j < 16; ++j) {
00721         w_den[j] = s->mixw_cb[j] + s->f[i][0].score;
00722     }
00723 
00724     pid_cw0 = s->mixw[i][s->f[i][0].codeword];
00725 
00726     for (l = j = 0; j < n_senone_active; j++) {
00727         int n = senone_active[j] + l;
00728         int tmp, cw;
00729 
00730         if (n & 1) {
00731             cw = pid_cw0[n/2] >> 4;
00732             tmp = w_den[cw];
00733         }
00734         else {
00735             cw = pid_cw0[n/2] & 0x0f;
00736             tmp = w_den[cw];
00737         }
00738         senone_scores[n] += tmp;
00739         l = n;
00740     }
00741     return 0;
00742 }
00743 
00744 static int32
00745 get_scores_4b_feat_any(s2_semi_mgau_t * s, int i, int topn,
00746                        int16 *senone_scores, uint8 *senone_active,
00747                        int32 n_senone_active)
00748 {
00749     int32 j, k, l;
00750 
00751     for (l = j = 0; j < n_senone_active; j++) {
00752         int n = senone_active[j] + l;
00753         int tmp, cw;
00754         uint8 *pid_cw;
00755     
00756         pid_cw = s->mixw[i][s->f[i][0].codeword];
00757         if (n & 1)
00758             cw = pid_cw[n/2] >> 4;
00759         else
00760             cw = pid_cw[n/2] & 0x0f;
00761         tmp = s->mixw_cb[cw] + s->f[i][0].score;
00762         for (k = 1; k < topn; ++k) {
00763             pid_cw = s->mixw[i][s->f[i][k].codeword];
00764             if (n & 1)
00765                 cw = pid_cw[n/2] >> 4;
00766             else
00767                 cw = pid_cw[n/2] & 0x0f;
00768             tmp = fast_logmath_add(s->lmath_8b, tmp,
00769                                    s->mixw_cb[cw] + s->f[i][k].score);
00770         }
00771         senone_scores[n] += tmp;
00772         l = n;
00773     }
00774     return 0;
00775 }
00776 
00777 static int32
00778 get_scores_4b_feat(s2_semi_mgau_t * s, int i, int topn,
00779                    int16 *senone_scores, uint8 *senone_active, int32 n_senone_active)
00780 {
00781     switch (topn) {
00782     case 6:
00783         return get_scores_4b_feat_6(s, i, senone_scores,
00784                                     senone_active, n_senone_active);
00785     case 5:
00786         return get_scores_4b_feat_5(s, i, senone_scores,
00787                                     senone_active, n_senone_active);
00788     case 4:
00789         return get_scores_4b_feat_4(s, i, senone_scores,
00790                                     senone_active, n_senone_active);
00791     case 3:
00792         return get_scores_4b_feat_3(s, i, senone_scores,
00793                                     senone_active, n_senone_active);
00794     case 2:
00795         return get_scores_4b_feat_2(s, i, senone_scores,
00796                                     senone_active, n_senone_active);
00797     case 1:
00798         return get_scores_4b_feat_1(s, i, senone_scores,
00799                                     senone_active, n_senone_active);
00800     default:
00801         return get_scores_4b_feat_any(s, i, topn, senone_scores,
00802                                       senone_active, n_senone_active);
00803     }
00804 }
00805 
00806 static int32
00807 get_scores_4b_feat_all(s2_semi_mgau_t * s, int i, int topn, int16 *senone_scores)
00808 {
00809     int32 j, k;
00810 
00811     for (j = 0; j < s->n_sen; j++) {
00812         uint8 *pid_cw;
00813         int32 tmp;
00814         pid_cw = s->mixw[i][s->f[i][0].codeword];
00815         tmp = pid_cw[j] + s->f[i][0].score;
00816         for (k = 1; k < topn; ++k) {
00817             pid_cw = s->mixw[i][s->f[i][k].codeword];
00818             tmp = fast_logmath_add(s->lmath_8b, tmp,
00819                                    pid_cw[j] + s->f[i][k].score);
00820         }
00821         senone_scores[j] += tmp;
00822     }
00823     return 0;
00824 }
00825 
00826 /*
00827  * Compute senone scores for the active senones.
00828  */
00829 int32
00830 s2_semi_mgau_frame_eval(ps_mgau_t *ps,
00831                         int16 *senone_scores,
00832                         uint8 *senone_active,
00833                         int32 n_senone_active,
00834                         mfcc_t ** featbuf, int32 frame,
00835                         int32 compallsen)
00836 {
00837     s2_semi_mgau_t *s = (s2_semi_mgau_t *)ps;
00838     int i, topn_idx;
00839 
00840     memset(senone_scores, 0, s->n_sen * sizeof(*senone_scores));
00841     /* No bounds checking is done here, which just means you'll get
00842      * semi-random crap if you request a frame in the future or one
00843      * that's too far in the past. */
00844     topn_idx = frame % s->n_topn_hist;
00845     s->f = s->topn_hist[topn_idx];
00846     for (i = 0; i < s->n_feat; ++i) {
00847         /* For past frames this will already be computed. */
00848         if (frame >= ps_mgau_base(ps)->frame_idx) {
00849             vqFeature_t **lastf;
00850             if (topn_idx == 0)
00851                 lastf = s->topn_hist[s->n_topn_hist-1];
00852             else
00853                 lastf = s->topn_hist[topn_idx-1];
00854             memcpy(s->f[i], lastf[i], sizeof(vqFeature_t) * s->max_topn);
00855             mgau_dist(s, frame, i, featbuf[i]);
00856             s->topn_hist_n[topn_idx][i] = mgau_norm(s, i);
00857         }
00858         if (s->mixw_cb) {
00859             if (compallsen)
00860                 get_scores_4b_feat_all(s, i, s->topn_hist_n[topn_idx][i], senone_scores);
00861             else
00862                 get_scores_4b_feat(s, i, s->topn_hist_n[topn_idx][i], senone_scores,
00863                                    senone_active, n_senone_active);
00864         }
00865         else {
00866             if (compallsen)
00867                 get_scores_8b_feat_all(s, i, s->topn_hist_n[topn_idx][i], senone_scores);
00868             else
00869                 get_scores_8b_feat(s, i, s->topn_hist_n[topn_idx][i], senone_scores,
00870                                    senone_active, n_senone_active);
00871         }
00872     }
00873 
00874     return 0;
00875 }
00876 
00877 static int32
00878 read_sendump(s2_semi_mgau_t *s, bin_mdef_t *mdef, char const *file)
00879 {
00880     FILE *fp;
00881     char line[1000];
00882     int32 i, n, r, c;
00883     int32 do_swap, do_mmap;
00884     size_t filesize, offset;
00885     int n_clust = 0;
00886     int n_feat = s->n_feat;
00887     int n_density = s->n_density;
00888     int n_sen = bin_mdef_n_sen(mdef);
00889     int n_bits = 8;
00890 
00891     s->n_sen = n_sen; /* FIXME: Should have been done earlier */
00892     do_mmap = cmd_ln_boolean_r(s->config, "-mmap");
00893 
00894     if ((fp = fopen(file, "rb")) == NULL)
00895         return -1;
00896 
00897     E_INFO("Loading senones from dump file %s\n", file);
00898     /* Read title size, title */
00899     if (fread(&n, sizeof(int32), 1, fp) != 1) {
00900         E_ERROR_SYSTEM("Failed to read title size from %s", file);
00901         goto error_out;
00902     }
00903     /* This is extremely bogus */
00904     do_swap = 0;
00905     if (n < 1 || n > 999) {
00906         SWAP_INT32(&n);
00907         if (n < 1 || n > 999) {
00908             E_ERROR("Title length %x in dump file %s out of range\n", n, file);
00909             goto error_out;
00910         }
00911         do_swap = 1;
00912     }
00913     if (fread(line, sizeof(char), n, fp) != n) {
00914         E_ERROR_SYSTEM("Cannot read title");
00915         goto error_out;
00916     }
00917     if (line[n - 1] != '\0') {
00918         E_ERROR("Bad title in dump file\n");
00919         goto error_out;
00920     }
00921     E_INFO("%s\n", line);
00922 
00923     /* Read header size, header */
00924     if (fread(&n, sizeof(n), 1, fp) != 1) {
00925         E_ERROR_SYSTEM("Failed to read header size from %s", file);
00926         goto error_out;
00927     }
00928     if (do_swap) SWAP_INT32(&n);
00929     if (fread(line, sizeof(char), n, fp) != n) {
00930         E_ERROR_SYSTEM("Cannot read header");
00931         goto error_out;
00932     }
00933     if (line[n - 1] != '\0') {
00934         E_ERROR("Bad header in dump file\n");
00935         goto error_out;
00936     }
00937 
00938     /* Read other header strings until string length = 0 */
00939     for (;;) {
00940         if (fread(&n, sizeof(n), 1, fp) != 1) {
00941             E_ERROR_SYSTEM("Failed to read header string size from %s", file);
00942             goto error_out;
00943         }
00944         if (do_swap) SWAP_INT32(&n);
00945         if (n == 0)
00946             break;
00947         if (fread(line, sizeof(char), n, fp) != n) {
00948             E_ERROR_SYSTEM("Cannot read header");
00949             goto error_out;
00950         }
00951         /* Look for a cluster count, if present */
00952         if (!strncmp(line, "feature_count ", strlen("feature_count "))) {
00953             n_feat = atoi(line + strlen("feature_count "));
00954         }
00955         if (!strncmp(line, "mixture_count ", strlen("mixture_count "))) {
00956             n_density = atoi(line + strlen("mixture_count "));
00957         }
00958         if (!strncmp(line, "model_count ", strlen("model_count "))) {
00959             n_sen = atoi(line + strlen("model_count "));
00960         }
00961         if (!strncmp(line, "cluster_count ", strlen("cluster_count "))) {
00962             n_clust = atoi(line + strlen("cluster_count "));
00963         }
00964         if (!strncmp(line, "cluster_bits ", strlen("cluster_bits "))) {
00965             n_bits = atoi(line + strlen("cluster_bits "));
00966         }
00967     }
00968 
00969     /* Defaults for #rows, #columns in mixw array. */
00970     c = n_sen;
00971     r = n_density;
00972     if (n_clust == 0) {
00973         /* Older mixw files have them here, and they might be padded. */
00974         if (fread(&r, sizeof(r), 1, fp) != 1) {
00975             E_ERROR_SYSTEM("Cannot read #rows");
00976             goto error_out;
00977         }
00978         if (do_swap) SWAP_INT32(&r);
00979         if (fread(&c, sizeof(c), 1, fp) != 1) {
00980             E_ERROR_SYSTEM("Cannot read #columns");
00981             goto error_out;
00982         }
00983         if (do_swap) SWAP_INT32(&c);
00984         E_INFO("Rows: %d, Columns: %d\n", r, c);
00985     }
00986 
00987     if (n_feat != s->n_feat) {
00988         E_ERROR("Number of feature streams mismatch: %d != %d\n",
00989                 n_feat, s->n_feat);
00990         goto error_out;
00991     }
00992     if (n_density != s->n_density) {
00993         E_ERROR("Number of densities mismatch: %d != %d\n",
00994                 n_density, s->n_density);
00995         goto error_out;
00996     }
00997     if (n_sen != s->n_sen) {
00998         E_ERROR("Number of senones mismatch: %d != %d\n",
00999                 n_sen, s->n_sen);
01000         goto error_out;
01001     }
01002 
01003     if (!((n_clust == 0) || (n_clust == 15) || (n_clust == 16))) {
01004         E_ERROR("Cluster count must be 0, 15, or 16\n");
01005         goto error_out;
01006     }
01007     if (n_clust == 15)
01008         ++n_clust;
01009 
01010     if (!((n_bits == 8) || (n_bits == 4))) {
01011         E_ERROR("Cluster count must be 4 or 8\n");
01012         goto error_out;
01013     }
01014 
01015     if (do_mmap) {
01016             E_INFO("Using memory-mapped I/O for senones\n");
01017     }
01018     offset = ftell(fp);
01019     fseek(fp, 0, SEEK_END);
01020     filesize = ftell(fp);
01021     fseek(fp, offset, SEEK_SET);
01022 
01023     /* Allocate memory for pdfs (or memory map them) */
01024     if (do_mmap) {
01025         s->sendump_mmap = mmio_file_read(file);
01026         /* Get cluster codebook if any. */
01027         if (n_clust) {
01028             s->mixw_cb = ((uint8 *) mmio_file_ptr(s->sendump_mmap)) + offset;
01029             offset += n_clust;
01030         }
01031     }
01032     else {
01033         /* Get cluster codebook if any. */
01034         if (n_clust) {
01035             s->mixw_cb = ckd_calloc(1, n_clust);
01036             if (fread(s->mixw_cb, 1, n_clust, fp) != (size_t) n_clust) {
01037                 E_ERROR("Failed to read %d bytes from sendump\n", n_clust);
01038                 goto error_out;
01039             }
01040         }
01041     }
01042 
01043     /* Set up pointers, or read, or whatever */
01044     if (s->sendump_mmap) {
01045         s->mixw = ckd_calloc_2d(s->n_feat, n_density, sizeof(*s->mixw));
01046         for (n = 0; n < n_feat; n++) {
01047             int step = c;
01048             if (n_bits == 4)
01049                 step = (step + 1) / 2;
01050             for (i = 0; i < r; i++) {
01051                 s->mixw[n][i] = ((uint8 *) mmio_file_ptr(s->sendump_mmap)) + offset;
01052                 offset += step;
01053             }
01054         }
01055     }
01056     else {
01057         s->mixw = ckd_calloc_3d(n_feat, n_density, n_sen, sizeof(***s->mixw));
01058         /* Read pdf values and ids */
01059         for (n = 0; n < n_feat; n++) {
01060             int step = c;
01061             if (n_bits == 4)
01062                 step = (step + 1) / 2;
01063             for (i = 0; i < r; i++) {
01064                 if (fread(s->mixw[n][i], sizeof(***s->mixw), step, fp)
01065                     != (size_t) step) {
01066                     E_ERROR("Failed to read %d bytes from sendump\n", step);
01067                     goto error_out;
01068                 }
01069             }
01070         }
01071     }
01072 
01073     fclose(fp);
01074     return 0;
01075 error_out:
01076     fclose(fp);
01077     return -1;
01078 }
01079 
01080 static int32
01081 read_mixw(s2_semi_mgau_t * s, char const *file_name, double SmoothMin)
01082 {
01083     char **argname, **argval;
01084     char eofchk;
01085     FILE *fp;
01086     int32 byteswap, chksum_present;
01087     uint32 chksum;
01088     float32 *pdf;
01089     int32 i, f, c, n;
01090     int32 n_sen;
01091     int32 n_feat;
01092     int32 n_comp;
01093     int32 n_err;
01094 
01095     E_INFO("Reading mixture weights file '%s'\n", file_name);
01096 
01097     if ((fp = fopen(file_name, "rb")) == NULL)
01098         E_FATAL("fopen(%s,rb) failed\n", file_name);
01099 
01100     /* Read header, including argument-value info and 32-bit byteorder magic */
01101     if (bio_readhdr(fp, &argname, &argval, &byteswap) < 0)
01102         E_FATAL("bio_readhdr(%s) failed\n", file_name);
01103 
01104     /* Parse argument-value list */
01105     chksum_present = 0;
01106     for (i = 0; argname[i]; i++) {
01107         if (strcmp(argname[i], "version") == 0) {
01108             if (strcmp(argval[i], MGAU_MIXW_VERSION) != 0)
01109                 E_WARN("Version mismatch(%s): %s, expecting %s\n",
01110                        file_name, argval[i], MGAU_MIXW_VERSION);
01111         }
01112         else if (strcmp(argname[i], "chksum0") == 0) {
01113             chksum_present = 1; /* Ignore the associated value */
01114         }
01115     }
01116     bio_hdrarg_free(argname, argval);
01117     argname = argval = NULL;
01118 
01119     chksum = 0;
01120 
01121     /* Read #senones, #features, #codewords, arraysize */
01122     if ((bio_fread(&n_sen, sizeof(int32), 1, fp, byteswap, &chksum) != 1)
01123         || (bio_fread(&n_feat, sizeof(int32), 1, fp, byteswap, &chksum) !=
01124             1)
01125         || (bio_fread(&n_comp, sizeof(int32), 1, fp, byteswap, &chksum) !=
01126             1)
01127         || (bio_fread(&n, sizeof(int32), 1, fp, byteswap, &chksum) != 1)) {
01128         E_FATAL("bio_fread(%s) (arraysize) failed\n", file_name);
01129     }
01130     if (n_feat != s->n_feat)
01131         E_FATAL("#Features streams(%d) != %d\n", n_feat, s->n_feat);
01132     if (n != n_sen * n_feat * n_comp) {
01133         E_FATAL
01134             ("%s: #float32s(%d) doesn't match header dimensions: %d x %d x %d\n",
01135              file_name, i, n_sen, n_feat, n_comp);
01136     }
01137 
01138     /* n_sen = number of mixture weights per codeword, which is
01139      * fixed at the number of senones since we have only one codebook.
01140      */
01141     s->n_sen = n_sen;
01142 
01143     /* Quantized mixture weight arrays. */
01144     s->mixw = ckd_calloc_3d(s->n_feat, s->n_density, n_sen, sizeof(***s->mixw));
01145 
01146     /* Temporary structure to read in floats before conversion to (int32) logs3 */
01147     pdf = (float32 *) ckd_calloc(n_comp, sizeof(float32));
01148 
01149     /* Read senone probs data, normalize, floor, convert to logs3, truncate to 8 bits */
01150     n_err = 0;
01151     for (i = 0; i < n_sen; i++) {
01152         for (f = 0; f < n_feat; f++) {
01153             if (bio_fread((void *) pdf, sizeof(float32),
01154                           n_comp, fp, byteswap, &chksum) != n_comp) {
01155                 E_FATAL("bio_fread(%s) (arraydata) failed\n", file_name);
01156             }
01157 
01158             /* Normalize and floor */
01159             if (vector_sum_norm(pdf, n_comp) <= 0.0)
01160                 n_err++;
01161             vector_floor(pdf, n_comp, SmoothMin);
01162             vector_sum_norm(pdf, n_comp);
01163 
01164             /* Convert to LOG, quantize, and transpose */
01165             for (c = 0; c < n_comp; c++) {
01166                 int32 qscr;
01167 
01168                 qscr = -logmath_log(s->lmath_8b, pdf[c]);
01169                 if ((qscr > MAX_NEG_MIXW) || (qscr < 0))
01170                     qscr = MAX_NEG_MIXW;
01171                 s->mixw[f][c][i] = qscr;
01172             }
01173         }
01174     }
01175     if (n_err > 0)
01176         E_ERROR("Weight normalization failed for %d senones\n", n_err);
01177 
01178     ckd_free(pdf);
01179 
01180     if (chksum_present)
01181         bio_verify_chksum(fp, byteswap, chksum);
01182 
01183     if (fread(&eofchk, 1, 1, fp) == 1)
01184         E_FATAL("More data than expected in %s\n", file_name);
01185 
01186     fclose(fp);
01187 
01188     E_INFO("Read %d x %d x %d mixture weights\n", n_sen, n_feat, n_comp);
01189     return n_sen;
01190 }
01191 
01192 
01193 static int
01194 split_topn(char const *str, uint8 *out, int nfeat)
01195 {
01196     char *topn_list = ckd_salloc(str);
01197     char *c, *cc;
01198     int i, maxn;
01199 
01200     c = topn_list;
01201     i = 0;
01202     maxn = 0;
01203     while (i < nfeat && (cc = strchr(c, ',')) != NULL) {
01204         *cc = '\0';
01205         out[i] = atoi(c);
01206         if (out[i] > maxn) maxn = out[i];
01207         c = cc + 1;
01208         ++i;
01209     }
01210     if (i < nfeat && *c != '\0') {
01211         out[i] = atoi(c);
01212         if (out[i] > maxn) maxn = out[i];
01213         ++i;
01214     }
01215     while (i < nfeat)
01216         out[i++] = maxn;
01217 
01218     ckd_free(topn_list);
01219     return maxn;
01220 }
01221 
01222 
01223 ps_mgau_t *
01224 s2_semi_mgau_init(acmod_t *acmod)
01225 {
01226     s2_semi_mgau_t *s;
01227     ps_mgau_t *ps;
01228     char const *sendump_path;
01229     int i;
01230 
01231     s = ckd_calloc(1, sizeof(*s));
01232     s->config = acmod->config;
01233 
01234     s->lmath = logmath_retain(acmod->lmath);
01235     /* Log-add table. */
01236     s->lmath_8b = logmath_init(logmath_get_base(acmod->lmath), SENSCR_SHIFT, TRUE);
01237     if (s->lmath_8b == NULL)
01238         goto error_out;
01239     /* Ensure that it is only 8 bits wide so that fast_logmath_add() works. */
01240     if (logmath_get_width(s->lmath_8b) != 1) {
01241         E_ERROR("Log base %f is too small to represent add table in 8 bits\n",
01242                 logmath_get_base(s->lmath_8b));
01243         goto error_out;
01244     }
01245 
01246     /* Read means and variances. */
01247     if ((s->g = gauden_init(cmd_ln_str_r(s->config, "-mean"),
01248                             cmd_ln_str_r(s->config, "-var"),
01249                             cmd_ln_float32_r(s->config, "-varfloor"),
01250                             s->lmath)) == NULL)
01251         goto error_out;
01252     /* Currently only a single codebook is supported. */
01253     if (s->g->n_mgau != 1)
01254         goto error_out;
01255     /* FIXME: maintaining pointers for convenience for now */
01256     s->means = s->g->mean[0];
01257     s->vars = s->g->var[0];
01258     s->dets = s->g->det[0];
01259     s->veclen = s->g->featlen;    
01260     /* Verify n_feat and veclen, against acmod. */
01261     s->n_feat = s->g->n_feat;
01262     if (s->n_feat != feat_dimension1(acmod->fcb)) {
01263         E_ERROR("Number of streams does not match: %d != %d\n",
01264                 s->n_feat, feat_dimension(acmod->fcb));
01265         goto error_out;
01266     }
01267     for (i = 0; i < s->n_feat; ++i) {
01268         if (s->veclen[i] != feat_dimension2(acmod->fcb, i)) {
01269             E_ERROR("Dimension of stream %d does not match: %d != %d\n",
01270                     s->veclen[i], feat_dimension2(acmod->fcb, i));
01271             goto error_out;
01272         }
01273     }
01274     s->n_density = s->g->n_density;
01275     /* Read mixture weights */
01276     if ((sendump_path = cmd_ln_str_r(s->config, "-sendump"))) {
01277         if (read_sendump(s, acmod->mdef, sendump_path) < 0) {
01278             goto error_out;
01279         }
01280     }
01281     else {
01282         if (read_mixw(s, cmd_ln_str_r(s->config, "-mixw"),
01283                       cmd_ln_float32_r(s->config, "-mixwfloor")) < 0) {
01284             goto error_out;
01285         }
01286     }
01287     s->ds_ratio = cmd_ln_int32_r(s->config, "-ds");
01288 
01289     /* Determine top-N for each feature */
01290     s->topn_beam = ckd_calloc(s->n_feat, sizeof(*s->topn_beam));
01291     s->max_topn = cmd_ln_int32_r(s->config, "-topn");
01292     split_topn(cmd_ln_str_r(s->config, "-topn_beam"), s->topn_beam, s->n_feat);
01293     E_INFO("Maximum top-N: %d ", s->max_topn);
01294     E_INFOCONT("Top-N beams:");
01295     for (i = 0; i < s->n_feat; ++i) {
01296         E_INFOCONT(" %d", s->topn_beam[i]);
01297     }
01298     E_INFOCONT("\n");
01299 
01300     /* Top-N scores from recent frames */
01301     s->n_topn_hist = cmd_ln_int32_r(s->config, "-pl_window") + 2;
01302     s->topn_hist = (vqFeature_t ***)
01303         ckd_calloc_3d(s->n_topn_hist, s->n_feat, s->max_topn,
01304                       sizeof(***s->topn_hist));
01305     s->topn_hist_n = ckd_calloc_2d(s->n_topn_hist, s->n_feat,
01306                                    sizeof(**s->topn_hist_n));
01307     for (i = 0; i < s->n_topn_hist; ++i) {
01308         int j;
01309         for (j = 0; j < s->n_feat; ++j) {
01310             int k;
01311             for (k = 0; k < s->max_topn; ++k) {
01312                 s->topn_hist[i][j][k].score = WORST_DIST;
01313                 s->topn_hist[i][j][k].codeword = k;
01314             }
01315         }
01316     }
01317 
01318     ps = (ps_mgau_t *)s;
01319     ps->vt = &s2_semi_mgau_funcs;
01320     return ps;
01321 error_out:
01322     s2_semi_mgau_free(ps_mgau_base(s));
01323     return NULL;
01324 }
01325 
01326 int
01327 s2_semi_mgau_mllr_transform(ps_mgau_t *ps,
01328                             ps_mllr_t *mllr)
01329 {
01330     s2_semi_mgau_t *s = (s2_semi_mgau_t *)ps;
01331     return gauden_mllr_transform(s->g, mllr, s->config);
01332 }
01333 
01334 void
01335 s2_semi_mgau_free(ps_mgau_t *ps)
01336 {
01337     s2_semi_mgau_t *s = (s2_semi_mgau_t *)ps;
01338 
01339     logmath_free(s->lmath);
01340     logmath_free(s->lmath_8b);
01341     if (s->sendump_mmap) {
01342         ckd_free_2d(s->mixw); 
01343         mmio_file_unmap(s->sendump_mmap);
01344     }
01345     else {
01346         ckd_free_3d(s->mixw);
01347     }
01348     gauden_free(s->g);
01349     ckd_free(s->topn_beam);
01350     ckd_free_2d(s->topn_hist_n);
01351     ckd_free_3d((void **)s->topn_hist);
01352     ckd_free(s);
01353 }

Generated on Sat Jan 8 2011 for PocketSphinx by  doxygen 1.7.1