📄 mdef.c
字号:
/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*- *//* ==================================================================== * 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 * * * 22-Nov-2004 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University * Imported from s3.2, for supporting s3 format continuous * acoustic models. * * 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 <stdio.h>#include <string.h>#include <stdlib.h>#include <assert.h>#include "mdef.h"#include "ckd_alloc.h"#include "err.h"#define MODEL_DEF_VERSION "0.3"voidmdef_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 0int32mdef_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 voidciphone_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_table_enter(m->ciphone_ht, m->ciphone[p].name, (void *)p) != (void *)p) E_FATAL("hash_table_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 voidtriphone_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_tmdef_ciphone_id(mdef_t * m, char *ci){ void *id; assert(m); assert(ci); if (hash_table_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);}int32mdef_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_tmdef_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_tmdef_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);}int32mdef_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;}int32mdef_is_ciphone(mdef_t * m, s3pid_t p){ assert(m); assert((p >= 0) && (p < m->n_phone)); return ((p < m->n_ciphone) ? 1 : 0);}int32mdef_is_cisenone(mdef_t * m, s3senid_t s){ assert(m); if (s >= m->n_sen) { return 0; } assert(s >= 0); return ((s == m->cd2cisen[s]) ? 1 : 0);}/* Parse tmat and state->senone mappings for phone p and fill in structure */static voidparse_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 voidparse_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 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -