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