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 /* 38 * hmm.h -- HMM data structure. 39 * 40 * ********************************************** 41 * CMU ARPA Speech Project 42 * 43 * Copyright (c) 1997 Carnegie Mellon University. 44 * ALL RIGHTS RESERVED. 45 * ********************************************** 46 * 47 * HISTORY 48 * $Log$ 49 * Revision 1.1 2006/04/05 20:27:30 dhdfu 50 * A Great Reorganzation of header files and executables 51 * 52 * Revision 1.9 2006/02/22 16:46:38 arthchan2003 53 * Merged from SPHINX3_5_2_RCI_IRII_BRANCH: 1, Added function hmm_vit_eval, a wrapper of computing the hmm level scores. 2, Fixed issues in , 3, Fixed issues of dox-doc 54 * 55 * Revision 1.8.4.6 2005/09/25 18:53:36 arthchan2003 56 * Added hmm_vit_eval, in lextree.c, hmm_dump and hmm_vit_eval is now separated. 57 * 58 * Revision 1.8.4.5 2005/07/26 02:17:44 arthchan2003 59 * Fixed keyword problem. 60 * 61 * Revision 1.8.4.4 2005/07/17 05:15:47 arthchan2003 62 * Totally removed the data members in hmm_t structure 63 * 64 * Revision 1.8.4.3 2005/07/05 05:47:59 arthchan2003 65 * Fixed dox-doc. struct level of documentation are included. 66 * 67 * Revision 1.8.4.2 2005/07/04 07:15:55 arthchan2003 68 * Removed fsg compliant stuff from hmm_t 69 * 70 * Revision 1.8.4.1 2005/06/27 05:38:54 arthchan2003 71 * Added changes to make libsearch/fsg_* family of code to be compiled. 72 * 73 * Revision 1.8 2005/06/21 18:34:41 arthchan2003 74 * Log. 1, Fixed doxygen documentation for all functions. 2, Add $Log$ 75 * Revision 1.1 2006/04/05 20:27:30 dhdfu 76 * A Great Reorganzation of header files and executables 77 * 78 * Log. 1, Fixed doxygen documentation for all functions. 2, Add Revision 1.9 2006/02/22 16:46:38 arthchan2003 79 * Log. 1, Fixed doxygen documentation for all functions. 2, Add Merged from SPHINX3_5_2_RCI_IRII_BRANCH: 1, Added function hmm_vit_eval, a wrapper of computing the hmm level scores. 2, Fixed issues in , 3, Fixed issues of dox-doc 80 * Log. 1, Fixed doxygen documentation for all functions. 2, Add 81 * 82 * Revision 1.4 2005/06/13 04:02:55 archan 83 * Fixed most doxygen-style documentation under libs3decoder. 84 * 85 * Revision 1.3 2005/03/30 01:22:46 archan 86 * Fixed mistakes in last updates. Add 87 * 88 * 89 * 29-Feb-2000 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University 90 * Modified hmm_t.state to be a run-time array instead of a compile-time 91 * one. Modified compile-time 3 and 5-state versions of hmm_vit_eval 92 * into hmm_vit_eval_3st and hmm_vit_eval_5st, to allow run-time selection. 93 * Removed hmm_init(). 94 * 95 * 08-Dec-1999 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University. 96 * Added HMM_SKIPARCS compile-time option and hmm_init(). 97 * 98 * 10-May-1999 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University. 99 * Started, based on an earlier version. 100 */ 101 102 103 #ifndef _S3_HMM_H_ 104 #define _S3_HMM_H_ 105 106 #include <stdio.h> 107 108 #include "s3types.h" 109 110 #ifdef __cplusplus 111 extern "C" { 112 #endif 113 #if 0 114 } /* Fool Emacs into not indenting things. */ 115 #endif 116 117 /** Hardcoded limit on the number of states (temporary) */ 118 #define MAX_HMM_NSTATE 5 119 120 /** \file hmm.h 121 * \brief HMM data structure and operation 122 * 123 * For efficiency, this version is hardwired for two possible HMM 124 * topologies, but will fall back to others: 125 * 126 * 5-state left-to-right HMMs: (0 is the *emitting* entry state and E 127 * is a non-emitting exit state; the x's indicate allowed transitions 128 * between source and destination states): 129 * 130 * 0 1 2 3 4 E (destination-states) 131 * 0 x x x 132 * 1 x x x 133 * 2 x x x 134 * 3 x x x 135 * 4 x x 136 * (source-states) 137 * 5-state topologies that contain a subset of the above transitions should work as well. 138 * 139 * 3-state left-to-right HMMs (similar notation as the 5-state topology above): 140 * 141 * 0 1 2 E (destination-states) 142 * 0 x x x 143 * 1 x x x 144 * 2 x x 145 * (source-states) 146 * 3-state topologies that contain a subset of the above transitions should work as well. */ 147 148 /** \struct hmm_context_t 149 * \brief Shared information between a set of HMMs. 150 * 151 * We assume that the initial state is emitting and that the 152 * transition matrix is n_emit_state x (n_emit_state+1), where the 153 * extra destination dimension correponds to the non-emitting final or 154 * exit state. 155 */ 156 typedef struct hmm_context_s { 157 int32 n_emit_state; /**< Number of emitting states in this set of HMMs. */ 158 const int32 ***tp; /**< State transition scores tp[id][from][to] (logs3 values). */ 159 const int32 *senscore; /**< State emission scores senscore[senid] (logs3 values). */ 160 const s3senid_t **sseq;/**< Senone sequence mapping. */ 161 int32 *st_sen_scr; /**< Temporary array of senone scores (for some topologies). */ 162 void *udata; /**< Whatever you feel like, gosh. */ 163 } hmm_context_t; 164 165 /** \struct hmm_state_t 166 * \brief A single state in the HMM 167 */ 168 typedef struct { 169 int32 score; /**< State score (path log-likelihood) */ 170 union { 171 long id; /**< History index */ 172 void *ptr; /**< History object */ 173 } history; 174 } hmm_state_t; 175 176 /** \struct hmm_t 177 * \brief An individual HMM among the HMM search space. 178 * 179 * An individual HMM among the HMM search space. An HMM with N 180 * emitting states consists of N+2 internal states including the 181 * non-emitting entry (in) and exit (out) states. 182 */ 183 184 typedef struct hmm_s { 185 hmm_context_t *ctx; /**< Shared context data for this HMM. */ 186 hmm_state_t state[MAX_HMM_NSTATE]; /**< Per-state data for emitting states */ 187 hmm_state_t out; /**< Non-emitting exit state */ 188 union { 189 int32 *mpx_ssid; /**< Senone sequence IDs for each state (for multiplex HMMs). */ 190 int32 ssid; /**< Senone sequence ID. */ 191 } s; 192 int32 bestscore; /**< Best [emitting] state score in current frame (for pruning). */ 193 s3tmatid_t tmatid; /**< Transition matrix ID (see hmm_context_t). */ 194 s3frmid_t frame; /**< Frame in which this HMM was last active; <0 if inactive */ 195 uint8 mpx; /**< Is this HMM multiplex? (hoisted for speed) */ 196 uint8 n_emit_state; /**< Number of emitting states (hoisted for speed) */ 197 } hmm_t; 198 199 /** Access macros. */ 200 #define hmm_context(h) ((hmm_t *)(h))->ctx 201 #define hmm_is_mpx(h) ((hmm_t *)(h))->mpx 202 #define hmm_state(h,st) ((hmm_t *)(h))->state[st] 203 204 #define hmm_in_score(h) hmm_state(h,0).score 205 #define hmm_score(h,st) hmm_state(h,st).score 206 #define hmm_out_score(h) ((hmm_t *)(h))->out.score 207 208 #define hmm_in_history(h) hmm_state(h,0).history.id 209 #define hmm_history(h,st) hmm_state(h,st).history.id 210 #define hmm_out_history(h) ((hmm_t *)(h))->out.history.id 211 212 #define hmm_in_histobj(h) hmm_state(h,0).history.ptr 213 #define hmm_histobj(h,st) hmm_state(h,st).history.ptr 214 #define hmm_out_histobj(h) ((hmm_t *)(h))->out.history.ptr 215 216 #define hmm_bestscore(h) ((hmm_t *)(h))->bestscore 217 #define hmm_frame(h) ((hmm_t *)(h))->frame 218 #define hmm_mpx_ssid(h,st) ((hmm_t *)(h))->s.mpx_ssid[st] 219 #define hmm_nonmpx_ssid(h) ((hmm_t *)(h))->s.ssid 220 #define hmm_ssid(h,st) (hmm_is_mpx((hmm_t *)(h)) \ 221 ? hmm_mpx_ssid(h,st) : ((hmm_t *)(h))->s.ssid) 222 #define hmm_senid(h,st) (hmm_ssid(h,st) == -1 \ 223 ? -1 : ((hmm_t *)(h))->ctx->sseq[hmm_ssid(h,st)][st]) 224 #define hmm_senscr(h,st) (hmm_ssid(h,st) == -1 \ 225 ? S3_LOGPROB_ZERO \ 226 : ((hmm_t *)(h))->ctx->senscore[hmm_senid(h,st)]) 227 #define hmm_tmatid(h) ((hmm_t *)(h))->tmatid 228 #define hmm_tprob(h,i,j) ((hmm_t *)(h))->ctx->tp[hmm_tmatid(h)][i][j] 229 #define hmm_n_emit_state(h) (((hmm_t *)(h))->n_emit_state) 230 #define hmm_n_state(h) (((hmm_t *)(h))->n_emit_state + 1) 231 232 /** 233 * Create an HMM context. 234 **/ 235 hmm_context_t *hmm_context_init(int32 n_emit_state, 236 int32 ***tp, 237 int32 *senscore, 238 s3senid_t **sseq); 239 240 /** 241 * Change the senone score array for a context. 242 **/ 243 #define hmm_context_set_senscore(ctx, senscr) ((ctx)->senscore = (senscr)) 244 245 /** 246 * Free an HMM context. 247 * 248 * \note The transition matrices, senone scores, and senone sequence 249 * mapping are all assumed to be allocated externally, and will NOT be 250 * freed by this function. 251 **/ 252 void hmm_context_free(hmm_context_t *ctx); 253 254 /** 255 * Populate a previously-allocated HMM structure, allocating internal data. 256 **/ 257 void hmm_init(hmm_context_t *ctx, hmm_t *hmm, int mpx, 258 int32 ssid, s3tmatid_t tmatid); 259 260 /** 261 * Free an HMM structure, releasing internal data (but not the HMM structure itself). 262 */ 263 void hmm_deinit(hmm_t *hmm); 264 265 /** 266 * Reset the states of the HMM to the invalid condition; i.e., scores 267 * to WORST_SCORE and hist to undefined. 268 */ 269 void hmm_clear(hmm_t *h); 270 271 /** 272 * Reset the scores of the HMM. 273 */ 274 void hmm_clear_scores(hmm_t *h); 275 276 /** 277 * Renormalize the scores in this HMM based on the given best score. 278 */ 279 void hmm_normalize(hmm_t *h, int32 bestscr); 280 281 /** 282 * Enter an HMM with the given path score and history ID. 283 **/ 284 void hmm_enter(hmm_t *h, int32 score, 285 int32 histid, int32 frame); 286 287 /** 288 * Enter an HMM with the given path score and history object. 289 **/ 290 void hmm_enter_obj(hmm_t *h, int32 score, 291 void *histobj, int32 frame); 292 293 /** 294 * Viterbi evaluation of given HMM. (NOTE that if this module were being used for tracking 295 * state segmentations, the dummy, non-emitting exit state would have to be updated separately. 296 * In the Viterbi DP diagram, transitions to the exit state occur from the current time; they 297 * are vertical transitions. Hence they should be made only after the history has been logged 298 * for the emitting states. But we're not bothered with state segmentations, for now. So, we 299 * update the exit state as well.) 300 */ 301 int32 hmm_vit_eval(hmm_t *hmm); 302 303 304 /** 305 * Like hmm_vit_eval, but dump HMM state and relevant senscr to fp first, for debugging;. 306 */ 307 int32 hmm_dump_vit_eval(hmm_t *hmm, /**< In/Out: HMM being updated */ 308 FILE *fp /**< An output file pointer */ 309 ); 310 311 /** 312 * For debugging, dump the whole HMM out. 313 */ 314 315 void hmm_dump(hmm_t *h, /**< In/Out: HMM being updated */ 316 FILE *fp /**< An output file pointer */ 317 ); 318 319 320 #if 0 321 { /* Stop indent from complaining */ 322 #endif 323 #ifdef __cplusplus 324 } 325 #endif 326 327 #endif 328