julius/search_bestfirst_v1.c

説明を見る。
00001 
00098 /*
00099  * Copyright (c) 1991-2006 Kawahara Lab., Kyoto University
00100  * Copyright (c) 2000-2005 Shikano Lab., Nara Institute of Science and Technology
00101  * Copyright (c) 2005-2006 Julius project team, Nagoya Institute of Technology
00102  * All rights reserved
00103  */
00104 
00105 #include <julius.h>
00106 
00107 #ifndef PASS2_STRICT_IWCD
00108 
00109 #undef TCD                      
00110 
00111 /**********************************************************************/
00112 /************ 仮説ノードの基本操作                         ************/
00113 /************ Basic functions for hypothesis node handling ************/
00114 /**********************************************************************/
00115 
00116 #undef STOCKER_DEBUG
00117 
00118 static NODE *stocker_root = NULL; 
00119 
00120 #ifdef STOCKER_DEBUG
00121 static int stocked_num = 0;
00122 static int reused_num = 0;
00123 static int new_num = 0;
00124 static int request_num = 0;
00125 #endif
00126 
00139 void
00140 free_node_exec(NODE *node)
00141 {
00142   if (node == NULL) return;
00143 
00144   free(node->g);
00145   if (ccd_flag) free(node->g_prev);
00146 #ifdef GRAPHOUT
00147 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00148   free(node->wordend_frame);
00149   free(node->wordend_gscore);
00150 #endif
00151 #endif
00152 
00153   free(node);
00154 }
00155 
00168 void
00169 free_node(NODE *node)
00170 {
00171   if (node == NULL) return;
00172 
00173 #ifdef GRAPHOUT
00174   if (node->prevgraph != NULL && node->prevgraph->saved == FALSE) {
00175     wordgraph_free(node->prevgraph);
00176   }
00177 #endif
00178 
00179   /* save to stocker */
00180   node->next = stocker_root;
00181   stocker_root = node;
00182 
00183 #ifdef STOCKER_DEBUG
00184   stocked_num++;
00185 #endif
00186 }
00187 
00198 void
00199 clear_stocker()
00200 {
00201   NODE *node, *tmp;
00202   node = stocker_root;
00203   while(node) {
00204     tmp = node->next;
00205     free_node_exec(node);
00206     node = tmp;
00207   }
00208   stocker_root = NULL;
00209 
00210 #ifdef STOCKER_DEBUG
00211   printf("%d times requested, %d times newly allocated, %d times reused\n", request_num, new_num, reused_num);
00212   stocked_num = 0;
00213   reused_num = 0;
00214   new_num = 0;
00215   request_num = 0;
00216 #endif
00217 }
00218 
00237 NODE *
00238 cpy_node(NODE *dst, NODE *src)
00239 {
00240   
00241   dst->next = src->next;
00242   dst->prev = src->prev;
00243   memcpy(dst->g, src->g, sizeof(LOGPROB) * peseqlen);
00244   memcpy(dst->seq, src->seq, sizeof(WORD_ID) * MAXSEQNUM);
00245 #ifdef CM_SEARCH
00246 #ifdef CM_MULTIPLE_ALPHA
00247   {
00248     int w;
00249     for(w=0;w<src->seqnum;w++) {
00250       memcpy(dst->cmscore[w], src->cmscore[w], sizeof(LOGPROB) * cm_alpha_num);
00251     }
00252   }     
00253 #else
00254   memcpy(dst->cmscore, src->cmscore, sizeof(LOGPROB) * MAXSEQNUM);
00255 #endif
00256 #endif /* CM_SEARCH */
00257   dst->seqnum = src->seqnum;
00258   dst->score = src->score;
00259   dst->bestt = src->bestt;
00260   dst->estimated_next_t = src->estimated_next_t;
00261   dst->endflag = src->endflag;
00262 #ifdef USE_DFA
00263   dst->state = src->state;
00264 #endif
00265   dst->tre = src->tre;
00266   if (ccd_flag) {
00267     memcpy(dst->g_prev, src->g_prev, sizeof(LOGPROB)*peseqlen);
00268     dst->last_ph = src->last_ph;
00269 #ifdef MULTIPATH_VERSION
00270     dst->last_ph_sp_attached = src->last_ph_sp_attached;
00271 #endif
00272 #ifdef USE_NGRAM
00273     dst->lscore = src->lscore;
00274 #endif
00275   }
00276 #ifdef USE_NGRAM
00277   dst->totallscore = src->totallscore;
00278 #endif
00279 #ifdef MULTIPATH_VERSION
00280   dst->final_g = src->final_g;
00281 #endif
00282 #ifdef VISUALIZE
00283   dst->popnode = src->popnode;
00284 #endif
00285 #ifdef GRAPHOUT
00286 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00287   memcpy(dst->wordend_frame, src->wordend_frame, sizeof(short)*peseqlen);
00288   memcpy(dst->wordend_gscore, src->wordend_gscore, sizeof(LOGPROB)*peseqlen);
00289 #endif
00290   dst->prevgraph = src->prevgraph;
00291   dst->lastcontext = src->lastcontext;
00292 #ifndef GRAPHOUT_PRECISE_BOUNDARY
00293   dst->tail_g_score = src->tail_g_score;
00294 #endif
00295 #endif
00296   return(dst);
00297 }
00298 
00313 NODE *
00314 newnode()
00315 {
00316   NODE *tmp;
00317   int i;
00318 
00319 #ifdef STOCKER_DEBUG
00320   request_num++;
00321 #endif
00322   if (stocker_root != NULL) {
00323     /* re-use ones in the stocker */
00324     tmp = stocker_root;
00325     stocker_root = tmp->next;
00326 #ifdef STOCKER_DEBUG
00327     stocked_num--;
00328     reused_num++;
00329 #endif
00330   } else {
00331     /* allocate new */
00332     if ((tmp=(NODE *)mymalloc(sizeof(NODE)))==NULL) {
00333       j_error("can't malloc\n");
00334     }
00335     tmp->g = (LOGPROB *)mymalloc(sizeof(LOGPROB)*peseqlen);
00336     if (ccd_flag) {
00337       tmp->g_prev = (LOGPROB *)mymalloc(sizeof(LOGPROB)*peseqlen);
00338     }
00339 #ifdef GRAPHOUT
00340 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00341     tmp->wordend_frame = (short *)mymalloc(sizeof(short)*peseqlen);
00342     tmp->wordend_gscore = (LOGPROB *)mymalloc(sizeof(LOGPROB)*peseqlen);
00343 #endif
00344 #endif
00345 #ifdef STOCKER_DEBUG
00346     new_num++;
00347 #endif
00348   }
00349 
00350   /* clear the data */
00351   /*bzero(tmp,sizeof(NODE));*/
00352   tmp->next=NULL;
00353   tmp->prev=NULL;
00354   tmp->last_ph = NULL;
00355 #ifdef MULTIPATH_VERSION
00356   tmp->last_ph_sp_attached = FALSE;
00357 #endif 
00358   if (ccd_flag) {
00359 #ifdef USE_NGRAM
00360     tmp->lscore = LOG_ZERO;
00361     tmp->totallscore = LOG_ZERO;
00362 #endif
00363   }
00364   tmp->endflag = FALSE;
00365   tmp->seqnum = 0;
00366   for(i=0;i<peseqlen;i++) {
00367     tmp->g[i] = LOG_ZERO;
00368     if (ccd_flag) tmp->g_prev[i] = LOG_ZERO;
00369   }
00370 #ifdef MULTIPATH_VERSION
00371   tmp->final_g = LOG_ZERO;
00372 #endif
00373 #ifdef VISUALIZE
00374   tmp->popnode = NULL;
00375 #endif
00376   tmp->tre = NULL;
00377 #ifdef GRAPHOUT
00378   tmp->prevgraph = NULL;
00379   tmp->lastcontext = NULL;
00380 #endif
00381   return(tmp);
00382 }
00383 
00384 
00385 /**********************************************************************/
00386 /************ 前向きトレリス展開と尤度計算              ***************/
00387 /************ Expand trellis and update forward viterbi ***************/
00388 /**********************************************************************/
00389 
00390 static LOGPROB *wordtrellis[2]; 
00391 static int tn;                 
00392 static int tl;                 
00393 static LOGPROB *g;              
00394 static HMM_Logical **phmmseq;   
00395 static int phmmlen_max;         
00396 #ifdef MULTIPATH_VERSION
00397 static boolean *has_sp;         
00398 #endif
00399 
00400 #ifdef GRAPHOUT
00401 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00402 static short *wend_token_frame[2]; 
00403 static LOGPROB *wend_token_gscore[2]; 
00404 #endif
00405 #endif
00406 
00417 void
00418 malloc_wordtrellis()
00419 {
00420   int maxwn;
00421 
00422   maxwn = winfo->maxwn + 10;
00423   wordtrellis[0] = (LOGPROB *)mymalloc(sizeof(LOGPROB) * maxwn);
00424   wordtrellis[1] = (LOGPROB *)mymalloc(sizeof(LOGPROB) * maxwn);
00425 
00426   g = (LOGPROB *)mymalloc(sizeof(LOGPROB) * peseqlen);
00427 
00428   phmmlen_max = winfo->maxwlen + 2;
00429   phmmseq = (HMM_Logical **)mymalloc(sizeof(HMM_Logical *) * phmmlen_max);
00430 #ifdef MULTIPATH_VERSION
00431   has_sp = (boolean *)mymalloc(sizeof(boolean) * phmmlen_max);
00432 #endif
00433 
00434 #ifdef GRAPHOUT
00435 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00436   wend_token_frame[0] = (short *)mymalloc(sizeof(short) * maxwn);
00437   wend_token_frame[1] = (short *)mymalloc(sizeof(short) * maxwn);
00438   wend_token_gscore[0] = (LOGPROB *)mymalloc(sizeof(LOGPROB) * maxwn);
00439   wend_token_gscore[1] = (LOGPROB *)mymalloc(sizeof(LOGPROB) * maxwn);
00440 #endif
00441 #endif
00442   
00443 }
00444 
00455 void
00456 free_wordtrellis()
00457 {
00458   free(wordtrellis[0]);
00459   free(wordtrellis[1]);
00460   free(g);
00461   free(phmmseq);
00462 #ifdef MULTIPATH_VERSION
00463   free(has_sp);
00464 #endif
00465 #ifdef GRAPHOUT
00466 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00467   free(wend_token_frame[0]);
00468   free(wend_token_frame[1]);
00469   free(wend_token_gscore[0]);
00470   free(wend_token_gscore[1]);
00471 #endif
00472 #endif
00473 }
00474 
00475 
00476 /**********************************************************************/
00477 /************ 仮説の前向き尤度計算                  *******************/
00478 /************ Compute forward score of a hypothesis *******************/
00479 /**********************************************************************/
00480 
00481 #ifdef MULTIPATH_VERSION
00482 
00500 static LOGPROB
00501 get_max_out_arc(HTK_HMM_Trans *tr, int state_num)
00502 {
00503   LOGPROB max_a;
00504   int afrom;
00505   LOGPROB a;
00506   
00507   max_a = LOG_ZERO;
00508   for (afrom = 0; afrom < state_num - 1; afrom++) {
00509     a = tr->a[afrom][state_num-1];
00510     if (max_a < a) max_a = a;
00511   }
00512   return(max_a);
00513 }
00514 
00531 static LOGPROB
00532 max_out_arc(HMM_Logical *l)
00533 {
00534   return(get_max_out_arc(hmm_logical_trans(l), hmm_logical_state_num(l)));
00535 }
00536 
00537 #endif /* MULTIPATH_VERSION */
00538 
00554 void
00555 scan_word(NODE *now, HTK_Param *param)
00556 {
00557   int   i,t, j;
00558   HMM *whmm;
00559   A_CELL *ac;
00560   WORD_ID word;
00561   LOGPROB tmpmax, tmptmp, score1;
00562   int startt = 0, endt;
00563   int wordhmmnum;
00564 #ifdef MULTIPATH_VERSION
00565   LOGPROB tmpmax_store, store_point_maxarc;
00566 #else
00567   LOGPROB tmpmax2 = LOG_ZERO;
00568 #endif
00569   int phmmlen;
00570   HMM_Logical *ret, *wend;
00571 #ifdef MULTIPATH_VERSION
00572   int store_point = -1;
00573 #else
00574   int store_point = 0;
00575 #endif
00576   int crossword_point = 0;
00577   boolean back_rescan = FALSE;
00578   boolean node_exist_p;
00579   
00580   /* ----------------------- prepare HMM ----------------------- */
00581 
00582   if (ccd_flag) {
00583     /* 直前の音素があれば,そこまでさかのぼって scan する */
00584     /* if there are any last phone, enable backscan */
00585     if (now->last_ph == NULL) {
00586       /* initial score: now->g[] */
00587       /* scan range: phones in now->seq[now->seqnum-1] */
00588       back_rescan = FALSE;
00589     } else {
00590       /* initial score: now->g_prev[] (1-phone before)*/
00591       /* scan range: phones in now->seq[now->seqnum-1] + now->last_ph */
00592       back_rescan = TRUE;
00593     }
00594   }
00595 #ifdef TCD
00596   if (now->last_ph != NULL) {
00597     j_printf("inherited last_ph: %s\n", (now->last_ph)->name);
00598 #ifdef MULTIPATH_VERSION
00599     if (now->last_ph_sp_attached) j_printf(" (sp attached)\n");
00600 #endif
00601   } else {
00602     j_printf("no last_ph inherited\n");
00603   }
00604 #endif
00605 
00606   /* scan 範囲分のHMMを準備 */
00607   /* prepare HMM of the scan range */
00608   word = now->seq[now->seqnum-1];
00609 
00610   if (ccd_flag) {
00611 
00612     if (back_rescan) {
00613       
00614       /* scan range: phones in now->seq[now->seqnum-1] + now->last_ph */
00615       
00616       phmmlen = winfo->wlen[word] + 1;
00617       if (phmmlen > phmmlen_max) {
00618         j_error("short of phmmlen\n");
00619       }
00620       for (i=0;i<phmmlen - 2;i++) {
00621         phmmseq[i] = winfo->wseq[word][i];
00622 #ifdef MULTIPATH_VERSION
00623         has_sp[i] = FALSE;
00624 #endif
00625       }
00626       /* 最終単語と last_ph 間の単語間triphoneを考慮 */
00627       /* consider cross-word context dependency between the last word and now->last_ph */
00628       wend = winfo->wseq[word][winfo->wlen[word]-1];
00629       ret = get_right_context_HMM(wend, now->last_ph->name, hmminfo);
00630       if (ret == NULL) {        /* triphone not found */
00631         /* fallback to the original bi/mono-phone */
00632         /* error if the original is pseudo phone (not explicitly defined
00633            in hmmdefs/hmmlist) */
00634         /* exception: word with 1 phone (triphone may exist in the next expansion */
00635         if (winfo->wlen[word] > 1 && wend->is_pseudo) {
00636           error_missing_right_triphone(wend, now->last_ph->name);
00637         }
00638         phmmseq[phmmlen-2] = wend;
00639       } else {
00640         phmmseq[phmmlen-2] = ret;
00641       }
00642       ret = get_left_context_HMM(now->last_ph, wend->name, hmminfo);
00643       if (ret == NULL) {
00644         /* fallback to the original bi/mono-phone */
00645         /* error if the original is pseudo phone (not explicitly defined
00646            in hmmdefs/hmmlist) */
00647         if (now->last_ph->is_pseudo) {
00648           error_missing_left_triphone(now->last_ph, wend->name);
00649         }
00650         phmmseq[phmmlen-1] = now->last_ph;
00651       } else {
00652         phmmseq[phmmlen-1] = ret;
00653       }
00654 
00655 #ifdef MULTIPATH_VERSION
00656       has_sp[phmmlen-2] = has_sp[phmmlen-1] = FALSE;
00657       if (enable_iwsp) {
00658         has_sp[phmmlen-2] = TRUE;
00659         if (now->last_ph_sp_attached) {
00660           has_sp[phmmlen-1] = TRUE;
00661         }
00662       }
00663 #endif
00664  
00665 #ifdef TCD
00666       j_printf("w=");
00667       for(i=0;i<winfo->wlen[word];i++) {
00668         j_printf(" %s",(winfo->wseq[word][i])->name);
00669 #ifdef MULTIPATH_VERSION
00670         if (has_sp[i]) j_printf("(sp)");
00671 #endif
00672       }
00673       j_printf(" | %s\n", (now->last_ph)->name);
00674 #ifdef MULTIPATH_VERSION
00675       if (now->last_ph_sp_attached) j_printf("   (sp)\n");
00676 #endif
00677       j_printf("scan for:");
00678       
00679       for (i=0;i<phmmlen;i++) {
00680         j_printf(" %s", phmmseq[i]->name);
00681 #ifdef MULTIPATH_VERSION
00682         if (has_sp[i]) j_printf("(sp)");
00683 #endif
00684       }
00685       j_printf("\n");
00686 #endif
00687 
00688       /* 単語HMMを作る */
00689       /* make word HMM */
00690       whmm = new_make_word_hmm(hmminfo, phmmseq, phmmlen
00691 #ifdef MULTIPATH_VERSION
00692                                ,has_sp
00693 #endif
00694                                );
00695       
00696       /* backscan なので,計算前の g[] 初期値は now->g_prev[] を使用 */
00697       /* As backscan enabled, the initial forward score g[] is set by
00698          now->g_prev[] */
00699       for (t=0;t<peseqlen;t++) {
00700         g[t]=now->g_prev[t];
00701 
00702       }
00703       
00704       /* 次段用のg_prevを格納するノード位置を設定 */
00705       /* set where to store scores as new g_prev[] for the next backscan
00706          in the HMM */
00707 #ifdef MULTIPATH_VERSION
00708       store_point = hmm_logical_state_num(phmmseq[0]) - 2;
00709       store_point_maxarc = max_out_arc(phmmseq[0]);
00710       if (enable_iwsp && has_sp[0]) {
00711         store_point += hmm_logical_state_num(hmminfo->sp) - 2;
00712         if (store_point_maxarc < max_out_arc(hmminfo->sp)) {
00713           store_point_maxarc = max_out_arc(hmminfo->sp);
00714         }
00715       }
00716 #else
00717       store_point = hmm_logical_state_num(phmmseq[0]) - 2 - 1;
00718 #endif
00719       /* scan中に直前単語とこの単語をまたぐ場所を設定 */
00720       /* set where is the connection point of the last word in the HMM */
00721 #ifdef MULTIPATH_VERSION      
00722       crossword_point = whmm->len - hmm_logical_state_num(phmmseq[phmmlen-1]);
00723       if (enable_iwsp && has_sp[phmmlen-1]) {
00724         crossword_point -= hmm_logical_state_num(hmminfo->sp) - 2;
00725       }
00726 #else
00727       crossword_point = whmm->len - (hmm_logical_state_num(phmmseq[phmmlen-1]) - 2) - 1;
00728 #endif
00729       
00730     } else {                    /* not backscan mode */
00731       
00732       /* scan range: phones in now->seq[now->seqnum-1] */
00733       
00734 #ifdef TCD
00735       j_printf("scan(org):");
00736       for (i=0;i<winfo->wlen[word];i++) {
00737         j_printf(" %s", (winfo->wseq[word][i])->name);
00738       }
00739       j_printf("\n");
00740 #endif
00741 
00742 #ifdef MULTIPATH_VERSION
00743       /* 必要ならばショートポーズを挟み込む位置を指定する */
00744       for(i=0;i<winfo->wlen[word];i++) {
00745         has_sp[i] = FALSE;
00746       }
00747       if (enable_iwsp) {
00748         has_sp[winfo->wlen[word]-1] = TRUE;
00749       }
00750 #endif
00751       
00752       /* 単語HMMを作る */
00753       /* make word HMM */
00754       whmm = new_make_word_hmm(hmminfo, winfo->wseq[word], winfo->wlen[word]
00755 #ifdef MULTIPATH_VERSION
00756                                , has_sp
00757 #endif
00758                                );
00759       
00760       /* 計算前の g[] 初期値は now->g[] を使用 */
00761       /* the initial forward score g[] is set by now->g[] */
00762       for (t=0;t<peseqlen;t++) {
00763         g[t]=now->g[t];
00764       }
00765       
00766       /* 次段用のg_prevを格納するノード位置を設定 */
00767       /* set where to store scores as new g_prev[] for the next backscan
00768          in the HMM */
00769 #ifdef MULTIPATH_VERSION
00770       store_point = hmm_logical_state_num(winfo->wseq[word][0]) - 2;
00771       store_point_maxarc = max_out_arc(winfo->wseq[word][0]);
00772       if (enable_iwsp && has_sp[0]) {
00773         store_point += hmm_logical_state_num(hmminfo->sp) - 2;
00774         if (store_point_maxarc < max_out_arc(hmminfo->sp)) {
00775           store_point_maxarc = max_out_arc(hmminfo->sp);
00776         }
00777       }
00778 #else
00779       store_point = hmm_logical_state_num(winfo->wseq[word][0]) - 2 - 1;
00780 #endif
00781 
00782       /* scan中に直前単語とこの単語をまたぐ場所は,なし */
00783       /* the connection point of the last word is not exist in the HMM */
00784       crossword_point = -1;
00785     }
00786     
00787   } else {                      /* ccd_flag == FALSE */
00788 
00789 #ifdef MULTIPATH_VERSION
00790     /* 必要ならばショートポーズを挟み込む位置を指定する */
00791     for(i=0;i<winfo->wlen[word];i++) {
00792       has_sp[i] = FALSE;
00793     }
00794     if (enable_iwsp) {
00795       has_sp[winfo->wlen[word]-1] = TRUE;
00796     }
00797 #endif
00798 
00799     /* 音素環境非依存の場合は単純に最終単語分の HMM を作成 */
00800     /* for monophone: simple make HMM for the last word */
00801     whmm = new_make_word_hmm(hmminfo, winfo->wseq[word], winfo->wlen[word]
00802 #ifdef MULTIPATH_VERSION
00803                              , has_sp
00804 #endif
00805                              );
00806 
00807     /* 計算前の g[] 初期値は now->g[] を使用 */
00808     /* the initial forward score g[] is set by now->g[] */
00809     for (t=0;t<peseqlen;t++) {
00810       g[t]=now->g[t];
00811     }
00812     
00813   }
00814 
00815 #ifdef TCD
00816   j_printf("whmm len      = %d\n",whmm->len);
00817   j_printf("crossword_point = %d\n", crossword_point);
00818   j_printf("g[] store point = %d\n", store_point);
00819 #endif
00820 
00821   wordhmmnum = whmm->len;
00822   if (wordhmmnum >= winfo->maxwn + 10) {
00823     j_error("scan_word: word too long\n");
00824   }
00825 
00826 #ifdef GRAPHOUT
00827 #ifndef GRAPHOUT_PRECISE_BOUNDARY
00828   if (ccd_flag) {
00829     now->tail_g_score = now->g[now->bestt];
00830   }
00831 #endif
00832 #endif
00833 
00834   /* ----------------------- do scan ----------------------- */
00835   
00836   /* scan開始点を検索 -> starttへ*/
00837   /* search for the start frame -> set to startt */
00838   for(t = peseqlen-1; t >=0 ; t--) {
00839     if (
00840 #ifdef SCAN_BEAM
00841         g[t] > framemaxscore[t] - scan_beam_thres &&
00842 #endif
00843         g[t] > LOG_ZERO) {
00844       break;
00845     }
00846   }
00847   if (t < 0) {                  /* no node has score > LOG_ZERO */
00848     for(t=0;t<peseqlen;t++) {
00849       if (ccd_flag) now->g_prev[t] = LOG_ZERO;
00850       now->g[t] = LOG_ZERO;
00851 #ifdef GRAPHOUT
00852 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00853       now->wordend_frame[t] = -1;
00854       now->wordend_gscore[t] = LOG_ZERO;
00855 #endif
00856 #endif
00857     }
00858     goto end_of_scan;
00859   }
00860   startt = t;
00861   
00862   /* clear [startt+1..peseqlen-1] */
00863   for(t=peseqlen-1;t>startt;t--) {
00864     if (ccd_flag) now->g_prev[t] = LOG_ZERO;
00865     now->g[t] = LOG_ZERO;
00866 #ifdef GRAPHOUT
00867 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00868     now->wordend_frame[t] = -1;
00869     now->wordend_gscore[t] = LOG_ZERO;
00870 #endif
00871 #endif
00872   }
00873 
00874   /* バッファポインタ初期化 */
00875   tn = 0; tl = 1;
00876 
00877 #ifdef GRAPHOUT
00878 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00879   for(i=0;i<wordhmmnum;i++) {
00880     wend_token_frame[tn][i] = -1;
00881     wend_token_gscore[tn][i] = LOG_ZERO;
00882   }
00883 #endif
00884 #endif
00885   
00886 #ifndef MULTIPATH_VERSION
00887   /* Below initialization is not needed on multipath version, since
00888      the actual viterbi will begin at frame 0 in multipath mode in main loop */
00889   
00890   /* 時間 [startt] 上の値を初期化 */
00891   /* initialize scores on frame [startt] */
00892   for(i=0;i<wordhmmnum-1;i++) wordtrellis[tn][i] = LOG_ZERO;
00893   wordtrellis[tn][wordhmmnum-1] = g[startt] + outprob(startt, &(whmm->state[wordhmmnum-1]), param);
00894   if (ccd_flag) {
00895     now->g_prev[startt] = wordtrellis[tn][store_point];
00896   }
00897   now->g[startt] = wordtrellis[tn][0];
00898 
00899 #ifdef GRAPHOUT
00900 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00901   if (ccd_flag) {
00902     if (back_rescan) {
00903       if (wordhmmnum-1 == crossword_point) {
00904         wend_token_frame[tn][wordhmmnum-1] = startt;
00905         wend_token_gscore[tn][wordhmmnum-1] = g[startt];
00906       } else {
00907         wend_token_frame[tn][wordhmmnum-1] = -1;
00908         wend_token_gscore[tn][wordhmmnum-1] = LOG_ZERO;
00909       }
00910     } else {
00911       wend_token_frame[tn][wordhmmnum-1] = startt;
00912       wend_token_gscore[tn][wordhmmnum-1] = g[startt];
00913     }
00914   } else {
00915     wend_token_frame[tn][wordhmmnum-1] = startt;
00916     wend_token_gscore[tn][wordhmmnum-1] = g[startt];
00917   }
00918   now->wordend_frame[startt] = wend_token_frame[tn][0];
00919   now->wordend_gscore[startt] = wend_token_gscore[tn][0];
00920 #endif
00921 #endif
00922 
00923 #endif /* ~MULTIPATH_VERSION */
00924   
00925   endt = startt;
00926 
00927   /* メインループ: startt から始まり 0 に向かって Viterbi 計算 */
00928   /* main loop: start from [startt], and compute Viterbi toward [0] */
00929   for(t=
00930 #ifdef MULTIPATH_VERSION
00931         startt
00932 #else
00933         startt-1
00934 #endif
00935         ;t>=0;t--) {
00936     
00937     /* wordtrellisのワークエリアをスワップ */
00938     i = tn; tn = tl; tl = i;
00939     
00940     node_exist_p = FALSE;       /* TRUE if there is at least 1 survived node in this frame */
00941 
00942 #ifdef MULTIPATH_VERSION
00943 
00944     /* 端のノード [t][wordhmmnum-1]は g[] を参照する */
00945     /* the edge node [t][wordhmmnum-1] is equal to g[] */
00946   
00947     /* ノード [t][wordhmmnum-2..0] についてトレリスを計算 */
00948     /* expand trellis for node [t][wordhmmnum-2..0] */
00949     tmpmax_store = LOG_ZERO;
00950     
00951 #else  /* ~MULTIPATH_VERSION */
00952     
00953     /* 端のノード [t][wordhmmnum-1]は,内部遷移 か g[]の高い方になる */
00954     /* the edge node [t][wordhmmnum-1] is either internal transitin or g[] */
00955     tmptmp = LOG_ZERO;
00956     for (ac=whmm->state[wordhmmnum-1].ac;ac;ac=ac->next) {
00957       score1 = wordtrellis[tl][ac->arc] + ac->a;
00958       if (tmptmp < score1) {
00959         j = ac->arc;
00960         tmptmp = score1;
00961       }
00962     }
00963     if (g[t] > tmptmp) {
00964       tmpmax = g[t];
00965 #ifdef GRAPHOUT
00966 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00967       if (!back_rescan || wordhmmnum-1 == crossword_point) {
00968         wend_token_frame[tn][wordhmmnum-1] = t;
00969         wend_token_gscore[tn][wordhmmnum-1] = g[t];
00970       } else {
00971         wend_token_frame[tn][wordhmmnum-1] = wend_token_frame[tl][j];
00972         wend_token_gscore[tn][wordhmmnum-1] = wend_token_gscore[tl][j];
00973       }
00974 #endif
00975 #endif
00976     } else {
00977       tmpmax = tmptmp;
00978 #ifdef GRAPHOUT
00979 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00980       wend_token_frame[tn][wordhmmnum-1] = wend_token_frame[tl][j];
00981       wend_token_gscore[tn][wordhmmnum-1] = wend_token_gscore[tl][j];
00982 #endif
00983 #endif
00984     }
00985 
00986     /* 端のノードのスコアエンベロープチェック: 一定幅外なら落とす */
00987     /* check if the edge node is within score envelope */
00988     if (
00989 #ifdef SCAN_BEAM
00990         tmpmax <= framemaxscore[t] - scan_beam_thres ||
00991 #endif
00992         tmpmax <= LOG_ZERO
00993         ) {
00994       wordtrellis[tn][wordhmmnum-1] = LOG_ZERO;
00995 #ifdef GRAPHOUT
00996 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00997       wend_token_frame[tn][wordhmmnum-1] = -1;
00998       wend_token_gscore[tn][wordhmmnum-1] = LOG_ZERO;
00999 #endif
01000 #endif
01001     } else {
01002       node_exist_p = TRUE;
01003       wordtrellis[tn][wordhmmnum-1] = tmpmax + outprob(t, &(whmm->state[wordhmmnum-1]), param);
01004     }
01005 
01006 #endif /* MULTIPATH_VERSION  */
01007 
01008     /* ノード [t][wordhmmnum-2..0] についてトレリスを計算 */
01009     /* expand trellis for node [t][wordhmmnum-2..0] */
01010     for(i=wordhmmnum-2;i>=0;i--) {
01011 
01012       if (ccd_flag) {
01013 
01014         /* 最尤パスと最尤スコア tmpmax を見つける */
01015         /* tmpmax2 は次回用 g_prev[] のための最大値(自己遷移を除いた最大値) */
01016         /* find most likely path and the max score 'tmpmax' */
01017         /* 'tmpmax2' is max score excluding self transition, for next g_prev[] */
01018 #ifndef MULTIPATH_VERSION
01019         if (i == store_point) {
01020           tmpmax2 = LOG_ZERO;
01021         }
01022 #endif
01023         tmpmax = LOG_ZERO;
01024         for (ac=whmm->state[i].ac;ac;ac=ac->next) {
01025 #ifdef MULTIPATH_VERSION
01026           if (ac->arc == wordhmmnum-1) score1 = g[t];
01027           else if (t + 1 > startt) score1 = LOG_ZERO;
01028           else score1 = wordtrellis[tl][ac->arc];
01029           score1 += ac->a;
01030 #else
01031           score1 = wordtrellis[tl][ac->arc] + ac->a;
01032 #endif
01033           if (i <= crossword_point && ac->arc > crossword_point) {
01034             /* これは単語を越える遷移 (backscan 実行時) */
01035             /* this is a transition across word (when backscan is enabled) */
01036 #ifdef USE_NGRAM
01037             score1 += now->lscore; /* add N-gram LM score */
01038 #else
01039             score1 += penalty2; /* add DFA insertion penalty */
01040 #endif
01041           }
01042 #ifdef MULTIPATH_VERSION
01043           if (i <= store_point && ac->arc > store_point) {
01044             if (tmpmax_store < score1) tmpmax_store = score1;
01045           }
01046 #else
01047           if (i == store_point && i != ac->arc) {
01048             if (tmpmax2 < score1) tmpmax2 = score1;
01049           }
01050 #endif
01051           if (tmpmax < score1) {
01052             tmpmax = score1;
01053             j = ac->arc;
01054           }
01055         }
01056 
01057         /* スコアエンベロープチェック: 一定幅外なら落とす */
01058         /* check if score of this node is within the score envelope */
01059         if (
01060 #ifdef SCAN_BEAM
01061             tmpmax <= framemaxscore[t] - scan_beam_thres ||
01062 #endif
01063             tmpmax <= LOG_ZERO
01064             ) {  /* invalid node */
01065           wordtrellis[tn][i] = LOG_ZERO;
01066 #ifdef GRAPHOUT
01067 #ifdef GRAPHOUT_PRECISE_BOUNDARY
01068           wend_token_frame[tn][i] = -1;
01069           wend_token_gscore[tn][i] = LOG_ZERO;
01070 #endif
01071 #endif
01072 #ifndef MULTIPATH_VERSION
01073           if (i == store_point) now->g_prev[t] = LOG_ZERO;
01074 #endif
01075         } else { /* survived node */
01076 #ifndef MULTIPATH_VERSION
01077           if (i == store_point) now->g_prev[t] = tmpmax2;
01078 #endif
01079 #ifdef GRAPHOUT
01080 #ifdef GRAPHOUT_PRECISE_BOUNDARY
01081           if (
01082 #ifdef MULTIPATH_VERSION
01083               (back_rescan && i <= crossword_point && j > crossword_point)
01084               || j == wordhmmnum-1
01085 #else
01086               i <= crossword_point && j > crossword_point
01087 #endif
01088               ) {
01089             wend_token_frame[tn][i] = t;
01090             wend_token_gscore[tn][i] = tmpmax;
01091           } else {
01092             wend_token_frame[tn][i] = wend_token_frame[tl][j];
01093             wend_token_gscore[tn][i] = wend_token_gscore[tl][j];
01094           }
01095 #endif
01096 #endif
01097           node_exist_p = TRUE;  /* at least one node survive in this frame */
01098 #ifdef MULTIPATH_VERSION
01099           wordtrellis[tn][i] = tmpmax;
01100           if (i > 0) {
01101             /* compute output probability */
01102             wordtrellis[tn][i] += outprob(t, &(whmm->state[i]), param);
01103           }
01104 #else
01105           /* compute output probability */
01106           tmptmp = outprob(t, &(whmm->state[i]), param);
01107           /* score of node [t][i] has been determined here */
01108           wordtrellis[tn][i] = tmpmax + tmptmp;
01109 #endif
01110         }
01111         
01112       } else {                  /* not triphone */
01113 
01114         /* backscan 無し: store_point, crossword_point は無関係 */
01115         /* no backscan: store_point, crossword_point ignored */
01116         tmpmax = LOG_ZERO;
01117         for (ac=whmm->state[i].ac;ac;ac=ac->next) {
01118 #ifdef MULTIPATH_VERSION
01119           if (ac->arc == wordhmmnum-1) score1 = g[t];
01120           else if (t + 1 > startt) score1 = LOG_ZERO;
01121           else score1 = wordtrellis[tl][ac->arc];
01122           score1 += ac->a;
01123 #else
01124           score1 = wordtrellis[tl][ac->arc] + ac->a;
01125 #endif
01126           if (tmpmax < score1) {
01127             tmpmax = score1;
01128             j = ac->arc;
01129           }
01130         }
01131 
01132         /* スコアエンベロープチェック: 一定幅外なら落とす */
01133         /* check if score of this node is within the score envelope */
01134         if (
01135 #ifdef SCAN_BEAM
01136             tmpmax <= framemaxscore[t] - scan_beam_thres ||
01137 #endif
01138             tmpmax <= LOG_ZERO
01139             ) {
01140           /* invalid node */
01141           wordtrellis[tn][i] = LOG_ZERO;
01142 #ifdef GRAPHOUT
01143 #ifdef GRAPHOUT_PRECISE_BOUNDARY
01144           wend_token_frame[tn][i] = -1;
01145           wend_token_gscore[tn][i] = LOG_ZERO;
01146 #endif
01147 #endif
01148         } else {
01149           /* survived node */
01150           node_exist_p = TRUE;
01151 #ifdef GRAPHOUT
01152 #ifdef GRAPHOUT_PRECISE_BOUNDARY
01153 #ifdef MULTIPATH_VERSION
01154           if (j == wordhmmnum-1) {
01155             wend_token_frame[tn][i] = t;
01156             wend_token_gscore[tn][i] = tmpmax;
01157           } else {
01158             wend_token_frame[tn][i] = wend_token_frame[tl][j];
01159             wend_token_gscore[tn][i] = wend_token_gscore[tl][j];
01160           }
01161 #else
01162           wend_token_frame[tn][i] = wend_token_frame[tl][j];
01163           wend_token_gscore[tn][i] = wend_token_gscore[tl][j];
01164 #endif
01165 #endif
01166 #endif
01167           /* score of node [t][i] has been determined here */
01168 #ifdef MULTIPATH_VERSION
01169           wordtrellis[tn][i] = tmpmax;
01170           if (i > 0) {
01171             wordtrellis[tn][i] += outprob(t, &(whmm->state[i]), param);
01172           } 
01173 #else
01174           wordtrellis[tn][i] = tmpmax + outprob(t, &(whmm->state[i]), param);
01175 #endif
01176         }
01177         
01178       }
01179     } /* end of node loop */
01180 
01181     /* 時間 t のViterbi計算終了.前向きスコアはscanした単語の始端 */
01182     /* Viterbi end for frame [t].  the forward score is the score of word
01183        beginning scanned */
01184     now->g[t] = wordtrellis[tn][0];
01185 #ifdef GRAPHOUT
01186 #ifdef GRAPHOUT_PRECISE_BOUNDARY
01187     now->wordend_frame[t] = wend_token_frame[tn][0];
01188     now->wordend_gscore[t] = wend_token_gscore[tn][0];
01189 #endif
01190 #endif
01191 
01192 #ifdef MULTIPATH_VERSION
01193     /* triphone 時, 次段のために store_point のデータをg_prevに保存 */
01194     /* store the scores crossing the store_point to g_prev, for next scan */
01195     if (ccd_flag) {
01196       /* the max arc crossing the store_point always selected as tmpmax_score */ 
01197       tmpmax_store -= store_point_maxarc;
01198       if (tmpmax_store < LOG_ZERO) tmpmax_store = LOG_ZERO;
01199       now->g_prev[t] = tmpmax_store;
01200     }
01201 #endif
01202 
01203     /* store the number of last computed frame */
01204     if (node_exist_p) endt = t;
01205     
01206     /* scanした単語の第1パスでの始端時刻より先まで t が進んでおり,かつ
01207        この t においてスコアエンベロープによって生き残ったノードが一つも
01208        無かったならば,このフレームで計算を打ち切りそれ以上先([0..t-1])は
01209        計算しない */
01210     /* if frame 't' already reached the beginning frame of scanned word
01211        in 1st pass and no node was survived in this frame (all nodes pruned
01212        by score envelope), terminate computation at this frame and
01213        do not computer further frame ([0..t-1]). */
01214     if (t < now->estimated_next_t && (!node_exist_p)) {
01215       /* clear the rest scores */
01216       for (i=t-1;i>=0;i--) {
01217         now->g[i] = LOG_ZERO;
01218 #ifdef GRAPHOUT
01219 #ifdef GRAPHOUT_PRECISE_BOUNDARY
01220         now->wordend_frame[i] = -1;
01221         now->wordend_gscore[i] = LOG_ZERO;
01222 #endif
01223 #endif
01224         if (ccd_flag) now->g_prev[i] = LOG_ZERO;
01225       }
01226       /* terminate loop */
01227       break;
01228     }
01229     
01230   } /* end of time loop */
01231   
01232   if (debug2_flag) j_printf("scanned: [%3d-%3d]\n", endt, startt);
01233 
01234  end_of_scan:
01235 
01236 #ifdef MULTIPATH_VERSION
01237   /* 前向きスコアの最終値を計算 (状態 0 から時間 0 への遷移) */
01238   /* compute the total forward score (transition from state 0 to frame 0 */
01239   if (endt == 0) {
01240     tmpmax = LOG_ZERO;
01241     for(ac=whmm->state[0].ac;ac;ac=ac->next) {
01242       score1 = wordtrellis[tn][ac->arc] + ac->a;
01243       if (tmpmax < score1) tmpmax = score1;
01244     }
01245     now->final_g = score1;
01246   } else {
01247     now->final_g = LOG_ZERO;
01248   }
01249 #endif
01250   
01251   /* 次回 backscan のための情報格納 */
01252   /* store data for next backscan */
01253   if (ccd_flag) {
01254     if (store_point ==
01255 #ifdef MULTIPATH_VERSION
01256         wordhmmnum - 2
01257 #else
01258         wordhmmnum - 1
01259 #endif
01260         ) {
01261       /* last_ph無し,かつ単語の音素長=1の場合、次回の scan_word() で
01262          単語全体がもう一度再計算される.この場合,
01263          g_prev は,このscan_wordを開始する前のスコアを入れておく必要がある */
01264       /* if there was no 'last_ph' and the scanned word consists of only
01265          1 phone, the whole word should be re-computed in the future scan_word().
01266          So the next 'g_prev[]' should be the initial forward scores
01267          before we begin Viterbi (= g[t]). */
01268       for (t = startt; t>=0; t--) {
01269         now->g_prev[t] = g[t];
01270       }
01271     }
01272 #ifdef GRAPHOUT
01273 #ifndef GRAPHOUT_PRECISE_BOUNDARY
01274     if (now->tail_g_score != LOG_ZERO) {
01275       if (now->prevgraph != NULL) {
01276         (now->prevgraph)->leftscore = now->tail_g_score;
01277       }
01278     }
01279 #endif
01280 #endif
01281     /* 次回のために now->last_ph を更新 */
01282     /* update 'now->last_ph' for future scan_word() */
01283     if (back_rescan) {
01284       now->last_ph = phmmseq[0];
01285     } else {
01286       now->last_ph = winfo->wseq[word][0];
01287     }
01288 #ifdef MULTIPATH_VERSION
01289     now->last_ph_sp_attached = has_sp[0];
01290 #endif
01291   }
01292 
01293 #ifndef MULTIPATH_VERSION
01294 #ifdef GRAPHOUT
01295 #ifdef GRAPHOUT_PRECISE_BOUNDARY
01296   /* 次回の next_word 用に境界情報を調整 */
01297   /* proceed word boundary for one step for next_word */
01298   now->wordend_frame[peseqlen-1] = now->wordend_frame[0];
01299   now->wordend_gscore[peseqlen-1] = now->wordend_gscore[0];
01300   for (t=0;t<peseqlen-1;t++) {
01301     now->wordend_frame[t] = now->wordend_frame[t+1];
01302     now->wordend_gscore[t] = now->wordend_gscore[t+1];
01303   }
01304 #endif
01305 #endif
01306 #endif /* MULTIPATH_VERSION */
01307 
01308   /* free work area */
01309   free_hmm(whmm);
01310 #ifdef TCD
01311 #ifdef MULTIPATH_VERSION
01312   if (ccd_flag) {
01313     j_printf("last_ph = %s", (now->last_ph)->name);
01314     if (now->last_ph_sp_attached) j_printf(" (sp attached)");
01315     j_printf("\n");
01316   }
01317 #else
01318   j_printf("last_ph = %s\n", (now->last_ph)->name);
01319 #endif
01320 #endif
01321 }
01322 
01323 
01324 /**************************************************************************/
01325 /*** 新仮説の展開とヒューリスティックを繋いだ全体スコアを計算           ***/
01326 /*** Expand new hypothesis and compute the total score (with heuristic) ***/
01327 /**************************************************************************/
01328 
01352 void
01353 next_word(NODE *now, NODE *new, NEXTWORD *nword, HTK_Param *param, BACKTRELLIS *backtrellis)
01354 {
01355   int   t;
01356   HMM_Logical *newphone;
01357   int lastword;
01358   int   i;
01359   LOGPROB tmpp;
01360 #ifndef MULTIPATH_VERSION
01361   LOGPROB a_value;
01362 #endif
01363   int   startt;
01364   int word;
01365   LOGPROB totalscore;
01366   TRELLIS_ATOM *tre;
01367 
01368   new->score = LOG_ZERO;
01369 
01370   word = nword->id;
01371   lastword=now->seq[now->seqnum-1];
01372 
01373   /* 単語並び、DFA状態番号、言語スコアを継承・更新 */
01374   /* inherit and update word sequence, DFA state and total LM score */
01375   for (i=0;i< now->seqnum;i++){ 
01376     new->seq[i] = now->seq[i];
01377 #ifdef CM_SEARCH
01378 #ifdef CM_MULTIPLE_ALPHA
01379     memcpy(new->cmscore[i], now->cmscore[i], sizeof(LOGPROB) * cm_alpha_num);
01380 #else
01381     new->cmscore[i] = now->cmscore[i];
01382 #endif
01383 #endif /* CM_SEARCH */
01384   }
01385   new->seq[i] = word;
01386   new->seqnum = now->seqnum+1;
01387 #ifdef USE_DFA
01388   new->state = nword->next_state;
01389 #endif
01390 #ifdef USE_NGRAM
01391   new->totallscore = now->totallscore + nword->lscore;
01392 #endif  
01393 #ifdef MULTIPATH_VERSION
01394   new->final_g = now->final_g;
01395 #endif
01396   
01397   if (ccd_flag) {
01398     
01399     /* 展開単語の接続点の音素HMMをnewphoneにセットする.
01400        元仮説 now との単語間の音素環境依存性を考慮する */
01401     /* set the triphone at the connection point to 'newphone', considering
01402        cross-word context dependency to 'now' */
01403     newphone = get_right_context_HMM(winfo->wseq[word][winfo->wlen[word]-1], now->last_ph->name, hmminfo);
01404     if (newphone == NULL) {     /* triphone not found */
01405       /* fallback to the original bi/mono-phone */
01406       /* error if the original is pseudo phone (not explicitly defined
01407          in hmmdefs/hmmlist) */
01408       /* exception: word with 1 phone (triphone may exist in the next expansion */
01409       if (winfo->wlen[word] > 1 && winfo->wseq[word][winfo->wlen[word]-1]->is_pseudo){
01410         error_missing_right_triphone(winfo->wseq[word][winfo->wlen[word]-1], now->last_ph->name);
01411       }
01412       newphone = winfo->wseq[word][winfo->wlen[word]-1];
01413     }
01414     
01415     /* 元仮説をscanした時の末端音素HMM -> 新仮説の直前音素HMM */
01416     /* inherit last_ph */
01417     new->last_ph = now->last_ph;
01418 #ifdef MULTIPATH_VERSION
01419     new->last_ph_sp_attached = now->last_ph_sp_attached;
01420 #endif
01421     
01422     /* backscan用接続ポイントのスコア g_prev[] をコピー */
01423     /* copy g_prev[] that are scores at backscan connection point */
01424     for (t=0;t<peseqlen;t++) {
01425       new->g_prev[t] = now->g_prev[t];
01426     }
01427     
01428   } else {                      /* not triphone */
01429     
01430     /* 展開単語の接続(=終端)の音素HMMをnewphoneにセット */
01431     /* set the phone at the connection point to 'newphone' */
01432     newphone = winfo->wseq[word][winfo->wlen[word]-1];
01433   }
01434 
01435 #ifdef USE_NGRAM
01436   /* set current LM score */
01437   new->lscore = nword->lscore;
01438 #endif
01439 
01440 #ifndef MULTIPATH_VERSION
01441   /* a_value: 接続点の遷移確率 */
01442   /* a_value: transition probability of connection point */
01443   i = hmm_logical_state_num(newphone);
01444   a_value = (hmm_logical_trans(newphone))->a[i-2][i-1];
01445 #endif
01446 
01447   /***************************************************************************/
01448   /* 前向き(第2パス),後ろ向き(第1パス)トレリスを接続し最尤接続点を見つける */
01449   /* connect forward/backward trellis to look for the best connection time   */
01450   /***************************************************************************/
01451 
01452 #ifdef MULTIPATH_VERSION
01453   startt = peseqlen-1;
01454 #else
01455   startt = peseqlen-2;
01456   new->g[startt+1] = LOG_ZERO;
01457 #endif
01458 
01459   /*-----------------------------------------------------------------*/
01460   /* 単語トレリスを探して, 次単語の最尤接続点を発見する */
01461   /* determine the best connection time of the new word, seeking the word
01462      trellis */
01463   /*-----------------------------------------------------------------*/
01464 
01465   /* update new->g[t] */
01466   for(t=startt;t>=0;t--) {
01467     new->g[t] =
01468 #ifdef MULTIPATH_VERSION
01469       now->g[t]
01470 #else
01471       now->g[t+1] + a_value
01472 #endif
01473 #ifdef USE_NGRAM
01474       + nword->lscore
01475 #else
01476       + penalty2
01477 #endif
01478       ;
01479   }
01480 
01481   new->tre = NULL;
01482 
01483 #ifdef USE_DFA
01484   if (!looktrellis_flag) {
01485     /* すべてのフレームにわたって最尤を探す */
01486     /* search for best trellis word throughout all frame */
01487     for(t = startt; t >= 0; t--) {
01488       tre = bt_binsearch_atom(backtrellis, t, (WORD_ID) word);
01489       if (tre == NULL) continue;
01490 #ifdef MULTIPATH_VERSION
01491       totalscore = new->g[t] + tre->backscore;
01492 #else
01493       if (newphone->is_pseudo) {
01494         tmpp = outprob_cd(t, &(newphone->body.pseudo->stateset[newphone->body.pseudo->state_num-2]), param);
01495       } else {
01496         tmpp = outprob_state(t, newphone->body.defined->s[newphone->body.defined->state_num-2], param);
01497       }
01498       totalscore = new->g[t] + tre->backscore + tmpp;
01499 #endif
01500       if (new->score < totalscore) {
01501         new->score = totalscore;
01502         new->bestt = t;
01503         new->estimated_next_t = tre->begintime - 1;
01504         new->tre  =  tre;
01505       }
01506     }
01507   } else {
01508 #endif /* USE_DFA */
01509       
01510   /* この展開単語のトレリス上の終端時間の前後のみスキャンする
01511      前後に連続して存在するフレームについてのみ計算 */
01512   /* search for best trellis word only around the estimated time */
01513   /* 1. search forward */
01514   for(t = (nword->tre)->endtime; t >= 0; t--) {
01515     tre = bt_binsearch_atom(backtrellis, t, (WORD_ID) word);
01516     if (tre == NULL) break;     /* go to 2 if the trellis word disappear */
01517 #ifdef MULTIPATH_VERSION
01518     totalscore = new->g[t] + tre->backscore;
01519 #else
01520     if (newphone->is_pseudo) {
01521       tmpp = outprob_cd(t, &(newphone->body.pseudo->stateset[newphone->body.pseudo->state_num-2]), param);
01522     } else {
01523       tmpp = outprob_state(t, newphone->body.defined->s[newphone->body.defined->state_num-2], param);
01524     }
01525     totalscore = new->g[t] + tre->backscore + tmpp;
01526 #endif
01527     if (new->score < totalscore) {
01528       new->score = totalscore;
01529       new->bestt = t;
01530       new->estimated_next_t = tre->begintime - 1;
01531       new->tre = tre;
01532     }
01533   }
01534   /* 2. search backward */
01535   for(t = (nword->tre)->endtime + 1; t <= startt; t++) {
01536     tre = bt_binsearch_atom(backtrellis, t, (WORD_ID) word);
01537     if (tre == NULL) break;     /* end if the trellis word disapper */
01538 #ifdef MULTIPATH_VERSION
01539     totalscore = new->g[t] + tre->backscore;
01540 #else
01541     if (newphone->is_pseudo) {
01542       tmpp = outprob_cd(t, &(newphone->body.pseudo->stateset[newphone->body.pseudo->state_num-2]), param);
01543     } else {
01544       tmpp = outprob_state(t, newphone->body.defined->s[newphone->body.defined->state_num-2], param);
01545     }
01546     totalscore = new->g[t] + tre->backscore + tmpp;
01547 #endif
01548     if (new->score < totalscore) {
01549       new->score = totalscore;
01550       new->bestt = t;
01551       new->estimated_next_t = tre->begintime - 1;
01552       new->tre = tre;
01553     }
01554   }
01555 
01556 #ifdef USE_DFA
01557   }
01558 #endif
01559 
01560 }
01561 
01562 /**********************************************************************/
01563 /********** 初期仮説の生成                 ****************************/
01564 /********** Generate an initial hypothesis ****************************/
01565 /**********************************************************************/
01566 
01586 void
01587 start_word(NODE *new, NEXTWORD *nword, HTK_Param *param, BACKTRELLIS *backtrellis)
01588 {
01589   HMM_Logical *newphone;
01590   WORD_ID word;
01591   LOGPROB tmpp;
01592   int t;
01593   TRELLIS_ATOM *tre = NULL;
01594 
01595   /* initialize data */
01596   word = nword->id;
01597   new->score = LOG_ZERO;
01598   new->seqnum = 1;
01599   new->seq[0] = word;
01600 
01601 #ifdef USE_DFA
01602   new->state = nword->next_state;
01603 #endif
01604 #ifdef USE_NGRAM
01605   new->totallscore = nword->lscore;
01606 #endif  
01607 
01608   /* cross-word triphone handling is not needed on startup */
01609   newphone = winfo->wseq[word][winfo->wlen[word]-1];
01610   if (ccd_flag) {
01611     new->last_ph = NULL;
01612 #ifdef MULTIPATH_VERSION
01613     new->last_ph_sp_attached = FALSE;
01614 #endif
01615   }
01616 #ifdef USE_NGRAM
01617   new->lscore = nword->lscore;
01618 #endif
01619   
01620 #ifdef USE_NGRAM
01621   new->g[peseqlen-1] = nword->lscore;
01622 #else  /* USE_DFA */
01623   new->g[peseqlen-1] = 0;
01624 #endif
01625   
01626   for (t=peseqlen-1; t>=0; t--) {
01627     tre = bt_binsearch_atom(backtrellis, t, word);
01628     if (tre != NULL) {
01629 #ifdef GRAPHOUT
01630       new->bestt = peseqlen-1;
01631 #else
01632       new->bestt = t;
01633 #endif
01634 #ifdef MULTIPATH_VERSION
01635       new->score = new->g[peseqlen-1] + tre->backscore;
01636 #else
01637       if (newphone->is_pseudo) {
01638         tmpp = outprob_cd(peseqlen-1, &(newphone->body.pseudo->stateset[newphone->body.pseudo->state_num-2]), param);
01639       } else {
01640         tmpp = outprob_state(peseqlen-1, newphone->body.defined->s[newphone->body.defined->state_num-2], param);
01641       }
01642       new->score = new->g[peseqlen-1] + tre->backscore + tmpp;
01643 #endif
01644       new->estimated_next_t = tre->begintime - 1;
01645       new->tre = tre;
01646       break;
01647     }
01648   }
01649   if (tre == NULL) {            /* no word in backtrellis */
01650     new->score = LOG_ZERO;
01651   }
01652 
01653 }
01654 
01655 
01673 void
01674 last_next_word(NODE *now, NODE *new, HTK_Param *param)
01675 {
01676   cpy_node(new, now);
01677   /* 最終スコアを設定 */
01678   /* update the final score */
01679 #ifdef MULTIPATH_VERSION
01680   new->score = now->final_g;
01681 #else
01682   new->score = now->g[0];
01683 #endif
01684 }
01685 
01686 
01687 #endif /* PASS2_STRICT_IWCD */

Juliusに対してTue Dec 26 16:19:28 2006に生成されました。  doxygen 1.5.0