~logan/ubuntu/quantal/julius/new-upstream

« back to all changes in this revision

Viewing changes to libsent/src/phmm/mkwhmm.c

  • Committer: Bazaar Package Importer
  • Author(s): Siegfried-Angel Gevatter Pujals
  • Date: 2008-07-25 17:44:08 UTC
  • Revision ID: james.westby@ubuntu.com-20080725174408-lzgv2q5m2rmpecmv
Tags: upstream-4.0.2
ImportĀ upstreamĀ versionĀ 4.0.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * @file   mkwhmm.c
 
3
 * 
 
4
 * <JA>
 
5
 * @brief  ļæ½ļæ½ļæ½ļæ½ļæ½ó¤«¤ļæ½×»ļæ½ļæ½Ń¤Ī·ļæ½ļæ½%HMMļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½ļæ½
 
6
 * </JA>
 
7
 * 
 
8
 * <EN>
 
9
 * @brief  Generate compound %HMM instance for recognition from phoneme sequence.
 
10
 * </EN>
 
11
 * 
 
12
 * @author Akinobu LEE
 
13
 * @date   Fri Feb 18 18:31:40 2005
 
14
 *
 
15
 * $Revision: 1.3 $
 
16
 * 
 
17
 */
 
18
/*
 
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
 
22
 * All rights reserved
 
23
 */
 
24
 
 
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. */
 
27
 
 
28
#include <sent/stddefs.h>
 
29
#include <sent/hmm.h>
 
30
 
 
31
/** 
 
32
 * Calculate total number of states in a phoneme sequence.
 
33
 * 
 
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
 
38
 * 
 
39
 * @return the total number of states in the sequence.
 
40
 */
 
41
static int
 
42
totalstatelen(HMM_Logical **hdseq, int hdseqlen, boolean *has_sp, HTK_HMM_INFO *hmminfo)
 
43
{
 
44
  int i, len;
 
45
 
 
46
  len = 0;
 
47
  for (i=0;i<hdseqlen;i++) {
 
48
    len += hmm_logical_state_num(hdseq[i]) - 2;
 
49
    if (has_sp) {
 
50
      if (has_sp[i]) {
 
51
        len += hmm_logical_state_num(hmminfo->sp) - 2;
 
52
      }
 
53
    }
 
54
  }
 
55
  if (hmminfo->multipath) {
 
56
    /* add count for the initial and final state */
 
57
    len += 2;
 
58
  }
 
59
  return(len);
 
60
}
 
61
 
 
62
/** 
 
63
 * Add a transition arc on the HMM state.
 
64
 * 
 
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
 
68
 */
 
69
static void
 
70
add_arc(HMM_STATE *state, int arc, LOGPROB a)
 
71
{
 
72
  A_CELL *atmp;
 
73
 
 
74
  atmp = (A_CELL *)mymalloc(sizeof(A_CELL));
 
75
  atmp->a = a;
 
76
  atmp->arc = arc;
 
77
  atmp->next = state->ac;
 
78
  state->ac = atmp;
 
79
}
 
80
 
 
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 */
 
84
 
 
85
/** 
 
86
 * Make a HMM instance for recognition from phoneme sequence, with connection
 
87
 * probabiliry given for each phoneme.
 
88
 * 
 
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.
 
95
 * 
 
96
 * @return newly allocated HMM instance generated from the given data.
 
97
 */
 
98
HMM *
 
99
new_make_word_hmm_with_lm(HTK_HMM_INFO *hmminfo, HMM_Logical **hdseq, int hdseqlen, boolean *has_sp, LOGPROB *lscore)
 
100
{
 
101
  HMM *new;
 
102
  int i,j,n;
 
103
  int afrom, ato;
 
104
  LOGPROB logprob;
 
105
  HTK_HMM_Trans *tr;
 
106
  int state_num;
 
107
 
 
108
  if (has_sp) {
 
109
    if (hmminfo->sp == NULL) {
 
110
      jlog("Error: mkwhmm: no short-pause model in hmminfo\n");
 
111
      return NULL;
 
112
    }
 
113
  }
 
114
 
 
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;
 
124
  }
 
125
 
 
126
  /* assign outprob informations into the states  */
 
127
  n = 0;
 
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]);
 
134
        n++;
 
135
      }
 
136
    } else {
 
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];
 
140
        n++;
 
141
      }
 
142
    }
 
143
    if (has_sp) {
 
144
      if (has_sp[i]) {
 
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]);
 
150
            n++;
 
151
          }
 
152
        } else {
 
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];
 
156
            n++;
 
157
          }
 
158
        }
 
159
      }
 
160
    }
 
161
  }
 
162
  
 
163
  /* make transition arcs between each state*/
 
