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;

	assert(m);
	assert((b >= 0) && (b < m->n_ciphone));
	assert((pos >= 0) && (pos < N_WORD_POSN));

	if ((NOT_CIPID(l)) || (NOT_CIPID(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_PID(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_PID(p))
				return p;
		}
	}

	/* Nothing yet; backoff to silence phone if non-silence filler context */
	if (IS_CIPID(m->sil)) {
		newl = m->ciphone[l].filler ? m->sil : l;
		newr = m->ciphone[r].filler ? m->sil : r;
		if ((newl != l) || (newr != r)) {
			p = mdef_phone_id(m, b, newl, newr, pos);
			if (IS_PID(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_PID(p))
						return p;
				}
			}
		}
	}

	/* Nothing yet; backoff to base phone */
	return ((s3pid_t) b);
}
Esempio n. 2
0
File: dict.c Progetto: 10v/cmusphinx
static int32 dict_read (FILE *fp, dict_t *d)
{
    char line[16384], **wptr;
    s3cipid_t p[4096];
    int32 lineno, nwd;
    s3wid_t w;
    int32 i, maxwd;
    
    maxwd = 4092;
    wptr = (char **) ckd_calloc (maxwd, sizeof(char *));
    
    lineno = 0;
    while (fgets (line, sizeof(line), fp) != NULL) {
        lineno++;
	if (line[0] == '#')	/* Comment line */
	    continue;
	
	if ((nwd = str2words (line, wptr, maxwd)) < 0)
	    E_FATAL("str2words(%s) failed; Increase maxwd from %d\n", line, maxwd);

	if (nwd == 0)	    /* Empty line */
	    continue;
	/* wptr[0] is the word-string and wptr[1..nwd-1] the pronunciation sequence */
	if (nwd == 1) {
	    E_ERROR("Line %d: No pronunciation for word %s; ignored\n", lineno, wptr[0]);
	    continue;
	}
	
	/* Convert pronunciation string to CI-phone-ids */
	for (i = 1; i < nwd; i++) {
	    p[i-1] = dict_ciphone_id (d, wptr[i]);
	    if (NOT_CIPID(p[i-1])) {
		E_ERROR("Line %d: Bad ciphone: %s; word %s ignored\n",
			lineno, wptr[i], wptr[0]);
		break;
	    }
	}
	
	if (i == nwd) {	/* All CI-phones successfully converted to IDs */
	    w = dict_add_word (d, wptr[0], p, nwd-1);
	    if (NOT_WID(w))
		E_ERROR("Line %d: dict_add_word (%s) failed (duplicate?); ignored\n",
			lineno, wptr[0]);
	}
    }

    ckd_free (wptr);
    
    return 0;
}
Esempio n. 3
0
File: mdef.c Progetto: 10v/cmusphinx
static int32 parse_tri_line (mdef_t *m, char *line, int32 lineno, s3pid_t p)
{
    int32 wlen;
    char *word;
    s3cipid_t ci, lc, rc;
    word_posn_t wpos;
    char tmp;

    /* Read base phone name */
    if ((wlen = nextword (line, delim, &word, &tmp)) < 0)	/* Empty line */
	E_FATAL("Line %d: Incomplete triphone line\n", lineno);
    ci = mdef_ciphone_id (m, word);
    if (NOT_CIPID(ci))
        E_FATAL("Line %d: Unknown base phone in triphone: %s\n", lineno, word);
    line = word+wlen;
    word[wlen] = tmp;

    /* Read lc */
    if ((wlen = nextword (line, delim, &word, &tmp)) < 0)
        E_FATAL("Line %d: Incomplete triphone line\n", lineno);
    lc = mdef_ciphone_id (m, word);
    if (NOT_CIPID(lc))
        E_FATAL("Line %d: Unknown left context in triphone: %s\n", lineno, word);
    line = word+wlen;
    word[wlen] = tmp;

    /* Read rc */
    if ((wlen = nextword (line, delim, &word, &tmp)) < 0)
        E_FATAL("Line %d: Incomplete triphone line\n", lineno);
    rc = mdef_ciphone_id (m, word);
    if (NOT_CIPID(rc))
        E_FATAL("Line %d: Unknown left context in triphone: %s\n", lineno, word);
    line = word+wlen;
    word[wlen] = tmp;
    
    /* Read tripone word-position within word */
    if (((wlen = nextword (line, delim, &word, &tmp)) < 0) ||
	(word[1] != '\0'))
        E_FATAL("Line %d: Missing or bad triphone word-position spec\n", lineno);
    switch (word[0]) {
    case 'b': wpos = WORD_POSN_BEGIN; break;
    case 'e': wpos = WORD_POSN_END; break;
    case 's': wpos = WORD_POSN_SINGLE; break;
    case 'i': wpos = WORD_POSN_INTERNAL; break;
    default: E_FATAL("Line %d: Bad word-position spec: %s\n", lineno, word);
    }
    line = word+wlen;
    word[wlen] = tmp;

    /* Read filler attribute, if present.  Must match base phone attribute */
    if ((wlen = nextword (line, delim, &word, &tmp)) < 0)
	E_FATAL("Line %d: Incomplete base phone line\n", lineno);
    if (((strcmp (word, "filler") == 0) && (m->ciphone[ci].filler)) ||
	((strcmp (word, "n/a") == 0) && (! m->ciphone[ci].filler))) {
    } else
        E_FATAL("Line %d: Bad attribute string: %s\n", lineno, word);
    line = word+wlen;
    word[wlen] = tmp;
    
    if (triphone_add (m, ci, lc, rc, wpos, p) < 0)
	E_FATAL("Line %d: Duplicate/Bad triphone\n", lineno);

    /* Parse remainder of line: transition matrix and state->senone mappings */
    parse_tmat_senmap (m, line, lineno, p);
    
    return 0;
}
Esempio n. 4
0
static wseg_t *line2wseg (char *line, s3wid_t *ref,
			  s3cipid_t *ap, int8 *ap_err, int32 aplen, char *id)
{
    char word[1024], uttid[1024], *lp;
    int32 i, k, n_hypci, n_refwd, n_refci, pronlen;
    s3cipid_t ci;
    typedef enum {CORR=0, REFERR=1, HYPERR=2} state_t;
    state_t state;
    static wseg_t *wseg = NULL;
    
    if (! wseg)
	wseg = (wseg_t *) ckd_calloc (MAX_UTT_LEN, sizeof(wseg_t));

    lp = line;
    n_hypci = n_refci = pronlen = 0;
    n_refwd = -1;
    uttid[0] = '\0';
    state = CORR;
    
    while (sscanf (lp, "%s%n", word, &k) == 1) {
	lp += k;
	
	if (is_uttid (word, uttid))
	    break;
	
	if (strcmp (word, "[[") == 0) {
	    if (state != CORR)
		E_FATAL("%s: Illegal [[\n", id);
	    state = REFERR;
	    if (n_refci < pronlen)
		wseg[n_refwd].err = 1;
	} else if (strcmp (word, "]]") == 0) {
	    if (state != HYPERR)
		E_FATAL("%s: Illegal ]]\n", id);
	    state = CORR;
	} else if (strcmp (word, "=>") == 0) {
	    if (state != REFERR)
		E_FATAL("%s: Illegal =>\n", id);
	    state = HYPERR;
	} else {
	    ci = mdef_ciphone_id (mdef, word);
	    if (NOT_CIPID(ci))
		E_FATAL("%s: Unknown CIphone %s\n", id, word);
	    
	    if (state != HYPERR) {	/* Check if matches next pron in ref word */
		if (n_refci >= pronlen) {
		    assert (n_refci == pronlen);
		    n_refwd++;
		    pronlen = dict->word[ref[n_refwd]].pronlen;
		    assert (pronlen > 0);

		    wseg[n_refwd].s = (state == CORR) ? n_hypci : -1;
		    wseg[n_refwd].e = -1;
		    wseg[n_refwd].err = 0;
		    
		    n_refci = 0;
		}
		if (NOT_WID(ref[n_refwd]))
		    E_FATAL("%s: Premature end of ref wid\n", id);

		if (dict->word[ref[n_refwd]].ciphone[n_refci] != ci)
		    E_FATAL("%s: CIphone mismatch at word %d, ciphone %d\n",
			    id, n_refwd, n_refci);
		n_refci++;
		if ((n_refci == pronlen) && (state == CORR))
		    wseg[n_refwd].e = n_hypci;

		if (state != CORR)
		    wseg[n_refwd].err = 1;
	    }
	    
	    if (state != REFERR) {
		if (n_hypci >= aplen)
		    E_FATAL("%s: Too many CIphones: >%d\n", id, aplen);
		ap[n_hypci] = ci;
		ap_err[n_hypci] = (state == CORR) ? 0 : 1;
		n_hypci++;
	    }
	}
    }
    assert (n_refci == pronlen);
    n_refwd++;
    assert (NOT_WID(ref[n_refwd]));
    wseg[n_refwd].s = wseg[n_refwd].e = n_hypci;
    wseg[n_refwd].err = 0;
    
    ap[n_hypci] = BAD_CIPID;
    ap_err[n_hypci] = 1;
    
    if (strcmp (uttid, id) != 0)
	E_FATAL("Uttid mismatch: %s expected, %s found\n", id, uttid);

#if 0
    for (i = 0; IS_WID(ref[i]); i++) {
	printf ("%s: %4d %4d %d %s\n", id, wseg[i].s, wseg[i].e, wseg[i].err,
		dict_wordstr (dict, ref[i]));
    }
#endif

    return wseg;
}
/*
 * Create phone-level HMM for a single word and append to partial sentence HMM.
 * Replicate HMM nodes as needed to account for all possible left and right context
 * phones.
 * Return a list of the final HMM nodes for the single word appended.
 */
