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); }
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; }