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