static pnode_t *append_word (s3wid_t w,
			     pnode_t *prev_end,
			     s3cipid_t *pred_ci,
			     s3cipid_t *succ_ci)
{
    int32 i, M, N, m, n, pronlen, pron;
    pnode_t *node, *nodelist, *p;
    plink_t *l, *new_end;
    
    for (i = 0; IS_CIPID(pred_ci[i]); i++);
    M = (i > 0) ? i : 1;	/* #predecessor CI phones */
    
    for (i = 0; IS_CIPID(succ_ci[i]); i++);
    N = (i > 0) ? i : 1;	/* #successor CI phones */
    
    if ((pronlen = dict->word[w].pronlen) == 1) {
	/* Single phone case; replicated MxN times for all possible contexts */
	nodelist = NULL;

	for (m = 0; m < M; m++) {
	    for (n = 0; n < N; n++) {
		node = alloc_pnode (w, 0,
				    dict->word[w].ciphone[0], pred_ci[m], succ_ci[n],
				    WORD_POSN_SINGLE);
		/* Link to all predecessor nodes matching context requirements */
		for (p = prev_end; p; p = p->next) {
		    if ((p->ci == node->lc) &&
			((NOT_CIPID(p->rc)) || (p->rc == node->ci))) {
			link_pnodes (p, node);
		    }
		}

		node->next = nodelist;
		nodelist = node;
	    }
	}
	
	return nodelist;
    }

    /* Multi-phone case.  First phone, replicated M times */
    nodelist = NULL;
    for (m = 0; m < M; m++) {
	node = alloc_pnode (w, 0,
			    dict->word[w].ciphone[0],
			    pred_ci[m],
			    dict->word[w].ciphone[1],
			    WORD_POSN_BEGIN);
	/* Link to predecessor node(s) matching context requirements */
	for (p = prev_end; p; p = p->next) {
	    if ((p->ci == node->lc) &&
		((NOT_CIPID(p->rc)) || (p->rc == node->ci))) {
		link_pnodes (p, node);
	    }
	}
	node->next = nodelist;
	nodelist = node;
    }

    /* Intermediate phones */
    for (pron = 1; pron < pronlen-1; pron++) {
	node = alloc_pnode (w, pron,
			    dict->word[w].ciphone[pron],
			    dict->word[w].ciphone[pron-1],
			    dict->word[w].ciphone[pron+1],
			    WORD_POSN_INTERNAL);
	for (p = nodelist; p; p = p->next)
	    link_pnodes (p, node);
	nodelist = node;
    }

    /* Final phone, replicated N times */
    prev_end = nodelist;
    nodelist = NULL;
    for (n = 0; n < N; n++) {
	node = alloc_pnode (w, pron,
			    dict->word[w].ciphone[pron],
			    dict->word[w].ciphone[pron-1],
			    succ_ci[n],
			    WORD_POSN_END);
	for (p = prev_end; p; p = p->next)
	    link_pnodes (p, node);
	node->next = nodelist;
	nodelist = node;
    }

    return nodelist;
}