/**
* @file read_rdhmmlist.c
*
*
* @brief HMMListファイルを読み込む(バイナリ版)
*
* HMMList ファイルは,辞書上の音素表記(トライフォン表記)から
* 実際に定義されている %HMM へのマッピングを行なうファイルです.
*
* HMMListファイルでは,登場しうる音素について,対応する
* HMM 定義の名前を記述します.一行に1つづつ,第1カラムに音素名,
* スペースで区切って第2カラムに定義されている実際の %HMM 名を指定します.
* 第1カラムと第2カラムが全く同じ場合,すなわちその音素名のモデルが直接
* %HMM として定義されている場合は,第2カラムは省略することができます.
*
* トライフォン使用時は,HMMListファイルで登場しうる全てのトライフォンに
* ついて記述する必要がある点に注意して下さい.もし与えられた認識辞書
* 上で登場しうるトライフォンがHMMListに記述されていない場合,
* エラーとなります.
*
*
*
* @brief Read in HMMList file from binary format
*
* HMMList file specifies how the phones as described in word dictionary,
* or their context-dependent form, should be mapped to actual defined %HMM.
*
* In HMMList file, the possible phone names and their corresponding %HMM
* name should be specified one per line. The phone name should be put on
* the first column, and its corresponding %HMM name in the HTK %HMM definition
* file should be defined on the second column. If the two strings are
* the same, which occurs when a %HMM of the phone name is directly defined,
* the second column can be omitted.
*
* When using a triphone model, ALL the possible triphones that can appear
* on the given word dictionary should be specified in the HMMList file.
* If some possible triphone are not specified in the HMMList, Julius
* produces error.
*
*
* @author Akinobu LEE
* @date Wed Feb 16 04:04:23 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
/**
* Callback to read hmmlist data from file.
*
* @param data_p [out] pointer to index tree node to store the leaf content
* @param data [in] user data
* @param fp [in] file pointer to read
*
* @return TRUE on success, FALSE on failure.
*/
static boolean
load_hmmlist_callback(void **data_p, void *data, FILE *fp)
{
HTK_HMM_INFO *hmminfo = data;
HMM_Logical *new;
int len;
char buf[MAX_HMMNAME_LEN];
HTK_HMM_Data *d;
new = (HMM_Logical *)mybmalloc2(sizeof(HMM_Logical), &(hmminfo->lroot));
if (myfread(&(new->is_pseudo), sizeof(boolean), 1, fp) < 1) return FALSE;
if (myfread(&len, sizeof(int), 1, fp) < 1) return FALSE;
new->name = (char *)mybmalloc2(len, &(hmminfo->lroot));
if (myfread(new->name, len, 1, fp) < 1) return FALSE;
if (myfread(&len, sizeof(int), 1, fp) < 1) return FALSE;
if (myfread(buf, len, 1, fp) < 1) return FALSE;
if (new->is_pseudo) {
jlog("Error: sorry, pseudo logical phone saving not implemented yet\n");
return FALSE;
} else {
d = htk_hmmdata_lookup_physical(hmminfo, buf);
if (d == NULL) {
jlog("Error: load_hmmlist_callback: no name \"%s\" in hmmdefs!\n", buf);
return FALSE;
}
new->body.defined = d;
}
new->next = hmminfo->lgstart;
hmminfo->lgstart = new;
*data_p = new;
return TRUE;
}
typedef struct {
HTK_HMM_Trans **tr;
HTK_HMM_State **st;
} ListData;
/**
* Callback to read cdset data from file.
*
* @param data_p [out] pointer to index tree node to store the leaf content
* @param data [in] user data
* @param fp [in] file pointer to read
*
* @return TRUE on success, FALSE on failure.
*/
static boolean
load_cdset_callback(void **data_p, void *data, FILE *fp)
{
HTK_HMM_INFO *hmminfo = data;
ListData *ld = (ListData *)hmminfo->hook;
CD_Set *new;
int len;
int id;
int i, j;
HTK_HMM_Trans *ttmp;
new = (CD_Set *)mybmalloc2(sizeof(CD_Set), &(hmminfo->cdset_root));
if (myfread(&len, sizeof(int), 1, fp) < 1) return FALSE;
new->name = (char *)mybmalloc2(len, &(hmminfo->cdset_root));
if (myfread(new->name, len, 1, fp) < 1) return FALSE;
if (myfread(&id, sizeof(int), 1, fp) < 1) return FALSE;
new->tr = ld->tr[id];
if (myfread(&(new->state_num), sizeof(unsigned short), 1, fp) < 1) return FALSE;
new->stateset = (CD_State_Set *)mybmalloc2(sizeof(CD_State_Set) * new->state_num, &(hmminfo->cdset_root));
for(i=0;istate_num;i++) {
if (myfread(&(new->stateset[i].num), sizeof(unsigned short), 1, fp) < 1) return FALSE;
new->stateset[i].maxnum = new->stateset[i].num;
new->stateset[i].s = (HTK_HMM_State **)mybmalloc2(sizeof(HTK_HMM_State *) * new->stateset[i].num, &(hmminfo->cdset_root));
for(j=0;jstateset[i].num;j++) {
if (myfread(&id, sizeof(int), 1, fp) < 1) return FALSE;
new->stateset[i].s[j] = ld->st[id];
}
}
*data_p = new;
return TRUE;
}
/**
* Load HMMList and CDSet data from binary file.
*
* @param fp [in] file pointer to read
* @param hmminfo [in] HMM definition
*
* @return TRUE on success, FALSE on failure.
*/
boolean
load_hmmlist_bin(FILE *fp, HTK_HMM_INFO *hmminfo)
{
HMM_Logical *l;
int n;
HTK_HMM_Trans *t;
HTK_HMM_State *s;
ListData ld;
/* build id->entity list */
ld.tr = (HTK_HMM_Trans **)mymalloc(sizeof(HTK_HMM_Trans *) * hmminfo->totaltransnum);
n = 0;
for (t = hmminfo->trstart; t; t = t->next) {
ld.tr[n++] = t;
}
ld.st = (HTK_HMM_State **)mymalloc(sizeof(HTK_HMM_State *) * hmminfo->totalstatenum);
n = 0;
for (s = hmminfo->ststart; s; s = s->next) {
ld.st[n++] = s;
}
/* set it to hook */
hmminfo->hook = &ld;
/* load hmmlist */
jlog("Stat: load_hmmlist_bin: reading hmmlist\n");
if (aptree_read(fp, &(hmminfo->logical_root), &(hmminfo->lroot), hmminfo, load_hmmlist_callback) == FALSE) {
jlog("Error: load_hmmlist_bin: failed to read hmmlist from binary file\n");
return FALSE;
}
/* load cdset */
jlog("Stat: load_hmmlist_bin: reading pseudo phone set\n");
if (aptree_read(fp, &(hmminfo->cdset_info.cdtree), &(hmminfo->cdset_root), hmminfo, load_cdset_callback) == FALSE) {
jlog("Warning: load_hmmlist_bin: cdset not in binary file, skip reading\n");
} else {
hmminfo->cdset_info.binary_malloc = TRUE;
}
/* remove data */
free(ld.st);
free(ld.tr);
hmminfo->hook = NULL;
/* form other data */
n = 0;
for(l=hmminfo->lgstart;l;l=l->next) n++;
hmminfo->totallogicalnum = n;
return TRUE;
}