📄 chkhmmlist.c
字号:
/** * @file chkhmmlist.c * @author Akinobu LEE * @date Tue Feb 15 19:17:51 2005 * * <JA> * @brief HMMList に链ての材墙なトライフォンが崔まれているかチェックする * * 涂えられた不读モデルにおいて·千急箕に判眷しうる链てのトライフォンが * %HMM年盗あるいはHMMListで年盗されているかどうかをチェックしますˉ * * チェック箕には辑今の胳酌が雇胃されますˉすなわち·涂えられた胳酌の帽胳柒 * および帽胳粗で栏じうるトライフォンについてのみチェックされますˉ * </JA> * * <EN> * @brief Check existence of all possible triphone in HMMList. * * These functions check whether all the possible triphones that may appear * while recognition process is fully defined or mapped in %HMM definition * file and HMMList file. * * Word dictionary is considered for the test. Only triphones that can * appear as word-internal triphones and cross-word triphones on the given * dictionary will be considered. * </EN> * * $Revision: 1.5 $ * *//* * Copyright (c) 1991-2006 Kawahara Lab., Kyoto University * Copyright (c) 2000-2005 Shikano Lab., Nara Institute of Science and Technology * Copyright (c) 2005-2006 Julius project team, Nagoya Institute of Technology * All rights reserved */#include <sent/htk_hmm.h>#include <sent/vocabulary.h>/** * Build a list of base phones by gathering center phones of the defined %HMM. * * @param hmminfo [i/o] %HMM definition data */voidmake_hmm_basephone_list(HTK_HMM_INFO *hmminfo){ HMM_Logical *lg; static char p[MAX_HMMNAME_LEN]; BASEPHONE *match = NULL, *new; APATNODE *root; int n; n = 0; root = NULL; for(lg=hmminfo->lgstart; lg; lg=lg->next) { center_name(lg->name, p); if (root != NULL) { match = aptree_search_data(p, root); if (strmatch(match->name, p)) continue; } new = (BASEPHONE *)mybmalloc2(sizeof(BASEPHONE), &(hmminfo->mroot)); new->bgnflag = FALSE; new->endflag = FALSE; new->name = (char *)mybmalloc2(strlen(p)+1, &(hmminfo->mroot)); strcpy(new->name, p); if (root == NULL) root = aptree_make_root_node(new); else aptree_add_entry(new->name, new, match->name, &root); n++; } hmminfo->basephone.num = n; hmminfo->basephone.root = root;}/** * Traverse function callback to output detailed information of a basephone in text to stdout. * * @param x [in] pointer to a basephone data. */static voidprint_callback_detail(void *x){ BASEPHONE *b = x; j_printf("\"%s\": bgn=%d, end=%d\n", b->name, b->bgnflag, b->endflag);}/** * Traverse function callback to output name of a basephone in text to stdout. * * @param x [in] pointer to a basephone data. */static voidprint_callback_name(void *x){ BASEPHONE *b = x; j_printf("%s, ", b->name);}/** * Output all basephone informations to stdout. * * @param base [in] pointer to the top basephone data holder. */voidprint_all_basephone_detail(HMM_basephone *base){ aptree_traverse_and_do(base->root, print_callback_detail);}/** * Output all basephone names to stdout * * @param base [in] pointer to the top basephone data holder. */voidprint_all_basephone_name(HMM_basephone *base){ aptree_traverse_and_do(base->root, print_callback_name); j_printf("\n");}static int bncnt; ///< Count of basephone that can appear at the beginning of sentencestatic int edcnt; ///< Count of basephone that can appear at the end of sentence/** * Traverse callback function to increment the number of base phones * that can appear at beginning of word and end of word. * * @param x [in] pointer */static voidcount_callback(void *x){ BASEPHONE *b = x; if (b->bgnflag) bncnt++; if (b->endflag) edcnt++;}/** * Count the total number of base phones that can appear at beginning of * word and end of word. * * @param base */static voidcount_all_phone(HMM_basephone *base){ bncnt = edcnt = 0; aptree_traverse_and_do(base->root, count_callback); base->bgnnum = bncnt; base->endnum = edcnt;}/** * Mark each basephone if it can appear at beginning or end of a word. * * @param winfo [in] word dictinary * @param base [in] top basephone data holder */static voidmark_word_edge(WORD_INFO *winfo, HMM_basephone *base){ WORD_ID w; static char p[MAX_HMMNAME_LEN]; char *key; BASEPHONE *match; /* mark what is at beginning of word (can be right context) */ for(w=0;w<winfo->num;w++) { if (w == winfo->head_silwid) continue; key = center_name(winfo->wseq[w][0]->name, p); match = aptree_search_data(key, base->root); if (strmatch(match->name, key)) { match->bgnflag = TRUE; } else { /* not found!!! */ j_error("InternalError: basephone \"%s\" specified in dict, but not found in HMM\n"); } } /* mark what is at end of word (can be left context) */ for(w=0;w<winfo->num;w++) { if (w == winfo->tail_silwid) continue; key = center_name(winfo->wseq[w][winfo->wlen[w]-1]->name, p); match = aptree_search_data(key, base->root); if (strmatch(match->name, key)) { match->endflag = TRUE; } else { /* not found!!! */ j_error("InternalError: basephone \"%s\" specified in dict, but not found in HMM\n"); } }}/* check if all possible triphones are exist in logical HMM *//* temporal storage for aptree() callback */static HTK_HMM_INFO *local_hmminfo; ///< Local work area to hold HTK %HMM datastatic WORD_INFO *local_winfo; ///< Local work area to hold word dictionarystatic APATNODE *local_root; ///< Local work area to hold basephone index rootstatic WORD_ID current_w; ///< Local work area to hold current word IDstatic char gbuf[MAX_HMMNAME_LEN]; ///< Local work area for phone name handlingstatic APATNODE *error_root; ///< Error phone liststatic int error_num; ///< Number of encountered error phone/** * Add unknown (error) triphone to error list. * * @param lostname [in] name of error triphone. * @param hmminfo [i/o] %HMM definition data */static voidadd_to_error(char *lostname, HTK_HMM_INFO *hmminfo){ char *match = NULL, *new; if (error_root != NULL) { match = aptree_search_data(lostname, error_root); if (strmatch(match, lostname)) return; } new = (char *)mybmalloc2(strlen(lostname)+1, &(hmminfo->mroot)); strcpy(new, lostname); if (error_root == NULL) error_root = aptree_make_root_node(new); else aptree_add_entry(new, new, match, &error_root); error_num++;}/** * Traverse callback function to output error phone name. * * @param x [in] pointer to error phone name */static voidprint_error_callback(void *x){ char *p = x; j_printf("%s\n", p);}/** * Traverse callback function to check if the cross-word triphones * "basephone x - word[current_w]" and "word[current_w] + basephone x" exist, * according to the basephone mark. * * @param x [in] a basephone */static voidtriphone_callback_normal(void *x){ BASEPHONE *b = x; WORD_ID w = current_w; HMM_Logical *lg, *found; if (b->endflag) { /* x can appear as end of word */ lg = local_winfo->wseq[w][0]; strcpy(gbuf, lg->name); add_left_context(gbuf, b->name); /* printf("checking \"%s\" - \"%s\"\n", b->name, lg->name); */ if ((found = htk_hmmdata_lookup_logical(local_hmminfo, gbuf)) == NULL) { if (lg->is_pseudo) { j_printerr("Error: \"%s\" not found, fallback to pseudo {%s}\n", gbuf, lg->name); add_to_error(gbuf, local_hmminfo); } } } if (b->bgnflag) { /* x can appear as beginning of word */ lg = local_winfo->wseq[w][local_winfo->wlen[w]-1]; strcpy(gbuf, lg->name); add_right_context(gbuf, b->name); /* printf("checking \"%s\" - \"%s\"\n", lg->name, b->name); */ if ((found = htk_hmmdata_lookup_logical(local_hmminfo, gbuf)) == NULL) { if (lg->is_pseudo) { j_printerr("Error: \"%s\" not found, fallback to pseudo {%s}\n", gbuf, lg->name); add_to_error(gbuf, local_hmminfo); } } }}/* for words with only one phone, all combination of "x - current_w + x" should be checked *//** * Traverse callback function to check if the cross-word triphone * "basephone x - word[current_w] + basephone x" exist, for * words with only one phone: right part. * * @param x [in] a basephone */static voidtriphone_callback_right(void *x){ BASEPHONE *b = x; WORD_ID w = current_w; HMM_Logical *lg, *found; static char buf[MAX_HMMNAME_LEN]; if (b->bgnflag) { lg = local_winfo->wseq[w][0]; strcpy(buf, gbuf); add_right_context(buf, b->name); /* printf(" checking \"%s\" - \"%s\"\n", gbuf, b->name); */ if ((found = htk_hmmdata_lookup_logical(local_hmminfo, buf)) == NULL) { if (lg->is_pseudo) { j_printerr("Error: \"%s\" not found, fallback to pseudo {%s}\n", buf, lg->name); add_to_error(buf, local_hmminfo); } } }}/** * Traverse callback function to check if the cross-word triphone * "basephone x - word[current_w] + basephone x" exist, for * words with only one phone: left part. * * @param x [in] a basephone */static voidtriphone_callback_left(void *x){ BASEPHONE *b = x; WORD_ID w = current_w; HMM_Logical *lg; if (b->endflag) { lg = local_winfo->wseq[w][0]; strcpy(gbuf, lg->name); add_left_context(gbuf, b->name); /*printf("continue checking \"%s\" - \"%s\"\n", b->name, lg->name);*/ aptree_traverse_and_do(local_root, triphone_callback_right); }}/** * Top function to check if all the possible triphones on given word * dictionary actually exist in the logical %HMM. * * @param hmminfo [in] %HMM definition information, with basephone list. * @param winfo [in] word dictionary information */voidtest_interword_triphone(HTK_HMM_INFO *hmminfo, WORD_INFO *winfo){ WORD_ID w; local_hmminfo = hmminfo; local_winfo = winfo; local_root = hmminfo->basephone.root; error_root = NULL; error_num = 0; j_printf("Inter-word triphone existence test...\n"); for(w=0;w<winfo->num;w++) { current_w = w; if (winfo->wlen[w] > 1) { /* check beginning phone and ending phone of this word */ aptree_traverse_and_do(hmminfo->basephone.root, triphone_callback_normal); } else { /* for word of only 1 phoneme, check both */ aptree_traverse_and_do(hmminfo->basephone.root, triphone_callback_left); } } if (error_root == NULL) { j_printf("passed\n"); } else { j_printf("following triphones are missing in HMMList:\n"); aptree_traverse_and_do(error_root, print_error_callback); j_printf("total %d missing inter-word triphones\n", error_num); }}/** * @brief Build basephone information * * Extract base phones from %HMM definition, mark them whether they appear * on word head or word tail, and count the number. * * @param hmminfo [i/o] %HMM definition information, basephone list will be added. * @param winfo [in] word dictionary information */voidmake_base_phone(HTK_HMM_INFO *hmminfo, WORD_INFO *winfo){ /* gather base phones and word-{head,tail} phones */ j_printf("Exploring HMM database and lexicon tree:\n"); mark_word_edge(winfo, &(hmminfo->basephone)); count_all_phone(&(hmminfo->basephone));}/** * Output general information concerning phone mapping in %HMM definition. * * @param hmminfo [in] %HMM definition data. */voidprint_phone_info(HTK_HMM_INFO *hmminfo){ /* output information */ j_printf("%5d physical HMMs defined in hmmdefs\n", hmminfo->totalhmmnum); if (hmminfo->totalhmmnum == hmminfo->totallogicalnum - hmminfo->totalpseudonum) { j_printf(" no HMMList, physical HMM names are redirected to logicalHMM\n"); } else { if (hmminfo->is_triphone) { j_printf("%5d triphones listed in hmmlist\n", hmminfo->totallogicalnum - hmminfo->totalpseudonum); } else { j_printf("%5d phones in hmmlist\n", hmminfo->totallogicalnum - hmminfo->totalpseudonum); } } if (hmminfo->totalpseudonum != 0) { j_printf("%5d pseudo HMM generated for missing mono/bi-phones\n",hmminfo->totalpseudonum); } j_printf("%5d TOTAL logical HMMs\n", hmminfo->totallogicalnum); j_printf("%5d base phones in logical HMM\n", hmminfo->basephone.num); j_printf("%5d phones appear on word head, %d phones on word tail\n", hmminfo->basephone.bgnnum, hmminfo->basephone.endnum);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -