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 + -
显示快捷键?