hmm_check.c
来自「julius version 4.12.about sound recognit」· C语言 代码 · 共 383 行
C
383 行
/** * @file hmm_check.c * * <JA> * @brief トライフォンの辑今惧での腊圭拉チェック * </JA> * * <EN> * @brief Triphone checker on word dictionary * </EN> * * @author Akinobu LEE * @date Thu Mar 17 20:50:07 2005 * * $Revision: 1.2 $ * *//* * Copyright (c) 1991-2007 Kawahara Lab., Kyoto University * Copyright (c) 2000-2005 Shikano Lab., Nara Institute of Science and Technology * Copyright (c) 2005-2007 Julius project team, Nagoya Institute of Technology * All rights reserved */#include <julius/julius.h>#define PHSTEP 10 ///< Malloc step for phoneme conversion/** * <JA> * @brief 不燎误からHMM误への恃垂を乖ない·冯蔡を山绩する. * * このル〖チンは·Julius/Julian に涂えられた不读モデルと * HMMList ファイルにおいて·不燎误からHMM误への恃垂をテストする * ための簇眶である. * * 鄂球で惰磊られた不燎误の矢机误に滦して·トライフォンモデル蝗脱箕には * コンテキストが雇胃され·呵姜弄に滦炳する HMM 误へ恃垂される. * その稿·恃垂した冯蔡を· * - 不燎误から瞥かれる塑丸の努脱すべきモデル叹 * - 惧淡を HMMList にしたがって恃垂した侠妄 HMM 叹 * - 悸狠に纷换で脱いられる湿妄HMM叹または pseudo HMM 叹 * の界に叫蜗する. * * なお·矢机误面に "|" を崔めることで·そこを帽胳惰磊りとして胺い· * トライフォンにおいて帽胳粗の鸥倡を雇胃することができる. * * @param str [i/o] 鄂球で惰磊られた不燎误の矢机误 * @param hmminfo [in] HMM年盗菇陇挛 * @param len_ret [out] 手り猛の侠妄 HMM の妥燎眶 * * @return 糠たにメモリ充り烧けられた恃垂稿の侠妄HMMのポインタ误 * </JA> * <EN> * @brief Convert phoneme sequences to logical HMM sequences, and output the * result. * * This function is for testing procedure to convert words in dictionary * to corresponding HMM sequences in Julius/Julian, given an HMMList and * HTK HMM definition. * * Given a space-separated list of phoneme names in a string, each phonemes * will be converted to context-dependent style (if using triphone model), * and then converted to HMM sequence that will finally be used for * recognition. Then, the following data will be output for all HMM: * - Original phone HMM name, * - Logical HMM name that is converted from above, * - Physical or pseudo HMM name that will actually be used. * * Additionally, specifying '|' in the string gives a word boundary between * phonemes, and triphone conversion will consider the cross-word expansion. * * @param str [i/o] string that contains space-saparated phoneme sequence. * @param hmminfo [in] HMM definition structure * @param len_ret [out] num of elements in the return value * * @return the newly allocated pointer array to the converted logical HMMs. * </EN> */static HMM_Logical **new_str2phseq(char *str, HTK_HMM_INFO *hmminfo, int *len_ret){ char **tokens; boolean *word_end; int phnum; boolean word_mode = FALSE; HMM_Logical **new; static char buf[MAX_HMMNAME_LEN]; /* read in string and divide into token unit */ { char *p; int tokenmax; tokenmax = PHSTEP; tokens = (char **)mymalloc(sizeof(char *) * tokenmax); word_end = (boolean *)mymalloc(sizeof(boolean) * tokenmax); phnum = 0; for(p = strtok(str, DELM); p; p = strtok(NULL, DELM)) { if (strmatch(p, "|")) { word_mode = TRUE; if (phnum > 0) word_end[phnum-1] = TRUE; continue; } if (phnum >= tokenmax) { tokenmax += PHSTEP; tokens = (char **)myrealloc(tokens, sizeof(char *) * tokenmax); word_end = (boolean *)myrealloc(word_end, sizeof(boolean) * tokenmax); } tokens[phnum] = strcpy((char *)mymalloc(strlen(p)+1), p); word_end[phnum] = FALSE; phnum++; } if (phnum == 0) { jlog("ERROR: hmm_check: no phone specified\n"); printf("ERROR: hmm_check: no phone specified\n"); new = NULL; goto spend; } word_end[phnum-1] = TRUE; } /* check if the phonemes exist in basephone list */ { BASEPHONE *ph; int i; boolean ok_flag = TRUE; for (i=0;i<phnum;i++) { ph = aptree_search_data(tokens[i], hmminfo->basephone.root); if (ph == NULL || ! strmatch(ph->name, tokens[i])) { jlog("ERROR: hmm_check: %2d - unknown phone \"%s\"\n", i+1, tokens[i]); printf("ERROR: hmm_check: %2d - unknown phone \"%s\"\n", i+1, tokens[i]); ok_flag = FALSE; continue; } } if (! ok_flag) { jlog("ERROR: hmm_check: unknown phone(s)\n"); printf("ERROR: hmm_check: unknown phone(s)\n"); new = NULL; goto spend; } } /* token -> original logical name -> logical HMM -> physical/pseudo phone */ /* cross-word conversion and fallback to bi/mono-phone is also considered */ { int i; char *hmmstr; HMM_Logical *lg; boolean ok_flag = TRUE; new = (HMM_Logical **)mymalloc(sizeof(HMM_Logical *) * phnum); /* original logical name, applied logical HMM name (defined by HMMList), and the actual physical/pseudo HMM name (defined in hmmdefs) */ printf("\n id original logical physical/pseudo\n"); printf(" -------------------------------------------------\n"); if (hmminfo->is_triphone) { cycle_triphone(NULL); cycle_triphone(tokens[0]); for (i = 0; i < phnum; i++) { if (i < phnum - 1) { hmmstr = cycle_triphone(tokens[i+1]); } else { hmmstr = cycle_triphone_flush(); } lg = htk_hmmdata_lookup_logical(hmminfo, hmmstr); if (lg == NULL) { if (word_mode) { if (i > 0 && word_end[i-1]) { if (word_end[i]) { center_name(hmmstr, buf); } else { rightcenter_name(hmmstr, buf); } } else if (word_end[i]) { leftcenter_name(hmmstr, buf); } lg = htk_hmmdata_lookup_logical(hmminfo, buf); if (lg == NULL) { jlog("ERROR: hmm_check: no defined/pseudo HMM for \"%s\"??\n", buf); printf("ERROR: hmm_check: no defined/pseudo HMM for \"%s\"??\n", buf); ok_flag = FALSE; continue; } if (lg->is_pseudo) { printf(" %2d: %11s -> (pseudo) -> {%s}\n", i+1, hmmstr, lg->body.pseudo->name); } else { printf(" %2d: %11s -> %8s -> [%s]\n", i+1, hmmstr, lg->name, lg->body.defined->name); } } else { jlog("ERROR: hmm_check: UNKNOWN %2d: (%s)\n", i+1, hmmstr); printf("ERROR: hmm_check: UNKNOWN %2d: (%s)\n", i+1, hmmstr); ok_flag = FALSE; continue; } } else { if (lg->is_pseudo) { printf(" %2d: %11s -> (pseudo) -> {%s}\n", i+1, hmmstr, lg->body.pseudo->name); } else { printf(" %2d: %11s -> %8s -> [%s]\n", i+1, hmmstr, " ", lg->body.defined->name); } } new[i] = lg; } } else { for (i = 0; i < phnum; i++) { lg = htk_hmmdata_lookup_logical(hmminfo, tokens[i]); if (lg == NULL) { jlog("ERROR: hmm_check: %2d - unknown logical HMM \"%s\"\n", i+1, tokens[i]); printf("ERROR: hmm_check: %2d - unknown logical HMM \"%s\"\n", i+1, tokens[i]); ok_flag = FALSE; continue; } new[i] = lg; } } if (ok_flag) { printf("succeeded\n"); } else { jlog("ERROR: hmm_check: failed\n"); printf("failed\n"); free(new); new = NULL; goto spend; } } spend: { int i; for(i=0;i<phnum;i++) { free(tokens[i]); } free(tokens); free(word_end); } *len_ret = phnum; return new;}/** * <JA> * 筛洁掐蜗から1乖を不燎误山淡として粕み哈み·トライフォンへの恃垂チェックを * 乖なう. * * @param hmminfo [in] HMM年盗菇陇挛 * </JA> * <EN> * Read in line from stdin as phoneme sequence and try convertion to * triphone for checking. * * @param hmminfo [in] HMM definition structure * </EN> */static booleantest_expand_triphone(HTK_HMM_INFO *hmminfo){ char *buf; int newline; HMM_Logical **phseq; int phlen; boolean flag = FALSE; buf = (char *)mymalloc(4096); for(;;) { /* read in phoneme sequence from stdin */ printf(">>> input phone sequence (word delimiter is `|', blank to return)\n"); if (fgets(buf, 4096, stdin) == NULL) { flag = TRUE; break; } newline = strlen(buf)-1; /* chop newline */ if (buf[newline] == '\n') buf[newline] = '\0'; if (buf[0] == '\0') break; /* convert string to phseq and output */ phseq = new_str2phseq(buf, hmminfo, &phlen); free(phseq); } free(buf); return flag;}/** * <JA> * コマンドライン惧でトライフォンのチェックを乖なうモ〖ド ("-check triphone"). * * @param r [in] 千急借妄インスタンス * </JA> * <EN> * Mode to do interactive triphone conversion check ("-check triphone"). * * @param r [in] recognition process instance * </EN> * * @callgraph * @callergraph */voidhmm_check(RecogProcess *r){ boolean endflag; static char cmd[MAX_HMMNAME_LEN]; int newline; printf("*************************************************\n"); printf("******** TRIPHONE COHERENCE CHECK MODE ********\n"); printf("*************************************************\n"); printf("hmmdefs=%s\n", r->am->config->hmmfilename); if (r->am->config->mapfilename != NULL) { printf("hmmlist=%s\n", r->am->config->mapfilename); } printf("dict=%s\n", r->lm->config->dictfilename); printf("headsil = "); put_voca(stdout, r->lm->winfo, r->lm->winfo->head_silwid); printf("tailsil = "); put_voca(stdout, r->lm->winfo, r->lm->winfo->tail_silwid); if (make_base_phone(r->am->hmminfo, r->lm->winfo) == FALSE) { jlog("ERROR: hmm_check: error in making base phone list\n"); printf("ERROR: hmm_check: error in making base phone list\n"); return; } print_phone_info(stdout, r->am->hmminfo); for(endflag = FALSE; endflag == FALSE;) { printf("===== command (\"H\" for help) > "); if (fgets(cmd, MAX_HMMNAME_LEN, stdin) == NULL) break; newline = strlen(cmd)-1; /* chop newline */ if (cmd[newline] == '\n') cmd[newline] = '\0'; if (cmd[0] == '\0') continue; /* if blank line, read next */ switch(cmd[0]) { case 'a': /* all */ /* check if logical HMMs cover all possible variants */ test_interword_triphone(r->am->hmminfo, r->lm->winfo); break; case 'c': /* conv */ /* try to expand triphone for given phoneme sequence */ endflag = test_expand_triphone(r->am->hmminfo); break; case 'i': /* info */ /* output data source */ printf("hmmdefs=%s\n", r->am->config->hmmfilename); if (r->am->config->mapfilename != NULL) { printf("hmmlist=%s\n", r->am->config->mapfilename); } printf("dict=%s\n", r->lm->config->dictfilename); printf("headsil = "); put_voca(stdout, r->lm->winfo, r->lm->winfo->head_silwid); printf("tailsil = "); put_voca(stdout, r->lm->winfo, r->lm->winfo->tail_silwid); print_phone_info(stdout, r->am->hmminfo); break; case 'p': /* phonelist */ /* output basephone */ print_all_basephone_name(&(r->am->hmminfo->basephone)); break; case 'd': /* phonelist in detail */ /* output basephone */ print_all_basephone_detail(&(r->am->hmminfo->basephone)); break; case 'q': /* quit */ /* quit this check mode */ endflag = TRUE; break; default: printf("COMMANDS:\n"); printf(" info --- output HMM information\n"); printf(" conv --- try HMM conversion for given phone sequence\n"); printf(" phonelist --- print base phone list\n"); printf(" all --- check if all possible IW-triphone is covered\n"); printf(" quit --- quit\n"); break; } } printf("*************************************************\n"); printf("***** END OF TRIPHONE COHERENCE CHECK MODE ****\n"); printf("*************************************************\n");}/* end of file */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?