5
* @brief ļæ½ļæ½ļæ½ļæ½ļæ½ó¤«¤ļæ½×»ļæ½ļæ½Ń¤Ī·ļæ½ļæ½%HMMļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½
9
* @brief Generate compound %HMM instance for recognition from phoneme sequence.
13
* @date Fri Feb 18 18:31:40 2005
19
* Copyright (c) 1991-2007 Kawahara Lab., Kyoto University
20
* Copyright (c) 2000-2005 Shikano Lab., Nara Institute of Science and Technology
21
* Copyright (c) 2005-2007 Julius project team, Nagoya Institute of Technology
25
/* When not a multi-path mode, initial & accept arc will be stripped and
26
trans prob to accept state will be stored in accept_ac_a. */
28
#include <sent/stddefs.h>
32
* Calculate total number of states in a phoneme sequence.
34
* @param hdseq [in] phoneme sequence as given by pointer list of logical %HMM
35
* @param hdseqlen [in] length of above
36
* @param has_sp [in] indicates where short-pause insertion is possible
37
* @param hmminfo [in] HMM definition
39
* @return the total number of states in the sequence.
42
totalstatelen(HMM_Logical **hdseq, int hdseqlen, boolean *has_sp, HTK_HMM_INFO *hmminfo)
47
for (i=0;i<hdseqlen;i++) {
48
len += hmm_logical_state_num(hdseq[i]) - 2;
51
len += hmm_logical_state_num(hmminfo->sp) - 2;
55
if (hmminfo->multipath) {
56
/* add count for the initial and final state */
63
* Add a transition arc on the HMM state.
65
* @param state [out] HMM state to add the arc
66
* @param arc [in] state id of destination
67
* @param a [in] transition log probability
70
add_arc(HMM_STATE *state, int arc, LOGPROB a)
74
atmp = (A_CELL *)mymalloc(sizeof(A_CELL));
77
atmp->next = state->ac;
81
/* make word(phrase) HMM from HTK_HMM_INFO */
82
/* LM prob will be assigned for cross-word arcs */
83
/* new HMM is malloced and returned */
86
* Make a HMM instance for recognition from phoneme sequence, with connection
87
* probabiliry given for each phoneme.
89
* @param hmminfo [in] HTK %HMM definitions data
90
* @param hdseq [in] phoneme sequence as given by pointer list of logical %HMM
91
* @param hdseqlen [in] length of above
92
* @param has_sp [in] indicates where short-pause insertion is possible
93
* @param lscore [in] list of log probability to be added at the emitting
94
* transition of each phoneme, or NULL if not needed.
96
* @return newly allocated HMM instance generated from the given data.
99
new_make_word_hmm_with_lm(HTK_HMM_INFO *hmminfo, HMM_Logical **hdseq, int hdseqlen, boolean *has_sp, LOGPROB *lscore)
109
if (hmminfo->sp == NULL) {
110
jlog("Error: mkwhmm: no short-pause model in hmminfo\n");
115
/* allocate needed states */
116
new = (HMM *)mymalloc(sizeof(HMM));
117
new->len = totalstatelen(hdseq, hdseqlen, has_sp, hmminfo);
118
new->state = (HMM_STATE *)mymalloc(sizeof(HMM_STATE) * new->len);
119
for (i=0;i<new->len;i++) {
120
new->state[i].ac = NULL;
121
new->state[i].is_pseudo_state = FALSE;
122
new->state[i].out.state = NULL;
123
new->state[i].out.cdset = NULL;
126
/* assign outprob informations into the states */
128
if (hmminfo->multipath) n++; /* skip first state */
129
for (i = 0; i < hdseqlen; i++) {
130
if (hdseq[i]->is_pseudo) {
131
for (j = 1; j < hdseq[i]->body.pseudo->state_num - 1; j++) {
132
new->state[n].is_pseudo_state = TRUE;
133
new->state[n].out.cdset = &(hdseq[i]->body.pseudo->stateset[j]);
137
for (j = 1; j < hdseq[i]->body.defined->state_num - 1; j++) {
138
new->state[n].is_pseudo_state = FALSE;
139
new->state[n].out.state = hdseq[i]->body.defined->s[j];
145
/* append sp at the end of the phone */
146
if (hmminfo->sp->is_pseudo) {
147
for (j = 1; j < hmm_logical_state_num(hmminfo->sp) - 1; j++) {
148
new->state[n].is_pseudo_state = TRUE;
149
new->state[n].out.cdset = &(hmminfo->sp->body.pseudo->stateset[j]);
153
for (j = 1; j < hmm_logical_state_num(hmminfo->sp) - 1; j++) {
154
new->state[n].is_pseudo_state = FALSE;
155
new->state[n].out.state = hmminfo->sp->body.defined->s[j];
163
/* make transition arcs between each state*/
165
* for (i=0;i<hdseq[0]->def->state_num;i++) {
166
* if (i != 1 && (hdseq[0]->def->tr->a[0][i]) != LOG_ZERO) {
167
* jlog("initial state contains more than 1 arc.\n");
172
if (hmminfo->multipath) {
174
int *out_from, *out_from_next;
175
LOGPROB *out_a, *out_a_next;
176
int out_num_prev, out_num_next;
177
out_from = (int *)mymalloc(sizeof(int) * new->len);
178
out_from_next = (int *)mymalloc(sizeof(int) * new->len);
179
out_a = (LOGPROB *)mymalloc(sizeof(LOGPROB) * new->len);
180
out_a_next = (LOGPROB *)mymalloc(sizeof(LOGPROB) * new->len);
182
n = 0; /* n points to previous state */
187
for (i = 0; i < hdseqlen; i++) {
188
state_num = hmm_logical_state_num(hdseq[i]);
189
tr = hmm_logical_trans(hdseq[i]);
191
/* arc from initial state */
192
for (ato = 1; ato < state_num; ato++) {
193
logprob = tr->a[0][ato];
194
if (logprob != LOG_ZERO) {
196
if (ato == state_num-1) {
197
/* from initial to final ... register all previously registered arcs for next expansion */
198
if (lscore != NULL) logprob += lscore[i];
199
for(j=0;j<out_num_prev;j++) {
200
out_from_next[out_num_next] = out_from[j];
201
out_a_next[out_num_next] = out_a[j] + logprob;
205
for(j=0;j<out_num_prev;j++) {
206
add_arc(&(new->state[out_from[j]]), n + ato,
212
/* arc from output state */
213
for(afrom = 1; afrom < state_num - 1; afrom++) {
214
for (ato = 1; ato < state_num; ato++) {
215
logprob = tr->a[afrom][ato];
216
if (logprob != LOG_ZERO) {
217
if (ato == state_num - 1) {
218
/* from output state to final ... register the arc for next expansion */
219
if (lscore != NULL) logprob += lscore[i];
220
out_from_next[out_num_next] = n+afrom;
221
out_a_next[out_num_next++] = logprob;
223
add_arc(&(new->state[n+afrom]), n + ato, logprob);
229
for(j=0;j<out_num_next;j++) {
230
out_from[j] = out_from_next[j];
231
out_a[j] = out_a_next[j];
233
out_num_prev = out_num_next;
235
/* inter-word short pause handling */
236
if (has_sp && has_sp[i]) {
240
/* arc from initial state */
241
for (ato = 1; ato < hmm_logical_state_num(hmminfo->sp); ato++) {
242
logprob = hmm_logical_trans(hmminfo->sp)->a[0][ato];
243
if (logprob != LOG_ZERO) {
244
/* to control short pause insertion, transition probability toward
245
the word-end short pause will be given a penalty */
246
logprob += hmminfo->iwsp_penalty;
248
if (ato == hmm_logical_state_num(hmminfo->sp)-1) {
249
/* from initial to final ... register all previously registered arcs for next expansion */
250
for(j=0;j<out_num_prev;j++) {
251
out_from_next[out_num_next] = out_from[j];
252
out_a_next[out_num_next] = out_a[j] + logprob;
256
for(j=0;j<out_num_prev;j++) {
257
add_arc(&(new->state[out_from[j]]), n + ato,
263
/* if short pause model doesn't have a model skip transition, also add it */
264
if (hmm_logical_trans(hmminfo->sp)->a[0][hmm_logical_state_num(hmminfo->sp)-1] == LOG_ZERO) {
265
/* to make insertion sp model to have no effect on the original path,
266
the skip transition probability should be 0.0 (=100%) */
268
for(j=0; j<out_num_prev; j++) {
269
out_from_next[out_num_next] = out_from[j];
270
out_a_next[out_num_next] = out_a[j] + logprob;
274
/* arc from output state */
275
for(afrom = 1; afrom < hmm_logical_state_num(hmminfo->sp) - 1; afrom++) {
276
for (ato = 1; ato < hmm_logical_state_num(hmminfo->sp); ato++) {
277
logprob = hmm_logical_trans(hmminfo->sp)->a[afrom][ato];
278
if (logprob != LOG_ZERO) {
279
if (ato == hmm_logical_state_num(hmminfo->sp) - 1) {
280
/* from output state to final ... register the arc for next expansion */
281
out_from_next[out_num_next] = n+afrom;
282
out_a_next[out_num_next++] = logprob;
284
add_arc(&(new->state[n+afrom]), n + ato, logprob);
289
n += hmm_logical_state_num(hmminfo->sp) - 2;
290
for(j=0;j<out_num_next;j++) {
291
out_from[j] = out_from_next[j];
292
out_a[j] = out_a_next[j];
294
out_num_prev = out_num_next;
299
for(j=0;j<out_num_prev;j++) {
300
add_arc(&(new->state[out_from[j]]), new->len-1, out_a[j]);
308
/* non-multipath version */
310
new->accept_ac_a = LOG_ZERO;
312
for (i = 0; i < hdseqlen; i++) {
313
state_num = hmm_logical_state_num(hdseq[i]);
314
tr = hmm_logical_trans(hdseq[i]);
315
/* for each phoneme, consult the transition matrix to form HMM instance */
316
for (afrom = 1; afrom < state_num - 1; afrom++) {
317
for (ato = 1; ato < state_num; ato++) {
318
logprob = tr->a[afrom][ato];
319
if (logprob != LOG_ZERO) {
320
/* if emitting transition, add connection probability to the arc */
321
if (ato == state_num - 1 && lscore != NULL){
322
logprob += lscore[i];
324
if (n + (ato - afrom) >= new->len) { /* arc to accept node */
325
if (new->accept_ac_a != LOG_ZERO) {
326
jlog("Error: mkwhmm: more than 1 arc to accept node found\n");
330
new->accept_ac_a = logprob;
333
add_arc(&(new->state[n]), n + (ato - afrom), logprob);
346
* Make a HMM instance for recognition from phoneme sequence.
348
* @param hmminfo [in] HTK %HMM definitions data
349
* @param hdseq [in] phoneme sequence as given by pointer list of logical %HMM
350
* @param hdseqlen [in] length of above
351
* @param has_sp [in] indicates where short-pause insertion is possible
353
* @return newly allocated HMM instance generated from the given data.
356
new_make_word_hmm(HTK_HMM_INFO *hmminfo, HMM_Logical **hdseq, int hdseqlen, boolean *has_sp)
358
return(new_make_word_hmm_with_lm(hmminfo, hdseq, hdseqlen, has_sp, NULL));
362
* Free an HMM instance.
364
* @param d [in] HMM instance to free
372
for (i=0;i<d->len;i++) {