1 /**
2 * @file paramselect.c
3 *
4 * <JA>
5 * @brief �ѥ����٥��ȥ�η��Υ����å���Ĵ��
6 *
7 * %HMM��������ħ�ѥ����η�������å����ޤ��������פ����פ��ʤ���硤
8 * ��ħ�ѥ����ΰ����������뤳�Ȥǰ��פ���褦Ĵ���Ǥ��뤫�ɤ���
9 * ���ߤޤ������㡧��ħ�̥ե����뤬 MFCC_E_D_Z (26����) ��Ϳ����줿
10 * �Ȥ���������ǥ뤬 MFCC_E_D_N_Z (25����) �Ǥ����硤�����ͥѥ���
11 * �����������Ȥ�Ĵ���Ǥ��ޤ�����
12 *
13 * Ĵ�����르�ꥺ��ϰʲ��ΤȤ���Ǥ���
14 * -# ���Ϥγƥ٥��ȥ����Ǥ��б�����ޡ����� 0 �˽����
15 * -# %HMM���ᤵ��Ƥ��뷿���б����ʤ��٥��ȥ����Ǥ� 1 ��ޡ�������
16 * -# �����˥ѥ����ΰ����ݤ���ɬ�פ����ǡʥޡ�������Ƥ��ʤ����ǡ�
17 * �Τߤԡ����롥
18 *
19 * </JA>
20 * <EN>
21 * @brief Check and adjust parameter vector types
22 *
23 * This file is to check if %HMM parameter and input parameter are the same.
24 * If they are not the same, it then tries to modify the input to match the
25 * required format in %HMM. Available parameter modification is only to
26 * delete some part of the parameter (ex. MFCC_E_D_Z (26 dim.) can be
27 * modified to MFCC_E_D_N_Z (25 dim.) by just deleting the absolute power).
28 * Note that no parameter generation or conversion is implemented currently.
29 *
30 * The adjustment algorithm is as follows:
31 * -# Initialize mark to 0 for each input vector element.
32 * -# Compare parameter type and mark unnecessary element as EXCLUDE(=1).
33 * -# Allocate a new parameter area and copy needed (=NOT marked) element.
34 * </EN>
35 *
36 * @author Akinobu LEE
37 * @date Sun Feb 13 20:46:39 2005
38 *
39 * $Revision: 1.2 $
40 *
41 */
42 /*
43 * Copyright (c) 1991-2007 Kawahara Lab., Kyoto University
44 * Copyright (c) 2000-2005 Shikano Lab., Nara Institute of Science and Technology
45 * Copyright (c) 2005-2007 Julius project team, Nagoya Institute of Technology
46 * All rights reserved
47 */
48
49 #include <sent/stddefs.h>
50 #include <sent/htk_param.h>
51 #include <sent/htk_hmm.h>
52
53
54 /**
55 * Put exlusion marks for vector for @a len elements from @a loc -th dimension.
56 *
57 * @param loc [in] beginning dimension to mark
58 * @param len [in] number of dimension to mark from @a loc
59 * @param vmark [in] mark buffer
60 * @param vlen [in] length of vmark
61 */
62 static void
mark_exclude_vector(int loc,int len,int * vmark,int vlen)63 mark_exclude_vector(int loc, int len, int *vmark, int vlen)
64 {
65 int i;
66 #ifdef DEBUG
67 printf("delmark: %d-%d\n",loc, loc+len-1);
68 #endif
69 for (i=0;i<len;i++) {
70 #ifdef DEBUG
71 if (loc + i >= vlen) {
72 printf("delmark buffer exceeded!!\n");
73 exit(0);
74 }
75 #endif
76 vmark[loc+i] = 1;
77 }
78 #ifdef DEBUG
79 printf("now :");
80 for (i=0;i<vlen;i++) {
81 if (vmark[i] == 1) {
82 printf("-");
83 } else {
84 printf("O");
85 }
86 }
87 printf("\n");
88 #endif
89 }
90
91 /**
92 * @brief Execute exclusion for a parameter data according to the
93 * exclusion marks.
94 *
95 * Execute vector element exclusion will be done inline.
96 *
97 * @param p [i/o] parameter
98 * @param vmark [in] mark buffer
99 */
100 static void
exec_exclude_vectors(HTK_Param * p,int * vmark)101 exec_exclude_vectors(HTK_Param *p, int *vmark)
102 {
103 int src, dst;
104 unsigned int t;
105
106 /* shrink */
107 for(t = 0; t < p->samplenum; t++) {
108 dst = 0;
109 for (src = 0; src < p->veclen; src++) {
110 if (vmark[src] == 0) {
111 if (dst != src) p->parvec[t][dst] = p->parvec[t][src];
112 dst++;
113 }
114 }
115 }
116 p->veclen = dst;
117 #ifdef DEBUG
118 printf("new length = %d\n", p->veclen);
119 #endif
120 }
121
122
123 /**
124 * Guess the length of the base coefficient according to the total vector
125 * length and parameter type.
126 *
127 * @param p [in] parameter data
128 * @param qualtype [in] parameter type
129 *
130 * @return the guessed size of the base coefficient.
131 */
132 int
guess_basenum(HTK_Param * p,short qualtype)133 guess_basenum(HTK_Param *p, short qualtype)
134 {
135 int size;
136 int compnum;
137
138 compnum = 1 + ((qualtype & F_DELTA) ? 1 : 0) + ((qualtype & F_ACCL) ? 1 : 0);
139
140 size = p->veclen;
141 if (p->header.samptype & F_ENERGY_SUP) size += 1;
142 if ((size % compnum) != 0) {
143 jlog("Error: paramselect: illegal vector length (should not happen)\n");
144 return -1;
145 }
146 size /= compnum;
147 if (p->header.samptype & F_ENERGY) size -= 1;
148 if (p->header.samptype & F_ZEROTH) size -= 1;
149
150 return(size);
151 }
152
153 /* can add: _N */
154 /* can sub: _E_D_A_0 */
155
156 /**
157 * Compare source parameter type and required type in HTK %HMM, and set mark.
158 *
159 * @param src [in] input parameter
160 * @param dst_type_arg [in] required parameter type
161 * @param vmark [in] mark buffer
162 * @param vlen [in] length of vmark
163 * @param new_type [out] return the new type
164 *
165 * @return TRUE on success, FALSE on failure.
166 */
167 static boolean
select_param_vmark(HTK_Param * src,short dst_type_arg,int * vmark,int vlen,short * new_type)168 select_param_vmark(HTK_Param *src, short dst_type_arg, int *vmark, int vlen, short *new_type)
169 {
170 short dst_type;
171 short del_type, add_type;
172 int basenum, pb[3],pe[3],p0[3]; /* location */
173 int i, len;
174 char srcstr[80], dststr[80], buf[80];
175 short src_type;
176
177 src_type = src->header.samptype & ~(F_COMPRESS | F_CHECKSUM);
178 src_type &= ~(F_BASEMASK); /* only qualifier code needed */
179 srcstr[0] = '\0';
180 param_qualcode2str(srcstr, src_type, FALSE);
181 dst_type = dst_type_arg & ~(F_COMPRESS | F_CHECKSUM);
182 dst_type &= ~(F_BASEMASK); /* only qualifier code needed */
183 dststr[0] = '\0';
184 param_qualcode2str(dststr, dst_type, FALSE);
185
186 #ifdef DEBUG
187 printf("try to select qualifiers: %s -> %s\n", srcstr, dststr);
188 #endif
189
190 if (dst_type == F_ERR_INVALID) {
191 jlog("Error: paramselect: unknown parameter kind for selection: %s\n", dststr);
192 return(FALSE);
193 }
194
195 /* guess base coefficient num */
196 basenum = guess_basenum(src, src_type);
197 if (basenum < 0) { /* error */
198 return(FALSE);
199 }
200 #ifdef DEBUG
201 printf("base num = %d\n", basenum);
202 #endif
203
204 /* determine which component to use */
205 del_type = src_type & (~(dst_type));
206 add_type = (~(src_type)) & dst_type;
207
208 /* vector layout for exclusion*/
209 pb[0] = 0;
210 if ((src_type & F_ENERGY) && (src_type & F_ZEROTH)){
211 p0[0] = basenum;
212 pe[0] = basenum + 1;
213 len = basenum + 2;
214 } else if ((src_type & F_ENERGY) || (src_type & F_ZEROTH)){
215 p0[0] = pe[0] = basenum;
216 len = basenum + 1;
217 } else {
218 p0[0] = pe[0] = 0;
219 len = basenum;
220 }
221 for (i=1;i<3;i++) {
222 pb[i] = pb[i-1] + len;
223 pe[i] = pe[i-1] + len;
224 p0[i] = p0[i-1] + len;
225 }
226 if (src_type & F_ENERGY_SUP) {
227 pe[0] = 0;
228 for (i=1;i<3;i++) {
229 pb[i]--;
230 pe[i]--;
231 p0[i]--;
232 }
233 }
234
235 /* modification begin */
236 /* qualifier addition: "_N" */
237 #ifdef DEBUG
238 buf[0] = '\0';
239 printf("try to add: %s\n", param_qualcode2str(buf, add_type, FALSE));
240 #endif
241
242 if (add_type & F_ENERGY_SUP) {
243 if (src_type & F_ENERGY) {
244 mark_exclude_vector(pe[0], 1, vmark, vlen);
245 src_type = src_type | F_ENERGY_SUP;
246 } else if (src_type & F_ZEROTH) {
247 mark_exclude_vector(p0[0], 1, vmark, vlen);
248 src_type = src_type | F_ENERGY_SUP;
249 } else {
250 jlog("Warning: paramselect: \"_N\" needs \"_E\" or \"_0\". ignored\n");
251 }
252 add_type = add_type & (~(F_ENERGY_SUP)); /* set to 0 */
253 }
254 if (add_type != 0) { /* others left */
255 buf[0] = '\0';
256 jlog("Warning: paramselect: can do only parameter exclusion. qualifiers %s ignored\n", param_qualcode2str(buf, add_type, FALSE));
257 }
258
259 /* qualifier excludeion: "_D","_A","_0","_E" */
260 #ifdef DEBUG
261 buf[0] = '\0';
262 printf("try to del: %s\n", param_qualcode2str(buf, del_type, FALSE));
263 #endif
264
265 if (del_type & F_DELTA) del_type |= F_ACCL;
266 /* mark delete vector */
267 if (del_type & F_ACCL) {
268 mark_exclude_vector(pb[2], len, vmark, vlen);
269 src_type &= ~(F_ACCL);
270 del_type &= ~(F_ACCL);
271 }
272 if (del_type & F_DELTA) {
273 mark_exclude_vector(pb[1], len, vmark, vlen);
274 src_type &= ~(F_DELTA);
275 del_type &= ~(F_DELTA);
276 }
277
278 if (del_type & F_ENERGY) {
279 mark_exclude_vector(pe[2], 1, vmark, vlen);
280 mark_exclude_vector(pe[1], 1, vmark, vlen);
281 if (!(src_type & F_ENERGY_SUP)) {
282 mark_exclude_vector(pe[0], 1, vmark, vlen);
283 }
284 src_type &= ~(F_ENERGY | F_ENERGY_SUP);
285 del_type &= ~(F_ENERGY | F_ENERGY_SUP);
286 }
287 if (del_type & F_ZEROTH) {
288 mark_exclude_vector(p0[2], 1, vmark, vlen);
289 mark_exclude_vector(p0[1], 1, vmark, vlen);
290 if (!(src_type & F_ENERGY_SUP)) {
291 mark_exclude_vector(p0[0], 1, vmark, vlen);
292 }
293 src_type &= ~(F_ZEROTH | F_ENERGY_SUP);
294 del_type &= ~(F_ZEROTH | F_ENERGY_SUP);
295 }
296
297 if (del_type != 0) { /* left */
298 buf[0] = '\0';
299 jlog("Warning: paramselect: cannot exclude qualifiers %s. selection ignored\n", param_qualcode2str(buf, del_type, FALSE));
300 }
301
302
303 *new_type = src_type;
304
305 return(TRUE);
306 }
307
308
309 /**
310 * Extracts needed parameter vector specified in dst_type_arg from src,
311 * and returns newly allocated parameter structure.
312 *
313 * @param src [in] input parameter
314 * @param dst_type_arg [in] required parameter type
315 *
316 * @return newly allocated adjusted parameter, NULL on failure.
317 */
318 static boolean
select_param_kind(HTK_Param * p,short dst_type_arg)319 select_param_kind(HTK_Param *p, short dst_type_arg)
320 {
321 int *vmark;
322 int vlen;
323 int i;
324 short new_type;
325
326 /* prepare work area */
327 vmark = (int *)mymalloc(sizeof(int) * p->veclen);
328 vlen = p->veclen;
329 for (i=0;i<vlen;i++) {
330 vmark[i] = 0;
331 }
332
333 /* mark to determine operation */
334 if (select_param_vmark(p, dst_type_arg, vmark, vlen, &new_type) == FALSE) return(FALSE);
335 /* execute deletion (copy needed to new param)*/
336 exec_exclude_vectors(p, vmark);
337
338 /* copy & set header info */
339 p->header.sampsize = p->veclen * sizeof(VECT);
340 p->header.samptype = new_type | (p->header.samptype & F_BASEMASK);
341
342 #ifdef DEBUG
343 {
344 char pbuf[80];
345 printf("new param made: %s\n", param_code2str(pbuf, p->header.samptype, FALSE));
346 }
347 #endif
348
349 /* free work area */
350 free(vmark);
351
352 return(TRUE);
353 }
354
355 /**
356 * @brief Top function to adjust parameter.
357 *
358 * It compares the types for the given parameter @a param and
359 * %HMM definition @a hmminfo. If type is not the same, adjustment will be
360 * tried.
361 *
362 * @param hmminfo [in] HTK %HMM definition
363 * @param param [i/o] input parameter, will be freed if adjustment was
364 * performed in this function
365 * @param vflag [in] if TRUE, output verbose messages
366 *
367 * @return 1 on success, 0 if no adjustment needed, or -1 on failure (in case
368 * parameter type does not match even by the adjustment).
369 */
370 int
param_check_and_adjust(HTK_HMM_INFO * hmminfo,HTK_Param * param,boolean vflag)371 param_check_and_adjust(HTK_HMM_INFO *hmminfo, HTK_Param *param, boolean vflag)
372 {
373 char pbuf[80],hbuf[80];
374
375 param_code2str(pbuf, (short)(param->header.samptype & ~(F_COMPRESS | F_CHECKSUM)), FALSE);
376 param_code2str(hbuf, hmminfo->opt.param_type, FALSE);
377 if (!check_param_basetype(hmminfo, param)) {
378 /* error if base type not match */
379 jlog("Error: paramselect: incompatible parameter type\n");
380 jlog("Error: paramselect: HMM trained by %s(%d)\n", hbuf, hmminfo->opt.vec_size);
381 jlog("Error: paramselect: input parameter is %s(%d)\n", pbuf, param->veclen);
382 return -1;
383 }
384 if (!check_param_coherence(hmminfo, param)) {
385 /* try to select needed parameter vector */
386 if (vflag) jlog("Stat: paramselect: attaching %s\n", pbuf);
387 if (select_param_kind(param, hmminfo->opt.param_type) == FALSE) {
388 if (vflag) jlog("Error: paramselect: failed to attach to %s\n", hbuf);
389
390 jlog("Error: paramselect: incompatible parameter type\n");
391 jlog("Error: paramselect: HMM trained by %s(%d)\n", hbuf, hmminfo->opt.vec_size);
392 jlog("Error: paramselect: input parameter is %s(%d)\n", pbuf, param->veclen);
393 return -1;
394 }
395 param_code2str(pbuf, param->header.samptype, FALSE);
396 if (vflag) jlog("Stat: paramselect: attached to %s\n", pbuf);
397 return(1);
398 }
399 return(0);
400 }
401