Exemple #1
0
/** 
 * Initialize and setup acoustic computation functions.
 * 
 * @param wrk [i/o] HMM computation work area
 * @param hmminfo [in] HMM definition
 * @param gshmm [in] GMS HMM definition if exist, or NULL if not
 * @param gms_num [in] number of GMS HMM to compute (valid if gshmm != NULL)
 * @param gprune_method [in] gaussian pruning method
 * @param gprune_mixnum [in] number of pdf to compute at a codebook
 * in gaussian pruning
 * 
 * @return TRUE on success, FALSE on failure.
 */
boolean
outprob_init(HMMWork *wrk, HTK_HMM_INFO *hmminfo,
	     HTK_HMM_INFO *gshmm, int gms_num,
	     int gprune_method, int gprune_mixnum
	     )
{
  int i;
  /* check if variances are inversed */
  if (!hmminfo->variance_inversed) {
    /* here, inverse all variance values for faster computation */
    htk_hmm_inverse_variances(hmminfo);
    hmminfo->variance_inversed = TRUE;
  }
  /* check if variances are inversed */
  if (gshmm) {
    if (!gshmm->variance_inversed) {
      /* here, inverse all variance values for faster computation */
      htk_hmm_inverse_variances(gshmm);
      gshmm->variance_inversed = TRUE;
    }
  }

  /** select functions **/
  /* select pruning function to compute likelihood of a mixture component
     and set the pointer to global */
#ifdef ENABLE_MSD
  /* currently MSD model works only for non pruning mode */
  if (hmminfo->has_msd && gprune_method != GPRUNE_SEL_NONE) {
    jlog("Error: outprob_init: only \"-gprune none\" is supported when MSD-HMM enabled\n");
    return FALSE;
  }
#endif
  switch(gprune_method) {
  case GPRUNE_SEL_NONE:
    wrk->compute_gaussset = gprune_none;
    wrk->compute_gaussset_init = gprune_none_init;
    wrk->compute_gaussset_free = gprune_none_free;
    break;
  case GPRUNE_SEL_SAFE:
    wrk->compute_gaussset = gprune_safe;
    wrk->compute_gaussset_init = gprune_safe_init;
    wrk->compute_gaussset_free = gprune_safe_free;
    break;
  case GPRUNE_SEL_HEURISTIC:
    wrk->compute_gaussset = gprune_heu;
    wrk->compute_gaussset_init = gprune_heu_init;
    wrk->compute_gaussset_free = gprune_heu_free;
    break;
  case GPRUNE_SEL_BEAM:
    wrk->compute_gaussset = gprune_beam;
    wrk->compute_gaussset_init = gprune_beam_init;
    wrk->compute_gaussset_free = gprune_beam_free;
    break;
  case GPRUNE_SEL_USER:
    /* assume user functions are already registered to the entries */
    break;
  }
  /* select caching function to compute output probability of a mixture */
  if (hmminfo->is_tied_mixture) {
    /* check if all mixture PDFs are tied-mixture */
    {
      HTK_HMM_PDF *p;
      boolean ok_p = TRUE;
      for (p = hmminfo->pdfstart; p; p = p->next) {
	if (p->tmix == FALSE) {
	  ok_p = FALSE;
	  break;
	}
      }
      if (ok_p) {
	jlog("Stat: outprob_init: all mixture PDFs are tied-mixture, use calc_tied_mix()\n");
	wrk->calc_outprob = calc_tied_mix; /* enable book-level cache, typically for a tied-mixture model */
      } else {
	jlog("Stat: outprob_init: tied-mixture PDF exist (not all), calc_compound_mix()\n");
	wrk->calc_outprob = calc_compound_mix; /* enable book-level cache, typically for a tied-mixture model */
      }
    }
  } else {
    jlog("Stat: outprob_init: state-level mixture PDFs, use calc_mix()\n");
    wrk->calc_outprob = calc_mix; /* no mixture-level cache, for a shared-state, non tied-mixture model */
  }
  
  /* select back-off functon for state probability calculation */
  if (gshmm != NULL) {
    wrk->calc_outprob_state = gms_state; /* enable GMS */
  } else {
    wrk->calc_outprob_state = wrk->calc_outprob; /* call mixture outprob directly */
  }

  /* store common variable to global */
  wrk->OP_hmminfo = hmminfo;
  wrk->OP_gshmm = gshmm;		/* NULL if GMS not used */
  wrk->OP_gprune_num = gprune_mixnum;

  /* store multi-stream data */
  wrk->OP_nstream = hmminfo->opt.stream_info.num;
  for(i=0;i<wrk->OP_nstream;i++) {
    wrk->OP_veclen_stream[i] = hmminfo->opt.stream_info.vsize[i];
  }

  /* generate addlog table */
  make_log_tbl();
  
  /* initialize work area for mixture component pruning function */
  if ((*(wrk->compute_gaussset_init))(wrk) == FALSE) return FALSE; /* OP_gprune may change */
  /* initialize work area for book level cache on tied-mixture model */
  if (hmminfo->is_tied_mixture) {
    if (calc_tied_mix_init(wrk) == FALSE) return FALSE;
  }
  /* initialize work area for GMS */
  if (wrk->OP_gshmm != NULL) {
    wrk->my_nbest = gms_num;
    if (gms_init(wrk) == FALSE) return FALSE;
  }
  /* initialize cache for all output probabilities */
  if (outprob_cache_init(wrk) == FALSE)  return FALSE;

  /* initialize word area for computation of pseudo HMM set when N-max is specified */
  if (hmminfo->cdset_method == IWCD_NBEST) {
    outprob_cd_nbest_init(wrk, hmminfo->cdmax_num);
  }

  return TRUE;
}
Exemple #2
0
/** 
 * <JA>
 * GMMの計算のための初期化. 起動時に一度だけ呼ばれる. 
 * 
 * @param recog [i/o] エンジンインスタンス
 * </JA>
 * <EN>
 * Initialization for computing GMM likelihoods.  This will be called
 * once on startup.
 * 
 * @param recog [i/o] engine instance
 * </EN>
 *
 * @callgraph
 * @callergraph
 * 
 */
