メインページ | モジュール | データ構造 | Directories | ファイル一覧 | データフィールド | グローバル | 関連ページ

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

Juliusに対してTue Mar 28 16:20:49 2006に生成されました。  doxygen 1.4.2