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

src/libpocketsphinx/hmm.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 
00042 /* System headers. */
00043 #include <assert.h>
00044 #include <stdlib.h>
00045 #include <string.h>
00046 #include <limits.h>
00047 
00048 /* SphinxBase headers. */
00049 #include <ckd_alloc.h>
00050 #include <err.h>
00051 
00052 /* Local headers. */
00053 #include "hmm.h"
00054 
00055 hmm_context_t *
00056 hmm_context_init(int32 n_emit_state,
00057                  int32 ** const *tp,
00058                  int16 const *senscore,
00059                  int16 * const *sseq)
00060 {
00061     hmm_context_t *ctx;
00062 
00063     assert(n_emit_state > 0);
00064     if (n_emit_state > HMM_MAX_NSTATE) {
00065         E_ERROR("Number of emitting states must be <= 5\n");
00066         return NULL;
00067     }
00068 
00069     ctx = ckd_calloc(1, sizeof(*ctx));
00070     ctx->n_emit_state = n_emit_state;
00071     ctx->tp = tp;
00072     ctx->senscore = senscore;
00073     ctx->sseq = sseq;
00074     ctx->st_sen_scr = ckd_calloc(n_emit_state, sizeof(*ctx->st_sen_scr));
00075     ctx->mpx_ssid_alloc = listelem_alloc_init(sizeof(int32) * ctx->n_emit_state);
00076 
00077     return ctx;
00078 }
00079 
00080 void
00081 hmm_context_free(hmm_context_t *ctx)
00082 {
00083     listelem_alloc_free(ctx->mpx_ssid_alloc);
00084     ckd_free(ctx->st_sen_scr);
00085     ckd_free(ctx);
00086 }
00087 
00088 void
00089 hmm_init(hmm_context_t *ctx, hmm_t *hmm, int mpx, int ssid, int tmatid)
00090 {
00091     /* Watch for integer overflows in ssids (shouldn't happen anymore) */
00092     assert(ssid >= -1);
00093     hmm->ctx = ctx;
00094     hmm->mpx = mpx;
00095     hmm->n_emit_state = ctx->n_emit_state;
00096     if (mpx) {
00097         hmm->s.mpx_ssid = listelem_malloc(ctx->mpx_ssid_alloc);
00098         memset(hmm->s.mpx_ssid, -1, sizeof(*hmm->s.mpx_ssid) * hmm_n_emit_state(hmm));
00099         hmm->s.mpx_ssid[0] = ssid;
00100     }
00101     else {
00102         hmm->s.ssid = ssid;
00103     }
00104     hmm->tmatid = tmatid;
00105     hmm_clear(hmm);
00106 }
00107 
00108 void
00109 hmm_deinit(hmm_t *hmm)
00110 {
00111     hmm_context_t *ctx = hmm->ctx;
00112 
00113     if (hmm->mpx)
00114         listelem_free(ctx->mpx_ssid_alloc, hmm->s.mpx_ssid);
00115 }
00116 
00117 void
00118 hmm_dump(hmm_t * hmm,
00119          FILE * fp)
00120 {
00121     int32 i;
00122 
00123     if (hmm_is_mpx(hmm)) {
00124         fprintf(fp, "MPX   ");
00125         for (i = 0; i < hmm_n_emit_state(hmm); i++)
00126             fprintf(fp, " %11d", hmm_senid(hmm, i));
00127         fprintf(fp, " ( ");
00128         for (i = 0; i < hmm_n_emit_state(hmm); i++)
00129             fprintf(fp, "%d ", hmm_ssid(hmm, i));
00130         fprintf(fp, ")\n");
00131     }
00132     else {
00133         fprintf(fp, "SSID  ");
00134         for (i = 0; i < hmm_n_emit_state(hmm); i++)
00135             fprintf(fp, " %11d", hmm_senid(hmm, i));
00136         fprintf(fp, " (%d)\n", hmm_ssid(hmm, 0));
00137     }
00138 
00139     if (hmm->ctx->senscore) {
00140         fprintf(fp, "SENSCR");
00141         for (i = 0; i < hmm_n_emit_state(hmm); i++)
00142             fprintf(fp, " %11d", hmm_senscr(hmm, i));
00143         fprintf(fp, "\n");
00144     }
00145 
00146     fprintf(fp, "SCORES %11d", hmm_in_score(hmm));
00147     for (i = 1; i < hmm_n_emit_state(hmm); i++)
00148         fprintf(fp, " %11d", hmm_score(hmm, i));
00149     fprintf(fp, " %11d", hmm_out_score(hmm));
00150     fprintf(fp, "\n");
00151 
00152     fprintf(fp, "HISTID %11d", hmm_in_history(hmm));
00153     for (i = 1; i < hmm_n_emit_state(hmm); i++)
00154         fprintf(fp, " %11d", hmm_history(hmm, i));
00155     fprintf(fp, " %11d", hmm_out_history(hmm));
00156     fprintf(fp, "\n");
00157 
00158     if (hmm_in_score(hmm) > 0)
00159         fprintf(fp,
00160                 "ALERT!! The input score %d is large than 0. Probably wrap around.\n",
00161                 hmm_in_score(hmm));
00162     if (hmm_out_score(hmm) > 0)
00163         fprintf(fp,
00164                 "ALERT!! The output score %d is large than 0. Probably wrap around\n.",
00165                 hmm_out_score(hmm));
00166 
00167     fflush(fp);
00168 }
00169 
00170 
00171 void
00172 hmm_clear_scores(hmm_t * h)
00173 {
00174     int32 i;
00175 
00176     hmm_in_score(h) = WORST_SCORE;
00177     for (i = 1; i < hmm_n_emit_state(h); i++)
00178         hmm_score(h, i) = WORST_SCORE;
00179     hmm_out_score(h) = WORST_SCORE;
00180 
00181     h->bestscore = WORST_SCORE;
00182 }
00183 
00184 void
00185 hmm_clear(hmm_t * h)
00186 {
00187     int32 i;
00188 
00189     hmm_in_score(h) = WORST_SCORE;
00190     hmm_in_history(h) = -1;
00191     for (i = 1; i < hmm_n_emit_state(h); i++) {
00192         hmm_score(h, i) = WORST_SCORE;
00193         hmm_history(h, i) = -1;
00194     }
00195     hmm_out_score(h) = WORST_SCORE;
00196     hmm_out_history(h) = -1;
00197 
00198     h->bestscore = WORST_SCORE;
00199     h->frame = -1;
00200 }
00201 
00202 void
00203 hmm_enter(hmm_t *h, int32 score, int32 histid, int frame)
00204 {
00205     hmm_in_score(h) = score;
00206     hmm_in_history(h) = histid;
00207     hmm_frame(h) = frame;
00208 }
00209 
00210 void
00211 hmm_normalize(hmm_t *h, int32 bestscr)
00212 {
00213     int32 i;
00214 
00215     for (i = 0; i < hmm_n_emit_state(h); i++) {
00216         if (hmm_score(h, i) > WORST_SCORE)
00217             hmm_score(h, i) -= bestscr;
00218     }
00219     if (hmm_out_score(h) > WORST_SCORE)
00220         hmm_out_score(h) -= bestscr;
00221 }
00222 
00223 #define hmm_tprob_5st(i, j) (tp[(i)*6+(j)])
00224 #define nonmpx_senscr(i) (-senscore[sseq[i]] << 10)
00225 
00226 static int32
00227 hmm_vit_eval_5st_lr(hmm_t * hmm)
00228 {
00229     int16 const *senscore = hmm->ctx->senscore;
00230     int32 const *tp = hmm->ctx->tp[hmm->tmatid][0];
00231     /* Cache problem here! */
00232     int16 const *sseq = hmm->ctx->sseq[hmm_ssid(hmm, 0)];
00233     int32 s5, s4, s3, s2, s1, s0, t2, t1, t0, bestScore;
00234 
00235     /* It was the best of scores, it was the worst of scores. */
00236     bestScore = WORST_SCORE;
00237 
00238     /* Cache problem here! */
00239     s4 = hmm_score(hmm, 4) + nonmpx_senscr(4);
00240     s3 = hmm_score(hmm, 3) + nonmpx_senscr(3);
00241     /* Transitions into non-emitting state 5 */
00242     if (s3 > WORST_SCORE) {
00243         t1 = s4 + hmm_tprob_5st(4, 5);
00244         t2 = s3 + hmm_tprob_5st(3, 5);
00245         if (t1 > t2) {
00246             s5 = t1;
00247             hmm_out_history(hmm)  = hmm_history(hmm, 4);
00248         } else {
00249             s5 = t2;
00250             hmm_out_history(hmm)  = hmm_history(hmm, 3);
00251         }
00252         if (s5 < WORST_SCORE) s5 = WORST_SCORE;
00253         hmm_out_score(hmm) = s5;
00254         bestScore = s5;
00255     }
00256 
00257     s2 = hmm_score(hmm, 2) + nonmpx_senscr(2);
00258     /* All transitions into state 4 */
00259     if (s2 > WORST_SCORE) {
00260         t0 = s4 + hmm_tprob_5st(4, 4);
00261         t1 = s3 + hmm_tprob_5st(3, 4);
00262         t2 = s2 + hmm_tprob_5st(2, 4);
00263         if (t0 > t1) {
00264             if (t2 > t0) {
00265                 s4 = t2;
00266                 hmm_history(hmm, 4)  = hmm_history(hmm, 2);
00267             } else
00268                 s4 = t0;
00269         } else {
00270             if (t2 > t1) {
00271                 s4 = t2;
00272                 hmm_history(hmm, 4)  = hmm_history(hmm, 2);
00273             } else {
00274                 s4 = t1;
00275                 hmm_history(hmm, 4)  = hmm_history(hmm, 3);
00276             }
00277         }
00278         if (s4 < WORST_SCORE) s4 = WORST_SCORE;
00279         if (s4 > bestScore) bestScore = s4;
00280         hmm_score(hmm, 4) = s4;
00281     }
00282 
00283     s1 = hmm_score(hmm, 1) + nonmpx_senscr(1);
00284     /* All transitions into state 3 */
00285     if (s1 > WORST_SCORE) {
00286         t0 = s3 + hmm_tprob_5st(3, 3);
00287         t1 = s2 + hmm_tprob_5st(2, 3);
00288         t2 = s1 + hmm_tprob_5st(1, 3);
00289         if (t0 > t1) {
00290             if (t2 > t0) {
00291                 s3 = t2;
00292                 hmm_history(hmm, 3)  = hmm_history(hmm, 1);
00293             } else
00294                 s3 = t0;
00295         } else {
00296             if (t2 > t1) {
00297                 s3 = t2;
00298                 hmm_history(hmm, 3)  = hmm_history(hmm, 1);
00299             } else {
00300                 s3 = t1;
00301                 hmm_history(hmm, 3)  = hmm_history(hmm, 2);
00302             }
00303         }
00304         if (s3 < WORST_SCORE) s3 = WORST_SCORE;
00305         if (s3 > bestScore) bestScore = s3;
00306         hmm_score(hmm, 3) = s3;
00307     }
00308 
00309     s0 = hmm_in_score(hmm) + nonmpx_senscr(0);
00310     /* All transitions into state 2 (state 0 is always active) */
00311     t0 = s2 + hmm_tprob_5st(2, 2);
00312     t1 = s1 + hmm_tprob_5st(1, 2);
00313     t2 = s0 + hmm_tprob_5st(0, 2);
00314     if (t0 > t1) {
00315         if (t2 > t0) {
00316             s2 = t2;
00317             hmm_history(hmm, 2)  = hmm_in_history(hmm);
00318         } else
00319             s2 = t0;
00320     } else {
00321         if (t2 > t1) {
00322             s2 = t2;
00323             hmm_history(hmm, 2)  = hmm_in_history(hmm);
00324         } else {
00325             s2 = t1;
00326             hmm_history(hmm, 2)  = hmm_history(hmm, 1);
00327         }
00328     }
00329     if (s2 < WORST_SCORE) s2 = WORST_SCORE;
00330     if (s2 > bestScore) bestScore = s2;
00331     hmm_score(hmm, 2) = s2;
00332 
00333 
00334     /* All transitions into state 1 */
00335     t0 = s1 + hmm_tprob_5st(1, 1);
00336     t1 = s0 + hmm_tprob_5st(0, 1);
00337     if (t0 > t1) {
00338         s1 = t0;
00339     } else {
00340         s1 = t1;
00341         hmm_history(hmm, 1)  = hmm_in_history(hmm);
00342     }
00343     if (s1 < WORST_SCORE) s1 = WORST_SCORE;
00344     if (s1 > bestScore) bestScore = s1;
00345     hmm_score(hmm, 1) = s1;
00346 
00347     /* All transitions into state 0 */
00348     s0 = s0 + hmm_tprob_5st(0, 0);
00349     if (s0 < WORST_SCORE) s0 = WORST_SCORE;
00350     if (s0 > bestScore) bestScore = s0;
00351     hmm_in_score(hmm) = s0;
00352 
00353     hmm_bestscore(hmm) = bestScore;
00354     return bestScore;
00355 }
00356 
00357 #define mpx_senid(st) sseq[ssid[st]][st]
00358 #define mpx_senscr(st) (-senscore[mpx_senid(st)] << 10)
00359 
00360 static int32
00361 hmm_vit_eval_5st_lr_mpx(hmm_t * hmm)
00362 {
00363     const int32 *tp = hmm->ctx->tp[hmm->tmatid][0];
00364     const int16 *senscore = hmm->ctx->senscore;
00365     int16 * const *sseq = hmm->ctx->sseq;
00366     int32 *ssid = hmm->s.mpx_ssid;
00367     int32 bestScore;
00368     int32 s5, s4, s3, s2, s1, s0, t2, t1, t0;
00369 
00370     /* Don't propagate WORST_SCORE */
00371     if (ssid[4] == -1)
00372         s4 = t1 = WORST_SCORE;
00373     else {
00374         s4 = hmm_score(hmm, 4) + mpx_senscr(4);
00375         t1 = s4 + hmm_tprob_5st(4, 5);
00376     }
00377     if (ssid[3] == -1)
00378         s3 = t2 = WORST_SCORE;
00379     else {
00380         s3 = hmm_score(hmm, 3) + mpx_senscr(3);
00381         t2 = s3 + hmm_tprob_5st(3, 5);
00382     }
00383     if (t1 > t2) {
00384         s5 = t1;
00385         hmm_out_history(hmm) = hmm_history(hmm, 4);
00386     }
00387     else {
00388         s5 = t2;
00389         hmm_out_history(hmm) = hmm_history(hmm, 3);
00390     }
00391     if (s5 < WORST_SCORE) s5 = WORST_SCORE;
00392     hmm_out_score(hmm) = s5;
00393     bestScore = s5;
00394 
00395     /* Don't propagate WORST_SCORE */
00396     if (ssid[2] == -1)
00397         s2 = t2 = WORST_SCORE;
00398     else {
00399         s2 = hmm_score(hmm, 2) + mpx_senscr(2);
00400         t2 = s2 + hmm_tprob_5st(2, 4);
00401     }
00402 
00403     t0 = t1 = WORST_SCORE;
00404     if (s4 != WORST_SCORE)
00405         t0 = s4 + hmm_tprob_5st(4, 4);
00406     if (s3 != WORST_SCORE)
00407         t1 = s3 + hmm_tprob_5st(3, 4);
00408     if (t0 > t1) {
00409         if (t2 > t0) {
00410             s4 = t2;
00411             hmm_history(hmm, 4) = hmm_history(hmm, 2);
00412             ssid[4] = ssid[2];
00413         }
00414         else
00415             s4 = t0;
00416     }
00417     else {
00418         if (t2 > t1) {
00419             s4 = t2;
00420             hmm_history(hmm, 4) = hmm_history(hmm, 2);
00421             ssid[4] = ssid[2];
00422         }
00423         else {
00424             s4 = t1;
00425             hmm_history(hmm, 4) = hmm_history(hmm, 3);
00426             ssid[4] = ssid[3];
00427         }
00428     }
00429     if (s4 < WORST_SCORE) s4 = WORST_SCORE;
00430     if (s4 > bestScore)
00431         bestScore = s4;
00432     hmm_score(hmm, 4) = s4;
00433 
00434     /* Don't propagate WORST_SCORE */
00435     if (ssid[1] == -1)
00436         s1 = t2 = WORST_SCORE;
00437     else {
00438         s1 = hmm_score(hmm, 1) + mpx_senscr(1);
00439         t2 = s1 + hmm_tprob_5st(1, 3);
00440     }
00441     t0 = t1 = WORST_SCORE;
00442     if (s3 != WORST_SCORE)
00443         t0 = s3 + hmm_tprob_5st(3, 3);
00444     if (s2 != WORST_SCORE)
00445         t1 = s2 + hmm_tprob_5st(2, 3);
00446     if (t0 > t1) {
00447         if (t2 > t0) {
00448             s3 = t2;
00449             hmm_history(hmm, 3) = hmm_history(hmm, 1);
00450             ssid[3] = ssid[1];
00451         }
00452         else
00453             s3 = t0;
00454     }
00455     else {
00456         if (t2 > t1) {
00457             s3 = t2;
00458             hmm_history(hmm, 3) = hmm_history(hmm, 1);
00459             ssid[3] = ssid[1];
00460         }
00461         else {
00462             s3 = t1;
00463             hmm_history(hmm, 3) = hmm_history(hmm, 2);
00464             ssid[3] = ssid[2];
00465         }
00466     }
00467     if (s3 < WORST_SCORE) s3 = WORST_SCORE;
00468     if (s3 > bestScore) bestScore = s3;
00469     hmm_score(hmm, 3) = s3;
00470 
00471     /* State 0 is always active */
00472     s0 = hmm_in_score(hmm) + mpx_senscr(0);
00473 
00474     /* Don't propagate WORST_SCORE */
00475     t0 = t1 = WORST_SCORE;
00476     if (s2 != WORST_SCORE)
00477         t0 = s2 + hmm_tprob_5st(2, 2);
00478     if (s1 != WORST_SCORE)
00479         t1 = s1 + hmm_tprob_5st(1, 2);
00480     t2 = s0 + hmm_tprob_5st(0, 2);
00481     if (t0 > t1) {
00482         if (t2 > t0) {
00483             s2 = t2;
00484             hmm_history(hmm, 2) = hmm_in_history(hmm);
00485             ssid[2] = ssid[0];
00486         }
00487         else
00488             s2 = t0;
00489     }
00490     else {
00491         if (t2 > t1) {
00492             s2 = t2;
00493             hmm_history(hmm, 2) = hmm_in_history(hmm);
00494             ssid[2] = ssid[0];
00495         }
00496         else {
00497             s2 = t1;
00498             hmm_history(hmm, 2) = hmm_history(hmm, 1);
00499             ssid[2] = ssid[1];
00500         }
00501     }
00502     if (s2 < WORST_SCORE) s2 = WORST_SCORE;
00503     if (s2 > bestScore) bestScore = s2;
00504     hmm_score(hmm, 2) = s2;
00505 
00506     /* Don't propagate WORST_SCORE */
00507     t0 = WORST_SCORE;
00508     if (s1 != WORST_SCORE)
00509         t0 = s1 + hmm_tprob_5st(1, 1);
00510     t1 = s0 + hmm_tprob_5st(0, 1);
00511     if (t0 > t1) {
00512         s1 = t0;
00513     }
00514     else {
00515         s1 = t1;
00516         hmm_history(hmm, 1) = hmm_in_history(hmm);
00517         ssid[1] = ssid[0];
00518     }
00519     if (s1 < WORST_SCORE) s1 = WORST_SCORE;
00520     if (s1 > bestScore) bestScore = s1;
00521     hmm_score(hmm, 1) = s1;
00522 
00523     s0 += hmm_tprob_5st(0, 0);
00524     if (s0 < WORST_SCORE) s0 = WORST_SCORE;
00525     if (s0 > bestScore) bestScore = s0;
00526     hmm_in_score(hmm) = s0;
00527 
00528     hmm_bestscore(hmm) = bestScore;
00529     return bestScore;
00530 }
00531 
00532 #define hmm_tprob_3st(i, j) (tp[(i)*4+(j)])
00533 
00534 static int32
00535 hmm_vit_eval_3st_lr(hmm_t * hmm)
00536 {
00537     const int16 *senscore = hmm->ctx->senscore;
00538     const int32 *tp = hmm->ctx->tp[hmm->tmatid][0];
00539     const int16 *sseq = hmm->ctx->sseq[hmm_ssid(hmm, 0)];
00540     int32 s3, s2, s1, s0, t2, t1, t0, bestScore;
00541 
00542     s2 = hmm_score(hmm, 2) + nonmpx_senscr(2);
00543     s1 = hmm_score(hmm, 1) + nonmpx_senscr(1);
00544     s0 = hmm_in_score(hmm) + nonmpx_senscr(0);
00545 
00546     /* It was the best of scores, it was the worst of scores. */
00547     bestScore = WORST_SCORE;
00548     t2 = INT_MIN; /* Not used unless skipstate is true */
00549 
00550     /* Transitions into non-emitting state 3 */
00551     if (s1 > WORST_SCORE) {
00552         t1 = s2 + hmm_tprob_3st(2, 3);
00553         if (hmm_tprob_3st(1,3) > WORST_SCORE)
00554             t2 = s1 + hmm_tprob_3st(1, 3);
00555         if (t1 > t2) {
00556             s3 = t1;
00557             hmm_out_history(hmm)  = hmm_history(hmm, 2);
00558         } else {
00559             s3 = t2;
00560             hmm_out_history(hmm)  = hmm_history(hmm, 1);
00561         }
00562         if (s3 < WORST_SCORE) s3 = WORST_SCORE;
00563         hmm_out_score(hmm) = s3;
00564         bestScore = s3;
00565     }
00566 
00567     /* All transitions into state 2 (state 0 is always active) */
00568     t0 = s2 + hmm_tprob_3st(2, 2);
00569     t1 = s1 + hmm_tprob_3st(1, 2);
00570     if (hmm_tprob_3st(0, 2) > WORST_SCORE)
00571         t2 = s0 + hmm_tprob_3st(0, 2);
00572     if (t0 > t1) {
00573         if (t2 > t0) {
00574             s2 = t2;
00575             hmm_history(hmm, 2)  = hmm_in_history(hmm);
00576         } else
00577             s2 = t0;
00578     } else {
00579         if (t2 > t1) {
00580             s2 = t2;
00581             hmm_history(hmm, 2)  = hmm_in_history(hmm);
00582         } else {
00583             s2 = t1;
00584             hmm_history(hmm, 2)  = hmm_history(hmm, 1);
00585         }
00586     }
00587     if (s2 < WORST_SCORE) s2 = WORST_SCORE;
00588     if (s2 > bestScore) bestScore = s2;
00589     hmm_score(hmm, 2) = s2;
00590 
00591     /* All transitions into state 1 */
00592     t0 = s1 + hmm_tprob_3st(1, 1);
00593     t1 = s0 + hmm_tprob_3st(0, 1);
00594     if (t0 > t1) {
00595         s1 = t0;
00596     } else {
00597         s1 = t1;
00598         hmm_history(hmm, 1)  = hmm_in_history(hmm);
00599     }
00600     if (s1 < WORST_SCORE) s1 = WORST_SCORE;
00601     if (s1 > bestScore) bestScore = s1;
00602     hmm_score(hmm, 1) = s1;
00603 
00604     /* All transitions into state 0 */
00605     s0 = s0 + hmm_tprob_3st(0, 0);
00606     if (s0 < WORST_SCORE) s0 = WORST_SCORE;
00607     if (s0 > bestScore) bestScore = s0;
00608     hmm_in_score(hmm) = s0;
00609 
00610     hmm_bestscore(hmm) = bestScore;
00611     return bestScore;
00612 }
00613 
00614 static int32
00615 hmm_vit_eval_3st_lr_mpx(hmm_t * hmm)
00616 {
00617     int32 const *tp = hmm->ctx->tp[hmm->tmatid][0];
00618     int16 const *senscore = hmm->ctx->senscore;
00619     int16 * const *sseq = hmm->ctx->sseq;
00620     int32 *ssid = hmm->s.mpx_ssid;
00621     int32 bestScore;
00622     int32 s3, s2, s1, s0, t2, t1, t0;
00623 
00624     /* Don't propagate WORST_SCORE */
00625     t2 = INT_MIN; /* Not used unless skipstate is true */
00626     if (ssid[2] == -1)
00627         s2 = t1 = WORST_SCORE;
00628     else {
00629         s2 = hmm_score(hmm, 2) + mpx_senscr(2);
00630         t1 = s2 + hmm_tprob_3st(2, 3);
00631     }
00632     if (ssid[1] == -1)
00633         s1 = WORST_SCORE;
00634     else {
00635         s1 = hmm_score(hmm, 1) + mpx_senscr(1);
00636         t2 = s1 + hmm_tprob_3st(1, 3);
00637     }
00638     if (t1 > t2) {
00639         s3 = t1;
00640         hmm_out_history(hmm) = hmm_history(hmm, 2);
00641     }
00642     else {
00643         s3 = t2;
00644         hmm_out_history(hmm) = hmm_history(hmm, 1);
00645     }
00646     if (s3 < WORST_SCORE) s3 = WORST_SCORE;
00647     hmm_out_score(hmm) = s3;
00648     bestScore = s3;
00649 
00650     /* State 0 is always active */
00651     s0 = hmm_in_score(hmm) + mpx_senscr(0);
00652 
00653     /* Don't propagate WORST_SCORE */
00654     t0 = t1 = WORST_SCORE;
00655     if (s2 != WORST_SCORE)
00656         t0 = s2 + hmm_tprob_3st(2, 2);
00657     if (s1 != WORST_SCORE)
00658         t1 = s1 + hmm_tprob_3st(1, 2);
00659     if (hmm_tprob_3st(0,2) > WORST_SCORE)
00660         t2 = s0 + hmm_tprob_3st(0, 2);
00661     if (t0 > t1) {
00662         if (t2 > t0) {
00663             s2 = t2;
00664             hmm_history(hmm, 2) = hmm_in_history(hmm);
00665             ssid[2] = ssid[0];
00666         }
00667         else
00668             s2 = t0;
00669     }
00670     else {
00671         if (t2 > t1) {
00672             s2 = t2;
00673             hmm_history(hmm, 2) = hmm_in_history(hmm);
00674             ssid[2] = ssid[0];
00675         }
00676         else {
00677             s2 = t1;
00678             hmm_history(hmm, 2) = hmm_history(hmm, 1);
00679             ssid[2] = ssid[1];
00680         }
00681     }
00682     if (s2 < WORST_SCORE) s2 = WORST_SCORE;
00683     if (s2 > bestScore) bestScore = s2;
00684     hmm_score(hmm, 2) = s2;
00685 
00686     /* Don't propagate WORST_SCORE */
00687     t0 = WORST_SCORE;
00688     if (s1 != WORST_SCORE)
00689         t0 = s1 + hmm_tprob_3st(1, 1);
00690     t1 = s0 + hmm_tprob_3st(0, 1);
00691     if (t0 > t1) {
00692         s1 = t0;
00693     }
00694     else {
00695         s1 = t1;
00696         hmm_history(hmm, 1) = hmm_in_history(hmm);
00697         ssid[1] = ssid[0];
00698     }
00699     if (s1 < WORST_SCORE) s1 = WORST_SCORE;
00700     if (s1 > bestScore) bestScore = s1;
00701     hmm_score(hmm, 1) = s1;
00702 
00703     /* State 0 is always active */
00704     s0 += hmm_tprob_3st(0, 0);
00705     if (s0 < WORST_SCORE) s0 = WORST_SCORE;
00706     if (s0 > bestScore) bestScore = s0;
00707     hmm_in_score(hmm) = s0;
00708 
00709     hmm_bestscore(hmm) = bestScore;
00710     return bestScore;
00711 }
00712 
00713 static int32
00714 hmm_vit_eval_anytopo(hmm_t * hmm)
00715 {
00716     hmm_context_t *ctx = hmm->ctx;
00717     int32 to, from, bestfrom;
00718     int32 newscr, scr, bestscr;
00719     int final_state;
00720 
00721     /* Compute previous state-score + observation output prob for each emitting state */
00722     ctx->st_sen_scr[0] = hmm_in_score(hmm) + hmm_senscr(hmm, 0);
00723     for (from = 1; from < hmm_n_emit_state(hmm); ++from) {
00724         if ((ctx->st_sen_scr[from] =
00725              hmm_score(hmm, from) + hmm_senscr(hmm, from)) < WORST_SCORE)
00726             ctx->st_sen_scr[from] = WORST_SCORE;
00727     }
00728 
00729     /* FIXME/TODO: Use the BLAS for all this. */
00730     /* Evaluate final-state first, which does not have a self-transition */
00731     final_state = hmm_n_emit_state(hmm);
00732     to = final_state;
00733     scr = WORST_SCORE;
00734     bestfrom = -1;
00735     for (from = to - 1; from >= 0; --from) {
00736         if ((hmm_tprob(hmm, from, to) > WORST_SCORE) &&
00737             ((newscr = ctx->st_sen_scr[from]
00738               + hmm_tprob(hmm, from, to)) > scr)) {
00739             scr = newscr;
00740             bestfrom = from;
00741         }
00742     }
00743     hmm_out_score(hmm) = scr;
00744     if (bestfrom >= 0)
00745         hmm_out_history(hmm) = hmm_history(hmm, bestfrom);
00746     bestscr = scr;
00747 
00748     /* Evaluate all other states, which might have self-transitions */
00749     for (to = final_state - 1; to >= 0; --to) {
00750         /* Score from self-transition, if any */
00751         scr =
00752             (hmm_tprob(hmm, to, to) > WORST_SCORE)
00753             ? ctx->st_sen_scr[to] + hmm_tprob(hmm, to, to)
00754             : WORST_SCORE;
00755 
00756         /* Scores from transitions from other states */
00757         bestfrom = -1;
00758         for (from = to - 1; from >= 0; --from) {
00759             if ((hmm_tprob(hmm, from, to) > WORST_SCORE) &&
00760                 ((newscr = ctx->st_sen_scr[from]
00761                   + hmm_tprob(hmm, from, to)) > scr)) {
00762                 scr = newscr;
00763                 bestfrom = from;
00764             }
00765         }
00766 
00767         /* Update new result for state to */
00768         if (to == 0) {
00769             hmm_in_score(hmm) = scr;
00770             if (bestfrom >= 0)
00771                 hmm_in_history(hmm) = hmm_history(hmm, bestfrom);
00772         }
00773         else {
00774             hmm_score(hmm, to) = scr;
00775             if (bestfrom >= 0)
00776                 hmm_history(hmm, to) = hmm_history(hmm, bestfrom);
00777         }
00778         if (bestfrom >= 0 && hmm_is_mpx(hmm))
00779             hmm->s.mpx_ssid[to] = hmm->s.mpx_ssid[bestfrom];
00780 
00781         if (bestscr < scr)
00782             bestscr = scr;
00783     }
00784 
00785     hmm_bestscore(hmm) = bestscr;
00786     return bestscr;
00787 }
00788 
00789 int32
00790 hmm_vit_eval(hmm_t * hmm)
00791 {
00792     if (hmm_is_mpx(hmm)) {
00793         if (hmm_n_emit_state(hmm) == 5)
00794             return hmm_vit_eval_5st_lr_mpx(hmm);
00795         else if (hmm_n_emit_state(hmm) == 3)
00796             return hmm_vit_eval_3st_lr_mpx(hmm);
00797         else
00798             return hmm_vit_eval_anytopo(hmm);
00799     }
00800     else {
00801         if (hmm_n_emit_state(hmm) == 5)
00802             return hmm_vit_eval_5st_lr(hmm);
00803         else if (hmm_n_emit_state(hmm) == 3)
00804             return hmm_vit_eval_3st_lr(hmm);
00805         else
00806             return hmm_vit_eval_anytopo(hmm);
00807     }
00808 }
00809 
00810 int32
00811 hmm_dump_vit_eval(hmm_t * hmm, FILE * fp)
00812 {
00813     int32 bs = 0;
00814 
00815     if (fp) {
00816         fprintf(fp, "BEFORE:\n");
00817         hmm_dump(hmm, fp);
00818     }
00819     bs = hmm_vit_eval(hmm);
00820     if (fp) {
00821         fprintf(fp, "AFTER:\n");
00822         hmm_dump(hmm, fp);
00823     }
00824 
00825     return bs;
00826 }

Generated on Thu Jan 27 2011 for PocketSphinx by  doxygen 1.7.1