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