⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fsg_search.c

📁 WinCE平台上的语音识别程序
💻 C
📖 第 1 页 / 共 3 页
字号:
    fsg_pnode_t *child;    CHAN_T *hmm;    int32 newscore, thresh, nf;    assert(pnode);    assert(!fsg_pnode_leaf(pnode));    nf = search->frame + 1;    thresh = search->bestscore + search->beam;    hmm = fsg_pnode_hmmptr(pnode);    for (child = fsg_pnode_succ(pnode);         child; child = fsg_pnode_sibling(child)) {        newscore = hmm->score[HMM_LAST_STATE] + child->logs2prob;        if ((newscore >= thresh) && (newscore > child->hmm.score[0])) {            /* Incoming score > pruning threshold and > target's existing score */            if (child->hmm.active < nf) {                /* Child node not yet activated; do so */                search->pnode_active_next =                    glist_add_ptr(search->pnode_active_next,                                  (void *) child);                child->hmm.active = nf;            }            child->hmm.score[0] = newscore;            child->hmm.path[0] = hmm->path[HMM_LAST_STATE];        }    }}static voidfsg_search_pnode_exit(fsg_search_t * search, fsg_pnode_t * pnode){    CHAN_T *hmm;    word_fsglink_t *fl;    int32 wid, endwid;    fsg_pnode_ctxt_t ctxt;    assert(pnode);    assert(fsg_pnode_leaf(pnode));    hmm = fsg_pnode_hmmptr(pnode);    fl = fsg_pnode_fsglink(pnode);    assert(fl);    endwid = kb_get_word_id(cmd_ln_str("-lmendsym"));    wid = word_fsglink_wid(fl);    assert(wid >= 0);#if __FSG_DBG__    E_INFO("[%5d] Exit(%08x) %10d(score) %5d(pred)\n",           search->frame, (int32) pnode,           hmm->score[HMM_LAST_STATE], hmm->path[HMM_LAST_STATE]);#endif    /*     * Check if this is filler or single phone word; these do not model right     * context (i.e., the exit score applies to all right contexts).     */    if (dict_is_filler_word(word_dict, wid) ||        (wid == endwid) || (dict_pronlen(word_dict, wid) == 1)) {        /* Create a dummy context structure that applies to all right contexts */        fsg_pnode_add_all_ctxt(&ctxt);        /* Create history table entry for this word exit */        fsg_history_entry_add(search->history,                              fl,                              search->frame,                              hmm->score[HMM_LAST_STATE],                              hmm->path[HMM_LAST_STATE],                              pnode->ci_ext, ctxt);    }    else {        /* Create history table entry for this word exit */        fsg_history_entry_add(search->history,                              fl,                              search->frame,                              hmm->score[HMM_LAST_STATE],                              hmm->path[HMM_LAST_STATE],                              pnode->ci_ext, pnode->ctxt);    }}/* * (Beam) prune the just evaluated HMMs, determine which ones remain * active, which ones transition to successors, which ones exit and * terminate in their respective destination FSM states. * (Executed once per frame.) */voidfsg_search_hmm_prune_prop(fsg_search_t * search){    gnode_t *gn;    fsg_pnode_t *pnode;    CHAN_T *hmm;    int32 thresh, word_thresh, phone_thresh;    assert(search->pnode_active_next == NULL);    thresh = search->bestscore + search->beam;    phone_thresh = search->bestscore + search->pbeam;    word_thresh = search->bestscore + search->wbeam;    for (gn = search->pnode_active; gn; gn = gnode_next(gn)) {        pnode = (fsg_pnode_t *) gnode_ptr(gn);        hmm = fsg_pnode_hmmptr(pnode);        if (hmm->bestscore >= thresh) {            /* Keep this HMM active in the next frame */            if (hmm->active == search->frame) {                hmm->active = search->frame + 1;                search->pnode_active_next =                    glist_add_ptr(search->pnode_active_next,                                  (void *) pnode);            }            else {                assert(hmm->active == search->frame + 1);            }            if (!fsg_pnode_leaf(pnode)) {                if (hmm->score[HMM_LAST_STATE] >= phone_thresh) {                    /* Transition out of this phone into its children */                    fsg_search_pnode_trans(search, pnode);                }            }            else {                if (hmm->score[HMM_LAST_STATE] >= word_thresh) {                    /* Transition out of leaf node into destination FSG state */                    fsg_search_pnode_exit(search, pnode);                }            }        }    }}/* * Propagate newly created history entries through null transitions. */static voidfsg_search_null_prop(fsg_search_t * search){    int32 bpidx, n_entries, thresh, newscore;    fsg_hist_entry_t *hist_entry;    word_fsglink_t *l;    int32 s, d;    word_fsg_t *fsg;    fsg = search->fsg;    thresh = search->bestscore + search->wbeam; /* Which beam really?? */    n_entries = fsg_history_n_entries(search->history);    for (bpidx = search->bpidx_start; bpidx < n_entries; bpidx++) {        hist_entry = fsg_history_entry_get(search->history, bpidx);        l = fsg_hist_entry_fsglink(hist_entry);        /* Destination FSG state for history entry */        s = l ? word_fsglink_to_state(l) : word_fsg_start_state(fsg);        /*         * Check null transitions from d to all other states.  (Only need to         * propagate one step, since FSG contains transitive closure of null         * transitions.)         */        for (d = 0; d < word_fsg_n_state(fsg); d++) {            l = word_fsg_null_trans(fsg, s, d);            if (l) {            /* Propagate history entry through this null transition */                newscore =                    fsg_hist_entry_score(hist_entry) +                    word_fsglink_logs2prob(l);                if (newscore >= thresh) {                    fsg_history_entry_add(search->history, l,                                          fsg_hist_entry_frame(hist_entry),                                          newscore,                                          bpidx,                                          fsg_hist_entry_lc(hist_entry),                                          fsg_hist_entry_rc(hist_entry));                }            }        }    }}/* * Perform cross-word transitions; propagate each history entry created in this * frame to lextree roots attached to the target FSG state for that entry. */static voidfsg_search_word_trans(fsg_search_t * search){    int32 bpidx, n_entries;    fsg_hist_entry_t *hist_entry;    word_fsglink_t *l;    int32 score, newscore, thresh, nf, d;    fsg_pnode_t *root;    int32 lc, rc;    n_entries = fsg_history_n_entries(search->history);    thresh = search->bestscore + search->beam;    nf = search->frame + 1;    for (bpidx = search->bpidx_start; bpidx < n_entries; bpidx++) {        hist_entry = fsg_history_entry_get(search->history, bpidx);        assert(hist_entry);        score = fsg_hist_entry_score(hist_entry);        assert(search->frame == fsg_hist_entry_frame(hist_entry));        l = fsg_hist_entry_fsglink(hist_entry);        /* Destination state for hist_entry */        d = l ? word_fsglink_to_state(l) : word_fsg_start_state(search->                                                                fsg);        lc = fsg_hist_entry_lc(hist_entry);        /* Transition to all root nodes attached to state d */        for (root = fsg_lextree_root(search->lextree, d);             root; root = root->sibling) {            rc = root->ci_ext;            if ((root->ctxt.bv[lc >> 5] & (1 << (lc & 0x001f))) &&                (hist_entry->rc.bv[rc >> 5] & (1 << (rc & 0x001f)))) {                /*                 * Last CIphone of history entry is in left-context list supported by                 * target root node, and                 * first CIphone of target root node is in right context list supported                 * by history entry;                 * So the transition can go ahead (if new score is good enough).                 */                newscore = score + root->logs2prob;                if ((newscore >= thresh)                    && (newscore > root->hmm.score[0])) {                    if (root->hmm.active < nf) {                        /* Newly activated node; add to active list */                        search->pnode_active_next =                            glist_add_ptr(search->pnode_active_next,                                          (void *) root);                        root->hmm.active = nf;#if __FSG_DBG__                        E_INFO                            ("[%5d] WordTrans bpidx[%d] -> pnode[%08x] (activated)\n",                             search->frame, bpidx, (int32) root);#endif                    }                    else {#if __FSG_DBG__                        E_INFO                            ("[%5d] WordTrans bpidx[%d] -> pnode[%08x]\n",                             search->frame, bpidx, (int32) root);#endif                    }                    root->hmm.score[0] = newscore;                    root->hmm.path[0] = bpidx;                }            }        }    }}voidfsg_search_frame_fwd(fsg_search_t * search){    gnode_t *gn;    fsg_pnode_t *pnode;    CHAN_T *hmm;    search->bpidx_start = fsg_history_n_entries(search->history);    /* Evaluate all active pnodes (HMMs) */    fsg_search_hmm_eval(search);    /*     * Prune and propagate the HMMs evaluated; create history entries for     * word exits.  The words exits are tentative, and may be pruned; make     * the survivors permanent via fsg_history_end_frame().     */    fsg_search_hmm_prune_prop(search);    fsg_history_end_frame(search->history);    /*     * Propagate new history entries through any null transitions, creating     * new history entries, and then make the survivors permanent.     */    fsg_search_null_prop(search);    fsg_history_end_frame(search->history);    /*     * Perform cross-word transitions; propagate each history entry across its     * terminating state to the root nodes of the lextree attached to the state.     */    fsg_search_word_trans(search);    /*     * We've now come full circle, HMM and FSG states have been updated for     * the next frame.     * Update the active lists, deactivate any currently active HMMs that     * did not survive into the next frame     */    for (gn = search->pnode_active; gn; gn = gnode_next(gn)) {        pnode = (fsg_pnode_t *) gnode_ptr(gn);        hmm = fsg_pnode_hmmptr(pnode);        if (hmm->active == search->frame) {            /* This HMM NOT activated for the next frame; reset it */            fsg_psubtree_pnode_deactivate(pnode);        }        else {            assert(hmm->active == (search->frame + 1));        }    }    /* Free the currently active list */    glist_free(search->pnode_active);    /* Make the next-frame active list the current one */    search->pnode_active = search->pnode_active_next;    search->pnode_active_next = NULL;    /* End of this frame; ready for the next */    (search->frame)++;}static voidfsg_search_hyp_free(fsg_search_t * search){    search_hyp_t *hyp, *nexthyp;    for (hyp = search->hyp; hyp; hyp = nexthyp) {        nexthyp = hyp->next;        ckd_free(hyp);    }    search->hyp = NULL;}/* * Set all HMMs to inactive, clear active lists, initialize FSM start * state to be the only active node. * (Executed at the start of each utterance.) */voidfsg_search_utt_start(fsg_search_t * search){    int32 silcipid;    fsg_pnode_ctxt_t ctxt;    /* Reset dynamic adjustment factor for beams */    search->beam_factor = 1.0f;    search->beam = search->beam_orig;    search->pbeam = search->pbeam_orig;    search->wbeam = search->wbeam_orig;    silcipid = phone_to_id("SIL",  TRUE);    /* Initialize EVERYTHING to be inactive */    assert(search->pnode_active == NULL);    assert(search->pnode_active_next == NULL);    fsg_lextree_utt_start(search->lextree);    fsg_history_utt_start(search->history);    /* Dummy context structure that allows all right contexts to use this entry */    fsg_pnode_add_all_ctxt(&ctxt);    /* Create dummy history entry leading to start state */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -