1 /**
2 * @file hmm_lookup.c
3 *
4 * <JA>
5 * @brief %HMM ��̾��������Τ�����
6 *
7 * "g-u+i" �ʤɤ� %HMM ����̾���顤�б����� %HMM ����������ޤ���
8 *
9 * ������̤�����%HMM HMM_Logical �ؤΥݥ����֤���ޤ���HMM_Logical �ϡ�
10 * �ºݤ��������Ƥ��� %HMM �ؤΥݥ��������뤤�ϥХ��ե���Υե���
11 * ������%HMM̾�Ǥ��Ĥ���餬%HMM����ե������HMMList���������Ƥ��ʤ���硤
12 * �б����� pseudo %HMM set �ؤΥݥ��Τɤ��餫���ݻ����Ƥ��ޤ���
13 *
14 * �ޤ�������̾�������̾�ؤΥޥåԥؿ��ؤμ�%HMM̾�� pseudo %HMM̾��
15 * �ɲ���Ͽ�⤳���ǹԤʤ��ޤ���
16 * </JA>
17 *
18 * <EN>
19 * @brief Look up logical %HMM entry from phone name
20 *
21 * These function is for searching %HMM definition from phone name
22 * like "g-u+i".
23 *
24 * The result is pointer to the corresponding logical %HMM (HMM_Logical).
25 * The logical %HMM holds either pointer to an actual %HMM data defined in
26 * HTK %HMM definition, or pointer to a pseudo %HMM set when the query name
27 * is biphone or monophone and they are not defined in either HTK %HMM
28 * definition or HMMList mapping file.
29 *
30 * Adding physical %HMM defined in HTK %HMM definitions and pseudo phones
31 * to the logical %HMM mapping function is also done here.
32 * </EN>
33 *
34 * @author Akinobu LEE
35 * @date Tue Feb 15 22:34:30 2005
36 *
37 * $Revision: 1.4 $
38 *
39 */
40 /*
41 * Copyright (c) 1991-2007 Kawahara Lab., Kyoto University
42 * Copyright (c) 2000-2005 Shikano Lab., Nara Institute of Science and Technology
43 * Copyright (c) 2005-2007 Julius project team, Nagoya Institute of Technology
44 * All rights reserved
45 */
46
47 /* physical HMMs ... already indexed when reading in hmmdefs */
48 /* logical HMMs ... already indexed when reading in HMMList */
49
50 #include <sent/stddefs.h>
51 #include <sent/htk_hmm.h>
52 #include <sent/ptree.h>
53
54 /**
55 * Look up physical (defined in HTK %HMM definition file) %HMM by its name.
56 *
57 * @param hmminfo [in] HMM definition data
58 * @param keyname [in] key string of %HMM name
59 *
60 * @return pointer to the found physical %HMM, NULL if not found.
61 */
62 HTK_HMM_Data *
htk_hmmdata_lookup_physical(HTK_HMM_INFO * hmminfo,char * keyname)63 htk_hmmdata_lookup_physical(HTK_HMM_INFO *hmminfo, char *keyname)
64 {
65 HTK_HMM_Data *tmp;
66 tmp = aptree_search_data(keyname, hmminfo->physical_root);
67 if (tmp != NULL && strmatch(tmp->name, keyname)) {
68 return tmp;
69 } else {
70 return NULL;
71 }
72 }
73
74 /**
75 * Look up logical %HMM by its name.
76 *
77 * @param hmminfo [in] HMM definition data
78 * @param keyname [in] key string of %HMM name
79 *
80 * @return pointer to the found logical %HMM, NULL if not found.
81 */
82 HMM_Logical *
htk_hmmdata_lookup_logical(HTK_HMM_INFO * hmminfo,char * keyname)83 htk_hmmdata_lookup_logical(HTK_HMM_INFO *hmminfo, char *keyname)
84 {
85 HMM_Logical *tmp;
86 tmp = aptree_search_data(keyname, hmminfo->logical_root);
87 if (tmp != NULL && strmatch(tmp->name, keyname)) {
88 return tmp;
89 } else {
90 return NULL;
91 }
92 }
93
94 /**
95 * Count the number of logical %HMM and store it.
96 *
97 * @param hmminfo [in] %HMM definition data.
98 */
99 static void
hmm_count_logical_num(HTK_HMM_INFO * hmminfo)100 hmm_count_logical_num(HTK_HMM_INFO *hmminfo)
101 {
102 HMM_Logical *lg;
103 int n;
104
105 n = 0;
106 for (lg = hmminfo->lgstart; lg; lg = lg->next) n++;
107 hmminfo->totallogicalnum = n;
108 }
109
110 /**
111 * @brief Add all physical %HMM to logical %HMM.
112 *
113 * This function should be called only if HMMList is not specified.
114 * Julius assumes all the triphones should be explicitly mapped
115 * using HMMList file.
116 *
117 * @param hmminfo [in] %HMM definition data.
118 */
119 void
hmm_add_physical_to_logical(HTK_HMM_INFO * hmminfo)120 hmm_add_physical_to_logical(HTK_HMM_INFO *hmminfo)
121 {
122 HMM_Logical *new, *match = NULL;
123 HTK_HMM_Data *ph;
124
125 for (ph = hmminfo->start; ph; ph = ph->next) {
126
127 /* check if same name already exist */
128 if (hmminfo->logical_root != NULL) {
129 match = aptree_search_data(ph->name, hmminfo->logical_root);
130 if (match != NULL && strmatch(match->name, ph->name)) {
131 /* the physcal name was already mapped to other HMMs in HMMList */
132 jlog("Warning: hmm_lookup: \"%s\" is defined in hmmdefs, but \"%s\" will be used instead\n", ph->name, (match->body.defined)->name);
133 continue;
134 }
135 }
136 /* create new HMM_Logical */
137 /* body refers to the physical HMM */
138 new = (HMM_Logical *)mybmalloc2(sizeof(HMM_Logical), &(hmminfo->lroot));
139 new->name = (char *)mybmalloc2(strlen(ph->name) + 1, &(hmminfo->lroot));
140 strcpy(new->name, ph->name);
141 new->is_pseudo = FALSE;
142 new->body.defined = ph;
143 new->next = hmminfo->lgstart;
144 hmminfo->lgstart = new;
145 if (hmminfo->logical_root == NULL) {
146 hmminfo->logical_root = aptree_make_root_node(new, &(hmminfo->lroot));
147 } else {
148 aptree_add_entry(new->name, new, match->name, &(hmminfo->logical_root), &(hmminfo->lroot));
149 }
150 }
151
152 /* re-count total number */
153 hmm_count_logical_num(hmminfo);
154 }
155
156
157
158 /**
159 * @brief Add a pseudo monophone and pseudo biphone to logical %HMM.
160 *
161 * Logical %HMM specified in HMMlist precedes
162 * pseudo %HMM: if some monophones or biphones are already
163 * defined in HMMList, pseudo %HMM will not be added.
164 *
165 * @param hmminfo [in] %HMM definition data.
166 * @param name [in] name of the pseudo phone to add.
167 */
168 static boolean
hmm_add_pseudo_phones_sub(HTK_HMM_INFO * hmminfo,char * name)169 hmm_add_pseudo_phones_sub(HTK_HMM_INFO *hmminfo, char *name)
170 {
171 HMM_Logical *new, *match;
172
173 /* check if already exist */
174 match = aptree_search_data(name, hmminfo->logical_root);
175 if (match != NULL && strmatch(match->name, name)) {
176 /* already exist in list */
177 /* if (! match->is_pseudo) {*/
178 /* this pseudo-HMM is already defined as real HMM in hmmdefs or in HMMList */
179 /*designated_count++;
180 }*/
181 } else {
182 /* create new HMM_Logical with pseudo body */
183 new = (HMM_Logical *)mybmalloc2(sizeof(HMM_Logical), &(hmminfo->lroot));
184 new->name = (char *)mybmalloc2(strlen(name) + 1, &(hmminfo->lroot));
185 strcpy(new->name, name);
186 new->is_pseudo = TRUE;
187 new->body.pseudo = cdset_lookup(hmminfo, name);
188 if (new->body.pseudo == NULL) { /* should never happen */
189 jlog("Error: hmm_lookup: tried to add pseudo phone \"%s\" to logical HMM, but no corresponding CD_Set found. Why??\n");
190 return FALSE;
191 }
192 new->next = hmminfo->lgstart;
193 hmminfo->lgstart = new;
194 if (hmminfo->logical_root == NULL) {
195 hmminfo->logical_root = aptree_make_root_node(new, &(hmminfo->lroot));
196 } else {
197 aptree_add_entry(new->name, new, match->name, &(hmminfo->logical_root), &(hmminfo->lroot));
198 }
199 hmminfo->totalpseudonum++;
200 }
201 return TRUE;
202 }
203
204 /**
205 * Update logical %HMM list by adding all the possible pseudo monophone
206 * and biphone to the list.
207 *
208 * @param hmminfo [in] %HMM definition data.
209 */
210 void
hmm_add_pseudo_phones(HTK_HMM_INFO * hmminfo)211 hmm_add_pseudo_phones(HTK_HMM_INFO *hmminfo)
212 {
213 HMM_Logical *lg;
214 char buf[MAX_HMMNAME_LEN];
215 boolean ok_p = TRUE;
216
217 hmminfo->totalpseudonum = 0;
218 /* add pseudo monophone */
219 for (lg = hmminfo->lgstart; lg; lg = lg->next) {
220 if (lg->is_pseudo) continue;
221 if (hmm_add_pseudo_phones_sub(hmminfo, center_name(lg->name, buf)) == FALSE) {
222 jlog("Error: hmm_lookup: failed to add \"%s\" as logical\n", center_name(lg->name, buf));
223 ok_p = FALSE;
224 }
225 }
226 /* add pseudo biphone, i.e. "a-k" etc. */
227 for (lg = hmminfo->lgstart; lg; lg = lg->next) {
228 if (lg->is_pseudo) continue;
229 if (hmm_add_pseudo_phones_sub(hmminfo, leftcenter_name(lg->name, buf)) == FALSE) {
230 jlog("Error: hmm_lookup: failed to add \"%s\" as logical\n", leftcenter_name(lg->name, buf));
231 ok_p = FALSE;
232 }
233 }
234 /* add pseudo biphone, i.e. "k+e" etc. */
235 for (lg = hmminfo->lgstart; lg; lg = lg->next) {
236 if (lg->is_pseudo) continue;
237 if (hmm_add_pseudo_phones_sub(hmminfo, rightcenter_name(lg->name, buf)) == FALSE) {
238 jlog("Error: hmm_lookup: failed to add \"%s\" as logical\n", rightcenter_name(lg->name, buf));
239 ok_p = FALSE;
240 }
241 }
242 jlog("Stat: hmm_lookup: %d pseudo phones are added to logical HMM list\n", hmminfo->totalpseudonum);
243 /* re-count total number */
244 hmm_count_logical_num(hmminfo);
245 }
246
247 /**
248 * Generic function to get the number of states in a logical %HMM.
249 *
250 * @param lg [in] logical %HMM
251 *
252 * @return the number of states in the logical %HMM.
253 */
254 int
hmm_logical_state_num(HMM_Logical * lg)255 hmm_logical_state_num(HMM_Logical *lg)
256 {
257 int len;
258 if (lg->is_pseudo) len = lg->body.pseudo->state_num;
259 else len = lg->body.defined->state_num;
260 return(len);
261 }
262
263 /**
264 * Generic function to get transition matrix of a logical %HMM.
265 *
266 * @param lg [in] logical %HMM
267 *
268 * @return pointer to the transition matrix of the logical %HMM.
269 */
270 HTK_HMM_Trans *
hmm_logical_trans(HMM_Logical * lg)271 hmm_logical_trans(HMM_Logical *lg)
272 {
273 HTK_HMM_Trans *tr;
274 if (lg->is_pseudo) tr = lg->body.pseudo->tr;
275 else tr = lg->body.defined->tr;
276 return(tr);
277 }
278