14a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*---------------------------------------------------------------------------*
24a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  make_cfst.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#include "srec_arb.h"
224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "simapi.h"
234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "fst/lib/fstlib.h"
254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "fst/lib/fst-decl.h"
264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "fst/lib/vector-fst.h"
274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "fst/lib/arcsort.h"
284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "fst/lib/invert.h"
294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "fst/lib/rmepsilon.h"
304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define MAX_LINE_LENGTH     256
324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define MAX_PRONS_LENGTH 1024
334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define EPSILON_LABEL 0
344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define MAX_MODELS 1024
354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define MAXPHID 8888
364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define MAX_PHONEMES 128
374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectusing namespace fst;
394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectint usage(const char* prog)
414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  printf("usage: %s  -phones models/phones.map -models models/models128x.map -cfst models/generic.C -swiarb models/generic.swiarb\n", prog);
434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return 1;
444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttypedef struct Minifst_t
474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  char lcontexts[MAX_PHONEMES];
494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  char rcontexts[MAX_PHONEMES];
504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int modelId;
514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int stateSt;
524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int stateEn;
534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  phonemeID phonemeId;
544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  unsigned char phonemeCode;
554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int lcontext_state[MAX_PHONEMES];
564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int rcontext_state[MAX_PHONEMES];
574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project} Minifst;
584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectint main(int argc, char **argv)
604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  char* cfstFilename = 0;
624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  char* swiarbFilename = 0;
634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  char* phonesMap;
644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  char* modelsMap;
654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int i;
664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  phonemeID lphonId, cphonId, rphonId;
674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  unsigned char cphon;
684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  modelID modelId, max_modelId = 0;
694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int stateSt, stateEn;
704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int stateN, stateNp1;
714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int rc;
724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  Minifst minifst[MAX_MODELS];
734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int do_show_text = 1;
744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int do_until_step = 99;
754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* initial memory */
774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  rc = PMemInit();
784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ASSERT( rc == ESR_SUCCESS);
794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // A vector FST is a general mutable FST
814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::StdVectorFst myCfst;
824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // fst::Fst<fst::StdArc> myCfst;
834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if(argc <= 1)
854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return usage(argv[0]);
864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for(i=1; i<argc; i++)
884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if(0) ;
904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    else if(!strcmp(argv[i],"-phones"))
914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      phonesMap = argv[++i];
924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    else if(!strcmp(argv[i],"-models"))
934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      modelsMap = argv[++i];
944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    else if(!strcmp(argv[i],"-cfst"))
954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      cfstFilename = argv[++i];
964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    else if(!strcmp(argv[i],"-step"))
974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      do_until_step = atoi(argv[++i]);
984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    else if(!strcmp(argv[i],"-swiarb"))
994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      swiarbFilename = argv[++i];
1004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    else {
1014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      return usage(argv[0]);
1024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
1034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
1044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  printf("loading %s ...\n", swiarbFilename);
1064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  CA_Arbdata* ca_arbdata = CA_LoadArbdata(swiarbFilename);
1074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  srec_arbdata *allotree = (srec_arbdata*)ca_arbdata;
1084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*-------------------------------------------------------------------------
1114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   *
1124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   *       /---<---<---<---<---<---<---\
1134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   *      /                             \
1144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   *     /       -wb--         -wb-      \
1154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   *    /        \   /         \  /       \
1164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   *   0 ---#--->  n ----M---> n+1 ---#---> 1
1174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   *
1184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   *
1194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   *
1204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   *
1214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   *-------------------------------------------------------------------------
1224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   */
1234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // Adds state 0 to the initially empty FST and make it the start state.
1254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  stateSt = myCfst.AddState();   // 1st state will be state 0 (returned by AddState)
1264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  stateEn = myCfst.AddState();
1274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  myCfst.SetStart(stateSt);  // arg is state ID
1284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  myCfst.SetFinal(stateEn, 0.0);  // 1st arg is state ID, 2nd arg weight
1294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  myCfst.AddArc(stateEn, fst::StdArc(EPSILON_LABEL, EPSILON_LABEL, 0.0, stateSt));
1304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  phonemeID silencePhonId = 0;
1324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  modelID silenceModelId = 0;
1334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  silenceModelId = (modelID)get_modelid_for_pic(allotree, silencePhonId, silencePhonId, silencePhonId);
1344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // silenceModelId += MODEL_LABEL_OFFSET; #define MODEL_LABEL_OFFSET 128
1354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for(modelId=0; modelId<MAX_MODELS; modelId++) {
1374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    minifst[modelId].modelId = MAXmodelID;
1384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    minifst[modelId].stateSt = minifst[modelId].stateEn = 0;
1394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    minifst[modelId].phonemeId = MAXphonemeID;
1404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    minifst[modelId].phonemeCode = 0;
1414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for(i=0;i<MAX_PHONEMES;i++) {
1424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      minifst[modelId].lcontexts[i] = minifst[modelId].rcontexts[i] = 0;
1434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      minifst[modelId].lcontext_state[i] = minifst[modelId].rcontext_state[i] = 0;
1444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
1454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
1464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for(cphonId=0; cphonId<allotree->num_phonemes && cphonId<MAXPHID; cphonId++) {
1484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    cphon = allotree->pdata[cphonId].code;
1494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    printf("processing phoneme %d of %d %d %c\n", cphonId, allotree->num_phonemes, cphon, cphon);
1504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for(lphonId=0; lphonId<allotree->num_phonemes && lphonId<MAXPHID; lphonId++) {
1524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      unsigned char lphon = allotree->pdata[lphonId].code;
1534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      for(rphonId=0; rphonId<allotree->num_phonemes && rphonId<MAXPHID; rphonId++) {
1544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	unsigned char rphon = allotree->pdata[rphonId].code;
1554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	if( 1|| cphon=='a') { //22222
1564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  modelId = (modelID)get_modelid_for_pic(allotree, lphonId, cphonId, rphonId);
1574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	} else {
1584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  modelId = (modelID)get_modelid_for_pic(allotree, 0, cphonId, 0);
1594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	}
1604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	if(modelId == MAXmodelID) {
1614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  printf("error while get_modelid_for_pic( %p, %d, %d, %d)\n",
1624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project		 allotree, lphonId, cphonId, rphonId);
1634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  continue;
1644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	} else
1654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  if(do_show_text) printf("%c %c %c hmm%03d_%c %d %d %d\n", lphon, cphon, rphon, modelId, cphon, lphonId, cphonId, rphonId);
1664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	ASSERT(modelId < MAX_MODELS);
1674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	minifst[ modelId].phonemeId = cphonId;
1684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	minifst[ modelId].phonemeCode = cphon;
1694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	minifst[ modelId].modelId = modelId;
1704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	minifst[ modelId].lcontexts[lphonId] = 1;
1714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	minifst[ modelId].rcontexts[rphonId] = 1;
1724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	if(modelId>max_modelId) max_modelId = modelId;
1734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
1744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
1754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
1764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  printf("adding model arcs .. max_modelId %d\n",max_modelId);
1784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for(modelId=0; modelId<=max_modelId; modelId++) {
1794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if( minifst[modelId].modelId == MAXmodelID) continue;
1804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    cphon = minifst[modelId].phonemeCode;
1814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    minifst[modelId].stateSt = (stateN = myCfst.AddState());
1824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    minifst[modelId].stateEn = (stateNp1 = myCfst.AddState()); /* n plus 1 */
1834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    myCfst.AddArc( stateN, fst::StdArc(cphon,modelId,0.0,stateNp1));
1844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    myCfst.AddArc( stateNp1, fst::StdArc(WORD_BOUNDARY,WORD_BOUNDARY,0.0,stateNp1));
1854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if(do_show_text) printf("%d\t\%d\t%c\t\%d\n", stateN,stateNp1,cphon,modelId);
1874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if 1
1884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for( lphonId=0; lphonId<allotree->num_phonemes; lphonId++) {
1894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      minifst[modelId].lcontext_state[lphonId] = myCfst.AddState();
1904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      myCfst.AddArc( minifst[modelId].lcontext_state[lphonId],
1914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project		  fst::StdArc(EPSILON_LABEL,EPSILON_LABEL,0.0,
1924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project			      minifst[modelId].stateSt));
1934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
1954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for( rphonId=0; rphonId<allotree->num_phonemes; rphonId++) {
1964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      minifst[modelId].rcontext_state[rphonId] = myCfst.AddState();
1974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      myCfst.AddArc( minifst[modelId].stateEn,
1984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project		  fst::StdArc(EPSILON_LABEL,EPSILON_LABEL,0.0,
1994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project			      minifst[modelId].rcontext_state[rphonId]));
2004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
2014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
2024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
2034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if 1
2044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  printf("adding cross-connections\n");
2054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for( modelId=0; modelId<=max_modelId; modelId++) {
2064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    printf("processing model %d\n", modelId);
2074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if( minifst[modelId].modelId == MAXmodelID) continue;
2084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    cphonId = minifst[modelId].phonemeId;
2094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for( modelID mId=0; mId<=max_modelId; mId++) {
2104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if( minifst[mId].modelId != MAXmodelID &&
2114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  // minifst[mId].phonemeId == rphonId &&
2124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  minifst[modelId].rcontexts[ minifst[mId].phonemeId] == 1 &&
2134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  minifst[mId].lcontexts[ cphonId] == 1) {
2144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	myCfst.AddArc( minifst[modelId].stateEn,
2154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project		    fst::StdArc(EPSILON_LABEL,EPSILON_LABEL,0.0,
2164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project				minifst[mId].stateSt));
2174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
2184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
2194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
2204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* start node connections */
2214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  myCfst.AddArc( stateSt,
2224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	      fst::StdArc(EPSILON_LABEL, EPSILON_LABEL, 0.0,
2234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project			  minifst[silenceModelId].stateSt));
2244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  myCfst.AddArc(  minifst[silenceModelId].stateEn,
2254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	      fst::StdArc(EPSILON_LABEL, EPSILON_LABEL, 0.0, stateEn));
2264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
2274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::StdVectorFst fst2;
2294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst::StdVectorFst* ofst = &myCfst;
2304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if(do_until_step>0) {
2314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    printf("invert\n");
2324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    fst::Invert(&myCfst);
2334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    bool FLAGS_connect = true;
2344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if(do_until_step>1) {
2354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      printf("rmepsilon\n");
2364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      fst::RmEpsilon( &myCfst, FLAGS_connect);
2374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if(do_until_step>2) {
2384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	printf("determinize\n");
2394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	fst::Determinize(myCfst, &fst2);
2404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	ofst = &fst2;
2414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	if(do_until_step>3) {
2424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  printf("arcsort olabels\n");
2434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  fst::ArcSort(&fst2, fst::StdOLabelCompare());
2444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	}
2454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
2464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
2474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
2484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if 0
2504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for(fst::SymbolTableIterator syms_iter( *syms); !syms_iter.Done(); syms_iter.Next() ) {
2514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    int value = (int)syms_iter.Value();
2524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    const char* key = syms_iter.Symbol();
2534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
2544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
2554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  printf("writing output file %s\n", cfstFilename);
2574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // We can save this FST to a file with:
2594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* fail compilation if char and LCHAR aren't the same! */
2604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  { char zzz[ 1 - (sizeof(LCHAR)!=sizeof(char))]; zzz[0] = 0; }
2624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ofst->Write((const char*)cfstFilename);
2634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  CA_FreeArbdata( ca_arbdata);
2654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  PMemShutdown();
2674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  //  CLEANUP:
2694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return (int)rc;
2704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
2714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
273