1 /**
2 * @file rdhmmdef_trans.c
3 *
4 * <JA>
5 * @brief HTK %HMM ����ե�������ɤ߹��ߡ����ܹ���
6 *
7 * ���ܳ�Ψ�ϥե������ɤ߹��߽�λ��� log10 ���Ѵ�����ޤ���
8 * </JA>
9 *
10 * <EN>
11 * @brief Read HTK %HMM definition file: transition matrix
12 *
13 * The transition probabilities will be converted to log10 scale
14 * after finished reading the while %HMM definition file.
15 * </EN>
16 *
17 * @author Akinobu LEE
18 * @date Wed Feb 16 03:50:55 2005
19 *
20 * $Revision: 1.3 $
21 *
22 */
23 /*
24 * Copyright (c) 1991-2007 Kawahara Lab., Kyoto University
25 * Copyright (c) 2000-2005 Shikano Lab., Nara Institute of Science and Technology
26 * Copyright (c) 2005-2007 Julius project team, Nagoya Institute of Technology
27 * All rights reserved
28 */
29
30 #include <sent/stddefs.h>
31 #include <sent/htk_hmm.h>
32
33 extern char *rdhmmdef_token; ///< Current token
34
35 /**
36 * Allocate a new data area and return it.
37 *
38 * @return pointer to newly allocated data.
39 */
40 static HTK_HMM_Trans *
trans_new(HTK_HMM_INFO * hmm)41 trans_new(HTK_HMM_INFO *hmm)
42 {
43 HTK_HMM_Trans *new;
44
45 new = (HTK_HMM_Trans *)mybmalloc2(sizeof(HTK_HMM_Trans), &(hmm->mroot));
46 new->name = (char *)NULL;
47 new->statenum = 0;
48 new->a = (PROB **)NULL;
49 new->next = NULL;
50
51 return(new);
52 }
53
54 /**
55 * Add a new data to the global structure.
56 *
57 * @param hmm [i/o] %HMM definition data to store it
58 * @param new [in] new data to be added
59 */
60 void
trans_add(HTK_HMM_INFO * hmm,HTK_HMM_Trans * new)61 trans_add(HTK_HMM_INFO *hmm, HTK_HMM_Trans *new)
62 {
63 HTK_HMM_Trans *match;
64
65 /* link data structure */
66 new->next = hmm->trstart;
67 hmm->trstart = new;
68
69 if (new->name != NULL) {
70 /* add index to search index tree */
71 if (hmm->tr_root == NULL) {
72 hmm->tr_root = aptree_make_root_node(new, &(hmm->mroot));
73 } else {
74 match = aptree_search_data(new->name, hmm->tr_root);
75 if (match != NULL && strmatch(match->name,new->name)) {
76 jlog("Error: rdhmmdef_trans: ~t \"%s\" is already defined\n", new->name);
77 rderr(NULL);
78 } else {
79 aptree_add_entry(new->name, new, match->name, &(hmm->tr_root), &(hmm->mroot));
80 }
81 }
82 }
83 }
84
85 /**
86 * Look up a data macro by the name.
87 *
88 * @param hmm [in] %HMM definition data
89 * @param keyname [in] macro name to find
90 *
91 * @return pointer to the found data, or NULL if not found.
92 */
93 static HTK_HMM_Trans *
trans_lookup(HTK_HMM_INFO * hmm,char * keyname)94 trans_lookup(HTK_HMM_INFO *hmm, char *keyname)
95 {
96 HTK_HMM_Trans *t;
97
98 t = aptree_search_data(keyname, hmm->tr_root);
99 if (t != NULL && strmatch(t->name, keyname)) {
100 return t;
101 } else {
102 return NULL;
103 }
104 }
105
106 /**
107 * @brief Read one new data and returns the pointer
108 *
109 * If a sub-component of this data is directly defined at here, they
110 * will be read from here and assigned to this data. If a sub-component
111 * is not defined here but a macro name referencing to the component previously
112 * defined in other place, the data will be searched by the macro name and
113 * the pointer to the found component will be assigned to this model.
114 *
115 * @param fp [in] file pointer
116 * @param hmm [i/o] %HMM definition data
117 *
118 * @return pointer to the newly read data.
119 */
120 static HTK_HMM_Trans *
trans_read(FILE * fp,HTK_HMM_INFO * hmm)121 trans_read(FILE *fp, HTK_HMM_INFO *hmm)
122 {
123 HTK_HMM_Trans *new;
124 int i,j;
125 PROB prob;
126 PROB *atmp;
127
128 /* read tag */
129 if (!currentis("TRANSP")) rderr("<TRANSP> not found"); /* not match */
130 read_token(fp);
131
132 /* read statenum */
133 new = trans_new(hmm);
134 NoTokErr("missing TRANSP state num");
135 new->statenum = atoi(rdhmmdef_token);
136 read_token(fp);
137
138 /* allocate array */
139 new->a = (PROB **)mybmalloc2(sizeof(PROB *) * new->statenum, &(hmm->mroot));
140 atmp = (PROB *)mybmalloc2(sizeof(PROB) * new->statenum * new->statenum, &(hmm->mroot));
141 new->a[0] = &(atmp[0]);
142 for (i=1;i<new->statenum;i++) {
143 new->a[i] = &(atmp[i*new->statenum]);
144 }
145
146 /* begin reading transition prob */
147 for (i=0;i<new->statenum; i++) {
148 for (j=0;j<new->statenum; j++) {
149 NoTokErr("missing some TRANSP value");
150 prob = (PROB)atof(rdhmmdef_token);
151 new->a[i][j] = prob;
152 read_token(fp);
153 }
154 }
155
156 return(new);
157 }
158
159 /**
160 * @brief Return a pointer to the data located at the current point.
161 *
162 * If the current point is a macro reference, the pointer to the
163 * already defined data will be searched and returned.
164 * Otherwise, the definition of the data will be read from the current
165 * point and pointer to the newly allocated data will be returned.
166 *
167 * @param fp [in] file pointer
168 * @param hmm [i/o] %HMM definition data
169 *
170 * @return pointer to the data located at the current point.
171 */
172 HTK_HMM_Trans *
get_trans_data(FILE * fp,HTK_HMM_INFO * hmm)173 get_trans_data(FILE *fp, HTK_HMM_INFO *hmm)
174 {
175 HTK_HMM_Trans *tmp;
176
177 if (currentis("TRANSP")) {
178 /* definition: define transition data, and return the pointer */
179 tmp = trans_read(fp, hmm);
180 tmp->name = NULL; /* no name */
181 trans_add(hmm, tmp);
182 return(tmp);
183 } else if (currentis("~t")) {
184 /* macro reference: lookup and return the pointer */
185 read_token(fp);
186 NoTokErr("missing TRANSP macro name");
187 tmp = trans_lookup(hmm, rdhmmdef_token);
188 if (tmp == NULL) {
189 jlog("Error: rdhmmdef_trans: ~t \"%s\" not defined\n", rdhmmdef_token);
190 rderr(NULL);
191 }
192 read_token(fp);
193 return(tmp);
194 } else {
195 rderr("no transition data");
196 return(NULL);
197 }
198 }
199
200 /**
201 * Read a new data and store it as a macro.
202 *
203 * @param name [in] macro name
204 * @param fp [in] file pointer
205 * @param hmm [i/o] %HMM definition data
206 */
207 void
def_trans_macro(char * name,FILE * fp,HTK_HMM_INFO * hmm)208 def_trans_macro(char *name, FILE *fp, HTK_HMM_INFO *hmm)
209 {
210 HTK_HMM_Trans *new;
211
212 /* read in data and return newly malloced data */
213 new = trans_read(fp, hmm);
214
215 /* register it to the grobal HMM structure */
216 new->name = name;
217 trans_add(hmm, new);
218 }
219