graphout.c

来自「julius version 4.12.about sound recognit」· C语言 代码 · 共 2,136 行 · 第 1/5 页

C
2,136
字号
 *  * @param rootp [i/o] 帽胳グラフのル〖トノ〖ドへのポインタ * </JA> * <EN> * Free all the words in a word graph. *  * @param rootp [i/o] pointer to root node of a word graph * </EN> * * @callgraph * @callergraph * */voidwordgraph_clean(WordGraph **rootp){  WordGraph *wg, *wtmp;  wg = *rootp;  while(wg != NULL) {    wtmp = wg->next;    wordgraph_free(wg);    wg = wtmp;  }  *rootp = NULL;}/*********************************************************************//* Post-processing of generated word arcs after search has been done *//**  * <JA> * 帽胳グラフ考さカットのための qsort 脱コ〖ルバック. fscore_head で * 惯界にソ〖トする.  *  * @param x [in] 妥燎1 * @param y [in] 妥燎2 *  * @return qsort に洁じた手り猛 * </JA> * <EN> * Callback function for qsort to do word graph depth cutting. Graph * words will be sorted downward based on fscore_head. *  * @param x [in] element 1 * @param y [in] element 2 *  * @return values for qsort * </EN> */static intcompare_beam(WordGraph **x, WordGraph **y){  if ((*x)->fscore_head < (*y)->fscore_head) return 1;  else if ((*x)->fscore_head > (*y)->fscore_head) return -1;  else return 0;}/**  * <JA> * @brief  グラフ稿借妄その1¨介袋帽胳グラフの藐叫.  *  * 玫瑚面に栏喇された帽胳铬输礁圭から·琐眉から幌まるパス惧に痰いleaf帽胳を * 猴近することで介袋帽胳グラフを藐叫する.  *  * @param rootp [i/o] 帽胳グラフのル〖トノ〖ドへのポインタ * @param r [in] 千急借妄インスタンス * </JA> * <EN> * @brief  Post-processing step 1: Extract initial word graph. *  * Extract initial word graph from generated word arcs while search, by * purging leaf nodes and arcs that are not on the path from edge to edge. *  * @param rootp [i/o] pointer to root node of a word graph * @param r [in] recognition process instance * </EN> * * @callgraph * @callergraph *  */voidwordgraph_purge_leaf_nodes(WordGraph **rootp, RecogProcess *r){  WordGraph *wg;  int i, dst;  boolean changed;  int count, erased, del_left, del_right;  /* count whole */  count = 0;  for(wg=*rootp;wg;wg=wg->next) count++;  if (verbose_flag) jlog("STAT: graphout: %d initial word arcs generated\n", count);  if (count == 0) return;    if (verbose_flag) jlog("STAT: graphout: step 1: purge leaf nodes\n");  /* mark words to be erased */  del_left = del_right = 0;  do {    changed = FALSE;    for(wg=*rootp;wg;wg=wg->next) {      if (wg->mark == TRUE) continue;      /* mark if wg has no left context, or all leftwords are marked */      if (wg->lefttime != 0) {	for(i=0;i<wg->leftwordnum;i++) {	  if (wg->leftword[i]->mark == FALSE) break;	}	if (i >= wg->leftwordnum) {	  wg->mark = TRUE;	  changed = TRUE;	  del_left++;	  continue;	}      }      /* mark if wg has no right context, or all rightwords are marked */      if (wg->righttime != r->peseqlen - 1) {	for(i=0;i<wg->rightwordnum;i++) {	  if (wg->rightword[i]->mark == FALSE) break;	}	if (i >= wg->rightwordnum) {	  wg->mark = TRUE;	  changed = TRUE;	  del_right++;	  continue;	}      }    }  } while (changed == TRUE);  if (verbose_flag) jlog("STAT: graphout: %d leaf words found (left_blank=%d, right_blank=%d)\n", del_left + del_right, del_left, del_right);  /* do compaction of left/rightwords */    for(wg=*rootp;wg;wg=wg->next) {      if (wg->mark) continue;      dst = 0;      for(i=0;i<wg->leftwordnum;i++) {	if (wg->leftword[i]->mark == FALSE) {	  if (dst != i) {	    wg->leftword[dst] = wg->leftword[i];	    wg->left_lscore[dst] = wg->left_lscore[i];	  }	  dst++;	}      }      wg->leftwordnum = dst;    }    for(wg=*rootp;wg;wg=wg->next) {      if (wg->mark) continue;      dst = 0;      for(i=0;i<wg->rightwordnum;i++) {	if (wg->rightword[i]->mark == FALSE) {	  if (dst != i) {	    wg->rightword[dst] = wg->rightword[i];	    wg->right_lscore[dst] = wg->right_lscore[i];	  }	  dst++;	}      }      wg->rightwordnum = dst;    }  /* execute erase of marked words */  erased = wordgraph_exec_erase(rootp);  if (verbose_flag) jlog("STAT: graphout: %d words purged, %d words left in lattice\n", erased, count - erased);}/**  * <JA> * @brief  グラフ稿借妄その1. 5¨グラフの考さによる帽胳铬输のカット *  * GRAPHOUT_DEPTHCUT 回年箕·グラフの考さによる帽胳铬输のカットを乖う.  *  * @param rootp [i/o] 帽胳グラフのル〖トノ〖ドへのポインタ * @param r [in] 千急借妄インスタンス * </JA> * <EN> * @brief  Post-processing step 1.5: word graph depth cutting *  * If GRAPHOUT_DEPTHCUT is defined, perform word graph depth cutting. *  * @param rootp [i/o] pointer to root node of a word graph * @param r [in] recognition process instance * </EN> * * @callgraph * @callergraph *  */voidwordgraph_depth_cut(WordGraph **rootp, RecogProcess *r){#ifdef GRAPHOUT_DEPTHCUT  WordGraph *wg;  int i, dst;  boolean changed;  int count, erased, del_left, del_right;  WordGraph **wlist;  boolean f;  int *wc;  int t;  int pruned;  if (r->config->graph.graphout_cut_depth < 0) return;  if (verbose_flag) jlog("STAT: graphout: step 1.5: cut less likely hypothesis by depth of %d\n", r->config->graph.graphout_cut_depth);  /* count whole */  count = 0;  for(wg=*rootp;wg;wg=wg->next) count++;  if (count == 0) return;    /* prepare buffer to count words per frame */  wc = (int *)mymalloc(sizeof(int) * r->peseqlen);  for (t=0;t<r->peseqlen;t++) wc[t] = 0;  /* sort words by fscore_head */  wlist = (WordGraph **)mymalloc(sizeof(WordGraph *) * count);  i = 0;  for(wg=*rootp;wg;wg=wg->next) {    wlist[i++] = wg;  }  qsort(wlist, count, sizeof(WordGraph *), (int (*)(const void *, const void *))compare_beam);  /* count words per frame, and unlink/mark them if below beam width */  pruned = 0;  for (i=0;i<count;i++) {    wg = wlist[i];    f = TRUE;    for (t=wg->lefttime;t<=wg->righttime;t++) {      wc[t]++;      if (wc[t] <= r->config->graph.graphout_cut_depth) f = FALSE;    }    if (f) {      //wordgraph_remove_context(wg);      wg->mark = TRUE;      pruned++;    }  }#ifdef GDEBUG2  jlog("DEBUG: GRAPH DEPTH STATISTICS: NUMBER OF WORDS PER FRAME\n");  for(t=0;t<r->peseqlen;t++) {    if (wc[t] > r->config->graph.graphout_cut_depth) {      jlog("*");    } else {      jlog(" ");    }    jlog("%4d: %d\n", t, wc[t]);  }#endif  if (verbose_flag) jlog("STAT: graphout: %d words out of %d are going to be pruned by depth cutting\n", pruned, count);  free(wlist);  free(wc);  /* mark words to be erased */  del_left = del_right = 0;  do {    changed = FALSE;    for(wg=*rootp;wg;wg=wg->next) {      if (wg->mark == TRUE) continue;      /* mark if wg has no left context, or all leftwords are marked */      if (wg->lefttime != 0) {	for(i=0;i<wg->leftwordnum;i++) {	  if (wg->leftword[i]->mark == FALSE) break;	}	if (i >= wg->leftwordnum) {	  wg->mark = TRUE;	  changed = TRUE;	  del_left++;	  continue;	}      }      /* mark if wg has no right context, or all rightwords are marked */      if (wg->righttime != r->peseqlen - 1) {	for(i=0;i<wg->rightwordnum;i++) {	  if (wg->rightword[i]->mark == FALSE) break;	}	if (i >= wg->rightwordnum) {	  wg->mark = TRUE;	  changed = TRUE;	  del_right++;	  continue;	}      }    }  } while (changed == TRUE);  if (verbose_flag) jlog("STAT: graphout: %d new leaves found (left_blank=%d, right_blank=%d)\n", del_left + del_right, del_left, del_right);  /* do compaction of left/rightwords */    for(wg=*rootp;wg;wg=wg->next) {      if (wg->mark) continue;      dst = 0;      for(i=0;i<wg->leftwordnum;i++) {	if (wg->leftword[i]->mark == FALSE) {	  if (dst != i) {	    wg->leftword[dst] = wg->leftword[i];	    wg->left_lscore[dst] = wg->left_lscore[i];	  }	  dst++;	}      }      wg->leftwordnum = dst;    }    for(wg=*rootp;wg;wg=wg->next) {      if (wg->mark) continue;      dst = 0;      for(i=0;i<wg->rightwordnum;i++) {	if (wg->rightword[i]->mark == FALSE) {	  if (dst != i) {	    wg->rightword[dst] = wg->rightword[i];	    wg->right_lscore[dst] = wg->right_lscore[i];	  }	  dst++;	}      }      wg->rightwordnum = dst;    }  /* execute erase of marked words */  erased = wordgraph_exec_erase(rootp);  if (verbose_flag) jlog("STAT: graphout: total %d words purged, %d words left in lattice\n", erased, count - erased);#else  /* ~GRAPHOUT_DEPTHCUT */  if (verbose_flag) jlog("STAT: graphout: step 1.5: graph depth cutting has been disabled, skipped\n");#endif}/**  * <JA> * 帽胳粗の董肠攫鼠のずれ输赖を悸乖する. グラフ面の帽胳をチェックし, * 儡鲁帽胳粗で董肠箕粗攫鼠にずれがあるときは·そのずれを饯赖する.  * 剩眶のコンテキスト粗で佰なる董肠攫鼠が赂哼する眷圭は,铬输を * コピ〖してそれぞれに圭わせる. またアラインメントが稍赖な帽胳を近殿する.  *  * @param rootp [i/o] グラフ帽胳リストのル〖トポインタ * @param mov_num_ret [out] 董肠箕粗が瓢いた帽胳眶を呈羌する恃眶へのポインタ * @param dup_num_ret [out] コピ〖された帽胳眶を呈羌する恃眶へのポインタ * @param del_num_ret [out] 猴近された帽胳眶を呈羌する恃眶へのポインタ * @param mod_num_ret [out] 恃构された帽胳眶を呈羌する恃眶へのポインタ * @param count [in] グラフ惧の帽胳眶 * @param maxfnum * @param peseqlen * @param lmtype * @param p_framelist * @param p_framescorelist *  * @return グラフ柒の帽胳が1つ笆惧恃构されれば TRUE·恃构なしであれば FALSE * を手す.  * </JA> * <EN> * Execute adjustment of word boundaries.  It looks through the graph to * check correspondence of word boundary information among context, and if * there is a gap, the beginning frame of right word will be moved to the * end frame of left word.  If several alignment is found among contexts, * the word will be duplicated and each will be fit to each context.  Also, * words with invalid alignment will be eliminated. *  * @param rootp [in] root pointer to the list of graph words * @param mov_num_ret [out] pointer to hold resulted number of moved words * @param dup_num_ret [out] pointer to hold resulted number of duplicated words * @param del_num_ret [out] pointer to hold resulted number of eliminated words * @param mod_num_ret [out] pointer to hold resulted number of modified words * @param count [in] number of words in graph * @param maxfnum * @param peseqlen * @param lmtype * @param p_framelist * @param p_framescorelist *  * @return TRUE if any word has been changed, or FALSE if no word has been altered. * </EN> */static booleanwordgraph_adjust_boundary_sub(WordGraph **rootp, int *mov_num_ret, int *dup_num_ret, int *del_num_ret, int *mod_num_ret, int count, int *maxfnum, int peseqlen, int lmtype, int **p_framelist, LOGPROB **p_framescorelist){  WordGraph *wg, *left, *new;  int i, j, k;  int fnum;  int mov_num, dup_num, del_num, mod_num;  boolean changed = FALSE;  int *framelist;  LOGPROB *framescorelist;  mov_num = dup_num = del_num = mod_num = 0;  framelist = *p_framelist;  framescorelist = *p_framescorelist;  /* maximum number of left context words does not exceed total word num */  /* allocate temporal work area.  these are permanent buffer that will     be kept between recognition sessions. */  if (*maxfnum == 0) {    /* when this is called for the first time, allocate buffer */    *maxfnum = count;    framelist = (int *)mymalloc(sizeof(int) * (*maxfnum));    framescorelist = (LOGPROB *)mymalloc(sizeof(LOGPROB) * (*maxfnum));#ifdef GDEBUG    jlog("DEBUG: Notice: maxfnum starts at %d\n", *maxfnum);#endif  } else if (*maxfnum < count) {    /* for later call, expand buffer if necessary */    free(framescorelist);    free(framelist);    *maxfnum = count;    framelist = (int *)mymalloc(sizeof(int) * (*maxfnum));    framescorelist = (LOGPROB *)mymalloc(sizeof(LOGPROB) * (*maxfnum));#ifdef GDEBUG    jlog("DEBUG: Notice: maxfnum expanded by count (%d)\n", *maxfnum);#endif  }#ifdef GDEBUG2  jlog("DEBUG: ***CHECK LOOP BEGIN***\n");#endif  for(wg=*rootp;wg;wg=wg->next) {    if (wg->mark) continue;	/* already marked */#ifdef GDEBUG2    jlog("DEBUG:   [%d..%d] \"%s\"\n", wg->lefttime, wg->righttime, wchmm_local->winfo->woutput[wg->wid]);#endif    if (wg->leftwordnum == 0) {	/* no leftword */      if (wg->lefttime != 0) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?