graphout.c

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

C
2,136
字号
/** * @file   graphout.c *  * <JA> * @brief  帽胳ラティスの栏喇. * </JA> *  * <EN> * @brief  Output word lattice. * </EN> *  * @author Akinobu LEE * @date   Thu Mar 17 12:46:31 2005 * * $Revision: 1.5 $ *  *//* * Copyright (c) 1991-2007 Kawahara Lab., Kyoto University * Copyright (c) 2000-2005 Shikano Lab., Nara Institute of Science and Technology * Copyright (c) 2005-2007 Julius project team, Nagoya Institute of Technology * All rights reserved */#include <julius/julius.h>/// Define if you want debugging output for graph generation#undef GDEBUG/// Define if you want much more debugging output for graph generation#undef GDEBUG2#if defined(GDEBUG) || defined(GDEBUG2)static WCHMM_INFO *wchmm_local;	///< Local copy, just for debug#endif/**  * <JA> * グラフ叫蜗を介袋步する. 附哼はデバッグ脱借妄のみ.  *  * @param wchmm [in] 腾菇陇步辑今 * </JA> * <EN> * Initialize data for graphout. *  * @param wchmm [in] tree lexicon * </EN> * * @callgraph * @callergraph *  */voidwordgraph_init(WCHMM_INFO *wchmm){#if defined(GDEBUG) || defined(GDEBUG2)  wchmm_local = wchmm;#endif}/**************************************************************//* allocation and free of a WordGraph instance *//**  * <JA> * グラフ帽胳を糠たに栏喇し·そのポインタを手す.  *  * @param wid [in] 帽胳ID * @param headphone [in] 帽胳黎片の不燎 * @param tailphone [in] 帽胳琐眉の不燎 * @param leftframe [in] 幌眉箕癸(フレ〖ム) * @param rightframe [in] 姜眉箕癸(フレ〖ム) * @param fscore_head [in] 幌眉での婶尸矢スコア (g + h) * @param fscore_tail [in] 姜眉での婶尸矢スコア (g + h) * @param gscore_head [in] 黎片での掐蜗琐眉からのViterbiスコア (g) * @param gscore_tail [in] 琐萨での掐蜗琐眉からのViterbiスコア (g) * @param lscore [in] 帽胳の咐胳スコア (Julian では猛に罢蹋なし) * @param cm [in] 帽胳の慨完刨スコア (玫瑚箕に瓢弄に纷换されたもの) *  * @return 糠たに栏喇されたグラフ帽胳へのポインタ * </JA> * <EN> * Allocate a new graph word and return a new pointer to it. *  * @param wid [in] word ID * @param headphone [in] phoneme on head of word * @param tailphone [in] phoneme on tail of word * @param leftframe [in] beginning time in frames * @param rightframe [in] end time in frames * @param fscore_head [in] sentence score on search at word head (g + h) * @param fscore_tail [in] sentence score on search at word tail (g + h) * @param gscore_head [in] Viterbi score accumulated from input end at word head (g) * @param gscore_tail [in] Viterbi score accumulated from input end at word tail (g) * @param lscore [in] language score of the word (bogus in Julian) * @param cm [in] word confidence score (computed on search time) *  * @return pointer to the newly created graph word. * </EN> */static WordGraph *wordgraph_new(WORD_ID wid, HMM_Logical *headphone, HMM_Logical *tailphone, int leftframe, int rightframe, LOGPROB fscore_head, LOGPROB fscore_tail, LOGPROB gscore_head, LOGPROB gscore_tail, LOGPROB lscore, LOGPROB cm){  WordGraph *new;  new = (WordGraph *)mymalloc(sizeof(WordGraph));  new->wid = wid;  new->lefttime = leftframe;  new->righttime = rightframe;  new->fscore_head = fscore_head;  new->fscore_tail = fscore_tail;  new->gscore_head = gscore_head;  new->gscore_tail = gscore_tail;  new->lscore_tmp = lscore;		/* n-gram only */#ifdef CM_SEARCH  new->cmscore = cm;#endif  new->forward_score = new->backward_score = 0.0;  if (rightframe - leftframe + 1 != 0) {    //new->amavg = (gscore_head - gscore_tail - lscore) / (float)(rightframe - leftframe + 1);    new->amavg = (gscore_head - gscore_tail) / (float)(rightframe - leftframe + 1);  }  new->headphone = headphone;  new->tailphone = tailphone;  new->leftwordmaxnum = FANOUTSTEP;  new->leftword = (WordGraph **)mymalloc(sizeof(WordGraph *) * new->leftwordmaxnum);  new->left_lscore = (LOGPROB *)mymalloc(sizeof(LOGPROB) * new->leftwordmaxnum);  new->leftwordnum = 0;  new->rightwordmaxnum = FANOUTSTEP;  new->rightword = (WordGraph **)mymalloc(sizeof(WordGraph *) * new->rightwordmaxnum);  new->right_lscore = (LOGPROB *)mymalloc(sizeof(LOGPROB) * new->rightwordmaxnum);  new->rightwordnum = 0;  new->mark = FALSE;#ifdef GRAPHOUT_DYNAMIC  new->purged = FALSE;#endif  new->next = NULL;  new->saved = FALSE;  new->graph_cm = 0.0;#ifdef GDEBUG {   int i;   WordGraph *w;   jlog("DEBUG: NEW: \"%s\"[%d..%d]\n", wchmm_local->winfo->woutput[new->wid], new->lefttime, new->righttime);   for(i=0;i<new->leftwordnum;i++) {     w = new->leftword[i];     jlog("DEBUG: \t left%d:  \"%15s\"[%d..%d]\n", i, wchmm_local->winfo->woutput[w->wid], w->lefttime, w->righttime);   }   for(i=0;i<new->rightwordnum;i++) {     w = new->rightword[i];     jlog("DEBUG: \tright%d:  \"%15s\"[%d..%d]\n", i, wchmm_local->winfo->woutput[w->wid], w->lefttime, w->righttime);   }   jlog("DEBUG: \headphone: %s\n", new->headphone->name);   jlog("DEBUG: \tailphone: %s\n", new->tailphone->name); }#endif  return(new);}/**  * <JA> * あるグラフ帽胳のメモリ挝拌を豺庶する.  *  * @param wg [in] グラフ帽胳 * </JA> * <EN> * Free a graph word. *  * @param wg [in] graph word to be freed. * </EN> * * @callgraph * @callergraph *  */voidwordgraph_free(WordGraph *wg){  free(wg->rightword);  free(wg->right_lscore);  free(wg->leftword);  free(wg->left_lscore);  free(wg);}/**************************************************************//* Handling contexts *//**  * <JA> * あるグラフ帽胳の焊コンテキストに糠たなグラフ帽胳を纳裁する.  *  * @param wg [i/o] 纳裁黎のグラフ帽胳 * @param left [in] @a wg の焊コンテキストとして纳裁されるグラフ帽胳 * @param lscore [in] 儡鲁咐胳スコア * </JA> * <EN> * Add a graph word as a new left context. *  * @param wg [i/o] word graph to which the @a left word will be added as left context. * @param left [in] word graph which will be added to the @a wg as left context. * @param lscore [in] word connection score * </EN> */static voidwordgraph_add_leftword(WordGraph *wg, WordGraph *left, LOGPROB lscore){  if (wg == NULL) return;  if (left == NULL) return;  if (wg->leftwordnum >= wg->leftwordmaxnum) {    /* expand */    wg->leftwordmaxnum += FANOUTSTEP;    wg->leftword = (WordGraph **)myrealloc(wg->leftword, sizeof(WordGraph *) * wg->leftwordmaxnum);    wg->left_lscore = (LOGPROB *)myrealloc(wg->left_lscore, sizeof(LOGPROB) * wg->leftwordmaxnum);  }  wg->leftword[wg->leftwordnum] = left;  wg->left_lscore[wg->leftwordnum] = lscore;  wg->leftwordnum++;#ifdef GDEBUG  jlog("DEBUG: addleft: \"%s\"[%d..%d] added as %dth left of \"%s\"[%d..%d]\n", wchmm_local->winfo->woutput[left->wid], left->lefttime, left->righttime, wg->leftwordnum, wchmm_local->winfo->woutput[wg->wid], wg->lefttime, wg->righttime);#endif}/**  * <JA> * あるグラフ帽胳の宝コンテキストに糠たなグラフ帽胳を纳裁する.  *  * @param wg [i/o] 纳裁黎のグラフ帽胳 * @param right [in] @a wg の宝コンテキストとして纳裁されるグラフ帽胳 * @param lscore [in] 儡鲁咐胳スコア * </JA> * <EN> * Add a graph word as a new right context. *  * @param wg [i/o] word graph to which the @a right word will be added as * right context. * @param right [in] word graph which will be added to the @a wg as right * context. * @param lscore [in] word connection score * </EN> */static voidwordgraph_add_rightword(WordGraph *wg, WordGraph *right, LOGPROB lscore){  if (wg == NULL) return;  if (right == NULL) return;  if (wg->rightwordnum >= wg->rightwordmaxnum) {    /* expand */    wg->rightwordmaxnum += FANOUTSTEP;    wg->rightword = (WordGraph **)myrealloc(wg->rightword, sizeof(WordGraph *) * wg->rightwordmaxnum);    wg->right_lscore = (LOGPROB *)myrealloc(wg->right_lscore, sizeof(LOGPROB) * wg->rightwordmaxnum);  }  wg->rightword[wg->rightwordnum] = right;  wg->right_lscore[wg->rightwordnum] = lscore;  wg->rightwordnum++;#ifdef GDEBUG  jlog("DEBUG: addright: \"%s\"[%d..%d] added as %dth right of \"%s\"[%d..%d]\n", wchmm_local->winfo->woutput[right->wid], right->lefttime, right->righttime, wg->rightwordnum, wchmm_local->winfo->woutput[wg->wid], wg->lefttime, wg->righttime);#endif}/**  * <JA> * 焊コンテキストに回年したグラフ帽胳が贷にあるかどうかチェックし· * なければ纳裁する.  *  * @param wg [i/o] 拇べるグラフ帽胳 * @param left [in] このグラフ帽胳が @a wg の焊コンテキストにあるかチェックする * @param lscore [in] 儡鲁咐胳スコア *  * @return 票じグラフ帽胳が焊コンテキストに赂哼せず糠たに纳裁した眷圭は TRUE, * 焊コンテキストとして票じグラフ帽胳がすでに赂哼しており纳裁しなかった眷圭は * FALSEを手す.  * </JA> * <EN> * Check for the left context if the specified graph already exists, and * add it if not yet. *  * @param wg [i/o] graph word whose left context will be checked  * @param left [in] graph word to be checked as left context of @a wg * @param lscore [in] word connection score *  * @return TRUE if not exist yet and has been added, or FALSE if already * exist and thus not added. * </EN> * * @callgraph * @callergraph *  */booleanwordgraph_check_and_add_leftword(WordGraph *wg, WordGraph *left, LOGPROB lscore){  int i;  if (wg == NULL) return FALSE;  if (left == NULL) return FALSE;  for(i=0;i<wg->leftwordnum;i++) {    if (wg->leftword[i] == left) {      break;    }  }  if (i >= wg->leftwordnum) { /* no leftword matched */    wordgraph_add_leftword(wg, left, lscore);    return TRUE;  } else if (wg->left_lscore[i] < lscore) {    /* for same word connection, keep maximum LM score */    if (debug2_flag) jlog("DEBUG: check_and_add_leftword: update left\n");    wg->left_lscore[i] = lscore;  }  return FALSE;}/**  * <JA> * 宝コンテキストに回年したグラフ帽胳が贷にあるかどうかチェックし· * なければ纳裁する.  *  * @param wg [i/o] 拇べるグラフ帽胳 * @param right [in] このグラフ帽胳が @a wg の宝コンテキストにあるかチェックする * @param lscore [in] 儡鲁咐胳スコア *  * @return 票じグラフ帽胳が宝コンテキストに赂哼せず糠たに纳裁した眷圭は TRUE, * 宝コンテキストとして票じグラフ帽胳がすでに赂哼しており纳裁しなかった眷圭は * FALSEを手す.  * </JA> * <EN> * Check for the right context if the specified graph already exists, and * add it if not yet. *  * @param wg [i/o] graph word whose right context will be checked  * @param right [in] graph word to be checked as right context of @a wg * @param lscore [in] word connection score *  * @return TRUE if not exist yet and has been added, or FALSE if already * exist and thus not added. * </EN> * * @callgraph * @callergraph *  */booleanwordgraph_check_and_add_rightword(WordGraph *wg, WordGraph *right, LOGPROB lscore){  int i;  if (wg == NULL) return FALSE;  if (right == NULL) return FALSE;  for(i=0;i<wg->rightwordnum;i++) {    if (wg->rightword[i] == right) {      break;    }  }  if (i >= wg->rightwordnum) { /* no rightword matched */    wordgraph_add_rightword(wg, right, lscore);    return TRUE;  } else if (wg->right_lscore[i] < lscore) {    /* for same word connection, keep maximum LM score */    if (debug2_flag) jlog("DEBUG: check_and_add_rightword: update right\n");    wg->right_lscore[i] = lscore;  }  return FALSE;}/**  * <JA> * 票办グラフ帽胳のマ〖ジ箕に,帽胳グラフのコンテキストを链て侍の帽胳グラフに * 纳裁する.  *  * @param dst [i/o] 纳裁黎のグラフ帽胳 * @param src [in] 纳裁傅のグラフ帽胳 *  * @return 1つでも糠たに纳裁されれば TRUE, 1つも纳裁されなければ FALSE を手す.  * </JA> * <EN> * Add all the context words to other for merging the same two graph words. *  * @param dst [i/o] destination graph word * @param src [in] source graph word *  * @return TRUE if at least one context word has been newly added, or FALSE if * context on @a dst has not been updated. * </EN> */static booleanmerge_contexts(WordGraph *dst, WordGraph *src){  int s, d;  WordGraph *adding;  boolean ret;#ifdef GDEBUG  jlog("DEBUG: merge_contexts: merging context of \"%s\"[%d..%d] to \"%s\"[%d..%d]...\n",	 wchmm_local->winfo->woutput[src->wid], src->lefttime, src->righttime,	 wchmm_local->winfo->woutput[dst->wid], dst->lefttime, dst->righttime);#endif  ret = FALSE;    /* left context */  for(s=0;s<src->leftwordnum;s++) {    adding = src->leftword[s];    if (adding->mark) continue;    /* direct link between dst and src will disapper to avoid unneccesary loop */    if (adding == dst) {#ifdef GDEBUG      jlog("DEBUG: merge_contexts: skipping direct link (dst) -> (src)\n");#endif      continue;    }    for(d=0;d<dst->leftwordnum;d++) {      if (dst->leftword[d]->mark) continue;      if (dst->leftword[d] == adding) {	break;      }    }    if (d >= dst->leftwordnum) { /* no leftword matched */      wordgraph_add_leftword(dst, adding, src->left_lscore[s]);#ifdef GDEBUG      jlog("DEBUG: merge_contexts: added \"%s\"[%d..%d] as a new left context\n",	     wchmm_local->winfo->woutput[adding->wid], adding->lefttime, adding->righttime);#endif      ret = TRUE;    } else if (dst->left_lscore[d] < src->left_lscore[s]) {

⌨️ 快捷键说明

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