00001 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 #include <julius/julius.h>
00066 
00067 #ifdef PASS2_STRICT_IWCD
00068 
00069 #undef TCD                      
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 #undef STOCKER_DEBUG
00078 
00079 #ifdef STOCKER_DEBUG
00080 static int stocked_num = 0;
00081 static int reused_num = 0;
00082 static int new_num = 0;
00083 static int request_num = 0;
00084 #endif
00085 
00098 static void
00099 free_node_exec(NODE *node)
00100 {
00101   if (node == NULL) return;
00102   free(node->g);
00103 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00104   if (node->region->graphout) {
00105     free(node->wordend_frame);
00106     free(node->wordend_gscore);
00107   }
00108 #endif
00109   free(node);
00110 }
00111 
00126 void
00127 free_node(NODE *node)
00128 {
00129   if (node == NULL) return;
00130 
00131   if (node->region->graphout) {
00132     if (node->prevgraph != NULL && node->prevgraph->saved == FALSE) {
00133       wordgraph_free(node->prevgraph);
00134     }
00135   }
00136 
00137   
00138   node->next = node->region->pass2.stocker_root;
00139   node->region->pass2.stocker_root = node;
00140 
00141 #ifdef STOCKER_DEBUG
00142   stocked_num++;
00143 #endif
00144 }
00145 
00162 void
00163 clear_stocker(StackDecode *s)
00164 {
00165   NODE *node, *tmp;
00166   node = s->stocker_root;
00167   while(node) {
00168     tmp = node->next;
00169     free_node_exec(node);
00170     node = tmp;
00171   }
00172   s->stocker_root = NULL;
00173 
00174 #ifdef STOCKER_DEBUG
00175   jlog("DEBUG: %d times requested, %d times newly allocated, %d times reused\n", request_num, new_num, reused_num);
00176   stocked_num = 0;
00177   reused_num = 0;
00178   new_num = 0;
00179   request_num = 0;
00180 #endif
00181 }
00182 
00203 NODE *
00204 cpy_node(NODE *dst, NODE *src)
00205 {
00206   int peseqlen;
00207 
00208   peseqlen = src->region->peseqlen;
00209   
00210   dst->next = src->next;
00211   dst->prev = src->prev;
00212   memcpy(dst->g, src->g, sizeof(LOGPROB) * peseqlen);
00213   memcpy(dst->seq, src->seq, sizeof(WORD_ID) * MAXSEQNUM);
00214 #ifdef CM_SEARCH
00215 #ifdef CM_MULTIPLE_ALPHA
00216   {
00217     int w;
00218     for(w=0;w<src->seqnum;w++) {
00219       memcpy(dst->cmscore[w], src->cmscore[w], sizeof(LOGPROB) * src->region->config->annotate.cm_alpha_num);
00220     }
00221   }     
00222 #else
00223   memcpy(dst->cmscore, src->cmscore, sizeof(LOGPROB) * MAXSEQNUM);
00224 #endif
00225 #endif 
00226   dst->seqnum = src->seqnum;
00227   dst->score = src->score;
00228   dst->bestt = src->bestt;
00229   dst->estimated_next_t = src->estimated_next_t;
00230   dst->endflag = src->endflag;
00231   dst->state = src->state;
00232   dst->tre = src->tre;
00233   if (src->region->ccd_flag) {
00234     dst->last_ph = src->last_ph;
00235     dst->last_ph_sp_attached = src->last_ph_sp_attached;
00236   }
00237   dst->totallscore = src->totallscore;
00238   dst->final_g = src->final_g;
00239 #ifdef VISUALIZE
00240   dst->popnode = src->popnode;
00241 #endif
00242 
00243   if (src->region->graphout) {
00244 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00245     memcpy(dst->wordend_frame, src->wordend_frame, sizeof(short) * peseqlen);
00246     memcpy(dst->wordend_gscore, src->wordend_gscore, sizeof(LOGPROB) * peseqlen);
00247 #endif
00248     dst->prevgraph = src->prevgraph;
00249     dst->lastcontext = src->lastcontext;
00250 #ifndef GRAPHOUT_PRECISE_BOUNDARY
00251     dst->tail_g_score = src->tail_g_score;
00252 #endif
00253   }
00254   return(dst);
00255 }
00256 
00277 NODE *
00278 newnode(RecogProcess *r)
00279 {
00280   NODE *tmp;
00281   int i;
00282   int peseqlen;
00283 
00284   peseqlen = r->peseqlen;
00285 
00286 #ifdef STOCKER_DEBUG
00287   request_num++;
00288 #endif
00289   if ((tmp = r->pass2.stocker_root) != NULL) {
00290     
00291     r->pass2.stocker_root = tmp->next;
00292 #ifdef STOCKER_DEBUG
00293     stocked_num--;
00294     reused_num++;
00295 #endif
00296   } else {
00297     
00298     tmp = (NODE *)mymalloc(sizeof(NODE));
00299     tmp->g = (LOGPROB *)mymalloc(sizeof(LOGPROB) * peseqlen);
00300 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00301     if (r->graphout) {
00302       tmp->wordend_frame = (short *)mymalloc(sizeof(short) * peseqlen);
00303       tmp->wordend_gscore = (LOGPROB *)mymalloc(sizeof(LOGPROB) * peseqlen);
00304     }
00305 #endif
00306 #ifdef STOCKER_DEBUG
00307     new_num++;
00308 #endif
00309   }
00310 
00311   
00312   
00313   tmp->next=NULL;
00314   tmp->prev=NULL;
00315   tmp->last_ph = NULL;
00316   tmp->last_ph_sp_attached = FALSE;
00317   if (r->ccd_flag) {
00318     tmp->totallscore = LOG_ZERO;
00319   }
00320   tmp->endflag = FALSE;
00321   tmp->seqnum = 0;
00322   for(i = 0; i < peseqlen; i++) {
00323     tmp->g[i] = LOG_ZERO;
00324   }
00325   tmp->final_g = LOG_ZERO;
00326 #ifdef VISUALIZE
00327   tmp->popnode = NULL;
00328 #endif
00329   if (r->graphout) {
00330     tmp->prevgraph = NULL;
00331     tmp->lastcontext = NULL;
00332   }
00333 
00334   tmp->region = r;
00335 
00336   return(tmp);
00337 }
00338 
00339 
00340 
00341 
00342 
00343 
00344 
00345 static LOGPROB *wordtrellis[2]; 
00346 static int tn;                 
00347 static int tl;                 
00348 static LOGPROB *g;              
00349 static HMM_Logical **phmmseq;   
00350 static int phmmlen_max;         
00351 static HMM_Logical *tailph;     
00352 static boolean *has_sp;         
00353 
00354 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00355 static short *wend_token_frame[2]; 
00356 static LOGPROB *wend_token_gscore[2]; 
00357 static short *wef;              
00358 static LOGPROB *wes;            
00359 #endif
00360 
00377 void
00378 malloc_wordtrellis(RecogProcess *r)
00379 {
00380   int maxwn;
00381 
00382   maxwn = r->lm->winfo->maxwn + 10;     
00383   wordtrellis[0] = (LOGPROB *)mymalloc(sizeof(LOGPROB) * maxwn);
00384   wordtrellis[1] = (LOGPROB *)mymalloc(sizeof(LOGPROB) * maxwn);
00385 
00386   g = (LOGPROB *)mymalloc(sizeof(LOGPROB) * r->peseqlen);
00387 
00388   phmmlen_max = r->lm->winfo->maxwlen + 2;
00389   phmmseq = (HMM_Logical **)mymalloc(sizeof(HMM_Logical *) * phmmlen_max);
00390   if (r->am->hmminfo->multipath) {
00391     has_sp = (boolean *)mymalloc(sizeof(boolean) * phmmlen_max);
00392   } else {
00393     has_sp = NULL;
00394   }
00395 
00396   wef = NULL;
00397   wes = NULL;
00398   wend_token_frame[0] = NULL;
00399   wend_token_frame[1] = NULL;
00400   wend_token_gscore[0] = NULL;
00401   wend_token_gscore[1] = NULL;
00402 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00403   if (r->graphout) {
00404     wef = (short *)mymalloc(sizeof(short) * r->peseqlen);
00405     wes = (LOGPROB *)mymalloc(sizeof(LOGPROB) * r->peseqlen);
00406     wend_token_frame[0] = (short *)mymalloc(sizeof(short) * maxwn);
00407     wend_token_frame[1] = (short *)mymalloc(sizeof(short) * maxwn);
00408     wend_token_gscore[0] = (LOGPROB *)mymalloc(sizeof(LOGPROB) * maxwn);
00409     wend_token_gscore[1] = (LOGPROB *)mymalloc(sizeof(LOGPROB) * maxwn);
00410   }
00411 #endif
00412 }
00413 
00426 void
00427 free_wordtrellis()
00428 {
00429   free(wordtrellis[0]);
00430   free(wordtrellis[1]);
00431   free(g);
00432   free(phmmseq);
00433   if (has_sp) {
00434     free(has_sp);
00435     has_sp = NULL;
00436   }
00437 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00438   if (wef) {
00439     free(wef);
00440     free(wes);
00441     free(wend_token_frame[0]);
00442     free(wend_token_frame[1]);
00443     free(wend_token_gscore[0]);
00444     free(wend_token_gscore[1]);
00445     wef = NULL;
00446   }
00447 #endif
00448 }
00449 
00450 
00451 
00452 
00453 
00454 
00455 
00456 
00457 
00458 
00459 
00460 
00461 
00462 
00504 static void
00505 do_viterbi(LOGPROB *g, LOGPROB *g_new, HMM_Logical **phmmseq, boolean *has_sp, int phmmlen, HTK_Param *param, int framelen, int least_frame, LOGPROB *final_g, short *wordend_frame_src, short *wordend_frame_dst, LOGPROB *wordend_gscore_src, LOGPROB *wordend_gscore_dst, RecogProcess *r) 
00506 {
00507   HMM *whmm;                    
00508   int wordhmmnum;               
00509   int startt;                   
00510   LOGPROB tmpmax,tmpscore;      
00511   A_CELL *ac;
00512   int t,i,j;
00513   boolean node_exist_p;
00514 
00515   
00516   WORD_INFO *winfo;
00517   HTK_HMM_INFO *hmminfo;
00518   LOGPROB *framemaxscore;
00519 #ifdef SCAN_BEAM
00520   LOGPROB scan_beam_thres;
00521 #endif
00522 
00523   winfo = r->lm->winfo;
00524   hmminfo = r->am->hmminfo;
00525   framemaxscore = r->pass2.framemaxscore;
00526 #ifdef SCAN_BEAM
00527   scan_beam_thres = r->config->pass2.scan_beam_thres;
00528 #endif
00529 
00530 
00531 #ifdef TCD
00532   jlog("DEBUG: scan for:");
00533   for (i=0;i<phmmlen;i++) {
00534     jlog(" %s", phmmseq[i]->name);
00535   }
00536   jlog("\n");
00537 #endif
00538   
00539   
00540   
00541   whmm = new_make_word_hmm(hmminfo, phmmseq, phmmlen, hmminfo->multipath ? has_sp : NULL);
00542   if (whmm == NULL) {
00543     j_internal_error("Error: failed to make word hmm\n");
00544   }
00545   wordhmmnum = whmm->len;
00546   if (wordhmmnum >= winfo->maxwn + 10) {
00547     j_internal_error("do_viterbi: word too long (>%d)\n", winfo->maxwn + 10);
00548   }
00549 
00550   
00551   
00552   for(t = framelen-1; t >=0 ; t--) {
00553     if (
00554 #ifdef SCAN_BEAM
00555         g[t] > framemaxscore[t] - scan_beam_thres &&
00556 #endif
00557         g[t] > LOG_ZERO) {
00558       break;
00559     }
00560   }
00561   if (t < 0) {                  
00562     
00563     for(t=0;t<framelen;t++) {
00564       g_new[t] = LOG_ZERO;
00565 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00566       if (r->graphout) {
00567         wordend_frame_dst[t] = -1;
00568         wordend_gscore_dst[t] = LOG_ZERO;
00569       }
00570 #endif
00571     }
00572     free_hmm(whmm);
00573     return;
00574   }
00575   startt = t;
00576   
00577   
00578   
00579   for(t=framelen-1;t>startt;t--) {
00580     g_new[t] = LOG_ZERO;
00581 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00582     if (r->graphout) {
00583       wordend_frame_dst[t] = -1;
00584       wordend_gscore_dst[t] = LOG_ZERO;
00585     }
00586 #endif
00587   }
00588 
00589   
00590   
00591   
00592 
00593   
00594   tn = 0; tl = 1;
00595 
00596 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00597   if (r->graphout) {
00598     for(i=0;i<wordhmmnum;i++) {
00599       wend_token_frame[tn][i] = -1;
00600       wend_token_gscore[tn][i] = LOG_ZERO;
00601     }
00602   }
00603 #endif
00604 
00605   if (! hmminfo->multipath) {
00606     
00607     
00608     for(i=0;i<wordhmmnum-1;i++) wordtrellis[tn][i] = LOG_ZERO;
00609     wordtrellis[tn][wordhmmnum-1] = g[startt] + outprob(&(r->am->hmmwrk), startt, &(whmm->state[wordhmmnum-1]), param);
00610     g_new[startt] = wordtrellis[tn][0];
00611 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00612     if (r->graphout) {
00613       wend_token_frame[tn][wordhmmnum-1] = wordend_frame_src[startt];
00614       wend_token_gscore[tn][wordhmmnum-1] = wordend_gscore_src[startt];
00615       wordend_frame_dst[startt] = wend_token_frame[tn][0];
00616       wordend_gscore_dst[startt] = wend_token_gscore[tn][0];
00617     }
00618 #endif
00619   }
00620   
00621   
00622   
00623   for(t = hmminfo->multipath ? startt : startt - 1; t >= 0; t--) {
00624     
00625     
00626     
00627     i = tn; tn = tl; tl = i;
00628 
00629     node_exist_p = FALSE;       
00630 
00631     if (! hmminfo->multipath) {
00632     
00633       
00634       
00635       tmpscore = LOG_ZERO;
00636       for (ac=whmm->state[wordhmmnum-1].ac;ac;ac=ac->next) {
00637         if (tmpscore < wordtrellis[tl][ac->arc] + ac->a) {
00638           j = ac->arc;
00639           tmpscore = wordtrellis[tl][ac->arc] + ac->a;
00640         }
00641       }
00642       if (g[t] > tmpscore) {
00643         tmpmax = g[t];
00644 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00645         if (r->graphout) {
00646           wend_token_frame[tn][wordhmmnum-1] = wordend_frame_src[t];
00647           wend_token_gscore[tn][wordhmmnum-1] = wordend_gscore_src[t];
00648         }
00649 #endif
00650       } else {
00651         tmpmax = tmpscore;
00652 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00653         if (r->graphout) {
00654           wend_token_frame[tn][wordhmmnum-1] = wend_token_frame[tl][j];
00655           wend_token_gscore[tn][wordhmmnum-1] = wend_token_gscore[tl][j];
00656         }
00657 #endif
00658       }
00659       
00660       
00661       
00662       if (
00663 #ifdef SCAN_BEAM
00664           tmpmax <= framemaxscore[t] - scan_beam_thres ||
00665 #endif
00666           tmpmax <= LOG_ZERO
00667           ) {
00668         wordtrellis[tn][wordhmmnum-1] = LOG_ZERO;
00669 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00670         if (r->graphout) {
00671           wend_token_frame[tn][wordhmmnum-1] = -1;
00672           wend_token_gscore[tn][wordhmmnum-1] = LOG_ZERO;
00673         }
00674 #endif
00675       } else {
00676         node_exist_p = TRUE;
00677         wordtrellis[tn][wordhmmnum-1] = tmpmax + outprob(&(r->am->hmmwrk), t, &(whmm->state[wordhmmnum-1]), param);
00678       }
00679 
00680     }
00681 
00682     
00683     
00684     for(i=wordhmmnum-2;i>=0;i--) {
00685       
00686       
00687       
00688       tmpmax = LOG_ZERO;
00689       for (ac=whmm->state[i].ac;ac;ac=ac->next) {
00690         if (hmminfo->multipath) {
00691           if (ac->arc == wordhmmnum-1) tmpscore = g[t];
00692           else if (t + 1 > startt) tmpscore = LOG_ZERO;
00693           else tmpscore = wordtrellis[tl][ac->arc];
00694           tmpscore += ac->a;
00695         } else {
00696           tmpscore = wordtrellis[tl][ac->arc] + ac->a;
00697         }
00698         if (tmpmax < tmpscore) {
00699           tmpmax = tmpscore;
00700           j = ac->arc;
00701         }
00702       }
00703       
00704       
00705       
00706       if (
00707 #ifdef SCAN_BEAM
00708           tmpmax <= framemaxscore[t] - scan_beam_thres ||
00709 #endif
00710           tmpmax <= LOG_ZERO
00711           ) {
00712         
00713         wordtrellis[tn][i] = LOG_ZERO;
00714 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00715         if (r->graphout) {
00716           wend_token_frame[tn][i] = -1;
00717           wend_token_gscore[tn][i] = LOG_ZERO;
00718         }
00719 #endif
00720       } else {
00721         
00722         node_exist_p = TRUE;
00723         wordtrellis[tn][i] = tmpmax;
00724         if (! hmminfo->multipath || i > 0) {
00725           wordtrellis[tn][i] += outprob(&(r->am->hmmwrk), t, &(whmm->state[i]), param);
00726         }
00727 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00728         if (r->graphout) {
00729           if (hmminfo->multipath) {
00730             if (j == wordhmmnum-1) {
00731               wend_token_frame[tn][i] = wordend_frame_src[t];
00732               wend_token_gscore[tn][i] = wordend_gscore_src[t];
00733             } else {
00734               wend_token_frame[tn][i] = wend_token_frame[tl][j];
00735               wend_token_gscore[tn][i] = wend_token_gscore[tl][j];
00736             }
00737           } else {
00738             wend_token_frame[tn][i] = wend_token_frame[tl][j];
00739             wend_token_gscore[tn][i] = wend_token_gscore[tl][j];
00740           }
00741         }
00742 #endif
00743       }
00744     } 
00745 
00746     
00747     
00748     g_new[t] = wordtrellis[tn][0];
00749 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00750     if (r->graphout) {
00751     
00752       wordend_frame_dst[t] = wend_token_frame[tn][0];
00753       wordend_gscore_dst[t] = wend_token_gscore[tn][0];
00754     }
00755 #endif
00756     
00757 
00758 
00759     
00760 
00761 
00762 
00763     if (t < least_frame && (!node_exist_p)) {
00764       
00765       for (i=t-1;i>=0;i--) {
00766         g_new[i] = LOG_ZERO;
00767 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00768         if (r->graphout) {
00769           wordend_frame_dst[i] = -1;
00770           wordend_gscore_dst[i] = LOG_ZERO;
00771         }
00772 #endif
00773       }
00774       
00775       break;
00776     }
00777     
00778   } 
00779 
00780   if (hmminfo->multipath) {
00781     
00782     
00783     if (t < 0) {                        
00784       tmpmax = LOG_ZERO;
00785       for(ac=whmm->state[0].ac;ac;ac=ac->next) {
00786         tmpscore = wordtrellis[tn][ac->arc] + ac->a;
00787         if (tmpmax < tmpscore) tmpmax = tmpscore;
00788       }
00789       *final_g = tmpmax;
00790     } else {
00791       *final_g = LOG_ZERO;
00792     }
00793   }
00794 
00795   
00796   free_hmm(whmm);
00797 }
00798 
00822 static void
00823 do_viterbi_next_word(NODE *now, NODE *new, HMM_Logical *lastphone, boolean sp, HTK_Param *param, RecogProcess *r) 
00824 {
00825   int t, n;
00826   LOGPROB a_value;              
00827   int peseqlen;
00828   boolean multipath;
00829 
00830   multipath = r->am->hmminfo->multipath;
00831 
00832   peseqlen = r->peseqlen;
00833   
00834   if (! multipath) {
00835 
00836     
00837 
00838 
00839 
00840 
00841     
00842 
00843 
00844 
00845 
00846 
00847     if (r->lm->winfo->wlen[now->seq[now->seqnum-1]] > 1) {
00848       n = hmm_logical_state_num(lastphone);
00849       a_value = (hmm_logical_trans(lastphone))->a[n-2][n-1];
00850       for(t=0; t<peseqlen-1; t++) g[t] = now->g[t+1] + a_value;
00851       g[peseqlen-1] = LOG_ZERO;
00852     } else {
00853       for(t=0; t<peseqlen; t++) g[t] = now->g[t];
00854     }
00855 
00856   } else {
00857   
00858     for(t=0; t<peseqlen; t++) g[t] = now->g[t];
00859     phmmseq[0] = lastphone;
00860     has_sp[0] = sp;
00861 
00862   }
00863   
00864   do_viterbi(g, new->g,
00865              multipath ? phmmseq : &lastphone,
00866              multipath ? has_sp : NULL,
00867              1, param, peseqlen, now->estimated_next_t, &(new->final_g)
00868 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00869              , now->wordend_frame, new->wordend_frame
00870              , now->wordend_gscore, new->wordend_gscore
00871 #else
00872              , NULL, NULL
00873              , NULL, NULL
00874 #endif
00875              , r
00876              );
00877 
00878 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00879   if (! multipath) {
00880     if (r->graphout) {
00881       
00882       
00883       new->wordend_frame[r->peseqlen-1] = new->wordend_frame[0];
00884       new->wordend_gscore[r->peseqlen-1] = new->wordend_gscore[0];
00885       for (t=0;t<r->peseqlen-1;t++) {
00886         new->wordend_frame[t] = new->wordend_frame[t+1];
00887         new->wordend_gscore[t] = new->wordend_gscore[t+1];
00888       }
00889     }
00890   }
00891 #endif
00892 }
00893 
00913 void
00914 scan_word(NODE *now, HTK_Param *param, RecogProcess *r)
00915 {
00916   int   i,t;
00917   WORD_ID word;
00918   int phmmlen;
00919 
00920   
00921   WORD_INFO *winfo;
00922   HTK_HMM_INFO *hmminfo;
00923   int peseqlen;
00924   boolean ccd_flag;
00925   boolean enable_iwsp;          
00926 
00927   winfo = r->lm->winfo;
00928   hmminfo = r->am->hmminfo;
00929   peseqlen = r->peseqlen;
00930   ccd_flag = r->ccd_flag;
00931   if (hmminfo->multipath) {
00932     enable_iwsp = r->lm->config->enable_iwsp;
00933   }
00934   
00935 #ifndef GRAPHOUT_PRECISE_BOUNDARY
00936   if (r->graphout) {
00937     if (ccd_flag) {
00938       now->tail_g_score = now->g[now->bestt];
00939     }
00940   }
00941 #endif
00942 
00943   
00944   
00945   
00946   
00947 
00948 
00949   word = now->seq[now->seqnum-1];
00950   
00951 #ifdef TCD
00952     jlog("DEBUG: w=");
00953     for(i=0;i<winfo->wlen[word];i++) {
00954       jlog(" %s",(winfo->wseq[word][i])->name);
00955     }
00956     if (ccd_flag) {
00957       if (now->last_ph != NULL) {
00958         jlog(" | %s", (now->last_ph)->name);
00959       }
00960     }
00961     jlog("\n");
00962 #endif 
00963     
00964   if (ccd_flag) {
00965     
00966     
00967     if (now->last_ph != NULL) {
00968       tailph = get_right_context_HMM(winfo->wseq[word][winfo->wlen[word]-1], now->last_ph->name, hmminfo);
00969       if (tailph == NULL) {
00970         
00971         
00972 
00973         
00974         if (winfo->wlen[word] > 1 && winfo->wseq[word][winfo->wlen[word]-1]->is_pseudo){
00975           error_missing_right_triphone(winfo->wseq[word][winfo->wlen[word]-1], now->last_ph->name);
00976         }
00977 
00978         tailph = winfo->wseq[word][winfo->wlen[word]-1];
00979       }
00980     } else {
00981       tailph = winfo->wseq[word][winfo->wlen[word]-1];
00982     }
00983     
00984     
00985 
00986     if (winfo->wlen[word] == 1) {
00987       now->last_ph = tailph;
00988       if (hmminfo->multipath) now->last_ph_sp_attached = TRUE;
00989 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00990       if (r->graphout) {
00991         
00992         
00993         for (t=0;t<peseqlen;t++) {
00994           now->wordend_frame[t] = t;
00995           now->wordend_gscore[t] = now->g[t];
00996         }
00997       }
00998 #endif
00999 #ifdef TCD
01000       jlog("DEBUG: suspended as %s\n", (now->last_ph)->name);
01001 #endif
01002       return;
01003     }
01004 
01005     
01006     
01007     phmmlen = winfo->wlen[word] - 1;
01008     if (phmmlen > phmmlen_max) {
01009       j_internal_error("scan_word: num of phonemes in a word exceed phmmlenmax (%d) ?\n", phmmlen_max);
01010     }
01011     for (i=0;i<phmmlen-1;i++) {
01012       phmmseq[i] = winfo->wseq[word][i+1];
01013     }
01014     phmmseq[phmmlen-1] = tailph;
01015     if (hmminfo->multipath) {
01016       for (i=0;i<phmmlen-1;i++) has_sp[i] = FALSE;
01017       has_sp[phmmlen-1] = (enable_iwsp) ? TRUE : FALSE;
01018     }
01019 
01020   } else {                      
01021 
01022     phmmlen = winfo->wlen[word];
01023     for (i=0;i<phmmlen;i++) phmmseq[i] = winfo->wseq[word][i];
01024     if (hmminfo->multipath) {
01025       for (i=0;i<phmmlen;i++) has_sp[i] = FALSE;
01026       if (enable_iwsp) has_sp[phmmlen-1] = TRUE;
01027     }
01028 
01029   }
01030 
01031   
01032   
01033   for (t=0;t<peseqlen;t++) g[t] = now->g[t];
01034 
01035 #ifdef GRAPHOUT_PRECISE_BOUNDARY
01036   if (r->graphout) {
01037     
01038     
01039     for (t=0;t<peseqlen;t++) {
01040       wef[t] = t;
01041       wes[t] = now->g[t];
01042     }
01043   }
01044 #endif
01045 
01046   
01047   
01048   do_viterbi(g, now->g, phmmseq, hmminfo->multipath ? has_sp : NULL, 
01049              phmmlen, param, peseqlen, now->estimated_next_t, &(now->final_g)
01050 #ifdef GRAPHOUT_PRECISE_BOUNDARY
01051              
01052              
01053              , wef, now->wordend_frame
01054              , wes, now->wordend_gscore
01055 #else
01056              , NULL, NULL
01057              , NULL, NULL
01058 #endif
01059              , r
01060              );
01061 #ifdef GRAPHOUT_PRECISE_BOUNDARY
01062   if (! hmminfo->multipath) {
01063     if (r->graphout) {
01064       
01065       
01066       now->wordend_frame[peseqlen-1] = now->wordend_frame[0];
01067       now->wordend_gscore[peseqlen-1] = now->wordend_gscore[0];
01068       for (t=0;t<peseqlen-1;t++) {
01069         now->wordend_frame[t] = now->wordend_frame[t+1];
01070         now->wordend_gscore[t] = now->wordend_gscore[t+1];
01071       }
01072     }
01073   }
01074 #endif
01075 
01076   if (ccd_flag) {
01077     
01078     
01079     now->last_ph = winfo->wseq[word][0];
01080     if (hmminfo->multipath) now->last_ph_sp_attached = FALSE; 
01081 #ifdef TCD
01082     jlog("DEBUG: last_ph = %s\n", (now->last_ph)->name);
01083 #endif
01084   }
01085 }
01086 
01087 
01088 
01089 
01090 
01091 
01092 
01118 void
01119 next_word(NODE *now, NODE *new, NEXTWORD *nword, HTK_Param *param, RecogProcess *r)
01120 {
01121   static HMM_Logical *lastphone, *newphone;
01122   static LOGPROB *g_src;
01123   int   t;
01124   int lastword;
01125   int   i;
01126   LOGPROB a_value;
01127   LOGPROB tmpp;
01128   int   startt;
01129   int word;
01130   TRELLIS_ATOM *tre;
01131   LOGPROB totalscore;
01132   BACKTRELLIS *backtrellis;
01133   WORD_INFO *winfo;
01134   HTK_HMM_INFO *hmminfo;
01135   int peseqlen;
01136   boolean ccd_flag;
01137 
01138   backtrellis = r->backtrellis;
01139   winfo = r->lm->winfo;
01140   hmminfo = r->am->hmminfo;
01141   peseqlen = r->peseqlen;
01142   ccd_flag = r->ccd_flag;
01143 
01144   word = nword->id;
01145   lastword = now->seq[now->seqnum-1];
01146 
01147   
01148   
01149   if (ccd_flag) {
01150     
01151     
01152     lastphone = get_left_context_HMM(now->last_ph, winfo->wseq[word][winfo->wlen[word]-1]->name, hmminfo);
01153     if (lastphone == NULL) {
01154       
01155       
01156 
01157       
01158       if (now->last_ph->is_pseudo){
01159         error_missing_left_triphone(now->last_ph, winfo->wseq[word][winfo->wlen[word]-1]->name);
01160       }
01161       lastphone = now->last_ph;
01162     }
01163   }
01164 
01165   
01166   
01167   if (ccd_flag) {
01168     newphone = get_right_context_HMM(winfo->wseq[word][winfo->wlen[word]-1], now->last_ph->name, hmminfo);
01169     if (newphone == NULL) {
01170       
01171       
01172 
01173       
01174       if (winfo->wlen[word] > 1 && winfo->wseq[word][winfo->wlen[word]-1]->is_pseudo){
01175         error_missing_right_triphone(winfo->wseq[word][winfo->wlen[word]-1], now->last_ph->name);
01176       }
01177       newphone = winfo->wseq[word][winfo->wlen[word]-1];
01178     }
01179   } else {
01180     newphone = winfo->wseq[word][winfo->wlen[word]-1];
01181   }
01182   
01183   
01184   
01185   new->score = LOG_ZERO;
01186   for (i=0;i< now->seqnum;i++){
01187     new->seq[i] = now->seq[i];
01188 #ifdef CM_SEARCH
01189 #ifdef CM_MULTIPLE_ALPHA
01190     memcpy(new->cmscore[i], now->cmscore[i], sizeof(LOGPROB) * r->config->annotate.cm_alpha_num);
01191 #else
01192     new->cmscore[i] = now->cmscore[i];
01193 #endif
01194 #endif 
01195   }
01196   new->seq[i] = word;
01197   new->seqnum = now->seqnum+1;
01198   new->state = nword->next_state;
01199   new->totallscore = now->totallscore + nword->lscore;
01200   if (ccd_flag) {
01201     
01202     
01203     new->last_ph = lastphone;
01204     new->last_ph_sp_attached = now->last_ph_sp_attached;
01205   }
01206 
01207   if (ccd_flag) {
01208     
01209     
01210     do_viterbi_next_word(now, new, lastphone,
01211                          hmminfo->multipath ? now->last_ph_sp_attached : FALSE,
01212                          param, r);
01213     g_src = new->g;
01214   } else {
01215     g_src = now->g;
01216 #ifdef GRAPHOUT_PRECISE_BOUNDARY
01217     if (r->graphout) {
01218       memcpy(new->wordend_frame, now->wordend_frame, sizeof(short)*peseqlen);
01219       memcpy(new->wordend_gscore, now->wordend_gscore, sizeof(LOGPROB)*peseqlen);
01220     }
01221 #endif
01222   }
01223       
01224   
01225   
01226   if (hmminfo->multipath) {
01227     startt = peseqlen-1;
01228   } else {
01229     startt = peseqlen-2;
01230   }
01231   i = hmm_logical_state_num(newphone);
01232   a_value = (hmm_logical_trans(newphone))->a[i-2][i-1];
01233   if (hmminfo->multipath) {
01234     for(t=0; t <= startt; t++) {
01235       new->g[t] = g_src[t] + nword->lscore;
01236     }
01237   } else {
01238     for(t=0; t <= startt; t++) {
01239       new->g[t] = g_src[t+1] + a_value + nword->lscore;
01240     }
01241   }
01242 
01243   
01244   
01245   
01246   
01247   
01248   
01249   
01250 
01251   
01252 
01253   if (r->lmtype == LM_DFA && !r->config->pass2.looktrellis_flag) {
01254     
01255     
01256     for(t = startt; t >= 0; t--) {
01257       tre = bt_binsearch_atom(backtrellis, t, (WORD_ID) word);
01258       if (tre == NULL) continue;
01259       totalscore = new->g[t] + tre->backscore;
01260       if (! hmminfo->multipath) {
01261         if (newphone->is_pseudo) {
01262           tmpp = outprob_cd(&(r->am->hmmwrk), t, &(newphone->body.pseudo->stateset[newphone->body.pseudo->state_num-2]), param);
01263         } else {
01264           tmpp = outprob_state(&(r->am->hmmwrk), t, newphone->body.defined->s[newphone->body.defined->state_num-2], param);
01265         }
01266         totalscore += tmpp;
01267       }
01268       if (new->score < totalscore) {
01269         new->score = totalscore;
01270         new->bestt = t;
01271         new->estimated_next_t = tre->begintime - 1;
01272         new->tre = tre;
01273       }
01274     }
01275 
01276     return;
01277   }
01278 
01279   
01280   
01281 
01282   
01283 
01284   
01285   
01286   for(t = (nword->tre)->endtime; t >= 0; t--) {
01287     tre = bt_binsearch_atom(backtrellis, t, (WORD_ID) word);
01288     if (tre == NULL) break;     
01289     totalscore = new->g[t] + tre->backscore;
01290     if (! hmminfo->multipath) {
01291       if (newphone->is_pseudo) {
01292         tmpp = outprob_cd(&(r->am->hmmwrk), t, &(newphone->body.pseudo->stateset[newphone->body.pseudo->state_num-2]), param);
01293       } else {
01294         tmpp = outprob_state(&(r->am->hmmwrk), t, newphone->body.defined->s[newphone->body.defined->state_num-2], param);
01295       }
01296       totalscore += tmpp;
01297     }
01298     if (new->score < totalscore) {
01299       new->score = totalscore;
01300       new->bestt = t;
01301       new->estimated_next_t = tre->begintime - 1;
01302       new->tre = tre;
01303     }
01304   }
01305   
01306   for(t = (nword->tre)->endtime + 1; t <= startt; t++) {
01307     tre = bt_binsearch_atom(backtrellis, t, (WORD_ID) word);
01308     if (tre == NULL) break;     
01309     totalscore = new->g[t] + tre->backscore;
01310     if (! hmminfo->multipath) {
01311       if (newphone->is_pseudo) {
01312         tmpp = outprob_cd(&(r->am->hmmwrk), t, &(newphone->body.pseudo->stateset[newphone->body.pseudo->state_num-2]), param);
01313       } else {
01314         tmpp = outprob_state(&(r->am->hmmwrk), t, newphone->body.defined->s[newphone->body.defined->state_num-2], param);
01315       }
01316       totalscore += tmpp;
01317     }
01318     if (new->score < totalscore) {
01319       new->score = totalscore;
01320       new->bestt = t;
01321       new->estimated_next_t = tre->begintime - 1;
01322       new->tre = tre;
01323     }
01324   }
01325 
01326   
01327   new->lscore = nword->lscore;
01328   
01329 }
01330 
01331 
01332 
01333 
01334 
01335 
01336 
01358 void
01359 start_word(NODE *new, NEXTWORD *nword, HTK_Param *param, RecogProcess *r)
01360 {
01361   HMM_Logical *newphone;
01362   WORD_ID word;
01363   TRELLIS_ATOM *tre = NULL;
01364   LOGPROB tmpp;
01365   int t;
01366 
01367   BACKTRELLIS *backtrellis;
01368   WORD_INFO *winfo;
01369 
01370   int peseqlen;
01371   boolean ccd_flag;
01372   boolean multipath;
01373 
01374   backtrellis = r->backtrellis;
01375   winfo = r->lm->winfo;
01376   peseqlen = r->peseqlen;
01377   ccd_flag = r->ccd_flag;
01378   multipath = r->am->hmminfo->multipath;
01379 
01380   
01381   word = nword->id;
01382   new->score = LOG_ZERO;
01383   new->seqnum = 1;
01384   new->seq[0] = word;
01385 
01386   new->state = nword->next_state;
01387   new->totallscore = nword->lscore;
01388 
01389   
01390   new->lscore = nword->lscore;
01391 
01392   
01393   newphone = winfo->wseq[word][winfo->wlen[word]-1];
01394   if (ccd_flag) {
01395     new->last_ph = NULL;
01396   }
01397   
01398   if (r->lmtype == LM_PROB) {
01399     new->g[peseqlen-1] = nword->lscore;
01400   } else {
01401     new->g[peseqlen-1] = 0;
01402   }
01403   
01404   for (t=peseqlen-1; t>=0; t--) {
01405     tre = bt_binsearch_atom(backtrellis, t, word);
01406     if (tre != NULL) {
01407       if (r->graphout) {
01408         new->bestt = peseqlen-1;
01409       } else {
01410         new->bestt = t;
01411       }
01412       new->score = new->g[peseqlen-1] + tre->backscore;
01413       if (! multipath) {
01414         if (newphone->is_pseudo) {
01415           tmpp = outprob_cd(&(r->am->hmmwrk), peseqlen-1, &(newphone->body.pseudo->stateset[newphone->body.pseudo->state_num-2]), param);
01416         } else {
01417           tmpp = outprob_state(&(r->am->hmmwrk), peseqlen-1, newphone->body.defined->s[newphone->body.defined->state_num-2], param);
01418         }
01419         new->score += tmpp;
01420       }
01421       new->estimated_next_t = tre->begintime - 1;
01422       new->tre = tre;
01423       break;
01424     }
01425   }
01426   if (tre == NULL) {            
01427     new->score = LOG_ZERO;
01428   }
01429 }
01430 
01452 void
01453 last_next_word(NODE *now, NODE *new, HTK_Param *param, RecogProcess *r)
01454 {
01455   cpy_node(new, now);
01456   if (r->ccd_flag) {
01457     
01458     
01459     if (r->am->hmminfo->multipath) {
01460       do_viterbi_next_word(now, new, now->last_ph, now->last_ph_sp_attached, param, r);
01461       new->score = new->final_g;
01462     } else {
01463       do_viterbi_next_word(now, new, now->last_ph, FALSE, param, r);
01464       new->score = new->g[0];
01465     }
01466   } else {
01467     if (r->am->hmminfo->multipath) {
01468       new->score = now->final_g;
01469     } else {
01470       new->score = now->g[0];
01471     }
01472 #ifdef GRAPHOUT_PRECISE_BOUNDARY
01473     if (r->graphout) {
01474       
01475       memcpy(new->wordend_frame, now->wordend_frame, sizeof(short)*r->peseqlen);
01476       memcpy(new->wordend_gscore, now->wordend_gscore, sizeof(LOGPROB)*r->peseqlen);
01477     }
01478 #endif
01479   }
01480 }
01481 
01482 #endif 
01483 
01484