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

📄 mdef.c

📁 CMU大名鼎鼎的SPHINX-3大词汇量连续语音识别系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ==================================================================== * Copyright (c) 1999-2004 Carnegie Mellon University.  All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer.  * * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in *    the documentation and/or other materials provided with the *    distribution. * * This work was supported in part by funding from the Defense Advanced  * Research Projects Agency and the National Science Foundation of the  * United States of America, and the CMU Sphinx Speech Consortium. * * THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY ``AS IS'' AND  * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY * NOR ITS EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ==================================================================== * *//* * mdef.c -- HMM model definition: base (CI) phones and triphones * * ********************************************** * CMU ARPA Speech Project * * Copyright (c) 1999 Carnegie Mellon University. * ALL RIGHTS RESERVED. * ********************************************** *  * HISTORY *  * 19.Apr-2001  Ricky Houghton, added code for free allocated memory * * 14-Oct-1999	M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon * 		Added mdef_sseq2sen_active(). *  * 06-May-1999	M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon * 		In mdef_phone_id(), added backing off to silence phone context from filler * 		context if original triphone not found. *  * 30-Apr-1999	M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon * 		Added senone-sequence id (ssid) to phone_t and appropriate functions to * 		maintain it.  Instead, moved state sequence info to mdef_t. *  * 13-Jul-96	M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University. * 		Added mdef_phone_str(). *  * 01-Jan-96	M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University. * 		Allowed mdef_phone_id_nearest to return base phone id if either * 		left or right context (or both) is undefined. *  * 01-Jan-96	M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University. * 		Created. *//* * Major assumptions: *   All phones have same #states, same topology. *   Every phone has exactly one non-emitting, final state--the last one. *   CI phones must appear first in model definition file. */#include "mdef.h"#define MODEL_DEF_VERSION	"0.3"void mdef_dump (FILE *fp, mdef_t *m){    int32 i, j;    int32 ssid;    char buf[1024];        fprintf (fp, "%d ciphone\n", m->n_ciphone);    fprintf (fp, "%d phone\n", m->n_phone);    fprintf (fp, "%d emitstate\n", m->n_emit_state);    fprintf (fp, "%d cisen\n", m->n_ci_sen);    fprintf (fp, "%d sen\n", m->n_sen);    fprintf (fp, "%d tmat\n", m->n_tmat);        for (i = 0; i < m->n_phone; i++) {	mdef_phone_str (m, i, buf);	ssid = m->phone[i].ssid;		fprintf (fp, "%3d %5d", m->phone[i].tmat, ssid);	for (j = 0; j < m->n_emit_state; j++)	    fprintf (fp, " %5d", m->sseq[ssid][j]);	fprintf (fp, "\t");	for (j = 0; j < m->n_emit_state; j++)	    fprintf (fp, " %3d", m->cd2cisen[m->sseq[ssid][j]]);	fprintf (fp, "\t%s\n", buf);    }        fflush (fp);}#if 0int32 mdef_hmm_cmp (mdef_t *m, s3pid_t p1, s3pid_t p2){    int32 i;        if (m->phone[p1].tmat != m->phone[p2].tmat)	return -1;        for (i = 0; i < m->n_emit_state; i++)	if (m->phone[p1].state[i] != m->phone[p2].state[i])	    return -1;        return 0;}#endifstatic void ciphone_add (mdef_t *m, char *ci, s3pid_t p){    assert (p < m->n_ciphone);    m->ciphone[p].name = (char *) ckd_salloc (ci); /* freed in mdef_free */    if (hash_enter (m->ciphone_ht, m->ciphone[p].name, p) != p)	E_FATAL("hash_enter(%s) failed; duplicate CIphone?\n", m->ciphone[p].name);}static ph_lc_t *find_ph_lc (ph_lc_t *lclist, s3cipid_t lc){    ph_lc_t *lcptr;    for (lcptr = lclist; lcptr && (lcptr->lc != lc); lcptr = lcptr->next);    return lcptr;}static ph_rc_t *find_ph_rc (ph_rc_t *rclist, s3cipid_t rc){    ph_rc_t *rcptr;    for (rcptr = rclist; rcptr && (rcptr->rc != rc); rcptr = rcptr->next);    return rcptr;}static void triphone_add (mdef_t *m,			  s3cipid_t ci, s3cipid_t lc, s3cipid_t rc, word_posn_t wpos,			  s3pid_t p){    ph_lc_t *lcptr;    ph_rc_t *rcptr;        assert (p < m->n_phone);    /* Fill in phone[p] information (state and tmat mappings added later) */    m->phone[p].ci = ci;    m->phone[p].lc = lc;    m->phone[p].rc = rc;    m->phone[p].wpos = wpos;    /* Create <ci,lc,rc,wpos> -> p mapping if not a CI phone */    if (p >= m->n_ciphone) {	if ((lcptr = find_ph_lc (m->wpos_ci_lclist[wpos][(int)ci], lc)) 	    == NULL)	{	lcptr = (ph_lc_t *) ckd_calloc (1, sizeof(ph_lc_t)); /* freed at mdef_free, I believe */	    lcptr->lc = lc;	    lcptr->next = m->wpos_ci_lclist[wpos][(int)ci];	    m->wpos_ci_lclist[wpos][(int)ci] = lcptr; /* This is what needs to be freed */	}	if ((rcptr = find_ph_rc (lcptr->rclist, rc)) != NULL) {	    char buf[4096];	    	    mdef_phone_str (m, rcptr->pid, buf);	    E_FATAL("Duplicate triphone: %s\n", buf);	}	      rcptr = (ph_rc_t *) ckd_calloc (1, sizeof(ph_rc_t)); /* freed in mdef_free, I believe */	rcptr->rc = rc;	rcptr->pid = p;	rcptr->next = lcptr->rclist;	lcptr->rclist = rcptr;    }}s3cipid_t mdef_ciphone_id (mdef_t *m, char *ci){    int32 id;        assert (m);    assert (ci);        if (hash_lookup (m->ciphone_ht, ci, &id) < 0)	return (BAD_S3CIPID);    return ((s3cipid_t) id);}const char *mdef_ciphone_str (mdef_t *m, s3cipid_t id){    assert (m);    assert ((id >= 0) && (id < m->n_ciphone));        return (m->ciphone[(int)id].name);}int32 mdef_phone_str (mdef_t *m, s3pid_t pid, char *buf){    char *wpos_name;        assert (m);    assert ((pid >= 0) && (pid < m->n_phone));    wpos_name = WPOS_NAME;        buf[0] = '\0';    if (pid < m->n_ciphone)	sprintf (buf, "%s", mdef_ciphone_str (m, (s3cipid_t) pid));    else {	sprintf (buf, "%s %s %s %c",		 mdef_ciphone_str(m, m->phone[pid].ci),		 mdef_ciphone_str(m, m->phone[pid].lc),		 mdef_ciphone_str(m, m->phone[pid].rc),		 wpos_name[m->phone[pid].wpos]);    }    return 0;}s3pid_t mdef_phone_id (mdef_t *m, 		       s3cipid_t ci, s3cipid_t lc, s3cipid_t rc, word_posn_t wpos){    ph_lc_t *lcptr;    ph_rc_t *rcptr;    s3cipid_t newl, newr;        assert (m);    assert ((ci >= 0) && (ci < m->n_ciphone));    assert ((lc >= 0) && (lc < m->n_ciphone));    assert ((rc >= 0) && (rc < m->n_ciphone));    assert ((wpos >= 0) && (wpos < N_WORD_POSN));    if (((lcptr = find_ph_lc (m->wpos_ci_lclist[wpos][(int)ci], lc)) == NULL) ||	((rcptr = find_ph_rc (lcptr->rclist, rc)) == NULL)) {	/* Not found; backoff to silence context if non-silence filler context */	if (NOT_S3CIPID(m->sil))	    return BAD_S3PID;		newl = m->ciphone[(int)lc].filler ? m->sil : lc;	newr = m->ciphone[(int)rc].filler ? m->sil : rc;	if ((newl == lc) && (newr == rc))	    return BAD_S3PID;		return (mdef_phone_id (m, ci, newl, newr, wpos));    }        return (rcptr->pid);}s3pid_t mdef_phone_id_nearest (mdef_t *m, 			       s3cipid_t b, s3cipid_t l, s3cipid_t r, word_posn_t pos){    word_posn_t tmppos;    s3pid_t p;    s3cipid_t newl, newr;    char *wpos_name;        assert (m);    assert ((b >= 0) && (b < m->n_ciphone));    assert ((pos >= 0) && (pos < N_WORD_POSN));    if ((NOT_S3CIPID(l)) || (NOT_S3CIPID(r)))	return ((s3pid_t) b);        assert ((l >= 0) && (l < m->n_ciphone));    assert ((r >= 0) && (r < m->n_ciphone));        p = mdef_phone_id (m, b, l, r, pos);    if (IS_S3PID(p))	return p;        /* Exact triphone not found; backoff to other word positions */    for (tmppos = 0; tmppos < N_WORD_POSN; tmppos++) {	if (tmppos != pos) {	    p = mdef_phone_id (m, b, l, r, tmppos);	    if (IS_S3PID(p))		return p;	}    }        /* Nothing yet; backoff to silence phone if non-silence filler context */    if (IS_S3CIPID(m->sil)) {	newl = m->ciphone[(int)l].filler ? m->sil : l;	newr = m->ciphone[(int)r].filler ? m->sil : r;	if ((newl != l) || (newr != r)) {	    p = mdef_phone_id (m, b, newl, newr, pos);	    if (IS_S3PID(p))		return p;	    	    for (tmppos = 0; tmppos < N_WORD_POSN; tmppos++) {		if (tmppos != pos) {		    p = mdef_phone_id (m, b, newl, newr, tmppos);		    if (IS_S3PID(p))			return p;		}	    }	}    }        /* Nothing yet; backoff to base phone */    if ((m->n_phone > m->n_ciphone) && (! m->ciphone[(int)b].filler)) {	wpos_name = WPOS_NAME;#if 0	E_WARN("Triphone(%s,%s,%s,%c) not found; backing off to CIphone\n",	       mdef_ciphone_str(m, b),	       mdef_ciphone_str(m, l),	       mdef_ciphone_str(m, r),	       wpos_name[pos]);#endif    }    return ((s3pid_t) b);}int32 mdef_phone_components (mdef_t *m,			     s3pid_t p,			     s3cipid_t *b,			     s3cipid_t *l,			     s3cipid_t *r,			     word_posn_t *pos){    assert (m);    assert ((p >= 0) && (p < m->n_phone));    *b = m->phone[p].ci;    *l = m->phone[p].lc;    *r = m->phone[p].rc;    *pos = m->phone[p].wpos;    return 0;}int32 mdef_is_ciphone (mdef_t *m, s3pid_t p){    assert (m);    assert ((p >= 0) && (p < m->n_phone));        return ((p < m->n_ciphone) ? 1 : 0);}int32 mdef_is_cisenone (mdef_t *m, s3senid_t s){    assert (m);    assert ((s >= 0) && (s < m->n_sen));    return ((s == m->cd2cisen[s]) ? 1 : 0);}/* Parse tmat and state->senone mappings for phone p and fill in structure */static void parse_tmat_senmap (mdef_t *m, char *line, int32 off, s3pid_t p){    int32 wlen, n, s;    char word[1024], *lp;    lp = line + off;        /* Read transition matrix id */    if ((sscanf (lp, "%d%n", &n, &wlen) != 1) || (n < 0))        E_FATAL("Missing or bad transition matrix id: %s\n", line);    m->phone[p].tmat = n;    if (m->n_tmat <= n)	E_FATAL("tmat-id(%d) > #tmat in header(%d): %s\n", n, m->n_tmat, line);    lp += wlen;        /* Read senone mappings for each emitting state */    for (n = 0; n < m->n_emit_state; n++) {        if ((sscanf (lp, "%d%n", &s, &wlen) != 1) || (s < 0))	    E_FATAL("Missing or bad state[%d]->senone mapping: %s\n", n, line);		/*20040821 ARCHAN, This line is added to allow 3.x/3.0 compatability. */	m->phone[p].state[n] = s;	if ((p < m->n_ciphone) && (m->n_ci_sen <= s))	    E_FATAL("CI-senone-id(%d) > #CI-senones(%d): %s\n", s, m->n_ci_sen, line);	if (m->n_sen <= s)	    E_FATAL("Senone-id(%d) > #senones(%d): %s\n", s, m->n_sen, line);	m->sseq[p][n] = s;	lp += wlen;    }    /* Check for the last non-emitting state N */    if ((sscanf (lp, "%s%n", word, &wlen) != 1) || (strcmp (word, "N") != 0))        E_FATAL("Missing non-emitting state spec: %s\n", line);    lp += wlen;    /* Check for end of line */    if (sscanf (lp, "%s%n", word, &wlen) == 1)        E_FATAL("Non-empty beyond non-emitting final state: %s\n", line);}static void parse_base_line (mdef_t *m, char *line, s3pid_t p){    int32 wlen, n;    char word[1024], *lp;    s3cipid_t ci;    lp = line;        /* Read base phone name */    if (sscanf (lp, "%s%n", word, &wlen) != 1)	E_FATAL("Missing base phone name: %s\n", line);    lp += wlen;        /* Make sure it's not a duplicate */    ci = mdef_ciphone_id (m, word);    if (IS_S3CIPID(ci))        E_FATAL("Duplicate base phone: %s\n", line);    /* Add ciphone to ciphone table with id p */    ciphone_add (m, word, p);    ci = (s3cipid_t) p;    /* Read and skip "-" for lc, rc, wpos */    for (n = 0; n < 3; n++) {	if ((sscanf (lp, "%s%n", word, &wlen) != 1) || (strcmp (word, "-") != 0))	    E_FATAL("Bad context info for base phone: %s\n", line);	lp += wlen;    }        /* Read filler attribute, if present */    if (sscanf (lp, "%s%n", word, &wlen) != 1)	E_FATAL("Missing filler atribute field: %s\n", line);    lp += wlen;    if (strcmp (word, "filler") == 0)        m->ciphone[(int)ci].filler = 1;

⌨️ 快捷键说明

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