📄 htklattice.cc
字号:
nodeinfo.xscore3 = getHTKscore(value, HTKlogbase, file);
} else if (keyis("x4")) {
nodeinfo.xscore4 = getHTKscore(value, HTKlogbase, file);
} else if (keyis("x5")) {
nodeinfo.xscore5 = getHTKscore(value, HTKlogbase, file);
} else if (keyis("x6")) {
nodeinfo.xscore6 = getHTKscore(value, HTKlogbase, file);
} else if (keyis("x7")) {
nodeinfo.xscore7 = getHTKscore(value, HTKlogbase, file);
} else if (keyis("x8")) {
nodeinfo.xscore8 = getHTKscore(value, HTKlogbase, file);
} else if (keyis("x9")) {
nodeinfo.xscore9 = getHTKscore(value, HTKlogbase, file);
} else if (keyis("p")) {
nodeinfo.posterior = atof(value);
} else {
file.position() << "unexpected node field name "
<< key << endl;
if (!useNullNodes) vocab.remove(HTKNodeDummy);
return false;
}
}
if (nodeinfo.time != HTK_undef_float) {
// record node time, but no word-related info
LatticeNode *nullNode = findNode(nullNodeIndex);
assert(nullNode != 0);
HTKWordInfo *nullInfo = new HTKWordInfo;
assert(nullInfo != 0);
htkinfos[htkinfos.size()] = nullInfo;
nullNode->htkinfo = nullInfo;
nullInfo->time = nodeinfo.time;
}
continue;
/*
* Header fields
*/
} else if (keyis("V") || keyis("VERSION")) {
; // ignore
} else if ( keyis("U") || keyis("UTTERANCE")) {
if (name) free((void *)name);
// HACK: strip duration spec (which shouldn't be there)
char *p = strstr(value, "(duration=");
if (p != 0) *p = '\0';
name = strdup(value);
assert(name != 0);
} else if (keyis("base")) {
HTKlogbase = (float)atof(value);
if (HTKwdpenalty[0] &&
(header == 0 || header->wdpenalty == HTK_undef_float))
{
// recompute wdpenalty with new logbase
htkheader.wdpenalty =
getHTKscore(HTKwdpenalty, HTKlogbase, file);
}
} else if (keyis("start")) {
HTKinitial = atoi(value);
} else if (keyis("end")) {
HTKfinal = atoi(value);
} else if (keyis("dir")) {
HTKdirection = value[0];
} else if (keyis("tscale")) {
htkheader.tscale = atof(value);
} else if (keyis("hmms")) {
htkheader.hmms = strdup(value);
assert(htkheader.hmms != 0);
} else if (keyis("ngname")) {
htkheader.ngname = strdup(value);
assert(htkheader.ngname != 0);
} else if (keyis("lmname")) {
htkheader.lmname = strdup(value);
assert(htkheader.lmname != 0);
} else if (keyis("vocab")) {
htkheader.vocab = strdup(value);
assert(htkheader.vocab != 0);
} else if (keyis("acscale")) {
if (header == 0 || header->acscale == HTK_undef_float) {
htkheader.acscale = atof(value);
}
} else if (keyis("ngscale")) {
if (header == 0 || header->ngscale == HTK_undef_float) {
htkheader.ngscale = atof(value);
}
} else if (keyis("lmscale")) {
if (header == 0 || header->lmscale == HTK_undef_float) {
htkheader.lmscale = atof(value);
}
} else if (keyis("prscale")) {
if (header == 0 || header->prscale == HTK_undef_float) {
htkheader.prscale = atof(value);
}
} else if (keyis("duscale")) {
if (header == 0 || header->duscale == HTK_undef_float) {
htkheader.duscale = atof(value);
}
} else if (keyis("wdpenalty")) {
if (header == 0 || header->wdpenalty == HTK_undef_float) {
htkheader.wdpenalty = getHTKscore(value, HTKlogbase, file);
strncpy(HTKwdpenalty, value, sizeof(HTKwdpenalty)-1);
}
} else if (keyis("x1scale")) {
if (header == 0 || header->x1scale == HTK_undef_float) {
htkheader.x1scale = atof(value);
}
} else if (keyis("x2scale")) {
if (header == 0 || header->x2scale == HTK_undef_float) {
htkheader.x2scale = atof(value);
}
} else if (keyis("x3scale")) {
if (header == 0 || header->x3scale == HTK_undef_float) {
htkheader.x3scale = atof(value);
}
} else if (keyis("x4scale")) {
if (header == 0 || header->x4scale == HTK_undef_float) {
htkheader.x4scale = atof(value);
}
} else if (keyis("x5scale")) {
if (header == 0 || header->x5scale == HTK_undef_float) {
htkheader.x5scale = atof(value);
}
} else if (keyis("x6scale")) {
if (header == 0 || header->x6scale == HTK_undef_float) {
htkheader.x6scale = atof(value);
}
} else if (keyis("x7scale")) {
if (header == 0 || header->x7scale == HTK_undef_float) {
htkheader.x7scale = atof(value);
}
} else if (keyis("x8scale")) {
if (header == 0 || header->x8scale == HTK_undef_float) {
htkheader.x8scale = atof(value);
}
} else if (keyis("x9scale")) {
if (header == 0 || header->x9scale == HTK_undef_float) {
htkheader.x9scale = atof(value);
}
} else if (keyis("amscale")) {
if (header == 0 || header->amscale == HTK_undef_float) {
htkheader.amscale = atof(value);
}
} else if (keyis("NODES") || keyis("N")) {
HTKnumnodes = atoi(value);
} else if (keyis("LINKS") || keyis("L")) {
HTKnumlinks = atoi(value);
} else {
file.position() << "unknown field name " << key << endl;
if (!useNullNodes) vocab.remove(HTKNodeDummy);
return false;
}
#undef keyis
}
}
if (HTKnumnodes == 0) {
file.position() << "lattice has no nodes\n";
if (!useNullNodes) vocab.remove(HTKNodeDummy);
return false;
}
/*
* Set up initial node
*/
HTKWordInfo *initialinfo;
LatticeNode *initialNode;
if (HTKinitial != HTK_undef_uint) {
initialinfo = &nodeInfoMap[HTKinitial];
NodeIndex *initialPtr = nodeMap.find(HTKinitial);
if (initialPtr) {
initial = *initialPtr;
initialNode = findNode(initial);
} else {
file.position() << "undefined start node " << HTKinitial << endl;
if (!useNullNodes) vocab.remove(HTKNodeDummy);
return false;
}
} else {
// search for start node: the one without incoming transitions
LHashIter<NodeIndex, LatticeNode> nodeIter(nodes);
NodeIndex nodeIndex;
while (LatticeNode *node = nodeIter.next(nodeIndex)) {
if (node->inTransitions.numEntries() == 0) {
initial = nodeIndex;
initialNode = node;
break;
}
}
// now find the HTK node info associated with first node
LHashIter<unsigned, NodeIndex> nodeMapIter(nodeMap);
unsigned htkNode;
while (NodeIndex *pfsgNode = nodeMapIter.next(htkNode)) {
if (*pfsgNode == initial) {
HTKinitial = htkNode;
initialinfo = &nodeInfoMap[HTKinitial];
break;
}
}
}
initialNode->word = vocab.ssIndex();
// attach HTK initial node info to lattice initial node
if (initialinfo) {
initialNode->htkinfo = new HTKWordInfo(*initialinfo);
assert(initialNode->htkinfo != 0);
htkinfos[htkinfos.size()] = initialNode->htkinfo;
}
/*
* Set up final node
*/
HTKWordInfo *finalinfo;
LatticeNode *finalNode;
if (HTKfinal != HTK_undef_uint) {
finalinfo = &nodeInfoMap[HTKfinal];
NodeIndex *finalPtr = nodeMap.find(HTKfinal);
if (finalPtr) {
final = *finalPtr;
finalNode = findNode(final);
} else {
file.position() << "undefined end node " << HTKfinal << endl;
if (!useNullNodes) vocab.remove(HTKNodeDummy);
return false;
}
} else {
// search for end node: the one without outgoing transitions
LHashIter<NodeIndex, LatticeNode> nodeIter(nodes);
NodeIndex nodeIndex;
while (LatticeNode *node = nodeIter.next(nodeIndex)) {
if (node->outTransitions.numEntries() == 0) {
final = nodeIndex;
finalNode = node;
break;
}
}
// now find the HTK node info associated with final node
LHashIter<unsigned, NodeIndex> nodeMapIter(nodeMap);
unsigned htkNode;
while (NodeIndex *pfsgNode = nodeMapIter.next(htkNode)) {
if (*pfsgNode == final) {
HTKfinal = htkNode;
finalinfo = &nodeInfoMap[HTKfinal];
break;
}
}
}
finalNode->word = vocab.seIndex();
// attach HTK final node info to lattice final node
if (finalinfo) {
finalNode->htkinfo = new HTKWordInfo(*finalinfo);
assert(finalNode->htkinfo != 0);
htkinfos[htkinfos.size()] = finalNode->htkinfo;
}
// eliminate dummy nodes
if (!useNullNodes) {
removeAllXNodes(HTKNodeDummy);
vocab.remove(HTKNodeDummy);
}
return true;
}
/*
* allowAsTrans()
* Determine if this node has the appropriate properties to be printed
* as just an HTK transition. The purpose is to allow a more compact printing.
* If an internal lattice node meets these characteristics then it need not
* be printed as an HTK node, and it's transitions can also be saved from
* printing because the node itself will be printed as the transition.
*
* Check for these properties:
* - must have one outgoing transition
* - must have one incoming transition
* - nodes on each side must be HTK null nodes
* - don't allow as a transition if an adjacent node could also be allowed
* (this last case should allow for the collapsing of these two nodes,
* but it's not impl.)
*/
static Boolean
allowAsTrans(Lattice &lat, NodeIndex nodeIndex)
{
LatticeNode *node = lat.findNode(nodeIndex);
assert(node != 0);
if (node->inTransitions.numEntries() == 1 &&
node->outTransitions.numEntries() == 1)
{
TRANSITER_T<NodeIndex,LatticeTransition>
outTransIter(node->outTransitions);
NodeIndex next;
while (outTransIter.next(next)) {
LatticeNode *nextNode = lat.findNode(next);
assert(nextNode != 0);
// check if next node is a NULL (the final node also acts as one)
if (nextNode->word == Vocab_None || next == lat.getFinal()) {
TRANSITER_T<NodeIndex,LatticeTransition>
inTransIter(node->inTransitions);
NodeIndex prev;
while (inTransIter.next(prev)) {
LatticeNode *prevNode = lat.findNode(prev);
assert(prevNode != 0);
// check if prev node is a NULL
// (the inital node also acts as one)
if (prevNode->word == Vocab_None ||
prev == lat.getInitial())
{
// check if next node would be allowed as a transition
if (allowAsTrans(lat, next)) {
// if we have a string of two nodes that could be
// transitions, that should be redundant and allow
// them to be combined, for now we'll just treat
// it as a case that returns false because two
// adjacent transitions is a problem (a node
// between them is required) so the first node
// will not be allowed as a transition
return false;
} else {
return true;
}
}
}
}
}
}
return false;
}
static double
scaleHTKScore(double score, double logscale)
{
if (logscale == 0.0) {
return LogPtoProb(score);
} else {
return score * logscale;
}
}
static void
writeScoreInfo(File &file, HTKWordInfo &htkinfo, HTKScoreMapping scoreMapping,
double logscale)
{
if (scoreMapping != mapHTKacoustic &&
htkinfo.acoustic != HTK_undef_float)
{
fprintf(file, "\ta=%lg", scaleHTKScore(htkinfo.acoustic, logscale));
}
if (htkinfo.pron != HTK_undef_float)
{
fprintf(file, "\tr=%lg", scaleHTKScore(htkinfo.pron, logscale));
}
if (htkinfo.duration != HTK_undef_float)
{
fprintf(file, "\tds=%lg", scaleHTKScore(htkinfo.duration, logscale));
}
if (htkinfo.xscore1 != HTK_undef_float)
{
fprintf(file, "\tx1=%lg", scaleHTKScore(htkinfo.xscore1, logscale));
}
if (htkinfo.xscore2 != HTK_undef_float)
{
fprintf(file, "\tx2=%lg", scaleHTKScore(htkinfo.xscore2, logscale));
}
if (htkinfo.xscore3 != HTK_undef_float)
{
fprintf(file, "\tx3=%lg", scaleHTKScore(htkinfo.xscore3, logscale));
}
if (htkinfo.xscore4 != HTK_undef_float)
{
fprintf(file, "\tx4=%lg", scaleHTKScore(htkinfo.xscore4, logscale));
}
if (htkinfo.xscore5 != HTK_undef_float)
{
fprintf(file, "\tx5=%lg", scaleHTKScore(htkinfo.xscore5, logscale));
}
if (htkinfo.xscore6 != HTK_undef_float)
{
fprintf(file, "\tx6=%lg", scaleHTKScore(htkinfo.xscore6, logscale));
}
if (htkinfo.xscore7 != HTK_undef_float)
{
fprintf(file, "\tx7=%lg", scaleHTKScore(htkinfo.xscore7, logscale));
}
if (htkinfo.xscore8 != HTK_undef_float)
{
fprintf(file, "\tx8=%lg", scaleHTKScore(htkinfo.xscore8, logscale));
}
if (htkinfo.xscore9 != HTK_undef_float)
{
fprintf(file, "\tx9=%lg", scaleHTKScore(htkinfo.xscore9, logscale));
}
}
static void
writeWordInfo(File &file, HTKWordInfo &htkinfo)
{
if (htkinfo.var != HTK_undef_uint)
{
fprintf(file, "\tv=%u", htkinfo.var);
}
if (htkinfo.div != 0)
{
fprintf(file, "\td=%s", htkinfo.div);
}
if (htkinfo.states != 0)
{
fprintf(file, "\ts=%s", htkinfo.states);
}
}
/*
* Output lattice in HTK format
* Algorithm:
* - each lattice node becomes an HTK node
* (unless it has only one incoming and one outgoing transition,
* both to HTK null nodes)
* - each lattice transitions becomes an HTK link.
* (unless it exists on a node which has been flagged to print as a
* transition, then the links are ignored)
* - word information is added to the HTK nodes.
* (all words and scores must be printed on the HTK transitions,
* not on the words)
* - link information attached to each node is added to the HTK link
* leading into the node.
* - lattice transition weights are mapped to one of the
* HTK score fields as indicated by the second argument.
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -