14a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*---------------------------------------------------------------------------*
24a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  srec.c  *
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 <stdlib.h>
214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include <string.h>
224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include <math.h>
234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "pstdio.h"
254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "passert.h"
264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "portable.h"
274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "hmm_desc.h"
294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "utteranc.h"
304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "hmmlib.h"
314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "srec_sizes.h"
324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "search_network.h"
334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "srec_context.h"
344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "srec.h"
354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "srec_stats.h"
364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "srec_debug.h"
374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "srec_tokens.h"
384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "word_lattice.h"
394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "swimodel.h"
404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if USE_COMP_STATS
414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "comp_stats.h"
424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "c42mul.h"
444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#ifdef SET_RCSID
464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic const char *rcsid = 0 ? (const char *) &rcsid :
474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project"$Id: srec.c,v 1.39.4.31 2008/06/23 17:20:39 dahan Exp $";
484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define SILENCE_MODEL_INDEX 0
514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define PRUNE_TIGHTEN 0.9     /*if we run out of room in the state arrays,
524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                keep multiplying pruning thresh by this amount
534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                until there is room */
544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*--------------------------------------------------------------------------*
564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                          *
574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * protos                                                                   *
584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                          *
594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *--------------------------------------------------------------------------*/
604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic void reset_cost_offsets(multi_srec* rec, frameID current_search_frame,
614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                               costdata current_best_cost);
624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic void update_internal_hmm_states(srec *rec, costdata *pcurrent_prune_delta,
634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                       costdata *pcurrent_best_cost,
644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                       costdata *precomputed_model_scores);
654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*--------------------------------------------------------------------------*
674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                          *
684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * utils                                                                    *
694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                          *
704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *--------------------------------------------------------------------------*/
714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic void dump_core(char *msg)
734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  PLogError ( msg );
754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ASSERT(0);
764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic altword_token* reprune_altword_token_batch(srec* rec,
794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    altword_token* batch,
804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    bigcostdata costlimit)
814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  altword_token *awtoken, *next_awtoken;
834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  altword_token **awtokenp;
844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* look for previous invalidate, see below */
864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (batch->costbasis == MAXcostdata / 2)
874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  { /* was costdelta // costlimit */
884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    free_altword_token(rec, batch);
894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return AWTNULL;
904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* a flag to check whether we already pruned this batch would be nice */
924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* first prune the CDR of the list, ie everything but the head */
944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  awtokenp = &batch->next_token;
954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (awtoken = batch->next_token; awtoken != AWTNULL; awtoken = next_awtoken)
964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    next_awtoken = awtoken->next_token;
984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if ((bigcostdata)batch->costbasis + awtoken->costdelta > costlimit)
994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
1004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      (*awtokenp) = awtoken->next_token;
1014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      awtoken->refcount = 1;             /* to make sure it frees */
1024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      free_altword_token(rec, awtoken);
1034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
1044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    else
1054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      awtokenp = &awtoken->next_token;
1064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
1074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* now see about the CAR of the list, ie the head */
1094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if ((bigcostdata)(batch->costbasis) + batch->costdelta < costlimit)
1104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
1114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /* head of list survives pruning => no problem */
1124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
1134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else if (batch->next_token != AWTNULL)
1144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
1154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /* head of list does not survive => since we can't change the pointer
1164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       we copy a survivor into it and free that original */
1174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    awtoken = batch->next_token;
1184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    batch->costdelta      = awtoken->costdelta;
1194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    batch->word           = awtoken->word;
1204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    batch->word_backtrace = awtoken->word_backtrace;
1214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /*ASSERT( batch->refcount == awtoken->refcount); */
1224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /* batch->refcount       = awtoken->refcount; */
1234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    batch->next_token     = awtoken->next_token;
1244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    awtoken->refcount = 1; /* to make sure it frees */
1254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    free_altword_token(rec, awtoken);
1264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
1274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else
1284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
1294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /* head of list does not survive, nothing survives, so invalidate it */
1304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    batch->costbasis = MAXcostdata / 2; /* was costdelta */
1314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    free_altword_token(rec, batch);
1324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    batch = AWTNULL;
1334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
1344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return batch;
1354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
1364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic void reprune_altword_tokens(srec* rec)
1384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
1394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  stokenID i, j;
1404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fsmarc_token* stoken;
1414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fsmnode_token* ftoken;
1424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  bigcostdata current_prune_delta = rec->prune_delta;
1434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  altword_token* awtoken;
1444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* first clear the costbases */
1464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (i = rec->active_fsmarc_tokens; i != MAXstokenID; i = stoken->next_token_index)
1474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
1484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    stoken = &rec->fsmarc_token_array[i];
1494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for (j = 0; j < stoken->num_hmm_states; j++)
1504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if ((awtoken = stoken->aword_backtrace[j]) != AWTNULL)
1514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        awtoken->costbasis = MAXcostdata;
1524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
1534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (i = rec->active_fsmnode_tokens;i != MAXftokenID;i = ftoken->next_token_index)
1544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
1554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ftoken = &rec->fsmnode_token_array[i];
1564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if ((awtoken = ftoken->aword_backtrace) != AWTNULL)
1574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      awtoken->costbasis = MAXcostdata;
1584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
1594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* costbases for altword attached to stoken */
1604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (i = rec->active_fsmarc_tokens; i != MAXstokenID; i = stoken->next_token_index)
1614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
1624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    stoken = &rec->fsmarc_token_array[i];
1634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for (j = 0; j < stoken->num_hmm_states; j++)
1644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if ((awtoken = stoken->aword_backtrace[j]) != AWTNULL)
1654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (awtoken->costbasis > stoken->cost[j])
1664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          awtoken->costbasis = stoken->cost[j];
1674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
1684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* costbases for altword attached to ftokens */
1694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (i = rec->active_fsmnode_tokens;i != MAXftokenID;i = ftoken->next_token_index)
1704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
1714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ftoken = &rec->fsmnode_token_array[i];
1724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if ((awtoken = ftoken->aword_backtrace) != AWTNULL)
1734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (awtoken->costbasis > ftoken->cost)
1744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        awtoken->costbasis = ftoken->cost;
1754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
1764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* now reprune */
1784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  while (rec->altword_token_freelist_len < rec->altword_token_array_size / 4
1794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project         || rec->altword_token_freelist_len < 2*rec->word_priority_q->max_in_q)
1804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
1814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    SREC_STATS_INC_AWTOKEN_REPRUNES(1);
1824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    current_prune_delta = (costdata)(PRUNE_TIGHTEN * PRUNE_TIGHTEN * current_prune_delta);
1834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for (i = rec->active_fsmarc_tokens; i != MAXstokenID; i = stoken->next_token_index)
1844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
1854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      stoken = &rec->fsmarc_token_array[i];
1864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      for (j = 0; j < stoken->num_hmm_states; j++)
1874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
1884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (stoken->aword_backtrace[j] != AWTNULL)
1894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        {
1904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          stoken->aword_backtrace[j] =
1914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            reprune_altword_token_batch(rec, stoken->aword_backtrace[j],
1924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                        current_prune_delta);
1934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
1944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
1954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
1964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for (i = rec->active_fsmnode_tokens;i != MAXftokenID;i = ftoken->next_token_index)
1974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
1984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      ftoken = &rec->fsmnode_token_array[i];
1994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (ftoken->aword_backtrace != AWTNULL)
2004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
2014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        ftoken->aword_backtrace =
2024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          reprune_altword_token_batch(rec, ftoken->aword_backtrace,
2034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                      current_prune_delta);
2044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
2054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
2064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ASSERT(current_prune_delta > 0);
2074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
2084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
2094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define refcopy_altwords(rEc, aWtOkEn) (aWtOkEn?(aWtOkEn->refcount++,aWtOkEn):aWtOkEn)
2114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic altword_token* copy_altwords(srec* rec, altword_token* list1, costdata delta)
2134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
2144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  altword_token *q2, dummy, *last_q2 = &dummy;
2154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  costdata q2_costdelta;
2164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* first check for space */
2184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if BUILD & BUILD_DEBUG
2194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int num = 0;
2204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (num = 0, q2 = list1; q2 != AWTNULL; q2 = q2->next_token)
2224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    num++;
2234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (num > rec->altword_token_freelist_len)
2244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
2254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    printf("warning: mid-copy reprune_altword_tokens()\n");
2264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ASSERT(0);
2274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    reprune_altword_tokens(rec);
2284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
2294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
2304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* now do the copy */
2324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (; list1 != AWTNULL; list1 = list1->next_token)
2334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
2344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ASSERT(list1->refcount >= 1);
2354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    q2_costdelta = list1->costdelta + delta;
2374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ASSERT(list1->costdelta != MAXcostdata);
2384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (q2_costdelta > rec->prune_delta)
2394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      continue;
2404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    q2 = get_free_altword_token(rec, NULL_IF_NO_TOKENS);
2414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (!q2) /* this should never happen */
2424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      break;
2434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    last_q2->next_token = q2;
2444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    q2->costdelta      = q2_costdelta;
2454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    q2->word           = list1->word;
2464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    q2->word_backtrace = list1->word_backtrace;
2474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    last_q2 = q2;
2484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
2494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  last_q2->next_token = AWTNULL;
2504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return dummy.next_token;
2514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
2524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if 1
2544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/* sizewise_altwords just makes sure the list of altwords is no longer than
2554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   the number of possible word ends.  Any tokens beyond that length will get
2564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   ignored later anyways, so we may as well kill them here.
2574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   This also is related to the anticipated repruning.  This code currently
2584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   makes use of calloc/free and qsort, but can easily be rewritten to just
2594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   to a linear in-place sort, linear looking for the 10 best score should not
2604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   take too long. This is on the todo list!
2614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project*/
2624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectint altword_token_ptr_cmp(const void* a, const void* b)
2634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
2644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  const altword_token** A = (const altword_token**)a, **B = (const altword_token**)b;
2654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if ((*A)->costdelta > (*B)->costdelta) return 1;
2664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else if ((*A)->costdelta < (*B)->costdelta) return -1;
2674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else return 0;
2684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
2694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic altword_token* sizewise_altwords(srec* rec, altword_token* awtoken_head)
2704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
2714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define SIZEWISE_THRESH (rec->word_priority_q->max_in_q)
2724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define SIZEWISE_TARGET (rec->word_priority_q->max_in_q*4/5)
2734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int i, num;
2744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  altword_token *awtoken, **list;
2754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if( SIZEWISE_TARGET == 0) {
2774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  free_altword_token(rec, awtoken_head);
2784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  return NULL;
2794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
2804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  num = count_altword_token(rec, awtoken_head);
2814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* if the linked list is shorter than max_in_q we're fine */
2824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (num <= SIZEWISE_THRESH)
2834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return awtoken_head;
2844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else
2854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
2864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    list = (altword_token**)CALLOC(num, sizeof(altword_token*), L("search.srec.altword_tokens"));
2874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ASSERT(awtoken_head->refcount == 1);
2884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for (i = 0, awtoken = awtoken_head; i < num; i++, awtoken = awtoken->next_token)
2894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      list[i] = awtoken;
2904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    qsort(list, num, sizeof(altword_token*), altword_token_ptr_cmp);
2914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for (i = 0; i < SIZEWISE_TARGET; i++)
2924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      list[i]->next_token = list[i+1];
2934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if(i>0) list[i-1]->next_token = AWTNULL;
2944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for (; i < num; i++)
2954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
2964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      list[i]->refcount = 1; /* make sure it frees */
2974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      free_altword_token(rec, list[i]);
2984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
2994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    awtoken_head = list[0];
3004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    awtoken_head->refcount = 1;
3014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    FREE(list);
3024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return awtoken_head;
3034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
3044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
3054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#else
3064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define sizewise_altwords(ReC,hEad) hEad
3074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
3084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*--------------------------------------------------------------------------*
3104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                          *
3114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * acoustic scoring utils                                                   *
3124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                          *
3134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *--------------------------------------------------------------------------*/
3144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define DO_COMPUTE_MODEL     0
3164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define DO_NOT_COMPUTE_MODEL MAXcostdata
3174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic asr_uint16_t best_uint16(asr_uint16_t* p, int n)
3194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
3204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  asr_uint16_t rv = p[0];
3214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (;--n > 0;p++) if (rv > *p) rv = *p;
3224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return rv;
3234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
3244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic int compute_model_scores(costdata *current_model_scores, const SWIModel *acoustic_models,
3254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                pattern_info *pattern, frameID current_search_frame)
3264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
3274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int i;
3284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int num_models_computed = 0;
3294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (i = 0; i < acoustic_models->num_hmmstates; i++)
3314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
3324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (current_model_scores[i] == DO_COMPUTE_MODEL)
3334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
3344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      scodata score = mixture_diagonal_gaussian_swimodel(pattern->prep,
3354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              &acoustic_models->hmmstates[i], acoustic_models->num_dims);
3364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      ASSERT(score <= 0 && "model score out of range");
3374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      current_model_scores[i] = (costdata) - score;
3394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      num_models_computed++;
3404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
3414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
3424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return num_models_computed;
3434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
3444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*precompute all needed models to be used by next frame of search*/
3484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic int find_which_models_to_compute(srec *rec, const SWIModel *acoustic_models)
3504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
3514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int i;
3524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  modelID model_index;
3534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  stokenID current_token_index;
3544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ftokenID current_ftoken_index;
3554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fsmarc_token *current_token;
3564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fsmnode_token *current_ftoken;
3574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  costdata *current_model_scores;
3584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* arcID arc_index; */
3594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  arcID fsm_arc_index;
3604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  HMMInfo* hmm_info;
3614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  FSMnode* fsm_node;
3624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  FSMarc* fsm_arc;
3634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*use the current_model_scores array both to tell the model computing stuff
3644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    what models to compute and to get the scores back.  This is a bit ugly, but
3654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    saves having another array to allocate*/
3664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* this belongs elsewhere at initialization,
3684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     eg. where we'll associate search to acoustic models
3694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  */
3704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  rec->avg_state_durations = acoustic_models->avg_state_durations;
3714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  current_model_scores = rec->current_model_scores;
3734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (model_index = 0; model_index < acoustic_models->num_hmmstates; model_index++)
3754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
3764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    current_model_scores[model_index] = DO_NOT_COMPUTE_MODEL;
3774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
3784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  current_token_index = rec->active_fsmarc_tokens;
3804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  while (current_token_index != MAXstokenID)
3824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
3834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    current_token = &(rec->fsmarc_token_array[current_token_index]);
3844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /*need to compute all models needed within this HMM*/
3854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    fsm_arc = &rec->context->FSMarc_list[ current_token->FSMarc_index];
3864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    hmm_info = &rec->context->hmm_info_for_ilabel[fsm_arc->ilabel];
3874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /*handle all states that are alive in this hmm*/
3894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for (i = 0;i < hmm_info->num_states;i++)
3904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
3914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if ((current_token->cost[i] != MAXcostdata) ||
3924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          ((i > 0) && current_token->cost[i-1] != MAXcostdata))
3934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
3944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        model_index = hmm_info->state_indices[i];
3954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        current_model_scores[model_index] = DO_COMPUTE_MODEL;
3964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
3974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
3984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    current_token_index = current_token->next_token_index;
3994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
4004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*for each active FSM node, find models which can come from node*/
4024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  current_ftoken_index = rec->active_fsmnode_tokens;
4044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  while (current_ftoken_index != MAXftokenID)
4064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
4074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    current_ftoken = &(rec->fsmnode_token_array[current_ftoken_index]);
4084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    fsm_node = &rec->context->FSMnode_list[current_ftoken->FSMnode_index];
4094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    fsm_arc = NULL;
4104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for (fsm_arc_index = fsm_node->un_ptr.first_next_arc; fsm_arc_index != MAXarcID;
4114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        fsm_arc_index = fsm_arc->linkl_next_arc) {
4124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      fsm_arc = rec->context->FSMarc_list+fsm_arc_index;
4134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (fsm_arc->ilabel != MAXlabelID)
4154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
4164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        hmm_info = &rec->context->hmm_info_for_ilabel[fsm_arc->ilabel];
4174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (hmm_info->num_states > 0)
4184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        {
4194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          /* we should build in here a check that this arc has reasonable weight */
4214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          /* if(fsm_arc->cost < rec->prune_delta)  */
4224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          current_model_scores[hmm_info->state_indices[0]] = DO_COMPUTE_MODEL;
4234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
4244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
4254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
4264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    current_ftoken_index = current_ftoken->next_token_index;
4274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
4284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*compute the scores in a batch - this allows the model computing code to
4304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    chunk it up however it wants*/
4314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return 0;
4324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
4334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*--------------------------------------------------------------------------*
4354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                          *
4364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * pruning utils                                                            *
4374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                          *
4384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *--------------------------------------------------------------------------*/
4394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*this is called at the end of the search*/
4414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic int prune_new_tokens(srec *rec, costdata current_prune_thresh)
4424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
4434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int i;
4444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  nodeID num_deleted;
4454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  stokenID token_index;
4464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fsmarc_token *token;
4474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  stokenID next_token_index;
4484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  stokenID *list_head_pointer;
4494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  char any_alive;
4504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  num_deleted = 0;
4524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  list_head_pointer = &(rec->active_fsmarc_tokens);
4534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (token_index = rec->active_fsmarc_tokens; token_index != MAXstokenID;
4554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       token_index = next_token_index)
4564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
4574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    token = &(rec->fsmarc_token_array[token_index]);
4594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    next_token_index = token->next_token_index;
4604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    any_alive = 0;
4624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for (i = 0;i < token->num_hmm_states;i++)
4644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
4654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (token->cost[i] < current_prune_thresh)
4664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
4674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        any_alive = 1;
4684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
4694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
4704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (!any_alive)
4724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    { /*everything pruned so recylce the token*/
4734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      *list_head_pointer = next_token_index;
4744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      rec->best_token_for_arc[rec->fsmarc_token_array[token_index].FSMarc_index] = MAXstokenID;
4764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      free_fsmarc_token(rec, token_index);
4784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      num_deleted++;
4804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      rec->num_new_states--;
4814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
4824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    else
4834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
4844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      list_head_pointer = &token->next_token_index;
4854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
4864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
4874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return num_deleted;
4884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
4894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic void reprune_word_tokens_if_necessary(srec *rec)
4914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
4924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  word_token* wtoken;
4934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  wtokenID wtoken_index = rec->word_token_freelist;
4944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  wtokenID num_free_wtokens = 0;
4954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (; wtoken_index != MAXwtokenID; wtoken_index = wtoken->next_token_index)
4974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
4984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    wtoken = &rec->word_token_array[ wtoken_index];
4994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    num_free_wtokens++;
5004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
5014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (num_free_wtokens < 2*rec->word_priority_q->max_in_q)
5024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    reprune_word_tokens(rec, 0);
5034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
5044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*this is called when we run out of room in the state token arrays and need to make more room -
5064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project it only prunes in theh new time slice - we could also look at pruning the previous slice if needed*/
5074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic costdata reprune_new_states(srec *rec, costdata current_best_cost, costdata current_prune_delta)
5104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
5114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int num_deleted;
5124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*first check to see if current pruning thresholds make enough room
5134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    (because of better max)*/
5144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  prune_new_tokens(rec, current_best_cost + current_prune_delta);
5164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ASSERT(((float)current_best_cost) + current_prune_delta < (float)SHRT_MAX);
5184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  while ((rec->num_new_states >= rec->max_new_states - 1)
5204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project         || rec->fsmarc_token_freelist == MAXstokenID)
5214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
5224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    SREC_STATS_INC_STOKEN_REPRUNES(1);
5244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    current_prune_delta = (costdata)(PRUNE_TIGHTEN * current_prune_delta);
5264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (current_prune_delta <= 1)
5284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
5294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      /*this seems like an unlikely case, but if we can't prune enough to make room, give up
5304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      on the utterance (better than being stuck here forever!)*/
5314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      /*FIX replace with crec abort mechanism*/
5334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      PLogError ("reprune_new_states: can't seem to prune enough - best cost %d num_new_states %d\n",
5344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project             current_best_cost, rec->num_new_states);
5354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      print_fsmarc_token_list(rec, rec->active_fsmarc_tokens, "CANNOT PRUNE");
5374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      dump_core("reprune died\n");
5394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
5404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    num_deleted = prune_new_tokens(rec, current_best_cost + current_prune_delta);
5424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ASSERT(((float)current_best_cost + current_prune_delta) < (float)USHRT_MAX);
5444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
5454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return current_prune_delta;
5464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
5474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic void prune_fsmnode_tokens(srec *rec, costdata current_prune_thresh, ftokenID not_this_one)
5514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
5524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  nodeID num_deleted;
5534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ftokenID token_index;
5544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fsmnode_token *token;
5554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ftokenID next_token_index;
5564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ftokenID *list_head_pointer;
5574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  num_deleted = 0;
5594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  token_index = rec->active_fsmnode_tokens;
5604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  token = &(rec->fsmnode_token_array[token_index]);
5624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  list_head_pointer = &(rec->active_fsmnode_tokens);
5634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  while (token_index != MAXftokenID)
5654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
5664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    next_token_index = token->next_token_index;
5674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if( token_index!=not_this_one && token->cost >= current_prune_thresh)
5684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
5694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      /*pruned so recycle the token*/
5704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      *list_head_pointer = next_token_index;
5714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      rec->best_token_for_node[token->FSMnode_index] = MAXftokenID;
5724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      free_fsmnode_token(rec, token_index);
5734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      num_deleted++;
5744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
5754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    else
5764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
5774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      list_head_pointer = &token->next_token_index;
5784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
5794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    token_index = next_token_index;
5804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    token = &(rec->fsmnode_token_array[token_index]);
5814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
5824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
5834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*this is called when we run out of room in the state token arrays and need to make more room -
5864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project it only prunes in theh new time slice - we could also look at pruning the previous slice if needed*/
5874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic costdata reprune_fsmnode_tokens(srec *rec, costdata current_best_cost, costdata current_prune_delta,
5904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                       ftokenID not_this_one)
5914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
5924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*first check to see if current pruning thresholds make enough
5944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    room (because of better max)*/
5954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  prune_fsmnode_tokens(rec, current_best_cost+current_prune_delta, not_this_one);
5974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ASSERT((float)current_best_cost + (float)current_prune_delta < (float)SHRT_MAX);
5994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  while (rec->fsmnode_token_freelist == MAXftokenID)
6014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
6024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    SREC_STATS_INC_FTOKEN_REPRUNES(1);
6034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    current_prune_delta = (costdata)(PRUNE_TIGHTEN * current_prune_delta);
6054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (current_prune_delta <= 1)
6074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
6084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      /*this seems like an unlikely case, but if we can't prune enough to make room, give up
6094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      on the utterance (better than being stuck here forever!)*/
6104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      /*FIX replace with crec abort mechanism*/
6124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      PLogError ("reprune_fsmnode_tokens: can't seem to prune enough - best cost %d\n",
6134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project             current_best_cost);
6144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      print_fsmnode_token_list(rec, rec->active_fsmnode_tokens, "CANNOT PRUNE: ");
6164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      dump_core("reprune_fsmnode_tokens() died\n");
6184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
6194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    prune_fsmnode_tokens(rec, current_best_cost+current_prune_delta, not_this_one);
6214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ASSERT((float)current_best_cost + (float)current_prune_delta < (float)USHRT_MAX);
6224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
6234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return current_prune_delta;
6254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
6264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectvoid reset_best_cost_to_zero(srec* rec, costdata current_best_cost)
6294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
6304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fsmarc_token* stoken;
6314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  stokenID token_index;
6324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  short i, num_states;
6334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*do the state tokens*/
6364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (token_index = rec->active_fsmarc_tokens;
6374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       token_index != MAXstokenID;
6384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       token_index = stoken->next_token_index)
6394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
6404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    stoken = &rec->fsmarc_token_array[ token_index];
6424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    num_states = stoken->num_hmm_states;
6434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for (i = 0; i < num_states; i++)
6444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
6454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (stoken->cost[i] < MAXcostdata)
6464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
6474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        ASSERT(stoken->cost[i]  >= current_best_cost);
6484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        stoken->cost[i] = (costdata)(stoken->cost[i] - (costdata) current_best_cost);
6494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
6504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
6514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
6524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
6534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic void reset_cost_offsets(multi_srec* rec, frameID current_frame,
6554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                               costdata current_best_cost)
6564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
6574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  rec->cost_offset_for_frame[current_frame] = current_best_cost;
6584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (current_frame == 0)
6594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    rec->accumulated_cost_offset[current_frame] = current_best_cost;
6604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else
6614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    rec->accumulated_cost_offset[current_frame] = rec->accumulated_cost_offset[current_frame-1] + current_best_cost;
6624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
6634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*--------------------------------------------------------------------------*
6664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                          *
6674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * word_token functions                                                     *
6684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                          *
6694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *--------------------------------------------------------------------------*/
6704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*this function allocates a new word token and remembers it in a list in the srec structure (to be used for backtrace later on*/
6724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic wtokenID create_word_token(srec *rec)
6744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
6754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  wtokenID word_token_index;
6764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  word_token *word_token;
6774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  word_token_index = get_free_word_token(rec, NULL_IF_NO_TOKENS);
6794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (0 && word_token_index == MAXwtokenID)
6814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
6824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /*FIX - use crec error handling*/
6834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    dump_core("create_word_token: cannot allocate word token - we need"
6844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              " to figure out a word pruning strategy when this happens!\n");
6854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
6864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  word_token = &(rec->word_token_array[word_token_index]);
6884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return word_token_index;
6904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
6914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/* gets rid of fsmnode which trace back to this word since
6934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   the word is not goingto make it ono the word lattice */
6944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic int block_fsmnodes_per_backtrace(srec *rec, wtokenID wtoken_id)
6964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
6974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int num_ftokens_blocked = 0;
6984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ftokenID current_token_index = rec->active_fsmnode_tokens;
6994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  while (current_token_index != MAXftokenID) {
7004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    fsmnode_token *token = &(rec->fsmnode_token_array[current_token_index]);
7014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	if (token->word_backtrace == wtoken_id) {
7024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      num_ftokens_blocked++;
7034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      token->cost = MAXcostdata;
7044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	}
7054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	current_token_index = token->next_token_index;
7064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
7074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return num_ftokens_blocked;
7084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
7094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/* processing a word boundary,
7114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   current_token is the fsmnode_token to the left of the boundary
7124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   cost is the cost through this frame
7134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   pcurrent_word_threshold is the worst score for words on the prio.q
7144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   returns the word_token index just created
7154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project*/
7164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic wtokenID srec_process_word_boundary_nbest(srec* rec,
7174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    nodeID end_node,
7184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    wordID word,
7194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    wtokenID word_backtrace,
7204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    costdata cost,
7214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    costdata* pcurrent_word_threshold,
7224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    int *any_nodes_blocked)
7234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
7244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  wtokenID wtoken_index;
7254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  wtokenID return_wtoken_index;
7264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  wtokenID token_id_to_remove;
7274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  word_token* wtoken;
7294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (word_backtrace != MAXwtokenID)
7314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
7324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    word_token* btoken = &rec->word_token_array[word_backtrace];
7334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (btoken->end_time >= rec->current_search_frame)
7344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
7354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      SREC_STATS_INC_BAD_BACKTRACES();
7364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      return MAXwtokenID;
7374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
7384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
7394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*make new word token*/
7404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  wtoken_index = create_word_token(rec);
7414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  //ASSERT(wtoken_index != MAXwtokenID);
7424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (wtoken_index == MAXwtokenID)
7434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
7444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /* we could have called reprune_word_tokens() here, but we instead called it
7454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       at the beginning of do_epsilon_updates() to avoid complications of
7464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       re-pruning word tokens too deep in the search update */
7474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return_wtoken_index = MAXwtokenID;
7484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return return_wtoken_index;
7494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
7504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  wtoken = &(rec->word_token_array[wtoken_index]);
7524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  wtoken->word = word;
7534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  wtoken->_word_end_time = 0; // new
7544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  wtoken->end_time = rec->current_search_frame;
7554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  wtoken->end_node = end_node;
7564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  wtoken->backtrace = word_backtrace;
7574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  wtoken->cost = cost;
7584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  token_id_to_remove = add_word_token_to_priority_q(rec->word_priority_q, wtoken_index, rec->word_token_array);
7604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (token_id_to_remove == wtoken_index)
7624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return_wtoken_index = MAXwtokenID;
7634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else
7644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
7654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /* the word was truly added to the priority q, so we must
7664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       get the new worst word on that list */
7674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    *pcurrent_word_threshold = get_priority_q_threshold(rec->word_priority_q, rec->word_token_array);
7684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return_wtoken_index = wtoken_index;
7694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
7704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (token_id_to_remove != MAXwtokenID)
7724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
7734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /* Jean: must allow for this word_token to be recycled */
7744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /* ok, the word won't we maintained, so there's no point to
7764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       continue to search this path (as headed by this fsmarc_token) */
7774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      *any_nodes_blocked += block_fsmnodes_per_backtrace( rec, token_id_to_remove);
7794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /* we killed the fsmnode token associated with the word being removed.
7814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       But, we didn't kill it's word backtrace, so there may be word tokens
7824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       in the backtrace which cannot connect.  But we can't really kill
7834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       the whole backtrace since it might be shared with other
7844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       active states, Mike's idea is to add a counter on the
7854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       word_tokens, which counts how many active paths are using
7864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       this word_token ... TODO */
7874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /* print_word_token(rec, token_id_to_remove, "srec_process_word_boundary killed wtoken "); */
7894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    free_word_token(rec, token_id_to_remove);
7904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
7924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return return_wtoken_index;
7934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
7944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectftokenID* srec_get_parent_for_active_fsmnode(srec* rec, ftokenID ftoken_index)
7964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
7974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ftokenID* parent_ftoken_index = &rec->active_fsmnode_tokens;
7984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  while( (*parent_ftoken_index) != MAXftokenID) {
7994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    fsmnode_token* parent_ftoken = &rec->fsmnode_token_array[ *parent_ftoken_index];
8004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if( *parent_ftoken_index == ftoken_index)
8014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project		return parent_ftoken_index;
8024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    parent_ftoken_index = &parent_ftoken->next_token_index;
8034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
8044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return NULL;
8054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
8064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*---------------------------------------------------------------------------*
8084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                           *
8094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * updates                                                                   *
8104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                           *
8114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *---------------------------------------------------------------------------*/
8124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*handles epsilon transitions (used for word boundaries).  Epsilons come from active
8154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fsmnode tokens and maximize into new FSMnode tokens (finds the best path to an FSM
8164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  node).
8174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  When we hit an
8194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  epsilon, create a word token, put it in the path, and remember it in a
8204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  list of all word tokens*/
8214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic int do_epsilon_updates(srec *rec, costdata prune_delta,
8234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                              costdata best_cost)
8244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
8254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fsmnode_token *new_ftoken;
8264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fsmnode_token *current_ftoken;
8274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  wtokenID wtoken_index;
8284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  FSMnode* fsm_node;
8294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  FSMarc* fsm_arc;
8304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  costdata cost, cost_with_wtw;
8314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ftokenID new_ftoken_index;
8324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ftokenID current_ftoken_index;
8334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  costdata current_word_threshold;
8344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  arcID fsm_arc_index;
8354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  wordID word_with_wtw;
8364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int num_fsm_nodes_updated=0, num_fsm_nodes_blocked, num_fsm_nodes_blocked2;
8374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int num_wtokens_maybe_homonyms;
8384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  costdata current_prune_delta;
8394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  costdata current_prune_thresh;
8404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  altword_token* awtoken;
8414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // printf("FRAME %d\n", rec->current_search_frame);
8444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // print_fsmnode_token_list(rec, rec->active_fsmnode_tokens, "BEFORE UPDATE_EPSILONS ACTIVE_FSMNODE_TOKENS: \n");
8454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  current_word_threshold = MAXcostdata;
8474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  current_prune_delta = prune_delta;
8484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  current_prune_thresh = best_cost + current_prune_delta;
8494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  current_ftoken_index = rec->active_fsmnode_tokens;
8514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  while (current_ftoken_index != MAXftokenID)
8524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
8534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	//  print_fsmnode_token(rec, current_ftoken_index, "processing ... ");
8544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    current_ftoken = &(rec->fsmnode_token_array[current_ftoken_index]);
8554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    cost = current_ftoken->cost; /*get last state of token*/
8574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    fsm_node = &rec->context->FSMnode_list[current_ftoken->FSMnode_index];
8584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    fsm_arc = NULL;
8594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /* Jean: see below too, let's remember the wtoken_index we create in
8614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       case we need to re-use it.  All N epsilon updates, and all M
8624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       M outgoing arcs can share, cuz this is the same arriving arc@frame */
8634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    wtoken_index = MAXwtokenID;
8654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if( cost >= current_prune_thresh) {
8674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      ftokenID* parent_ftoken_index;
8684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      // the srec_get_parent_for_active_fsmnode() functions can be
8694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      // gotten rid of if we use a doubly-linked list (fwd/bwd ptrs)
8704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      parent_ftoken_index = srec_get_parent_for_active_fsmnode( rec, current_ftoken_index);
8714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if(!parent_ftoken_index) {
8724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	PLogError( ("Error: internal search error near %s %d, finding %d\n"), __FILE__, __LINE__, current_ftoken_index);
8734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	print_fsmnode_token_list(rec, rec->active_fsmnode_tokens, "in DO_UPDATE_EPSILONS ACTIVE_FSMNODE_TOKENS: \n");
8744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	exit(1);
8754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
8764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      *parent_ftoken_index = current_ftoken->next_token_index;
8774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      // effectively release this fsmnode_token and go to next one
8784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      rec->best_token_for_node[ current_ftoken->FSMnode_index] = MAXftokenID;
8794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      free_fsmnode_token( rec, current_ftoken_index);
8804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      current_ftoken_index = *parent_ftoken_index;
8814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      continue;
8824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
8834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    num_fsm_nodes_updated++;
8854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    num_fsm_nodes_blocked = 0;
8864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    num_wtokens_maybe_homonyms = 0;
8874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for (fsm_arc_index = fsm_node->un_ptr.first_next_arc;
8884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	 fsm_arc_index != MAXarcID;
8894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	 fsm_arc_index = fsm_arc->linkl_next_arc)
8904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
8914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        fsm_arc = &rec->context->FSMarc_list[ fsm_arc_index];
8924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        /* consider only epsilon transitions */
8944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (fsm_arc->ilabel >= EPSILON_OFFSET)
8954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          continue;
8964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        /* can't loop to yourself on epsilon! */
8984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        ASSERT(fsm_arc->to_node != current_ftoken->FSMnode_index);
8994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        cost_with_wtw = current_ftoken->cost + fsm_arc->cost; /* WTW */
9014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        word_with_wtw = current_ftoken->word;
9024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if(fsm_arc->olabel != WORD_EPSILON_LABEL)
9034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          word_with_wtw = fsm_arc->olabel ;
9044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        // we should compare cost_with_wtw but let's let the priority_q
9064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	// do the pruning
9074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	if (cost>=current_prune_thresh || fsm_arc->cost>=current_prune_thresh)
9084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  continue;
9094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        /*if word boundary, see if it crosses the word end threshold*/
9114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        /* no room on the word priority_q, so not worth pursuing */
9124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (fsm_arc->ilabel == WORD_BOUNDARY && cost_with_wtw >= current_word_threshold) {
9134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          continue; // goto NEXT_FTOKEN;
9144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
9154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project		new_ftoken = NULL;
9174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        new_ftoken_index = rec->best_token_for_node[ fsm_arc->to_node];
9184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if(new_ftoken_index != MAXftokenID)
9194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          new_ftoken = &rec->fsmnode_token_array[ new_ftoken_index];
9204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if( new_ftoken && (current_ftoken->cost+fsm_arc->cost)<new_ftoken->cost) {
9214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          /* clobber it */
9224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        } else if(new_ftoken) {
9234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          /* merge it */
9244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        } else if(rec->fsmnode_token_freelist == MAXftokenID) {
9254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	        /* create it? maybe  */
9264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project			current_prune_delta = reprune_fsmnode_tokens(rec, best_cost, current_prune_delta, current_ftoken_index);
9274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project		    current_prune_thresh = best_cost + current_prune_delta;
9284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
9294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (fsm_arc->ilabel == WORD_BOUNDARY) {
9314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          /* 20030920, for sure the backtrace will change! */
9324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          // token->word_backtrace = MAXwtokenID;
9334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          wtoken_index = srec_process_word_boundary_nbest(rec,
9354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project						 current_ftoken->FSMnode_index,
9364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                                 word_with_wtw,
9374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                                 current_ftoken->word_backtrace,
9384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                                 cost_with_wtw,
9394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                                 &current_word_threshold,
9404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                                 &num_fsm_nodes_blocked);
9414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project		  if (wtoken_index != MAXwtokenID) {
9424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            WORD_TOKEN_SET_WD_ETIME( (rec->word_token_array+wtoken_index),
9434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              rec->word_token_array[wtoken_index].end_time - current_ftoken->silence_duration);
9444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project		  }
9454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project		  if( fsm_arc->olabel!=WORD_EPSILON_LABEL && wtoken_index != MAXwtokenID) {
9464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project			  num_wtokens_maybe_homonyms++;
9474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project			  if( num_wtokens_maybe_homonyms>1)
9484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project				WORD_TOKEN_SET_HOMONYM( (rec->word_token_array+wtoken_index), 1);
9494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project		  }
9504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          /* now drop alternative words, note the use of current_token
9514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project             because token is on the other side already */
9524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          if (current_ftoken->aword_backtrace != AWTNULL) {
9534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            awtoken = current_ftoken->aword_backtrace;
9544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            for (; awtoken != AWTNULL; awtoken = awtoken->next_token) {
9554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              wtokenID wti;
9564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              wti = srec_process_word_boundary_nbest(rec,
9574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project						     current_ftoken->FSMnode_index,
9584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                                     awtoken->word,
9594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                                     awtoken->word_backtrace,
9604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                                     cost_with_wtw + awtoken->costdelta,
9614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                                     &current_word_threshold,
9624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                                     &num_fsm_nodes_blocked2);
9634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            }
9644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            /* if we don't free the altwords here, i had thought that
9654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project               updates from stateN would make the altwords grow and grow,
9664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project               but by that time all the fsmnodes are brand new */
9674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            /* leaving them alive allows them to propagate to state0 thru
9684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project               other epsilons (eg non .wb) to new nodes but we don't
9694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project               use such arcs.
9704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project               the .wb would not get dropped again 'cuz we check
9714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project               for that in wtoken_index above.
9724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project               this is quite complex and the case for dropping word_tokens
9734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project               from the node AFTER the .wb can be made
9744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project               ie. would need a re-write of do_epsilon_updates() */
9754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project			if( current_ftoken->aword_backtrace != AWTNULL)
9764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              free_altword_token_batch(rec, current_ftoken->aword_backtrace);
9774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            current_ftoken->aword_backtrace = AWTNULL;
9784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            /*print_fsmnode_token(rec, token-rec->fsmnode_token_array, "123a");*/
9794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          }
9804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          if( wtoken_index != MAXwtokenID) {
9824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            if( new_ftoken == NULL) {
9844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              /* create token for the other side */
9854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              new_ftoken_index = get_free_fsmnode_token(rec, NULL_IF_NO_TOKENS);
9864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project				  // this should not happen because of the above check near
9874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project				  // fsmnode_token_freelist == MAXftokenID
9884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              ASSERT(new_ftoken_index != MAXftokenID);
9894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              new_ftoken = &(rec->fsmnode_token_array[new_ftoken_index]);
9904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              new_ftoken->word_backtrace = wtoken_index;
9914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              new_ftoken->cost = cost_with_wtw;
9924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              new_ftoken->word = WORD_EPSILON_LABEL;
9934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              new_ftoken->FSMnode_index = fsm_arc->to_node;
9944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              new_ftoken->aword_backtrace = AWTNULL;
9954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              new_ftoken->next_token_index = current_ftoken->next_token_index;
9964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              current_ftoken->next_token_index = new_ftoken_index;
9974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              rec->best_token_for_node[fsm_arc->to_node] = new_ftoken_index;
9984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            } else if(new_ftoken && cost_with_wtw<new_ftoken->cost) {
9994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              /* update token on the other side */
10004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              ftokenID *parent_ftoken_index;
10014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              new_ftoken = &(rec->fsmnode_token_array[new_ftoken_index]);
10024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              new_ftoken->cost = cost_with_wtw;
10034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              new_ftoken->word_backtrace = wtoken_index;
10044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              new_ftoken->word = WORD_EPSILON_LABEL;
10054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              // unchanged token->FSMnode_index = fsm_arc->to_node;
10064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              // because this token was updated, we need to reprocess it, right after
10074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              parent_ftoken_index = srec_get_parent_for_active_fsmnode( rec, new_ftoken_index);
10084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              if(!parent_ftoken_index) {
10094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project		PLogError( ("Error: internal search error near %s %d, finding %d\n"), __FILE__, __LINE__, new_ftoken_index);
10104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project		print_fsmnode_token_list(rec, rec->active_fsmnode_tokens, "in DO_UPDATE_EPSILONS ACTIVE_FSMNODE_TOKENS: \n");
10114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project		exit(1);
10124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              }
10134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              *parent_ftoken_index = new_ftoken->next_token_index;
10144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              new_ftoken->next_token_index = current_ftoken->next_token_index;
10154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              current_ftoken->next_token_index = new_ftoken_index;
10164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              rec->best_token_for_node[ fsm_arc->to_node] = new_ftoken_index;
10174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	      /* new_ftoken->aword_backtrace must be null, alts here were
10184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project		 processed and dropped in srec_process_word_boundary_nbest() */
10194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              if(new_ftoken->aword_backtrace != AWTNULL) {
10204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project		PLogError( ("Error: internal search error near %s %d\n"), __FILE__, __LINE__);
10214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project		continue;
10224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              }
10234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            } else {
10244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              /* token on other side is same or better, just leave it */
10254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            }
10264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          }
10274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
10284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        else if(fsm_arc->ilabel == EPSILON_LABEL) {
10294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          if( new_ftoken == NULL) {
10304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            /* create token for the other side */
10314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            new_ftoken_index = get_free_fsmnode_token(rec, NULL_IF_NO_TOKENS);
10324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project			// this should not happen because of the above check near
10334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project			// fsmnode_token_freelist == MAXftokenID
10344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            ASSERT(new_ftoken_index != MAXftokenID);
10354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            new_ftoken = &(rec->fsmnode_token_array[new_ftoken_index]);
10364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            new_ftoken->word_backtrace = current_ftoken->word_backtrace;
10374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            new_ftoken->cost = cost_with_wtw;
10384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            new_ftoken->word = word_with_wtw;
10394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            new_ftoken->FSMnode_index = fsm_arc->to_node;
10404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            new_ftoken->aword_backtrace = refcopy_altwords(rec, current_ftoken->aword_backtrace);
10414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            new_ftoken->next_token_index = current_ftoken->next_token_index;
10424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            current_ftoken->next_token_index = new_ftoken_index;
10434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            rec->best_token_for_node[fsm_arc->to_node] = new_ftoken_index;
10444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          } else if(new_ftoken && cost_with_wtw<new_ftoken->cost) {
10454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            /* update token on the other side */
10464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            ftokenID *parent_ftoken_index;
10474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            new_ftoken = &(rec->fsmnode_token_array[new_ftoken_index]);
10484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            new_ftoken->cost = cost_with_wtw;
10494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            new_ftoken->word_backtrace = current_ftoken->word_backtrace;
10504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            new_ftoken->word = word_with_wtw;
10514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	    /* here we are giving up the path and alternatives that existed at
10524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	       this node, which is not great! The new (better) top choice
10534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	       coming in and it's alternatives are propagated instead.
10544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	       TODO: merge the alternative lists and the previous top choice
10554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	    */
10564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	    if(new_ftoken->aword_backtrace!=AWTNULL)
10574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              free_altword_token_batch( rec, new_ftoken->aword_backtrace);
10584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	    new_ftoken->aword_backtrace = AWTNULL;
10594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            new_ftoken->aword_backtrace = refcopy_altwords(rec, current_ftoken->aword_backtrace);
10604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            // unchanged token->FSMnode_index = fsm_arc->to_node;
10614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            // because this token was updated, we need to re-process it, right after
10624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            parent_ftoken_index = srec_get_parent_for_active_fsmnode( rec, new_ftoken_index);
10634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            if(!parent_ftoken_index) {
10644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	      PLogError( ("Error: internal search error near %s %d, finding %d\n"), __FILE__, __LINE__, new_ftoken_index);
10654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	      print_fsmnode_token_list(rec, rec->active_fsmnode_tokens, "in DO_UPDATE_EPSILONS ACTIVE_FSMNODE_TOKENS: \n");
10664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	      exit(1);
10674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            }
10684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            *parent_ftoken_index = new_ftoken->next_token_index;
10694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            new_ftoken->next_token_index = current_ftoken->next_token_index;
10704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            current_ftoken->next_token_index = new_ftoken_index;
10714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            rec->best_token_for_node[ fsm_arc->to_node] = new_ftoken_index;
10724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          } else {
10734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            /* token on other side is same or better, just leave it */
10744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	    /* todo: maybe merge alternative lists? */
10754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          }
10764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
10774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      } /* loop over arcs */
10784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
10794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      ASSERT( current_ftoken->cost != MAXcostdata);
10804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if( num_fsm_nodes_blocked) {
10814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        /* we do not want to propagate fsm node tokens for paths that have
10824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project           just been killed on the basis of no space for word propagation */
10834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        prune_fsmnode_tokens(rec, MAXcostdata/2, current_ftoken_index);
10844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
10854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
10864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    // NEXT_FTOKEN:
10874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      current_ftoken_index = current_ftoken->next_token_index;
10884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
10894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
10904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // print_fsmnode_token_list(rec, rec->active_fsmnode_tokens, "AFTER UPDATE_EPSILONS ACTIVE_FSMNODE_TOKENS: \n");
10914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
10924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  sanity_check_altwords(rec, rec->altword_token_freelist);
10934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return num_fsm_nodes_updated;
10944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
10954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
10964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic void update_internal_hmm_states(srec *rec, costdata *pcurrent_prune_delta,
10974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                       costdata *pcurrent_best_cost,
10984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                       costdata *precomputed_model_scores)
10994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
11004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  stokenID current_token_index;
11014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fsmarc_token *current_token;
11024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  costdata current_best_cost;
11034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  costdata current_prune_thresh;
11044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  costdata current_prune_delta;
11054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  costdata model_cost;
11064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  asr_int16_t any_alive;
11074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  HMMInfo *hmm_info;
11084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  modelID model_index;
11094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  asr_int16_t internal_state, end_state;
11104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  arcID fsm_arc_index;
11114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  FSMarc* fsm_arc;
11124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
11134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  costdata prev_cost;
11144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  costdata self_loop_cost;
11154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
11164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  current_best_cost = *pcurrent_best_cost;
11174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  current_prune_delta = *pcurrent_prune_delta;
11184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  current_prune_thresh = current_best_cost + current_prune_delta;
11194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
11204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ASSERT(((float)current_best_cost + current_prune_delta) < (float)USHRT_MAX);
11214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
11224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* best_token_for_arc must be reset here, cuz the same array might have
11234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     been used by another gender.  Alternatively we could have let each
11244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     recog use it's own array thereby save cpu at expense of memory */
11254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (fsm_arc_index = 0; fsm_arc_index < rec->context->num_arcs; fsm_arc_index++)
11264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    rec->best_token_for_arc[fsm_arc_index] = MAXstokenID;
11274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
11284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  current_token_index = rec->active_fsmarc_tokens;
11294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  while (current_token_index != MAXstokenID)
11304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
11314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    current_token = &(rec->fsmarc_token_array[current_token_index]);
11324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
11334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    fsm_arc_index = current_token->FSMarc_index;
11344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    fsm_arc = &rec->context->FSMarc_list[fsm_arc_index];
11354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
11364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /* best_token_for_arc must be set here, cuz it was reset above */
11374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    rec->best_token_for_arc[fsm_arc_index] = current_token_index;
11384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
11394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    hmm_info = &rec->context->hmm_info_for_ilabel[ fsm_arc->ilabel];
11404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    any_alive = 0;
11414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    end_state = current_token->num_hmm_states - 1;
11424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
11434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for (internal_state = end_state; internal_state >= 0; internal_state--)
11444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
11454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
11464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      model_index = hmm_info->state_indices[internal_state];
11474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      model_cost = precomputed_model_scores[model_index];
11484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
11494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      /*better to come from previous or self?*/
11504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
11514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (internal_state > 0)
11524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
11534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        prev_cost = current_token->cost[internal_state-1];
11544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                /* a duration model can be applied here,
11554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                   by changing the prev_cost according to some function of
11564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                     the current_token->duration[internal_state-1] rec->avg_state_durations[ prev_model_index] */
11574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (prev_cost < current_prune_thresh)
11584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        {
11594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	  modelID prev_model_index;
11604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          prev_cost = (costdata)(prev_cost + (costdata) model_cost);
11614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          /* apply duration model for "next" transition, note that it's nice
11624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project             to access the duration model (avg_state_durations) somehwere
11634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project             other than the acoustic models which could be far away in memory
11644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project             arrive penalty would be applied here too if it was reqd */
11654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
11664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          prev_model_index = hmm_info->state_indices[internal_state-1];
11674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          prev_cost = (costdata)(prev_cost + (costdata) duration_penalty_depart(rec->avg_state_durations[ prev_model_index],
11684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                 current_token->duration[internal_state-1]));
11694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
11704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
11714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
11724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      else
11734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
11744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        prev_cost = MAXcostdata;
11754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
11764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
11774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      self_loop_cost = current_token->cost[internal_state];
11784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                /* a duration model can be applied here,
11794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                   by changing the self_loop_cost according to some function of
11804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                     the current_token->duration[internal_state] rec->avg_state_durations[ prev_model_index] */
11814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (self_loop_cost < current_prune_thresh)
11824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
11834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        self_loop_cost = (costdata)(self_loop_cost + (costdata) model_cost);
11844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        /* apply duration model for "loop" transition */
11854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
11864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        self_loop_cost = (costdata)(self_loop_cost + (costdata) duration_penalty_loop(rec->avg_state_durations[ model_index],
11874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                    current_token->duration[internal_state]));
11884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
11894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
11904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
11914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (prev_cost < self_loop_cost)
11924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
11934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        current_token->cost[internal_state] = prev_cost;
11944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        current_token->word_backtrace[internal_state] = current_token->word_backtrace[internal_state-1];
11954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        current_token->word[internal_state] = current_token->word[internal_state-1];
11964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                current_token->duration[internal_state] = 1;
11974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (current_token->word[internal_state-1] != MAXwordID)
11984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        {
11994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          if (current_token->aword_backtrace[internal_state] != AWTNULL)
12004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            free_altword_token_batch(rec,
12014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                     current_token->aword_backtrace[internal_state]);
12024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          current_token->aword_backtrace[internal_state] = refcopy_altwords(rec, current_token->aword_backtrace[internal_state-1]);
12034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          /*print_fsmarc_token(rec, current_token_index, "123c");*/
12044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
12054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        else
12064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        {
12074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          /* if there's no top choice, there shouldn't be alternatives! */
12084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          ASSERT(current_token->aword_backtrace[internal_state] == AWTNULL);
12094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          ASSERT(current_token->aword_backtrace[internal_state-1] == AWTNULL);
12104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
12114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
12124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      else
12134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
12144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        current_token->cost[internal_state] = self_loop_cost;
12154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                current_token->duration[internal_state]++;
12164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
12174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
12184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (current_token->cost[internal_state] < current_prune_thresh)
12194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
12204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        any_alive = 1;
12214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (current_token->cost[internal_state] < current_best_cost)
12224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        {
12234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          current_best_cost = current_token->cost[internal_state];
12244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          current_prune_thresh = current_best_cost + current_prune_delta;
12254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
12264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
12274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
12284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    current_token_index = current_token->next_token_index;
12294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
12304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  *pcurrent_best_cost = current_best_cost;
12314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  *pcurrent_prune_delta = current_prune_delta;
12324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
12334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
12344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
12354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
12364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
12374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic int GetNumArcsArrivingClip2(srec_context* context, FSMnode* fsm_node)
12384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
12394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  arcID fpa = fsm_node->first_prev_arc;
12404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  FSMarc* arc;
12414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
12424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (fpa == MAXarcID)
12434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return 0;
12444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  arc = &context->FSMarc_list[fpa];
12454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (arc->linkl_prev_arc == MAXarcID)
12464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return 1;
12474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else
12484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return 2;
12494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
12504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
12514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic int update_from_hmms_to_fsmnodes(srec *rec, costdata prune_delta, costdata best_cost)
12524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
12534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  stokenID current_token_index;
12544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fsmarc_token *current_token;
12554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int end_state;
12564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  costdata end_cost;
12574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  costdata current_prune_thresh;
12584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  costdata current_prune_delta;  /*may get tighter to keep num fsmnodes under control*/
12594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // vFSMarc vfsm_arc;
12604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  FSMarc* fsm_arc;
12614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  FSMnode* fsm_node;
12624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // vFSMnode vfsm_node;
12634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  arcID fsm_arc_index;
12644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  nodeID to_node_index;
12654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ftokenID new_ftoken_index;
12664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fsmnode_token *ftoken;
12674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  modelID end_model_index;
12684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  labelID ilabel;
12694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  short end_cost_equality_hack;
12704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  HMMInfo* hmm_info;
12714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  altword_token *awtoken, *q;
12724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int num_fsmnode_updates = 0;
12734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
12744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  current_prune_delta = prune_delta;
12754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  current_prune_thresh = best_cost + current_prune_delta;
12764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  current_token_index = rec->active_fsmarc_tokens;
12774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
12784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (ilabel = 0; ilabel < NODE_INFO_NUMS; ilabel++)
12794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
12804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    rec->current_best_ftoken_cost[ilabel] = MAXcostdata / 2;
12814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    rec->current_best_ftoken_index[ilabel] = MAXftokenID;
12824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
12834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  sanity_check_altwords(rec, rec->altword_token_freelist);
12844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
12854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  while (current_token_index != MAXstokenID)
12864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
12874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    current_token = &(rec->fsmarc_token_array[current_token_index]);
12884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
12894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /*propagate from end of state token to new FSM node*/
12904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    end_state = (char) current_token->num_hmm_states - 1;
12914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
12924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ASSERT((current_token->aword_backtrace[end_state] == AWTNULL)
12934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project           || (current_token->word[end_state] != MAXwordID));
12944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    end_cost = current_token->cost[end_state];
12954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
12964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /* anticipated repruning: make sure there is enough space before
12974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       beginning complex computation */
12984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (rec->word_priority_q->max_in_q>1 && rec->altword_token_freelist_len < 3*rec->word_priority_q->max_in_q)
12994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      reprune_altword_tokens(rec);
13004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
13014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (end_cost < current_prune_thresh)
13024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
13034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      num_fsmnode_updates++;
13044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      fsm_arc_index = current_token->FSMarc_index;
13054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      fsm_arc = &rec->context->FSMarc_list[ fsm_arc_index];
13064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
13074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      hmm_info = &rec->context->hmm_info_for_ilabel[ fsm_arc->ilabel];
13084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
13094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      end_model_index = hmm_info->state_indices[end_state];
13104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
13114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      end_cost = (costdata)(end_cost + (costdata) duration_penalty_depart(rec->avg_state_durations[end_model_index],
13124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                            current_token->duration[end_state]));
13134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      to_node_index = fsm_arc->to_node;
13144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      new_ftoken_index = rec->best_token_for_node[to_node_index];
13154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (new_ftoken_index == MAXftokenID)
13164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
13174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        /*we need to make sure there is room in the new_states array
13184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          and there are free state tokens*/
13194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (rec->fsmnode_token_freelist == MAXftokenID)
13204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        {
13214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          /*make sure there is room for another FSMnode token
13224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            - if not, prune until there is room*/
13234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          current_prune_delta = reprune_fsmnode_tokens(rec, best_cost, current_prune_delta, MAXftokenID);
13244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          current_prune_thresh = best_cost + current_prune_delta;
13254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
13264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
13274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        /*because of the above check, this should always succeed*/
13284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        new_ftoken_index = get_free_fsmnode_token(rec, EXIT_IF_NO_TOKENS);
13294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
13304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        ftoken = &(rec->fsmnode_token_array[new_ftoken_index]);
13314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        ftoken->FSMnode_index = to_node_index;
13324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        ftoken->next_token_index = rec->active_fsmnode_tokens;
13334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        ftoken->cost = end_cost;
13344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        ftoken->word_backtrace = current_token->word_backtrace[end_state];
13354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        ftoken->word = current_token->word[end_state];
13364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (end_model_index == SILENCE_MODEL_INDEX && ftoken->word != rec->context->beg_silence_word)
13374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        {
13384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          ftoken->silence_duration = current_token->duration[end_state];
13394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
13404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        else
13414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        {
13424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          ftoken->silence_duration = 0;
13434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
13444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (ftoken->word != MAXwordID)
13454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        {
13464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          arcID narr;
13474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          fsm_node = &rec->context->FSMnode_list[ fsm_arc->to_node];
13484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          /* when there is only one arc arriving, a refcopy is good enough
13494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project             and saves memory */
13504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          narr = (arcID) GetNumArcsArrivingClip2(rec->context, fsm_node);
13514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          if (narr > 1)
13524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            ftoken->aword_backtrace = copy_altwords(rec, current_token->aword_backtrace[end_state], 0);
13534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          else
13544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            ftoken->aword_backtrace = refcopy_altwords(rec, current_token->aword_backtrace[end_state]);
13554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
13564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        else
13574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        {
13584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          /* if there's no top choice, there shouldn't be alternatives! */
13594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          ASSERT(current_token->aword_backtrace[end_state] == AWTNULL);
13604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          ftoken->aword_backtrace = AWTNULL;
13614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
13624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        rec->active_fsmnode_tokens = new_ftoken_index;
13634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        rec->best_token_for_node[to_node_index] = new_ftoken_index;
13644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
13654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      else /* a token already exists, use it! */
13664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
13674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
13684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        ftoken = &(rec->fsmnode_token_array[new_ftoken_index]);
13694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        ASSERT( ((current_token->word[end_state] == MAXwordID) && (ftoken->word == MAXwordID))
13704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project             || ((current_token->word[end_state] != MAXwordID) && (ftoken->word != MAXwordID)) );
13714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
13724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        /* this is a hack for preferring the shorter of the backtrace words
13734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project           when scores are equal, used to prefer longer pau2 word */
13744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        end_cost_equality_hack = 0;
13754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (end_cost == ftoken->cost)
13764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        {
13774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          if (current_token->word_backtrace[end_state] != ftoken->word_backtrace
13784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              && current_token->word_backtrace[end_state] != MAXwtokenID)
13794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          {
13804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            frameID ct_end_time = MAXframeID, et_end_time = 0;
13814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            if (current_token->word_backtrace[end_state] != MAXwtokenID)
13824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              ct_end_time = rec->word_token_array[current_token->word_backtrace[end_state]].end_time;
13834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            if (ftoken->word_backtrace != MAXwtokenID)
13844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              et_end_time = rec->word_token_array[ftoken->word_backtrace].end_time;
13854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            if (ct_end_time < et_end_time)
13864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              end_cost_equality_hack = 1;
13874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          }
13884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
13894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
13904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (end_cost < ftoken->cost || end_cost_equality_hack)
13914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        {
13924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          /* new one coming in is better, so push the current state down */
13934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          /* ftoken info goes into awtoken */
13944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          if (ftoken->word != MAXwordID)
13954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          {
13964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            /* copy_altwords() */
13974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            awtoken = get_free_altword_token(rec, NULL_IF_NO_TOKENS);
13984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            if (awtoken != AWTNULL)
13994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            {
14004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              awtoken->costdelta = ftoken->cost - end_cost;
14014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              awtoken->word_backtrace = ftoken->word_backtrace;
14024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              awtoken->word = ftoken->word;
14034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
14044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              /* ensure full ownership! */
14054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              q = ftoken->aword_backtrace;
14064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              if (q != AWTNULL && q->refcount > 1)
14074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              {
14084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                awtoken->next_token = copy_altwords(rec, ftoken->aword_backtrace, ftoken->cost - end_cost);
14094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                free_altword_token_batch(rec, ftoken->aword_backtrace);
14104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                /* reversed order above here !! */
14114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              }
14124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              else
14134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              {
14144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                awtoken->next_token = ftoken->aword_backtrace;
14154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project				count_altword_token( rec, awtoken);
14164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                for (q = awtoken->next_token; q; q = q->next_token)
14174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                  q->costdelta += ftoken->cost - end_cost;
14184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              }
14194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              ftoken->aword_backtrace = awtoken;
14204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              ftoken->aword_backtrace = sizewise_altwords(rec, ftoken->aword_backtrace);
14214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project			  if( (q=ftoken->aword_backtrace)!=AWTNULL) {
14224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                for (q = ftoken->aword_backtrace; q->next_token; q = q->next_token) ;
14234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                q->next_token = copy_altwords(rec, current_token->aword_backtrace[end_state], 0);
14244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                ftoken->aword_backtrace = sizewise_altwords(rec, ftoken->aword_backtrace);
14254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                /* awtoken->costbasis = &ftoken->cost; */
14264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                ftoken->aword_backtrace->refcount = 1;
14274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project			  }
14284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            }
14294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          }
14304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          else
14314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          {
14324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            /* if there's no top choice, there shouldn't be alternatives! */
14334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            ASSERT(ftoken->aword_backtrace == AWTNULL);
14344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          }
14354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          /* and stoken info goes into ftoken */
14364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          ftoken->cost = end_cost;
14374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          ftoken->word_backtrace = current_token->word_backtrace[end_state];
14384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          ftoken->word = current_token->word[end_state];
14394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          if (end_model_index == SILENCE_MODEL_INDEX && ftoken->word != rec->context->beg_silence_word)
14404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          {
14414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            ftoken->silence_duration = current_token->duration[end_state];
14424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          }
14434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          else
14444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          {
14454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            ftoken->silence_duration = 0;
14464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          }
14474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
14484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        else
14494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        {
14504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                    /* new arc arriving is worse */
14514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          /* print_fsmarc_token(rec, current_token_index, "new_arc_arriving worse");
14524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project             print_fsmnode_token(rec, new_ftoken_index, "new_arc_arriving tonode");*/
14534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          /* append it to the alt list */
14544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          /* stoken info goes into the awtoken, ftoken unchanged */
14554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          if (ftoken->word != MAXwordID)
14564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          {
14574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            /* copy_altwords() */
14584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            awtoken = get_free_altword_token(rec, NULL_IF_NO_TOKENS);
14594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            if (awtoken != AWTNULL)
14604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            {
14614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              awtoken->costdelta = end_cost - ftoken->cost;
14624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              awtoken->word = current_token->word[end_state];
14634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              awtoken->word_backtrace = current_token->word_backtrace[end_state];
14644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
14654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              if (current_token->aword_backtrace[end_state] != AWTNULL)
14664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                awtoken->next_token = copy_altwords(rec,
14674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                                    current_token->aword_backtrace[end_state],
14684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                                    awtoken->costdelta);
14694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              else
14704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                awtoken->next_token = AWTNULL;
14714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
14724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              /* ensure full ownership!, this is new here! */
14734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              q = ftoken->aword_backtrace;
14744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              if (q != AWTNULL && q->refcount > 1)
14754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              {
14764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                q = copy_altwords(rec, ftoken->aword_backtrace, 0);
14774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                free_altword_token_batch(rec, ftoken->aword_backtrace);
14784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                ftoken->aword_backtrace = q;
14794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              }
14804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            }
14814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            if (ftoken->aword_backtrace)
14824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            {
14834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              for (q = ftoken->aword_backtrace; q->next_token; q = q->next_token) ;
14844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              q->next_token = awtoken;
14854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            }
14864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            else
14874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            {
14884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              ftoken->aword_backtrace = awtoken;
14894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            }
14904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project			if (ftoken->aword_backtrace!=AWTNULL) {
14914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project				ftoken->aword_backtrace->refcount = 1;
14924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project				ftoken->aword_backtrace = sizewise_altwords(rec, ftoken->aword_backtrace);
14934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project			}
14944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          }
14954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
14964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        /*print_fsmnode_token(rec, new_ftoken_index, "123e reused-token ");*/
14974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
14984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      ilabel = rec->context->FSMnode_info_list[ ftoken->FSMnode_index];
14994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      ASSERT(ilabel < NODE_INFO_NUMS);
15004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (ftoken->cost < rec->current_best_ftoken_cost[ilabel])
15014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
15024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        rec->current_best_ftoken_cost[ilabel]  = ftoken->cost;
15034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        rec->current_best_ftoken_index[ilabel] = new_ftoken_index;
15044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
15054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (ftoken->cost < rec->current_best_ftoken_cost[NODE_INFO_UNKNOWN])
15064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
15074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        rec->current_best_ftoken_cost[NODE_INFO_UNKNOWN]  = ftoken->cost;
15084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        rec->current_best_ftoken_index[NODE_INFO_UNKNOWN] = new_ftoken_index;
15094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
15104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      ASSERT(ftoken->word != MAXwordID || ftoken->aword_backtrace == AWTNULL);
15114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
15124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    current_token_index = current_token->next_token_index;
15134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
15144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  sanity_check_altwords(rec, rec->altword_token_freelist);
15154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return num_fsmnode_updates;
15164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
15174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
15184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic int update_from_current_fsm_nodes_into_new_HMMs(srec* rec,
15194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    costdata *pcurrent_prune_delta,
15204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    costdata *pcurrent_best_cost,
15214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    costdata *precomputed_model_scores)
15224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
15234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  costdata prev_cost;
15244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  FSMnode* fsm_node;
15254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  FSMarc*  fsm_arc;
15264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  arcID fsm_arc_index;
15274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  HMMInfo *hmm_info;
15284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  modelID model_index;
15294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fsmarc_token *token;
15304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  stokenID new_token_index = MAXstokenID;
15314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  costdata cost;
15324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  costdata current_prune_thresh;
15334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  costdata current_prune_delta = *pcurrent_prune_delta;
15344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  costdata current_best_cost = *pcurrent_best_cost;
15354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ftokenID ftoken_index;
15364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ftokenID old_ftoken_index;
15374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fsmnode_token *fsmnode_token;
15384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int num_fsm_nodes_updated = 0;
15394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  costdata orig_prune_delta;
15404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
15414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ftoken_index = rec->active_fsmnode_tokens;
15424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
15434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  current_prune_thresh = *pcurrent_best_cost + *pcurrent_prune_delta;
15444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  orig_prune_delta = *pcurrent_prune_delta;
15454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
15464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  sanity_check_altwords(rec, rec->altword_token_freelist);
15474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
15484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  while (ftoken_index != MAXftokenID)
15494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
15504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    fsmnode_token = &rec->fsmnode_token_array[ftoken_index];
15514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
15524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    prev_cost = fsmnode_token->cost; /*get last state of token*/
15534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (fsmnode_token->FSMnode_index == rec->context->end_node)
15544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
15554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      prev_cost = MAXcostdata;
15564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
15574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
15584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (prev_cost < current_prune_thresh)
15594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
15604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      num_fsm_nodes_updated++;
15614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
15624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      fsm_node = &rec->context->FSMnode_list[fsmnode_token->FSMnode_index];
15634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
15644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      /* loop over arcs leaving this fsm_node */
15654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      for (fsm_arc_index = fsm_node->un_ptr.first_next_arc;
15664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project           fsm_arc_index != MAXarcID;
15674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project           fsm_arc_index = fsm_arc->linkl_next_arc)
15684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
15694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        labelID ilabel;
15704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        wordID olabel;
15714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        nodeID nextnode;
15724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
15734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        fsm_arc = &rec->context->FSMarc_list[  fsm_arc_index];
15744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
15754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        ilabel = fsm_arc->ilabel;
15764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        olabel = fsm_arc->olabel;
15774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        nextnode = fsm_arc->to_node;
15784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
15794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (ilabel >= EPSILON_OFFSET)
15804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        {
15814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                    /*so, not an epsilon arc*/
15824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          hmm_info = &rec->context->hmm_info_for_ilabel[ilabel];
15834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
15844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          model_index = hmm_info->state_indices[0];
15854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
15864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          cost = prev_cost + precomputed_model_scores[model_index];
15874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          cost = (costdata)(cost + (costdata) fsm_arc->cost);
15884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
15894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          if (cost < current_prune_thresh)
15904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          {
15914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            /*new node to keep*/
15924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
15934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            /* look for the fsmarc_token* token, into which to maximize, else create new one */
15944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            if (rec->best_token_for_arc[fsm_arc_index] == MAXstokenID)
15954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            {
15964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
15974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              /*make sure there is room for another state token - if not, prune
15984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              until there is room*/
15994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              /*we need to make sure there is room in the new_states array and
16004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              there are free state tokens*/
16014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              if (rec->fsmarc_token_freelist == MAXstokenID)
16024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              {
16034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                current_prune_delta = reprune_new_states(rec, current_best_cost, current_prune_delta);
16044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              }
16054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
16064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              /* because of the above check, this should always succeed */
16074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              new_token_index = setup_free_fsmarc_token(rec, fsm_arc, fsm_arc_index, EXIT_IF_NO_TOKENS);
16084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
16094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              token = &(rec->fsmarc_token_array[new_token_index]);
16104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
16114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              token->next_token_index = rec->active_fsmarc_tokens;
16124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              rec->active_fsmarc_tokens = new_token_index;
16134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              rec->num_new_states++;
16144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
16154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              rec->best_token_for_arc[fsm_arc_index] = new_token_index;
16164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              token->cost[0] = MAXcostdata;
16174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            }
16184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            else
16194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            {
16204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              new_token_index = rec->best_token_for_arc[fsm_arc_index];
16214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              token = &(rec->fsmarc_token_array[ new_token_index]);
16224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            }
16234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
16244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            if (cost < token->cost[0])
16254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            {
16264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              token->cost[0] = cost;
16274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                            token->duration[0] = 1;
16284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              token->word_backtrace[0] = fsmnode_token->word_backtrace;
16294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              if (token->aword_backtrace[0] != AWTNULL)
16304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                free_altword_token_batch(rec, token->aword_backtrace[0]);
16314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              token->aword_backtrace[0] = AWTNULL;
16324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              token->aword_backtrace[0] = refcopy_altwords(rec, fsmnode_token->aword_backtrace);
16334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
16344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              if (olabel != WORD_EPSILON_LABEL)
16354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              {
16364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                token->word[0] = olabel;
16374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                //ASSERT(token->aword_backtrace[0] == AWTNULL);
16384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              }
16394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              else
16404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              {
16414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                token->word[0] = fsmnode_token->word;
16424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              }
16434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              ASSERT(token->word[0] != MAXwordID
16444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                     || token->aword_backtrace[0] == AWTNULL);
16454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              if (cost < current_best_cost)
16464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              {
16474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                current_best_cost = cost;
16484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                current_prune_delta = orig_prune_delta;  /*if we have a new best cost, the prune delta could go back up*/
16494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                current_prune_thresh = cost + current_prune_delta;
16504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                ASSERT((float)cost + (float)current_prune_delta < (float)USHRT_MAX);
16514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              }
16524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            }
16534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          }
16544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
16554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
16564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
16574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    rec->best_token_for_node[fsmnode_token->FSMnode_index] = MAXftokenID; /*done with this node - remove it from the array*/
16584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    old_ftoken_index = ftoken_index;
16594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
16604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ftoken_index = fsmnode_token->next_token_index;
16614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    free_fsmnode_token(rec, old_ftoken_index); /*done with this node - free the token*/
16624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    rec->active_fsmnode_tokens = ftoken_index; /*needed for sanity_check_altwords*/
16634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
16644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*done with all the tokens, set active tokens to NULL*/
16654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  rec->active_fsmnode_tokens = MAXftokenID;
16664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  sanity_check_altwords(rec, rec->altword_token_freelist);
16674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
16684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  *pcurrent_best_cost = current_best_cost;
16694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  *pcurrent_prune_delta = current_prune_delta;
16704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
16714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return num_fsm_nodes_updated;
16724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
16734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
16744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if USE_COMP_STATS
16754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectvoid start_front_end_clock(void)
16764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
16774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (!comp_stats)
16784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    comp_stats = init_comp_stats();
16794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  start_cs_clock(&comp_stats->front_end);
16804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
16814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectvoid stop_front_end_clock(void)
16824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
16834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  end_cs_clock(&comp_stats->front_end, 1);
16844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
16854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
16864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
16874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
16884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*---------------------------------------------------------------------------*
16894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                           *
16904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * begin and end                                                             *
16914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                           *
16924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *---------------------------------------------------------------------------*/
16934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
16944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*gets things started for the viterbi search - sets up things for frame 0*/
16954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
16964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectint srec_begin(srec *rec, int begin_syn_node)
16974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
16984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  FSMnode* fsm_node;
16994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fsmnode_token *token;
17004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  stokenID new_token_index;
17014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  nodeID node_index;
17024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  arcID arc_index;
17034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
17044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (!rec || !rec->context)
17054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
17064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    log_report("Error: bad inputs to srec_begin()\n");
17074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return 1;
17084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
17094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (!rec->context->whether_prepared)
17104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
17114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    log_report("srec_begin: Grammar not prepared. Compiling!\n");
17124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    FST_PrepareContext(rec->context);
17134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
17144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (!rec->context->whether_prepared)
17154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
17164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      PLogError("ESR_INVALID_STATE: Grammar can not be compiled (FST_PrepareContext failed)");
17174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      return ESR_INVALID_STATE ;
17184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
17194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
17204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
17214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if USE_COMP_STATS
17224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (comp_stats == NULL)
17234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    comp_stats = init_comp_stats();
17244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
17254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*initialize token storage - not clear we really need this - as long as they
17264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  are managed correctly, we should be able to do this on startup - not each utt*/
17274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  initialize_free_fsmarc_tokens(rec);
17284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  initialize_free_word_tokens(rec);
17294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  initialize_free_fsmnode_tokens(rec);
17304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  initialize_word_lattice(rec->word_lattice);
17314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  initialize_free_altword_tokens(rec);
17324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
17334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (rec->context->num_nodes > rec->max_fsm_nodes)
17344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
17354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    log_report("Error: srec_begin failing due to too many grammar nodes\n");
17364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return 1;
17374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
17384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (node_index = 0;node_index < rec->context->num_nodes;node_index++)
17394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
17404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    rec->best_token_for_node[node_index] = MAXftokenID;
17414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
17424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (rec->context->num_arcs > rec->max_fsm_arcs)
17434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
17444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    log_report("Error: srec_begin failing due to too many grammar arcs\n");
17454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return 1;
17464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
17474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (arc_index = 0;arc_index < rec->context->num_arcs;arc_index++)
17484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
17494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    rec->best_token_for_arc[arc_index] = MAXstokenID;
17504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
17514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  rec->srec_ended = 0;
17524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  rec->num_new_states = 0;
17534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  rec->current_best_cost = 0;
17544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  rec->current_prune_delta = rec->prune_delta;
17554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
17564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*need help from johan - does ths FSM only have one start node?
17574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  Which one is it?   assume just one and it is node 0*/
17584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
17594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fsm_node =  &rec->context->FSMnode_list[ rec->context->start_node];
17604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  node_index = (nodeID) rec->context->start_node;
17614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* node_index is still 0 at this point */
17624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
17634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*now we just need to setup an initial fsmnode token (for begin FSM node) and then do epsilon updates*/
17644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
17654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  rec->active_fsmarc_tokens = MAXstokenID;
17664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
17674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  new_token_index = get_free_fsmnode_token(rec, EXIT_IF_NO_TOKENS);
17684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
17694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  token = &(rec->fsmnode_token_array[new_token_index]);
17704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  token->word_backtrace = MAXwtokenID; /* real value set below*/
17714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  token->cost = 0;
17724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  token->word = MAXwordID;
17734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  token->FSMnode_index = node_index;
17744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  token->next_token_index = MAXftokenID;
17754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  token->aword_backtrace = AWTNULL;
17764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
17774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  rec->best_token_for_node[node_index] = new_token_index;
17784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  rec->active_fsmnode_tokens = new_token_index;
17794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  rec->current_search_frame = 0;
17804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
17814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  do_epsilon_updates(rec, rec->prune_delta, 0);
17824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return 0;
17834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
17844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
17854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectvoid srec_force_the_end(srec* rec, frameID end_frame, wordID end_word)
17864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
17874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  srec_word_lattice* wl = rec->word_lattice;
17884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  wtokenID wtoken_index, tmp;
17894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  frameID frame;
17904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  wtoken_index = wl->words_for_frame[end_frame];
17914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (wtoken_index == MAXwtokenID)
17924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
17934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for (frame = end_frame - 1; frame > 20; frame--)
17944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
17954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (wl->words_for_frame[frame] != MAXwtokenID)
17964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
17974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        word_token* wtoken;
17984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        wl->words_for_frame[end_frame] = wl->words_for_frame[frame];
17994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        wl->words_for_frame[frame] = MAXwtokenID;
18004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        for (tmp = wl->words_for_frame[end_frame]; tmp != MAXwtokenID;
18014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project             tmp = wtoken->next_token_index)
18024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        {
18034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          wtoken = &rec->word_token_array[tmp];
18044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          wtoken->end_time = frame;
18054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          wtoken->word = end_word;
18064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          wtoken->end_node = rec->context->end_node;
18074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
18084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#ifdef _WIN32
18094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        PLogError(L("Forced an end path at end frame %d/%d)\n"), frame, end_frame);
18104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
18114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        break;
18124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
18134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
18144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
18154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
18164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
18174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/* when there are no more frames of input, this functions
18184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   kills all paths not ending at the end node and
18194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   creates a word linked list even though there is no WORD_BOUNDARY ilabel */
18204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
18214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectvoid srec_no_more_frames(srec* rec)
18224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
18234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if USE_COMP_STATS
18244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  frameID end_frame = rec->current_search_frame;
18254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
18264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  nodeID  end_node;
18274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fsmnode_token* ftoken;
18284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ftokenID current_token_index;
18294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  costdata current_word_threshold = MAXcostdata;
18304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  wtokenID word_token_index;
18314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int any_nodes_blocked = 0;
18324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  altword_token* awtoken;
18334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
18344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* this is just for sanity checking, to find out what the state was
18354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     at the end of input */
18364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  srec_check_end_of_speech_end(rec);
18374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
18384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (rec->srec_ended) return;
18394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  rec->srec_ended = 1;
18404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
18414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if USE_COMP_STATS
18424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  comp_stats->total_time += (float)(end_frame / 50.0f);
18434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  dump_comp_stats(comp_stats, PSTDOUT);
18444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
18454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
18464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  end_node = rec->context->end_node;
18474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*remove all word paths from the priority_q which do not end at end_node
18484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    to make space for those being added below */
18494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  remove_non_end_word_from_q(rec, rec->word_priority_q, rec->word_token_array,
18504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                             end_node);
18514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
18524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (rec->current_search_frame == 0)
18534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return;
18544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
18554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  rec->accumulated_cost_offset[ rec->current_search_frame] =
18564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    rec->accumulated_cost_offset[ rec->current_search_frame-1];
18574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  rec->cost_offset_for_frame[ rec->current_search_frame] = 0;
18584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
18594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* watch out if using the best_token_for_node[] array here
18604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     is it valid? not if multiple recognizers, maybe we
18614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     should remember best_token_for_end_node separately */
18624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
18634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  current_token_index = rec->active_fsmnode_tokens;
18644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  while (current_token_index != MAXftokenID)
18654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
18664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ftoken = &rec->fsmnode_token_array[current_token_index];
18674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (ftoken->FSMnode_index == end_node)
18684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
18694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      /* print_fsmnode_token(rec, current_token_index, "fsmnode_token at end_node "); */
18704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      word_token_index = srec_process_word_boundary_nbest(rec,
18714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                         ftoken->FSMnode_index,
18724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                         ftoken->word,
18734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                         ftoken->word_backtrace,
18744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                          ftoken->cost, &current_word_threshold, &any_nodes_blocked);
18754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (word_token_index != MAXwtokenID)
18764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
18774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        WORD_TOKEN_SET_WD_ETIME( (rec->word_token_array+word_token_index),
18784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          rec->word_token_array[word_token_index].end_time - ftoken->silence_duration);
18794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
18804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      /* now also dump alternatives at this last frame, sep19'03 fixed */
18814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      awtoken = ftoken->aword_backtrace;
18824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      for (; awtoken != AWTNULL; awtoken = awtoken->next_token)
18834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
18844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        srec_process_word_boundary_nbest(rec,
18854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                         ftoken->FSMnode_index,
18864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                         awtoken->word,
18874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                         awtoken->word_backtrace,
18884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                         ftoken->cost + awtoken->costdelta,
18894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                         &current_word_threshold,
18904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                         &any_nodes_blocked);
18914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
18924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
18934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    current_token_index = ftoken->next_token_index;
18944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
18954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
18964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* we clobber the word_lattice at the last frame that was created
18974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     in do_epsilon_updates() */
18984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  word_token_index = get_word_token_list(rec->word_priority_q, rec->word_token_array);
18994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  lattice_add_word_tokens(rec->word_lattice, rec->current_search_frame, word_token_index);
19004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
19014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (FST_IsVoiceEnrollment(rec->context) && word_token_index == MAXwtokenID)
19024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
19034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    srec_force_the_end(rec, rec->current_search_frame, rec->context->end_silence_word);
19044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
19054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
19064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* find the current_best_cost for this recognizer ... at the end node,
19074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     it will be used to decide which recognizer wins! */
19084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  rec->current_best_cost = lattice_best_cost_to_frame(rec->word_lattice,
19094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                           rec->word_token_array,
19104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                           rec->current_search_frame);
19114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
19124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
19134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
19144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectvoid srec_terminate(srec* rec)
19154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
19164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  frameID ifr;
19174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  stokenID stoken_index, next_stoken_index;
19184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fsmarc_token* stoken;
19194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ftokenID ftoken_index, next_ftoken_index;
19204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fsmnode_token* ftoken;
19214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  wtokenID wtoken_index, next_wtoken_index;
19224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  word_token* wtoken;
19234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
19244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* release all state tokens */
19254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (stoken_index = rec->active_fsmarc_tokens; stoken_index != MAXstokenID;
19264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       stoken_index = next_stoken_index)
19274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
19284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    stoken = &rec->fsmarc_token_array[ stoken_index];
19294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    next_stoken_index = stoken->next_token_index;
19304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    free_fsmarc_token(rec, stoken_index);
19314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
19324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  rec->active_fsmarc_tokens = MAXstokenID;
19334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
19344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* release all fsmnode tokens */
19354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (ftoken_index = rec->active_fsmnode_tokens; ftoken_index != MAXftokenID;
19364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       ftoken_index = next_ftoken_index)
19374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
19384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ftoken = &rec->fsmnode_token_array[ ftoken_index];
19394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    next_ftoken_index = ftoken->next_token_index;
19404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    free_fsmnode_token(rec, ftoken_index);
19414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
19424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  rec->active_fsmnode_tokens = MAXftokenID;
19434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
19444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* release all word tokens */
19454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (ifr = 0; ifr < rec->current_search_frame; ifr++)
19464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
19474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for (wtoken_index = rec->word_lattice->words_for_frame[ifr];
19484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project         wtoken_index != MAXwtokenID; wtoken_index = next_wtoken_index)
19494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
19504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      wtoken = &rec->word_token_array[wtoken_index];
19514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      next_wtoken_index = wtoken->next_token_index;
19524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      free_word_token(rec, wtoken_index);
19534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
19544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    rec->word_lattice->words_for_frame[ifr] = MAXwtokenID;
19554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
19564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  rec->current_model_scores[SILENCE_MODEL_INDEX] = DO_NOT_COMPUTE_MODEL;
19574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  rec->current_best_cost = MAXcostdata;
19584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  rec->srec_ended = 1;
19594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
19604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*------------------------------------------------------------------------*
19614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                        *
19624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * main work of the viterbi search                                        *
19634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                        *
19644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *------------------------------------------------------------------------*/
19654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
19664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*with new update to FSM node scheme, the sequence of operation is:
19674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
19684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for each frame:
19694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
19704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  1. Handle all internal HMM updates based on new frame observations.  This is
19714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  done in place with the current list of HMM tokens.
19724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
19734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  2. For each current active FSM node (from previous frame), activate update
19744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  into state 0 (either for existing HMM tokens or for new HMM tokens) by going
19754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  through an observation frame (so, only go from an FSM node to a new HMM
19764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  token if the first observation frame gets a score above the current pruning
19774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  threshold).  FSM nodes are freed as this is done.  So, no FSMnode tokens are left
19784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  at the end of this.
19794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
19804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  3. Prune.  Note that the best score will have already been established for
19814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  this frame (so therefore the pruning threshold will not change).
19824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
19834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  4. reset best cost to 0 (to keep scores in range).  We can do this here since we already  know the best score.
19844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
19854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  5. For end hmm states which are above the pruning threshold, create new
19864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  FSMnode_tokens.
19874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
19884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  6. update epsilons, including word boundary arcs (which put words onto the word lattice).
19894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  epsilon updates go from FSM node to FSM node.
19904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
19914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  repeat for next frame based on new FSM nodes and current HMMs
19924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
19934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project*/
19944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
19954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectvoid srec_viterbi_part1(srec *rec,
19964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                        const SWIModel *acoustic_models,
19974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                        pattern_info *pattern,
19984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                        costdata silence_model_cost);
19994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
20004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectvoid srec_viterbi_part2(srec *rec);
20014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
20024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectint multi_srec_viterbi(multi_srec *recm,
20034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                       srec_eos_detector_parms* eosd,
20044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                       pattern_info *pattern,
20054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                       utterance_info* utt_not_used)
20064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
20074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  EOSrc eosrc1 = SPEECH_ENDED, eosrc2 = SPEECH_ENDED;
20084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if DO_ALLOW_MULTIPLE_MODELS
20094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ASSERT(recm->num_activated_recs == recm->num_swimodels);
20104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (recm->num_activated_recs == 1)
20114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
20124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
20134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    srec* rec1 = &recm->rec[0];
20144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if USE_COMP_STATS
20154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    start_cs_clock1(&comp_stats->overall_search);
20164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
20174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (rec1->current_search_frame >= (rec1->word_lattice->max_frames - 1))
20184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      return 1;
20194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    srec_viterbi_part1(&recm->rec[0], recm->swimodel[0], pattern, DO_NOT_COMPUTE_MODEL);
20204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    reset_best_cost_to_zero(rec1, rec1->current_best_cost);
20214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    reset_cost_offsets(recm, rec1->current_search_frame, rec1->current_best_cost);
20224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    rec1->current_prune_delta = rec1->prune_delta;
20234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    rec1->current_best_cost   = 0;
20244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    srec_viterbi_part2(&recm->rec[0]);
20254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    eosrc1 = srec_check_end_of_speech(eosd, &recm->rec[0]);
20264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if USE_COMP_STATS
20274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    end_cs_clock1(&comp_stats->overall_search, 1);
20284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
20294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
20304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    SREC_STATS_UPDATE(&recm->rec[0]);
20314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    recm->eos_status = eosrc1;
20324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if DO_ALLOW_MULTIPLE_MODELS
20334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
20344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else if (recm->num_activated_recs == 2)
20354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
20364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    srec* rec1 = &recm->rec[0];
20374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    srec* rec2 = &recm->rec[1];
20384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    const SWIModel* acoustic_models1 = recm->swimodel[0];
20394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    const SWIModel* acoustic_models2 = recm->swimodel[1];
20404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    costdata diff;
20414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    costdata current_best_cost;
20424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
20434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ASSERT(rec1->prune_delta == rec2->prune_delta);
20444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /* in part 1 we need to operate by adjusting the prune delta, 'cuz we want
20454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       to operate on scores after consumption of a frame */
20464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if ((rec1->current_best_cost > MAXcostdata / 2 && !rec1->srec_ended) ||
20474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        (rec2->current_best_cost > MAXcostdata / 2 && !rec2->srec_ended))
20484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
20494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      printf("hey %d %d\n", rec1->current_best_cost, rec2->current_best_cost);
20504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
20514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
20524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /* figure out the prune_delta for the different genders, we
20534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       want that pruning should be joint (i.e. prune male and
20544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       female relative to overall best).  Before part1 we don't
20554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       yet know the overall best, so we use the gender score gap
20564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       from the last frame, and make the prune the worse gender
20574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       accordingly more aggressive */
20584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
20594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (!rec2->srec_ended && rec1->current_best_cost < rec2->current_best_cost)
20604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
20614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      diff = rec2->current_best_cost - rec1->current_best_cost;
20624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (rec2->current_search_frame >= (rec2->word_lattice->max_frames - 1))
20634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
20644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        return 1;
20654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
20664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (diff > rec2->prune_delta)
20674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
20684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        srec_terminate(rec2);
20694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#ifdef SREC_ENGINE_VERBOSE_LOGGING
20704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        PLogMessage("T: terminate_viterbi(rec2) @%d", rec2->current_search_frame);
20714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
20724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
20734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      else
20744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        rec2->current_prune_delta = rec2->prune_delta - diff;
20754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      rec1->current_prune_delta = rec1->prune_delta;
20764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
20774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    else if (!rec1->srec_ended)
20784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
20794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (rec1->current_search_frame >= (rec1->word_lattice->max_frames - 1))
20804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
20814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        return 1;
20824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
20834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      diff = rec1->current_best_cost - rec2->current_best_cost;
20844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (diff > rec1->prune_delta)
20854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
20864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        srec_terminate(rec1);
20874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#ifdef SREC_ENGINE_VERBOSE_LOGGING
20884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        PLogMessage("T: terminate_viterbi(rec1) @%d", rec1->current_search_frame);
20894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
20904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
20914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      else
20924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        rec1->current_prune_delta = rec1->prune_delta - diff;
20934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      rec2->current_prune_delta = rec2->prune_delta;
20944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
20954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
20964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /* now run part1 for each gender */
20974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (!rec1->srec_ended)
20984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
20994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      srec_viterbi_part1(rec1, acoustic_models1, pattern, DO_NOT_COMPUTE_MODEL);
21004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      SREC_STATS_UPDATE(rec1);
21014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
21024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
21034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (!rec2->srec_ended)
21044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
21054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      srec_viterbi_part1(rec2, acoustic_models2, pattern, rec1->current_model_scores[SILENCE_MODEL_INDEX]);
21064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      SREC_STATS_UPDATE(rec2);
21074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
21084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
21094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /* now adjust score offsets, score offsets are shared across genders */
21104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
21114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (rec1->current_best_cost <= rec2->current_best_cost)
21124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
21134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      /* am1 is winning, prune 2 harder */
21144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      current_best_cost = rec1->current_best_cost;
21154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      reset_cost_offsets(recm, rec1->current_search_frame, current_best_cost);
21164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
21174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    else
21184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
21194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      /* am2 is winning, prune 1 harder */
21204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      current_best_cost = rec2->current_best_cost;
21214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      reset_cost_offsets(recm, rec2->current_search_frame, current_best_cost);
21224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
21234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
21244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /* jean: some cleanup needed here */
21254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /** best_token_for_arc = rec1->best_token_for_arc;
21264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      rec1->best_token_for_arc = 0; **/
21274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (!rec1->srec_ended)
21284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
21294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      reset_best_cost_to_zero(rec1, current_best_cost);
21304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      rec1->current_best_cost = (costdata)(rec1->current_best_cost - (costdata) current_best_cost);
21314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      srec_viterbi_part2(rec1);
21324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (rec1->active_fsmnode_tokens == MAXftokenID)
21334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        srec_terminate(rec1);
21344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (!rec1->srec_ended)
21354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        eosrc1 = srec_check_end_of_speech(eosd, rec1);
21364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
21374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /** rec1->best_token_for_arc = best_token_for_arc;
21384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      best_token_for_arc = rec2->best_token_for_arc;
21394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      rec2->best_token_for_arc = 0; **/
21404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (!rec2->srec_ended)
21414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
21424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      reset_best_cost_to_zero(rec2, current_best_cost);
21434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      rec2->current_best_cost = (costdata)(rec2->current_best_cost - (costdata) current_best_cost);
21444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      srec_viterbi_part2(rec2);
21454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (rec2->active_fsmnode_tokens == MAXftokenID)
21464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        srec_terminate(rec2);
21474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (!rec2->srec_ended)
21484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        eosrc2 = srec_check_end_of_speech(eosd, rec2);
21494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
21504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /** rec2->best_token_for_arc = best_token_for_arc; **/
21514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    SREC_STATS_UPDATE(rec1);
21524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    SREC_STATS_UPDATE(rec2);
21534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    recm->eos_status = eosrc1;
21544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (rec1->current_best_cost > rec2->current_best_cost)
21554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      recm->eos_status = eosrc2;
21564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
21574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
21584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return 0;
21594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
21604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
21614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
21624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectvoid srec_viterbi_part1(srec *rec,
21634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                        const SWIModel *acoustic_models,
21644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                        pattern_info *pattern,
21654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                        costdata silence_model_cost)
21664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
21674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  costdata current_best_cost;
21684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*  costdata current_prune_thresh; */
21694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  costdata current_prune_delta;
21704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* the score difference for pruning - can get adjusted below if
21714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     pruning gets tighted to keep array sizes in check*/
21724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  costdata *current_model_scores;
21734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int num_models_computed;
21744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  nodeID num_fsm_nodes_updated;
21754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
21764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if USE_COMP_STATS
21774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  start_cs_clock(&comp_stats->models);
21784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
21794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
21804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*first go ahead and compute scores for all models which are needed by the search at this point*/
21814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
21824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
21834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  find_which_models_to_compute(rec, acoustic_models);
21844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* communication happens via rec->current_model_scores */
21854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define SCORE_FIRST_SILENCE_ONLY
21864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#ifdef SCORE_FIRST_SILENCE_ONLY
21874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (silence_model_cost != DO_NOT_COMPUTE_MODEL)
21884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    rec->current_model_scores[SILENCE_MODEL_INDEX] = silence_model_cost;
21894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
21904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  num_models_computed = compute_model_scores(rec->current_model_scores, acoustic_models, pattern, rec->current_search_frame);
21914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  rec->best_model_cost_for_frame[rec->current_search_frame] = best_uint16(rec->current_model_scores, acoustic_models->num_hmmstates);
21924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
21934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if USE_COMP_STATS
21944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  end_cs_clock(&comp_stats->models, num_models_computed);
21954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  start_cs_clock(&comp_stats->internal_hmm);
21964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
21974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
21984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*get some things out of the rec structure to make things a bit faster*/
21994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  current_model_scores = rec->current_model_scores;
22004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
22014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*update search to next frame*/
22024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  current_best_cost = MAXcostdata - ((costdata)2) * rec->prune_delta; /*to avoid overflows, must clean up later */
22034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* current_prune_thresh = MAXcostdata; */
22044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  current_prune_delta = rec->current_prune_delta;
22054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
22064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* srec_stats_update(rec, "(...0) "); */
22074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*------------------------------------------------------------------------*
22084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    1. Handle all internal HMM updates based on new frame observations.  This is
22094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    done in place with the current list of HMM tokens.
22104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   *------------------------------------------------------------------------*/
22114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
22124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  update_internal_hmm_states(rec, &current_prune_delta, &current_best_cost, current_model_scores);
22134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
22144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*  check_if_any_token_better_than_best_cost(rec, rec->active_fsmarc_tokens, current_best_cost, "after update into new");*/
22154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
22164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if USE_COMP_STATS
22174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  end_cs_clock(&comp_stats->internal_hmm, rec->num_new_states);
22184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  start_cs_clock(&comp_stats->fsm_to_hmm);
22194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
22204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
22214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* srec_stats_update(rec, "(...1) "); */
22224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*------------------------------------------------------------------------*
22234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    2. For each current active FSM node (from previous frame), activate update
22244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    into state 0 (either for existing HMM tokens or for new HMM tokens) by going
22254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    through an observation frame (so, only go from an FSM node to a new HMM
22264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    token if the first observation frame gets a score above the current pruning
22274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    threshold).  FSM nodes are freed as this is done.  So, no FSMnode tokens are left
22284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    at the end of this.
22294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   *------------------------------------------------------------------------*/
22304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
22314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  num_fsm_nodes_updated = (nodeID) update_from_current_fsm_nodes_into_new_HMMs(rec, &current_prune_delta, &current_best_cost, current_model_scores);
22324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* srec_stats_update(rec, "(...2) "); */
22334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*------------------------------------------------------------------------*
22344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    3. Prune.  Note that the best score will have already been established for
22354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    this frame (so therefore the pruning threshold will not change).
22364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   *------------------------------------------------------------------------*/
22374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
22384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if USE_COMP_STATS
22394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  end_cs_clock(&comp_stats->fsm_to_hmm, num_fsm_nodes_updated);
22404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  start_cs_clock(&comp_stats->prune);
22414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
22424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
22434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  prune_new_tokens(rec, (costdata)(current_best_cost + current_prune_delta));
22444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
22454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* it's nice to do word token pruning here 'cuz we only need to traceback
22464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     the active_fsmarc_tokens, active_fsmnode_tokens are propogated thereto */
22474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
22484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  reprune_word_tokens_if_necessary(rec);
22494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
22504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  rec->current_prune_delta = current_prune_delta;
22514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  rec->current_best_cost = current_best_cost;
22524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* srec_stats_update(rec, "(...3) "); */
22534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if USE_COMP_STATS
22544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  end_cs_clock(&comp_stats->prune, rec->num_new_states);
22554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
22564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
22574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
22584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectvoid srec_viterbi_part2(srec *rec)
22594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
22604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  wtokenID word_token_index;
22614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  nodeID inode, num_fsm_nodes_updated;
22624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  costdata current_prune_delta = rec->current_prune_delta;
22634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  costdata current_best_cost = rec->current_best_cost;
22644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ftokenID* ftmp;
22654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int num_updates;
22664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
22674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* first we clear the best_token_for_node array, there are no live
22684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     fsmnode_tokens at this point, and we don't want leftovers from
22694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     the last frame */
22704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ftmp = rec->best_token_for_node;
22714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (inode = 0; inode < rec->context->num_nodes; inode++)
22724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    *ftmp++ = MAXftokenID;
22734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
22744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*------------------------------------------------------------------------*
22754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    4. reset best cost to 0 (to keep scores in range).  We can do this here
22764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    since we already know the best score.  This is done here so that
22774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    no fsmnode tokens (there are none active now) need updating.  This is also
22784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    done here before epsilons - that way we don't need to update the word
22794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    tokens .
22804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
22814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    We assume this was done just before part2.
22824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   *------------------------------------------------------------------------*/
22834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
22844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if USE_COMP_STATS
22854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  start_cs_clock(&comp_stats->hmm_to_fsm);
22864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
22874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
22884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*------------------------------------------------------------------------*
22894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    5. For end hmm states which are above the pruning threshold, create new
22904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    FSMnode_tokens.
22914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   *------------------------------------------------------------------------*/
22924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
22934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  num_updates = update_from_hmms_to_fsmnodes(rec, current_prune_delta, current_best_cost);
22944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (num_updates == 0)
22954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
22964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    num_updates = update_from_hmms_to_fsmnodes(rec, 2 * current_prune_delta, current_best_cost);
22974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    SREC_STATS_INC_FORCED_UPDATES();
22984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
22994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  SREC_STATS_UPDATE(rec);
23004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
23014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if USE_COMP_STATS
23024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  end_cs_clock(&comp_stats->hmm_to_fsm, rec->num_new_states);
23034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  start_cs_clock(&comp_stats->epsilon);
23044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
23054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
23064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* srec_stats_update(rec, "(...5) "); */
23074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
23084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*------------------------------------------------------------------------*
23094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    6. update epsilons, including word boundary arcs (which put words onto the word lattice).
23104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    epsilon updates go from FSM node to FSM node.
23114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   *------------------------------------------------------------------------*/
23124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
23134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*clear priority_q for this frame*/
23144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  clear_priority_q(rec->word_priority_q);
23154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
23164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  num_fsm_nodes_updated = (nodeID) do_epsilon_updates(rec, current_prune_delta, current_best_cost);
23174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
23184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if USE_COMP_STATS
23194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  end_cs_clock(&comp_stats->epsilon, num_fsm_nodes_updated);
23204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
23214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
23224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* srec_stats_update(rec, "(...6) "); */
23234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  rec->current_search_frame++;
23244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
23254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* no need to prune again after epsilons since they add no new cost - if we
23264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     add costs to epsilon arcs (at word boundaries for example), add another
23274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     pruning stage */
23284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
23294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  word_token_index = get_word_token_list(rec->word_priority_q, rec->word_token_array);
23304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  lattice_add_word_tokens(rec->word_lattice, rec->current_search_frame, word_token_index);
23314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
23324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
23334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/* get the top choice, trace it back, and find out where speech starts
23344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   and ends.  this is used for channel normalization */
23354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
23364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic srec* WHICH_RECOG(multi_srec* rec)
23374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
23384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if DO_ALLOW_MULTIPLE_MODELS
23394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  srec* return_rec = NULL;
23404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  costdata current_best_cost = MAXcostdata;
23414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int i = 0;
23424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (i = 0; i < rec->num_activated_recs; i++)
23434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
23444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (current_best_cost > rec->rec[i].current_best_cost)
23454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
23464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      current_best_cost = rec->rec[i].current_best_cost;
23474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      return_rec = &rec->rec[i];
23484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
23494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
23504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return return_rec;
23514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#else
23524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return &rec->rec[0];
23534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
23544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
23554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
23564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectvoid multi_srec_get_speech_bounds(multi_srec* recm, frameID* start_frame, frameID* end_frame)
23574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
23584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  frameID csf;
23594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  wtokenID token_index;
23604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  wordID last_word;
23614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  srec* rec = WHICH_RECOG(recm);
23624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
23634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  *start_frame = *end_frame = 0;
23644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
23654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (!rec)
23664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return;
23674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  csf = rec->current_search_frame;
23684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  token_index = rec->word_lattice->words_for_frame[csf];
23694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  last_word = MAXwordID;
23704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  while (token_index != MAXwtokenID)
23714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
23724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    word_token* wtoken = &rec->word_token_array[token_index];
23734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    word_token* next_wtoken;
23744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
23754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (wtoken->word == rec->context->beg_silence_word)
23764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
23774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (*start_frame == 0) *start_frame = wtoken->end_time;
23784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
23794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (wtoken->word == rec->context->hack_silence_word)
23804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
23814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (wtoken->backtrace != MAXwtokenID)
23824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
23834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        next_wtoken = &rec->word_token_array[wtoken->backtrace];
23844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (next_wtoken->word == rec->context->beg_silence_word)
23854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          *start_frame = wtoken->end_time;
23864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
23874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
23884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
23894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (last_word == rec->context->end_silence_word)
23904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
23914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      *end_frame = wtoken->end_time;
23924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (wtoken->word ==  rec->context->hack_silence_word
23934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          && wtoken->backtrace != MAXwtokenID)
23944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
23954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        next_wtoken = &rec->word_token_array[wtoken->backtrace];
23964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        *end_frame = WORD_TOKEN_GET_WD_ETIME( next_wtoken);
23974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
23984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
23994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (token_index ==  wtoken->backtrace)
24004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
24014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      /* infinite loop! */
24024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      PLogError ("warning: breaking infinite loop\n");
24034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      *end_frame = 0;
24044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      break;
24054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
24064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    token_index = wtoken->backtrace;
24074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    last_word = wtoken->word;
24084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
24094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
24104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
24114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectint multi_srec_get_eos_status(multi_srec* rec)
24124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
24134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int rc;
24144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ASSERT(rec);
24154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  rc = (int)rec->eos_status;
24164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (rc < 0) rc = 0;
24174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return rc;
24184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
24194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
24204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*
24214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     ToDo List:
24224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
24234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     end-pointing
24244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     duration
24254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     channel normalization
24264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     re-use and appropriate killing of word_tokens
24274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     pruning fsmnode_tokens
24284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     astar backward for alternative choices
24294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
24304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     minimized graphs and word merging
24314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     Johans idea:
24324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     When propagating a fsmarc_token, we need to remember the word.id when it
24334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     is observed.  Let's continue to use fsmarc_token->word[] to remember those.
24344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     When merging 2+ fsmarc_tokens into a fsmnode_token, we need remember
24354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     both histories, not just the best. All histories and maintained on a linked
24364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     list, with word_token->next_token_index serving as links, somehow we also
24374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     remember the cost offset from one link to the next and keep track of that.
24384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     Try to create the word_token as late a possible, so as to keep usage down.
24394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     The list should be sorted so that we can drop things off the end, Ie. don't
24404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     need to keep all word, a max of 10 is fine cuz that's the most we'll need
24414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     to drop off at a .wb anyways!
24424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
24434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     altwords .. working .. now cpu optimize ... ideas
24444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     use only the head refcount, #define the refcopy, not a function
24454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     free_altword_token_batch() should not double check for AWTNULL
24464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     BUILD & BUILD_DEBUG in selected areas
24474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     reprune_altword_token_batch ... change costbasis to a tag ... to say (already repruned)
24484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
24494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
24504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
24514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     endpointing
24524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     at grammar prepare ...
24534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     get the list of endnodes ... get the list of opendnodes
24544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     ... start from the graph's endnode, walk backwards on all null or silence arcs, find the nodes which have a silence or null path to the end: those are sinknodes
24554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     ... sinknodes are endnodes or opendnodes ... the sinknodesO are the sinknodes that do go to speech arcs .. the sinknodes1 are the sinknodes that do not go to any speech arcs
24564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     ... walkforward all sinknodes0 through iwt arcs, those are openendnodes
24574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     ... walkforward all sinknodes1 through iwt arcs, those are endnodes
24584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     get the top score fsmnode_token ...
24594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     ... is it on an endnode ... has this been the top choice for the last 30 frames
24604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     ... is it on an optional endnode ... has this neen the top choice for the last 50 frames?
24614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
24624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  */
2463