boolean
gmm_init(Recog *recog)
{
  HTK_HMM_INFO *gmm;
  HTK_HMM_Data *d;
  GMMCalc *gc;
  int i;

  gmm = recog->gmm;

  /* check GMM format */
  /* tied-mixture GMM is not supported */
  if (gmm->is_tied_mixture) {
    jlog("ERROR: gmm_init: tied-mixture GMM is not supported\n");
    return FALSE;
  }
  /* assume 3 state GMM (only one output state) */
  for(d=gmm->start;d;d=d->next) {
    if (d->state_num > 3) {
      jlog("ERROR: gmm_init: more than three states (one output state) defined in GMM [%s]\n", d->name);
      return FALSE;
    }
  }

  /* check if CMN needed */

  /* allocate work area */
  if (recog->gc == NULL) {
    gc = (GMMCalc *)mymalloc(sizeof(GMMCalc));
    recog->gc = gc;
  } else {
    gc = recog->gc;
  }
  
  /* allocate buffers */
  gc->gmm_score = (LOGPROB *)mymalloc(sizeof(LOGPROB) * gmm->totalhmmnum);

#ifdef GMM_VAD
  gc->nframe = recog->jconf->detect.gmm_margin;
  gc->rates = (LOGPROB *)mymalloc(sizeof(LOGPROB) * gc->nframe);
#endif

  gc->is_voice = (boolean *)mymalloc(sizeof(boolean) * gmm->totalhmmnum);
  i = 0;
  if (recog->jconf->reject.gmm_reject_cmn_string) {
    for(d=recog->gmm->start;d;d=d->next) {
      if (strstr(recog->jconf->reject.gmm_reject_cmn_string, d->name)) {
	gc->is_voice[i] = FALSE;
      } else {
	gc->is_voice[i] = TRUE;
      }
      i++;
    }
  } else {
    for(d=recog->gmm->start;d;d=d->next) {
      gc->is_voice[i] = TRUE;
      i++;
    }
  }

  /* initialize work area */
  gc->OP_nstream = gmm->opt.stream_info.num;
  for(i=0;i<gc->OP_nstream;i++) {
    gc->OP_veclen_stream[i] = gmm->opt.stream_info.vsize[i];
  }
  gmm_gprune_safe_init(gc, gmm, recog->jconf->reject.gmm_gprune_num);

  /* check if variances are inversed */
  if (!gmm->variance_inversed) {
    /* here, inverse all variance values for faster computation */
    htk_hmm_inverse_variances(gmm);
    gmm->variance_inversed = TRUE;
  }

  return TRUE;
}
/** 
 * @brief  Main top routine to read in HTK %HMM definition file.
 *
 * A HTK %HMM definition file will be read from @a fp.  After reading,
 * the parameter type is checked and calculate some statistics.
 * 
 * @param fp [in] file pointer
 * @param hmm [out] pointer to a %HMM definition structure to store data.
 * 
 * @return TRUE on success, FALSE on failure.
 */
