📄 hlat.c
字号:
/* ----------------------------------------------------------- *//* *//* ___ *//* |_| | |_/ SPEECH *//* | | | | \ RECOGNITION *//* ========= SOFTWARE */ /* *//* *//* ----------------------------------------------------------- *//* developed at: *//* *//* Speech Vision and Robotics group *//* Cambridge University Engineering Department *//* http://svr-www.eng.cam.ac.uk/ *//* *//* author: Gunnar Evermann <ge204@eng.cam.ac.uk> *//* ----------------------------------------------------------- *//* Copyright: *//* 2001-2004 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: HLat.c: Lattice Manipulation *//* ----------------------------------------------------------- *//*#### todo: - implement lattice oracle WER calculation - allow batch processing?*/char *hlat_version = "!HVER!HLat: 3.3 [CUED 28/04/05]";char *hlat_vc_id = "$Id: HLat.c,v 1.1.1.1 2005/05/12 10:52:50 jal58 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 "HDict.h"#include "HNet.h"#include "HLM.h"#include "HLat.h"/* ----------------------------- Trace Flags ------------------------- */#define T_TOP 00001#define T_PRUN 00002#define T_FB 00004#define T_EXP 00010#define T_MEM 00020#define T_TRAN 00040#define T_LLF 00100static int trace=0;static ConfParam *cParm[MAXGLOBS]; /* config parameters */static int nParm = 0;/* --------------------------- Global Flags -------------------------- */static LabId startWord; /* word at start of Lattice (!SENT_START) */static LabId endWord; /* word at end of Lattice (!SENT_END) */static LabId startLMWord; /* word at start in LM (<s>) */static LabId endLMWord; /* word at end in LM (</s>) */static LabId nullWord; /* null word in Lattices (!NULL) */static Boolean beamPruneArcs = TRUE; /* apply beam pruning to arcs (rather than just nodes) */static char *llfExt = "LLF"; /* extension for LLF lattice files */static MemHeap slaHeap, slnHeap;/* MHEAPs for use in LatExpand() *//* --------------------------- Prototypes ---------------------------- */#ifndef NO_LAT_LMtypedef struct _SubLNode SubLNode;typedef struct _SubLArc SubLArc;struct _SubLNode { union { LMState lmstate; LNode *newln; } data; SubLArc *foll; SubLNode *next;};struct _SubLArc { LogFloat lmprob; SubLNode *end; LArc *la; SubLArc *next;};#endif/* --------------------------- LLF processing ---------------------- */typedef struct _LLFInfo LLFInfo;struct _LLFInfo { LLFInfo *next; char name[MAXFNAMELEN]; Source source; int lastAccess;};static int numLLFs = 0; static int maxLLFs = 5; static int numLatsLoaded = 0;static LLFInfo *llfInfo = NULL;static MemHeap llfHeap;void CloseLLF (LLFInfo *llf){ if (trace&T_LLF) printf ("Closing LLF %s\n", llf->name); CloseSource (&llf->source); llf->name[0] = '\0'; llf->lastAccess = 0;}LLFInfo *OpenLLF (char *fn){ LLFInfo *llf; Source s; char buf[MAXFNAMELEN]; if (trace&T_LLF) printf ("Opening LLF %s\n", fn); if (InitSource (fn, &s, NetFilter) < SUCCESS) { HError(-8630,"OpenLLF: Cannot open LLF %s", fn); return NULL; } if (!ReadStringWithLen (&s, buf, MAXFNAMELEN) || strcmp (buf, "#!LLF!#")) { /* no LLF header or read from pipe failed */ HError(-8630,"OpenLLF: Cannot read from LLF %s", fn); return NULL; } if (numLLFs < maxLLFs) { ++numLLFs; llf = New (&llfHeap, sizeof (LLFInfo)); llf->next = llfInfo; llfInfo = llf; } else { LLFInfo *l; /* find oldest (least recently accessed) LLF */ llf = llfInfo; for (l = llfInfo->next; l; l = l->next) if (l->lastAccess < llf->lastAccess) llf = l; CloseLLF (llf); } strcpy (llf->name, fn); llf->source = s; return llf;}void ScanLLF (LLFInfo *llf, char *fn, char *ext){ char buf[MAXFNAMELEN]; char latfn[MAXFNAMELEN]; llf->lastAccess = numLatsLoaded; MakeFN (fn, NULL, ext, latfn); while (ReadStringWithLen (&llf->source, buf, MAXFNAMELEN)) { if (!strcmp(buf, latfn)) { /* found name */ return; } if (trace&T_LLF) printf ("ScanLLF: skipping '%s'\n", buf); ReadUntilLine (&llf->source, "."); /* skip this lattice */ } HError (8631, "ScanLLF: lattice '%s' not found in LLF '%s'\n", latfn, llf->name);}Lattice *GetLattice (char *fn, char *path, char *ext, /* arguments of ReadLattice() below */ MemHeap *heap, Vocab *voc, Boolean shortArc, Boolean add2Dict){ Lattice *lat; LLFInfo *llf; char llfName[MAXFNAMELEN]; MakeFN (path, NULL, llfExt, llfName); /* check whether LLF is open already */ for (llf = llfInfo; llf; llf = llf->next) { if (!strcmp (llfName, llf->name)) break; } if (!llf) { /* not found -> try to open LLF */ llf = OpenLLF (llfName); if (!llf) { /* can't find LLF -> fall back to single file lattices */ char latfn[MAXFNAMELEN]; FILE *f; Boolean isPipe; MakeFN (fn, path, ext, latfn); if ((f = FOpen(latfn, NetFilter, &isPipe)) == NULL) HError(8632,"GetLattice: Cannot open Lattice file %s", latfn); lat = ReadLattice (f, heap, voc, shortArc, add2Dict); FClose(f, isPipe); return lat; } } /* scan for lattice with requested name in LLF */ ++numLatsLoaded; ScanLLF (llf, fn, ext); /* note we do not support sub lattices here, thus call ReadOneLattice() directly */ lat = ReadOneLattice (&llf->source, heap, voc, shortArc, add2Dict); return lat;}/* --------------------------- Initialisation ---------------------- *//* EXPORT->InitLat: register module & set configuration parameters */void InitLat(void){ int i; Boolean b; char buf[MAXSTRLEN]; Register(hlat_version,hlat_vc_id); nParm = GetConfig("HLAT", TRUE, cParm, MAXGLOBS); if (nParm>0){ if (GetConfInt(cParm,nParm,"TRACE",&i)) trace = i; if (GetConfBool(cParm,nParm,"BEAMPRUNEARCS",&b)) beamPruneArcs = b; if (GetConfStr(cParm,nParm,"LLFEXT",buf)) llfExt = CopyString(&gstack,buf); if (GetConfInt(cParm,nParm,"MAXLLFS",&i)) maxLLFs = i; } CreateHeap (&llfHeap, "LLF stack", MSTAK, 1, 1.0, 1000, 10000);#ifndef NO_LAT_LM CreateHeap (&slaHeap, "LatExpand arc heap", MHEAP, sizeof (SubLArc), 1.0, 1000, 128000); CreateHeap (&slnHeap, "LatExpand node heap", MHEAP,sizeof (SubLNode), 1.0, 1000, 32000);#endif}/* --------------------------- Lattice processing ------------------- *//* LatCheck check lattice for consistency: single start & end nodes; no cycles.*/void LatCheck (Lattice *lat){ int i, nStart, nEnd; LNode *ln; LNode **topOrder; /* check for unique start and end nodes */ nStart = nEnd = 0; for (i = 0, ln = lat->lnodes; i < lat->nn; ++i, ++ln) { if (!ln->pred) ++nStart; if (!ln->foll) ++nEnd; } if (nStart != 1) HError (8622, "HLat: lattice has %d start nodes (should be 1)", nStart); if (nEnd != 1) HError (8622, "HLat: lattice has %d end nodes (should be 1)", nEnd); /* check wheter lat is a DAG ( <=> top order exists). */ topOrder = (LNode **) New (&gcheap, lat->nn * sizeof(LNode *)); if (!LatTopSort (lat, topOrder)) HError (8622, "HLat: lattice contains cylces"); Dispose (&gcheap, topOrder);}/* FixPronProbs replace pronunciation probabilities in lattices with values taken from the dictionary*/void FixPronProbs (Lattice *lat, Vocab *voc){ int i, v; LNode *ln; Pron pron; LArc *la; for (i = 0, ln = lat->lnodes; i < lat->nn; ++i, ++ln) { if (ln->word != voc->nullWord) { if (ln->v > ln->word->nprons) HError (8621, "FixPronprbs: lattice refers to non-existing pron"); pron = ln->word->pron; for (v = 2; v <= ln->v; ++v) pron = pron->next; if (pron->pnum != ln->v) HError (8621, "FixPronprbs: dict pron numbering invalid"); for (la = ln->pred; la; la = la->parc) la->prlike = pron->prob; } else { for (la = ln->pred; la; la = la->parc) la->prlike = 0.0; } }}/* LatStartNode return lattice start node ###GE: maybe store this in Lattice structure to save time?*/LNode *LatStartNode (Lattice *lat){ int i; LNode *ln; for (i = 0, ln = lat->lnodes; i < lat->nn; ++i, ++ln) if (!ln->pred) return ln; HError (8622, "HLat: lattice has no start node"); return NULL; /* make compiler happy */}/* LatEndNode return lattice end node ###GE: maybe store this in Lattice structure to save time?*/LNode *LatEndNode (Lattice *lat){ int i; LNode *ln; for (i = 0, ln = lat->lnodes; i < lat->nn; ++i, ++ln) if (!ln->foll) return ln; HError (8622, "HLat: lattice has no end node"); return NULL; /* make compiler happy */}/* helper function for LatTopSort() number preceeding nodes depth first */void LatTopSortVisit (LNode *ln, int *time){ LArc *la; ln->n = -2; /* mark node as seen, but not numbered, yet (GRAY in CLR) */ for (la = ln->pred; la; la = la->parc) if (la->start->n == -1) LatTopSortVisit (la->start, time); ++(*time); ln->n = *time;}/* LatTopSort
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -