static void phone_transition(phone_loop_search_t *pls, int frame_idx) { int32 thresh = pls->best_score + pls->pbeam; int nf = frame_idx + 1; int i; /* Now transition out of phones whose last states are inside the * phone transition beam. */ for (i = 0; i < pls->n_phones; ++i) { hmm_t *hmm = (hmm_t *)&pls->phones[i]; int32 newphone_score; int j; if (hmm_frame(hmm) != nf) continue; newphone_score = hmm_out_score(hmm) + pls->pip; if (newphone_score BETTER_THAN thresh) { /* Transition into all phones using the usual Viterbi rule. */ for (j = 0; j < pls->n_phones; ++j) { hmm_t *nhmm = (hmm_t *)&pls->phones[j]; if (hmm_frame(nhmm) < frame_idx || newphone_score BETTER_THAN hmm_in_score(nhmm)) { hmm_enter(nhmm, newphone_score, hmm_out_history(hmm), nf); } } } } }
static int state_align_search_start(ps_search_t *search) { state_align_search_t *sas = (state_align_search_t *)search; /* Activate the initial state. */ hmm_enter(sas->hmms, 0, 0, 0); return 0; }
static int phone_loop_search_start(ps_search_t *search) { phone_loop_search_t *pls = (phone_loop_search_t *)search; int i; /* Reset and enter all phone HMMs. */ for (i = 0; i < pls->n_phones; ++i) { hmm_t *hmm = (hmm_t *)&pls->phones[i]; hmm_clear(hmm); hmm_enter(hmm, 0, -1, 0); } phone_loop_search_free_renorm(pls); pls->best_score = 0; return 0; }
void ngram_fwdflat_start(ngram_search_t *ngs) { root_chan_t *rhmm; int i; ptmr_reset(&ngs->fwdflat_perf); ptmr_start(&ngs->fwdflat_perf); build_fwdflat_wordlist(ngs); build_fwdflat_chan(ngs); ngs->bpidx = 0; ngs->bss_head = 0; for (i = 0; i < ps_search_n_words(ngs); i++) ngs->word_lat_idx[i] = NO_BP; /* Reset the permanently allocated single-phone words, since they * may have junk left over in them from previous searches. */ for (i = 0; i < ngs->n_1ph_words; i++) { int32 w = ngs->single_phone_wid[i]; rhmm = (root_chan_t *) ngs->word_chan[w]; hmm_clear(&rhmm->hmm); } /* Start search with <s>; word_chan[<s>] is permanently allocated */ rhmm = (root_chan_t *) ngs->word_chan[ps_search_start_wid(ngs)]; hmm_enter(&rhmm->hmm, 0, NO_BP, 0); ngs->active_word_list[0][0] = ps_search_start_wid(ngs); ngs->n_active_word[0] = 1; ngs->best_score = 0; ngs->renormalized = FALSE; for (i = 0; i < ps_search_n_words(ngs); i++) ngs->last_ltrans[i].sf = -1; if (!ngs->fwdtree) ngs->n_frame = 0; ngs->st.n_fwdflat_chan = 0; ngs->st.n_fwdflat_words = 0; ngs->st.n_fwdflat_word_transition = 0; ngs->st.n_senone_active_utt = 0; }
static int phone_loop_search_start(ps_search_t *search) { phone_loop_search_t *pls = (phone_loop_search_t *)search; int i; /* Reset and enter all phone HMMs. */ for (i = 0; i < pls->n_phones; ++i) { hmm_t *hmm = (hmm_t *)&pls->hmms[i]; hmm_clear(hmm); hmm_enter(hmm, 0, -1, 0); } memset(pls->penalties, 0, pls->n_phones * sizeof(*pls->penalties)); for (i = 0; i < pls->window; i++) memset(pls->pen_buf[i], 0, pls->n_phones * sizeof(*pls->pen_buf[i])); phone_loop_search_free_renorm(pls); pls->best_score = 0; pls->pen_buf_ptr = 0; return 0; }
static void phone_transition(state_align_search_t *sas, int frame_idx) { int nf = frame_idx + 1; int i; for (i = 0; i < sas->n_phones - 1; ++i) { hmm_t *hmm, *nhmm; int32 newphone_score; hmm = sas->hmms + i; if (hmm_frame(hmm) != nf) continue; newphone_score = hmm_out_score(hmm); /* Transition into next phone using the usual Viterbi rule. */ nhmm = hmm + 1; if (hmm_frame(nhmm) < frame_idx || newphone_score BETTER_THAN hmm_in_score(nhmm)) { hmm_enter(nhmm, newphone_score, hmm_out_history(hmm), nf); } } }
static void fwdflat_word_transition(ngram_search_t *ngs, int frame_idx) { int32 cf, nf, b, thresh, pip, i, w, newscore; int32 best_silrc_score = 0, best_silrc_bp = 0; /* FIXME: good defaults? */ bptbl_t *bp; int32 *rcss; root_chan_t *rhmm; int32 *awl; float32 lwf; dict_t *dict = ps_search_dict(ngs); dict2pid_t *d2p = ps_search_dict2pid(ngs); cf = frame_idx; nf = cf + 1; thresh = ngs->best_score + ngs->fwdflatbeam; pip = ngs->pip; best_silrc_score = WORST_SCORE; lwf = ngs->fwdflat_fwdtree_lw_ratio; /* Search for all words starting within a window of this frame. * These are the successors for words exiting now. */ get_expand_wordlist(ngs, cf, ngs->max_sf_win); /* Scan words exited in current frame */ for (b = ngs->bp_table_idx[cf]; b < ngs->bpidx; b++) { xwdssid_t *rssid; int32 silscore; bp = ngs->bp_table + b; ngs->word_lat_idx[bp->wid] = NO_BP; if (bp->wid == ps_search_finish_wid(ngs)) continue; /* DICT2PID location */ /* Get the mapping from right context phone ID to index in the * right context table and the bscore_stack. */ rcss = ngs->bscore_stack + bp->s_idx; if (bp->last2_phone == -1) rssid = NULL; else rssid = dict2pid_rssid(d2p, bp->last_phone, bp->last2_phone); /* Transition to all successor words. */ for (i = 0; ngs->expand_word_list[i] >= 0; i++) { int32 n_used; w = ngs->expand_word_list[i]; /* Get the exit score we recorded in save_bwd_ptr(), or * something approximating it. */ if (rssid) newscore = rcss[rssid->cimap[dict_first_phone(dict, w)]]; else newscore = bp->score; if (newscore == WORST_SCORE) continue; /* FIXME: Floating point... */ newscore += lwf * (ngram_tg_score(ngs->lmset, dict_basewid(dict, w), bp->real_wid, bp->prev_real_wid, &n_used) >> SENSCR_SHIFT); newscore += pip; /* Enter the next word */ if (newscore BETTER_THAN thresh) { rhmm = (root_chan_t *) ngs->word_chan[w]; if ((hmm_frame(&rhmm->hmm) < cf) || (newscore BETTER_THAN hmm_in_score(&rhmm->hmm))) { hmm_enter(&rhmm->hmm, newscore, b, nf); /* DICT2PID: This is where mpx ssids get introduced. */ /* Look up the ssid to use when entering this mpx triphone. */ hmm_mpx_ssid(&rhmm->hmm, 0) = dict2pid_ldiph_lc(d2p, rhmm->ciphone, rhmm->ci2phone, dict_last_phone(dict, bp->wid)); assert(IS_S3SSID(hmm_mpx_ssid(&rhmm->hmm, 0))); E_DEBUG(6,("ssid %d(%d,%d) = %d\n", rhmm->ciphone, dict_last_phone(dict, bp->wid), rhmm->ci2phone, hmm_mpx_ssid(&rhmm->hmm, 0))); bitvec_set(ngs->word_active, w); } } } /* Get the best exit into silence. */ if (rssid) silscore = rcss[rssid->cimap[ps_search_acmod(ngs)->mdef->sil]]; else silscore = bp->score; if (silscore BETTER_THAN best_silrc_score) { best_silrc_score = silscore; best_silrc_bp = b; } } /* Transition to <sil> */ newscore = best_silrc_score + ngs->silpen + pip; if ((newscore BETTER_THAN thresh) && (newscore BETTER_THAN WORST_SCORE)) { w = ps_search_silence_wid(ngs); rhmm = (root_chan_t *) ngs->word_chan[w]; if ((hmm_frame(&rhmm->hmm) < cf) || (newscore BETTER_THAN hmm_in_score(&rhmm->hmm))) { hmm_enter(&rhmm->hmm, newscore, best_silrc_bp, nf); bitvec_set(ngs->word_active, w); } } /* Transition to noise words */ newscore = best_silrc_score + ngs->fillpen + pip; if ((newscore BETTER_THAN thresh) && (newscore BETTER_THAN WORST_SCORE)) { for (w = ps_search_silence_wid(ngs) + 1; w < ps_search_n_words(ngs); w++) { rhmm = (root_chan_t *) ngs->word_chan[w]; /* Noise words that aren't a single phone will have NULL here. */ if (rhmm == NULL) continue; if ((hmm_frame(&rhmm->hmm) < cf) || (newscore BETTER_THAN hmm_in_score(&rhmm->hmm))) { hmm_enter(&rhmm->hmm, newscore, best_silrc_bp, nf); bitvec_set(ngs->word_active, w); } } } /* Reset initial channels of words that have become inactive even after word trans. */ i = ngs->n_active_word[cf & 0x1]; awl = ngs->active_word_list[cf & 0x1]; for (w = *(awl++); i > 0; --i, w = *(awl++)) { rhmm = (root_chan_t *) ngs->word_chan[w]; if (hmm_frame(&rhmm->hmm) == cf) { hmm_clear_scores(&rhmm->hmm); } } }
static void fwdflat_prune_chan(ngram_search_t *ngs, int frame_idx) { int32 i, cf, nf, w, pip, newscore, thresh, wordthresh; int32 *awl; root_chan_t *rhmm; chan_t *hmm, *nexthmm; cf = frame_idx; nf = cf + 1; i = ngs->n_active_word[cf & 0x1]; awl = ngs->active_word_list[cf & 0x1]; bitvec_clear_all(ngs->word_active, ps_search_n_words(ngs)); thresh = ngs->best_score + ngs->fwdflatbeam; wordthresh = ngs->best_score + ngs->fwdflatwbeam; pip = ngs->pip; E_DEBUG(3,("frame %d thresh %d wordthresh %d\n", frame_idx, thresh, wordthresh)); /* Scan all active words. */ for (w = *(awl++); i > 0; --i, w = *(awl++)) { rhmm = (root_chan_t *) ngs->word_chan[w]; /* Propagate active root channels */ if (hmm_frame(&rhmm->hmm) == cf && hmm_bestscore(&rhmm->hmm) BETTER_THAN thresh) { hmm_frame(&rhmm->hmm) = nf; bitvec_set(ngs->word_active, w); /* Transitions out of root channel */ newscore = hmm_out_score(&rhmm->hmm); if (rhmm->next) { assert(!dict_is_single_phone(ps_search_dict(ngs), w)); newscore += pip; if (newscore BETTER_THAN thresh) { hmm = rhmm->next; /* Enter all right context phones */ if (hmm->info.rc_id >= 0) { for (; hmm; hmm = hmm->next) { if ((hmm_frame(&hmm->hmm) < cf) || (newscore BETTER_THAN hmm_in_score(&hmm->hmm))) { hmm_enter(&hmm->hmm, newscore, hmm_out_history(&rhmm->hmm), nf); } } } /* Just a normal word internal phone */ else { if ((hmm_frame(&hmm->hmm) < cf) || (newscore BETTER_THAN hmm_in_score(&hmm->hmm))) { hmm_enter(&hmm->hmm, newscore, hmm_out_history(&rhmm->hmm), nf); } } } } else { assert(dict_is_single_phone(ps_search_dict(ngs), w)); /* Word exit for single-phone words (where did their * whmms come from?) (either from * ngram_search_fwdtree, or from * ngram_fwdflat_allocate_1ph(), that's where) */ if (newscore BETTER_THAN wordthresh) { ngram_search_save_bp(ngs, cf, w, newscore, hmm_out_history(&rhmm->hmm), 0); } } } /* Transitions out of non-root channels. */ for (hmm = rhmm->next; hmm; hmm = hmm->next) { if (hmm_frame(&hmm->hmm) >= cf) { /* Propagate forward HMMs inside the beam. */ if (hmm_bestscore(&hmm->hmm) BETTER_THAN thresh) { hmm_frame(&hmm->hmm) = nf; bitvec_set(ngs->word_active, w); newscore = hmm_out_score(&hmm->hmm); /* Word-internal phones */ if (hmm->info.rc_id < 0) { newscore += pip; if (newscore BETTER_THAN thresh) { nexthmm = hmm->next; /* Enter all right-context phones. */ if (nexthmm->info.rc_id >= 0) { for (; nexthmm; nexthmm = nexthmm->next) { if ((hmm_frame(&nexthmm->hmm) < cf) || (newscore BETTER_THAN hmm_in_score(&nexthmm->hmm))) { hmm_enter(&nexthmm->hmm, newscore, hmm_out_history(&hmm->hmm), nf); } } } /* Enter single word-internal phone. */ else { if ((hmm_frame(&nexthmm->hmm) < cf) || (newscore BETTER_THAN hmm_in_score(&nexthmm->hmm))) { hmm_enter(&nexthmm->hmm, newscore, hmm_out_history(&hmm->hmm), nf); } } } } /* Right-context phones - apply word beam and exit. */ else { if (newscore BETTER_THAN wordthresh) { ngram_search_save_bp(ngs, cf, w, newscore, hmm_out_history(&hmm->hmm), hmm->info.rc_id); } } } /* Zero out inactive HMMs. */ else if (hmm_frame(&hmm->hmm) != nf) { hmm_clear_scores(&hmm->hmm); } } } } }