PocketSphinx  5prealpha
hmm.c
1 /* -*- c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* ====================================================================
3  * Copyright (c) 1999-2004 Carnegie Mellon University. All rights
4  * reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in
15  * the documentation and/or other materials provided with the
16  * distribution.
17  *
18  * This work was supported in part by funding from the Defense Advanced
19  * Research Projects Agency and the National Science Foundation of the
20  * United States of America, and the CMU Sphinx Speech Consortium.
21  *
22  * THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY ``AS IS'' AND
23  * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
24  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY
26  * NOR ITS EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  *
34  * ====================================================================
35  *
36  */
37 
42 /* System headers. */
43 #include <assert.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <limits.h>
47 
48 /* SphinxBase headers. */
49 #include <sphinxbase/ckd_alloc.h>
50 #include <sphinxbase/err.h>
51 
52 /* Local headers. */
53 #include "hmm.h"
54 
56 hmm_context_init(int32 n_emit_state,
57  uint8 ** const *tp,
58  int16 const *senscore,
59  uint16 * const *sseq)
60 {
61  hmm_context_t *ctx;
62 
63  assert(n_emit_state > 0);
64  if (n_emit_state > HMM_MAX_NSTATE) {
65  E_ERROR("Number of emitting states must be <= %d\n", HMM_MAX_NSTATE);
66  return NULL;
67  }
68 
69  ctx = ckd_calloc(1, sizeof(*ctx));
70  ctx->n_emit_state = n_emit_state;
71  ctx->tp = tp;
72  ctx->senscore = senscore;
73  ctx->sseq = sseq;
74  ctx->st_sen_scr = ckd_calloc(n_emit_state, sizeof(*ctx->st_sen_scr));
75 
76  return ctx;
77 }
78 
79 void
81 {
82  if (ctx == NULL)
83  return;
84  ckd_free(ctx->st_sen_scr);
85  ckd_free(ctx);
86 }
87 
88 void
89 hmm_init(hmm_context_t *ctx, hmm_t *hmm, int mpx, int ssid, int tmatid)
90 {
91  hmm->ctx = ctx;
92  hmm->mpx = mpx;
93  hmm->n_emit_state = ctx->n_emit_state;
94  if (mpx) {
95  int i;
96  hmm->ssid = BAD_SSID;
97  hmm->senid[0] = ssid;
98  for (i = 1; i < hmm_n_emit_state(hmm); ++i) {
99  hmm->senid[i] = BAD_SSID;
100  }
101  }
102  else {
103  hmm->ssid = ssid;
104  memcpy(hmm->senid, ctx->sseq[ssid], hmm->n_emit_state * sizeof(*hmm->senid));
105  }
106  hmm->tmatid = tmatid;
107  hmm_clear(hmm);
108 }
109 
110 void
112 {
113 }
114 
115 void
117  FILE * fp)
118 {
119  int32 i;
120 
121  if (hmm_is_mpx(hmm)) {
122  fprintf(fp, "MPX ");
123  for (i = 0; i < hmm_n_emit_state(hmm); i++)
124  fprintf(fp, " %11d", hmm_senid(hmm, i));
125  fprintf(fp, " ( ");
126  for (i = 0; i < hmm_n_emit_state(hmm); i++)
127  fprintf(fp, "%d ", hmm_ssid(hmm, i));
128  fprintf(fp, ")\n");
129  }
130  else {
131  fprintf(fp, "SSID ");
132  for (i = 0; i < hmm_n_emit_state(hmm); i++)
133  fprintf(fp, " %11d", hmm_senid(hmm, i));
134  fprintf(fp, " (%d)\n", hmm_ssid(hmm, 0));
135  }
136 
137  if (hmm->ctx->senscore) {
138  fprintf(fp, "SENSCR");
139  for (i = 0; i < hmm_n_emit_state(hmm); i++)
140  fprintf(fp, " %11d", hmm_senscr(hmm, i));
141  fprintf(fp, "\n");
142  }
143 
144  fprintf(fp, "SCORES %11d", hmm_in_score(hmm));
145  for (i = 1; i < hmm_n_emit_state(hmm); i++)
146  fprintf(fp, " %11d", hmm_score(hmm, i));
147  fprintf(fp, " %11d", hmm_out_score(hmm));
148  fprintf(fp, "\n");
149 
150  fprintf(fp, "HISTID %11d", hmm_in_history(hmm));
151  for (i = 1; i < hmm_n_emit_state(hmm); i++)
152  fprintf(fp, " %11d", hmm_history(hmm, i));
153  fprintf(fp, " %11d", hmm_out_history(hmm));
154  fprintf(fp, "\n");
155 
156  if (hmm_in_score(hmm) > 0)
157  fprintf(fp,
158  "ALERT!! The input score %d is large than 0. Probably wrap around.\n",
159  hmm_in_score(hmm));
160  if (hmm_out_score(hmm) > 0)
161  fprintf(fp,
162  "ALERT!! The output score %d is large than 0. Probably wrap around\n.",
163  hmm_out_score(hmm));
164 
165  fflush(fp);
166 }
167 
168 
169 void
171 {
172  int32 i;
173 
174  hmm_in_score(h) = WORST_SCORE;
175  for (i = 1; i < hmm_n_emit_state(h); i++)
176  hmm_score(h, i) = WORST_SCORE;
177  hmm_out_score(h) = WORST_SCORE;
178 
179  h->bestscore = WORST_SCORE;
180 }
181 
182 void
184 {
185  int32 i;
186 
187  hmm_in_score(h) = WORST_SCORE;
188  hmm_in_history(h) = -1;
189  for (i = 1; i < hmm_n_emit_state(h); i++) {
190  hmm_score(h, i) = WORST_SCORE;
191  hmm_history(h, i) = -1;
192  }
193  hmm_out_score(h) = WORST_SCORE;
194  hmm_out_history(h) = -1;
195 
196  h->bestscore = WORST_SCORE;
197  h->frame = -1;
198 }
199 
200 void
201 hmm_enter(hmm_t *h, int32 score, int32 histid, int frame)
202 {
203  hmm_in_score(h) = score;
204  hmm_in_history(h) = histid;
205  hmm_frame(h) = frame;
206 }
207 
208 void
209 hmm_normalize(hmm_t *h, int32 bestscr)
210 {
211  int32 i;
212 
213  for (i = 0; i < hmm_n_emit_state(h); i++) {
214  if (hmm_score(h, i) BETTER_THAN WORST_SCORE)
215  hmm_score(h, i) -= bestscr;
216  }
217  if (hmm_out_score(h) BETTER_THAN WORST_SCORE)
218  hmm_out_score(h) -= bestscr;
219 }
220 
221 #define hmm_tprob_5st(i, j) (-tp[(i)*6+(j)])
222 #define nonmpx_senscr(i) (-senscore[sseq[i]])
223 
224 static int32
225 hmm_vit_eval_5st_lr(hmm_t * hmm)
226 {
227  int16 const *senscore = hmm->ctx->senscore;
228  uint8 const *tp = hmm->ctx->tp[hmm->tmatid][0];
229  uint16 const *sseq = hmm->senid;
230  int32 s5, s4, s3, s2, s1, s0, t2, t1, t0, bestScore;
231 
232  /* It was the best of scores, it was the worst of scores. */
233  bestScore = WORST_SCORE;
234 
235  /* Cache problem here! */
236  s4 = hmm_score(hmm, 4) + nonmpx_senscr(4);
237  s3 = hmm_score(hmm, 3) + nonmpx_senscr(3);
238  /* Transitions into non-emitting state 5 */
239  if (s3 BETTER_THAN WORST_SCORE) {
240  t1 = s4 + hmm_tprob_5st(4, 5);
241  t2 = s3 + hmm_tprob_5st(3, 5);
242  if (t1 BETTER_THAN t2) {
243  s5 = t1;
244  hmm_out_history(hmm) = hmm_history(hmm, 4);
245  } else {
246  s5 = t2;
247  hmm_out_history(hmm) = hmm_history(hmm, 3);
248  }
249  if (s5 WORSE_THAN WORST_SCORE) s5 = WORST_SCORE;
250  hmm_out_score(hmm) = s5;
251  bestScore = s5;
252  }
253 
254  s2 = hmm_score(hmm, 2) + nonmpx_senscr(2);
255  /* All transitions into state 4 */
256  if (s2 BETTER_THAN WORST_SCORE) {
257  t0 = s4 + hmm_tprob_5st(4, 4);
258  t1 = s3 + hmm_tprob_5st(3, 4);
259  t2 = s2 + hmm_tprob_5st(2, 4);
260  if (t0 BETTER_THAN t1) {
261  if (t2 BETTER_THAN t0) {
262  s4 = t2;
263  hmm_history(hmm, 4) = hmm_history(hmm, 2);
264  } else
265  s4 = t0;
266  } else {
267  if (t2 BETTER_THAN t1) {
268  s4 = t2;
269  hmm_history(hmm, 4) = hmm_history(hmm, 2);
270  } else {
271  s4 = t1;
272  hmm_history(hmm, 4) = hmm_history(hmm, 3);
273  }
274  }
275  if (s4 WORSE_THAN WORST_SCORE) s4 = WORST_SCORE;
276  if (s4 BETTER_THAN bestScore) bestScore = s4;
277  hmm_score(hmm, 4) = s4;
278  }
279 
280  s1 = hmm_score(hmm, 1) + nonmpx_senscr(1);
281  /* All transitions into state 3 */
282  if (s1 BETTER_THAN WORST_SCORE) {
283  t0 = s3 + hmm_tprob_5st(3, 3);
284  t1 = s2 + hmm_tprob_5st(2, 3);
285  t2 = s1 + hmm_tprob_5st(1, 3);
286  if (t0 BETTER_THAN t1) {
287  if (t2 BETTER_THAN t0) {
288  s3 = t2;
289  hmm_history(hmm, 3) = hmm_history(hmm, 1);
290  } else
291  s3 = t0;
292  } else {
293  if (t2 BETTER_THAN t1) {
294  s3 = t2;
295  hmm_history(hmm, 3) = hmm_history(hmm, 1);
296  } else {
297  s3 = t1;
298  hmm_history(hmm, 3) = hmm_history(hmm, 2);
299  }
300  }
301  if (s3 WORSE_THAN WORST_SCORE) s3 = WORST_SCORE;
302  if (s3 BETTER_THAN bestScore) bestScore = s3;
303  hmm_score(hmm, 3) = s3;
304  }
305 
306  s0 = hmm_in_score(hmm) + nonmpx_senscr(0);
307  /* All transitions into state 2 (state 0 is always active) */
308  t0 = s2 + hmm_tprob_5st(2, 2);
309  t1 = s1 + hmm_tprob_5st(1, 2);
310  t2 = s0 + hmm_tprob_5st(0, 2);
311  if (t0 BETTER_THAN t1) {
312  if (t2 BETTER_THAN t0) {
313  s2 = t2;
314  hmm_history(hmm, 2) = hmm_in_history(hmm);
315  } else
316  s2 = t0;
317  } else {
318  if (t2 BETTER_THAN t1) {
319  s2 = t2;
320  hmm_history(hmm, 2) = hmm_in_history(hmm);
321  } else {
322  s2 = t1;
323  hmm_history(hmm, 2) = hmm_history(hmm, 1);
324  }
325  }
326  if (s2 WORSE_THAN WORST_SCORE) s2 = WORST_SCORE;
327  if (s2 BETTER_THAN bestScore) bestScore = s2;
328  hmm_score(hmm, 2) = s2;
329 
330 
331  /* All transitions into state 1 */
332  t0 = s1 + hmm_tprob_5st(1, 1);
333  t1 = s0 + hmm_tprob_5st(0, 1);
334  if (t0 BETTER_THAN t1) {
335  s1 = t0;
336  } else {
337  s1 = t1;
338  hmm_history(hmm, 1) = hmm_in_history(hmm);
339  }
340  if (s1 WORSE_THAN WORST_SCORE) s1 = WORST_SCORE;
341  if (s1 BETTER_THAN bestScore) bestScore = s1;
342  hmm_score(hmm, 1) = s1;
343 
344  /* All transitions into state 0 */
345  s0 = s0 + hmm_tprob_5st(0, 0);
346  if (s0 WORSE_THAN WORST_SCORE) s0 = WORST_SCORE;
347  if (s0 BETTER_THAN bestScore) bestScore = s0;
348  hmm_in_score(hmm) = s0;
349 
350  hmm_bestscore(hmm) = bestScore;
351  return bestScore;
352 }
353 
354 #define mpx_senid(st) sseq[ssid[st]][st]
355 #define mpx_senscr(st) (-senscore[mpx_senid(st)])
356 
357 static int32
358 hmm_vit_eval_5st_lr_mpx(hmm_t * hmm)
359 {
360  uint8 const *tp = hmm->ctx->tp[hmm->tmatid][0];
361  int16 const *senscore = hmm->ctx->senscore;
362  uint16 * const *sseq = hmm->ctx->sseq;
363  uint16 *ssid = hmm->senid;
364  int32 bestScore;
365  int32 s5, s4, s3, s2, s1, s0, t2, t1, t0;
366 
367  /* Don't propagate WORST_SCORE */
368  if (ssid[4] == BAD_SSID)
369  s4 = t1 = WORST_SCORE;
370  else {
371  s4 = hmm_score(hmm, 4) + mpx_senscr(4);
372  t1 = s4 + hmm_tprob_5st(4, 5);
373  }
374  if (ssid[3] == BAD_SSID)
375  s3 = t2 = WORST_SCORE;
376  else {
377  s3 = hmm_score(hmm, 3) + mpx_senscr(3);
378  t2 = s3 + hmm_tprob_5st(3, 5);
379  }
380  if (t1 BETTER_THAN t2) {
381  s5 = t1;
382  hmm_out_history(hmm) = hmm_history(hmm, 4);
383  }
384  else {
385  s5 = t2;
386  hmm_out_history(hmm) = hmm_history(hmm, 3);
387  }
388  if (s5 WORSE_THAN WORST_SCORE) s5 = WORST_SCORE;
389  hmm_out_score(hmm) = s5;
390  bestScore = s5;
391 
392  /* Don't propagate WORST_SCORE */
393  if (ssid[2] == BAD_SSID)
394  s2 = t2 = WORST_SCORE;
395  else {
396  s2 = hmm_score(hmm, 2) + mpx_senscr(2);
397  t2 = s2 + hmm_tprob_5st(2, 4);
398  }
399 
400  t0 = t1 = WORST_SCORE;
401  if (s4 != WORST_SCORE)
402  t0 = s4 + hmm_tprob_5st(4, 4);
403  if (s3 != WORST_SCORE)
404  t1 = s3 + hmm_tprob_5st(3, 4);
405  if (t0 BETTER_THAN t1) {
406  if (t2 BETTER_THAN t0) {
407  s4 = t2;
408  hmm_history(hmm, 4) = hmm_history(hmm, 2);
409  ssid[4] = ssid[2];
410  }
411  else
412  s4 = t0;
413  }
414  else {
415  if (t2 BETTER_THAN t1) {
416  s4 = t2;
417  hmm_history(hmm, 4) = hmm_history(hmm, 2);
418  ssid[4] = ssid[2];
419  }
420  else {
421  s4 = t1;
422  hmm_history(hmm, 4) = hmm_history(hmm, 3);
423  ssid[4] = ssid[3];
424  }
425  }
426  if (s4 WORSE_THAN WORST_SCORE) s4 = WORST_SCORE;
427  if (s4 BETTER_THAN bestScore)
428  bestScore = s4;
429  hmm_score(hmm, 4) = s4;
430 
431  /* Don't propagate WORST_SCORE */
432  if (ssid[1] == BAD_SSID)
433  s1 = t2 = WORST_SCORE;
434  else {
435  s1 = hmm_score(hmm, 1) + mpx_senscr(1);
436  t2 = s1 + hmm_tprob_5st(1, 3);
437  }
438  t0 = t1 = WORST_SCORE;
439  if (s3 != WORST_SCORE)
440  t0 = s3 + hmm_tprob_5st(3, 3);
441  if (s2 != WORST_SCORE)
442  t1 = s2 + hmm_tprob_5st(2, 3);
443  if (t0 BETTER_THAN t1) {
444  if (t2 BETTER_THAN t0) {
445  s3 = t2;
446  hmm_history(hmm, 3) = hmm_history(hmm, 1);
447  ssid[3] = ssid[1];
448  }
449  else
450  s3 = t0;
451  }
452  else {
453  if (t2 BETTER_THAN t1) {
454  s3 = t2;
455  hmm_history(hmm, 3) = hmm_history(hmm, 1);
456  ssid[3] = ssid[1];
457  }
458  else {
459  s3 = t1;
460  hmm_history(hmm, 3) = hmm_history(hmm, 2);
461  ssid[3] = ssid[2];
462  }
463  }
464  if (s3 WORSE_THAN WORST_SCORE) s3 = WORST_SCORE;
465  if (s3 BETTER_THAN bestScore) bestScore = s3;
466  hmm_score(hmm, 3) = s3;
467 
468  /* State 0 is always active */
469  s0 = hmm_in_score(hmm) + mpx_senscr(0);
470 
471  /* Don't propagate WORST_SCORE */
472  t0 = t1 = WORST_SCORE;
473  if (s2 != WORST_SCORE)
474  t0 = s2 + hmm_tprob_5st(2, 2);
475  if (s1 != WORST_SCORE)
476  t1 = s1 + hmm_tprob_5st(1, 2);
477  t2 = s0 + hmm_tprob_5st(0, 2);
478  if (t0 BETTER_THAN t1) {
479  if (t2 BETTER_THAN t0) {
480  s2 = t2;
481  hmm_history(hmm, 2) = hmm_in_history(hmm);
482  ssid[2] = ssid[0];
483  }
484  else
485  s2 = t0;
486  }
487  else {
488  if (t2 BETTER_THAN t1) {
489  s2 = t2;
490  hmm_history(hmm, 2) = hmm_in_history(hmm);
491  ssid[2] = ssid[0];
492  }
493  else {
494  s2 = t1;
495  hmm_history(hmm, 2) = hmm_history(hmm, 1);
496  ssid[2] = ssid[1];
497  }
498  }
499  if (s2 WORSE_THAN WORST_SCORE) s2 = WORST_SCORE;
500  if (s2 BETTER_THAN bestScore) bestScore = s2;
501  hmm_score(hmm, 2) = s2;
502 
503  /* Don't propagate WORST_SCORE */
504  t0 = WORST_SCORE;
505  if (s1 != WORST_SCORE)
506  t0 = s1 + hmm_tprob_5st(1, 1);
507  t1 = s0 + hmm_tprob_5st(0, 1);
508  if (t0 BETTER_THAN t1) {
509  s1 = t0;
510  }
511  else {
512  s1 = t1;
513  hmm_history(hmm, 1) = hmm_in_history(hmm);
514  ssid[1] = ssid[0];
515  }
516  if (s1 WORSE_THAN WORST_SCORE) s1 = WORST_SCORE;
517  if (s1 BETTER_THAN bestScore) bestScore = s1;
518  hmm_score(hmm, 1) = s1;
519 
520  s0 += hmm_tprob_5st(0, 0);
521  if (s0 WORSE_THAN WORST_SCORE) s0 = WORST_SCORE;
522  if (s0 BETTER_THAN bestScore) bestScore = s0;
523  hmm_in_score(hmm) = s0;
524 
525  hmm_bestscore(hmm) = bestScore;
526  return bestScore;
527 }
528 
529 #define hmm_tprob_3st(i, j) (-tp[(i)*4+(j)])
530 
531 static int32
532 hmm_vit_eval_3st_lr(hmm_t * hmm)
533 {
534  int16 const *senscore = hmm->ctx->senscore;
535  uint8 const *tp = hmm->ctx->tp[hmm->tmatid][0];
536  uint16 const *sseq = hmm->senid;
537  int32 s3, s2, s1, s0, t2, t1, t0, bestScore;
538 
539  s2 = hmm_score(hmm, 2) + nonmpx_senscr(2);
540  s1 = hmm_score(hmm, 1) + nonmpx_senscr(1);
541  s0 = hmm_in_score(hmm) + nonmpx_senscr(0);
542 
543  /* It was the best of scores, it was the worst of scores. */
544  bestScore = WORST_SCORE;
545  t2 = INT_MIN; /* Not used unless skipstate is true */
546 
547  /* Transitions into non-emitting state 3 */
548  if (s1 BETTER_THAN WORST_SCORE) {
549  t1 = s2 + hmm_tprob_3st(2, 3);
550  if (hmm_tprob_3st(1,3) BETTER_THAN TMAT_WORST_SCORE)
551  t2 = s1 + hmm_tprob_3st(1, 3);
552  if (t1 BETTER_THAN t2) {
553  s3 = t1;
554  hmm_out_history(hmm) = hmm_history(hmm, 2);
555  } else {
556  s3 = t2;
557  hmm_out_history(hmm) = hmm_history(hmm, 1);
558  }
559  if (s3 WORSE_THAN WORST_SCORE) s3 = WORST_SCORE;
560  hmm_out_score(hmm) = s3;
561  bestScore = s3;
562  }
563 
564  /* All transitions into state 2 (state 0 is always active) */
565  t0 = s2 + hmm_tprob_3st(2, 2);
566  t1 = s1 + hmm_tprob_3st(1, 2);
567  if (hmm_tprob_3st(0, 2) BETTER_THAN TMAT_WORST_SCORE)
568  t2 = s0 + hmm_tprob_3st(0, 2);
569  if (t0 BETTER_THAN t1) {
570  if (t2 BETTER_THAN t0) {
571  s2 = t2;
572  hmm_history(hmm, 2) = hmm_in_history(hmm);
573  } else
574  s2 = t0;
575  } else {
576  if (t2 BETTER_THAN t1) {
577  s2 = t2;
578  hmm_history(hmm, 2) = hmm_in_history(hmm);
579  } else {
580  s2 = t1;
581  hmm_history(hmm, 2) = hmm_history(hmm, 1);
582  }
583  }
584  if (s2 WORSE_THAN WORST_SCORE) s2 = WORST_SCORE;
585  if (s2 BETTER_THAN bestScore) bestScore = s2;
586  hmm_score(hmm, 2) = s2;
587 
588  /* All transitions into state 1 */
589  t0 = s1 + hmm_tprob_3st(1, 1);
590  t1 = s0 + hmm_tprob_3st(0, 1);
591  if (t0 BETTER_THAN t1) {
592  s1 = t0;
593  } else {
594  s1 = t1;
595  hmm_history(hmm, 1) = hmm_in_history(hmm);
596  }
597  if (s1 WORSE_THAN WORST_SCORE) s1 = WORST_SCORE;
598  if (s1 BETTER_THAN bestScore) bestScore = s1;
599  hmm_score(hmm, 1) = s1;
600 
601  /* All transitions into state 0 */
602  s0 = s0 + hmm_tprob_3st(0, 0);
603  if (s0 WORSE_THAN WORST_SCORE) s0 = WORST_SCORE;
604  if (s0 BETTER_THAN bestScore) bestScore = s0;
605  hmm_in_score(hmm) = s0;
606 
607  hmm_bestscore(hmm) = bestScore;
608  return bestScore;
609 }
610 
611 static int32
612 hmm_vit_eval_3st_lr_mpx(hmm_t * hmm)
613 {
614  uint8 const *tp = hmm->ctx->tp[hmm->tmatid][0];
615  int16 const *senscore = hmm->ctx->senscore;
616  uint16 * const *sseq = hmm->ctx->sseq;
617  uint16 *ssid = hmm->senid;
618  int32 bestScore;
619  int32 s3, s2, s1, s0, t2, t1, t0;
620 
621  /* Don't propagate WORST_SCORE */
622  t2 = INT_MIN; /* Not used unless skipstate is true */
623  if (ssid[2] == BAD_SSID)
624  s2 = t1 = WORST_SCORE;
625  else {
626  s2 = hmm_score(hmm, 2) + mpx_senscr(2);
627  t1 = s2 + hmm_tprob_3st(2, 3);
628  }
629  if (ssid[1] == BAD_SSID)
630  s1 = t2 = WORST_SCORE;
631  else {
632  s1 = hmm_score(hmm, 1) + mpx_senscr(1);
633  if (hmm_tprob_3st(1,3) BETTER_THAN TMAT_WORST_SCORE)
634  t2 = s1 + hmm_tprob_3st(1, 3);
635  }
636  if (t1 BETTER_THAN t2) {
637  s3 = t1;
638  hmm_out_history(hmm) = hmm_history(hmm, 2);
639  }
640  else {
641  s3 = t2;
642  hmm_out_history(hmm) = hmm_history(hmm, 1);
643  }
644  if (s3 WORSE_THAN WORST_SCORE) s3 = WORST_SCORE;
645  hmm_out_score(hmm) = s3;
646  bestScore = s3;
647 
648  /* State 0 is always active */
649  s0 = hmm_in_score(hmm) + mpx_senscr(0);
650 
651  /* Don't propagate WORST_SCORE */
652  t0 = t1 = WORST_SCORE;
653  if (s2 != WORST_SCORE)
654  t0 = s2 + hmm_tprob_3st(2, 2);
655  if (s1 != WORST_SCORE)
656  t1 = s1 + hmm_tprob_3st(1, 2);
657  if (hmm_tprob_3st(0,2) BETTER_THAN TMAT_WORST_SCORE)
658  t2 = s0 + hmm_tprob_3st(0, 2);
659  if (t0 BETTER_THAN t1) {
660  if (t2 BETTER_THAN t0) {
661  s2 = t2;
662  hmm_history(hmm, 2) = hmm_in_history(hmm);
663  ssid[2] = ssid[0];
664  }
665  else
666  s2 = t0;
667  }
668  else {
669  if (t2 BETTER_THAN t1) {
670  s2 = t2;
671  hmm_history(hmm, 2) = hmm_in_history(hmm);
672  ssid[2] = ssid[0];
673  }
674  else {
675  s2 = t1;
676  hmm_history(hmm, 2) = hmm_history(hmm, 1);
677  ssid[2] = ssid[1];
678  }
679  }
680  if (s2 WORSE_THAN WORST_SCORE) s2 = WORST_SCORE;
681  if (s2 BETTER_THAN bestScore) bestScore = s2;
682  hmm_score(hmm, 2) = s2;
683 
684  /* Don't propagate WORST_SCORE */
685  t0 = WORST_SCORE;
686  if (s1 != WORST_SCORE)
687  t0 = s1 + hmm_tprob_3st(1, 1);
688  t1 = s0 + hmm_tprob_3st(0, 1);
689  if (t0 BETTER_THAN t1) {
690  s1 = t0;
691  }
692  else {
693  s1 = t1;
694  hmm_history(hmm, 1) = hmm_in_history(hmm);
695  ssid[1] = ssid[0];
696  }
697  if (s1 WORSE_THAN WORST_SCORE) s1 = WORST_SCORE;
698  if (s1 BETTER_THAN bestScore) bestScore = s1;
699  hmm_score(hmm, 1) = s1;
700 
701  /* State 0 is always active */
702  s0 += hmm_tprob_3st(0, 0);
703  if (s0 WORSE_THAN WORST_SCORE) s0 = WORST_SCORE;
704  if (s0 BETTER_THAN bestScore) bestScore = s0;
705  hmm_in_score(hmm) = s0;
706 
707  hmm_bestscore(hmm) = bestScore;
708  return bestScore;
709 }
710 
711 static int32
712 hmm_vit_eval_anytopo(hmm_t * hmm)
713 {
714  hmm_context_t *ctx = hmm->ctx;
715  int32 to, from, bestfrom;
716  int32 newscr, scr, bestscr;
717  int final_state;
718 
719  /* Compute previous state-score + observation output prob for each emitting state */
720  ctx->st_sen_scr[0] = hmm_in_score(hmm) + hmm_senscr(hmm, 0);
721  for (from = 1; from < hmm_n_emit_state(hmm); ++from) {
722  if ((ctx->st_sen_scr[from] =
723  hmm_score(hmm, from) + hmm_senscr(hmm, from)) WORSE_THAN WORST_SCORE)
724  ctx->st_sen_scr[from] = WORST_SCORE;
725  }
726 
727  /* FIXME/TODO: Use the BLAS for all this. */
728  /* Evaluate final-state first, which does not have a self-transition */
729  final_state = hmm_n_emit_state(hmm);
730  to = final_state;
731  scr = WORST_SCORE;
732  bestfrom = -1;
733  for (from = to - 1; from >= 0; --from) {
734  if ((hmm_tprob(hmm, from, to) BETTER_THAN TMAT_WORST_SCORE) &&
735  ((newscr = ctx->st_sen_scr[from]
736  + hmm_tprob(hmm, from, to)) BETTER_THAN scr)) {
737  scr = newscr;
738  bestfrom = from;
739  }
740  }
741  hmm_out_score(hmm) = scr;
742  if (bestfrom >= 0)
743  hmm_out_history(hmm) = hmm_history(hmm, bestfrom);
744  bestscr = scr;
745 
746  /* Evaluate all other states, which might have self-transitions */
747  for (to = final_state - 1; to >= 0; --to) {
748  /* Score from self-transition, if any */
749  scr =
750  (hmm_tprob(hmm, to, to) BETTER_THAN TMAT_WORST_SCORE)
751  ? ctx->st_sen_scr[to] + hmm_tprob(hmm, to, to)
752  : WORST_SCORE;
753 
754  /* Scores from transitions from other states */
755  bestfrom = -1;
756  for (from = to - 1; from >= 0; --from) {
757  if ((hmm_tprob(hmm, from, to) BETTER_THAN TMAT_WORST_SCORE) &&
758  ((newscr = ctx->st_sen_scr[from]
759  + hmm_tprob(hmm, from, to)) BETTER_THAN scr)) {
760  scr = newscr;
761  bestfrom = from;
762  }
763  }
764 
765  /* Update new result for state to */
766  if (to == 0) {
767  hmm_in_score(hmm) = scr;
768  if (bestfrom >= 0)
769  hmm_in_history(hmm) = hmm_history(hmm, bestfrom);
770  }
771  else {
772  hmm_score(hmm, to) = scr;
773  if (bestfrom >= 0)
774  hmm_history(hmm, to) = hmm_history(hmm, bestfrom);
775  }
776  /* Propagate ssid for multiplex HMMs */
777  if (bestfrom >= 0 && hmm_is_mpx(hmm))
778  hmm->senid[to] = hmm->senid[bestfrom];
779 
780  if (bestscr WORSE_THAN scr)
781  bestscr = scr;
782  }
783 
784  hmm_bestscore(hmm) = bestscr;
785  return bestscr;
786 }
787 
788 int32
790 {
791  if (hmm_is_mpx(hmm)) {
792  if (hmm_n_emit_state(hmm) == 5)
793  return hmm_vit_eval_5st_lr_mpx(hmm);
794  else if (hmm_n_emit_state(hmm) == 3)
795  return hmm_vit_eval_3st_lr_mpx(hmm);
796  else
797  return hmm_vit_eval_anytopo(hmm);
798  }
799  else {
800  if (hmm_n_emit_state(hmm) == 5)
801  return hmm_vit_eval_5st_lr(hmm);
802  else if (hmm_n_emit_state(hmm) == 3)
803  return hmm_vit_eval_3st_lr(hmm);
804  else
805  return hmm_vit_eval_anytopo(hmm);
806  }
807 }
808 
809 int32
810 hmm_dump_vit_eval(hmm_t * hmm, FILE * fp)
811 {
812  int32 bs = 0;
813 
814  if (fp) {
815  fprintf(fp, "BEFORE:\n");
816  hmm_dump(hmm, fp);
817  }
818  bs = hmm_vit_eval(hmm);
819  if (fp) {
820  fprintf(fp, "AFTER:\n");
821  hmm_dump(hmm, fp);
822  }
823 
824  return bs;
825 }
int32 hmm_dump_vit_eval(hmm_t *hmm, FILE *fp)
Like hmm_vit_eval, but dump HMM state and relevant senscr to fp first, for debugging;.
Definition: hmm.c:810
void hmm_init(hmm_context_t *ctx, hmm_t *hmm, int mpx, int ssid, int tmatid)
Populate a previously-allocated HMM structure, allocating internal data.
Definition: hmm.c:89
An individual HMM among the HMM search space.
void hmm_deinit(hmm_t *hmm)
Free an HMM structure, releasing internal data (but not the HMM structure itself).
Definition: hmm.c:111
#define BAD_SSID
Invalid senone sequence ID (limited to 16 bits for PocketSphinx).
Definition: bin_mdef.h:94
Implementation of HMM base structure.
#define HMM_MAX_NSTATE
Hard-coded limit on the number of emitting states.
Definition: hmm.h:160
int32 hmm_vit_eval(hmm_t *hmm)
Viterbi evaluation of given HMM.
Definition: hmm.c:789
void hmm_normalize(hmm_t *h, int32 bestscr)
Renormalize the scores in this HMM based on the given best score.
Definition: hmm.c:209
hmm_context_t * hmm_context_init(int32 n_emit_state, uint8 **const *tp, int16 const *senscore, uint16 *const *sseq)
Create an HMM context.
Definition: hmm.c:56
#define WORST_SCORE
Large &quot;bad&quot; score.
Definition: hmm.h:84
Shared information between a set of HMMs.
void hmm_enter(hmm_t *h, int32 score, int32 histid, int frame)
Enter an HMM with the given path score and history ID.
Definition: hmm.c:201
void hmm_dump(hmm_t *h, FILE *fp)
For debugging, dump the whole HMM out.
Definition: hmm.c:116
#define WORSE_THAN
Is one score worse than another?
Definition: hmm.h:100
void hmm_clear(hmm_t *h)
Reset the states of the HMM to the invalid condition.
Definition: hmm.c:183
#define TMAT_WORST_SCORE
Watch out, though! Transition matrix entries that are supposed to be &quot;zero&quot; don&#39;t actually get that...
Definition: hmm.h:90
#define BETTER_THAN
Is one score better than another?
Definition: hmm.h:95
void hmm_clear_scores(hmm_t *h)
Reset the scores of the HMM.
Definition: hmm.c:170
void hmm_context_free(hmm_context_t *ctx)
Free an HMM context.
Definition: hmm.c:80