/**
* @file paramselect.c
*
*
* @brief パラメータベクトルの型のチェックと調整
*
* %HMMと入力特徴パラメータの型をチェックします.タイプが一致しない場合,
* 特徴パラメータの一部を削除することで一致するよう調整できるかどうか
* を試みます.(例:特徴量ファイルが MFCC_E_D_Z (26次元) で与えられた
* とき,音響モデルが MFCC_E_D_N_Z (25次元) である場合,絶対値パワー項を
* 差し引くことで調整できます.)
*
* 調整アルゴリズムは以下のとおりです.
* -# 入力の各ベクトル要素に対応するマークを 0 に初期化
* -# %HMMで要求されている型に対応しないベクトル要素に 1 をマークする
* -# 新たにパラメータ領域を確保し,必要な要素(マークされていない要素)
* のみをコピーする.
*
*
*
* @brief Check and adjust parameter vector types
*
* This file is to check if %HMM parameter and input parameter are the same.
* If they are not the same, it then tries to modify the input to match the
* required format in %HMM. Available parameter modification is only to
* delete some part of the parameter (ex. MFCC_E_D_Z (26 dim.) can be
* modified to MFCC_E_D_N_Z (25 dim.) by just deleting the absolute power).
* Note that no parameter generation or conversion is implemented currently.
*
* The adjustment algorithm is as follows:
* -# Initialize mark to 0 for each input vector element.
* -# Compare parameter type and mark unnecessary element as EXCLUDE(=1).
* -# Allocate a new parameter area and copy needed (=NOT marked) element.
*
*
* @author Akinobu LEE
* @date Sun Feb 13 20:46:39 2005
*
* $Revision: 1.4 $
*
*/
/*
* Copyright (c) 1991-2012 Kawahara Lab., Kyoto University
* Copyright (c) 2000-2005 Shikano Lab., Nara Institute of Science and Technology
* Copyright (c) 2005-2012 Julius project team, Nagoya Institute of Technology
* All rights reserved
*/
#include
#include
#include
/**
* Put exlusion marks for vector for @a len elements from @a loc -th dimension.
*
* @param loc [in] beginning dimension to mark
* @param len [in] number of dimension to mark from @a loc
* @param vmark [in] mark buffer
* @param vlen [in] length of vmark
*/
static void
mark_exclude_vector(int loc, int len, int *vmark, int vlen)
{
int i;
#ifdef DEBUG
printf("delmark: %d-%d\n",loc, loc+len-1);
#endif
for (i=0;i= vlen) {
printf("delmark buffer exceeded!!\n");
exit(0);
}
#endif
vmark[loc+i] = 1;
}
#ifdef DEBUG
printf("now :");
for (i=0;isamplenum; t++) {
dst = 0;
for (src = 0; src < p->veclen; src++) {
if (vmark[src] == 0) {
if (dst != src) p->parvec[t][dst] = p->parvec[t][src];
dst++;
}
}
}
p->veclen = dst;
#ifdef DEBUG
printf("new length = %d\n", p->veclen);
#endif
}
/**
* Guess the length of the base coefficient according to the total vector
* length and parameter type.
*
* @param p [in] parameter data
* @param qualtype [in] parameter type
*
* @return the guessed size of the base coefficient.
*/
int
guess_basenum(HTK_Param *p, short qualtype)
{
int size;
int compnum;
compnum = 1 + ((qualtype & F_DELTA) ? 1 : 0) + ((qualtype & F_ACCL) ? 1 : 0);
size = p->veclen;
if (p->header.samptype & F_ENERGY_SUP) size += 1;
if ((size % compnum) != 0) {
jlog("Error: paramselect: illegal vector length (should not happen)\n");
return -1;
}
size /= compnum;
if (p->header.samptype & F_ENERGY) size -= 1;
if (p->header.samptype & F_ZEROTH) size -= 1;
return(size);
}
/* can add: _N */
/* can sub: _E_D_A_0 */
/**
* Compare source parameter type and required type in HTK %HMM, and set mark.
*
* @param src [in] input parameter
* @param dst_type_arg [in] required parameter type
* @param vmark [in] mark buffer
* @param vlen [in] length of vmark
* @param new_type [out] return the new type
*
* @return TRUE on success, FALSE on failure.
*/
static boolean
select_param_vmark(HTK_Param *src, short dst_type_arg, int *vmark, int vlen, short *new_type)
{
short dst_type;
short del_type, add_type;
int basenum, pb[3],pe[3],p0[3]; /* location */
int i, len;
char srcstr[80], dststr[80], buf[80];
short src_type;
src_type = src->header.samptype & ~(F_COMPRESS | F_CHECKSUM);
src_type &= ~(F_BASEMASK); /* only qualifier code needed */
srcstr[0] = '\0';
param_qualcode2str(srcstr, src_type, FALSE);
dst_type = dst_type_arg & ~(F_COMPRESS | F_CHECKSUM);
dst_type &= ~(F_BASEMASK); /* only qualifier code needed */
dststr[0] = '\0';
param_qualcode2str(dststr, dst_type, FALSE);
#ifdef DEBUG
printf("try to select qualifiers: %s -> %s\n", srcstr, dststr);
#endif
if (dst_type == F_ERR_INVALID) {
jlog("Error: paramselect: unknown parameter kind for selection: %s\n", dststr);
return(FALSE);
}
/* guess base coefficient num */
basenum = guess_basenum(src, src_type);
if (basenum < 0) { /* error */
return(FALSE);
}
#ifdef DEBUG
printf("base num = %d\n", basenum);
#endif
/* determine which component to use */
del_type = src_type & (~(dst_type));
add_type = (~(src_type)) & dst_type;
/* vector layout for exclusion*/
pb[0] = 0;
if ((src_type & F_ENERGY) && (src_type & F_ZEROTH)){
p0[0] = basenum;
pe[0] = basenum + 1;
len = basenum + 2;
} else if ((src_type & F_ENERGY) || (src_type & F_ZEROTH)){
p0[0] = pe[0] = basenum;
len = basenum + 1;
} else {
p0[0] = pe[0] = 0;
len = basenum;
}
for (i=1;i<3;i++) {
pb[i] = pb[i-1] + len;
pe[i] = pe[i-1] + len;
p0[i] = p0[i-1] + len;
}
if (src_type & F_ENERGY_SUP) {
pe[0] = 0;
for (i=1;i<3;i++) {
pb[i]--;
pe[i]--;
p0[i]--;
}
}
/* modification begin */
/* qualifier addition: "_N" */
#ifdef DEBUG
buf[0] = '\0';
printf("try to add: %s\n", param_qualcode2str(buf, add_type, FALSE));
#endif
if (add_type & F_ENERGY_SUP) {
if (src_type & F_ENERGY) {
mark_exclude_vector(pe[0], 1, vmark, vlen);
src_type = src_type | F_ENERGY_SUP;
} else if (src_type & F_ZEROTH) {
mark_exclude_vector(p0[0], 1, vmark, vlen);
src_type = src_type | F_ENERGY_SUP;
} else {
jlog("Warning: paramselect: \"_N\" needs \"_E\" or \"_0\". ignored\n");
}
add_type = add_type & (~(F_ENERGY_SUP)); /* set to 0 */
}
if (add_type != 0) { /* others left */
buf[0] = '\0';
jlog("Warning: paramselect: can do only parameter exclusion. qualifiers %s ignored\n", param_qualcode2str(buf, add_type, FALSE));
}
/* qualifier excludeion: "_D","_A","_0","_E" */
#ifdef DEBUG
buf[0] = '\0';
printf("try to del: %s\n", param_qualcode2str(buf, del_type, FALSE));
#endif
if (del_type & F_DELTA) del_type |= F_ACCL;
/* mark delete vector */
if (del_type & F_ACCL) {
mark_exclude_vector(pb[2], len, vmark, vlen);
src_type &= ~(F_ACCL);
del_type &= ~(F_ACCL);
}
if (del_type & F_DELTA) {
mark_exclude_vector(pb[1], len, vmark, vlen);
src_type &= ~(F_DELTA);
del_type &= ~(F_DELTA);
}
if (del_type & F_ENERGY) {
mark_exclude_vector(pe[2], 1, vmark, vlen);
mark_exclude_vector(pe[1], 1, vmark, vlen);
if (!(src_type & F_ENERGY_SUP)) {
mark_exclude_vector(pe[0], 1, vmark, vlen);
}
src_type &= ~(F_ENERGY | F_ENERGY_SUP);
del_type &= ~(F_ENERGY | F_ENERGY_SUP);
}
if (del_type & F_ZEROTH) {
mark_exclude_vector(p0[2], 1, vmark, vlen);
mark_exclude_vector(p0[1], 1, vmark, vlen);
if (!(src_type & F_ENERGY_SUP)) {
mark_exclude_vector(p0[0], 1, vmark, vlen);
}
src_type &= ~(F_ZEROTH | F_ENERGY_SUP);
del_type &= ~(F_ZEROTH | F_ENERGY_SUP);
}
if (del_type != 0) { /* left */
buf[0] = '\0';
jlog("Warning: paramselect: cannot exclude qualifiers %s. selection ignored\n", param_qualcode2str(buf, del_type, FALSE));
}
*new_type = src_type;
return(TRUE);
}
/**
* Extracts needed parameter vector specified in dst_type_arg from src,
* and returns newly allocated parameter structure.
*
* @param src [in] input parameter
* @param dst_type_arg [in] required parameter type
*
* @return newly allocated adjusted parameter, NULL on failure.
*/
static boolean
select_param_kind(HTK_Param *p, short dst_type_arg)
{
int *vmark;
int vlen;
int i;
short new_type;
/* prepare work area */
vmark = (int *)mymalloc(sizeof(int) * p->veclen);
vlen = p->veclen;
for (i=0;iheader.sampsize = p->veclen * sizeof(VECT);
p->header.samptype = new_type | (p->header.samptype & F_BASEMASK);
#ifdef DEBUG
{
char pbuf[80];
printf("new param made: %s\n", param_code2str(pbuf, p->header.samptype, FALSE));
}
#endif
/* free work area */
free(vmark);
return(TRUE);
}
/**
* @brief Top function to adjust parameter.
*
* It compares the types for the given parameter @a param and
* %HMM definition @a hmminfo. If type is not the same, adjustment will be
* tried.
*
* @param hmminfo [in] HTK %HMM definition
* @param param [i/o] input parameter, will be freed if adjustment was
* performed in this function
* @param vflag [in] if TRUE, output verbose messages
*
* @return 1 on success, 0 if no adjustment needed, or -1 on failure (in case
* parameter type does not match even by the adjustment).
*/
int
param_check_and_adjust(HTK_HMM_INFO *hmminfo, HTK_Param *param, boolean vflag)
{
char pbuf[80],hbuf[80];
param_code2str(pbuf, (short)(param->header.samptype & ~(F_COMPRESS | F_CHECKSUM)), FALSE);
param_code2str(hbuf, hmminfo->opt.param_type, FALSE);
if (!check_param_basetype(hmminfo, param)) {
/* error if base type not match */
jlog("Error: paramselect: incompatible parameter type\n");
jlog("Error: paramselect: HMM trained by %s(%d)\n", hbuf, hmminfo->opt.vec_size);
jlog("Error: paramselect: input parameter is %s(%d)\n", pbuf, param->veclen);
return -1;
}
if (!check_param_coherence(hmminfo, param)) {
/* try to select needed parameter vector */
if (vflag) jlog("Stat: paramselect: attaching %s\n", pbuf);
if (select_param_kind(param, hmminfo->opt.param_type) == FALSE) {
if (vflag) jlog("Error: paramselect: failed to attach to %s\n", hbuf);
jlog("Error: paramselect: incompatible parameter type\n");
jlog("Error: paramselect: HMM trained by %s(%d)\n", hbuf, hmminfo->opt.vec_size);
jlog("Error: paramselect: input parameter is %s(%d)\n", pbuf, param->veclen);
return -1;
}
param_code2str(pbuf, param->header.samptype, FALSE);
if (vflag) jlog("Stat: paramselect: attached to %s\n", pbuf);
return(1);
}
return(0);
}