164
/* 
 
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");
 
168
 *     }
 
169
 *   }
 
170
 */
 
171
 
 
172
  if (hmminfo->multipath) {
 
173
 
 
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);
 
181
 
 
182
    n = 0;                      /* n points to previous state */
 
183
 
 
184
    out_from[0] = 0;
 
185
    out_a[0] = 0.0;
 
186
    out_num_prev = 1;
 
187
    for (i = 0; i < hdseqlen; i++) {
 
188
      state_num = hmm_logical_state_num(hdseq[i]);
 
189
      tr = hmm_logical_trans(hdseq[i]);
 
190
      out_num_next = 0;
 
191
      /* arc from initial state */
 
192
      for (ato = 1; ato < state_num; ato++) {
 
193
        logprob = tr->a[0][ato];
 
194
        if (logprob != LOG_ZERO) {
 
195
          /* expand arc */
 
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;
 
202
              out_num_next++;
 
203
            }
 
204
          } else {
 
205
            for(j=0;j<out_num_prev;j++) {
 
206
              add_arc(&(new->state[out_from[j]]), n + ato,
 
207
                      out_a[j] + logprob);
 
208
            }
 
209
          }
 
210
        }
 
211
      }
 
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;
 
222
            } else {
 
223
              add_arc(&(new->state[n+afrom]), n + ato, logprob);
 
224
            }
 
225
          }
 
226
        }
 
227
      }
 
228
      n += state_num - 2;
 
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];
 
232
      }
 
233
      out_num_prev = out_num_next;
 
234
 
 
235
      /* inter-word short pause handling */
 
236
      if (has_sp && has_sp[i]) {
 
237
      
 
238
        out_num_next = 0;
 
239
 
 
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;
 
247
            /* expand arc */
 
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;
 
253
                out_num_next++;
 
254
              }
 
255
            } else {
 
256
              for(j=0;j<out_num_prev;j++) {
 
257
                add_arc(&(new->state[out_from[j]]), n + ato,
 
258
                        out_a[j] + logprob);
 
259
              }
 
260
            }
 
261
          }
 
262
        }
 
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%) */
 
267
          logprob = 0.0;
 
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;
 
271
            out_num_next++;
 
272
          }
 
273
        }
 
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;
 
283
              } else {
 
284
                add_arc(&(new->state[n+afrom]), n + ato, logprob);
 
285
              }
 
286
            }
 
287
          }
 
288
        }
 
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];
 
293
        }
 
294
        out_num_prev = out_num_next;
 
295
      }
 
296
    }
 
297
      
 
298
    
 
299
    for(j=0;j<out_num_prev;j++) {
 
300
      add_arc(&(new->state[out_from[j]]), new->len-1, out_a[j]);
 
301
    }
 
302
    free(out_from);
 
303
    free(out_from_next);
 
304
    free(out_a);
 
305
    free(out_a_next);
 
306
 
 
307
  } else {
 
308
    /* non-multipath version */
 
309
 
 
310
    new->accept_ac_a = LOG_ZERO;
 
311
    n = 0;
 
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];
 
323
            }
 
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");
 
327
                return NULL;
 
328
                
 
329
              } else {
 
330
                new->accept_ac_a = logprob;
 
331
              }
 
332
            } else {
 
333
              add_arc(&(new->state[n]), n + (ato - afrom), logprob);
 
334
            }
 
335
          }
 
336
        }
 
337
        n++;
 
338
      }
 
339
    }
 
340
  }
 
341
 
 
342
  return (new);
 
343
}
 
344
 
 
345
/** 
 
346
 * Make a HMM instance for recognition from phoneme sequence.
 
347
 * 
 
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
 
352
 * 
 
353
 * @return newly allocated HMM instance generated from the given data.
 
354
 */
 
355
HMM *
 
356
new_make_word_hmm(HTK_HMM_INFO *hmminfo, HMM_Logical **hdseq, int hdseqlen, boolean *has_sp)
 
357
{
 
358
  return(new_make_word_hmm_with_lm(hmminfo, hdseq, hdseqlen, has_sp, NULL));
 
359
}
 
360
 
 
361
/** 
 
362
 * Free an HMM instance.
 
363
 * 
 
364
 * @param d [in] HMM instance to free
 
365
 */
 
366
void
 
367
free_hmm(HMM *d)
 
368
{
 
369
  A_CELL *ac, *atmp;
 
370
  int i;
 
371
 
 
372
  for (i=0;i<d->len;i++) {
 
373
    ac = d->state[i].ac;
 
374
    while (ac) {
 
375
      atmp = ac->next;
 
376
      free(ac);
 
377
      ac = atmp;
 
378
    }
 
379
  }
 
380
  free(d->state);
 
381
  free(d);
 
382
}