Initial commit: FunASR Speech Recognition Toolkit
Update API Documentation / build-api-docs (push) Has been cancelled
Update API Documentation / build-api-docs (push) Has been cancelled
Add complete FunASR codebase including models, runtime, and documentation.
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
|
||||
# make "all" the target.
|
||||
all:
|
||||
|
||||
# Disable linking math libs because not needed here. Just for compilation speed.
|
||||
# no, it's now needed for context-fst-test.
|
||||
# MATHLIB = NONE
|
||||
|
||||
EXTRA_CXXFLAGS = -Wno-sign-compare
|
||||
|
||||
include ../kaldi.mk
|
||||
|
||||
BINFILES = fstdeterminizestar \
|
||||
fstrmsymbols fstisstochastic fstminimizeencoded fstmakecontextfst \
|
||||
fstmakecontextsyms fstaddsubsequentialloop fstaddselfloops \
|
||||
fstrmepslocal fstcomposecontext fsttablecompose fstrand \
|
||||
fstdeterminizelog fstphicompose fstcopy \
|
||||
fstpushspecial fsts-to-transcripts fsts-project fsts-union \
|
||||
fsts-concat make-grammar-fst
|
||||
|
||||
OBJFILES =
|
||||
|
||||
TESTFILES =
|
||||
|
||||
# actually, this library is currently empty. Everything is a header.
|
||||
LIBFILE =
|
||||
|
||||
ADDLIBS = ../decoder/kaldi-decoder.a ../fstext/kaldi-fstext.a \
|
||||
../util/kaldi-util.a ../matrix/kaldi-matrix.a ../base/kaldi-base.a
|
||||
|
||||
include ../makefiles/default_rules.mk
|
||||
@@ -0,0 +1,93 @@
|
||||
// fstbin/fstaddselfloops.cc
|
||||
|
||||
// Copyright 2009-2011 Microsoft Corporation
|
||||
|
||||
// See ../../COPYING for clarification regarding multiple authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
// MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
// See the Apache 2 License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#include "base/kaldi-common.h"
|
||||
#include "fst/fstlib.h"
|
||||
#include "fstext/determinize-star.h"
|
||||
#include "fstext/fstext-utils.h"
|
||||
#include "fstext/kaldi-fst-io.h"
|
||||
#include "util/parse-options.h"
|
||||
#include "util/simple-io-funcs.h"
|
||||
/* some test examples:
|
||||
pushd ~/tmpdir
|
||||
( echo 3; echo 4) > in.list
|
||||
( echo 5; echo 6) > out.list
|
||||
( echo "0 0 0 0"; echo "0 0" ) | fstcompile | fstaddselfloops in.list out.list | fstprint
|
||||
( echo "0 1 0 1"; echo " 0 2 1 0"; echo "1 0"; echo "2 0"; ) | fstcompile | fstaddselfloops in.list out.list | fstprint
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
try {
|
||||
using namespace kaldi;
|
||||
using namespace fst;
|
||||
using kaldi::int32;
|
||||
|
||||
const char *usage =
|
||||
"Adds self-loops to states of an FST to propagate disambiguation symbols through it\n"
|
||||
"They are added on each final state and each state with non-epsilon output symbols\n"
|
||||
"on at least one arc out of the state. Useful in conjunction with predeterminize\n"
|
||||
"\n"
|
||||
"Usage: fstaddselfloops in-disambig-list out-disambig-list [in.fst [out.fst] ]\n"
|
||||
"E.g: fstaddselfloops in.list out.list < in.fst > withloops.fst\n"
|
||||
"in.list and out.list are lists of integers, one per line, of the\n"
|
||||
"same length.\n";
|
||||
|
||||
ParseOptions po(usage);
|
||||
po.Read(argc, argv);
|
||||
|
||||
if (po.NumArgs() < 2 || po.NumArgs() > 4) {
|
||||
po.PrintUsage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
std::string disambig_in_rxfilename = po.GetArg(1),
|
||||
disambig_out_rxfilename = po.GetArg(2),
|
||||
fst_in_filename = po.GetOptArg(3),
|
||||
fst_out_filename = po.GetOptArg(4);
|
||||
|
||||
VectorFst<StdArc> *fst = ReadFstKaldi(fst_in_filename);
|
||||
|
||||
std::vector<int32> disambig_in;
|
||||
if (!ReadIntegerVectorSimple(disambig_in_rxfilename, &disambig_in))
|
||||
KALDI_ERR << "fstaddselfloops: Could not read disambiguation symbols from "
|
||||
<< kaldi::PrintableRxfilename(disambig_in_rxfilename);
|
||||
|
||||
std::vector<int32> disambig_out;
|
||||
if (!ReadIntegerVectorSimple(disambig_out_rxfilename, &disambig_out))
|
||||
KALDI_ERR << "fstaddselfloops: Could not read disambiguation symbols from "
|
||||
<< kaldi::PrintableRxfilename(disambig_out_rxfilename);
|
||||
|
||||
if (disambig_in.size() != disambig_out.size())
|
||||
KALDI_ERR << "fstaddselfloops: mismatch in size of disambiguation symbols";
|
||||
|
||||
AddSelfLoops(fst, disambig_in, disambig_out);
|
||||
|
||||
WriteFstKaldi(*fst, fst_out_filename);
|
||||
|
||||
delete fst;
|
||||
|
||||
return 0;
|
||||
} catch(const std::exception &e) {
|
||||
std::cerr << e.what();
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
// fstbin/fstaddsubsequentialloop.cc
|
||||
|
||||
// Copyright 2009-2011 Microsoft Corporation
|
||||
|
||||
// See ../../COPYING for clarification regarding multiple authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
// MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
// See the Apache 2 License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#include "base/kaldi-common.h"
|
||||
#include "util/kaldi-io.h"
|
||||
#include "util/parse-options.h"
|
||||
#include "util/text-utils.h"
|
||||
#include "fst/fstlib.h"
|
||||
#include "fstext/fstext-utils.h"
|
||||
#include "fstext/context-fst.h"
|
||||
#include "fstext/kaldi-fst-io.h"
|
||||
|
||||
|
||||
|
||||
/* some test examples:
|
||||
( echo "0 0 0 0"; echo "0 0" ) | fstcompile | fstaddsubsequentialloop 1 | fstprint
|
||||
( echo "0 1 0 0"; echo " 0 2 0 0"; echo "1 0"; echo "2 0"; ) | fstcompile | fstaddsubsequentialloop 1 | fstprint
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
try {
|
||||
using namespace kaldi;
|
||||
using namespace fst;
|
||||
using kaldi::int32;
|
||||
|
||||
const char *usage =
|
||||
"Minimizes FST after encoding [this algorithm applicable to all FSTs in tropical semiring]\n"
|
||||
"\n"
|
||||
"Usage: fstaddsubsequentialloop subseq_sym [in.fst [out.fst] ]\n"
|
||||
"E.g.: fstaddsubsequentialloop 52 < LG.fst > LG_sub.fst\n";
|
||||
|
||||
float delta = kDelta;
|
||||
ParseOptions po(usage);
|
||||
po.Register("delta", &delta,
|
||||
"Delta likelihood used for quantization of weights");
|
||||
po.Read(argc, argv);
|
||||
|
||||
if (po.NumArgs() < 1 || po.NumArgs() > 3) {
|
||||
po.PrintUsage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int32 subseq_sym;
|
||||
if (!ConvertStringToInteger(po.GetArg(1), &subseq_sym))
|
||||
KALDI_ERR << "Invalid subsequential symbol "<<po.GetArg(1);
|
||||
|
||||
std::string fst_in_filename = po.GetOptArg(2);
|
||||
|
||||
std::string fst_out_filename = po.GetOptArg(3);
|
||||
|
||||
VectorFst<StdArc> *fst = ReadFstKaldi(fst_in_filename);
|
||||
|
||||
int32 h = HighestNumberedInputSymbol(*fst);
|
||||
if (subseq_sym <= h) {
|
||||
std::cerr << "fstaddsubsequentialloop.cc: subseq symbol does not seem right, "<<subseq_sym<<" <= "<<h<<'\n';
|
||||
}
|
||||
|
||||
AddSubsequentialLoop(subseq_sym, fst);
|
||||
|
||||
WriteFstKaldi(*fst, fst_out_filename);
|
||||
delete fst;
|
||||
return 0;
|
||||
} catch(const std::exception &e) {
|
||||
std::cerr << e.what();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
// fstbin/fstcomposecontext.cc
|
||||
|
||||
// Copyright 2009-2011 Microsoft Corporation
|
||||
|
||||
// See ../../COPYING for clarification regarding multiple authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
// MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
// See the Apache 2 License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#include "base/kaldi-common.h"
|
||||
#include "util/common-utils.h"
|
||||
#include "fst/fstlib.h"
|
||||
#include "fstext/context-fst.h"
|
||||
#include "fstext/grammar-context-fst.h"
|
||||
#include "fstext/fstext-utils.h"
|
||||
#include "fstext/kaldi-fst-io.h"
|
||||
|
||||
/*
|
||||
A couple of test examples:
|
||||
|
||||
pushd ~/tmpdir
|
||||
# (1) with no disambig syms.
|
||||
( echo "0 1 1 1"; echo "1 2 2 2"; echo "2 3 3 3"; echo "3 0" ) | fstcompile | fstcomposecontext ilabels.sym > tmp.fst
|
||||
( echo "<eps> 0"; echo "a 1"; echo "b 2"; echo "c 3" ) > phones.txt
|
||||
fstmakecontextsyms phones.txt ilabels.sym > context.txt
|
||||
fstprint --isymbols=context.txt --osymbols=phones.txt tmp.fst
|
||||
# and the result is:
|
||||
|
||||
WARNING (fstcomposecontext[5.4]:main():fstcomposecontext.cc:130) Disambiguation symbols list is empty; this likely indicates an error in data preparation.
|
||||
0 1 <eps> a
|
||||
1 2 <eps>/a/b b
|
||||
2 3 a/b/c c
|
||||
3 4 b/c/<eps> <eps>
|
||||
4
|
||||
|
||||
|
||||
# (2) with disambig syms:
|
||||
( echo 4; echo 5) > disambig.list
|
||||
( echo "<eps> 0"; echo "a 1"; echo "b 2"; echo "c 3"; echo "#0 4"; echo "#1 5") > phones.txt
|
||||
( echo "0 1 1 1"; echo "1 2 2 2"; echo " 2 3 4 4"; echo "3 4 3 3"; echo "4 5 5 5"; echo "5 0" ) | fstcompile > in.fst
|
||||
fstcomposecontext --read-disambig-syms=disambig.list ilabels.sym in.fst tmp.fst
|
||||
fstmakecontextsyms phones.txt ilabels.sym > context.txt
|
||||
cp phones.txt phones_disambig.txt; ( echo "#0 4"; echo "#1 5" ) >> phones_disambig.txt
|
||||
fstprint --isymbols=context.txt --osymbols=phones_disambig.txt tmp.fst
|
||||
|
||||
0 1 #-1 a
|
||||
1 2 <eps>/a/b b
|
||||
2 3 #0 #0
|
||||
3 4 a/b/c c
|
||||
4 5 #1 #1
|
||||
5 6 b/c/<eps> <eps>
|
||||
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
try {
|
||||
using namespace kaldi;
|
||||
using namespace fst;
|
||||
using kaldi::int32;
|
||||
/*
|
||||
# fstcomposecontext composes efficiently with a context fst
|
||||
# that it generates. Without --disambig-syms specified, it
|
||||
# assumes that all input symbols of in.fst are phones.
|
||||
# It adds the subsequential symbol itself (it does not
|
||||
# appear in the output so doesn't need to be specified by the user).
|
||||
# the disambig.list is a list of disambiguation symbols on the LHS
|
||||
# of in.fst. The symbols on the LHS of out.fst are indexes into
|
||||
# the ilabels.list file, which is a kaldi-format file containing a
|
||||
# vector<vector<int32> >, which specifies what the labels mean in
|
||||
# terms of windows of symbols.
|
||||
fstcomposecontext ilabels.sym [ in.fst [ out.fst ] ]
|
||||
--disambig-syms=disambig.list
|
||||
--context-size=3
|
||||
--central-position=1
|
||||
--binary=false
|
||||
*/
|
||||
|
||||
const char *usage =
|
||||
"Composes on the left with a dynamically created context FST\n"
|
||||
"\n"
|
||||
"Usage: fstcomposecontext <ilabels-output-file> [<in.fst> [<out.fst>] ]\n"
|
||||
"E.g: fstcomposecontext ilabels.sym < LG.fst > CLG.fst\n";
|
||||
|
||||
|
||||
ParseOptions po(usage);
|
||||
bool binary = true;
|
||||
std::string disambig_rxfilename,
|
||||
disambig_wxfilename;
|
||||
int32 context_width = 3, central_position = 1;
|
||||
int32 nonterm_phones_offset = -1;
|
||||
po.Register("binary", &binary,
|
||||
"If true, output ilabels-output-file in binary format");
|
||||
po.Register("read-disambig-syms", &disambig_rxfilename,
|
||||
"List of disambiguation symbols on input of in.fst");
|
||||
po.Register("write-disambig-syms", &disambig_wxfilename,
|
||||
"List of disambiguation symbols on input of out.fst");
|
||||
po.Register("context-size", &context_width, "Size of phone context window");
|
||||
po.Register("central-position", ¢ral_position,
|
||||
"Designated central position in context window");
|
||||
po.Register("nonterm-phones-offset", &nonterm_phones_offset,
|
||||
"The integer id of #nonterm_bos in your phones.txt, if present "
|
||||
"(only relevant for grammar-FST construction, see "
|
||||
"doc/grammar.dox");
|
||||
|
||||
po.Read(argc, argv);
|
||||
|
||||
if (po.NumArgs() < 1 || po.NumArgs() > 3) {
|
||||
po.PrintUsage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
std::string ilabels_out_filename = po.GetArg(1),
|
||||
fst_in_filename = po.GetOptArg(2),
|
||||
fst_out_filename = po.GetOptArg(3);
|
||||
|
||||
VectorFst<StdArc> *fst = ReadFstKaldi(fst_in_filename);
|
||||
|
||||
if ( (disambig_wxfilename != "") && (disambig_rxfilename == "") )
|
||||
KALDI_ERR << "fstcomposecontext: cannot specify --write-disambig-syms if "
|
||||
"not specifying --read-disambig-syms\n";
|
||||
|
||||
std::vector<int32> disambig_in;
|
||||
if (disambig_rxfilename != "")
|
||||
if (!ReadIntegerVectorSimple(disambig_rxfilename, &disambig_in))
|
||||
KALDI_ERR << "fstcomposecontext: Could not read disambiguation symbols from "
|
||||
<< PrintableRxfilename(disambig_rxfilename);
|
||||
|
||||
if (disambig_in.empty()) {
|
||||
KALDI_WARN << "Disambiguation symbols list is empty; this likely "
|
||||
<< "indicates an error in data preparation.";
|
||||
}
|
||||
|
||||
std::vector<std::vector<int32> > ilabels;
|
||||
VectorFst<StdArc> composed_fst;
|
||||
|
||||
// Work gets done here (see context-fst.h)
|
||||
if (nonterm_phones_offset < 0) {
|
||||
// The normal case.
|
||||
ComposeContext(disambig_in, context_width, central_position,
|
||||
fst, &composed_fst, &ilabels);
|
||||
} else {
|
||||
// The grammar-FST case. See ../doc/grammar.dox for an intro.
|
||||
if (context_width != 2 || central_position != 1) {
|
||||
KALDI_ERR << "Grammar-fst graph creation only supports models with left-"
|
||||
"biphone context. (--nonterm-phones-offset option was supplied).";
|
||||
}
|
||||
ComposeContextLeftBiphone(nonterm_phones_offset, disambig_in,
|
||||
*fst, &composed_fst, &ilabels);
|
||||
}
|
||||
WriteILabelInfo(Output(ilabels_out_filename, binary).Stream(),
|
||||
binary, ilabels);
|
||||
|
||||
if (disambig_wxfilename != "") {
|
||||
std::vector<int32> disambig_out;
|
||||
for (size_t i = 0; i < ilabels.size(); i++)
|
||||
if (ilabels[i].size() == 1 && ilabels[i][0] <= 0)
|
||||
disambig_out.push_back(static_cast<int32>(i));
|
||||
if (!WriteIntegerVectorSimple(disambig_wxfilename, disambig_out)) {
|
||||
std::cerr << "fstcomposecontext: Could not write disambiguation symbols to "
|
||||
<< PrintableWxfilename(disambig_wxfilename) << '\n';
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
WriteFstKaldi(composed_fst, fst_out_filename);
|
||||
delete fst;
|
||||
return 0;
|
||||
} catch(const std::exception &e) {
|
||||
std::cerr << e.what();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
// fstbin/fstcopy.cc
|
||||
|
||||
// Copyright 2009-2011 Microsoft Corporation
|
||||
|
||||
// See ../../COPYING for clarification regarding multiple authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
// MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
// See the Apache 2 License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#include "base/kaldi-common.h"
|
||||
#include "util/common-utils.h"
|
||||
#include "fst/fstlib.h"
|
||||
#include "fstext/table-matcher.h"
|
||||
#include "fstext/fstext-utils.h"
|
||||
#include "fstext/kaldi-fst-io.h"
|
||||
|
||||
/*
|
||||
Test:
|
||||
the command below should print out something similar to the given
|
||||
input. and if you remove ,t from the output side it should print something
|
||||
binary.
|
||||
cat <<EOF | fstcopy ark,t:- ark,t:-
|
||||
foo
|
||||
0 1 9 9
|
||||
1 0.0
|
||||
|
||||
EOF
|
||||
|
||||
*/
|
||||
int main(int argc, char *argv[]) {
|
||||
try {
|
||||
using namespace kaldi;
|
||||
using namespace fst;
|
||||
using kaldi::int32;
|
||||
|
||||
const char *usage =
|
||||
"Copy tables/archives of FSTs, indexed by a string (e.g. utterance-id)\n"
|
||||
"\n"
|
||||
"Usage: fstcopy <fst-rspecifier> <fst-wspecifier>\n";
|
||||
|
||||
ParseOptions po(usage);
|
||||
|
||||
po.Read(argc, argv);
|
||||
|
||||
if (po.NumArgs() != 2) {
|
||||
po.PrintUsage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
std::string fst_rspecifier = po.GetArg(1),
|
||||
fst_wspecifier = po.GetArg(2);
|
||||
|
||||
SequentialTableReader<VectorFstHolder> fst_reader(fst_rspecifier);
|
||||
TableWriter<VectorFstHolder> fst_writer(fst_wspecifier);
|
||||
int32 n_done = 0;
|
||||
|
||||
for (; !fst_reader.Done(); fst_reader.Next(), n_done++)
|
||||
fst_writer.Write(fst_reader.Key(), fst_reader.Value());
|
||||
|
||||
KALDI_LOG << "Copied " << n_done << " FSTs.";
|
||||
return (n_done != 0 ? 0 : 1);
|
||||
} catch(const std::exception &e) {
|
||||
std::cerr << e.what();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
// fstbin/fstdeterminizelog.cc
|
||||
|
||||
// Copyright 2009-2011 Microsoft Corporation
|
||||
|
||||
// See ../../COPYING for clarification regarding multiple authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
// MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
// See the Apache 2 License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#include "base/kaldi-common.h"
|
||||
#include "util/kaldi-io.h"
|
||||
#include "util/parse-options.h"
|
||||
#include "util/text-utils.h"
|
||||
#include "fst/fstlib.h"
|
||||
#include "fstext/fstext-utils.h"
|
||||
#include "fstext/kaldi-fst-io.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
try {
|
||||
using namespace kaldi;
|
||||
using namespace fst;
|
||||
using kaldi::int32;
|
||||
|
||||
const char *usage =
|
||||
"Determinizes in the log semiring\n"
|
||||
"\n"
|
||||
"Usage: fstdeterminizelog [in.fst [out.fst] ]\n"
|
||||
"\n"
|
||||
"See also fstdeterminizestar\n";
|
||||
|
||||
ParseOptions po(usage);
|
||||
po.Read(argc, argv);
|
||||
|
||||
if (po.NumArgs() > 2) {
|
||||
po.PrintUsage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
std::string fst_in_filename = po.GetOptArg(1),
|
||||
fst_out_filename = po.GetOptArg(2);
|
||||
|
||||
VectorFst<StdArc> *fst = ReadFstKaldi(fst_in_filename);
|
||||
|
||||
DeterminizeInLog(fst);
|
||||
|
||||
WriteFstKaldi(*fst, fst_out_filename);
|
||||
delete fst;
|
||||
return 0;
|
||||
} catch(const std::exception &e) {
|
||||
std::cerr << e.what();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
// fstbin/fstdeterminizestar.cc
|
||||
|
||||
// Copyright 2009-2011 Microsoft Corporation
|
||||
|
||||
// See ../../COPYING for clarification regarding multiple authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
// MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
// See the Apache 2 License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#include "base/kaldi-common.h"
|
||||
#include "fst/fstlib.h"
|
||||
#include "fstext/determinize-star.h"
|
||||
#include "fstext/fstext-utils.h"
|
||||
#include "fstext/kaldi-fst-io.h"
|
||||
#include "util/parse-options.h"
|
||||
|
||||
#if !defined(_MSC_VER) && !defined(__APPLE__)
|
||||
#include <signal.h> // Comment this line and the call to signal below if
|
||||
// it causes compilation problems. It is only to enable a debugging procedure
|
||||
// when determinization does not terminate. We are disabling this code if
|
||||
// compiling on Windows because signal.h is not available there, and on
|
||||
// MacOS due to a problem with <signal.h> in the initial release of Sierra.
|
||||
#endif
|
||||
|
||||
/* some test examples:
|
||||
( echo "0 0 0 0"; echo "0 0" ) | fstcompile | fstdeterminizestar | fstprint
|
||||
( echo "0 0 1 0"; echo "0 0" ) | fstcompile | fstdeterminizestar | fstprint
|
||||
( echo "0 0 1 0"; echo "0 1 1 0"; echo "0 0" ) | fstcompile | fstdeterminizestar | fstprint
|
||||
# this last one fails [correctly]:
|
||||
( echo "0 0 0 1"; echo "0 0" ) | fstcompile | fstdeterminizestar | fstprint
|
||||
|
||||
cd ~/tmpdir
|
||||
while true; do
|
||||
fstrand > 1.fst
|
||||
fstpredeterminize out.lst 1.fst | fstdeterminizestar | fstrmsymbols out.lst > 2.fst
|
||||
fstequivalent --random=true 1.fst 2.fst || echo "Test failed"
|
||||
echo -n "."
|
||||
done
|
||||
|
||||
Test of debugging [with non-determinizable input]:
|
||||
( echo " 0 0 1 0 1.0"; echo "0 1 1 0"; echo "1 1 1 0 0"; echo "0 2 2 0"; echo "2"; echo "1" ) | fstcompile | fstdeterminizestar
|
||||
kill -SIGUSR1 [the process-id of fstdeterminizestar]
|
||||
# prints out a bunch of debugging output showing the mess it got itself into.
|
||||
*/
|
||||
|
||||
|
||||
bool debug_location = false;
|
||||
void signal_handler(int) {
|
||||
debug_location = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
try {
|
||||
using namespace kaldi;
|
||||
using namespace fst;
|
||||
using kaldi::int32;
|
||||
|
||||
const char *usage =
|
||||
"Removes epsilons and determinizes in one step\n"
|
||||
"\n"
|
||||
"Usage: fstdeterminizestar [in.fst [out.fst] ]\n"
|
||||
"\n"
|
||||
"See also: fstdeterminizelog, lattice-determinize\n";
|
||||
|
||||
float delta = kDelta;
|
||||
int max_states = -1;
|
||||
bool use_log = false;
|
||||
ParseOptions po(usage);
|
||||
po.Register("use-log", &use_log, "Determinize in log semiring.");
|
||||
po.Register("delta", &delta, "Delta value used to determine equivalence of weights.");
|
||||
po.Register("max-states", &max_states, "Maximum number of states in determinized FST before it will abort.");
|
||||
po.Read(argc, argv);
|
||||
|
||||
if (po.NumArgs() > 2) {
|
||||
po.PrintUsage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
std::string fst_in_str = po.GetOptArg(1),
|
||||
fst_out_str = po.GetOptArg(2);
|
||||
|
||||
// This enables us to get traceback info from determinization that is
|
||||
// not seeming to terminate.
|
||||
#if !defined(_MSC_VER) && !defined(__APPLE__)
|
||||
signal(SIGUSR1, signal_handler);
|
||||
#endif
|
||||
// Normal case: just files.
|
||||
VectorFst<StdArc> *fst = ReadFstKaldi(fst_in_str);
|
||||
|
||||
ArcSort(fst, ILabelCompare<StdArc>()); // improves speed.
|
||||
if (use_log) {
|
||||
DeterminizeStarInLog(fst, delta, &debug_location, max_states);
|
||||
} else {
|
||||
VectorFst<StdArc> det_fst;
|
||||
DeterminizeStar(*fst, &det_fst, delta, &debug_location, max_states);
|
||||
*fst = det_fst; // will do shallow copy and then det_fst goes
|
||||
// out of scope anyway.
|
||||
}
|
||||
WriteFstKaldi(*fst, fst_out_str);
|
||||
delete fst;
|
||||
return 0;
|
||||
} catch(const std::exception &e) {
|
||||
std::cerr << e.what();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
// fstbin/fstisstochastic.cc
|
||||
|
||||
// Copyright 2009-2011 Microsoft Corporation
|
||||
|
||||
// See ../../COPYING for clarification regarding multiple authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
// MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
// See the Apache 2 License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#include "base/kaldi-common.h"
|
||||
#include "util/kaldi-io.h"
|
||||
#include "util/parse-options.h"
|
||||
#include "fst/fstlib.h"
|
||||
#include "fstext/fstext-utils.h"
|
||||
#include "fstext/kaldi-fst-io.h"
|
||||
|
||||
// e.g. of test:
|
||||
// echo " 0 0" | fstcompile | fstisstochastic
|
||||
// should return 0 and print "0 0" [meaning, min and
|
||||
// max weight are one = exp(0)]
|
||||
// echo " 0 1" | fstcompile | fstisstochastic
|
||||
// should return 1, not stochastic, and print 1 1
|
||||
// (echo "0 0 0 0 0.693147 "; echo "0 1 0 0 0.693147 "; echo "1 0" ) | fstcompile | fstisstochastic
|
||||
// should return 0, stochastic; it prints "0 -1.78e-07" for me
|
||||
// (echo "0 0 0 0 0.693147 "; echo "0 1 0 0 0.693147 "; echo "1 0" ) | fstcompile | fstisstochastic --test-in-log=false
|
||||
// should return 1, not stochastic in tropical; it prints "0 0.693147" for me
|
||||
// (echo "0 0 0 0 0 "; echo "0 1 0 0 0 "; echo "1 0" ) | fstcompile | fstisstochastic --test-in-log=false
|
||||
// should return 0, stochastic in tropical; it prints "0 0" for me
|
||||
// (echo "0 0 0 0 0.693147 "; echo "0 1 0 0 0.693147 "; echo "1 0" ) | fstcompile | fstisstochastic --test-in-log=false --delta=1
|
||||
// returns 0 even though not stochastic because we gave it an absurdly large delta.
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
try {
|
||||
using namespace kaldi;
|
||||
using namespace fst;
|
||||
using kaldi::int32;
|
||||
|
||||
const char *usage =
|
||||
"Checks whether an FST is stochastic and exits with success if so.\n"
|
||||
"Prints out maximum error (in log units).\n"
|
||||
"\n"
|
||||
"Usage: fstisstochastic [ in.fst ]\n";
|
||||
|
||||
float delta = 0.01;
|
||||
bool test_in_log = true;
|
||||
|
||||
ParseOptions po(usage);
|
||||
po.Register("delta", &delta, "Maximum error to accept.");
|
||||
po.Register("test-in-log", &test_in_log, "Test stochasticity in log semiring.");
|
||||
po.Read(argc, argv);
|
||||
|
||||
if (po.NumArgs() > 1) {
|
||||
po.PrintUsage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
std::string fst_in_filename = po.GetOptArg(1);
|
||||
|
||||
Fst<StdArc> *fst = ReadFstKaldiGeneric(fst_in_filename);
|
||||
|
||||
bool ans;
|
||||
StdArc::Weight min, max;
|
||||
if (test_in_log) ans = IsStochasticFstInLog(*fst, delta, &min, &max);
|
||||
else ans = IsStochasticFst(*fst, delta, &min, &max);
|
||||
|
||||
std::cout << min.Value() << " " << max.Value() << '\n';
|
||||
delete fst;
|
||||
if (ans) return 0; // success;
|
||||
else return 1;
|
||||
} catch(const std::exception &e) {
|
||||
std::cerr << e.what();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
// fstbin/fstmakecontextfst.cc
|
||||
|
||||
// Copyright 2009-2011 Microsoft Corporation
|
||||
|
||||
// See ../../COPYING for clarification regarding multiple authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
// MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
// See the Apache 2 License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#include "base/kaldi-common.h"
|
||||
#include "util/kaldi-io.h"
|
||||
#include "util/common-utils.h"
|
||||
#include "fst/fstlib.h"
|
||||
#include "fstext/fstext-utils.h"
|
||||
#include "fstext/context-fst.h"
|
||||
#include "fstext/kaldi-fst-io.h"
|
||||
|
||||
|
||||
/* for example of testing setup, see fstmakecontextsymbols.cc */
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
try {
|
||||
using namespace kaldi;
|
||||
using namespace fst;
|
||||
using kaldi::int32;
|
||||
|
||||
const char *usage =
|
||||
"Constructs a context FST with a specified context-width and context-position.\n"
|
||||
"Outputs the context FST, and a file in Kaldi format that describes what the\n"
|
||||
"input labels mean. Note: this is very inefficient if there are a lot of phones,\n"
|
||||
"better to use fstcomposecontext instead\n"
|
||||
"\n"
|
||||
"Usage: fstmakecontextfst <phones-symbol-table> <subsequential-symbol> <ilabels-output-file> [<out-fst>]\n"
|
||||
"E.g.: fstmakecontextfst phones.txt 42 ilabels.sym > C.fst\n";
|
||||
|
||||
bool binary = true; // binary output to ilabels_output_file.
|
||||
std::string disambig_rxfilename, disambig_wxfilename;
|
||||
int32 context_width = 3, central_position = 1;
|
||||
|
||||
ParseOptions po(usage);
|
||||
po.Register("read-disambig-syms", &disambig_rxfilename,
|
||||
"List of disambiguation symbols to read");
|
||||
po.Register("write-disambig-syms", &disambig_wxfilename,
|
||||
"List of disambiguation symbols to write");
|
||||
po.Register("context-size", &context_width, "Size of phonetic context window");
|
||||
po.Register("central-position", ¢ral_position,
|
||||
"Designated central position in context window");
|
||||
po.Register("binary", &binary,
|
||||
"Write ilabels output file in binary Kaldi format");
|
||||
|
||||
po.Read(argc, argv);
|
||||
|
||||
if (po.NumArgs() < 3 || po.NumArgs() > 4) {
|
||||
po.PrintUsage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
std::string phones_symtab_filename = po.GetArg(1);
|
||||
int32 subseq_sym;
|
||||
if (!ConvertStringToInteger(po.GetArg(2), &subseq_sym))
|
||||
KALDI_ERR << "Invalid subsequential symbol " << po.GetArg(2);
|
||||
std::string ilabels_out_filename = po.GetArg(3);
|
||||
std::string fst_out_filename = po.GetOptArg(4);
|
||||
|
||||
|
||||
std::vector<kaldi::int32> phone_syms;
|
||||
{
|
||||
fst::SymbolTable *phones_symtab = NULL;
|
||||
{ // read phone symbol table.
|
||||
std::ifstream is(phones_symtab_filename.c_str());
|
||||
phones_symtab = fst::SymbolTable::ReadText(is, phones_symtab_filename);
|
||||
if (!phones_symtab) KALDI_ERR << "Could not read phones symbol-table file "<<phones_symtab_filename;
|
||||
}
|
||||
GetSymbols(*phones_symtab,
|
||||
false, // don't include eps,
|
||||
&phone_syms);
|
||||
delete phones_symtab;
|
||||
}
|
||||
|
||||
if ( (disambig_wxfilename != "") && (disambig_rxfilename == "") )
|
||||
KALDI_ERR << "fstmakecontextfst: cannot specify --write-disambig-syms if "
|
||||
"not specifying --read-disambig-syms\n";
|
||||
|
||||
std::vector<int32> disambig_in;
|
||||
if (disambig_rxfilename != "") {
|
||||
if (!ReadIntegerVectorSimple(disambig_rxfilename, &disambig_in))
|
||||
KALDI_ERR << "fstcomposecontext: Could not read disambiguation symbols from "
|
||||
<< PrintableRxfilename(disambig_rxfilename);
|
||||
}
|
||||
|
||||
if (std::binary_search(phone_syms.begin(), phone_syms.end(), subseq_sym)
|
||||
|| std::binary_search(disambig_in.begin(), disambig_in.end(), subseq_sym))
|
||||
KALDI_ERR << "Invalid subsequential symbol " << subseq_sym
|
||||
<< ", already a phone or disambiguation symbol.";
|
||||
|
||||
// 'loop_fst' will be an acceptor FST with single (initial and final) state, with
|
||||
// a loop for each phone and disambiguation symbol.
|
||||
StdVectorFst loop_fst;
|
||||
loop_fst.AddState(); // Add state zero.
|
||||
loop_fst.SetStart(0);
|
||||
loop_fst.SetFinal(0, TropicalWeight::One());
|
||||
for (size_t i = 0; i < phone_syms.size(); i++) {
|
||||
int32 sym = phone_syms[i];
|
||||
loop_fst.AddArc(0, StdArc(sym, sym, TropicalWeight::One(), 0));
|
||||
}
|
||||
|
||||
std::vector<std::vector<int32> > ilabels;
|
||||
VectorFst<StdArc> context_fst;
|
||||
|
||||
ComposeContext(disambig_in, context_width, central_position,
|
||||
&loop_fst, &context_fst, &ilabels, true);
|
||||
|
||||
WriteFstKaldi(context_fst, fst_out_filename);
|
||||
|
||||
WriteILabelInfo(Output(ilabels_out_filename, binary).Stream(),
|
||||
binary, ilabels);
|
||||
|
||||
if (disambig_wxfilename != "") {
|
||||
std::vector<int32> disambig_out;
|
||||
for (size_t i = 0; i < ilabels.size(); i++)
|
||||
if (ilabels[i].size() == 1 && ilabels[i][0] <= 0)
|
||||
disambig_out.push_back(static_cast<int32>(i));
|
||||
if (!WriteIntegerVectorSimple(disambig_wxfilename, disambig_out))
|
||||
KALDI_ERR << "fstcomposecontext: Could not write disambiguation symbols to "
|
||||
<< PrintableWxfilename(disambig_wxfilename);
|
||||
}
|
||||
return 0;
|
||||
} catch(const std::exception &e) {
|
||||
std::cerr << e.what();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
// fstbin/fstmakecontextsyms.cc
|
||||
|
||||
// Copyright 2009-2011 Microsoft Corporation
|
||||
|
||||
// See ../../COPYING for clarification regarding multiple authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
// MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
// See the Apache 2 License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "tree/context-dep.h"
|
||||
#include "util/common-utils.h"
|
||||
#include "fst/fstlib.h"
|
||||
#include "fstext/fstext-utils.h"
|
||||
#include "fstext/context-fst.h"
|
||||
|
||||
|
||||
/*
|
||||
Test for this and makecontextfst:
|
||||
mkdir -p ~/tmpdir
|
||||
pushd ~/tmpdir
|
||||
(echo "<eps> 0"; echo "a 1"; echo "b 2"; echo "#0 3"; echo "#1 4"; echo "#$ 5" ) > phones.txt
|
||||
( echo 3; echo 4 ) > disambig.list
|
||||
fstmakecontextfst --read-disambig-syms=disambig.list <(grep -v '#' phones.txt) 5 ilabels.int > C.fst
|
||||
fstmakecontextsyms phones.txt ilabels.int > context_syms.txt
|
||||
fstprint --isymbols=context_syms.txt --osymbols=phones.txt C.fst > C.txt
|
||||
|
||||
fstrandgen C.fst | fstprint --isymbols=context_syms.txt --osymbols=phones.txt
|
||||
|
||||
Example output:
|
||||
|
||||
fstrandgen C.fst | fstprint --isymbols=context_syms.txt --osymbols=phones.txt
|
||||
0 1 #-1 b
|
||||
1 2 <eps>/b/<eps> #$
|
||||
2 3 #1 #1
|
||||
3 4 #0 #0
|
||||
4 5 #0 #0
|
||||
5 6 #0 #0
|
||||
6 7 #0 #0
|
||||
7 8 #0 #0
|
||||
8 9 #1 #1
|
||||
9
|
||||
*/
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
try {
|
||||
using namespace kaldi;
|
||||
using namespace fst;
|
||||
typedef fst::StdArc::Label Label;
|
||||
const char *usage = "Create input symbols for CLG\n"
|
||||
"Usage: fstmakecontextsyms phones-symtab ilabels_input_file [output-symtab.txt]\n"
|
||||
"E.g.: fstmakecontextsyms phones.txt ilabels.sym > context_symbols.txt\n";
|
||||
|
||||
ParseOptions po(usage);
|
||||
|
||||
std::string disambig_list_file = "",
|
||||
phone_separator = "/",
|
||||
initial_disambig = "#-1";
|
||||
|
||||
po.Register("phone-separator", &phone_separator,
|
||||
"Separator for phones in phone-in-context symbols.");
|
||||
po.Register("initial-disambig", &initial_disambig,
|
||||
"Name for special disambiguation symbol that occurs at start "
|
||||
"of context-dependent phone sequences");
|
||||
|
||||
po.Read(argc, argv);
|
||||
|
||||
if (po.NumArgs() < 2 || po.NumArgs() > 3) {
|
||||
po.PrintUsage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
std::string phones_symtab_filename = po.GetArg(1),
|
||||
ilabel_info_filename = po.GetArg(2),
|
||||
clg_symtab_filename = po.GetOptArg(3);
|
||||
|
||||
std::vector<std::vector<kaldi::int32> > ilabel_info;
|
||||
{
|
||||
bool binary;
|
||||
Input ki(ilabel_info_filename, &binary);
|
||||
ReadILabelInfo(ki.Stream(),
|
||||
binary, &ilabel_info);
|
||||
}
|
||||
|
||||
fst::SymbolTable *phones_symtab = NULL;
|
||||
{ // read phone symbol table.
|
||||
std::ifstream is(phones_symtab_filename.c_str());
|
||||
phones_symtab = fst::SymbolTable::ReadText(is, phones_symtab_filename);
|
||||
if (!phones_symtab) KALDI_ERR << "Could not read phones symbol-table file "<<phones_symtab_filename;
|
||||
}
|
||||
|
||||
fst::SymbolTable *clg_symtab =
|
||||
CreateILabelInfoSymbolTable(ilabel_info,
|
||||
*phones_symtab,
|
||||
phone_separator,
|
||||
initial_disambig);
|
||||
|
||||
if (clg_symtab_filename == "") {
|
||||
if (!clg_symtab->WriteText(std::cout))
|
||||
KALDI_ERR << "Cannot write symbol table to standard output.";
|
||||
} else {
|
||||
if (!clg_symtab->WriteText(clg_symtab_filename))
|
||||
KALDI_ERR << "Cannot open symbol table file "<<clg_symtab_filename<<" for writing.";
|
||||
}
|
||||
delete clg_symtab;
|
||||
delete phones_symtab;
|
||||
return 0;
|
||||
} catch(const std::exception &e) {
|
||||
std::cerr << e.what();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// fstbin/fstminimizeencoded.cc
|
||||
|
||||
// Copyright 2009-2011 Microsoft Corporation
|
||||
|
||||
// See ../../COPYING for clarification regarding multiple authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
// MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
// See the Apache 2 License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#include "base/kaldi-common.h"
|
||||
#include "util/kaldi-io.h"
|
||||
#include "util/parse-options.h"
|
||||
#include "util/text-utils.h"
|
||||
#include "fst/fstlib.h"
|
||||
#include "fstext/determinize-star.h"
|
||||
#include "fstext/fstext-utils.h"
|
||||
#include "fstext/kaldi-fst-io.h"
|
||||
|
||||
/* some test examples:
|
||||
( echo "0 0 0 0"; echo "0 0" ) | fstcompile | fstminimizeencoded | fstprint
|
||||
( echo "0 1 0 0"; echo " 0 2 0 0"; echo "1 0"; echo "2 0"; ) | fstcompile | fstminimizeencoded | fstprint
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
try {
|
||||
using namespace kaldi;
|
||||
using namespace fst;
|
||||
using kaldi::int32;
|
||||
|
||||
const char *usage =
|
||||
"Minimizes FST after encoding [similar to fstminimize, but no weight-pushing]\n"
|
||||
"\n"
|
||||
"Usage: fstminimizeencoded [in.fst [out.fst] ]\n";
|
||||
|
||||
float delta = kDelta;
|
||||
ParseOptions po(usage);
|
||||
po.Register("delta", &delta, "Delta likelihood used for quantization of weights");
|
||||
po.Read(argc, argv);
|
||||
|
||||
if (po.NumArgs() > 2) {
|
||||
po.PrintUsage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
std::string fst_in_filename = po.GetOptArg(1),
|
||||
fst_out_filename = po.GetOptArg(2);
|
||||
|
||||
VectorFst<StdArc> *fst = ReadFstKaldi(fst_in_filename);
|
||||
|
||||
MinimizeEncoded(fst, delta);
|
||||
|
||||
WriteFstKaldi(*fst, fst_out_filename);
|
||||
|
||||
delete fst;
|
||||
return 0;
|
||||
} catch(const std::exception &e) {
|
||||
std::cerr << e.what();
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
// fstbin/fstphicompose.cc
|
||||
|
||||
// Copyright 2009-2011 Microsoft Corporation
|
||||
|
||||
// See ../../COPYING for clarification regarding multiple authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
// MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
// See the Apache 2 License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#include "base/kaldi-common.h"
|
||||
#include "util/common-utils.h"
|
||||
#include "fst/fstlib.h"
|
||||
#include "fstext/table-matcher.h"
|
||||
#include "fstext/fstext-utils.h"
|
||||
#include "fstext/kaldi-fst-io.h"
|
||||
|
||||
/*
|
||||
The following commands represent a basic test of this program.
|
||||
|
||||
cat <<EOF | fstcompile > a.fst
|
||||
0 1 10 10
|
||||
0 1 11 11
|
||||
1
|
||||
EOF
|
||||
|
||||
cat <<EOF | fstcompile > g.fst
|
||||
0 1 10 10 2.0
|
||||
0 2 100 100 6.6
|
||||
2 1 10 10 0.0
|
||||
2 1 11 11 1.0
|
||||
1
|
||||
EOF
|
||||
fstcompose a.fst g.fst | fstprint
|
||||
# gives, as expected:
|
||||
# 0 1 10 10 2
|
||||
# 1
|
||||
fstphicompose 100 a.fst g.fst | fstprint
|
||||
# gives, again correctly:
|
||||
#0 1 10 10 2
|
||||
#0 1 11 11 7.5999999
|
||||
#1
|
||||
|
||||
Next, test that it's working as desired for final-probs,
|
||||
i.e. it takes the backoff arc when looking for a final-prob,
|
||||
only if no final-prob present at current state.
|
||||
|
||||
cat <<EOF | fstcompile > a.fst
|
||||
0 1 10 10
|
||||
0 1 11 11
|
||||
1
|
||||
EOF
|
||||
cat <<EOF | fstcompile > g.fst
|
||||
0 1 10 10 2.0
|
||||
0 3 11 11 2.0
|
||||
1 2 100 110 6.6
|
||||
3 10.0
|
||||
3 2 100 110 0.0
|
||||
2
|
||||
EOF
|
||||
fstphicompose 100 a.fst g.fst | fstprint
|
||||
# output is:
|
||||
#0 1 10 10 2
|
||||
#0 2 11 11 2
|
||||
#1 6.5999999
|
||||
#2 10
|
||||
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
try {
|
||||
using namespace kaldi;
|
||||
using namespace fst;
|
||||
using kaldi::int32;
|
||||
/*
|
||||
fstphicompose does composition, but treats the second FST
|
||||
specially (basically, like a backoff LM); whenever the
|
||||
composition algorithm fails to find a match for a label
|
||||
in the second FST, if it sees a phi transition it will
|
||||
take it instead, and look for a match at the destination.
|
||||
phi is the label on the input side of the backoff arc of
|
||||
the LM (the label on the output side doesn't matter).
|
||||
|
||||
Also modifies the second fst so that it treats final-probs
|
||||
"correctly", i.e. takes the failure transition when looking
|
||||
for a final-prob. This would not work if there were
|
||||
epsilons.
|
||||
*/
|
||||
|
||||
const char *usage =
|
||||
"Composition, where the right FST has \"failure\" (phi) transitions\n"
|
||||
"that are only taken where there was no match of a \"real\" label\n"
|
||||
"You supply the label corresponding to phi.\n"
|
||||
"\n"
|
||||
"Usage: fstphicompose phi-label (fst1-rxfilename|fst1-rspecifier) "
|
||||
"(fst2-rxfilename|fst2-rspecifier) [(out-rxfilename|out-rspecifier)]\n"
|
||||
"E.g.: fstphicompose 54 a.fst b.fst c.fst\n"
|
||||
"or: fstphicompose 11 ark:a.fsts G.fst ark:b.fsts\n";
|
||||
|
||||
ParseOptions po(usage);
|
||||
|
||||
po.Read(argc, argv);
|
||||
|
||||
if (po.NumArgs() < 3 || po.NumArgs() > 4) {
|
||||
po.PrintUsage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
std::string
|
||||
phi_str = po.GetArg(1),
|
||||
fst1_in_str = po.GetArg(2),
|
||||
fst2_in_str = po.GetArg(3),
|
||||
fst_out_str = po.GetOptArg(4);
|
||||
|
||||
bool is_table_1 =
|
||||
(ClassifyRspecifier(fst1_in_str, NULL, NULL) != kNoRspecifier),
|
||||
is_table_2 =
|
||||
(ClassifyRspecifier(fst2_in_str, NULL, NULL) != kNoRspecifier),
|
||||
is_table_out =
|
||||
(ClassifyWspecifier(fst_out_str, NULL, NULL, NULL) != kNoWspecifier);
|
||||
|
||||
int32 phi_label;
|
||||
if (!ConvertStringToInteger(phi_str, &phi_label)
|
||||
|| phi_label <= 0)
|
||||
KALDI_ERR << "Invalid first argument (phi label), expect positive integer.";
|
||||
|
||||
if (is_table_out != (is_table_1 || is_table_2))
|
||||
KALDI_ERR << "Incompatible combination of archives and files";
|
||||
|
||||
if (!is_table_1 && !is_table_2) { // Only dealing with files...
|
||||
VectorFst<StdArc> *fst1 = ReadFstKaldi(fst1_in_str);
|
||||
|
||||
VectorFst<StdArc> *fst2 = ReadFstKaldi(fst2_in_str);
|
||||
|
||||
PropagateFinal(phi_label, fst2); // makes it work correctly
|
||||
// w.r.t. final-probs.
|
||||
|
||||
VectorFst<StdArc> composed_fst;
|
||||
|
||||
PhiCompose(*fst1, *fst2, phi_label, &composed_fst);
|
||||
|
||||
delete fst1;
|
||||
delete fst2;
|
||||
|
||||
WriteFstKaldi(composed_fst, fst_out_str);
|
||||
return 0;
|
||||
} else if (is_table_1 && !is_table_2) {
|
||||
|
||||
VectorFst<StdArc> *fst2 = ReadFstKaldi(fst2_in_str);
|
||||
PropagateFinal(phi_label, fst2); // makes it work correctly
|
||||
// w.r.t. final-probs.
|
||||
SequentialTableReader<VectorFstHolder> fst1_reader(fst1_in_str);
|
||||
TableWriter<VectorFstHolder> fst_writer(fst_out_str);
|
||||
int32 n_done = 0;
|
||||
for (; !fst1_reader.Done(); fst1_reader.Next(), n_done++) {
|
||||
VectorFst<StdArc> fst1(fst1_reader.Value());
|
||||
VectorFst<StdArc> fst_out;
|
||||
PhiCompose(fst1, *fst2, phi_label, &fst_out);
|
||||
fst_writer.Write(fst1_reader.Key(), fst_out);
|
||||
}
|
||||
KALDI_LOG << "Composed " << n_done << " FSTs.";
|
||||
return (n_done != 0 ? 0 : 1);
|
||||
} else {
|
||||
KALDI_ERR << "The combination of tables/non-tables that you "
|
||||
<< "supplied is not currently supported. Either implement this, "
|
||||
<< "ask the maintainers to implement it, or call this program "
|
||||
<< "differently.";
|
||||
}
|
||||
} catch(const std::exception &e) {
|
||||
std::cerr << e.what();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
// fstbin/fstpushspecial.cc
|
||||
|
||||
// Copyright 2012 Daniel Povey
|
||||
|
||||
// See ../../COPYING for clarification regarding multiple authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
// MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
// See the Apache 2 License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#include "base/kaldi-common.h"
|
||||
#include "util/kaldi-io.h"
|
||||
#include "util/parse-options.h"
|
||||
#include "util/text-utils.h"
|
||||
#include "fst/fstlib.h"
|
||||
#include "fstext/fstext-utils.h"
|
||||
#include "fstext/push-special.h"
|
||||
#include "fstext/kaldi-fst-io.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
try {
|
||||
using namespace kaldi;
|
||||
using namespace fst;
|
||||
using kaldi::int32;
|
||||
|
||||
const char *usage =
|
||||
"Pushes weights in an FST such that all the states\n"
|
||||
"in the FST have arcs and final-probs with weights that\n"
|
||||
"sum to the same amount (viewed as being in the log semiring).\n"
|
||||
"Thus, the \"extra weight\" is distributed throughout the FST.\n"
|
||||
"Tolerance parameter --delta controls how exact this is, and the\n"
|
||||
"speed.\n"
|
||||
"\n"
|
||||
"Usage: fstpushspecial [options] [in.fst [out.fst] ]\n";
|
||||
|
||||
BaseFloat delta = kDelta;
|
||||
ParseOptions po(usage);
|
||||
po.Register("delta", &delta, "Delta cost: after pushing, all states will "
|
||||
"have a total weight that differs from the average by no more "
|
||||
"than this.");
|
||||
po.Read(argc, argv);
|
||||
|
||||
if (po.NumArgs() > 2) {
|
||||
po.PrintUsage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
std::string fst_in_filename = po.GetOptArg(1),
|
||||
fst_out_filename = po.GetOptArg(2);
|
||||
|
||||
VectorFst<StdArc> *fst = ReadFstKaldi(fst_in_filename);
|
||||
|
||||
PushSpecial(fst, delta);
|
||||
|
||||
WriteFstKaldi(*fst, fst_out_filename);
|
||||
delete fst;
|
||||
return 0;
|
||||
} catch(const std::exception &e) {
|
||||
std::cerr << e.what();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
// fstbin/fstrand.cc
|
||||
|
||||
// Copyright 2009-2011 Microsoft Corporation
|
||||
|
||||
// See ../../COPYING for clarification regarding multiple authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
// MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
// See the Apache 2 License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#include "base/kaldi-common.h"
|
||||
#include "util/kaldi-io.h"
|
||||
#include "util/parse-options.h"
|
||||
#include "util/text-utils.h"
|
||||
#include "fstext/rand-fst.h"
|
||||
#include "time.h"
|
||||
#include "fstext/fstext-utils.h"
|
||||
#include "fstext/kaldi-fst-io.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
try {
|
||||
using namespace fst;
|
||||
using kaldi::int32;
|
||||
|
||||
const char *usage =
|
||||
"Generate random FST\n"
|
||||
"\n"
|
||||
"Usage: fstrand [out.fst]\n";
|
||||
|
||||
srand(time(NULL));
|
||||
RandFstOptions opts;
|
||||
|
||||
|
||||
kaldi::ParseOptions po(usage);
|
||||
po.Register("allow-empty", &opts.allow_empty,
|
||||
"If true, we may generate an empty FST.");
|
||||
|
||||
po.Read(argc, argv);
|
||||
|
||||
if (po.NumArgs() > 1) {
|
||||
po.PrintUsage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
std::string fst_out_filename = po.GetOptArg(1);
|
||||
|
||||
VectorFst <StdArc> *rand_fst = RandFst<StdArc>(opts);
|
||||
|
||||
WriteFstKaldi(*rand_fst, fst_out_filename);
|
||||
delete rand_fst;
|
||||
return 0;
|
||||
} catch(const std::exception &e) {
|
||||
std::cerr << e.what();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
// fstbin/fstrmepslocal.cc
|
||||
|
||||
// Copyright 2009-2011 Microsoft Corporation
|
||||
|
||||
// See ../../COPYING for clarification regarding multiple authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
// MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
// See the Apache 2 License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#include "base/kaldi-common.h"
|
||||
#include "util/kaldi-io.h"
|
||||
#include "util/parse-options.h"
|
||||
#include "util/text-utils.h"
|
||||
#include "fst/fstlib.h"
|
||||
#include "fstext/determinize-star.h"
|
||||
#include "fstext/fstext-utils.h"
|
||||
#include "fstext/kaldi-fst-io.h"
|
||||
|
||||
|
||||
/*
|
||||
A test example:
|
||||
( echo "0 1 1 0"; echo "1 2 0 2"; echo "2 0"; ) | fstcompile | fstrmepslocal | fstprint
|
||||
# prints:
|
||||
# 0 1 1 2
|
||||
# 1
|
||||
( echo "0 1 0 0"; echo "0 0"; echo "1 0" ) | fstcompile | fstrmepslocal | fstprint
|
||||
# 0
|
||||
( echo "0 1 0 0"; echo "0 0"; echo "1 0" ) | fstcompile | fstrmepslocal | fstprint
|
||||
( echo "0 1 0 0"; echo "0 0"; echo "1 0" ) | fstcompile | fstrmepslocal --use-log=true | fstprint
|
||||
# 0 -0.693147182
|
||||
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
try {
|
||||
using namespace kaldi;
|
||||
using namespace fst;
|
||||
using kaldi::int32;
|
||||
|
||||
const char *usage =
|
||||
"Removes some (but not all) epsilons in an algorithm that will always reduce the number of\n"
|
||||
"arcs+states. Option to preserves equivalence in tropical or log semiring, and\n"
|
||||
"if in tropical, stochasticit in either log or tropical.\n"
|
||||
"\n"
|
||||
"Usage: fstrmepslocal [in.fst [out.fst] ]\n";
|
||||
|
||||
ParseOptions po(usage);
|
||||
bool use_log = false;
|
||||
bool stochastic_in_log = true;
|
||||
po.Register("use-log", &use_log,
|
||||
"Preserve equivalence in log semiring [false->tropical]\n");
|
||||
po.Register("stochastic-in-log", &stochastic_in_log,
|
||||
"Preserve stochasticity in log semiring [false->tropical]\n");
|
||||
po.Read(argc, argv);
|
||||
|
||||
if (po.NumArgs() > 2) {
|
||||
po.PrintUsage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
std::string fst_in_filename = po.GetOptArg(1),
|
||||
fst_out_filename = po.GetOptArg(2);
|
||||
|
||||
VectorFst<StdArc> *fst = ReadFstKaldi(fst_in_filename);
|
||||
|
||||
if (!use_log && stochastic_in_log) {
|
||||
RemoveEpsLocalSpecial(fst);
|
||||
} else if (use_log && !stochastic_in_log) {
|
||||
std::cerr << "fstrmsymbols: invalid combination of flags\n";
|
||||
return 1;
|
||||
} else if (use_log) {
|
||||
VectorFst<LogArc> log_fst;
|
||||
Cast(*fst, &log_fst);
|
||||
delete fst;
|
||||
RemoveEpsLocal(&log_fst);
|
||||
fst = new VectorFst<StdArc>;
|
||||
Cast(log_fst, fst);
|
||||
} else {
|
||||
RemoveEpsLocal(fst);
|
||||
}
|
||||
|
||||
WriteFstKaldi(*fst, fst_out_filename);
|
||||
delete fst;
|
||||
return 0;
|
||||
} catch(const std::exception &e) {
|
||||
std::cerr << e.what();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
// fstbin/fstrmsymbols.cc
|
||||
|
||||
// Copyright 2009-2011 Microsoft Corporation
|
||||
|
||||
// See ../../COPYING for clarification regarding multiple authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
// MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
// See the Apache 2 License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#include "base/kaldi-common.h"
|
||||
#include "util/common-utils.h"
|
||||
#include "fst/fstlib.h"
|
||||
#include "fstext/determinize-star.h"
|
||||
#include "fstext/fstext-utils.h"
|
||||
#include "fstext/kaldi-fst-io.h"
|
||||
|
||||
namespace fst {
|
||||
// we can move these functions elsewhere later, if they are needed in other
|
||||
// places.
|
||||
|
||||
template<class Arc, class I>
|
||||
void RemoveArcsWithSomeInputSymbols(const std::vector<I> &symbols_in,
|
||||
VectorFst<Arc> *fst) {
|
||||
typedef typename Arc::StateId StateId;
|
||||
|
||||
kaldi::ConstIntegerSet<I> symbol_set(symbols_in);
|
||||
|
||||
StateId num_states = fst->NumStates();
|
||||
StateId dead_state = fst->AddState();
|
||||
for (StateId s = 0; s < num_states; s++) {
|
||||
for (MutableArcIterator<VectorFst<Arc> > iter(fst, s);
|
||||
!iter.Done(); iter.Next()) {
|
||||
if (symbol_set.count(iter.Value().ilabel) != 0) {
|
||||
Arc arc = iter.Value();
|
||||
arc.nextstate = dead_state;
|
||||
iter.SetValue(arc);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Connect() will actually remove the arcs, and the dead state.
|
||||
Connect(fst);
|
||||
if (fst->NumStates() == 0)
|
||||
KALDI_WARN << "After Connect(), fst was empty.";
|
||||
}
|
||||
|
||||
template<class Arc, class I>
|
||||
void PenalizeArcsWithSomeInputSymbols(const std::vector<I> &symbols_in,
|
||||
float penalty,
|
||||
VectorFst<Arc> *fst) {
|
||||
typedef typename Arc::StateId StateId;
|
||||
typedef typename Arc::Label Label;
|
||||
typedef typename Arc::Weight Weight;
|
||||
|
||||
Weight penalty_weight(penalty);
|
||||
|
||||
kaldi::ConstIntegerSet<I> symbol_set(symbols_in);
|
||||
|
||||
StateId num_states = fst->NumStates();
|
||||
for (StateId s = 0; s < num_states; s++) {
|
||||
for (MutableArcIterator<VectorFst<Arc> > iter(fst, s);
|
||||
!iter.Done(); iter.Next()) {
|
||||
if (symbol_set.count(iter.Value().ilabel) != 0) {
|
||||
Arc arc = iter.Value();
|
||||
arc.weight = Times(arc.weight, penalty_weight);
|
||||
iter.SetValue(arc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
try {
|
||||
using namespace kaldi;
|
||||
using namespace fst;
|
||||
using kaldi::int32;
|
||||
|
||||
bool apply_to_output = false;
|
||||
bool remove_arcs = false;
|
||||
float penalty = -std::numeric_limits<BaseFloat>::infinity();
|
||||
|
||||
const char *usage =
|
||||
"With no options, replaces a subset of symbols with epsilon, wherever\n"
|
||||
"they appear on the input side of an FST."
|
||||
"With --remove-arcs=true, will remove arcs that contain these symbols\n"
|
||||
"on the input\n"
|
||||
"With --penalty=<float>, will add the specified penalty to the\n"
|
||||
"cost of any arc that has one of the given symbols on its input side\n"
|
||||
"In all cases, the option --apply-to-output=true (or for\n"
|
||||
"back-compatibility, --remove-from-output=true) makes this apply\n"
|
||||
"to the output side.\n"
|
||||
"\n"
|
||||
"Usage: fstrmsymbols [options] <in-disambig-list> [<in.fst> [<out.fst>]]\n"
|
||||
"E.g: fstrmsymbols in.list < in.fst > out.fst\n"
|
||||
"<in-disambig-list> is an rxfilename specifying a file containing list of integers\n"
|
||||
"representing symbols, in text form, one per line.\n";
|
||||
|
||||
ParseOptions po(usage);
|
||||
po.Register("remove-from-output", &apply_to_output, "If true, this applies to symbols "
|
||||
"on the output, not the input, side. (For back compatibility; use "
|
||||
"--apply-to-output insead)");
|
||||
po.Register("apply-to-output", &apply_to_output, "If true, this applies to symbols "
|
||||
"on the output, not the input, side.");
|
||||
po.Register("remove-arcs", &remove_arcs, "If true, instead of converting the symbol "
|
||||
"to <eps>, remove the arcs.");
|
||||
po.Register("penalty", &penalty, "If specified, instead of converting "
|
||||
"the symbol to <eps>, penalize the arc it is on by adding this "
|
||||
"value to its cost.");
|
||||
|
||||
|
||||
po.Read(argc, argv);
|
||||
|
||||
if (remove_arcs &&
|
||||
penalty != -std::numeric_limits<BaseFloat>::infinity())
|
||||
KALDI_ERR << "--remove-arc and --penalty options are mutually exclusive";
|
||||
|
||||
if (po.NumArgs() < 1 || po.NumArgs() > 3) {
|
||||
po.PrintUsage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
std::string disambig_rxfilename = po.GetArg(1),
|
||||
fst_rxfilename = po.GetOptArg(2),
|
||||
fst_wxfilename = po.GetOptArg(3);
|
||||
|
||||
VectorFst<StdArc> *fst = CastOrConvertToVectorFst(
|
||||
ReadFstKaldiGeneric(fst_rxfilename));
|
||||
|
||||
std::vector<int32> disambig_in;
|
||||
if (!ReadIntegerVectorSimple(disambig_rxfilename, &disambig_in))
|
||||
KALDI_ERR << "fstrmsymbols: Could not read disambiguation symbols from "
|
||||
<< (disambig_rxfilename == "" ? "standard input" : disambig_rxfilename);
|
||||
|
||||
if (apply_to_output) Invert(fst);
|
||||
if (remove_arcs) {
|
||||
RemoveArcsWithSomeInputSymbols(disambig_in, fst);
|
||||
} else if (penalty != -std::numeric_limits<BaseFloat>::infinity()) {
|
||||
PenalizeArcsWithSomeInputSymbols(disambig_in, penalty, fst);
|
||||
} else {
|
||||
RemoveSomeInputSymbols(disambig_in, fst);
|
||||
}
|
||||
if (apply_to_output) Invert(fst);
|
||||
|
||||
WriteFstKaldi(*fst, fst_wxfilename);
|
||||
|
||||
delete fst;
|
||||
return 0;
|
||||
} catch(const std::exception &e) {
|
||||
std::cerr << e.what();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* some test examples:
|
||||
|
||||
( echo "0 0 1 1"; echo " 0 0 3 2"; echo "0 0"; ) | fstcompile | fstrmsymbols "echo 3; echo 4|" | fstprint
|
||||
# should produce:
|
||||
# 0 0 1 1
|
||||
# 0 0 0 2
|
||||
# 0
|
||||
|
||||
( echo "0 0 1 1"; echo " 0 0 3 2"; echo "0 0"; ) | fstcompile | fstrmsymbols --apply-to-output=true "echo 2; echo 3|" | fstprint
|
||||
# should produce:
|
||||
# 0 0 1 1
|
||||
# 0 0 3 0
|
||||
# 0
|
||||
|
||||
|
||||
( echo "0 0 1 1"; echo " 0 0 3 2"; echo "0 0"; ) | fstcompile | fstrmsymbols --remove-arcs=true "echo 3; echo 4|" | fstprint
|
||||
# should produce:
|
||||
# 0 0 1 1
|
||||
# 0
|
||||
|
||||
( echo "0 0 1 1"; echo " 0 0 3 2"; echo "0 0"; ) | fstcompile | fstrmsymbols --penalty=2 "echo 3; echo 4; echo 5|" | fstprint
|
||||
# should produce:
|
||||
# 0 0 1 1
|
||||
# 0 0 3 2 2
|
||||
# 0
|
||||
|
||||
*/
|
||||
@@ -0,0 +1,112 @@
|
||||
// fstbin/fsts-concat.cc
|
||||
|
||||
// Copyright 2016 Johns Hopkins University (Authors: Jan "Yenda" Trmal)
|
||||
// 2018 Soapbox Labs (Author: Karel Vesely)
|
||||
|
||||
// See ../../COPYING for clarification regarding multiple authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
// MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
// See the Apache 2 License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#include "base/kaldi-common.h"
|
||||
#include "util/common-utils.h"
|
||||
#include "fstext/fstext-utils.h"
|
||||
#include "fstext/kaldi-fst-io.h"
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
try {
|
||||
using namespace kaldi;
|
||||
using namespace fst;
|
||||
typedef kaldi::int32 int32;
|
||||
typedef kaldi::uint64 uint64;
|
||||
|
||||
const char *usage =
|
||||
"Reads kaldi archives with FSTs. Concatenates the fsts from all the rspecifiers.\n"
|
||||
"The fsts to concatenate must have same key. The sequencing is given by the position of arguments.\n"
|
||||
"\n"
|
||||
"Usage: fsts-concat [options] <fsts-rspecifier1> <fsts-rspecifier2> ... <fsts-wspecifier>\n"
|
||||
" e.g.: fsts-concat scp:fsts1.scp scp:fsts2.scp ... ark:fsts_out.ark\n"
|
||||
"\n"
|
||||
"see also: fstconcat (from the OpenFst toolkit)\n";
|
||||
|
||||
ParseOptions po(usage);
|
||||
|
||||
po.Read(argc, argv);
|
||||
|
||||
if (po.NumArgs() < 3) {
|
||||
po.PrintUsage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
std::string fsts_rspecifier = po.GetArg(1),
|
||||
fsts_wspecifier = po.GetArg(po.NumArgs());
|
||||
|
||||
SequentialTableReader<VectorFstHolder> fst_reader(fsts_rspecifier);
|
||||
std::vector<RandomAccessTableReader<VectorFstHolder>*> fst_readers;
|
||||
TableWriter<VectorFstHolder> fst_writer(fsts_wspecifier);
|
||||
|
||||
for (int32 i = 2; i < po.NumArgs(); i++)
|
||||
fst_readers.push_back(new RandomAccessTableReader<VectorFstHolder>(po.GetArg(i)));
|
||||
const int32 num_fst_readers = fst_readers.size();
|
||||
|
||||
int32 n_done = 0,
|
||||
n_skipped = 0;
|
||||
|
||||
for (; !fst_reader.Done(); fst_reader.Next()) {
|
||||
std::string key = fst_reader.Key();
|
||||
|
||||
// Check that the key exists in all 'fst_readers'.
|
||||
bool skip_key = false;
|
||||
for (int32 i = 0; i < num_fst_readers; i++) {
|
||||
if (!fst_readers[i]->HasKey(key)) {
|
||||
KALDI_WARN << "Skipping '" << key << "'"
|
||||
<< " due to missing the fst in " << (i+2) << "th <rspecifier> : "
|
||||
<< "'" << po.GetArg(i+2) << "'";
|
||||
skip_key = true;
|
||||
}
|
||||
}
|
||||
if (skip_key) {
|
||||
n_skipped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Concatenate!
|
||||
VectorFst<StdArc> fst_out = fst_readers.back()->Value(key);
|
||||
// Loop from (last-1) to first, as 'prepending' the fsts is faster,
|
||||
// see: http://www.openfst.org/twiki/bin/view/FST/ConcatDoc
|
||||
for (int32 i = num_fst_readers-2; i >= 0; i--) {
|
||||
fst::Concat(fst_readers[i]->Value(key), &fst_out);
|
||||
}
|
||||
// Finally, prepend the fst from the 'Sequential' reader.
|
||||
fst::Concat(fst_reader.Value(), &fst_out);
|
||||
|
||||
// Write the output.
|
||||
fst_writer.Write(key, fst_out);
|
||||
n_done++;
|
||||
}
|
||||
|
||||
// Cleanup.
|
||||
for (int32 i = 0; i < num_fst_readers; i++)
|
||||
delete fst_readers[i];
|
||||
fst_readers.clear();
|
||||
|
||||
KALDI_LOG << "Produced " << n_done << " FSTs by concatenating " << po.NumArgs()-1
|
||||
<< " streams " << "(" << n_skipped << " keys skipped).";
|
||||
return (n_done != 0 ? 0 : 1);
|
||||
} catch(const std::exception &e) {
|
||||
std::cerr << e.what();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
// fstbin/fsts-project.cc
|
||||
|
||||
// Copyright 2016 Johns Hopkins University (Authors: Jan "Yenda" Trmal)
|
||||
|
||||
// See ../../COPYING for clarification regarding multiple authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
// MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
// See the Apache 2 License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#include "base/kaldi-common.h"
|
||||
#include "util/common-utils.h"
|
||||
#include "fstext/fstext-utils.h"
|
||||
#include "fstext/kaldi-fst-io.h"
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
try {
|
||||
using namespace kaldi;
|
||||
using namespace fst;
|
||||
typedef kaldi::int32 int32;
|
||||
typedef kaldi::uint64 uint64;
|
||||
|
||||
const char *usage =
|
||||
"Reads kaldi archive of FSTs; for each element, performs the project\n"
|
||||
"operation either on input (default) or on the output (if the option\n"
|
||||
"--project-output is true).\n"
|
||||
"\n"
|
||||
"Usage: fsts-project [options] <fsts-rspecifier> <fsts-wspecifier>\n"
|
||||
" e.g.: fsts-project ark:train.fsts ark,t:train.fsts\n"
|
||||
"\n"
|
||||
"see also: fstproject (from the OpenFst toolkit)\n";
|
||||
|
||||
ParseOptions po(usage);
|
||||
|
||||
bool project_output = false;
|
||||
|
||||
po.Register("project-output", &project_output,
|
||||
"If true, project output vs input");
|
||||
|
||||
po.Read(argc, argv);
|
||||
|
||||
if (po.NumArgs() != 2) {
|
||||
po.PrintUsage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
std::string fsts_rspecifier = po.GetArg(1),
|
||||
fsts_wspecifier = po.GetArg(2);
|
||||
|
||||
|
||||
SequentialTableReader<VectorFstHolder> fst_reader(fsts_rspecifier);
|
||||
TableWriter<VectorFstHolder> fst_writer(fsts_wspecifier);
|
||||
|
||||
int32 n_done = 0;
|
||||
for (; !fst_reader.Done(); fst_reader.Next()) {
|
||||
std::string key = fst_reader.Key();
|
||||
VectorFst<StdArc> fst(fst_reader.Value());
|
||||
|
||||
Project(&fst, project_output ? PROJECT_OUTPUT : PROJECT_INPUT);
|
||||
|
||||
fst_writer.Write(key, fst);
|
||||
n_done++;
|
||||
}
|
||||
|
||||
KALDI_LOG << "Projected " << n_done << " FSTs";
|
||||
return (n_done != 0 ? 0 : 1);
|
||||
} catch(const std::exception &e) {
|
||||
std::cerr << e.what();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
// fstbin/fsts-to-transcripts.cc
|
||||
|
||||
// Copyright 2012-2013 Johns Hopkins University (Authors: Guoguo Chen,
|
||||
// Daniel Povey)
|
||||
|
||||
// See ../../COPYING for clarification regarding multiple authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
// MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
// See the Apache 2 License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#include "base/kaldi-common.h"
|
||||
#include "util/common-utils.h"
|
||||
#include "fstext/fstext-utils.h"
|
||||
#include "fstext/kaldi-fst-io.h"
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
try {
|
||||
using namespace kaldi;
|
||||
using namespace fst;
|
||||
typedef kaldi::int32 int32;
|
||||
typedef kaldi::uint64 uint64;
|
||||
|
||||
const char *usage =
|
||||
"Reads a table of FSTs; for each element, finds the best path and \n"
|
||||
"prints out the output-symbol sequence (if --output-side=true), or \n"
|
||||
"input-symbol sequence otherwise.\n"
|
||||
"\n"
|
||||
"Usage:\n"
|
||||
" fsts-to-transcripts [options] <fsts-rspecifier>"
|
||||
" <transcriptions-wspecifier>\n"
|
||||
"e.g.:\n"
|
||||
" fsts-to-transcripts ark:train.fsts ark,t:train.text\n";
|
||||
|
||||
ParseOptions po(usage);
|
||||
|
||||
bool output_side = true;
|
||||
|
||||
po.Register("output-side", &output_side, "If true, extract the symbols on "
|
||||
"the output side of the FSTs, else the input side.");
|
||||
|
||||
po.Read(argc, argv);
|
||||
|
||||
if (po.NumArgs() != 2) {
|
||||
po.PrintUsage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
std::string fst_rspecifier = po.GetArg(1),
|
||||
transcript_wspecifier = po.GetArg(2);
|
||||
|
||||
|
||||
SequentialTableReader<VectorFstHolder> fst_reader(fst_rspecifier);
|
||||
Int32VectorWriter transcript_writer(transcript_wspecifier);
|
||||
|
||||
int32 n_done = 0, n_err = 0;
|
||||
for (; !fst_reader.Done(); fst_reader.Next()) {
|
||||
std::string key = fst_reader.Key();
|
||||
const VectorFst<StdArc> &fst = fst_reader.Value();
|
||||
|
||||
|
||||
VectorFst<StdArc> shortest_path;
|
||||
ShortestPath(fst, &shortest_path); // the OpenFst algorithm ShortestPath.
|
||||
|
||||
if (shortest_path.NumStates() == 0) {
|
||||
KALDI_WARN << "Input FST (after shortest path) was empty. Producing "
|
||||
<< "no output for key " << key;
|
||||
n_err++;
|
||||
continue;
|
||||
}
|
||||
|
||||
std::vector<int32> transcript;
|
||||
bool ans;
|
||||
if (output_side) ans = fst::GetLinearSymbolSequence<StdArc, int32>(
|
||||
shortest_path, NULL, &transcript, NULL);
|
||||
else
|
||||
ans = fst::GetLinearSymbolSequence<StdArc, int32>(
|
||||
shortest_path, &transcript, NULL, NULL);
|
||||
if (!ans) {
|
||||
KALDI_ERR << "GetLinearSymbolSequence returned false (code error);";
|
||||
}
|
||||
transcript_writer.Write(key, transcript);
|
||||
n_done++;
|
||||
}
|
||||
|
||||
KALDI_LOG << "Converted " << n_done << " FSTs, " << n_err << " with errors";
|
||||
return (n_done != 0 ? 0 : 1);
|
||||
} catch(const std::exception &e) {
|
||||
std::cerr << e.what();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
// fstbin/fsts-union.cc
|
||||
|
||||
// Copyright 2016 Johns Hopkins University (Authors: Jan "Yenda" Trmal)
|
||||
|
||||
// See ../../COPYING for clarification regarding multiple authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
// MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
// See the Apache 2 License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#include "base/kaldi-common.h"
|
||||
#include "util/common-utils.h"
|
||||
#include "fstext/fstext-utils.h"
|
||||
#include "fstext/kaldi-fst-io.h"
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
try {
|
||||
using namespace kaldi;
|
||||
using namespace fst;
|
||||
typedef kaldi::int32 int32;
|
||||
typedef kaldi::uint64 uint64;
|
||||
|
||||
const char *usage =
|
||||
"Reads a kaldi archive of FSTs. Performs the FST operation union on\n"
|
||||
"all fsts sharing the same key. Assumes the archive is sorted by key.\n"
|
||||
"\n"
|
||||
"Usage: fsts-union [options] <fsts-rspecifier> <fsts-wspecifier>\n"
|
||||
" e.g.: fsts-union ark:keywords_tmp.fsts ark,t:keywords.fsts\n"
|
||||
"\n"
|
||||
"see also: fstunion (from the OpenFst toolkit)\n";
|
||||
|
||||
ParseOptions po(usage);
|
||||
|
||||
po.Read(argc, argv);
|
||||
|
||||
if (po.NumArgs() != 2) {
|
||||
po.PrintUsage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
std::string fsts_rspecifier = po.GetArg(1),
|
||||
fsts_wspecifier = po.GetArg(2);
|
||||
|
||||
|
||||
SequentialTableReader<VectorFstHolder> fst_reader(fsts_rspecifier);
|
||||
TableWriter<VectorFstHolder> fst_writer(fsts_wspecifier);
|
||||
|
||||
int32 n_out_done = 0,
|
||||
n_in_done = 0;
|
||||
std::string res_key = "";
|
||||
VectorFst<StdArc> res_fst;
|
||||
|
||||
for (; !fst_reader.Done(); fst_reader.Next()) {
|
||||
std::string key = fst_reader.Key();
|
||||
VectorFst<StdArc> fst(fst_reader.Value());
|
||||
|
||||
n_in_done++;
|
||||
if (key == res_key) {
|
||||
fst::Union(&res_fst, fst);
|
||||
} else {
|
||||
if (res_key != "") {
|
||||
VectorFst<StdArc> out_fst;
|
||||
fst::Determinize(res_fst, &out_fst);
|
||||
fst::Minimize(&out_fst);
|
||||
fst::RmEpsilon(&out_fst);
|
||||
fst_writer.Write(res_key, out_fst);
|
||||
n_out_done++;
|
||||
}
|
||||
res_fst = fst;
|
||||
res_key = key;
|
||||
}
|
||||
}
|
||||
if (res_key != "") {
|
||||
VectorFst<StdArc> out_fst;
|
||||
fst::Determinize(res_fst, &out_fst);
|
||||
fst::Minimize(&out_fst);
|
||||
fst::RmEpsilon(&out_fst);
|
||||
fst_writer.Write(res_key, out_fst);
|
||||
n_out_done++;
|
||||
}
|
||||
|
||||
KALDI_LOG << "Applied fst union on " << n_in_done
|
||||
<< " FSTs, produced " << n_out_done << " FSTs";
|
||||
return (n_out_done != 0 ? 0 : 1);
|
||||
} catch(const std::exception &e) {
|
||||
std::cerr << e.what();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
// fstbin/fsttablecompose.cc
|
||||
|
||||
// Copyright 2009-2011 Microsoft Corporation
|
||||
// 2013 Johns Hopkins University (author: Daniel Povey)
|
||||
|
||||
// See ../../COPYING for clarification regarding multiple authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
// MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
// See the Apache 2 License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#include "base/kaldi-common.h"
|
||||
//#include "util/common-utils.h"
|
||||
#include "fst/fstlib.h"
|
||||
#include "fstext/table-matcher.h"
|
||||
#include "fstext/fstext-utils.h"
|
||||
#include "fstext/kaldi-fst-io.h"
|
||||
#include "util/parse-options.h"
|
||||
|
||||
/*
|
||||
cd ~/tmpdir
|
||||
while true; do
|
||||
fstrand | fstarcsort --sort_type=olabel > 1.fst; fstrand | fstarcsort > 2.fst
|
||||
fstcompose 1.fst 2.fst > 3a.fst
|
||||
fsttablecompose 1.fst 2.fst > 3b.fst
|
||||
fstequivalent --random=true 3a.fst 3b.fst || echo "Test failed"
|
||||
echo -n "."
|
||||
done
|
||||
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
try {
|
||||
using namespace kaldi;
|
||||
using namespace fst;
|
||||
using kaldi::int32;
|
||||
/*
|
||||
fsttablecompose should always give equivalent results to compose,
|
||||
but it is more efficient for certain kinds of inputs.
|
||||
In particular, it is useful when, say, the left FST has states
|
||||
that typically either have epsilon olabels, or
|
||||
one transition out for each of the possible symbols (as the
|
||||
olabel). The same with the input symbols of the right-hand FST
|
||||
is possible.
|
||||
*/
|
||||
|
||||
const char *usage =
|
||||
"Composition algorithm [between two FSTs of standard type, in tropical\n"
|
||||
"semiring] that is more efficient for certain cases-- in particular,\n"
|
||||
"where one of the FSTs (the left one, if --match-side=left) has large\n"
|
||||
"out-degree\n"
|
||||
"\n"
|
||||
"Usage: fsttablecompose (fst1-rxfilename|fst1-rspecifier) "
|
||||
"(fst2-rxfilename|fst2-rspecifier) [(out-rxfilename|out-rspecifier)]\n";
|
||||
|
||||
ParseOptions po(usage);
|
||||
|
||||
TableComposeOptions opts;
|
||||
std::string match_side = "left";
|
||||
std::string compose_filter = "sequence";
|
||||
|
||||
po.Register("connect", &opts.connect, "If true, trim FST before output.");
|
||||
po.Register("match-side", &match_side, "Side of composition to do table "
|
||||
"match, one of: \"left\" or \"right\".");
|
||||
po.Register("compose-filter", &compose_filter, "Composition filter to use, "
|
||||
"one of: \"alt_sequence\", \"auto\", \"match\", \"sequence\"");
|
||||
|
||||
po.Read(argc, argv);
|
||||
|
||||
if (match_side == "left") {
|
||||
opts.table_match_type = MATCH_OUTPUT;
|
||||
} else if (match_side == "right") {
|
||||
opts.table_match_type = MATCH_INPUT;
|
||||
} else {
|
||||
KALDI_ERR << "Invalid match-side option: " << match_side;
|
||||
}
|
||||
|
||||
if (compose_filter == "alt_sequence") {
|
||||
opts.filter_type = ALT_SEQUENCE_FILTER;
|
||||
} else if (compose_filter == "auto") {
|
||||
opts.filter_type = AUTO_FILTER;
|
||||
} else if (compose_filter == "match") {
|
||||
opts.filter_type = MATCH_FILTER;
|
||||
} else if (compose_filter == "sequence") {
|
||||
opts.filter_type = SEQUENCE_FILTER;
|
||||
} else {
|
||||
KALDI_ERR << "Invalid compose-filter option: " << compose_filter;
|
||||
}
|
||||
|
||||
if (po.NumArgs() < 2 || po.NumArgs() > 3) {
|
||||
po.PrintUsage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
std::string fst1_in_str = po.GetArg(1),
|
||||
fst2_in_str = po.GetArg(2),
|
||||
fst_out_str = po.GetOptArg(3);
|
||||
|
||||
|
||||
//// Note: the "table" in is_table_1 and similar variables has nothing
|
||||
//// to do with the "table" in "fsttablecompose"; is_table_1 relates to
|
||||
//// whether we are dealing with a single FST or a whole set of FSTs.
|
||||
//bool is_table_1 =
|
||||
// (ClassifyRspecifier(fst1_in_str, NULL, NULL) != kNoRspecifier),
|
||||
// is_table_2 =
|
||||
// (ClassifyRspecifier(fst2_in_str, NULL, NULL) != kNoRspecifier),
|
||||
// is_table_out =
|
||||
// (ClassifyWspecifier(fst_out_str, NULL, NULL, NULL) != kNoWspecifier);
|
||||
//if (is_table_out != (is_table_1 || is_table_2))
|
||||
// KALDI_ERR << "Incompatible combination of archives and files";
|
||||
//
|
||||
//if (!is_table_1 && !is_table_2) { // Only dealing with files...
|
||||
VectorFst<StdArc> *fst1 = ReadFstKaldi(fst1_in_str);
|
||||
|
||||
VectorFst<StdArc> *fst2 = ReadFstKaldi(fst2_in_str);
|
||||
|
||||
// Checks if <fst1> is olabel sorted and <fst2> is ilabel sorted.
|
||||
if (fst1->Properties(fst::kOLabelSorted, true) == 0) {
|
||||
KALDI_WARN << "The first FST is not olabel sorted.";
|
||||
}
|
||||
if (fst2->Properties(fst::kILabelSorted, true) == 0) {
|
||||
KALDI_WARN << "The second FST is not ilabel sorted.";
|
||||
}
|
||||
|
||||
VectorFst<StdArc> composed_fst;
|
||||
|
||||
TableCompose(*fst1, *fst2, &composed_fst, opts);
|
||||
|
||||
delete fst1;
|
||||
delete fst2;
|
||||
|
||||
WriteFstKaldi(composed_fst, fst_out_str);
|
||||
return 0;
|
||||
//} else if (!is_table_1 && is_table_2
|
||||
// && opts.table_match_type == MATCH_OUTPUT) {
|
||||
// // second arg is an archive, and match-side=left (default).
|
||||
// TableComposeCache<Fst<StdArc> > cache(opts);
|
||||
// VectorFst<StdArc> *fst1 = ReadFstKaldi(fst1_in_str);
|
||||
// SequentialTableReader<VectorFstHolder> fst2_reader(fst2_in_str);
|
||||
// TableWriter<VectorFstHolder> fst_writer(fst_out_str);
|
||||
// int32 n_done = 0;
|
||||
|
||||
// // Checks if <fst1> is olabel sorted.
|
||||
// if (fst1->Properties(fst::kOLabelSorted, true) == 0) {
|
||||
// KALDI_WARN << "The first FST is not olabel sorted.";
|
||||
// }
|
||||
// for (; !fst2_reader.Done(); fst2_reader.Next(), n_done++) {
|
||||
// VectorFst<StdArc> fst2(fst2_reader.Value());
|
||||
// VectorFst<StdArc> fst_out;
|
||||
// TableCompose(*fst1, fst2, &fst_out, &cache);
|
||||
// fst_writer.Write(fst2_reader.Key(), fst_out);
|
||||
// }
|
||||
// KALDI_LOG << "Composed " << n_done << " FSTs.";
|
||||
// return (n_done != 0 ? 0 : 1);
|
||||
//} else if (is_table_1 && is_table_2) {
|
||||
// SequentialTableReader<VectorFstHolder> fst1_reader(fst1_in_str);
|
||||
// RandomAccessTableReader<VectorFstHolder> fst2_reader(fst2_in_str);
|
||||
// TableWriter<VectorFstHolder> fst_writer(fst_out_str);
|
||||
// int32 n_done = 0, n_err = 0;
|
||||
// for (; !fst1_reader.Done(); fst1_reader.Next()) {
|
||||
// std::string key = fst1_reader.Key();
|
||||
// if (!fst2_reader.HasKey(key)) {
|
||||
// KALDI_WARN << "No such key " << key << " in second table.";
|
||||
// n_err++;
|
||||
// } else {
|
||||
// const VectorFst<StdArc> &fst1(fst1_reader.Value()),
|
||||
// &fst2(fst2_reader.Value(key));
|
||||
// VectorFst<StdArc> result;
|
||||
// TableCompose(fst1, fst2, &result, opts);
|
||||
// if (result.NumStates() == 0) {
|
||||
// KALDI_WARN << "Empty output for key " << key;
|
||||
// n_err++;
|
||||
// } else {
|
||||
// fst_writer.Write(key, result);
|
||||
// n_done++;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// KALDI_LOG << "Successfully composed " << n_done << " FSTs, errors or "
|
||||
// << "empty output on " << n_err;
|
||||
//} else {
|
||||
// KALDI_ERR << "The combination of tables/non-tables and match-type that you "
|
||||
// << "supplied is not currently supported. Either implement this, "
|
||||
// << "ask the maintainers to implement it, or call this program "
|
||||
// << "differently.";
|
||||
//}
|
||||
} catch(const std::exception &e) {
|
||||
std::cerr << e.what();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
// fstbin/make-grammar-fst.cc
|
||||
|
||||
// Copyright 2018 Johns Hopkins University (author: Daniel Povey)
|
||||
|
||||
// See ../../COPYING for clarification regarding multiple authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
// MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
// See the Apache 2 License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#include "base/kaldi-common.h"
|
||||
#include "util/common-utils.h"
|
||||
#include "fst/fstlib.h"
|
||||
#include "fstext/table-matcher.h"
|
||||
#include "fstext/kaldi-fst-io.h"
|
||||
#include "decoder/grammar-fst.h"
|
||||
|
||||
template<typename FST>
|
||||
void MakeGrammarFst(kaldi::ParseOptions po,
|
||||
int32 nonterm_phones_offset,
|
||||
bool write_as_grammar){
|
||||
using namespace kaldi;
|
||||
using namespace fst;
|
||||
using kaldi::int32;
|
||||
|
||||
std::string fst_out_str = po.GetArg(po.NumArgs());
|
||||
std::string top_fst_str = po.GetArg(1);
|
||||
|
||||
ConstFst<StdArc> *top_tmp_fst = ConstFst<StdArc>::Read(top_fst_str);
|
||||
std::shared_ptr<FST> top_fst(new FST(*top_tmp_fst));
|
||||
|
||||
std::vector<std::pair<int32, std::shared_ptr<FST> > > pairs;
|
||||
|
||||
int32 num_pairs = (po.NumArgs() - 2) / 2;
|
||||
for (int32 i = 1; i <= num_pairs; i++) {
|
||||
int32 nonterminal;
|
||||
std::string nonterm_str = po.GetArg(2*i);
|
||||
if (!ConvertStringToInteger(nonterm_str, &nonterminal) ||
|
||||
nonterminal <= 0)
|
||||
KALDI_ERR << "Expected positive integer as nonterminal, got: "
|
||||
<< nonterm_str;
|
||||
std::string fst_str = po.GetArg(2*i + 1);
|
||||
|
||||
ConstFst<StdArc> *tmp_fst = ConstFst<StdArc>::Read(fst_str);
|
||||
std::shared_ptr<FST> this_fst(new FST(*tmp_fst));
|
||||
|
||||
pairs.push_back(std::pair<int32, std::shared_ptr<FST> >(
|
||||
nonterminal, this_fst));
|
||||
};
|
||||
|
||||
GrammarFstTpl<FST> *grammar_fst = new GrammarFstTpl<FST>(nonterm_phones_offset,
|
||||
top_fst,
|
||||
pairs);
|
||||
|
||||
if (write_as_grammar) {
|
||||
bool binary = true; // GrammarFst does not support non-binary write.
|
||||
WriteKaldiObject(*grammar_fst, fst_out_str, binary);
|
||||
} else {
|
||||
VectorFst<StdArc> vfst;
|
||||
CopyToVectorFst<FST>(grammar_fst, &vfst);
|
||||
ConstFst<StdArc> cfst(vfst);
|
||||
// We don't have a wrapper in kaldi-fst-io.h for writing type
|
||||
// ConstFst<StdArc>, so do it manually.
|
||||
bool binary = true, write_binary_header = false; // suppress the ^@B
|
||||
Output ko(fst_out_str, binary, write_binary_header);
|
||||
FstWriteOptions wopts(kaldi::PrintableWxfilename(fst_out_str));
|
||||
cfst.Write(ko.Stream(), wopts);
|
||||
}
|
||||
|
||||
KALDI_LOG << "Created grammar FST and wrote it to "
|
||||
<< fst_out_str;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
try {
|
||||
using namespace kaldi;
|
||||
using namespace fst;
|
||||
using kaldi::int32;
|
||||
|
||||
const char *usage =
|
||||
"Construct GrammarFst and write it to disk (or convert it to ConstFst\n"
|
||||
"and write that to disk instead). Mostly intended for demonstration\n"
|
||||
"and testing purposes (since it may be more convenient to construct\n"
|
||||
"GrammarFst from code). See kaldi-asr.org/doc/grammar.html\n"
|
||||
"Can also be used to prepares FSTs for this use, by calling\n"
|
||||
"PrepareForGrammarFst(), which does things like adding final-probs and\n"
|
||||
"making small structural tweaks to the FST\n"
|
||||
"\n"
|
||||
"Usage (1): make-grammar-fst [options] <top-level-fst> <symbol1> <fst1> \\\n"
|
||||
" [<symbol2> <fst2> ...]] <fst-out>\n"
|
||||
"\n"
|
||||
"<symbol1>, <symbol2> are the integer ids of the corresponding\n"
|
||||
" user-defined nonterminal symbols (e.g. #nonterm:contact_list) in the\n"
|
||||
" phones.txt file.\n"
|
||||
"e.g.: make-grammar-fst --nonterm-phones-offset=317 HCLG.fst \\\n"
|
||||
" 320 HCLG1.fst HCLG_grammar.fst\n"
|
||||
"\n"
|
||||
"Usage (2): make-grammar-fst <fst-in> <fst-out>\n"
|
||||
" Prepare individual FST for compilation into GrammarFst.\n"
|
||||
" E.g. make-grammar-fst HCLG.fst HCLGmod.fst. The outputs of this\n"
|
||||
" will then become the arguments <top-level-fst>, <fst1>, ... for usage\n"
|
||||
" pattern (1).\n"
|
||||
"\n"
|
||||
"The --nonterm-phones-offset option is required for both usage patterns.\n";
|
||||
|
||||
|
||||
ParseOptions po(usage);
|
||||
|
||||
|
||||
int32 nonterm_phones_offset = -1;
|
||||
bool write_as_grammar = true;
|
||||
bool make_mutable = false;
|
||||
|
||||
po.Register("nonterm-phones-offset", &nonterm_phones_offset,
|
||||
"Integer id of #nonterm_bos in phones.txt");
|
||||
po.Register("write-as-grammar", &write_as_grammar, "If true, "
|
||||
"write as GrammarFst object; if false, convert to "
|
||||
"ConstFst<StdArc> (readable by standard decoders) "
|
||||
"and write that.");
|
||||
po.Register("make-mutable", &make_mutable, "If true, "
|
||||
"Make a GrammarFst using StdVectorFst as the "
|
||||
"underlying FST instance type."
|
||||
"Use const ConstFst<StdArc> otherwise.");
|
||||
|
||||
po.Read(argc, argv);
|
||||
|
||||
if (po.NumArgs() < 2 || po.NumArgs() % 2 != 0) {
|
||||
po.PrintUsage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (nonterm_phones_offset < 0)
|
||||
KALDI_ERR << "The --nonterm-phones-offset option must be supplied "
|
||||
"and positive.";
|
||||
|
||||
if (po.NumArgs() == 2) {
|
||||
// this usage pattern calls PrepareForGrammarFst().
|
||||
VectorFst<StdArc> *fst = ReadFstKaldi(po.GetArg(1));
|
||||
PrepareForGrammarFst(nonterm_phones_offset, fst);
|
||||
// This will write it as VectorFst; to avoid it having to be converted to
|
||||
// ConstFst when read again by make-grammar-fst, you may want to pipe
|
||||
// through fstconvert --fst_type=const.
|
||||
WriteFstKaldi(*fst, po.GetArg(2));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (make_mutable) {
|
||||
MakeGrammarFst<StdVectorFst>(po, nonterm_phones_offset, write_as_grammar);
|
||||
} else {
|
||||
MakeGrammarFst<const ConstFst<StdArc> >(po, nonterm_phones_offset, write_as_grammar);
|
||||
}
|
||||
} catch(const std::exception &e) {
|
||||
std::cerr << e.what();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user