First Environment
Creating Architecture Descriptions
Now we have to make a couple of decisions about how the recognizer should look
like. We have to decide the following things: 
-  what topologies and transition probablities to use for HMMs of phonemes
-  want to start with simple semicontinuous system or with something better
-  how many Gaussians do we want in our mixtures
Since this should be a tiny system to make training easily reproducible and
fast, we decide the following:
-  the phoneme topology for non-silence phonemes will be:   
 i.e. two states with transitions to themselves and to the next state,
   the silence phone will only use one state, all the transitions have 
   equal probability (0.5)
-  we will start with a continuous densities system, i.e. one codebook for
   each of the 2 * 16 + 1 states
-  every codebook will have eight Gaussians, this is a number small enough to
   be trained awfully fast, and large enough to allow at least a tiny little
   bit of recognition accuracy
So we create the following files manually in an editor:
phones:	
A E F H I K L N O P R S T U V Y X
trans:
any { {0 0.5} {1 0.5} }
topoSet:
SIL	{ ROOT-b ROOT-e } { any any }
NONSIL	{ ROOT-m } { any }
topoTree:
ROOT 0=X NONSIL SIL - -
If you look at the topology defined above and look at the Janus documentation
you will easily understand the meanings of these files (in the phones file
we use the character X for the silence phoneme). 
Let Janus Create the Rest
Creating a first recognizer environment means to create some description files.
Although it is possible to not actually create files, but instead reproduce
their information on the fly, while Janus is running, this can become rather
unconvenient. You can use a rather simple script for creating the missing
three files:
-  codebookSet: A file that contains the description for 33
     codebooks, two for each of the 16 phonemes plus one for the silence phone.
-  distribSet: A file that contains the description for 33
     mixture-weight distributions; initially there is one distribution for
     each of the codebooks.
-  distribTree: A simple decision tree with question about the central
     phone only, and onoe leaf node for each of the 33 distributions
The following script will create these files. It is establishing the basic
objects that are needed and then fills the initially empty codebook set, and
distribution set, and distribution tree. Eventually all three objects are
saved into a file:
[FeatureSet fs] setDesc ../prepare/featdesc
CodebookSet cbs fs
DistribSet dss cbs
[Phones phones] read ../prepare/phones 
PhonesSet phonesSet
Tags tags
Tree dst phones phonesSet tags dss
set modelList {
    {A b} {E b} {F b} {H b} {I b} {K b} {L b} {N b} {O b} {P b} {R b} 
    {S b} {T b} {U b} {V b} {Y b} {A e} {E e} {F e} {H e} {I e} {K e} 
    {L e} {N e} {O e} {P e} {R e} {S e} {T e} {U e} {V e} {Y e} {X m}
}
foreach model $modelList { eval addModel $model MSC 8 8 DIAGONAL cbs dss dst }
cbs write cbs-desc
dss write dss-dest
dst write tree-desc
The heart of the above script is the call of the "addModel" procedure. It is
documented in more detail in the scripts-thread. 
proc addModel { phone subTree feature refN dimN type cbs dss tree } {
  set dsname   $phone-$subTree
  set question 0=$phone
  set cbname   $phone-$subTree
  set root     ROOT-$subTree
  # Create new codebook $cbname in codebook set $cbs and
  # create new distribution $dsname in distribution set $dss
  # --------------------------------------------------------
  if {[$cbs index $cbname] < 0} { $cbs add $cbname $feature $refN $dimN $type }
  if {[$dss index $dsname] < 0} { $dss add $dsname $cbname }
  # compose name of hook node (question node) and the attached leaf node
  # --------------------------------------------------------------------
  set qnode hook-$dsname
  set lnode      $dsname
  # if the requested root in the tree does not yet exist, create it,
  # then add the new node (hook and leaf) by traversing all no-successors
  # ---------------------------------------------------------------------
  if {[$tree index $root] < 0} {
    $tree add $root {} $qnode $qnode $qnode "-"
    $tree add $qnode $question - $lnode - -
    $tree add $lnode {} - - - $dsname
  } else {
    $tree add $qnode $question - $lnode - - 
    $tree add $lnode {} - - - $dsname
    # Find last NO node starting at root
    set lidx [$tree index $root]
    set idx   $lidx
    while { [set idx [$tree.item($lidx) configure -no]] > -1} { set lidx $idx }
    $tree.item($lidx) configure -no [$tree index $qnode]
  }
}