Julius 4.2
libjulius/src/backtrellis.c
説明を見る。
00001 
00052 /*
00053  * Copyright (c) 1991-2011 Kawahara Lab., Kyoto University
00054  * Copyright (c) 2000-2005 Shikano Lab., Nara Institute of Science and Technology
00055  * Copyright (c) 2005-2011 Julius project team, Nagoya Institute of Technology
00056  * All rights reserved
00057  */
00058 
00059 #include <julius/julius.h>
00060 
00078 void
00079 bt_init(BACKTRELLIS *bt)
00080 {
00081   bt->num  = NULL;
00082   bt->rw   = NULL;
00083   bt->list = NULL;
00084   bt->root = NULL;
00085 }
00086 
00103 void
00104 bt_prepare(BACKTRELLIS *bt)
00105 {
00106   /* free previously allocated data */
00107   mybfree2(&(bt->root));
00108 
00109   /* reset entry point */
00110   bt->num = NULL;
00111   bt->rw = NULL;
00112   bt->list = NULL;
00113   bt->root = NULL;
00114 }  
00115 
00130 void
00131 bt_free(BACKTRELLIS *bt)
00132 {
00133   if (bt->root) mybfree2(&(bt->root));
00134   free(bt);
00135 }
00136 
00153 TRELLIS_ATOM *
00154 bt_new(BACKTRELLIS *bt)
00155 {
00156   TRELLIS_ATOM *new;
00157 
00158   new = (TRELLIS_ATOM *)mybmalloc2(sizeof(TRELLIS_ATOM), &(bt->root));
00159   return new;
00160 }
00161 
00162 
00163 
00189 void
00190 bt_store(BACKTRELLIS *bt, TRELLIS_ATOM *tatom)
00191 {
00192 #ifdef WORD_GRAPH
00193   tatom->within_context = FALSE;
00194   tatom->within_wordgraph = FALSE;
00195 #endif
00196   tatom->next = bt->list;
00197   bt->list = tatom;
00198 }
00199 
00217 void
00218 bt_relocate_rw(BACKTRELLIS *bt)
00219 {
00220   TRELLIS_ATOM *tre;
00221   int t;
00222   int totalnum, n;
00223   TRELLIS_ATOM **tmp;
00224 
00225   if (bt->framelen == 0) {
00226     bt->num = NULL;
00227     return;
00228   }
00229 
00230   bt->num = (int *)mybmalloc2(sizeof(int) * bt->framelen, &(bt->root));
00231 
00232   /* count number of trellis atom (= survived word end) for each frame */
00233   for (t=0;t<bt->framelen;t++) bt->num[t] = 0;
00234   totalnum = 0;
00235   for (tre=bt->list;tre;tre=tre->next) {
00236     /* the last frame (when triggered from sp to non-sp) should be discarded */
00237     if (tre->endtime >= bt->framelen) continue;
00238     bt->num[tre->endtime]++;
00239     totalnum++;
00240   }
00241   /* if no atom found, return here with all bt->num[t] set to 0 */
00242   if (totalnum <= 0) {
00243     bt->num = NULL;
00244     return;
00245   }
00246   
00247   /* allocate area */
00248   bt->rw  = (TRELLIS_ATOM ***)mybmalloc2(sizeof(TRELLIS_ATOM **) * bt->framelen, &(bt->root));
00249   tmp = (TRELLIS_ATOM **)mybmalloc2(sizeof(TRELLIS_ATOM *) * totalnum, &(bt->root));
00250   n = 0;
00251   for (t=0;t<bt->framelen;t++) {
00252     if (bt->num[t] > 0) {
00253       bt->rw[t] = (TRELLIS_ATOM **)&(tmp[n]);
00254       n += bt->num[t];
00255     }
00256   }
00257   /* then store the atoms */
00258   for (t=0;t<bt->framelen;t++) bt->num[t] = 0;
00259   for (tre=bt->list;tre;tre=tre->next) {
00260     /* the last frame (when triggered from sp to non-sp) should be discarded */
00261     if (tre->endtime >= bt->framelen) continue;
00262     t = tre->endtime;
00263     
00264     bt->rw[t][bt->num[t]] = tre;
00265     bt->num[t]++;
00266   }
00267 }
00268 
00269 
00270 /* 以下の関数は bt_relocate_rw 実行後にのみ使用可能となる. */
00271 /* functions below this line should be called after bt_relocate_rw() */
00272 
00294 void
00295 set_terminal_words(RecogProcess *r)
00296 {
00297   LOGPROB maxscore;
00298   int i,t;
00299   BACKTRELLIS *bt;
00300 
00301   bt = r->backtrellis;
00302 
00303   if (bt->num == NULL) return;
00304 
00305   maxscore = LOG_ZERO;
00306   /* find last frame where a word exists */
00307   for(t=bt->framelen-1;t>=0;t--) {
00308     if (bt->num[t] > 0) break;
00309   }
00310   /* get maximum word hypothesis at that frame */
00311   for(i=0;i<bt->num[t];i++) {
00312     if (maxscore < (bt->rw[t][i])->backscore) {
00313       maxscore = (bt->rw[t][i])->backscore;
00314       r->sp_break_2_begin_word = (bt->rw[t][i])->wid;
00315     }
00316   }
00317   maxscore = LOG_ZERO;
00318   /* find first frame where a word exists */
00319   for(t=0;t<bt->framelen;t++) {
00320     if (bt->num[t] > 0) break;
00321   }
00322   /* get maximum word hypothesis at that frame */
00323   for(i=0;i<bt->num[t];i++) {
00324     if (maxscore < (bt->rw[t][i])->backscore) {
00325       maxscore = (bt->rw[t][i])->backscore;
00326       r->sp_break_2_end_word = (bt->rw[t][i])->wid;
00327     }
00328   }
00329 #ifdef SP_BREAK_DEBUG
00330   jlog("DEBUG: 2nd pass begin word: %s\n",
00331          (r->sp_break_2_begin_word == WORD_INVALID) ? "WORD_INVALID" : r->lm->winfo->wname[r->sp_break_2_begin_word]);
00332   jlog("DEBUG: 2nd pass end word: %s\n",
00333          (r->sp_break_2_end_word == WORD_INVALID) ? "WORD_INVALID" : r->lm->winfo->wname[r->sp_break_2_end_word]);
00334 #endif
00335 }
00336 
00337 
00338 /* the outprob on the trellis connection point should be discounted */
00366 void
00367 bt_discount_pescore(WCHMM_INFO *wchmm, BACKTRELLIS *bt, HTK_Param *param)
00368 {
00369   int t,i;
00370   TRELLIS_ATOM *tre;
00371 
00372   if (bt->num == NULL) return;
00373   
00374   for (t=0; t<bt->framelen; t++) {
00375     for (i=0; i<bt->num[t]; i++) {
00376       tre = bt->rw[t][i];
00377       /* On normal version, both language score and the output prob. score
00378          at the connection point should removed on the trellis for the
00379          later connection.  On multi-path mode, removing only the language
00380          score is enough. */
00381       tre->backscore -= outprob_style(wchmm, wchmm->wordend[tre->wid], tre->last_tre->wid, t, param);
00382     }
00383   }
00384 }
00385 
00400 void
00401 bt_discount_lm(BACKTRELLIS *bt)
00402 {
00403   int t,i;
00404   TRELLIS_ATOM *tre;
00405 
00406   if (bt->num == NULL) return;
00407   
00408   /* the LM score of the last word should be subtracted, because
00409      their LM will be assigned by 3-gram on the 2nd pass. */
00410   for (t=0; t<bt->framelen; t++) {
00411     for (i=0; i<bt->num[t]; i++) {
00412       tre = bt->rw[t][i];
00413       tre->backscore -= tre->lscore;
00414     }
00415   }
00416 }
00417 
00438 static int
00439 compare_wid(TRELLIS_ATOM **a, TRELLIS_ATOM **b)
00440 {
00441   if ((*a)->wid > (*b)->wid) return 1;
00442   if ((*a)->wid < (*b)->wid) return -1;
00443   return 0;
00444 }
00445 
00467 void
00468 bt_sort_rw(BACKTRELLIS *bt)
00469 {
00470   int t;
00471 
00472   if (bt->num == NULL) return;
00473 
00474   for (t=0;t<bt->framelen;t++) {
00475     qsort(bt->rw[t], bt->num[t], sizeof(TRELLIS_ATOM *),
00476           (int (*)(const void *,const void *))compare_wid);
00477   }
00478 }
00479 
00480 /* 以下の関数は事前にbt_sort_rw() が呼ばれていること(第2パス用) */
00481 /* functions below should be called after bt_sort_rw() */
00482 
00508 TRELLIS_ATOM *
00509 bt_binsearch_atom(BACKTRELLIS *bt, int t, WORD_ID wkey)
00510 {
00511   /* do binary search */
00512   /* assume rw are ordered by wid */
00513   int left, right, mid;
00514   TRELLIS_ATOM *tmp;
00515 #ifdef WPAIR
00516   int i;
00517   LOGPROB maxscore;
00518   TRELLIS_ATOM *maxtre;
00519 #endif
00520   
00521   if (bt->num[t] == 0) return(NULL);
00522   
00523   left = 0;
00524   right = bt->num[t] - 1;
00525   while (left < right) {
00526     mid = (left + right) / 2;
00527     if ((bt->rw[t][mid])->wid < wkey) {
00528       left = mid + 1;
00529     } else {
00530       right = mid;
00531     }
00532   }
00533   tmp = bt->rw[t][left];
00534   if (tmp->wid == wkey) {
00535 #ifdef WPAIR
00536     /* same word with different context will be found:
00537        most likely one will be returned */
00538     maxscore = LOG_ZERO;
00539     maxtre = NULL;
00540     i = left;
00541     while (i >= 0) {
00542       tmp = bt->rw[t][i];
00543       if (tmp->wid != wkey) break;
00544 #ifdef WORD_GRAPH
00545       /* only words on a graph path should be counted */
00546       if (!tmp->within_wordgraph) {
00547         i--; continue;
00548       }
00549 #endif
00550       if (maxscore < tmp->backscore) {
00551         maxscore = tmp->backscore;
00552         maxtre = tmp;
00553       }
00554       i--;
00555     }
00556     i = left;
00557     while (i < bt->num[t]) {
00558       tmp = bt->rw[t][i];
00559       if (tmp->wid != wkey) break;
00560 #ifdef WORD_GRAPH
00561       /* only words on a graph path should be counted */
00562       if (!tmp->within_wordgraph) {
00563         i++; continue;
00564       }
00565 #endif
00566       if (maxscore < tmp->backscore) {
00567         maxscore = tmp->backscore;
00568         maxtre = tmp;
00569       }
00570       i++;
00571     }
00572     tmp = maxtre;
00573 #else
00574 #ifdef WORD_GRAPH
00575     /* treat only words on a graph path */
00576     if (! tmp->within_wordgraph) {
00577       return NULL;
00578     }
00579 #endif
00580 #endif /* WPAIR */
00581 
00582     return(tmp);
00583   } else {
00584     return(NULL);
00585   }
00586 }
00587 
00588 /* end of file */