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

📄 word_fsg.c

📁 WinCE平台上的语音识别程序
💻 C
📖 第 1 页 / 共 3 页
字号:
 * Add silence and noise filler words to the FSG. * Return the number of transitions added.. */static int32word_fsg_add_filler(word_fsg_t * fsg, float32 silprob, float32 fillprob){    int32 src;    int32 wid, silwid, n_word;    int32 n_trans;    int32 logsilp, logfillp;    E_INFO("Adding filler words to FSG\n");    assert(fsg);    silwid = kb_get_word_id("SIL");    n_word = word_dict->dict_entry_count;    logsilp = (int32) (LOG(silprob) * fsg->lw);    logfillp = (int32) (LOG(fillprob) * fsg->lw);    /*     * Add silence and filler word self-loop transitions to each state.     * NOTE: No check to see if these words already exist in FSG!     */    n_trans = 0;    if (silwid >= 0) {        for (src = 0; src < fsg->n_state; src++) {            word_fsg_trans_add(fsg, src, src, logsilp, silwid);            n_trans++;            if (fillprob > 0.0) {                /* Add other filler (noise) words */                for (wid = silwid + 1; wid < n_word; wid++) {                    word_fsg_trans_add(fsg, src, src, logfillp, wid);                    n_trans++;                }            }        }    }    return n_trans;}/* * Compute the left and right context CIphone sets for each state. * (Needed for building the phone HMM net using cross-word triphones.  Invoke * after computing null transitions closure.) */static voidword_fsg_lc_rc(word_fsg_t * fsg){    int32 s, d, i, j;    int32 n_ci;    gnode_t *gn;    word_fsglink_t *l;    int32 silcipid;    int32 endwid;    int32 len;    endwid = kb_get_word_id(cmd_ln_str("-lmendsym"));    silcipid = phone_to_id("SIL", TRUE);    assert(silcipid >= 0);    n_ci = phoneCiCount();    if (n_ci > 127) {        E_FATAL            ("#phones(%d) > 127; cannot use int8** for word_fsg_t.{lc,rc}\n",             n_ci);    }    /*     * fsg->lc[s] = set of left context CIphones for state s.  Similarly, rc[s]     * for right context CIphones.     */    fsg->lc =        (int8 **) ckd_calloc_2d(fsg->n_state, n_ci + 1, sizeof(int8));    fsg->rc =        (int8 **) ckd_calloc_2d(fsg->n_state, n_ci + 1, sizeof(int8));    for (s = 0; s < fsg->n_state; s++) {        for (d = 0; d < fsg->n_state; d++) {            for (gn = fsg->trans[s][d]; gn; gn = gnode_next(gn)) {                l = (word_fsglink_t *) gnode_ptr(gn);                assert(l->wid >= 0);                /*                 * Add the first CIphone of l->wid to the rclist of state s, and                 * the last CIphone to lclist of state d.                 * (Filler phones are a pain to deal with.  There is no direct                 * marking of a filler phone; but only filler words are supposed to                 * use such phones, so we use that fact.  HACK!!  FRAGILE!!)                 */                if (dict_is_filler_word(word_dict, l->wid)                    || (l->wid == endwid)) {                    /* Filler phone; use silence phone as context */                    fsg->rc[s][silcipid] = 1;                    fsg->lc[d][silcipid] = 1;                }                else {                    len = dict_pronlen(word_dict, l->wid);                    fsg->rc[s][dict_ciphone(word_dict, l->wid, 0)] = 1;                    fsg->lc[d][dict_ciphone(word_dict, l->wid, len - 1)] = 1;                }            }        }        /*         * Add SIL phone to the lclist and rclist of each state.  Strictly         * speaking, only needed at start and final states, respectively, but         * all states considered since the user may change the start and final         * states.  In any case, most applications would have a silence self         * loop at each state, hence these would be needed anyway.         */        fsg->lc[s][silcipid] = 1;        fsg->rc[s][silcipid] = 1;    }    /*     * Propagate lc and rc lists past null transitions.  (Since FSG contains     * null transitions closure, no need to worry about a chain of successive     * null transitions.  Right??)     */    for (s = 0; s < fsg->n_state; s++) {        for (d = 0; d < fsg->n_state; d++) {            l = fsg->null_trans[s][d];            if (l) {                /*                 * lclist(d) |= lclist(s), because all the words ending up at s, can                 * now also end at d, becoming the left context for words leaving d.                 */                for (i = 0; i < n_ci; i++)                    fsg->lc[d][i] |= fsg->lc[s][i];                /*                 * Similarly, rclist(s) |= rclist(d), because all the words leaving d                 * can equivalently leave s, becoming the right context for words                 * ending up at s.                 */                for (i = 0; i < n_ci; i++)                    fsg->rc[s][i] |= fsg->rc[d][i];            }        }    }    /* Convert the bit-vector representation into a list */    for (s = 0; s < fsg->n_state; s++) {        j = 0;        for (i = 0; i < n_ci; i++) {            if (fsg->lc[s][i]) {                fsg->lc[s][j] = i;                j++;            }        }        fsg->lc[s][j] = -1;     /* Terminate the list */        j = 0;        for (i = 0; i < n_ci; i++) {            if (fsg->rc[s][i]) {                fsg->rc[s][j] = i;                j++;            }        }        fsg->rc[s][j] = -1;     /* Terminate the list */    }}word_fsg_t *word_fsg_load(s2_fsg_t * fsg,              boolean use_altpron, boolean use_filler,              float32 silprob, float32 fillprob, float32 lw){    word_fsg_t *word_fsg;    s2_fsg_trans_t *trans;    int32 n_trans, n_null_trans, n_alt_trans, n_filler_trans, n_unk;    int32 wid;    int32 logp;    glist_t nulls;    int32 i, j;    assert(fsg);    /* Some error checking */    if (lw <= 0.0)        E_WARN("Unusual language-weight value: %.3e\n", lw);    if (use_filler && ((silprob < 0.0) || (fillprob < 0.0))) {        E_ERROR("silprob/fillprob must be >= 0\n");        return NULL;    }    if ((fsg->n_state <= 0)        || ((fsg->start_state < 0) || (fsg->start_state >= fsg->n_state))        || ((fsg->final_state < 0) || (fsg->final_state >= fsg->n_state))) {        E_ERROR("Bad #states/start_state/final_state values: %d/%d/%d\n",                fsg->n_state, fsg->start_state, fsg->final_state);        return NULL;    }    for (trans = fsg->trans_list; trans; trans = trans->next) {        if ((trans->from_state < 0) || (trans->from_state >= fsg->n_state)            || (trans->to_state < 0) || (trans->to_state >= fsg->n_state)            || (trans->prob <= 0) || (trans->prob > 1.0)) {            E_ERROR("Bad transition: P(%d -> %d) = %e\n",                    trans->from_state, trans->to_state, trans->prob);            return NULL;        }    }    word_fsg = (word_fsg_t *) ckd_calloc(1, sizeof(word_fsg_t));    word_fsg->name = ckd_salloc(fsg->name ? fsg->name : "");    word_fsg->n_state = fsg->n_state;    word_fsg->start_state = fsg->start_state;    word_fsg->final_state = fsg->final_state;    word_fsg->use_altpron = use_altpron;    word_fsg->use_filler = use_filler;    word_fsg->lw = lw;    word_fsg->lc = NULL;    word_fsg->rc = NULL;    /* Allocate non-epsilon transition matrix array */    word_fsg->trans = (glist_t **) ckd_calloc_2d(word_fsg->n_state,                                                 word_fsg->n_state,                                                 sizeof(glist_t));    /* Allocate epsilon transition matrix array */    word_fsg->null_trans = (word_fsglink_t ***)        ckd_calloc_2d(word_fsg->n_state, word_fsg->n_state,                      sizeof(word_fsglink_t *));    /* Process transitions */    n_null_trans = 0;    n_alt_trans = 0;    n_filler_trans = 0;    n_unk = 0;    nulls = NULL;    for (trans = fsg->trans_list, n_trans = 0;         trans; trans = trans->next, n_trans++) {        /* Convert prob to logs2prob and apply language weight */        logp = (int32) (LOG(trans->prob) * lw);        /* Check if word is in dictionary */        if (trans->word) {            wid = kb_get_word_id(trans->word);            if (wid < 0) {                E_ERROR("Unknown word '%s'; ignored\n", trans->word);                n_unk++;            }            else if (use_altpron) {                wid = dictid_to_baseid(word_dict, wid);                assert(wid >= 0);            }        }        else            wid = -1;           /* Null transition */        /* Add transition to word_fsg structure */        i = trans->from_state;        j = trans->to_state;        if (wid < 0) {            if (word_fsg_null_trans_add(word_fsg, i, j, logp) == 1) {                n_null_trans++;                nulls =                    glist_add_ptr(nulls,                                  (void *) word_fsg->null_trans[i][j]);            }        }        else {            word_fsg_trans_add(word_fsg, i, j, logp, wid);            /* Add transitions for alternative pronunciations, if any */            if (use_altpron) {                for (wid = dict_next_alt(word_dict, wid);                     wid >= 0; wid = dict_next_alt(word_dict, wid)) {                    word_fsg_trans_add(word_fsg, i, j, logp, wid);                    n_alt_trans++;                    n_trans++;                }            }        }    }    /* Add silence and noise filler word transitions if specified */    if (use_filler) {        n_filler_trans = word_fsg_add_filler(word_fsg, silprob, fillprob);        n_trans += n_filler_trans;    }    E_INFO        ("FSG: %d states, %d transitions (%d null, %d alt, %d filler,  %d unknown)\n",         word_fsg->n_state, n_trans, n_null_trans, n_alt_trans,         n_filler_trans, n_unk);#if __FSG_DBG__    E_INFO("FSG before NULL closure:\n");    word_fsg_write(word_fsg, stdout);#endif    /* Null transitions closure */    nulls = word_fsg_null_trans_closure(word_fsg, nulls);    glist_free(nulls);#if __FSG_DBG__    E_INFO("FSG after NULL closure:\n");    word_fsg_write(word_fsg, stdout);#endif    /* Compute left and right context CIphone lists for each state */    word_fsg_lc_rc(word_fsg);#if __FSG_DBG__    E_INFO("FSG after lc/rc:\n");    word_fsg_write(word_fsg, stdout);#endif    return word_fsg;}static voids2_fsg_free(s2_fsg_t * fsg){    s2_fsg_trans_t *trans;    trans = fsg->trans_list;    while (trans) {        fsg->trans_list = trans->next;        ckd_free((void *) trans->word);        ckd_free((void *) trans);        trans = fsg->trans_list;    }    ckd_free((void *) fsg->name);    ckd_free((void *) fsg);}word_fsg_t *word_fsg_read(FILE * fp,              boolean use_altpron, boolean use_filler,              float32 silprob, float32 fillprob, float32 lw){    s2_fsg_t *fsg;              /* "External" FSG structure */

⌨️ 快捷键说明

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