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 
00361 void
00362 malloc_wordtrellis(RecogProcess *r)
00363 {
00364   int maxwn;
00365   StackDecode *dwrk;
00366 
00367   maxwn = r->lm->winfo->maxwn + 10;     
00368   dwrk = &(r->pass2);
00369 
00370   dwrk->wordtrellis[0] = (LOGPROB *)mymalloc(sizeof(LOGPROB) * maxwn);
00371   dwrk->wordtrellis[1] = (LOGPROB *)mymalloc(sizeof(LOGPROB) * maxwn);
00372 
00373   dwrk->g = (LOGPROB *)mymalloc(sizeof(LOGPROB) * r->peseqlen);
00374 
00375   dwrk->phmmlen_max = r->lm->winfo->maxwlen + 2;
00376   dwrk->phmmseq = (HMM_Logical **)mymalloc(sizeof(HMM_Logical *) * dwrk->phmmlen_max);
00377   if (r->lm->config->enable_iwsp && r->am->hmminfo->multipath) {
00378     dwrk->has_sp = (boolean *)mymalloc(sizeof(boolean) * dwrk->phmmlen_max);
00379   } else {
00380     dwrk->has_sp = NULL;
00381   }
00382 
00383   dwrk->wef = NULL;
00384   dwrk->wes = NULL;
00385   dwrk->wend_token_frame[0] = NULL;
00386   dwrk->wend_token_frame[1] = NULL;
00387   dwrk->wend_token_gscore[0] = NULL;
00388   dwrk->wend_token_gscore[1] = NULL;
00389 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00390   if (r->graphout) {
00391     dwrk->wef = (short *)mymalloc(sizeof(short) * r->peseqlen);
00392     dwrk->wes = (LOGPROB *)mymalloc(sizeof(LOGPROB) * r->peseqlen);
00393     dwrk->wend_token_frame[0] = (short *)mymalloc(sizeof(short) * maxwn);
00394     dwrk->wend_token_frame[1] = (short *)mymalloc(sizeof(short) * maxwn);
00395     dwrk->wend_token_gscore[0] = (LOGPROB *)mymalloc(sizeof(LOGPROB) * maxwn);
00396     dwrk->wend_token_gscore[1] = (LOGPROB *)mymalloc(sizeof(LOGPROB) * maxwn);
00397   }
00398 #endif
00399 }
00400 
00413 void
00414 free_wordtrellis(StackDecode *dwrk)
00415 {
00416   free(dwrk->wordtrellis[0]);
00417   free(dwrk->wordtrellis[1]);
00418   free(dwrk->g);
00419   free(dwrk->phmmseq);
00420   if (dwrk->has_sp) {
00421     free(dwrk->has_sp);
00422     dwrk->has_sp = NULL;
00423   }
00424 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00425   if (dwrk->wef) {
00426     free(dwrk->wef);
00427     free(dwrk->wes);
00428     free(dwrk->wend_token_frame[0]);
00429     free(dwrk->wend_token_frame[1]);
00430     free(dwrk->wend_token_gscore[0]);
00431     free(dwrk->wend_token_gscore[1]);
00432     dwrk->wef = NULL;
00433   }
00434 #endif
00435 }
00436 
00437 
00438 
00439 
00440 
00441 
00442 
00443 
00444 
00445 
00446 
00447 
00448 
00449 
00491 static void
00492 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) 
00493 {
00494   HMM *whmm;                    
00495   int wordhmmnum;               
00496   int startt;                   
00497   LOGPROB tmpmax,tmpscore;      
00498   A_CELL *ac;
00499   int t,i,j;
00500   boolean node_exist_p;
00501   int tn;                      
00502   int tl;                      
00503 
00504   
00505   StackDecode *dwrk;
00506   WORD_INFO *winfo;
00507   HTK_HMM_INFO *hmminfo;
00508   LOGPROB *framemaxscore;
00509 #ifdef SCAN_BEAM
00510   LOGPROB scan_beam_thres;
00511 #endif
00512 
00513   dwrk = &(r->pass2);
00514   winfo = r->lm->winfo;
00515   hmminfo = r->am->hmminfo;
00516   framemaxscore = r->pass2.framemaxscore;
00517 #ifdef SCAN_BEAM
00518   scan_beam_thres = r->config->pass2.scan_beam_thres;
00519 #endif
00520 
00521 
00522 #ifdef TCD
00523   jlog("DEBUG: scan for:");
00524   for (i=0;i<phmmlen;i++) {
00525     jlog(" %s", phmmseq[i]->name);
00526   }
00527   jlog("\n");
00528 #endif
00529   
00530   
00531   
00532   whmm = new_make_word_hmm(hmminfo, phmmseq, phmmlen, has_sp);
00533   if (whmm == NULL) {
00534     j_internal_error("Error: failed to make word hmm\n");
00535   }
00536   wordhmmnum = whmm->len;
00537   if (wordhmmnum >= winfo->maxwn + 10) {
00538     j_internal_error("do_viterbi: word too long (>%d)\n", winfo->maxwn + 10);
00539   }
00540 
00541   
00542   
00543   for(t = framelen-1; t >=0 ; t--) {
00544     if (
00545 #ifdef SCAN_BEAM
00546         g[t] > framemaxscore[t] - scan_beam_thres &&
00547 #endif
00548         g[t] > LOG_ZERO) {
00549       break;
00550     }
00551   }
00552   if (t < 0) {                  
00553     
00554     for(t=0;t<framelen;t++) {
00555       g_new[t] = LOG_ZERO;
00556 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00557       if (r->graphout) {
00558         wordend_frame_dst[t] = -1;
00559         wordend_gscore_dst[t] = LOG_ZERO;
00560       }
00561 #endif
00562     }
00563     free_hmm(whmm);
00564     return;
00565   }
00566   startt = t;
00567   
00568   
00569   
00570   for(t=framelen-1;t>startt;t--) {
00571     g_new[t] = LOG_ZERO;
00572 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00573     if (r->graphout) {
00574       wordend_frame_dst[t] = -1;
00575       wordend_gscore_dst[t] = LOG_ZERO;
00576     }
00577 #endif
00578   }
00579 
00580   
00581   
00582   
00583 
00584   
00585   tn = 0; tl = 1;
00586 
00587 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00588   if (r->graphout) {
00589     for(i=0;i<wordhmmnum;i++) {
00590       dwrk->wend_token_frame[tn][i] = -1;
00591       dwrk->wend_token_gscore[tn][i] = LOG_ZERO;
00592     }
00593   }
00594 #endif
00595 
00596   if (! hmminfo->multipath) {
00597     
00598     
00599     for(i=0;i<wordhmmnum-1;i++) dwrk->wordtrellis[tn][i] = LOG_ZERO;
00600     dwrk->wordtrellis[tn][wordhmmnum-1] = g[startt] + outprob(&(r->am->hmmwrk), startt, &(whmm->state[wordhmmnum-1]), param);
00601     g_new[startt] = dwrk->wordtrellis[tn][0];
00602 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00603     if (r->graphout) {
00604       dwrk->wend_token_frame[tn][wordhmmnum-1] = wordend_frame_src[startt];
00605       dwrk->wend_token_gscore[tn][wordhmmnum-1] = wordend_gscore_src[startt];
00606       wordend_frame_dst[startt] = dwrk->wend_token_frame[tn][0];
00607       wordend_gscore_dst[startt] = dwrk->wend_token_gscore[tn][0];
00608     }
00609 #endif
00610   }
00611   
00612   
00613   
00614   for(t = hmminfo->multipath ? startt : startt - 1; t >= 0; t--) {
00615     
00616     
00617     
00618     i = tn; tn = tl; tl = i;
00619 
00620     node_exist_p = FALSE;       
00621 
00622     if (! hmminfo->multipath) {
00623     
00624       
00625       
00626       tmpscore = LOG_ZERO;
00627       for (ac=whmm->state[wordhmmnum-1].ac;ac;ac=ac->next) {
00628         if (tmpscore < dwrk->wordtrellis[tl][ac->arc] + ac->a) {
00629           j = ac->arc;
00630           tmpscore = dwrk->wordtrellis[tl][ac->arc] + ac->a;
00631         }
00632       }
00633       if (g[t] > tmpscore) {
00634         tmpmax = g[t];
00635 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00636         if (r->graphout) {
00637           dwrk->wend_token_frame[tn][wordhmmnum-1] = wordend_frame_src[t];
00638           dwrk->wend_token_gscore[tn][wordhmmnum-1] = wordend_gscore_src[t];
00639         }
00640 #endif
00641       } else {
00642         tmpmax = tmpscore;
00643 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00644         if (r->graphout) {
00645           dwrk->wend_token_frame[tn][wordhmmnum-1] = dwrk->wend_token_frame[tl][j];
00646           dwrk->wend_token_gscore[tn][wordhmmnum-1] = dwrk->wend_token_gscore[tl][j];
00647         }
00648 #endif
00649       }
00650       
00651       
00652       
00653       if (
00654 #ifdef SCAN_BEAM
00655           tmpmax <= framemaxscore[t] - scan_beam_thres ||
00656 #endif
00657           tmpmax <= LOG_ZERO
00658           ) {
00659         dwrk->wordtrellis[tn][wordhmmnum-1] = LOG_ZERO;
00660 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00661         if (r->graphout) {
00662           dwrk->wend_token_frame[tn][wordhmmnum-1] = -1;
00663           dwrk->wend_token_gscore[tn][wordhmmnum-1] = LOG_ZERO;
00664         }
00665 #endif
00666       } else {
00667         node_exist_p = TRUE;
00668         dwrk->wordtrellis[tn][wordhmmnum-1] = tmpmax + outprob(&(r->am->hmmwrk), t, &(whmm->state[wordhmmnum-1]), param);
00669       }
00670 
00671     }
00672 
00673     
00674     
00675     for(i=wordhmmnum-2;i>=0;i--) {
00676       
00677       
00678       
00679       tmpmax = LOG_ZERO;
00680       for (ac=whmm->state[i].ac;ac;ac=ac->next) {
00681         if (hmminfo->multipath) {
00682           if (ac->arc == wordhmmnum-1) tmpscore = g[t];
00683           else if (t + 1 > startt) tmpscore = LOG_ZERO;
00684           else tmpscore = dwrk->wordtrellis[tl][ac->arc];
00685           tmpscore += ac->a;
00686         } else {
00687           tmpscore = dwrk->wordtrellis[tl][ac->arc] + ac->a;
00688         }
00689         if (tmpmax < tmpscore) {
00690           tmpmax = tmpscore;
00691           j = ac->arc;
00692         }
00693       }
00694       
00695       
00696       
00697       if (
00698 #ifdef SCAN_BEAM
00699           tmpmax <= framemaxscore[t] - scan_beam_thres ||
00700 #endif
00701           tmpmax <= LOG_ZERO
00702           ) {
00703         
00704         dwrk->wordtrellis[tn][i] = LOG_ZERO;
00705 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00706         if (r->graphout) {
00707           dwrk->wend_token_frame[tn][i] = -1;
00708           dwrk->wend_token_gscore[tn][i] = LOG_ZERO;
00709         }
00710 #endif
00711       } else {
00712         
00713         node_exist_p = TRUE;
00714         dwrk->wordtrellis[tn][i] = tmpmax;
00715         if (! hmminfo->multipath || i > 0) {
00716           dwrk->wordtrellis[tn][i] += outprob(&(r->am->hmmwrk), t, &(whmm->state[i]), param);
00717         }
00718 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00719         if (r->graphout) {
00720           if (hmminfo->multipath) {
00721             if (j == wordhmmnum-1) {
00722               dwrk->wend_token_frame[tn][i] = wordend_frame_src[t];
00723               dwrk->wend_token_gscore[tn][i] = wordend_gscore_src[t];
00724             } else {
00725               dwrk->wend_token_frame[tn][i] = dwrk->wend_token_frame[tl][j];
00726               dwrk->wend_token_gscore[tn][i] = dwrk->wend_token_gscore[tl][j];
00727             }
00728           } else {
00729             dwrk->wend_token_frame[tn][i] = dwrk->wend_token_frame[tl][j];
00730             dwrk->wend_token_gscore[tn][i] = dwrk->wend_token_gscore[tl][j];
00731           }
00732         }
00733 #endif
00734       }
00735     } 
00736 
00737     
00738     
00739     g_new[t] = dwrk->wordtrellis[tn][0];
00740 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00741     if (r->graphout) {
00742     
00743       wordend_frame_dst[t] = dwrk->wend_token_frame[tn][0];
00744       wordend_gscore_dst[t] = dwrk->wend_token_gscore[tn][0];
00745     }
00746 #endif
00747     
00748 
00749 
00750     
00751 
00752 
00753 
00754     if (t < least_frame && (!node_exist_p)) {
00755       
00756       for (i=t-1;i>=0;i--) {
00757         g_new[i] = LOG_ZERO;
00758 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00759         if (r->graphout) {
00760           wordend_frame_dst[i] = -1;
00761           wordend_gscore_dst[i] = LOG_ZERO;
00762         }
00763 #endif
00764       }
00765       
00766       break;
00767     }
00768     
00769   } 
00770 
00771   if (hmminfo->multipath) {
00772     
00773     
00774     if (t < 0) {                        
00775       tmpmax = LOG_ZERO;
00776       for(ac=whmm->state[0].ac;ac;ac=ac->next) {
00777         tmpscore = dwrk->wordtrellis[tn][ac->arc] + ac->a;
00778         if (tmpmax < tmpscore) tmpmax = tmpscore;
00779       }
00780       *final_g = tmpmax;
00781     } else {
00782       *final_g = LOG_ZERO;
00783     }
00784   }
00785 
00786   
00787   free_hmm(whmm);
00788 }
00789 
00813 static void
00814 do_viterbi_next_word(NODE *now, NODE *new, HMM_Logical *lastphone, boolean sp, HTK_Param *param, RecogProcess *r) 
00815 {
00816   int t, n;
00817   LOGPROB a_value;              
00818   int peseqlen;
00819   boolean multipath;
00820   StackDecode *dwrk;
00821 
00822   dwrk = &(r->pass2);
00823 
00824   multipath = r->am->hmminfo->multipath;
00825 
00826   peseqlen = r->peseqlen;
00827   
00828   if (! multipath) {
00829 
00830     
00831 
00832 
00833 
00834 
00835     
00836 
00837 
00838 
00839 
00840 
00841     if (r->lm->winfo->wlen[now->seq[now->seqnum-1]] > 1) {
00842       n = hmm_logical_state_num(lastphone);
00843       a_value = (hmm_logical_trans(lastphone))->a[n-2][n-1];
00844       for(t=0; t<peseqlen-1; t++) dwrk->g[t] = now->g[t+1] + a_value;
00845       dwrk->g[peseqlen-1] = LOG_ZERO;
00846     } else {
00847       for(t=0; t<peseqlen; t++) dwrk->g[t] = now->g[t];
00848     }
00849 
00850   } else {
00851   
00852     for(t=0; t<peseqlen; t++) dwrk->g[t] = now->g[t];
00853     dwrk->phmmseq[0] = lastphone;
00854     if (r->lm->config->enable_iwsp) dwrk->has_sp[0] = sp;
00855 
00856   }
00857   
00858   do_viterbi(dwrk->g, new->g,
00859              multipath ? dwrk->phmmseq : &lastphone,
00860              (r->lm->config->enable_iwsp && multipath) ? dwrk->has_sp : NULL,
00861              1, param, peseqlen, now->estimated_next_t, &(new->final_g)
00862 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00863              , now->wordend_frame, new->wordend_frame
00864              , now->wordend_gscore, new->wordend_gscore
00865 #else
00866              , NULL, NULL
00867              , NULL, NULL
00868 #endif
00869              , r
00870              );
00871 
00872 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00873   if (! multipath) {
00874     if (r->graphout) {
00875       
00876       
00877       new->wordend_frame[r->peseqlen-1] = new->wordend_frame[0];
00878       new->wordend_gscore[r->peseqlen-1] = new->wordend_gscore[0];
00879       for (t=0;t<r->peseqlen-1;t++) {
00880         new->wordend_frame[t] = new->wordend_frame[t+1];
00881         new->wordend_gscore[t] = new->wordend_gscore[t+1];
00882       }
00883     }
00884   }
00885 #endif
00886 }
00887 
00907 void
00908 scan_word(NODE *now, HTK_Param *param, RecogProcess *r)
00909 {
00910   int   i,t;
00911   WORD_ID word;
00912   int phmmlen;
00913   HMM_Logical *tailph;
00914 
00915   
00916   WORD_INFO *winfo;
00917   HTK_HMM_INFO *hmminfo;
00918   int peseqlen;
00919   boolean ccd_flag;
00920   boolean enable_iwsp;          
00921   StackDecode *dwrk;
00922 
00923   dwrk = &(r->pass2);
00924   winfo = r->lm->winfo;
00925   hmminfo = r->am->hmminfo;
00926   peseqlen = r->peseqlen;
00927   ccd_flag = r->ccd_flag;
00928   if (hmminfo->multipath) {
00929     enable_iwsp = r->lm->config->enable_iwsp;
00930   }
00931   
00932 #ifndef GRAPHOUT_PRECISE_BOUNDARY
00933   if (r->graphout) {
00934     if (ccd_flag) {
00935       now->tail_g_score = now->g[now->bestt];
00936     }
00937   }
00938 #endif
00939 
00940   
00941   
00942   
00943   
00944 
00945 
00946   word = now->seq[now->seqnum-1];
00947   
00948 #ifdef TCD
00949     jlog("DEBUG: w=");
00950     for(i=0;i<winfo->wlen[word];i++) {
00951       jlog(" %s",(winfo->wseq[word][i])->name);
00952     }
00953     if (ccd_flag) {
00954       if (now->last_ph != NULL) {
00955         jlog(" | %s", (now->last_ph)->name);
00956       }
00957     }
00958     jlog("\n");
00959 #endif 
00960     
00961   if (ccd_flag) {
00962     
00963     
00964     if (now->last_ph != NULL) {
00965       tailph = get_right_context_HMM(winfo->wseq[word][winfo->wlen[word]-1], now->last_ph->name, hmminfo);
00966       if (tailph == NULL) {
00967         
00968         
00969 
00970         
00971         if (winfo->wlen[word] > 1 && winfo->wseq[word][winfo->wlen[word]-1]->is_pseudo){
00972           error_missing_right_triphone(winfo->wseq[word][winfo->wlen[word]-1], now->last_ph->name);
00973         }
00974 
00975         tailph = winfo->wseq[word][winfo->wlen[word]-1];
00976       }
00977     } else {
00978       tailph = winfo->wseq[word][winfo->wlen[word]-1];
00979     }
00980     
00981     
00982 
00983     if (winfo->wlen[word] == 1) {
00984       now->last_ph = tailph;
00985       if (enable_iwsp && hmminfo->multipath) now->last_ph_sp_attached = TRUE;
00986 #ifdef GRAPHOUT_PRECISE_BOUNDARY
00987       if (r->graphout) {
00988         
00989         
00990         for (t=0;t<peseqlen;t++) {
00991           now->wordend_frame[t] = t;
00992           now->wordend_gscore[t] = now->g[t];
00993         }
00994       }
00995 #endif
00996 #ifdef TCD
00997       jlog("DEBUG: suspended as %s\n", (now->last_ph)->name);
00998 #endif
00999       return;
01000     }
01001 
01002     
01003     
01004     phmmlen = winfo->wlen[word] - 1;
01005     if (phmmlen > dwrk->phmmlen_max) {
01006       j_internal_error("scan_word: num of phonemes in a word exceed phmmlenmax (%d) ?\n", dwrk->phmmlen_max);
01007     }
01008     for (i=0;i<phmmlen-1;i++) {
01009       dwrk->phmmseq[i] = winfo->wseq[word][i+1];
01010     }
01011     dwrk->phmmseq[phmmlen-1] = tailph;
01012     if (enable_iwsp && hmminfo->multipath) {
01013       for (i=0;i<phmmlen-1;i++) dwrk->has_sp[i] = FALSE;
01014       dwrk->has_sp[phmmlen-1] = TRUE;
01015     }
01016 
01017   } else {                      
01018 
01019     phmmlen = winfo->wlen[word];
01020     for (i=0;i<phmmlen;i++) dwrk->phmmseq[i] = winfo->wseq[word][i];
01021     if (enable_iwsp && hmminfo->multipath) {
01022       for (i=0;i<phmmlen;i++) dwrk->has_sp[i] = FALSE;
01023       dwrk->has_sp[phmmlen-1] = TRUE;
01024     }
01025 
01026   }
01027 
01028   
01029   
01030   for (t=0;t<peseqlen;t++) dwrk->g[t] = now->g[t];
01031 
01032 #ifdef GRAPHOUT_PRECISE_BOUNDARY
01033   if (r->graphout) {
01034     
01035     
01036     for (t=0;t<peseqlen;t++) {
01037       dwrk->wef[t] = t;
01038       dwrk->wes[t] = now->g[t];
01039     }
01040   }
01041 #endif
01042 
01043   
01044   
01045   do_viterbi(dwrk->g, now->g, dwrk->phmmseq, (enable_iwsp && hmminfo->multipath) ? dwrk->has_sp : NULL, 
01046              phmmlen, param, peseqlen, now->estimated_next_t, &(now->final_g)
01047 #ifdef GRAPHOUT_PRECISE_BOUNDARY
01048              
01049              
01050              , dwrk->wef, now->wordend_frame
01051              , dwrk->wes, now->wordend_gscore
01052 #else
01053              , NULL, NULL
01054              , NULL, NULL
01055 #endif
01056              , r
01057              );
01058 #ifdef GRAPHOUT_PRECISE_BOUNDARY
01059   if (! hmminfo->multipath) {
01060     if (r->graphout) {
01061       
01062       
01063       now->wordend_frame[peseqlen-1] = now->wordend_frame[0];
01064       now->wordend_gscore[peseqlen-1] = now->wordend_gscore[0];
01065       for (t=0;t<peseqlen-1;t++) {
01066         now->wordend_frame[t] = now->wordend_frame[t+1];
01067         now->wordend_gscore[t] = now->wordend_gscore[t+1];
01068       }
01069     }
01070   }
01071 #endif
01072 
01073   if (ccd_flag) {
01074     
01075     
01076     now->last_ph = winfo->wseq[word][0];
01077     if (enable_iwsp && hmminfo->multipath) now->last_ph_sp_attached = FALSE; 
01078 #ifdef TCD
01079     jlog("DEBUG: last_ph = %s\n", (now->last_ph)->name);
01080 #endif
01081   }
01082 }
01083 
01084 
01085 
01086 
01087 
01088 
01089 
01115 void
01116 next_word(NODE *now, NODE *new, NEXTWORD *nword, HTK_Param *param, RecogProcess *r)
01117 {
01118   HMM_Logical *lastphone, *newphone;
01119   LOGPROB *g_src;
01120   int   t;
01121   int lastword;
01122   int   i;
01123   LOGPROB a_value;
01124   LOGPROB tmpp;
01125   int   startt;
01126   int word;
01127   TRELLIS_ATOM *tre;
01128   LOGPROB totalscore;
01129   BACKTRELLIS *backtrellis;
01130   WORD_INFO *winfo;
01131   HTK_HMM_INFO *hmminfo;
01132   int peseqlen;
01133   boolean ccd_flag;
01134   StackDecode *dwrk;
01135 
01136   dwrk = &(r->pass2);
01137   backtrellis = r->backtrellis;
01138   winfo = r->lm->winfo;
01139   hmminfo = r->am->hmminfo;
01140   peseqlen = r->peseqlen;
01141   ccd_flag = r->ccd_flag;
01142 
01143   word = nword->id;
01144   lastword = now->seq[now->seqnum-1];
01145 
01146   
01147   
01148   if (ccd_flag) {
01149     
01150     
01151     lastphone = get_left_context_HMM(now->last_ph, winfo->wseq[word][winfo->wlen[word]-1]->name, hmminfo);
01152     if (lastphone == NULL) {
01153       
01154       
01155 
01156       
01157       if (now->last_ph->is_pseudo){
01158         error_missing_left_triphone(now->last_ph, winfo->wseq[word][winfo->wlen[word]-1]->name);
01159       }
01160       lastphone = now->last_ph;
01161     }
01162   }
01163 
01164   
01165   
01166   if (ccd_flag) {
01167     newphone = get_right_context_HMM(winfo->wseq[word][winfo->wlen[word]-1], now->last_ph->name, hmminfo);
01168     if (newphone == NULL) {
01169       
01170       
01171 
01172       
01173       if (winfo->wlen[word] > 1 && winfo->wseq[word][winfo->wlen[word]-1]->is_pseudo){
01174         error_missing_right_triphone(winfo->wseq[word][winfo->wlen[word]-1], now->last_ph->name);
01175       }
01176       newphone = winfo->wseq[word][winfo->wlen[word]-1];
01177     }
01178   } else {
01179     newphone = winfo->wseq[word][winfo->wlen[word]-1];
01180   }
01181   
01182   
01183   
01184   new->score = LOG_ZERO;
01185   for (i=0;i< now->seqnum;i++){
01186     new->seq[i] = now->seq[i];
01187 #ifdef CM_SEARCH
01188 #ifdef CM_MULTIPLE_ALPHA
01189     memcpy(new->cmscore[i], now->cmscore[i], sizeof(LOGPROB) * r->config->annotate.cm_alpha_num);
01190 #else
01191     new->cmscore[i] = now->cmscore[i];
01192 #endif
01193 #endif 
01194   }
01195   new->seq[i] = word;
01196   new->seqnum = now->seqnum+1;
01197   new->state = nword->next_state;
01198   new->totallscore = now->totallscore + nword->lscore;
01199   if (ccd_flag) {
01200     
01201     
01202     new->last_ph = lastphone;
01203     new->last_ph_sp_attached = now->last_ph_sp_attached;
01204   }
01205 
01206   if (ccd_flag) {
01207     
01208     
01209     do_viterbi_next_word(now, new, lastphone,
01210                          hmminfo->multipath ? now->last_ph_sp_attached : FALSE,
01211                          param, r);
01212     g_src = new->g;
01213   } else {
01214     g_src = now->g;
01215 #ifdef GRAPHOUT_PRECISE_BOUNDARY
01216     if (r->graphout) {
01217       memcpy(new->wordend_frame, now->wordend_frame, sizeof(short)*peseqlen);
01218       memcpy(new->wordend_gscore, now->wordend_gscore, sizeof(LOGPROB)*peseqlen);
01219     }
01220 #endif
01221   }
01222       
01223   
01224   
01225   if (hmminfo->multipath) {
01226     startt = peseqlen-1;
01227   } else {
01228     startt = peseqlen-2;
01229   }
01230   i = hmm_logical_state_num(newphone);
01231   a_value = (hmm_logical_trans(newphone))->a[i-2][i-1];
01232   if (hmminfo->multipath) {
01233     for(t=0; t <= startt; t++) {
01234       new->g[t] = g_src[t] + nword->lscore;
01235     }
01236   } else {
01237     for(t=0; t <= startt; t++) {
01238       new->g[t] = g_src[t+1] + a_value + nword->lscore;
01239     }
01240   }
01241 
01242   
01243   
01244   
01245   
01246   
01247   
01248   
01249 
01250   
01251 
01252   if (r->lmtype == LM_DFA && !r->config->pass2.looktrellis_flag) {
01253     
01254     
01255     for(t = startt; t >= 0; t--) {
01256       tre = bt_binsearch_atom(backtrellis, t, (WORD_ID) word);
01257       if (tre == NULL) continue;
01258       totalscore = new->g[t] + tre->backscore;
01259       if (! hmminfo->multipath) {
01260         if (newphone->is_pseudo) {
01261           tmpp = outprob_cd(&(r->am->hmmwrk), t, &(newphone->body.pseudo->stateset[newphone->body.pseudo->state_num-2]), param);
01262         } else {
01263           tmpp = outprob_state(&(r->am->hmmwrk), t, newphone->body.defined->s[newphone->body.defined->state_num-2], param);
01264         }
01265         totalscore += tmpp;
01266       }
01267       if (new->score < totalscore) {
01268         new->score = totalscore;
01269         new->bestt = t;
01270         new->estimated_next_t = tre->begintime - 1;
01271         new->tre = tre;
01272       }
01273     }
01274 
01275     return;
01276   }
01277 
01278   
01279   
01280 
01281   
01282 
01283   
01284   
01285   for(t = (nword->tre)->endtime; t >= 0; t--) {
01286     tre = bt_binsearch_atom(backtrellis, t, (WORD_ID) word);
01287     if (tre == NULL) break;     
01288     totalscore = new->g[t] + tre->backscore;
01289     if (! hmminfo->multipath) {
01290       if (newphone->is_pseudo) {
01291         tmpp = outprob_cd(&(r->am->hmmwrk), t, &(newphone->body.pseudo->stateset[newphone->body.pseudo->state_num-2]), param);
01292       } else {
01293         tmpp = outprob_state(&(r->am->hmmwrk), t, newphone->body.defined->s[newphone->body.defined->state_num-2], param);
01294       }
01295       totalscore += tmpp;
01296     }
01297     if (new->score < totalscore) {
01298       new->score = totalscore;
01299       new->bestt = t;
01300       new->estimated_next_t = tre->begintime - 1;
01301       new->tre = tre;
01302     }
01303   }
01304   
01305   for(t = (nword->tre)->endtime + 1; t <= startt; t++) {
01306     tre = bt_binsearch_atom(backtrellis, t, (WORD_ID) word);
01307     if (tre == NULL) break;     
01308     totalscore = new->g[t] + tre->backscore;
01309     if (! hmminfo->multipath) {
01310       if (newphone->is_pseudo) {
01311         tmpp = outprob_cd(&(r->am->hmmwrk), t, &(newphone->body.pseudo->stateset[newphone->body.pseudo->state_num-2]), param);
01312       } else {
01313         tmpp = outprob_state(&(r->am->hmmwrk), t, newphone->body.defined->s[newphone->body.defined->state_num-2], param);
01314       }
01315       totalscore += tmpp;
01316     }
01317     if (new->score < totalscore) {
01318       new->score = totalscore;
01319       new->bestt = t;
01320       new->estimated_next_t = tre->begintime - 1;
01321       new->tre = tre;
01322     }
01323   }
01324 
01325   
01326   new->lscore = nword->lscore;
01327   
01328 }
01329 
01330 
01331 
01332 
01333 
01334 
01335 
01357 void
01358 start_word(NODE *new, NEXTWORD *nword, HTK_Param *param, RecogProcess *r)
01359 {
01360   HMM_Logical *newphone;
01361   WORD_ID word;
01362   TRELLIS_ATOM *tre = NULL;
01363   LOGPROB tmpp;
01364   int t;
01365 
01366   BACKTRELLIS *backtrellis;
01367   WORD_INFO *winfo;
01368 
01369   int peseqlen;
01370   boolean ccd_flag;
01371   boolean multipath;
01372 
01373   backtrellis = r->backtrellis;
01374   winfo = r->lm->winfo;
01375   peseqlen = r->peseqlen;
01376   ccd_flag = r->ccd_flag;
01377   multipath = r->am->hmminfo->multipath;
01378 
01379   
01380   word = nword->id;
01381   new->score = LOG_ZERO;
01382   new->seqnum = 1;
01383   new->seq[0] = word;
01384 
01385   new->state = nword->next_state;
01386   new->totallscore = nword->lscore;
01387 
01388   
01389   new->lscore = nword->lscore;
01390 
01391   
01392   newphone = winfo->wseq[word][winfo->wlen[word]-1];
01393   if (ccd_flag) {
01394     new->last_ph = NULL;
01395   }
01396   
01397   if (r->lmtype == LM_PROB) {
01398     new->g[peseqlen-1] = nword->lscore;
01399   } else {
01400     new->g[peseqlen-1] = 0;
01401   }
01402   
01403   for (t=peseqlen-1; t>=0; t--) {
01404     tre = bt_binsearch_atom(backtrellis, t, word);
01405     if (tre != NULL) {
01406       if (r->graphout) {
01407         new->bestt = peseqlen-1;
01408       } else {
01409         new->bestt = t;
01410       }
01411       new->score = new->g[peseqlen-1] + tre->backscore;
01412       if (! multipath) {
01413         if (newphone->is_pseudo) {
01414           tmpp = outprob_cd(&(r->am->hmmwrk), peseqlen-1, &(newphone->body.pseudo->stateset[newphone->body.pseudo->state_num-2]), param);
01415         } else {
01416           tmpp = outprob_state(&(r->am->hmmwrk), peseqlen-1, newphone->body.defined->s[newphone->body.defined->state_num-2], param);
01417         }
01418         new->score += tmpp;
01419       }
01420       new->estimated_next_t = tre->begintime - 1;
01421       new->tre = tre;
01422       break;
01423     }
01424   }
01425   if (tre == NULL) {            
01426     new->score = LOG_ZERO;
01427   }
01428 }
01429 
01451 void
01452 last_next_word(NODE *now, NODE *new, HTK_Param *param, RecogProcess *r)
01453 {
01454   cpy_node(new, now);
01455   if (r->ccd_flag) {
01456     
01457     
01458     if (r->am->hmminfo->multipath) {
01459       do_viterbi_next_word(now, new, now->last_ph, now->last_ph_sp_attached, param, r);
01460       new->score = new->final_g;
01461     } else {
01462       do_viterbi_next_word(now, new, now->last_ph, FALSE, param, r);
01463       new->score = new->g[0];
01464     }
01465   } else {
01466     if (r->am->hmminfo->multipath) {
01467       new->score = now->final_g;
01468     } else {
01469       new->score = now->g[0];
01470     }
01471 #ifdef GRAPHOUT_PRECISE_BOUNDARY
01472     if (r->graphout) {
01473       
01474       memcpy(new->wordend_frame, now->wordend_frame, sizeof(short)*r->peseqlen);
01475       memcpy(new->wordend_gscore, now->wordend_gscore, sizeof(LOGPROB)*r->peseqlen);
01476     }
01477 #endif
01478   }
01479 }
01480 
01481 #endif 
01482 
01483