boolean
rdhmmdef(FILE *fp, HTK_HMM_INFO *hmm)
{
  char macrosw;
  char *name;

  /* variances in htkdefs are not inversed yet */
  hmm->variance_inversed = FALSE;

  /* read the first token */
  /* read new 1 line */
  line = 1;
  if (getl(buf, MAXBUFLEN, fp) == NULL) {
    rdhmmdef_token = NULL;
  } else {
    rdhmmdef_token = mystrtok_quote(buf, HMMDEF_DELM);
  }
  
  /* the toplevel loop */
  while (rdhmmdef_token != NULL) {/* break on EOF */
    if (rdhmmdef_token[0] != '~') { /* toplevel commands are always macro */
      return FALSE;
    }
    macrosw = rdhmmdef_token[1];
    read_token(fp);		/* read next token after the "~.."  */
    switch(macrosw) {
    case 'o':			/* global option */
      if (set_global_opt(fp,hmm) == FALSE) {
	return FALSE;
      }
      break;
    case 't':			/* transition macro */
      name = mybstrdup2(rdhmmdef_token, &(hmm->mroot));
      if (strlen(name) >= MAX_HMMNAME_LEN) rderr("Macro name too long");
      read_token(fp);
      def_trans_macro(name, fp, hmm);
      break;
    case 's':			/* state macro */
      name = mybstrdup2(rdhmmdef_token, &(hmm->mroot));
      if (strlen(name) >= MAX_HMMNAME_LEN) rderr("Macro name too long");
      read_token(fp);
      def_state_macro(name, fp, hmm);
      break;
    case 'm':			/* density (mixture) macro */
      name = mybstrdup2(rdhmmdef_token, &(hmm->mroot));
      if (strlen(name) >= MAX_HMMNAME_LEN) rderr("Macro name too long");
      read_token(fp);
      def_dens_macro(name, fp, hmm);
      break;
    case 'h':			/* HMM define */
      name = mybstrdup2(rdhmmdef_token, &(hmm->mroot));
      if (strlen(name) >= MAX_HMMNAME_LEN) rderr("Macro name too long");
      read_token(fp);
      def_HMM(name, fp, hmm);
      break;
    case 'v':			/* Variance macro */
      name = mybstrdup2(rdhmmdef_token, &(hmm->mroot));
      if (strlen(name) >= MAX_HMMNAME_LEN) rderr("Macro name too long");
      read_token(fp);
      def_var_macro(name, fp, hmm);
      break;
    case 'w':			/* Stream weight macro */
      name = mybstrdup2(rdhmmdef_token, &(hmm->mroot));
      if (strlen(name) >= MAX_HMMNAME_LEN) rderr("Macro name too long");
      read_token(fp);
      def_streamweight_macro(name, fp, hmm);
      break;
    case 'r':			/* Regression class macro (ignore) */
      name = mybstrdup2(rdhmmdef_token, &(hmm->mroot));
      if (strlen(name) >= MAX_HMMNAME_LEN) rderr("Macro name too long");
      read_token(fp);
      def_regtree_macro(name, fp, hmm);
      break;
    case 'p':			/* Mixture pdf macro (extension of HTS) */
      name = mybstrdup2(rdhmmdef_token, &(hmm->mroot));
      if (strlen(name) >= MAX_HMMNAME_LEN) rderr("Macro name too long");
      read_token(fp);
      def_mpdf_macro(name, fp, hmm);
      break;
    }
  }

  /* convert transition prob to log scale */
  conv_log_arc(hmm);

  jlog("Stat: rdhmmdef: ascii format HMM definition\n");
  
  /* check limitation */
  if (check_all_hmm_limit(hmm)) {
    jlog("Stat: rdhmmdef: limit check passed\n");
  } else {
    jlog("Error: rdhmmdef: cannot handle this HMM due to system limitation\n");
    return FALSE;
  }

  /* determine whether this model needs multi-path handling */
  hmm->need_multipath = htk_hmm_has_several_arc_on_edge(hmm);
  if (hmm->need_multipath) {
    jlog("Stat: rdhmmdef: this HMM requires multipath handling at decoding\n");
  } else {
    jlog("Stat: rdhmmdef: this HMM does not need multipath handling\n");
  }
  
  /* inverse all variance values for faster computation */
  if (! hmm->variance_inversed) {
    htk_hmm_inverse_variances(hmm);
    hmm->variance_inversed = TRUE;
  }

  /* check HMM parameter option type */
  if (!check_hmm_options(hmm)) {
    jlog("Error: rdhmmdef: hmm options check failed\n");
    return FALSE;
  }

  /* add ID number for all HTK_HMM_State if not assigned */
  {
    HTK_HMM_State *stmp;
    int n;
    boolean has_sid;

    /* caclculate total num and check if has sid */
    has_sid = FALSE;
    n = 0;
    for (stmp = hmm->ststart; stmp; stmp = stmp->next) {
      n++;
      if (n >= MAX_STATE_NUM) {
	jlog("Error: rdhmmdef: too much states in a model > %d\n", MAX_STATE_NUM);
	return FALSE;
      }
      if (stmp->id != -1) {
	has_sid = TRUE;
      }
    }
    hmm->totalstatenum = n;
    if (has_sid) {
      jlog("Stat: rdhmmdef: <SID> found in the definition\n");
      /* check if each state is assigned a valid sid */
      if (htk_hmm_check_sid(hmm) == FALSE) {
	jlog("Error: rdhmmdef: error in SID\n");
	return FALSE;
      }
    } else {
      /* assign internal sid (will not be saved) */
      jlog("Stat: rdhmmdef: no <SID> embedded\n");
      jlog("Stat: rdhmmdef: assign SID by the order of appearance\n");
      n = hmm->totalstatenum;
      for (stmp = hmm->ststart; stmp; stmp = stmp->next) {
	stmp->id = --n;
      }
    }
  }
  /* calculate the maximum number of mixture */
  {
    HTK_HMM_State *stmp;
    int max, s, mix;
    max = 0;
    for (stmp = hmm->ststart; stmp; stmp = stmp->next) {
      for(s=0;s<stmp->nstream;s++) {
	mix = stmp->pdf[s]->mix_num;
	if (max < mix) max = mix;
      }
    }
    hmm->maxmixturenum = max;
  }
  /* compute total number of HMM models and maximum length */
  {
    HTK_HMM_Data *dtmp;
    int n, maxlen;
    n = 0;
    maxlen = 0;
    for (dtmp = hmm->start; dtmp; dtmp = dtmp->next) {
      if (maxlen < dtmp->state_num) maxlen = dtmp->state_num;
      n++;
    }
    hmm->maxstatenum = maxlen;
    hmm->totalhmmnum = n;
  }
  /* compute total number of Gaussians */
  {
    HTK_HMM_Dens *dtmp;
    int n = 0;
    for (dtmp = hmm->dnstart; dtmp; dtmp = dtmp->next) {
      n++;
    }
    hmm->totalmixnum = n;
  }
  /* check of HMM name length exceed the maximum */
  {
    HTK_HMM_Dens *dtmp;
    int n = 0;
    for (dtmp = hmm->dnstart; dtmp; dtmp = dtmp->next) {
      n++;
    }
    hmm->totalmixnum = n;
  }
  /* compute total number of mixture PDFs */
  {
    HTK_HMM_PDF *p;
    int n = 0;
    for (p = hmm->pdfstart; p; p = p->next) {
      n++;
    }
    hmm->totalpdfnum = n;
  }
  /* assign ID number for all HTK_HMM_Trans */
  {
    HTK_HMM_Trans *ttmp;
    int n = 0;
    for (ttmp = hmm->trstart; ttmp; ttmp = ttmp->next) {
      ttmp->id = n++;
    }
    hmm->totaltransnum = n;
  }
#ifdef ENABLE_MSD
  /* check if MSD-HMM */
  htk_hmm_check_msd(hmm);
#endif

  return(TRUE);			/* success */
}