graphout.c

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

C
2,136
字号
	/* some fraction found by former elimination: remove this */#ifdef GDEBUG2	jlog("DEBUG:   -> no leftword at middle of lattice, eliminate this\n");#endif	wordgraph_remove_context(wg);	wg->mark = TRUE;	del_num++;	changed = TRUE;      }      /* if has no leftword, adjustment of this word is not needed */      continue;    }    if (wg->rightwordnum == 0) {	/* no rightword */      if (wg->righttime != peseqlen-1) {	/* some fraction found by former elimination: remove this */#ifdef GDEBUG2	jlog("DEBUG:   -> no rightword at middle of lattice, eliminate this\n");#endif	wordgraph_remove_context(wg);	wg->mark = TRUE;	del_num++;	changed = TRUE;	continue;      }      /* if on right edge, continue adjusting */    }    /* correct lefttime variation to framelist[] and framescorelist[] */    fnum = 0;    /* check for buffer overrun */    if (wg->leftwordnum > (*maxfnum)) {      /* expand buffer if necessary */      free(framescorelist);      free(framelist);      *maxfnum = wg->leftwordnum;      framelist = (int *)mymalloc(sizeof(int) * (*maxfnum));      framescorelist = (LOGPROB *)mymalloc(sizeof(LOGPROB) * (*maxfnum));#ifdef GDEBUG      jlog("DEBUG: Notice: wg->leftwordnum exceeds maxfnum (%d > %d), expanded\n", wg->leftwordnum, *maxfnum);#endif    }    for(i=0;i<wg->leftwordnum;i++) {      left = wg->leftword[i];      if (left->mark) continue;      for(j=0;j<fnum;j++) {	if (framelist[j] == left->righttime + 1) break;      }      if (j >= fnum) {	framelist[fnum] = left->righttime + 1;	/* the tail gscore contains the language score of the word,	   so the head gscore of its right context should consider this */	framescorelist[fnum] = left->gscore_tail - wg->left_lscore[i];	fnum++;      }    }#ifdef GDEBUG2    jlog("DEBUG:   possible boundary of left words:");    if (fnum == 0) {      jlog(" (not exist)\n");    } else {      for(j=0;j<fnum;j++) jlog(" %d", framelist[j]);      jlog("\n");    }#endif    if (fnum == 0) continue;	/* no left context */    /* one candidate: just move the original (or not move) */    if (fnum == 1) {      if (wg->lefttime != framelist[0]) {#ifdef GDEBUG2	jlog("DEBUG:     !moving as [%d..%d]", framelist[0], wg->righttime);#endif	/* check the time correctness: if the lefttime is larger than	   righttime, this graph word has been completely overridden by	   the left word (i.e. the aligned frames are absorbed by	   re-alignment.  In this case this word should be removed.	*/	if (framelist[0] > wg->righttime) {#ifdef GDEBUG2	  jlog(" : eliminated");#endif	  wordgraph_link_context(wg);	  wordgraph_remove_context(wg);	  wg->mark = TRUE;	  del_num++;	} else {#ifdef GDEBUG2	  jlog(" : ok");#endif	  /* adjust time and score */	  wg->lefttime = framelist[0];	  wg->gscore_head = framescorelist[0];	  mov_num++;	}#ifdef GDEBUG2	jlog("\n");#endif	changed = TRUE;      } else if (wg->gscore_head != framescorelist[0]) {	/* adjust only score */#ifdef GDEBUG2	jlog("DEBUG:     !ghead score changed: %f -> %f\n", wg->gscore_head, framescorelist[0]);#endif	wg->gscore_head = framescorelist[0];	mod_num++;	changed = TRUE;      }    }    if (fnum > 1) {      /* multiple candidate: make copy for each (fnum)*/      for(j=0;j<fnum;j++) {	/* duplicate */	dup_num++;#ifdef GDEBUG2	jlog("DEBUG:     !duping as [%d..%d]", framelist[j], wg->righttime);#endif		if (framelist[j] > wg->righttime) {	  /* bogus link: link leftwords and rightwords, and delete this */#ifdef GDEBUG2	  jlog(" : eliminated");#endif	  for(i=0;i<wg->leftwordnum;i++) {	    left = wg->leftword[i];	    if (left->mark) continue;	    if (left->righttime + 1 == framelist[j]) {	      for(k=0;k<wg->rightwordnum;k++) {		if ((wg->rightword[k])->mark) continue;		if (wg->rightword[k] == left) continue;		wordgraph_check_and_add_leftword(wg->rightword[k], left, wg->left_lscore[i]);		wordgraph_check_and_add_rightword(left, wg->rightword[k], wg->right_lscore[k]);	      }	    }	  }	  del_num++;	  	} else {	  /* really duplicate */#ifdef GDEBUG2	  jlog(" : ok");#endif	  new = wordgraph_new(wg->wid, wg->headphone, wg->tailphone, framelist[j], wg->righttime, wg->fscore_head, wg->fscore_tail, framescorelist[j], wg->gscore_tail, wg->lscore_tmp#ifdef CM_SEARCH			      , wg->cmscore#else			      , LOG_ZERO#endif			      );	  /* copy corresponding link */	  for(i=0;i<wg->leftwordnum;i++) {	    if ((wg->leftword[i])->mark) continue;	    if ((wg->leftword[i])->righttime + 1 == framelist[j]) {	      wordgraph_add_leftword(new, wg->leftword[i], wg->left_lscore[i]);	      wordgraph_add_rightword(wg->leftword[i], new, wg->left_lscore[i]);	    }	  }	  for(i=0;i<wg->rightwordnum;i++) {	    if ((wg->rightword[i])->mark) continue;	    wordgraph_add_rightword(new, wg->rightword[i], wg->right_lscore[i]);	    wordgraph_add_leftword(wg->rightword[i], new, wg->right_lscore[i]);	  }	  new->saved = TRUE;	  new->next = *rootp;	  *rootp = new;	}#ifdef GDEBUG2	jlog("\n");#endif      }            /* remove the original */#ifdef GDEBUG2      jlog("DEBUG:     !delete original [%d..%d]\n", wg->lefttime, wg->righttime);#endif      wordgraph_remove_context(wg);      wg->mark = TRUE;      dup_num--;            changed = TRUE;    }  }  *mov_num_ret = mov_num;  *dup_num_ret = dup_num;  *del_num_ret = del_num;  *mod_num_ret = mod_num;  *p_framelist = framelist;  *p_framescorelist = framescorelist;#ifdef GDEBUG2  if (changed) {    jlog("DEBUG: *** some graph has been altered, check loop continues\n");  } else {    jlog("DEBUG: *** graph not changed at last loop, check ends here\n");  }#endif  return (changed);}/**  * <JA> * グラフ柒に董肠攫鼠やスコアが链く票办の帽胳がある眷圭それらをマ〖ジする.  *  * @param rootp [i/o] グラフ帽胳リストのル〖トポインタ * @param rest_ret [out] マ〖ジ稿のグラフ柒の帽胳眶を手すポインタ * @param merged_ret [out] マ〖ジされた帽胳眶を手すポインタ * </JA> * <EN> * Merge duplicated words with exactly the same scores and alignments. *  * @param rootp [i/o] root pointer to the list of graph words * @param rest_ret [out] pointer to hold resulted number of words left in graph * @param merged_ret [out] pointer to hold resuled number of merged words * </EN> */static voidwordgraph_compaction_thesame_sub(WordGraph **rootp, int *rest_ret, int *merged_ret){  WordGraph *wg, *we;  int i, count, erased, merged;  count = 0;  merged = 0;  for(wg=*rootp;wg;wg=wg->next) {    count++;    if (wg->mark == TRUE) continue;    for(we=wg->next;we;we=we->next) {      if (we->mark == TRUE) continue;      /* find the word with exactly the same time and score */      if (wg->wid == we->wid &&	  wg->headphone == we->headphone &&	  wg->tailphone == we->tailphone &&	  wg->lefttime == we->lefttime &&	  wg->righttime == we->righttime &&	  wg->fscore_head == we->fscore_head &&	  wg->fscore_tail == we->fscore_tail) {	/* merge contexts */	merge_contexts(wg, we);	/* swap contexts of left / right contexts */	for(i=0;i<we->leftwordnum;i++) {	  if (we->leftword[i]->mark) continue;	  //if (we->leftword[i] == wg) continue;	  swap_rightword(we->leftword[i], we, wg, we->left_lscore[i]);	}	for(i=0;i<we->rightwordnum;i++) {	  if (we->rightword[i]->mark) continue;	  //if (we->rightword[i] == wg) continue;	  swap_leftword(we->rightword[i], we, wg, we->right_lscore[i]);	}	we->mark = TRUE;	merged++;      }    }  }  erased = wordgraph_exec_erase(rootp);  for(wg=*rootp;wg;wg=wg->next) {    uniq_leftword(wg);    uniq_rightword(wg);  }  *rest_ret = count - erased;  *merged_ret = merged;}/**  * <JA> * @brief  グラフ稿借妄その2¨帽胳董肠攫鼠の拇腊.  *  * GRAPHOUT_PRECISE_BOUNDARY 年盗箕·稿鲁帽胳に巴赂した赖澄な帽胳董肠 * を评るために·玫瑚面において·グラフ帽胳を栏喇したあとに肌搀鸥倡箕に * 祸稿弄に帽胳董肠を败瓢させる. このため·涟稿の帽胳のもつ∈败瓢涟の∷ * 董肠攫鼠との滦炳がとれなくなるので·玫瑚姜位稿に称帽胳の涟稿の帽胳へ * 赖しい帽胳董肠を帕嚷させることで腊圭拉をとる.  * * 帽胳董肠のずれは帽胳粗で帕嚷するため·すべての帽胳董肠が瓢かなくなるまで * 拇腊が帆り手される. 叼络なグラフでは没い帽胳の狮きだしで借妄が姜わらない * 眷圭があるが·この眷圭 GRAPHOUT_LIMIT_BOUNDARY_LOOP を回年することで· * 帆り手す眶の惧嘎を graphout_limit_boundary_loop_num に扩嘎できる.  *  * @param rootp [i/o] 帽胳グラフのル〖トノ〖ドへのポインタ * @param r [i/o] 千急借妄インスタンス * </JA> * <EN> * @brief  Post-processing step 2: Adjust word boundaries. *  * When GRAPHOUT_PRECISE_BOUNDARY is defined, the word boundaries will be * moved depending on the later word expansion to get context-dependent * precise boundaries.  So the precise boundary, modified after generation * while search, should be propagated to the context words in the post * processing. * * Since the affect of word boundaries may propagate to the context words, * the adjustment procedure has to be executed iteratively until all the * boundaries are fixated.  However, when graph is large, the oscillation of * short words will results in very long loop.  By defining * GRAPHOUT_LIMIT_BOUNDARY_LOOP, the number of the adjustment loop can be * up to the number specified by graphout_limit_bounrady_loop_num. *  * @param rootp [i/o] pointer to root node of a word graph * @param r [i/o] recognition process instance * </EN> * * @callgraph * @callergraph *  */voidwordgraph_adjust_boundary(WordGraph **rootp, RecogProcess *r){#ifdef GRAPHOUT_PRECISE_BOUNDARY  WordGraph *wg;  int mov_num, dup_num, del_num, mod_num;  int count, merged;  boolean flag;  int loopcount;  int maxfnum;  int *framelist;		///< frame list for adjust_boundary_sub  LOGPROB *framescorelist;	///< frame score list for adjust_boundary_sub  loopcount = 0;  if (verbose_flag) jlog("STAT: graphout: step 2: adjust boundaries\n");  mov_num = dup_num = del_num = 0;  /* count number of all words */  count = 0;  for(wg=*rootp;wg;wg=wg->next) count++;  maxfnum = 0;  do {    /* do adjust */    flag = wordgraph_adjust_boundary_sub(rootp, &mov_num, &dup_num, &del_num, &mod_num, count, &maxfnum, r->peseqlen, r->lmtype, &framelist, &framescorelist);    /* do compaction */    wordgraph_compaction_thesame_sub(rootp, &count, &merged);    if (verbose_flag) jlog("STAT: graphout: #%d: %d moved, %d duplicated, %d purged, %d modified, %d idential, %d left\n", loopcount + 1, mov_num, dup_num, del_num, mod_num, merged, count);#ifdef GRAPHOUT_LIMIT_BOUNDARY_LOOP    if (++loopcount >= r->config->graph.graphout_limit_boundary_loop_num) {      if (verbose_flag) jlog("STAT: graphout: loop count reached %d, terminate loop now\n", r->config->graph.graphout_limit_boundary_loop_num);      break;    }#endif  } while (flag);  /* free work area allocated in adjust_boundary_sub */  if (maxfnum > 0) {    free(framescorelist);    free(framelist);  }  /* execute erase of marked words */  wordgraph_exec_erase(rootp);#else  if (verbose_flag) jlog("STAT: graphout: step 2: SKIP (adjusting boundaries)\n");#endif /* GRAPHOUT_PRECISE_BOUNDARY */} /**  * <JA> * @brief  グラフ稿借妄その3¨帽胳の芦ね∈窗链票办∷ *  * 帽胳董肠箕癸と婶尸矢簿棱スコアが窗链に办米する票じ帽胳どうしを办つに芦ねる.  *  * @param rootp [i/o] 帽胳グラフのル〖トノ〖ドへのポインタ * </JA> * <EN> * @brief  Post-processing step 3: Bundle words (exactly the same ones) *  * This function bundles same words which have exactly the same * boundaries and partial sentence scores. *  * @param rootp [i/o] pointer to root node of a word graph * </EN> * * @callgraph * @callergraph *  */voidwordgraph_compaction_thesame(WordGraph **rootp){  int rest, erased;  if (verbose_flag) jlog("STAT: graphout: step 3: merge idential hypotheses (same score, boundary, context)\n");  wordgraph_compaction_thesame_sub(rootp, &rest, &erased);  if (verbose_flag) jlog("STAT: graphout: %d words merged, %d words left in lattice\n", erased, rest);}/**  * <JA> * @brief  グラフ稿借妄その4¨帽胳の芦ね∈惰粗票办∷ *  * 帽胳董肠箕癸が办米する票じ帽胳どうしを办つに芦ねる. スコアが * 票办でなくても芦ねられる. この眷圭·婶尸矢スコアが呵も光い铬输が * 荒る. graph_merge_neighbor_range が 砷 の眷圭は悸乖されない.  *  * @param rootp [i/o] 帽胳グラフのル〖トノ〖ドへのポインタ * @param r [i/o] 千急借妄インスタンス * </JA> * <EN> * @brief  Post-processing step 4: Bundle words (same boundaries) *  * This function bundles the same words which have exactly the same * boundaries, allowing having different scores.  The word with * the best partial sentence score will be adopted.  This function * will not take effect when graph_merge_neightbor_range is lower than 0. *  * @param rootp [i/o] pointer to root node of a word graph * @param r [i/o] recognition process instance * </EN> * * @callgraph * @callergraph * */voidwordgraph_compaction_exacttime(WordGraph **rootp, RecogProcess *r){  WordGraph *wg, *we;  int i, count, erased;

⌨️ 快捷键说明

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