📄 hmodel.c
字号:
/* ----------------------------------------------------------- *//* *//* ___ *//* |_| | |_/ SPEECH *//* | | | | \ RECOGNITION *//* ========= SOFTWARE */ /* *//* *//* ----------------------------------------------------------- *//* developed at: *//* *//* Speech Vision and Robotics group *//* Cambridge University Engineering Department *//* http://svr-www.eng.cam.ac.uk/ *//* *//* Entropic Cambridge Research Laboratory *//* (now part of Microsoft) *//* *//* ----------------------------------------------------------- *//* Copyright: Microsoft Corporation *//* 1995-2000 Redmond, Washington USA *//* http://www.microsoft.com *//* *//* 2002 Cambridge University *//* Engineering Department *//* *//* Use of this software is governed by a License Agreement *//* ** See the file License for the Conditions of Use ** *//* ** This banner notice must not be removed ** *//* *//* ----------------------------------------------------------- *//* File: HModel.c HMM Model Definition Data Type *//* ----------------------------------------------------------- */char *hmodel_version = "!HVER!HModel: 3.3 [CUED 28/04/05]";char *hmodel_vc_id = "$Id: HModel.c,v 1.4 2005/07/22 10:17:01 mjfg Exp $";#include "HShell.h"#include "HMem.h"#include "HMath.h"#include "HWave.h"#include "HAudio.h"#include "HParm.h"#include "HLabel.h"#include "HModel.h"#include "HUtil.h"#include "HTrain.h"#include "HAdapt.h"/* --------------------------- Trace Flags ------------------------- */static int trace = 0;#define T_TOP 00001 /* Top Level tracing */#define T_CHK 00002 /* Show HMM Checking */#define T_TOK 00004 /* Scanner Token Processing */#define T_PAR 00010 /* Trace Parsing */#define T_PMP 00020 /* Pointer Map Tracing */#define T_MAC 00040 /* Macro Load/Save Tracing */#define T_ORP 00100 /* Orphan macro handling */#define T_BTR 00200 /* Decision Tree handling */#define T_GMX 00400 /* GMP optimisation */#define T_XFM 01000 /* Loading of xform macros */#define T_XFD 02000 /* Additional detail of loading of xform macros */#define CREATEFIDX -1#define LOADFIDX -2/* ------------------ Input XForm directory info ------------------- */typedef struct _XFDirInfo *XFDirLink;typedef struct _XFDirInfo { char *dirName; /* input XForm directory name */ XFDirLink next; /* next directory name in list */} XFDirInfo;/* --------------------------- Initialisation ---------------------- */static ConfParam *cParm[MAXGLOBS]; /* config parameters */static int nParm = 0;static Boolean checking = TRUE; /* check HMM defs */static Boolean saveBinary = FALSE; /* save HMM defs in binary */static Boolean saveGlobOpts = TRUE; /* save ~o with HMM defs */static Boolean saveRegTree = FALSE; /* save regression classes and tree */ static Boolean saveBaseClass = FALSE; /* save base classes */ static Boolean saveInputXForm = FALSE; /* save input xforms with models set */static Boolean forceHSKind= FALSE; /* force HMM Set Kind */static Boolean keepDistinct=FALSE; /* keep orphan HMMs distinct */static Boolean discreteLZero=FALSE; /* map DLOGZERO to LZERO */static Boolean reorderComps=FALSE; /* re-order mixture components (PDE) */static Boolean allowOthers=TRUE; /* allow unseen models in files */static HSetKind cfHSKind;static char orphanMacFile[100]; /* last resort file for new macros */static XFDirLink xformDirNames = NULL; /* linked list of input transform directories */static Boolean indexSet = FALSE; /* have the indexes been set for the model set */static MemHeap xformStack; /* For Storage of xforms with no model sets ... */static int pde1BlockEnd = 13; /* size of PDE blocks */static int pde2BlockEnd = 26; /* size of PDE blocks */static LogFloat pdeTh1 = -5.0; /* threshold for 1/3 PDE */static LogFloat pdeTh2 = 0.0; /* threshold for 2/3 PDE */#ifdef PDE_STATSstatic int nGaussTot = 0;static int nGaussPDE1 = 0;static int nGaussPDE2 = 0;#endifvoid InitSymNames(void);/* EXPORT->InitModel: initialise memory and configuration parameters */void InitModel(void){ int i; double d; Boolean b; char buf[MAXSTRLEN]; Register(hmodel_version,hmodel_vc_id); CreateHeap(&xformStack,"XFormStore",MSTAK, 1, 0.5, 100 , 1000 ); strcpy(orphanMacFile,"newMacros"); InitSymNames(); nParm = GetConfig("HMODEL", TRUE, cParm, MAXGLOBS); if (nParm>0){ if (GetConfInt(cParm,nParm,"TRACE",&i)) trace = i; if (GetConfBool(cParm,nParm,"CHKHMMDEFS",&b)) checking = b; if (GetConfBool(cParm,nParm,"SAVEBINARY",&b)) saveBinary = b; if (GetConfBool(cParm,nParm,"KEEPDISTINCT",&b)) keepDistinct = b; if (GetConfBool(cParm,nParm,"SAVEGLOBOPTS",&b)) saveGlobOpts = b; if (GetConfBool(cParm,nParm,"SAVEREGTREE",&b)) saveRegTree = b; if (GetConfBool(cParm,nParm,"SAVEBASECLASS",&b)) saveBaseClass = b; if (GetConfBool(cParm,nParm,"SAVEINPUTXFORM",&b)) saveInputXForm = b; if (GetConfBool(cParm,nParm,"ALLOWOTHERHMMS",&b)) allowOthers = b; if (GetConfBool(cParm,nParm,"DISCRETELZERO",&b)) discreteLZero = b; if (GetConfStr (cParm,nParm,"ORPHANMACFILE",buf)) strcpy(orphanMacFile,buf); if (GetConfStr (cParm,nParm,"HMMSETKIND",buf)) { if (strcmp(buf,"PLAIN")==0) cfHSKind = PLAINHS; else if (strcmp(buf,"SHARED")==0) cfHSKind = SHAREDHS; else if (strcmp(buf,"TIED")==0) cfHSKind = TIEDHS; else if (strcmp(buf,"DISCRETE")==0) cfHSKind = DISCRETEHS; else HError(7070,"InitModel: Unknown HMM kind %s",buf); forceHSKind = TRUE; } if (GetConfBool(cParm,nParm,"REORDERCOMPS",&b)) reorderComps = b; if (GetConfInt(cParm,nParm,"PDE1BLOCKEND",&i)) pde1BlockEnd = i; if (GetConfInt(cParm,nParm,"PDE2BLOCKEND",&i)) pde2BlockEnd = i; if (GetConfFlt(cParm,nParm,"PDETHRESHOLD1",&d)) pdeTh1 = d; if (GetConfFlt(cParm,nParm,"PDETHRESHOLD2",&d)) pdeTh2 = d; }}/* -------------------- Check Model Consistency -------------------- *//* CheckMix: check given mixture pdf of state n, stream s, mixture m */static ReturnStatus CheckMix(char *defName, MixPDF *mp, int n, int s, int m, int sw){ if (trace&T_CHK) { printf("HModel: checking mix %d\n",m); fflush(stdout); } if (mp->mean == NULL){ HRError(7030,"CheckMix: %s: pdf for s=%d,j=%d,m=%d has NULL mean", defName,n,s,m); return(FAIL); } if (VectorSize(mp->mean) != sw){ HRError(7030,"CheckMix: %s: mean for s=%d,j=%d,m=%d has bad vecSize", defName,n,s,m); return(FAIL); } if (mp->cov.var == NULL){ HRError(7030,"CheckMix: %s: pdf for s=%d,j=%d,m=%d has NULL covariance", defName,n,s,m); return(FAIL); } switch(mp->ckind){ case DIAGC: if (VectorSize(mp->cov.var) != sw){ HRError(7030,"CheckMix: %s: var for s=%d,j=%d,m=%d has bad vecSize", defName,n,s,m); return(FAIL); } break; case FULLC: case LLTC: if (TriMatSize(mp->cov.inv) != sw){ HRError(7030,"CheckMix: %s: inv for s=%d,j=%d,m=%d has bad dimens", defName,n,s,m); return(FAIL); } break; case XFORMC: if (NumCols(mp->cov.xform) != sw){ HRError(7030,"CheckMix: %s: xform for s=%d,j=%d,m=%d has bad dimens", defName,n,s,m); return(FAIL); } break; } if (mp->gConst == LZERO){ if (mp->ckind==DIAGC) FixDiagGConst(mp); else if (mp->ckind==FULLC) FixFullGConst(mp,-CovDet(mp->cov.inv)); else if (mp->ckind==LLTC) FixLLTGConst(mp); else if (mp->ckind==XFORMC) HRError(7030,"CheckMix: No GConst set for xformc covariance matrix"); } Touch(&mp->nUse); return(SUCCESS);}/* CheckStream: check the stream s for state n */static ReturnStatus CheckStream(char *defName, HLink hmm, StreamElem *se, int s, int n){ double sum=0.0; int m,sw; LogFloat wt; MixtureElem *me; MixPDF *mp; HSetKind hk; if (trace&T_CHK) { printf("HModel: checking stream %d, se=%p\n",s,se); fflush(stdout); } hk = hmm->owner->hsKind; sw = hmm->owner->swidth[s]; switch(hk){ case PLAINHS: case SHAREDHS: me = se->spdf.cpdf+1; for (m=1; m<=se->nMix; m++,me++){ wt=me->weight; wt = MixWeight(hmm->owner,wt); sum += wt; if (wt > MINMIX ){ if (me->mpdf == NULL){ HRError(7030,"CheckStream: %s: MixDef %d missing for s=%d, j=%d", defName, m, s, n); return(FAIL); } mp = me->mpdf; if((!IsSeen(mp->nUse))&&(CheckMix(defName,me->mpdf,n,s,m,sw)<SUCCESS)) return(FAIL); } } break; case TIEDHS: for (m=1; m<=se->nMix; m++) sum += se->spdf.tpdf[m]; break; case DISCRETEHS: for (m=1; m<=se->nMix; m++) sum += exp((float)se->spdf.dpdf[m]/DLOGSCALE); break; } if (sum<0.99 || sum>1.01){ HRError(7031,"CheckStream: %s: Mix weights sum %e for s=%d, j=%d", defName,sum,s,n); return(FAIL); } return(SUCCESS);}/* CheckState: check state n */static ReturnStatus CheckState(char *defName, HLink hmm, StateInfo *si, int n){ int s,S; StreamElem *ste; if (trace&T_CHK) { printf("HModel: checking state %d, si=%p\n",n,si); fflush(stdout); } S = hmm->owner->swidth[0]; if (si->pdf == NULL){ HRError(7030,"CheckState: %s: state %d has no pdf",defName,n); return(FAIL); } ste = si->pdf+1; for (s=1; s<=S; s++,ste++){ if (ste->spdf.cpdf == NULL){ HRError(7030,"CheckState: %s: Stream %d missing in state %d",defName,s,n); return(FAIL); } if(CheckStream(defName,hmm,ste,s,n)<SUCCESS) return(FAIL); } if (S>1) if (si->weights==NULL){ HRError(7030,"CheckState: %s: Stream weights missing in state %d",defName,n); return(FAIL); } Touch(&si->nUse); return(SUCCESS);}/* CheckHMM: check the consistency of the given model */static ReturnStatus CheckHMM(char *defName, HLink hmm){ int i; StateElem *se; StateInfo *si; if (trace&T_CHK) { printf("HModel: checking HMM %s\n",defName); fflush(stdout); } for (i=2,se=hmm->svec+2; i<hmm->numStates; i++,se++) { si = se->info; if (si == NULL){ HRError(7030,"CheckHMM: %s: state %d has NULL info",defName,i); return(FAIL); } else if((!IsSeen(si->nUse))&&(CheckState(defName,hmm,si,i)<SUCCESS)) return(FAIL); } return(SUCCESS);}/* CheckTMRecs: check the tied mix codebook attached to a HMM Set */static ReturnStatus CheckTMRecs(HMMSet *hset){ int s,m,sw; MixPDF *mp; if (trace&T_CHK) { printf("HModel: checking tied mixture codebook\n"); fflush(stdout); } for (s=1;s<=hset->swidth[0]; s++){ sw = hset->swidth[s]; if (hset->tmRecs[s].mixId == NULL){ HRError(7030,"CheckTMRecs: no mix id set in stream %d",s); return(FAIL); } if (hset->tmRecs[s].mixes == NULL){ HRError(7030,"CheckTMRecs: no mixes array allocated in stream %d",s); return(FAIL); } for (m=1; m<=hset->tmRecs[s].nMix; m++){ mp = hset->tmRecs[s].mixes[m]; if(CheckMix("TMRec",mp,0,s,m,sw)<SUCCESS) return(FAIL); } } return(SUCCESS);}/* CheckDiscrete: check discrete HMM Set */static ReturnStatus CheckDiscrete(HMMSet *hset){ int s; for (s=1;s<=hset->swidth[0]; s++){ if ((hset->swidth[s] != 1) && (!(HasVQ(hset->pkind)))) { HRError(7030,"CheckDiscrete: stream width not equal to 1 in discrete stream %d ",s); return(FAIL); } } return (SUCCESS);}/* CheckHSet: check the consistency of a complete HMM Set */static ReturnStatus CheckHSet(HMMSet *hset){ int h; MLink m; for (h=0; h<MACHASHSIZE; h++) for (m=hset->mtab[h]; m!=NULL; m=m->next) if (m->type == 'h') if(CheckHMM(m->id->name,(HLink)m->structure)<SUCCESS) return(FAIL); if ((hset->hsKind == TIEDHS) && (CheckTMRecs(hset)<SUCCESS)) return(FAIL); if ((hset->hsKind == DISCRETEHS) && (CheckDiscrete(hset)<SUCCESS)) return(FAIL); ClearSeenFlags(hset,CLR_ALL); return(SUCCESS);}/* ------------------------ Lexical Scanner ------------------------ */#define MAXSYMLEN 40/* Internal and binary keyword representation */typedef enum { /* Only a character big !! */ BEGINHMM, USEMAC, ENDHMM, NUMMIXES, NUMSTATES, STREAMINFO, VECSIZE, NDUR, PDUR, GDUR, RELDUR, GENDUR, DIAGCOV, FULLCOV, XFORMCOV, STATE, TMIX, MIXTURE, STREAM, SWEIGHTS, MEAN, VARIANCE, INVCOVAR, XFORM, GCONST, DURATION, INVDIAGCOV, TRANSP, DPROB, LLTCOV, LLTCOVAR, XFORMKIND=90, PARENTXFORM, NUMXFORMS, XFORMSET, LINXFORM, OFFSET, BIAS, LOGDET, BLOCKINFO, BLOCK, BASECLASS, CLASS, XFORMWGTSET, CLASSXFORM, MMFIDMASK, PARAMETERS, NUMCLASSES, ADAPTKIND, PREQUAL, INPUTXFORM, RCLASS=110, REGTREE, NODE, TNODE, HMMSETID=119, PARMKIND=120, MACRO, EOFSYM, NULLSYM /* Special Syms - not literals */} Symbol;/* Mapping between verbose keywords for readable external HMM format *//* and internal/external binary token numbers */static struct { char *name; Symbol sym; } symMap[] = { { "BEGINHMM", BEGINHMM }, { "USE", USEMAC }, { "ENDHMM", ENDHMM }, { "NUMMIXES", NUMMIXES }, { "NUMSTATES", NUMSTATES }, { "STREAMINFO", STREAMINFO }, { "VECSIZE", VECSIZE }, { "NULLD", NDUR }, { "POISSOND", PDUR }, { "GAMMAD", GDUR },
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -