📄 search.c
字号:
thresh, newphone_thresh, lastphn_thresh, BestScore);#endif nacl = active_chan_list[nf & 0x1]; for (i = 0, rhmm = root_chan; i < n_root_chan; i++, rhmm++) { /* First check if this channel was active in current frame */ if (rhmm->active < cf) continue; if (rhmm->bestscore > thresh) { rhmm->active = nf; /* rhmm will be active in next frame */ if (skip_alt_frm && (!(cf % skip_alt_frm))) continue; /* transitions out of this root channel */ newphone_score = rhmm->score[HMM_LAST_STATE] + pip; if (newphone_score > newphone_thresh) { /* transition to all next-level channels in the HMM tree */ for (hmm = rhmm->next; hmm; hmm = hmm->alt) { if (npa[hmm->ciphone]) { if ((hmm->active < cf) || (hmm->score[0] < newphone_score)) { hmm->score[0] = newphone_score; hmm->path[0] = rhmm->path[HMM_LAST_STATE]; hmm->active = nf; *(nacl++) = hmm; } } } /* * Transition to last phone of all words for which this is the * penultimate phone (the last phones may need multiple right contexts). * Remember to remove the temporary newword_penalty. */ if (newphone_score > lastphn_thresh) { for (w = rhmm->penult_phn_wid; w >= 0; w = homophone_set[w]) { de = word_dict->dict_list[w]; if (npa[de->ci_phone_ids[de->len - 1]]) { candp = lastphn_cand + n_lastphn_cand; n_lastphn_cand++; candp->wid = w; candp->score = newphone_score - newword_penalty; candp->bp = rhmm->path[HMM_LAST_STATE]; } } } } } } n_active_chan[nf & 0x1] = nacl - active_chan_list[nf & 0x1];}/* * Prune currently active nonroot channels in HMM tree for next frame. Also, perform * exit transitions out of such channels and activate successors. */voidprune_nonroot_chan(void){ CHAN_T *hmm, *nexthmm; int32 cf, nf, w, i, pip; int32 thresh, newphone_thresh, lastphn_thresh, newphone_score; CHAN_T **acl, **nacl; /* active list, next active list */ lastphn_cand_t *candp; dict_entry_t *de; cf = CurrentFrame; nf = cf + 1; thresh = BestScore + DynamicLogBeamWidth; newphone_thresh = BestScore + (DynamicLogBeamWidth > NewPhoneLogBeamWidth ? DynamicLogBeamWidth : NewPhoneLogBeamWidth); lastphn_thresh = BestScore + (DynamicLogBeamWidth > LastPhoneLogBeamWidth ? DynamicLogBeamWidth : LastPhoneLogBeamWidth); pip = logPhoneInsertionPenalty; acl = active_chan_list[cf & 0x1]; /* currently active HMMs in tree */ nacl = active_chan_list[nf & 0x1] + n_active_chan[nf & 0x1]; for (i = n_active_chan[cf & 0x1], hmm = *(acl++); i > 0; --i, hmm = *(acl++)) { assert(hmm->active >= cf); if (hmm->bestscore > thresh) { /* retain this channel in next frame */ if (hmm->active != nf) { hmm->active = nf; *(nacl++) = hmm; } if (skip_alt_frm && (!(cf % skip_alt_frm))) continue; /* transitions out of this channel */ newphone_score = hmm->score[HMM_LAST_STATE] + pip; if (newphone_score > newphone_thresh) { /* transition to all next-level channel in the HMM tree */ for (nexthmm = hmm->next; nexthmm; nexthmm = nexthmm->alt) { if (npa[nexthmm->ciphone]) { if ((nexthmm->active < cf) || (nexthmm->score[0] < newphone_score)) { nexthmm->score[0] = newphone_score; nexthmm->path[0] = hmm->path[HMM_LAST_STATE]; if (nexthmm->active != nf) { nexthmm->active = nf; *(nacl++) = nexthmm; } } } } /* * Transition to last phone of all words for which this is the * penultimate phone (the last phones may need multiple right contexts). * Remember to remove the temporary newword_penalty. */ if (newphone_score > lastphn_thresh) { for (w = hmm->info.penult_phn_wid; w >= 0; w = homophone_set[w]) { de = word_dict->dict_list[w]; if (npa[de->ci_phone_ids[de->len - 1]]) { candp = lastphn_cand + n_lastphn_cand; n_lastphn_cand++; candp->wid = w; candp->score = newphone_score - newword_penalty; candp->bp = hmm->path[HMM_LAST_STATE]; } } } } } else if (hmm->active != nf) { /* hmm->active = -1; */ hmm->bestscore = WORST_SCORE; hmm->score[0] = WORST_SCORE; hmm->score[1] = WORST_SCORE; hmm->score[2] = WORST_SCORE;#if HMM_5_STATE hmm->score[3] = WORST_SCORE; hmm->score[4] = WORST_SCORE;#endif } } n_active_chan[nf & 0x1] = nacl - active_chan_list[nf & 0x1];}/* * Since the same instance of a word (i.e., <word,start-frame>) reaches its last * phone several times, we can compute its best BP and LM transition score info * just the first time and cache it for future occurrences. Structure for such * a cache. */typedef struct { int32 sf; /* Start frame */ int32 dscr; /* Delta-score upon entering last phone */ int32 bp; /* Best BP */} last_ltrans_t;static last_ltrans_t *last_ltrans; /* one per word */#define CAND_SF_ALLOCSIZE 32typedef struct { int32 bp_ef; int32 cand;} cand_sf_t;static int32 cand_sf_alloc = 0;static cand_sf_t *cand_sf;/* * Execute the transition into the last phone for all candidates words emerging from * the HMM tree. Attach LM scores to such transitions. * (Executed after pruning root and non-root, but before pruning word-chan.) */voidlast_phone_transition(void){ int32 i, j, k, cf, nf, bp, bplast, w; lastphn_cand_t *candp; int32 *nawl; int32 fwid2, thresh; int32 *rcpermtab, ciph0; int32 bestscore, dscr; dict_entry_t *de; CHAN_T *hmm; BPTBL_T *bpe; int32 n_cand_sf = 0; cf = CurrentFrame; nf = cf + 1; nawl = active_word_list[nf & 0x1];#if SEARCH_PROFILE n_lastphn_cand_utt += n_lastphn_cand;#endif /* If best LM score and bp for candidate known use it, else sort cands by startfrm */ for (i = 0, candp = lastphn_cand; i < n_lastphn_cand; i++, candp++) { bpe = &(BPTable[candp->bp]); rcpermtab = (bpe->r_diph >= 0) ? RightContextFwdPerm[bpe->r_diph] : zeroPermTab; /* Subtract starting score for candidate, leave it with only word score */ de = word_dict->dict_list[candp->wid]; ciph0 = de->ci_phone_ids[0]; candp->score -= BScoreStack[bpe->s_idx + rcpermtab[ciph0]]; /* * If this candidate not occurred in an earlier frame, prepare for finding * best transition score into last phone; sort by start frame. */ if (last_ltrans[candp->wid].sf != bpe->frame + 1) { for (j = 0; j < n_cand_sf; j++) { if (cand_sf[j].bp_ef == bpe->frame) break; } if (j < n_cand_sf) candp->next = cand_sf[j].cand; else { if (n_cand_sf >= cand_sf_alloc) { if (cand_sf_alloc == 0) { cand_sf = ckd_calloc(CAND_SF_ALLOCSIZE, sizeof(cand_sf_t)); cand_sf_alloc = CAND_SF_ALLOCSIZE; } else { cand_sf_alloc += CAND_SF_ALLOCSIZE; cand_sf = ckd_realloc(cand_sf, cand_sf_alloc * sizeof(cand_sf_t)); E_INFO("cand_sf[] increased to %d entries\n", cand_sf_alloc); } } j = n_cand_sf++; candp->next = -1; cand_sf[j].bp_ef = bpe->frame; } cand_sf[j].cand = i; last_ltrans[candp->wid].dscr = WORST_SCORE; last_ltrans[candp->wid].sf = bpe->frame + 1; } } /* Compute best LM score and bp for new cands entered in the sorted lists above */ for (i = 0; i < n_cand_sf; i++) { /* For the i-th unique end frame... */ bp = BPTableIdx[cand_sf[i].bp_ef]; bplast = BPTableIdx[cand_sf[i].bp_ef + 1] - 1; for (bpe = &(BPTable[bp]); bp <= bplast; bp++, bpe++) { if (!bpe->valid) continue; /* For each bp entry in the i-th end frame... */ rcpermtab = (bpe->r_diph >= 0) ? RightContextFwdPerm[bpe->r_diph] : zeroPermTab; /* For each candidate at the start frame find bp->cand transition-score */ for (j = cand_sf[i].cand; j >= 0; j = candp->next) { candp = &(lastphn_cand[j]); de = word_dict->dict_list[candp->wid]; ciph0 = de->ci_phone_ids[0]; fwid2 = de->fwid; dscr = BScoreStack[bpe->s_idx + rcpermtab[ciph0]]; dscr += lm_tg_score(bpe->prev_real_fwid, bpe->real_fwid, fwid2); if (last_ltrans[candp->wid].dscr < dscr) { last_ltrans[candp->wid].dscr = dscr; last_ltrans[candp->wid].bp = bp; } } } } /* Update best transitions for all candidates; also update best lastphone score */ bestscore = LastPhoneBestScore; for (i = 0, candp = lastphn_cand; i < n_lastphn_cand; i++, candp++) { candp->score += last_ltrans[candp->wid].dscr; candp->bp = last_ltrans[candp->wid].bp; if (bestscore < candp->score) bestscore = candp->score; } LastPhoneBestScore = bestscore; /* At this pt, we know the best entry score (with LM component) for all candidates */ thresh = bestscore + LastPhoneAloneLogBeamWidth; for (i = n_lastphn_cand, candp = lastphn_cand; i > 0; --i, candp++) { if (candp->score > thresh) { w = candp->wid; alloc_all_rc(w); k = 0; for (hmm = word_chan[w]; hmm; hmm = hmm->next) { if ((hmm->active < cf) || (hmm->score[0] < candp->score)) { hmm->score[0] = candp->score; hmm->path[0] = candp->bp; assert(hmm->active != nf); hmm->active = nf; k++; } } if (k > 0) { assert(!word_active[w]); *(nawl++) = w; word_active[w] = 1; } } } n_active_word[nf & 0x1] = nawl - active_word_list[nf & 0x1];}/* * Prune currently active word channels for next frame. Also, perform exit * transitions out of such channels and active successors. */voidprune_word_chan(void){ ROOT_CHAN_T *rhmm; CHAN_T *hmm, *thmm; CHAN_T **phmmp; /* previous HMM-pointer */ int32 cf, nf, w, i, k; int32 newword_thresh, lastphn_thresh; int32 *awl, *nawl; cf = CurrentFrame; nf = cf + 1; newword_thresh = LastPhoneBestScore + (DynamicLogBeamWidth > NewWordLogBeamWidth ? DynamicLogBeamWidth : NewWordLogBeamWidth); lastphn_thresh = LastPhoneBestScore + (DynamicLogBeamWidth > LastPhoneAloneLogBeamWidth ? DynamicLogBeamWidth : LastPhoneAloneLogBeamWidth); awl = active_word_list[cf & 0x1]; nawl = active_word_list[nf & 0x1] + n_active_word[nf & 0x1]; /* Dynamically allocated last channels of multi-phone words */ for (i = n_active_word[cf & 0x1], w = *(awl++); i > 0; --i, w = *(awl++)) { k = 0; phmmp = &(word_chan[w]); for (hmm = word_chan[w]; hmm; hmm = thmm) { assert(hmm->active >= cf); thmm = hmm->next; if (hmm->bestscore > lastphn_thresh) { /* retain this channel in next frame */ hmm->active = nf; k++; phmmp = &(hmm->next); /* Could if ((! skip_alt_frm) || (cf & 0x1)) the following */ if (hmm->score[HMM_LAST_STATE] > newword_thresh) { /* can exit channel and recognize word */ save_bwd_ptr(w, hmm->score[HMM_LAST_STATE], hmm->path[HMM_LAST_STATE], hmm->info.rc_id); } } else if (hmm->active == nf) { phmmp = &(hmm->next); } else { listelem_free(hmm, sizeof(CHAN_T)); *phmmp = thmm; } } if ((k > 0) && (!word_active[w])) { *(nawl++) = w; word_active[w] = 1; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -