static void dump_pnode_info (pnode_t *p)
{
    if (NOT_WID(p->wid))
	printf ("%s", (p->id == -1) ? "<head>" : "<tail>");
    else
	printf ("%s.%d.",
		dict_wordstr(p->wid), p->pos, mdef_ciphone_str (mdef, p->ci));
    printf ("%s", IS_CIPID(p->lc) ? mdef_ciphone_str (mdef, p->lc) : "-");
    printf ("(%s)", IS_CIPID(p->ci) ? mdef_ciphone_str (mdef, p->ci) : "-");
    printf ("%s", IS_CIPID(p->rc) ? mdef_ciphone_str (mdef, p->rc) : "-");
}
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);
}
Beispiel #3
0
static int32 parse_base_line (mdef_t *m, char *line, int32 lineno, s3pid_t p)
{
    int32 wlen, n;
    char *word;
    s3cipid_t ci;
    char tmp;

    /* Read base phone name */
    if ((wlen = nextword (line, delim, &word, &tmp)) < 0)	/* Empty line */
	E_FATAL("Line %d: Incomplete base phone line\n", lineno);

    /* Make sure it's not a duplicate */
    ci = mdef_ciphone_id (m, word);
    if (IS_CIPID(ci))
        E_FATAL("Line %d: Duplicate base phone: %s\n", lineno, word);

    /* Add ciphone to ciphone table with id p */
    ciphone_add (m, word, p);
    ci = p;

    /* Restore original delimiter to word */
    line = word+wlen;
    word[wlen] = tmp;

    /* Read and skip "-" for lc, rc, wpos */
    for (n = 0; n < 3; n++) {
        if ((wlen = nextword (line, delim, &word, &tmp)) < 0)
	    E_FATAL("Line %d: Incomplete base phone line\n", lineno);
	if ((wlen != 1) || (word[0] != '-'))
	    E_FATAL("Line %d: %s instead of '-' in base phone line\n", word, lineno);
	line = word+wlen;
	word[wlen] = tmp;
    }
    
    /* Read filler attribute, if present */
    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 = 1;
    else if (strcmp (word, "n/a") == 0)
        m->ciphone[ci].filler = 0;
    else
        E_FATAL("Line %d: Illegal attribute string: %s\n", lineno, word);
    line = word+wlen;
    word[wlen] = tmp;

    if (triphone_add (m, ci, BAD_CIPID, BAD_CIPID, WORD_POSN_UNDEFINED, 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;
}
static void dump_pnode_succ (pnode_t *p)
{
    plink_t *l;
    
    printf ("  %5d", p->id);
    if (IS_WID(p->wid))
	printf (" %20s %02d %6d %4s",
		dict_wordstr(p->wid), p->pos, p->pid, mdef_ciphone_str (mdef, p->ci));
    else
	printf (" %20s %02d %6d %4s",
		"<phead>", 0, BAD_PID, "");
    printf (" %4s %4s",
	    IS_CIPID(p->lc) ? mdef_ciphone_str (mdef, p->lc) : "-",
	    IS_CIPID(p->rc) ? mdef_ciphone_str (mdef, p->rc) : "-");
    printf ("\t");

    for (l = p->succlist; l; l = l->next)
	printf (" %5d", l->node->id);
    
    printf ("\n");
}
/*
 * 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;
}