Julius 4.2
|
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 */