14a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*---------------------------------------------------------------------------*
24a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  grxmlcompile.cpp  *
34a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                           *
44a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  Copyright 2007, 2008 Nuance Communciations, Inc.                               *
54a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                           *
64a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  Licensed under the Apache License, Version 2.0 (the 'License');          *
74a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  you may not use this file except in compliance with the License.         *
84a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                           *
94a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  You may obtain a copy of the License at                                  *
104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0                           *
114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                           *
124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  Unless required by applicable law or agreed to in writing, software      *
134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  distributed under the License is distributed on an 'AS IS' BASIS,        *
144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  See the License for the specific language governing permissions and      *
164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  limitations under the License.                                           *
174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                           *
184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *---------------------------------------------------------------------------*/
194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "ptypes.h"
214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include <ext/hash_map>
234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "fst/lib/fst.h"
254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "fst/lib/fstlib.h"
264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "fst/lib/arc.h"
274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "fst/lib/fst-decl.h"
284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "fst/lib/vector-fst.h"
294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "fst/lib/arcsort.h"
304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "fst/lib/invert.h"
314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "fst-io.h"
334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "ESR_Locale.h"
354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "LCHAR.h"
364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "pstdio.h"
374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "PFileSystem.h"
384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "PANSIFileSystem.h"
394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "plog.h"
404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "pmemory.h"
414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "ESR_Session.h"
424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "SR_Session.h"
434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "SR_Vocabulary.h"
444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "srec_arb.h"       // for EPSILON_LABEL etc
454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include <fstream>
464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include <iostream>
474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "tinyxml.h"
484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "grxmldoc.h"
494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#ifdef MEMTRACE
514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include <mcheck.h>
524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define OPENFST_ACKNOWLEDGEMENT	\
554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	"This tool uses the OpenFst library. \n" \
564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project "Licensed under the Apache License, Version 2.0 (the \"License\");\n" \
574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project" you may not use this file except in compliance with the License.\n" \
584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project" You may obtain a copy of the License at" \
594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project"\n" \
604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project"      http://www.apache.org/licenses/LICENSE-2.0\n" \
614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project"\n" \
624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project" Unless required by applicable law or agreed to in writing, software\n" \
634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project" distributed under the License is distributed on an \"AS IS\" BASIS,\n" \
644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" \
654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project" See the License for the specific language governing permissions and\n" \
664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project" limitations under the License.\n" \
674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project"\n" \
684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project" This library was developed at Google Research (M. Riley, J. Schalkwyk, W. Skut) and NYU's Courant Institute (C. Allauzen, M. Mohri). It is intended to be comprehensive, flexible, efficient and scale well to large problems. It is an open source project distributed under the Apache license. \n"
694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define TINYXML_ACKNOWLEDGEMENT	\
724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	"This tool uses the tinyxml library. \n" \
734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project"Copyright (c) 2007 Project Admins: leethomason \n" \
744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project"The TinyXML software is provided 'as-is', without any express or implied\n" \
754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project"warranty. In no event will the authors be held liable for any damages\n" \
764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project"arising from the use of this software.\n" \
774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project"\n" \
784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project"Permission is granted to anyone to use this software for any purpose,\n" \
794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project"including commercial applications, and to alter it and redistribute it\n" \
804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project"freely, subject to the following restrictions:\n"
814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define NUANCE_COPYRIGHT \
834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project"// grxmlcompile\n" \
844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project"//\n" \
854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" \
864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project"// you may not use this file except in compliance with the License.\n" \
874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project"// You may obtain a copy of the License at\n" \
884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project"//\n" \
894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project"//      http://www.apache.org/licenses/LICENSE-2.0\n" \
904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project"//\n" \
914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project"// Unless required by applicable law or agreed to in writing, software\n" \
924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" \
934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" \
944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project"// See the License for the specific language governing permissions and\n" \
954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project"// limitations under the License.\n" \
964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project"//\n" \
974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project"// This program compiles a .grxml grammar into the graphs needed for \n" \
984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project"// decoding with SREC\n" \
994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project"// \n"
1004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define MAX_LINE_LENGTH   256
1024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define MAX_PATH_NAME 512
1034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define MAX_PRONS_LENGTH 1024
1044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define SILENCE_PREFIX_WORD "-pau-"
1054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define SILENCE_SUFFIX_WORD "-pau2-"
1064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define SLOT_SUFFIX "__"
1074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define SLOT_PREFIX "__"
1084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define MAX_NUM_SLOTS 12 /* must agree with srec_context.h */
1094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define EXTRA_EPSILON_LABEL 39999 // must be higher than the number of models
1104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define DEFAULT_WB_COST 40
1114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define DEFAULT_WB_COST_STR "40"
1124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define SLOT_COUNTER_OFFSET 30000 // must be higher than the number of models
1134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define NOISE_PHONEME_CODE 'J'
1144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic int debug = 0;
1164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic int verbose = 0;
1174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectusing namespace std;
1194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectESR_ReturnCode make_openfst_graphs(GRXMLDoc* pDoc, /* for metas */
1214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project				   const std::string& grxmlBasename,
1224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project				   const char* vocabFilename,
1234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project				   const char* cfstFilename,
1244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project				   const char* modelmapFilename);
1254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectconst char* showline(const char* fn, int line_num)
1274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
1284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  static char line[8096] = { 0 };
1294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int line_count = 0;
1304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ifstream strm(fn);
1314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  while (strm && strm.getline(line, sizeof(line)))
1324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  if(line_count++ == line_num) break;
1334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return &line[0];
1344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
1354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstd::string ExtractFileName(const std::string& full)
1374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
1384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  std::string::size_type idx = full.find_last_of("/");
1394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (idx != std::string::npos)
1414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return full.substr(idx+1);
1424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else
1434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return full;
1444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
1454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*-----------------------------------------------------------------------*
1474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                       *
1484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                       *
1494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *-----------------------------------------------------------------------*/
1504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectint usage_error(const char* prgname)
1524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
1534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  printf("USAGE: -par <par file> -grxml <grxml grammar file> -vocab <dictionary file (.ok)> [-outdir <output directory>]\n");
1544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return (int)ESR_INVALID_ARGUMENT;
1554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
1564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectint main(int argc, char* argv[])
1584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
1594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ESR_ReturnCode status = ESR_SUCCESS;
1604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  char *parfile = NULL;
1614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  char *grxmlfile = NULL;
1624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  char *cmdline_vocfile = NULL;
1634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  std::string outdir("."); // default output dir is current directory
1644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* for now, assume char and LCHAR are the same, else fail to compile! */
1654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  { char zzz[ 1 - (sizeof(LCHAR)!=sizeof(char))]; zzz[0] = 0; }
1664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#ifdef MEMTRACE
1684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    mtrace();
1694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
1704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if defined(GRXMLCOMPILE_PRINT_ACKNOWLEDGEMENT)
1724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    cout << OPENFST_ACKNOWLEDGEMENT <<std::endl;
1734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    cout << TINYXML_ACKNOWLEDGEMENT <<std::endl;
1744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    cout << NUANCE_COPYRIGHT <<std::endl;
1754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
1764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    // Process all XML files given on command line
1784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if(argc<5){
1804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      return usage_error(argv[0]);
1814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
1824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for(int i=1;i<argc;i++)
1844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
1854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if(!strcmp(argv[i],"-grxml"))
1864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        grxmlfile = argv[++i];
1874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      else if(!strcmp(argv[i],"-debug"))
1884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        debug++;
1894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      else if(!strcmp(argv[i],"-verbose"))
1904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        verbose++;
1914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      else if(!strcmp(argv[i],"-par") || !strcmp(argv[i],"-parfile"))
1924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        parfile = argv[++i];
1934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      else if(!strcmp(argv[i],"-vocab"))
1944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        cmdline_vocfile = argv[++i];
1954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      else if(!strcmp(argv[i],"-outdir"))
1964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        outdir = std::string(argv[++i]);
1974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      else {
1984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        printf("error_usage: argument [%s]\n", argv[i]);
1994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	return usage_error(argv[0]);
2004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	return (int)ESR_INVALID_ARGUMENT;
2014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
2024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
2034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    //process_xml( std::string(grxmlfile), parfile );
2054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    std::string filename = std::string(grxmlfile);
2064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /***************************
2084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            process xml
2094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ***************************/
2104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    cout << "processing [" << filename << "] ..." << endl;
2124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    TiXmlDocument node;
2144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    bool bLoadedOK = node.LoadFile( filename.c_str() );
2154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if(!bLoadedOK || node.Error()) {
2164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      std::cout << "Error: while creating TiXmlDocument from " << filename << std::endl;
2174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      std::cout << "Error: " << node.Error() << " id " << node.ErrorId() << " row " << node.ErrorRow() << " col " << node.ErrorCol() << std::endl;
2184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      std::cout << "Error: " << node.ErrorDesc() <<  std::endl;
2194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      std::cout << "Error: near " << showline( filename.c_str(), node.ErrorRow()) << std::endl;
2204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      return (int)ESR_INVALID_ARGUMENT;
2214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
2224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    // *************************************************
2254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    //	Parse the file into a DOM object and create word graph
2264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    //
2274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    GRXMLDoc *doc = new (GRXMLDoc);
2284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    std::string filenameNoPath = ExtractFileName(filename);
2294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    doc->parseGrammar( node, filenameNoPath );   // THE PARSING AND NETWORK BUILD HAPPENS IN HERE
2304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /************************
2314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      end of xml processing
2324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ************************/
2334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    // Create grammar network files. Use prefix of input file for output.
2354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    std::string s = filename;
2364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    std::string grxmlbase = outdir + "/" + ExtractFileName(grxmlfile);
2374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    unsigned int p1 = grxmlbase.find_last_of(".");
2384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if ( p1 != string::npos )
2394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      grxmlbase.assign( grxmlbase, 0, p1);
2404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    std::string newName;
2424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    newName = grxmlbase + ".map";
2434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    doc->writeMapFile( newName );
2444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    newName = grxmlbase + ".script";
2454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    doc->writeScriptFile( newName );
2464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    doc->writeGraphFiles( grxmlbase, false );
2484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    //
2504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    // SR initialization
2514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    //
2524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    char vocfile[MAX_PATH_NAME];
2534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    char cfstfile[MAX_PATH_NAME];
2544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    char modelmapfile[MAX_PATH_NAME];
2554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    size_t len;
2564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    PMemInit();
2584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    printf("info: Using parfile %s\n",parfile);
2594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    status = SR_SessionCreate((const LCHAR*) parfile);
2604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    // status = SR_SessionCreate ( parfile );
2614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (  status != ESR_SUCCESS ) {
2624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      LPRINTF("Error: SR_SessionCreate(%s) %s\n", parfile, ESR_rc2str(status));
2634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      return (int)status;
2644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
2654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    // vocfile
2674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if(cmdline_vocfile) {
2684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      strcpy( vocfile, cmdline_vocfile);
2694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    } else {
2704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      len = MAX_PATH_NAME;
2714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      ESR_SessionGetLCHAR ( L("cmdline.vocabulary"), (LCHAR*)vocfile, &len );
2724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      // skip PrefixWithBaseDirectory(), 'tis done inside SR_VocabularyLoad()
2734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
2744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    printf("info: Using dictionary %s\n",vocfile);
2754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    // modelmapfile
2774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    len = MAX_PATH_NAME;
2784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ESR_SessionGetLCHAR ( L("cmdline.arbfile"), (LCHAR*)modelmapfile, &len);
2794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    len = MAX_PATH_NAME;
2804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    status = ESR_SessionPrefixWithBaseDirectory ( (LCHAR*)modelmapfile, &len);
2814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    char* p = strrchr(modelmapfile,'/');
2824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if(!p) p = strrchr(modelmapfile,'\\');
2834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if(p) strcpy(p, "/models128x.map");
2844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    // cfstfile
2864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    len = MAX_PATH_NAME;
2874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ESR_SessionGetLCHAR ( L("cmdline.arbfile"), (LCHAR*)cfstfile, &len);
2884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    len = MAX_PATH_NAME;
2894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    status = ESR_SessionPrefixWithBaseDirectory ( (LCHAR*)cfstfile, &len);
2904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    p = strrchr(cfstfile,'/');
2914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if(!p) p = strrchr(cfstfile,'\\');
2924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if(p) strcpy(p, "/generic.C");
2934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    status = make_openfst_graphs( doc, grxmlbase, (const char*)vocfile, (const char*)cfstfile, (const char*)modelmapfile);
2954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if(status != ESR_SUCCESS) {
2964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      LPRINTF("Error: make_openfst_graphs() returned %s\n",  ESR_rc2str(status));
2974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    } else {
2984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      /* make_openfst_graphs() can sometimes call doc->setMeta() to put
2994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	 Session parameters into the .params file, so writeParamsFile()
3004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	 should be called after make_openfst_graphs() */
3014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      newName = grxmlbase + ".params";
3024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      doc->writeParamsFile( newName );
3034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
3044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    //
3064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    // SR de-initialization
3074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    //
3084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    SR_SessionDestroy();
3094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    PMemShutdown();
3104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    delete doc;
3124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return (int)status;
3134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
3144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*-----------------------------------------------------------------*
3164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * utils                                                           *
3174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *-----------------------------------------------------------------*/
3184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectbool is_slot_symbol( const char* sym)
3204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
3214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  const char* p = strstr(sym,SLOT_PREFIX);
3224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int len = strlen(sym);
3234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if(len>4 && !strcmp(sym+len-2,SLOT_SUFFIX) && (p-sym)<len-2) {
3244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return true;
3254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  } else
3264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return false;
3274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
3284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectint64 StrToId(const char *s, fst::SymbolTable *syms,
3304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	      const char *name)
3314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
3324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int64 n;
3334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (syms) {
3344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    n = syms->Find(s);
3354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (n < 0) {
3364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      cerr << "FstReader: Symbol \"" << s
3374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	   << "\" is not mapped to any integer " << name
3384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	   << ", symbol table = " << syms->Name();
3394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
3404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  } else {
3414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    char *p;
3424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    n = strtoll(s, &p, 10);
3434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (p < s + strlen(s) || n < 0) {
3444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      cerr << "FstReader: Bad " << name << " integer = \"" << s;
3454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
3464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
3474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return n;
3484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
3494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/* FstMergeOLabelsToILabels, FstSplitOLabelsFromILabels
3514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   are used to make sure the minimization does not go overboard in pushing
3524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   output labels toward the beginning of the graph.  When that happens
3534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   then the speech recognition decoder fails! */
3544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectESR_ReturnCode FstMergeOLabelsToILabels( fst::StdVectorFst& fst_, int max_ilabels )
3564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
3574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::StdArc::StateId s = fst_.Start();
3584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (s == fst::kNoStateId)
3594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ESR_INVALID_ARGUMENT;
3604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (fst::StateIterator< fst::StdVectorFst> siter(fst_);
3614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       !siter.Done(); siter.Next()) {
3624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    s = siter.Value();
3634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for(fst::MutableArcIterator<fst::StdVectorFst> aiter(&fst_, s);
3654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	!aiter.Done(); aiter.Next()) {
3664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      fst::StdArc arc = aiter.Value();
3674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if( arc.ilabel >= max_ilabels ||
3684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  (float)arc.ilabel + ((float)max_ilabels)*arc.olabel > INT_MAX) {
3694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	std::cout << "Error: internal error in FstMergeOLabelsToILabels() " << std::endl;
3704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	return ESR_NOT_IMPLEMENTED;
3714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
3724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      arc.ilabel = arc.ilabel + max_ilabels * arc.olabel;
3734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      arc.olabel = 0;
3744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      aiter.SetValue( arc);
3754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
3764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
3774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return ESR_SUCCESS;
3784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
3794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectESR_ReturnCode FstMergeOLabelsToILabels_GetMax( fst::StdVectorFst& fst_, int& max_ilabel )
3814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
3824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (fst_.Start() == fst::kNoStateId) return ESR_INVALID_ARGUMENT;
3834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (fst::StateIterator< fst::StdVectorFst> siter(fst_);
3844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       !siter.Done(); siter.Next()) {
3854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for(fst::MutableArcIterator<fst::StdVectorFst> aiter(&fst_, siter.Value());
3864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	!aiter.Done(); aiter.Next()) {
3874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if( aiter.Value().ilabel > max_ilabel)
3884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	max_ilabel = aiter.Value().ilabel;
3894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
3904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
3914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  max_ilabel++;
3924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return ESR_SUCCESS;
3934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
3944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectESR_ReturnCode FstSplitOLabelsFromILabels( fst::StdVectorFst& fst_, int max_ilabels )
3964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
3974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::StdArc::StateId s = fst_.Start();
3984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (s == fst::kNoStateId)
3994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ESR_INVALID_ARGUMENT;
4004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (fst::StateIterator< fst::StdVectorFst> siter(fst_);
4014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       !siter.Done(); siter.Next()) {
4024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    s = siter.Value();
4034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for(fst::MutableArcIterator<fst::StdVectorFst> aiter(&fst_, s);
4054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	!aiter.Done(); aiter.Next()) {
4064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      fst::StdArc arc = aiter.Value();
4074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      arc.olabel = arc.ilabel / max_ilabels;
4084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      arc.ilabel = arc.ilabel - arc.olabel*max_ilabels;
4094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      aiter.SetValue( arc);
4104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
4114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
4124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return ESR_SUCCESS;
4134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
4144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/* this is to replace the "fake" extra epsilon input labels, which were
4164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   put there to disambiguate homonyms */
4174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectESR_ReturnCode FstReplaceILabel( fst::StdVectorFst& fst_, int from_ilabel, int into_ilabel)
4194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
4204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::StdArc::StateId s = fst_.Start();
4214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (s == fst::kNoStateId)
4224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ESR_INVALID_ARGUMENT;
4234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (fst::StateIterator< fst::StdVectorFst> siter(fst_);
4244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       !siter.Done(); siter.Next()) {
4254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    s = siter.Value();
4264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for(fst::MutableArcIterator<fst::StdVectorFst> aiter(&fst_, s);
4284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	!aiter.Done(); aiter.Next()) {
4294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      fst::StdArc arc = aiter.Value();
4304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if(arc.ilabel == from_ilabel) {
4314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	arc.ilabel = into_ilabel;
4324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	aiter.SetValue( arc);
4334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
4344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
4354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
4364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return ESR_SUCCESS;
4374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
4384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/* this pushes the slot labels forward which gives an opportunity for
4404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   multiple instances of the slot to be merged, eg. lookup NAME
4414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   vs lookup contact NAME .. if in separate rules, then they will
4424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   merge thanks to using 3 arcs for the NAME */
4434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectESR_ReturnCode FstPushSlotLikeOLabels( fst::StdVectorFst& fst_, int myMin, int myMax)
4454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
4464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int i;
4474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ESR_ReturnCode rc = ESR_SUCCESS;
4484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  char done_for_state[2*65536]; // hope this is enough!
4494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  memset( &done_for_state[0], 0, sizeof(done_for_state));
4504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::StdArc::StateId s = fst_.Start();
4524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (fst::StateIterator< fst::StdVectorFst> siter(fst_);
4534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       !siter.Done(); siter.Next()) {
4544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    s = siter.Value();
4554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if(done_for_state[ s]) continue;
4574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    done_for_state[ s]++;
4584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for(fst::MutableArcIterator<fst::StdVectorFst> aiter(&fst_, s);
4604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	!aiter.Done(); aiter.Next()) {
4614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      fst::StdArc arc = aiter.Value();
4624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if(arc.olabel >= myMin && arc.olabel < myMax) {
4634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	fst::StdArc::StateId s2 = arc.nextstate;
4644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	int slotId = arc.olabel;
4654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	if(verbose)
4674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  std::cout << "info: FstPushSlotLikeOLabels() at state " << s << " arc ilabel " << arc.ilabel << " olabel " << arc.olabel << std::endl;
4684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	arc.ilabel = EPSILON_LABEL;
4704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	arc.olabel = EPSILON_LABEL;
4714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	arc.weight = 0; // zero weight
4724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	aiter.SetValue( arc);
4734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	done_for_state[ s2]++;
4744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	for(fst::MutableArcIterator<fst::StdVectorFst> aiter2(&fst_, s2);
4754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	    !aiter2.Done(); aiter2.Next()) {
4764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  fst::StdArc arc2 = aiter2.Value();
4774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  if(arc2.ilabel == WORD_BOUNDARY) {
4784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	    std::cout << "Error: FstPushSlotLikeOLabels() failing, there could be confusion between the slot (hack-pron) and a real-pron, the slot olabel may have been pushed by earlier fst operations!" << std::endl;
4794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	    rc = ESR_INVALID_STATE;
4804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  } else
4814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	    arc2.ilabel = EPSILON_LABEL;
4824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  arc2.olabel = slotId;
4834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  aiter2.SetValue( arc2);
4844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	}
4854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
4864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
4874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
4884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* check */
4904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int *num_pclg_arcs_using_slot = new int[myMax];
4914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for(i=0;i<myMax;i++) num_pclg_arcs_using_slot[i] = 0;
4924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (fst::StateIterator< fst::StdVectorFst> siter(fst_);
4934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       !siter.Done(); siter.Next()) {
4944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    s = siter.Value();
4954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for(fst::MutableArcIterator<fst::StdVectorFst> aiter(&fst_, s);
4974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	!aiter.Done(); aiter.Next()) {
4984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      fst::StdArc arc = aiter.Value();
4994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if(arc.olabel >= myMin && arc.olabel < myMax)
5004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	num_pclg_arcs_using_slot[arc.olabel]++;
5014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
5024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
5034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for(i=0; i<myMax; i++) {
5044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if(num_pclg_arcs_using_slot[i] > 1) {
5054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      std::cout << "Error: SREC will not support multiply referred slots." << std::endl;
5064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      std::cout << "Error: Consider re-working your grammar to merge the references into one rule" << std::endl;
5074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      std::cout << "Error: or use two different slots" << std::endl;
5084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      rc = ESR_NOT_SUPPORTED;
5094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
5104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
5114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  delete [] num_pclg_arcs_using_slot;
5124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return rc;
5144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
5154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/* gets the range of slot numbers, myMin inclusive, myMax is exclusive */
5174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectvoid get_slot_olabel_range( const fst::SymbolTable* syms, int* myMin, int* myMax)
5194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
5204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // assumes slots are at the top of the symbol table
5214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::SymbolTableIterator iter( *syms);
5224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  *myMin = *myMax = 0;
5234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for(iter.Reset(); !iter.Done(); iter.Next() ) {
5244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    const char* sym = iter.Symbol();
5254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if ( is_slot_symbol( sym)) {
5264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if(! (*myMin)) *myMin = iter.Value();
5274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      *myMax = iter.Value()+1;
5284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
5294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
5304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
5314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/* SLOT_COUNTER_OFFSET
5334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   The cfst is used to turn phonemes into acoustic models, but we're using
5344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   special phonemes for the slots, and must here add those as pass through
5354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   in the Cfst, meaning that the slot marker must be unchanged after
5364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   composition.  To do that we find the places in the Cfst where silence is
5374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   used, and put the slot marker arcs in parallel.  This also causes the
5384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   models before the slot to assume silence to the right, and the models after
5394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   the slot to assume silence to the left, both of which are reasonable */
5404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectESR_ReturnCode FstAddSlotMarkersToCFst( fst::StdVectorFst& cfst_, int myMin, int myMax)
5424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
5434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int num_silence_arcs_in_cfst = 0;
5444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int mimicPhonemeCode = SILENCE_CODE;
5454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::StdArc::StateId s = cfst_.Start();
5474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (s == fst::kNoStateId)
5484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ESR_INVALID_ARGUMENT;
5494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (fst::StateIterator< fst::StdVectorFst> siter(cfst_);
5504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       !siter.Done(); siter.Next()) {
5514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    s = siter.Value();
5524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for(fst::MutableArcIterator<fst::StdVectorFst> aiter(&cfst_, s);
5544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	!aiter.Done(); aiter.Next()) {
5554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      fst::StdArc arc = aiter.Value();
5564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if( arc.olabel == mimicPhonemeCode) {
5574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	num_silence_arcs_in_cfst++;
5584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	for(int i=myMin; i<myMax; i++)
5594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  cfst_.AddArc( s, fst::StdArc(SLOT_COUNTER_OFFSET+i /*model*/,
5604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project				       SLOT_COUNTER_OFFSET+i /*phoneme*/, 0.0, arc.nextstate));
5614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
5624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
5634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
5644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::ArcSort(&cfst_, fst::StdOLabelCompare());
5654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if(!num_silence_arcs_in_cfst)
5664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ESR_INVALID_ARGUMENT;
5674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else
5684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ESR_SUCCESS;
5694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
5704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*
5724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * make the graphs used by the recognition engine during the search.
5734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project */
5744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectESR_ReturnCode make_openfst_graphs(  GRXMLDoc* pDoc,
5764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project				     const std::string& grxmlBasename,
5774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project				     const char* vocabFilename,
5784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project				     const char* cfstFilename,
5794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project				     const char* modelmapFilename)
5804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
5814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  SR_Vocabulary *vocab = 0;
5824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ESR_ReturnCode rc;
5834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::StdVectorFst l_fst;      // .L file, created from the .map and .ok
5854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int stateSt, stateEn;
5874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  size_t len;
5884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  bool do_skip_interword_silence = false;
5894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  hash_map<string,int> homonym_count;
5904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int word_penalty = 0;
5914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  rc = SR_VocabularyLoad(vocabFilename, &vocab);
5934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (rc != ESR_SUCCESS) {
5944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    cerr << "Error: " <<  ESR_rc2str(rc) << endl;
5954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ESR_INVALID_ARGUMENT; // goto CLEANUP;
5964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
5974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  std::string word_penalty_str;
5994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if( pDoc->findMeta(std::string("word_penalty"),word_penalty_str))
6004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    word_penalty = atoi((const char *)word_penalty_str.c_str());
6014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else {
6024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    rc = ESR_SessionGetInt( L("CREC.Recognizer.wordpen"), &word_penalty);
6034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if(rc != ESR_SUCCESS)
6044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      word_penalty = DEFAULT_WB_COST;
6054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    word_penalty_str = DEFAULT_WB_COST_STR;
6064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    pDoc->setMeta( std::string("word_penalty"), word_penalty_str) ;
6074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    cout << "using word_penalty " << word_penalty << endl;
6084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
6094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  std::string do_skip_interword_silence_str;
6114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if( pDoc->findMeta(std::string("do_skip_interword_silence"), do_skip_interword_silence_str))
6124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    do_skip_interword_silence = ((do_skip_interword_silence_str != "true") ? false : true);
6134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*-----------------------------------------------------------------*
6154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   *   read the .map and .omap created from grxmlcompiler classes    *
6164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   *-----------------------------------------------------------------*/
6174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  std::string omapFilename = grxmlBasename + std::string(".omap");
6194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  std::string imapFilename = grxmlBasename + std::string(".map");
6204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  cout << "info: reading word symbols " << imapFilename << endl;
6224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::SymbolTable *word_syms = fst::SymbolTable::ReadText(imapFilename);
6234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if(!word_syms) {
6244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    cerr << "error: reading word_syms" << endl;
6254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ESR_INVALID_ARGUMENT;
6264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
6274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  cout << "info: reading parser symbols " << omapFilename << endl;
6284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::SymbolTable *prsr_syms = fst::SymbolTable::ReadText(omapFilename);
6294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if(!prsr_syms) {
6304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    cerr << "error: reading prsr_syms" << endl;
6314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ESR_INVALID_ARGUMENT;
6324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
6334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  cout << "info: reading model symbols " << modelmapFilename << endl;
6344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::SymbolTable *model_syms = fst::SymbolTable::ReadText(modelmapFilename);
6354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if(!prsr_syms) {
6364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    cerr << "error: reading prsr_syms" << endl;
6374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ESR_INVALID_ARGUMENT;
6384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
6394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int max_model_sym = 0;
6404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* if(1) {
6414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     fst::SymbolTableIterator iter( *model_syms);
6424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     for(iter.Reset(); !iter.Done(); iter.Next() ) max_model_sym++; */
6434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*-----------------------------------------------------------------*
6454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   * create the .L pronunciations transducer                         *
6464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   *-----------------------------------------------------------------*/
6474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // Adds state 0 to the initially empty FST and make it the start state.
6494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  stateSt = l_fst.AddState();
6504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  stateEn = l_fst.AddState();
6514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  l_fst.SetStart(stateSt);  // arg is state ID
6524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  l_fst.SetFinal(stateEn, 0.0);  // 1st arg is state ID, 2nd arg weight
6534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  l_fst.AddArc(stateEn, fst::StdArc(EPSILON_LABEL,EPSILON_LABEL,0.0,stateSt));
6544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int num_slots = 0;
6564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::SymbolTableIterator iter( *word_syms);
6574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for(iter.Reset(); !iter.Done(); iter.Next() ) {
6584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ESR_ReturnCode rc;
6594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    LCHAR prons[MAX_PRONS_LENGTH];
6604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    const char* phrase = iter.Symbol();
6614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    int wordId = iter.Value();
6624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    bool wordId_is_silence = false;
6634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    bool wordId_is_slot    = false;
6644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /* script or scope marker, skip it */
6654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /* if( is_scope_marker( phrase) || is_script_marker(phrase))
6664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       continue; */
6674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /* epsilon */
6684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if(!strcmp( phrase, SILENCE_PREFIX_WORD)
6694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       || !strcmp(phrase,SILENCE_SUFFIX_WORD))
6704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      wordId_is_silence = true;
6714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    else if( !strcmp( phrase, "eps") && wordId == 0)
6724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      continue;
6734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /* rule markers */
6744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    else if( strstr( phrase, ".grxml@"))
6754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      continue;
6764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /* script markers */
6774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    else if( phrase[0]=='_' && strspn(phrase+1,"0123456789")==strlen(phrase+1))
6784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      continue;
6794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    else if(is_slot_symbol(phrase)) {
6804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      cout << "SLOT>> " << phrase << endl;
6814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      wordId_is_slot = true;
6824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      num_slots++;
6834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
6844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if(num_slots > MAX_NUM_SLOTS) {
6864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      std::cout << "Error: SREC may have trouble with this many slots! (" << num_slots << ")" << std::endl;
6874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      // return ESR_NOT_SUPPORTED;
6884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
6894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if(wordId_is_slot) {
6914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      int stateP = stateSt, statePp1;
6924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      /* with 2 arcs, we have a better chance to merge the slot if used from
6934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	 different parts of the grammar, see FstPushSlotLikeOLabels elsewhere */
6944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      statePp1 = l_fst.AddState();
6954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      l_fst.AddArc(stateP, fst::StdArc( wordId+SLOT_COUNTER_OFFSET, wordId, 0.0, statePp1));
6964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      stateP = statePp1;
6974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      statePp1 = l_fst.AddState();
6984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      l_fst.AddArc(stateP, fst::StdArc( wordId+SLOT_COUNTER_OFFSET, EPSILON_LABEL, 0.0, statePp1));
6994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      stateP = statePp1;
7004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      l_fst.AddArc(stateP, fst::StdArc( WORD_BOUNDARY, EPSILON_LABEL, 0.0, stateEn));
7014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    } else {
7024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      size_t len_used;
7034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      LCHAR *pron = 0, *p;
7044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      /* word is ok, get the pron */
7054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      len = MAX_PRONS_LENGTH;
7064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      rc = SR_VocabularyGetPronunciation(vocab, phrase, prons, &len);
7074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (rc != ESR_SUCCESS) {
7084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	LPRINTF( "ERROR: SR_VocabularyGetPronunciation(*,%s,*,*) returned %s\n", phrase, ESR_rc2str(rc));
7094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	SR_VocabularyDestroy(vocab);
7104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	return rc;
7114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
7124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      for(len_used=0; len_used<len; ) {
7134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	pron = &prons[0]+len_used;
7144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	len_used += LSTRLEN(pron)+1;
7154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	if( *pron == 0) break;
7164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	int stateP = stateSt, statePp1;
7174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	int olabel = wordId;
7184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	LPRINTF("%s : %s\n", phrase, pron);
7194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	/* main pronunciation */
7204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	for(p=pron; *p; p++) {
7214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  statePp1 = l_fst.AddState();
7224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  if(*p == OPTSILENCE_CODE) {
7234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	    l_fst.AddArc(stateP, fst::StdArc( SILENCE_CODE, olabel, 0.0, statePp1));
7244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	    l_fst.AddArc(stateP, fst::StdArc( EPSILON_LABEL, olabel, 0.0, statePp1));
7254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  } else {
7264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	    l_fst.AddArc(stateP, fst::StdArc( *p, olabel, 0.0, statePp1));
7274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  }
7284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  stateP = statePp1;
7294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  olabel = EPSILON_LABEL;
7304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	}
7314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	/* add epsilons if this is a homonym */
7324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	string pron_string = pron;
7334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	hash_map<string,int>::const_iterator it = homonym_count.find( pron_string);
7344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	if(it == homonym_count.end()) {
7354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  homonym_count[ pron_string] = 0;
7364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	} else {
7374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  homonym_count[ pron_string] = homonym_count[ pron_string]+1;
7384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	}
7394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	int extra_epsilons_needed = homonym_count[ pron_string] ;
7404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	if(wordId_is_silence) extra_epsilons_needed = 0;
7414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	for(int i=0;i<extra_epsilons_needed;i++) {
7424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  statePp1 = l_fst.AddState();
7434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  l_fst.AddArc(stateP, fst::StdArc( EXTRA_EPSILON_LABEL, olabel, 0.0, statePp1));
7444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  stateP = statePp1;
7454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	}
7464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	/* add optional silence after each word */
7474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	if(!do_skip_interword_silence && !wordId_is_silence && !wordId_is_slot) {
7484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  statePp1 = l_fst.AddState();
7494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  l_fst.AddArc(stateP, fst::StdArc( SILENCE_CODE, EPSILON_LABEL, 0.0, statePp1));
7504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  l_fst.AddArc(statePp1, fst::StdArc( WORD_BOUNDARY, EPSILON_LABEL, 0.0, stateEn));
7514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  l_fst.AddArc(stateP, fst::StdArc( WORD_BOUNDARY, EPSILON_LABEL, 0.0, stateEn));
7524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	} else if(wordId_is_silence && !strcmp(phrase, SILENCE_SUFFIX_WORD)) {
7534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  /* SILENCE_SUFFIX_WORD does not need a terminal .wb */
7544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  l_fst.AddArc(stateP, fst::StdArc( EPSILON_LABEL, EPSILON_LABEL, 0.0, stateEn));
7554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	} else {
7564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  l_fst.AddArc(stateP, fst::StdArc( WORD_BOUNDARY, EPSILON_LABEL, 0.0, stateEn));
7574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	}
7584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      } // loop over multiple prons
7594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    } // slot vs non-slot
7604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  } /* .map (word_syms) iterator */
7614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  std::string lfstFilename = grxmlBasename + ".L";
7634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // We can save this FST to a file with:
7644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if(debug) l_fst.Write(lfstFilename.c_str());
7654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*-----------------------------------------------------------------*
7674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   *   read the .P.txt created from grxmlcompiler classes            *
7684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   *-----------------------------------------------------------------*/
7694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  std::string ptxtFilename = grxmlBasename + std::string(".P.txt");
7714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  std::ifstream istrm(ptxtFilename.c_str());
7724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if(!istrm) {
7734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    cerr << "error: reading ptxtFilename" << endl;
7744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ESR_INVALID_ARGUMENT;
7754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
7764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  cout << "info: reading parser from text " << ptxtFilename << endl;
7784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::FstReader<fst::StdArc> reader( istrm, ptxtFilename, word_syms, prsr_syms,
7794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project				      /*state_syms*/ NULL,
7804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project				      /*acceptor*/ false,
7814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project				      /*ikeep*/ false,
7824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project				      /*okeep*/ false,
7834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project				      /*nkeep*/ false);
7844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // .P file, created from the .P.txt and .omap
7854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  const fst::StdVectorFst& p_fst = reader.Fst();
7864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*-----------------------------------------------------------------*
7884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   *   make the helper FSTs                                          *
7894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   *-----------------------------------------------------------------*/
7904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  cout << "info: creating helper fsts" << endl;
7924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::StdVectorFst prefix_fst;
7934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::StdVectorFst suffix_fst;
7944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::StdVectorFst eps_fst;
7954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // int eps_word = StrToId("eps", word_syms, "arc ilabel");
7964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int pau_word = StrToId(SILENCE_PREFIX_WORD, word_syms, "arc ilabel");
7974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int pau2_word = StrToId(SILENCE_SUFFIX_WORD, word_syms, "arc ilabel");
7984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if(pau_word < 0 || pau2_word < 0)
7994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ESR_INVALID_ARGUMENT;
8004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  stateSt = prefix_fst.AddState();
8024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  stateEn = prefix_fst.AddState();
8034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  prefix_fst.SetStart(stateSt);  // arg is state ID
8044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  prefix_fst.SetFinal(stateEn, 0.0);  // 1st arg is state ID, 2nd arg weight
8054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  prefix_fst.AddArc(stateSt, fst::StdArc(pau_word, pau_word, 0.0, stateEn));
8064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  stateSt = suffix_fst.AddState();
8084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  stateEn = suffix_fst.AddState();
8094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  suffix_fst.SetStart(stateSt);  // arg is state ID
8104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  suffix_fst.SetFinal(stateEn, 0.0);  // 1st arg is state ID, 2nd arg weight
8114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  suffix_fst.AddArc(stateSt, fst::StdArc(pau2_word, pau2_word, 0.0, stateEn));
8124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  stateSt = eps_fst.AddState();
8144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  stateEn = stateSt; // stateEn = eps_fst.AddState();
8154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  eps_fst.SetStart(stateSt);  // arg is state ID
8164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  eps_fst.SetFinal(stateEn, 0.0);  // 1st arg is state ID, 2nd arg weight
8174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // eps_fst.AddArc(stateSt, fst::StdArc(eps_word, eps_word, 0.0, stateEn));
8184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*-----------------------------------------------------------------*
8204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   *    make Grev2.det.txt                                           *
8214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   *-----------------------------------------------------------------*/
8224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  cout << "info: creating reverse g fst" << endl;
8234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::StdVectorFst g_fst = p_fst;   // this is a copy!!
8244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::StdVectorFst grev_fst;        // reversed
8254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::StdVectorFst grev_min_fst;    // eps removed and minimized
8264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::StdVectorFst grev_det_fst;
8274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::Project(&g_fst, fst::PROJECT_INPUT);
8294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if(debug) g_fst.Write( grxmlBasename + ".G");
8304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::Reverse( g_fst, &grev_fst);
8314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if(debug) grev_fst.Write( grxmlBasename + ".Grev");
8324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::RmEpsilon( &grev_fst, /*connect?*/ true );
8334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if(debug) grev_fst.Write( grxmlBasename + ".Grevrme");
8344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::Determinize(grev_fst, &grev_det_fst);
8354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if(debug) grev_det_fst.Write( grxmlBasename + ".Grevrmedet");
8364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if(1) fst::Minimize(&grev_det_fst);
8374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if(debug) grev_det_fst.Write( grxmlBasename + ".Grevrmedetmin");
8384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::Concat( &eps_fst, grev_det_fst);
8394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  grev_det_fst = eps_fst;
8404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if(debug) grev_det_fst.Write( grxmlBasename + ".Grevrmedetmin2");
8414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  std::string grevFilename = grxmlBasename + std::string(".Grev2.det.txt");
8424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  cout << "info: writing reverse G fst as text " << grevFilename << endl;
8444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ostream* ostrm1 = new ofstream( grevFilename.c_str(), ios_base::out);
8454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::FstPrinter<fst::StdArc> printer1( grev_det_fst,
8464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project					word_syms, word_syms,
8474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project					 NULL, /*acceptor?*/ true);
8484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  printer1.Print( ostrm1, grevFilename);
8494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  delete ostrm1;
8504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*-----------------------------------------------------------------*
8524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   *    make PCLG.txt                                                *
8534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   *-----------------------------------------------------------------*/
8544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::StdVectorFst* c_fst;
8564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::StdVectorFst lg_fst;
8574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::StdVectorFst clg_fst;
8584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::StdVectorFst clg_det_fst;
8594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  cout << "info: reading model fst " << cfstFilename << endl;
8614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  c_fst = fst::StdVectorFst::Read( cfstFilename);
8624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int slot_olabel_min=0, slot_olabel_max=0; // [min,max) .. ie excludes max
8644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  get_slot_olabel_range( word_syms, &slot_olabel_min, &slot_olabel_max);
8654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if(slot_olabel_max > MAX_NUM_SLOTS)
8664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    std::cout << "Error: SREC may have trouble with this many slots! (" << slot_olabel_max << ")" << std::endl;
8674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* add slot markers as if they were silence phonemes, this makes the context
8694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     for them as if the slot were silence, which is reasonable, although another
8704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     reasonable thing would be to allow all contexts.  Adding the true context
8714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     only would add complexity and slow down word addition too much. */
8724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  rc = FstAddSlotMarkersToCFst( *c_fst, slot_olabel_min, slot_olabel_max);
8744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if(rc) return rc;
8754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::Concat( &g_fst, suffix_fst);
8774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::Concat( &prefix_fst, g_fst);
8784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if(debug) prefix_fst.Write( grxmlBasename + ".G2");
8794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::ComposeOptions copts( /*connect?*/ true);
8804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::ArcSort(&l_fst, fst::StdOLabelCompare());
8824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::ArcSort(&prefix_fst, fst::StdILabelCompare());
8834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::Compose(l_fst, prefix_fst, &lg_fst, copts);
8854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if(debug) lg_fst.Write( grxmlBasename + ".LG");
8864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::ArcSort(&lg_fst, fst::StdILabelCompare());
8874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if(debug) lg_fst.Write( grxmlBasename + ".LG2");
8884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::RmEpsilon( &lg_fst, /*connect?*/ true );
8904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if(debug) lg_fst.Write( grxmlBasename + ".LGrme");
8914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::Determinize( lg_fst, &clg_fst); // clg_fst is really lg_det_fst!
8924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if(debug) clg_fst.Write( grxmlBasename + ".LGrmedet");
8934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  rc = FstReplaceILabel( clg_fst, EXTRA_EPSILON_LABEL, EPSILON_LABEL);
8944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::Compose( *c_fst, clg_fst, &clg_det_fst, copts);
8954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if(debug) clg_det_fst.Write( grxmlBasename + ".CLGrmedet");
8964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  rc = FstMergeOLabelsToILabels_GetMax( clg_det_fst, /*int&*/max_model_sym);
8984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if(verbose)
8994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    cout << "info: merging into ilabels I=i+" << max_model_sym << "*o" << endl;
9004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  rc = FstMergeOLabelsToILabels( clg_det_fst, max_model_sym);
9014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if(debug) clg_det_fst.Write( grxmlBasename + ".CLGrmedet2");
9024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::Minimize( &clg_det_fst);
9034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if(debug) clg_det_fst.Write( grxmlBasename + ".CLGrmedet3");
9044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if(verbose)
9054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    cout << "info: splitting from ilabels" << endl;
9064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  rc = FstSplitOLabelsFromILabels( clg_det_fst, max_model_sym);
9074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if(debug) clg_det_fst.Write( grxmlBasename + ".CLGrmedet4");
9084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  rc = FstPushSlotLikeOLabels( clg_det_fst, slot_olabel_min, slot_olabel_max);
9104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if(rc != ESR_SUCCESS)
9114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        std::cout << "Error: FstPushSlotLikeOLabels() failed" << std::endl;
9124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if(debug) clg_det_fst.Write( grxmlBasename + ".CLG");
9134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  std::string pclgFilename = grxmlBasename + ".PCLG.txt";
9154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ostream* ostrm = new ofstream( pclgFilename.c_str(), ios_base::out);
9164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::FstPrinter<fst::StdArc> printer( clg_det_fst,
9174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project					model_syms, word_syms,
9184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project					NULL, /*acceptor?*/ false);
9194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  printer.Print( ostrm, pclgFilename);
9204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  delete ostrm;
9214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  delete c_fst;
9234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  delete word_syms;  word_syms = NULL;
9244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  delete prsr_syms;  prsr_syms = NULL;
9254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  delete model_syms; model_syms = NULL;
9264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*-----------------------------------------------------------------*
9284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   *    cleanup                                                      *
9294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   *-----------------------------------------------------------------*/
9304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if(vocab) {
9324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    SR_VocabularyDestroy(vocab);
9334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    vocab = NULL;
9344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
9354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return rc;
9374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
9394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
941