📄 beam.c
字号:
/* 矢姜位帽胳(silE,剁爬(IPAモデル))なら·silB で倡幌 */ /* initial word = best last word hypothesis on the last segment */ /* if silE or sp, begin with silB */ /*if (is_sil(recog.sp_break_last_word, wchmm->winfo, wchmm->hmminfo)) {*/ if (r->sp_break_last_word == wchmm->winfo->tail_silwid) { beginword = wchmm->winfo->head_silwid; d->bos.wid = WORD_INVALID; /* reset initial word context */ } else { beginword = r->sp_break_last_word; } } else { /* initial segment: initial word set to silB */ beginword = wchmm->winfo->head_silwid; } } else { /* not sp segment mode */ /* initial word fixed to silB */ beginword = wchmm->winfo->head_silwid; }#ifdef SP_BREAK_DEBUG jlog("DEBUG: startword=[%s], last_nword=[%s]\n", (beginword == WORD_INVALID) ? "WORD_INVALID" : wchmm->winfo->wname[beginword], (d->bos.wid == WORD_INVALID) ? "WORD_INVALID" : wchmm->winfo->wname[d->bos.wid]);#endif /* create the first token at the first node of initial word */ newid = create_token(d); new = &(d->tlist[d->tn][newid]); /* initial node = head node of the beginword */ if (wchmm->hmminfo->multipath) { node = wchmm->wordbegin[beginword]; } else { node = wchmm->offset[beginword][0]; } /* set initial LM score */ if (wchmm->state[node].scid != 0) { /* if initial node is on a factoring branch, use the factored score */ new->last_lscore = max_successor_prob(wchmm, d->bos.wid, node); } else { /* else, set to 0.0 */ new->last_lscore = 0.0; }#ifdef FIX_PENALTY new->last_lscore = new->last_lscore * d->lm_weight;#else new->last_lscore = new->last_lscore * d->lm_weight + d->lm_penalty;#endif /* set initial word history */ new->last_tre = &(d->bos); new->last_cword = d->bos.wid; if (wchmm->hmminfo->multipath) { /* set initial score using the initial LM score */ new->score = new->last_lscore; } else { /* set initial score using the initial LM score and AM score of the first state */ new->score = outprob_style(wchmm, node, d->bos.wid, 0, param) + new->last_lscore; } /* assign the initial node to token list */ node_assign_token(d, node, newid); } if (r->lmtype == LM_DFA && r->lmvar == LM_DFA_GRAMMAR) { /* 介袋簿棱: 矢恕惧矢片に儡鲁しうる帽胳礁圭 */ /* initial words: all words that can be begin of sentence grammatically */ /* アクティブな矢恕に掳する帽胳のみ钓す */ /* only words in active grammars are allowed to be an initial words */ MULTIGRAM *m; int t,tb,te; WORD_ID iw; boolean flag; DFA_INFO *gdfa; gdfa = r->lm->dfa; flag = FALSE; /* for all active grammar */ for(m = r->lm->grammars; m; m = m->next) { if (m->active) { tb = m->cate_begin; te = tb + m->dfa->term_num; for(t=tb;t<te;t++) { /* for all word categories that belong to the grammar */ if (dfa_cp_begin(gdfa, t) == TRUE) { /* if the category can appear at beginning of sentence, */ flag = TRUE; for (iw=0;iw<gdfa->term.wnum[t];iw++) { /* create the initial token at the first node of all words that belongs to the category */ i = gdfa->term.tw[t][iw]; if (wchmm->hmminfo->multipath) { node = wchmm->wordbegin[i]; } else { node = wchmm->offset[i][0]; } /* in tree lexicon, words in the same category may share the same root node, so skip it if the node has already existed */ if (node_exist_token(d, d->tn, node, d->bos.wid) != TOKENID_UNDEFINED) continue; newid = create_token(d); new = &(d->tlist[d->tn][newid]); new->last_tre = &(d->bos); new->last_lscore = 0.0; if (wchmm->hmminfo->multipath) { new->score = 0.0; } else { new->score = outprob_style(wchmm, node, d->bos.wid, 0, param); } node_assign_token(d, node, newid); } } } } } if (!flag) { jlog("ERROR: init_nodescore: no initial state found in active DFA grammar\n"); return FALSE; } } if (r->lmtype == LM_DFA && r->lmvar == LM_DFA_WORD) { /* アクティブな矢恕に掳する帽胳のみ钓す */ /* only words in active grammars are allowed to be an initial words */ MULTIGRAM *m; for(m = r->lm->grammars; m; m = m->next) { if (m->active) { for(i = m->word_begin; i < m->word_begin + m->winfo->num; i++) { if (wchmm->hmminfo->multipath) { node = wchmm->wordbegin[i]; } else { node = wchmm->offset[i][0]; } if (node_exist_token(d, d->tn, node, d->bos.wid) != TOKENID_UNDEFINED) continue; newid = create_token(d); new = &(d->tlist[d->tn][newid]); new->last_tre = &(d->bos); new->last_lscore = 0.0; if (wchmm->hmminfo->multipath) { new->score = 0.0; } else { new->score = outprob_style(wchmm, node, d->bos.wid, 0, param); } node_assign_token(d, node, newid); } } } } return TRUE;}/******************************************************//* フレ〖ム票袋ビ〖ム玫瑚の悸乖 --- 呵介のフレ〖ム脱 *//* frame synchronous beam search --- first frame only *//******************************************************//** * <JA> * @brief フレ〖ム票袋ビ〖ム玫瑚の介袋步 * * ここではビ〖ムサ〖チに脱いるワ〖クエリアの澄瘦と介袋步を乖う. * 介袋步棱の栏喇は init_nodescore() で乖われる. * * @param param [in] 掐蜗ベクトル误攫鼠 (呵介の1フレ〖ム誊のみ脱いられる) * @param r [i/o] 不兰千急借妄インスタンス * </JA> * <EN> * @brief Initialization of the frame synchronous beam search * * This function will initialize work area for the 1st pass. * Generation of initial hypotheses will be performed in init_nodescore(). * * @param param [in] input vectors (only the first frame will be used) * @param r [i/o] recognition process instance * </EN> * * @callergraph * @callgraph * */booleanget_back_trellis_init(HTK_Param *param, RecogProcess *r){ WCHMM_INFO *wchmm; BACKTRELLIS *backtrellis; FSBeam *d; wchmm = r->wchmm; backtrellis = r->backtrellis; d = &(r->pass1); /* Viterbi遍换脱ワ〖クエリアのスイッチャ〖 tl,tn の介袋猛肋年 */ /* tn: このフレ〖ム脱ID tl: 1フレ〖ム涟のID */ /* initialize switch tl, tn for Viterbi computation */ /* tn: this frame tl: last frame */ d->tn = 0; d->tl = 1; /* 冯蔡の帽胳トレリスを呈羌するバックトレリス菇陇挛を介袋步 */ /* initialize backtrellis structure to store resulting word trellis */ bt_prepare(backtrellis); /* 纷换脱ワ〖クエリアを介袋步 */ /* initialize some data on work area */ if (r->lmtype == LM_PROB) { d->lm_weight = r->config->lmp.lm_weight; d->lm_penalty = r->config->lmp.lm_penalty; } if (r->lmtype == LM_DFA) { d->penalty1 = r->config->lmp.penalty1; }#if defined(WPAIR) && defined(WPAIR_KEEP_NLIMIT) d->wpair_keep_nlimit = r->config->pass1.wpair_keep_nlimit;#endif /* ワ〖クエリアを澄瘦 */ /* malloc work area */ /* 蝗脱するト〖クン翁 = viterbi箕に莲败黎となる觉轮铬输の眶 * 徒卢: ビ〖ム眶 x 2 (极甘莲败+肌觉轮) + 腾菇陇步辑今のル〖トノ〖ド眶 */ /* assumed initial number of needed tokens: beam width x 2 (self + next trans.) * + root node on the tree lexicon (for inter-word trans.) */ if (d->totalnodenum != wchmm->n) { free_nodes(d); } if (d->nodes_malloced == FALSE) { malloc_nodes(d, wchmm->n, r->trellis_beam_width * 2 + wchmm->startnum); } prepare_nodes(d, r->trellis_beam_width); /* 介袋スコアを nodescore[tn] にセット */ /* set initial score to nodescore[tn] */ if (init_nodescore(param, r) == FALSE) { jlog("ERROR: get_back_trellis_init: failed to set initial node scores\n"); return FALSE; } sort_token_no_order(d, r->trellis_beam_width, &(d->n_start), &(d->n_end)); /* 敛肌叫蜗を乖なう眷圭のインタ〖バルを纷换 */ /* set interval frame for progout */ r->config->output.progout_interval_frame = (int)((float)r->config->output.progout_interval / ((float)param->header.wshift / 10000.0)); if (r->config->successive.enabled) { /* ショ〖トポ〖ズセグメンテ〖ション脱パラメ〖タの介袋步 */ /* initialize parameter for short pause segmentation */ d->in_sparea = TRUE; /* assume beginning is silence */ r->am->mfcc->sparea_start = d->tmp_sparea_start = 0; /* set start frame to 0 */#ifdef SP_BREAK_RESUME_WORD_BEGIN d->tmp_sp_break_last_word = WORD_INVALID;#endif r->sp_break_last_word = WORD_INVALID; /* 呵介のセグメント: 肌の润ポ〖ズフレ〖ムで妈2パスへ败乖しない */ /* the first end of pause segment should be always silB, so skip the first segment */ d->first_sparea = TRUE; r->sp_break_2_begin_word = WORD_INVALID; }#ifdef DETERMINE if (r->lmvar == LM_DFA_WORD) { /* initialize */ determine_word(r, 0, NULL, 0, 0); }#endif return TRUE;}/*****************************************************//* frame synchronous beam search --- proceed 1 frame *//* フレ〖ム票袋ビ〖ム玫瑚の悸乖 --- 1フレ〖ム渴める *//*****************************************************//** * <EN> * Propagate a token to next node. * * </EN> * <JA> * ト〖クンを肌ノ〖ドに帕嚷する. * * </JA> * * @param d [i/o] work area for 1st pass recognition processing * @param next_node [in] next node id * @param next_score [in] score when transmitted to the next node * @param last_tre [in] previous word context for the next node * @param last_cword [in] previous context-valid word for the next node * @param last_lscore [in] LM score to be propagated * */static voidpropagate_token(FSBeam *d, int next_node, LOGPROB next_score, TRELLIS_ATOM *last_tre, WORD_ID last_cword, LOGPROB last_lscore){ TOKEN2 *tknext; TOKENID tknextid; if ((tknextid = node_exist_token(d, d->tn, next_node, last_tre->wid)) != TOKENID_UNDEFINED) { /* 莲败黎ノ〖ドには贷に戮ノ〖ドから帕嚷貉み: スコアが光いほうを荒す */ /* the destination node already has a token: compare score */ tknext = &(d->tlist[d->tn][tknextid]); if (tknext->score < next_score) { /* その莲败黎ノ〖ドが积つト〖クンの柒推を惧今きする(糠惮ト〖クンは侯らない) */ /* overwrite the content of existing destination token: not create a new token */ tknext->last_tre = last_tre; /* propagate last word info */ tknext->last_cword = last_cword; /* propagate last context word info */ tknext->last_lscore = last_lscore; /* set new LM score */ tknext->score = next_score; /* set new score */ } } else { /* 莲败黎ノ〖ドは踏帕嚷: 糠惮ト〖クンを侯って充り烧ける */ /* token unassigned: create new token and assign */ if (next_score > LOG_ZERO) { /* valid token */ tknextid = create_token(d); /* get new token */ } tknext = &(d->tlist[d->tn][tknextid]); tknext->last_tre = last_tre; /* propagate last word info */ tknext->last_cword = last_cword; /* propagate last context word info */ tknext->last_lscore = last_lscore; tknext->score = next_score; /* set new score */ node_assign_token(d, next_node, tknextid); /* assign this new token to the next node */ }}/** * <JA> * 帽胳柒のあるノ〖ド粗の莲败を乖う. * * @param wchmm [in] 腾菇陇步辑今 * @param d [i/o] 妈1パスワ〖クエリア * @param tk_ret [i/o] 帕嚷傅のト〖クン∈柒婶でポインタ构糠箕は惧今き∷ * @param j [in] @a tk_ret の傅のト〖クンリストのID * @param next_node [in] 莲败黎のノ〖ド戎规 * @param next_a [in] 莲败澄唯 * </JA> * <EN> * Word-internal transition for a set of nodes. * * @param wchmm [in] tree lexicon * @param d [i/o] work area for the 1st pass * @param tk_ret [in] source token (if pointer updated, overwrite this) * @param j [in] the token ID of @a tk_ret * @param next_node [in] id of next node * @param next_a [in] transition probability * * </EN> */static voidbeam_intra_word_core(WCHMM_INFO *wchmm, FSBeam *d, TOKEN2 **tk_ret, int j, int next_node, LOGPROB next_a){ int node; ///< Temporal work to hold the current node number on the lexicon tree LOGPROB tmpsum; LOGPROB ngram_score_cache; TOKEN2 *tk; tk = *tk_ret; node = tk->node; /* now, 'node' is the source node, 'next_node' is the destication node, and ac-> holds transition probability */ /* tk->score is the accumulated score at the 'node' on previous frame */ /******************************************************************/ /* 2.1.1 莲败黎へのスコア纷换(莲败澄唯≤咐胳スコア) */ /* compute score of destination node (transition prob + LM) */ /******************************************************************/ tmpsum = tk->score + next_a; ngram_score_cache = LOG_ZERO; /* the next score at 'next_node' will be computed on 'tmpsum', and the new LM probability (if updated) will be stored on 'ngram_score_cache' at below */ if (!wchmm->category_tree) { /* 咐胳スコア factoring: arcが极甘莲败でない帽胳柒の莲败で·かつ莲败黎にsuccessorリスト があれば·lexicon tree の尸呆婶尸の莲败である */ /* LM factoring: If this is not a self transition and destination node has successor list, this is branching transition */ if (next_node != node) { if (wchmm->state[next_node].scid != 0#ifdef UNIGRAM_FACTORING /* 1-gram factoring 蝗脱箕は, 剩眶で鼎铜される晦では wchmm->state[node].scid は砷の猛となり·その冷滦猛を 藕机として wchmm->fscore[] に帽胳礁圭の1-gramの呵络猛が呈羌 されている. 琐眉の晦(剩眶帽胳で鼎铜されない)では· wchmm->state[node].scid は赖の猛となり· 1帽胳を sc として积つのでそこで赖澄な2-gramを纷换する */ /* When uni-gram factoring, wchmm->state[node].scid is below 0 for shared branches. In this case the maximum uni-gram probability for sub-tree is stored in
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -