00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00043
00044 #include <string.h>
00045 #include <assert.h>
00046
00047
00048 #include <ckd_alloc.h>
00049 #include <listelem_alloc.h>
00050 #include <profile.h>
00051 #include <err.h>
00052
00053
00054 #include "pocketsphinx_internal.h"
00055 #include "ps_lattice_internal.h"
00056 #include "tst_search.h"
00057
00058 static int tst_search_start(ps_search_t *search);
00059 static int tst_search_step(ps_search_t *search, int frame_idx);
00060 static int tst_search_finish(ps_search_t *search);
00061 static int tst_search_reinit(ps_search_t *search);
00062 static ps_lattice_t *tst_search_lattice(ps_search_t *search);
00063 static char const *tst_search_hyp(ps_search_t *search, int32 *out_score);
00064 static int32 tst_search_prob(ps_search_t *search);
00065 static ps_seg_t *tst_search_seg_iter(ps_search_t *search, int32 *out_score);
00066
00067 static ps_searchfuncs_t tst_funcs = {
00068 "tst",
00069 tst_search_start,
00070 tst_search_step,
00071 tst_search_finish,
00072 tst_search_reinit,
00073 tst_search_free,
00074 tst_search_lattice,
00075 tst_search_hyp,
00076 tst_search_prob,
00077 tst_search_seg_iter,
00078 };
00079
00080 static histprune_t *
00081 histprune_init(int32 maxhmm, int32 maxhist, int32 maxword,
00082 int32 hmmhistbinsize, int32 numNodes)
00083 {
00084 histprune_t *h;
00085 int32 n;
00086
00087 h = (histprune_t *) ckd_calloc(1, sizeof(histprune_t));
00088 h->maxwpf = maxword;
00089 h->maxhmmpf = maxhmm;
00090 h->maxhistpf = maxhist;
00091 h->hmm_hist_binsize = hmmhistbinsize;
00092
00093 n = numNodes;
00094 n /= h->hmm_hist_binsize;
00095
00096 h->hmm_hist_bins = n + 1;
00097
00098 h->hmm_hist = (int32 *) ckd_calloc(h->hmm_hist_bins, sizeof(int32));
00099
00100
00101 return h;
00102 }
00103
00104 static void
00105 histprune_zero_histbin(histprune_t * h)
00106 {
00107 int32 *hmm_hist;
00108 int32 numhistbins;
00109 int32 i;
00110
00111 hmm_hist = h->hmm_hist;
00112 numhistbins = h->hmm_hist_bins;
00113
00114 for (i = 0; i < numhistbins; i++)
00115 hmm_hist[i] = 0;
00116
00117 }
00118
00119 static void
00120 histprune_free(histprune_t * h)
00121 {
00122 if (h != NULL) {
00123 if (h->hmm_hist != NULL) {
00124 ckd_free(h->hmm_hist);
00125 }
00126 free(h);
00127 }
00128 }
00129
00130 static void
00131 histprune_showhistbin(histprune_t * hp, int32 nfr, char *uttid)
00132 {
00133 int32 i, j, k;
00134
00135 if (nfr == 0) {
00136 nfr = 1;
00137 E_WARN("Set number of frame to 1\n");
00138 }
00139
00140 for (j = hp->hmm_hist_bins - 1; (j >= 0) && (hp->hmm_hist[j] == 0);
00141 --j);
00142 E_INFO("HMMHist[0..%d](%s):", j, uttid);
00143 for (i = 0, k = 0; i <= j; i++) {
00144 k += hp->hmm_hist[i];
00145 E_INFOCONT(" %d(%d)", hp->hmm_hist[i], (k * 100) / nfr);
00146 }
00147 E_INFOCONT("\n");
00148 }
00149
00150
00151 static void
00152 histprune_report(histprune_t * h)
00153 {
00154 E_INFO_NOFN("Initialization of histprune_t, report:\n");
00155 E_INFO_NOFN("Parameters used in histogram pruning:\n");
00156 E_INFO_NOFN("Max. HMM per frame=%d\n", h->maxhmmpf);
00157 E_INFO_NOFN("Max. history per frame=%d\n", h->maxhistpf);
00158 E_INFO_NOFN("Max. word per frame=%d\n", h->maxwpf);
00159 E_INFO_NOFN("Size of histogram bin=%d\n", h->hmm_hist_binsize);
00160 E_INFO_NOFN("No. of histogram bin=%d\n", h->hmm_hist_bins);
00161 E_INFO_NOFN("\n");
00162 }
00163
00164 static beam_t *
00165 beam_init(float64 hmm, float64 ptr, float64 wd, float64 wdend,
00166 int32 ptranskip, int32 n_ciphone, logmath_t *logmath)
00167 {
00168 beam_t *beam;
00169
00170 beam = (beam_t *) ckd_calloc(1, sizeof(beam_t));
00171
00172 beam->hmm = logmath_log(logmath, hmm);
00173 beam->ptrans = logmath_log(logmath, ptr);
00174 beam->word = logmath_log(logmath, wd);
00175 beam->wordend = logmath_log(logmath, wdend);
00176 beam->ptranskip = ptranskip;
00177 beam->bestscore = MAX_NEG_INT32;
00178 beam->bestwordscore = MAX_NEG_INT32;
00179 beam->n_ciphone = n_ciphone;
00180
00181 beam->wordbestscores = (int32 *) ckd_calloc(n_ciphone, sizeof(int32));
00182 beam->wordbestexits = (int32 *) ckd_calloc(n_ciphone, sizeof(int32));
00183
00184 return beam;
00185 }
00186
00187 static void
00188 beam_report(beam_t * b)
00189 {
00190 E_INFO_NOFN("Initialization of beam_t, report:\n");
00191 E_INFO_NOFN("Parameters used in Beam Pruning of Viterbi Search:\n");
00192 E_INFO_NOFN("Beam=%d\n", b->hmm);
00193 E_INFO_NOFN("PBeam=%d\n", b->ptrans);
00194 E_INFO_NOFN("WBeam=%d (Skip=%d)\n", b->word, b->ptranskip);
00195 E_INFO_NOFN("WEndBeam=%d \n", b->wordend);
00196 E_INFO_NOFN("No of CI Phone assumed=%d \n", b->n_ciphone);
00197 E_INFO_NOFN("\n");
00198 }
00199
00200 static void
00201 beam_free(beam_t * b)
00202 {
00203 if (b) {
00204 if (b->wordbestscores) {
00205 free(b->wordbestscores);
00206 }
00207 if (b->wordbestexits) {
00208 free(b->wordbestexits);
00209 }
00210 free(b);
00211 }
00212 }
00213
00214
00215 static lextree_t **
00216 create_lextree(tst_search_t *tstg, const char *lmname, ptmr_t *tm_build)
00217 {
00218 int j;
00219 lextree_t **lextree;
00220
00221 lextree = (lextree_t **)ckd_calloc(tstg->n_lextree, sizeof(lextree_t *));
00222 hash_table_enter(tstg->ugtree, lmname, lextree);
00223 for (j = 0; j < tstg->n_lextree; ++j) {
00224 if (tm_build)
00225 ptmr_start(tm_build);
00226
00227 lextree[j] = lextree_init(ps_search_acmod(tstg)->mdef,
00228 ps_search_acmod(tstg)->tmat,
00229 ps_search_dict(tstg),
00230 ps_search_dict2pid(tstg),
00231 tstg->fillpen,
00232 tstg->lmset,
00233 lmname,
00234 TRUE, TRUE,
00235 LEXTREE_TYPE_UNIGRAM);
00236
00237 if (tm_build)
00238 ptmr_stop(tm_build);
00239
00240 if (lextree[j] == NULL) {
00241 int i;
00242 E_INFO
00243 ("Failed to allocate lexical tree for lm %s and lextree %d\n",
00244 lmname, j);
00245
00246 for (i = j - 1; i >= 0; --i)
00247 lextree_free(lextree[i]);
00248 ckd_free(lextree);
00249
00250 return NULL;
00251 }
00252 E_INFO("Lextree (%d) for lm \"%s\" has %d nodes(ug)\n",
00253 j, lmname, lextree_n_node(lextree[j]));
00254 }
00255
00256 lextree_report(lextree[0]);
00257
00258 return lextree;
00259 }
00260
00261 static int
00262 tst_search_reinit(ps_search_t *search)
00263 {
00264
00265 return -1;
00266 }
00267
00268 ps_search_t *
00269 tst_search_init(cmd_ln_t *config,
00270 acmod_t *acmod,
00271 s3dict_t *dict,
00272 dict2pid_t *d2p)
00273 {
00274 tst_search_t *tstg;
00275 char const *path;
00276 int32 n_ltree;
00277 int32 i, j;
00278 ptmr_t tm_build;
00279 ngram_model_set_iter_t *lmset_iter;
00280 lextree_t **lextree = NULL;
00281
00282 tstg = ckd_calloc(1, sizeof(*tstg));
00283 ps_search_init(&tstg->base, &tst_funcs, config, acmod, dict, d2p);
00284
00285 tstg->fillpen = fillpen_init(ps_search_dict(tstg), NULL,
00286 cmd_ln_float32_r(config, "-silprob"),
00287 cmd_ln_float32_r(config, "-fillprob"),
00288 cmd_ln_float32_r(config, "-lw"),
00289 cmd_ln_float32_r(config, "-wip"),
00290 acmod->lmath);
00291 tstg->beam = beam_init(cmd_ln_float64_r(config, "-beam"),
00292 cmd_ln_float64_r(config, "-pbeam"),
00293 cmd_ln_float64_r(config, "-wbeam"),
00294 cmd_ln_float64_r(config, "-wend_beam"),
00295 0, bin_mdef_n_ciphone(acmod->mdef),
00296 acmod->lmath);
00297 beam_report(tstg->beam);
00298
00299 tstg->ssid_active = bitvec_alloc(bin_mdef_n_sseq(acmod->mdef));
00300 tstg->comssid_active = bitvec_alloc(dict2pid_n_comsseq(ps_search_dict2pid(tstg)));
00301 tstg->composite_senone_scores = ckd_calloc(dict2pid_n_comstate(ps_search_dict2pid(tstg)),
00302 sizeof(*tstg->composite_senone_scores));
00303
00304 ptmr_init(&(tm_build));
00305
00306 tstg->epl = cmd_ln_int32_r(config, "-epl");
00307 tstg->n_lextree = cmd_ln_int32_r(config, "-Nlextree");
00308 n_ltree = tstg->n_lextree;
00309
00310
00311
00312 if ((path = cmd_ln_str_r(config, "-lmctl"))) {
00313 tstg->lmset = ngram_model_set_read(config, path, acmod->lmath);
00314 if (tstg->lmset == NULL) {
00315 E_ERROR("Failed to read language model control file: %s\n",
00316 path);
00317 goto error_out;
00318 }
00319
00320 if ((path = cmd_ln_str_r(config, "-lmname"))) {
00321 ngram_model_set_select(tstg->lmset, path);
00322 }
00323 }
00324 else if ((path = cmd_ln_str_r(config, "-lm"))) {
00325 static const char *name = "default";
00326 ngram_model_t *lm;
00327
00328 lm = ngram_model_read(config, path, NGRAM_AUTO, acmod->lmath);
00329 if (lm == NULL) {
00330 E_ERROR("Failed to read language model file: %s\n", path);
00331 goto error_out;
00332 }
00333 tstg->lmset = ngram_model_set_init(config,
00334 &lm, (char **)&name,
00335 NULL, 1);
00336 if (tstg->lmset == NULL) {
00337 E_ERROR("Failed to initialize language model set\n");
00338 goto error_out;
00339 }
00340 }
00341
00342
00343
00344 tstg->ugtree =
00345 hash_table_new(ngram_model_set_count(tstg->lmset), HASH_CASE_YES);
00346
00347
00348
00349
00350 tstg->curugtree =
00351 (lextree_t **) ckd_calloc(n_ltree, sizeof(lextree_t *));
00352
00353
00354
00355 ptmr_reset(&(tm_build));
00356
00357
00358
00359
00360 if ((lextree = create_lextree(tstg, "lmset", &tm_build)) == NULL) {
00361 goto error_out;
00362 }
00363 for (j = 0; j < n_ltree; ++j)
00364 tstg->curugtree[j] = lextree[j];
00365
00366 E_INFO("Time for building trees, %4.4f CPU %4.4f Clk\n",
00367 tm_build.t_cpu, tm_build.t_elapsed);
00368
00369
00370
00371 tstg->fillertree =
00372 (lextree_t **) ckd_calloc(n_ltree, sizeof(lextree_t *));
00373
00374 for (i = 0; i < n_ltree; i++) {
00375 if ((tstg->fillertree[i] = fillertree_init(acmod->mdef, acmod->tmat,
00376 ps_search_dict(tstg), ps_search_dict2pid(tstg),
00377 tstg->fillpen)) == NULL) {
00378 E_INFO("Fail to allocate filler tree %d\n", i);
00379 goto error_out;
00380 }
00381 E_INFO("Lextrees(%d), %d nodes(filler)\n",
00382 i, lextree_n_node(tstg->fillertree[0]));
00383 }
00384
00385 if (cmd_ln_int32_r(config, "-lextreedump")) {
00386 for (lmset_iter = ngram_model_set_iter(tstg->lmset);
00387 lmset_iter; lmset_iter = ngram_model_set_iter_next(lmset_iter)) {
00388 const char *model_name;
00389 ngram_model_set_iter_model(lmset_iter, &model_name);
00390 hash_table_lookup(tstg->ugtree, model_name, (void*)&lextree);
00391 for (j = 0; j < n_ltree; j++) {
00392 E_INFO("LM name: \'%s\' UGTREE: %d\n",
00393 model_name, j);
00394 lextree_dump(lextree[j], stderr,
00395 cmd_ln_int32_r(config, "-lextreedump"));
00396 }
00397 }
00398 ngram_model_set_iter_free(lmset_iter);
00399 for (i = 0; i < n_ltree; i++) {
00400 E_INFO("FILLERTREE %d\n", i);
00401 lextree_dump(tstg->fillertree[i], stderr,
00402 cmd_ln_int32_r(config, "-lextreedump"));
00403 }
00404 }
00405
00406 tstg->histprune = histprune_init(cmd_ln_int32_r(config, "-maxhmmpf"),
00407 cmd_ln_int32_r(config, "-maxhistpf"),
00408 cmd_ln_int32_r(config, "-maxwpf"),
00409 cmd_ln_int32_r(config, "-hmmhistbinsize"),
00410 (tstg->curugtree[0]->n_node + tstg->fillertree[0]->n_node) *
00411 tstg->n_lextree);
00412 histprune_report(tstg->histprune);
00413
00414
00415 tstg->vithist = vithist_init(ngram_model_get_counts(tstg->lmset)[0],
00416 bin_mdef_n_ciphone(acmod->mdef),
00417 logmath_log(acmod->lmath, cmd_ln_float64_r(config, "-vhbeam")),
00418 cmd_ln_int32_r(config, "-bghist"), TRUE);
00419
00420
00421 return (ps_search_t *)tstg;
00422
00423 error_out:
00424 tst_search_free(ps_search_base(tstg));
00425 return NULL;
00426 }
00427
00428 void
00429 tst_search_free(ps_search_t *search)
00430 {
00431 tst_search_t *tstg = (tst_search_t *)search;
00432
00433 if (tstg == NULL)
00434 return;
00435
00436 if (tstg->ugtree) {
00437 hash_iter_t *hiter = hash_table_iter(tstg->ugtree);
00438 if (hiter)
00439 do {
00440 lextree_t **lextree = (lextree_t**)hash_entry_val(hiter->ent);
00441 if (lextree) {
00442 int j;
00443 for (j = 0; j < tstg->n_lextree; ++j)
00444 lextree_free(lextree[j]);
00445 }
00446 } while ((hiter = hash_table_iter_next(hiter)));
00447 hash_table_free(tstg->ugtree);
00448 }
00449
00450 ckd_free(tstg->curugtree);
00451 if (tstg->fillertree) {
00452 int32 j;
00453 for (j = 0; j < tstg->n_lextree; ++j)
00454 lextree_free(tstg->fillertree[j]);
00455 ckd_free(tstg->fillertree);
00456 }
00457
00458 if (tstg->vithist)
00459 vithist_free(tstg->vithist);
00460 if (tstg->histprune)
00461 histprune_free(tstg->histprune);
00462 if (tstg->fillpen)
00463 fillpen_free(tstg->fillpen);
00464 if (tstg->beam)
00465 beam_free(tstg->beam);
00466 bitvec_free(tstg->ssid_active);
00467 bitvec_free(tstg->comssid_active);
00468 ckd_free(tstg->composite_senone_scores);
00469 ps_search_deinit(search);
00470 ckd_free(tstg);
00471 }
00472
00473 static int
00474 tst_search_start(ps_search_t *search)
00475 {
00476 tst_search_t *tstg = (tst_search_t *)search;
00477 int32 n, pred;
00478 int32 i;
00479
00480
00481 vithist_utt_reset(tstg->vithist);
00482 histprune_zero_histbin(tstg->histprune);
00483
00484
00485 memset(&tstg->st, 0, sizeof(tstg->st));
00486 tstg->n_frame = 0;
00487
00488
00489 pred = vithist_utt_begin(tstg->vithist,
00490 s3dict_startwid(ps_search_dict(tstg)),
00491 ngram_wid(tstg->lmset, "<s>"));
00492 assert(pred == 0);
00493
00494
00495
00496
00497 n = lextree_n_next_active(tstg->curugtree[0]);
00498 assert(n == 0);
00499 lextree_enter(tstg->curugtree[0],
00500 bin_mdef_silphone(ps_search_acmod(tstg)->mdef),
00501 -1, 0, pred, tstg->beam->hmm);
00502
00503
00504 n = lextree_n_next_active(tstg->fillertree[0]);
00505 assert(n == 0);
00506 lextree_enter(tstg->fillertree[0], BAD_S3CIPID, -1, 0, pred, tstg->beam->hmm);
00507
00508 tstg->n_lextrans = 1;
00509
00510 tstg->exit_id = -1;
00511
00512 for (i = 0; i < tstg->n_lextree; i++) {
00513 lextree_active_swap(tstg->curugtree[i]);
00514 lextree_active_swap(tstg->fillertree[i]);
00515 }
00516
00517 return 0;
00518 }
00519
00520 static int
00521 tst_search_finish(ps_search_t *search)
00522 {
00523 tst_search_t *tstg = (tst_search_t *)search;
00524 int32 i, cf;
00525
00526
00527 cf = ps_search_acmod(search)->output_frame;
00528
00529
00530
00531 tstg->exit_id = vithist_utt_end(tstg->vithist,
00532 tstg->lmset, ps_search_dict(tstg),
00533 ps_search_dict2pid(tstg), tstg->fillpen);
00534
00535
00536 histprune_showhistbin(tstg->histprune, cf, "histbin");
00537
00538 for (i = 0; i < tstg->n_lextree; i++) {
00539 lextree_utt_end(tstg->curugtree[i]);
00540 lextree_utt_end(tstg->fillertree[i]);
00541 }
00542
00543
00544 if (cf > 0) {
00545 E_INFO("%8d words recognized (%d/fr)\n",
00546 vithist_n_entry(tstg->vithist),
00547 (vithist_n_entry(tstg->vithist) + (cf >> 1)) / (cf + 1));
00548 E_INFO("%8d senones evaluated (%d/fr)\n", tstg->st.n_senone_active_utt,
00549 (tstg->st.n_senone_active_utt + (cf >> 1)) / (cf + 1));
00550 E_INFO("%8d channels searched (%d/fr)\n",
00551 tstg->st.n_hmm_eval, tstg->st.n_hmm_eval / (cf + 1));
00552 }
00553
00554 if (tstg->exit_id >= 0)
00555 return 0;
00556 else
00557 return -1;
00558 }
00559
00560 static int
00561 srch_TST_hmm_compute_lv2(tst_search_t *tstg, int32 frmno)
00562 {
00563
00564
00565 int32 i, j;
00566 lextree_t *lextree;
00567 beam_t *bm;
00568 histprune_t *hp;
00569
00570 int32 besthmmscr, bestwordscr;
00571 int32 frm_nhmm, hb, pb, wb;
00572 int32 n_ltree;
00573 int32 maxwpf;
00574 int32 maxhistpf;
00575 int32 maxhmmpf;
00576 int32 histbinsize;
00577 int32 numhistbins;
00578 int32 hmmbeam;
00579 int32 pbeam;
00580 int32 wbeam;
00581 int32 *hmm_hist;
00582
00583 n_ltree = tstg->n_lextree;
00584 hp = tstg->histprune;
00585 bm = tstg->beam;
00586 hmm_hist = hp->hmm_hist;
00587
00588 maxwpf = hp->maxwpf;
00589 maxhistpf = hp->maxhistpf;
00590 maxhmmpf = hp->maxhmmpf;
00591 histbinsize = hp->hmm_hist_binsize;
00592 numhistbins = hp->hmm_hist_bins;
00593
00594 hmmbeam = bm->hmm;
00595 pbeam = bm->ptrans;
00596 wbeam = bm->word;
00597
00598
00599 besthmmscr = MAX_NEG_INT32;
00600 bestwordscr = MAX_NEG_INT32;
00601 frm_nhmm = 0;
00602
00603 for (i = 0; i < (n_ltree << 1); i++) {
00604 lextree =
00605 (i < n_ltree) ? tstg->curugtree[i] : tstg->fillertree[i - n_ltree];
00606 if (tstg->hmmdumpfp != NULL)
00607 fprintf(tstg->hmmdumpfp, "Fr %d Lextree %d #HMM %d\n", frmno, i,
00608 lextree->n_active);
00609 lextree_hmm_eval(lextree,
00610 ps_search_acmod(tstg)->senone_scores,
00611 tstg->composite_senone_scores,
00612 frmno, tstg->hmmdumpfp);
00613
00614 if (besthmmscr < lextree->best)
00615 besthmmscr = lextree->best;
00616 if (bestwordscr < lextree->wbest)
00617 bestwordscr = lextree->wbest;
00618
00619 tstg->st.n_hmm_eval += lextree->n_active;
00620 frm_nhmm += lextree->n_active;
00621 }
00622 if (besthmmscr > 0) {
00623 E_ERROR
00624 ("***ERROR*** Fr %d, best HMM score > 0 (%d); int32 wraparound?\n",
00625 frmno, besthmmscr);
00626 }
00627
00628
00629
00630
00631
00632
00633
00634 if (frm_nhmm / histbinsize > hp->hmm_hist_bins - 1)
00635 hmm_hist[hp->hmm_hist_bins - 1]++;
00636 else
00637 hmm_hist[frm_nhmm / histbinsize]++;
00638
00639
00640
00641
00642
00643 if (maxhmmpf != -1 && frm_nhmm > (maxhmmpf + (maxhmmpf >> 1))) {
00644 int32 *bin, nbin, bw;
00645
00646
00647 nbin = 1000;
00648 bw = -(hmmbeam) / nbin;
00649 bin = (int32 *) ckd_calloc(nbin, sizeof(int32));
00650
00651 for (i = 0; i < (n_ltree << 1); i++) {
00652 lextree = (i < n_ltree) ?
00653 tstg->curugtree[i] : tstg->fillertree[i - n_ltree];
00654
00655 lextree_hmm_histbin(lextree, besthmmscr, bin, nbin, bw);
00656 }
00657
00658 for (i = 0, j = 0; (i < nbin) && (j < maxhmmpf); i++, j += bin[i]);
00659 ckd_free((void *) bin);
00660
00661
00662 hb = -(i * bw);
00663 pb = (hb > pbeam) ? hb : pbeam;
00664 wb = (hb > wbeam) ? hb : wbeam;
00665 }
00666 else {
00667 hb = hmmbeam;
00668 pb = pbeam;
00669 wb = wbeam;
00670 }
00671
00672 bm->bestscore = besthmmscr;
00673 bm->bestwordscore = bestwordscr;
00674
00675 bm->thres = bm->bestscore + hb;
00676 bm->phone_thres = bm->bestscore + pb;
00677 bm->word_thres = bm->bestwordscore + wb;
00678
00679 return 0;
00680 }
00681
00682 static int
00683 srch_TST_propagate_graph_ph_lv2(tst_search_t *tstg, int32 frmno)
00684 {
00685 int32 i;
00686 int32 n_ltree;
00687
00688 lextree_t *lextree;
00689
00690 n_ltree = tstg->n_lextree;
00691
00692 for (i = 0; i < (n_ltree << 1); i++) {
00693 lextree = (i < n_ltree)
00694 ? tstg->curugtree[i]
00695 : tstg->fillertree[i - tstg-> n_lextree];
00696
00697 if (lextree_hmm_propagate_non_leaves(lextree, frmno,
00698 tstg->beam->thres,
00699 tstg->beam->phone_thres,
00700 tstg->beam->word_thres)
00701 != LEXTREE_OPERATION_SUCCESS) {
00702 E_ERROR
00703 ("Propagation Failed for lextree_hmm_propagate_non_leave at tree %d\n",
00704 i);
00705 lextree_utt_end(lextree);
00706 return -1;
00707 }
00708 }
00709
00710 return 0;
00711 }
00712
00713 static void
00714 mdef_sseq2sen_active(bin_mdef_t * mdef, bitvec_t * sseq, bitvec_t * sen)
00715 {
00716 int32 ss, i;
00717 s3senid_t *sp;
00718
00719 for (ss = 0; ss < bin_mdef_n_sseq(mdef); ss++) {
00720 if (bitvec_is_set(sseq,ss)) {
00721 sp = mdef->sseq[ss];
00722 for (i = 0; i < mdef_n_emit_state(mdef); i++)
00723 bitvec_set(sen, sp[i]);
00724 }
00725 }
00726 }
00727
00728 static int
00729 srch_TST_select_active_gmm(tst_search_t *tstg)
00730 {
00731 int32 n_ltree;
00732 dict2pid_t *d2p;
00733 bin_mdef_t *mdef;
00734 lextree_t *lextree;
00735 int32 i;
00736
00737 n_ltree = tstg->n_lextree;
00738 mdef = ps_search_acmod(tstg)->mdef;
00739 d2p = ps_search_dict2pid(tstg);
00740
00741 bitvec_clear_all(tstg->ssid_active, bin_mdef_n_sseq(mdef));
00742 bitvec_clear_all(tstg->comssid_active, dict2pid_n_comsseq(d2p));
00743
00744
00745 for (i = 0; i < (n_ltree << 1); i++) {
00746 lextree = (i < n_ltree) ? tstg->curugtree[i] :
00747 tstg->fillertree[i - n_ltree];
00748 lextree_ssid_active(lextree, tstg->ssid_active,
00749 tstg->comssid_active);
00750 }
00751
00752
00753 acmod_clear_active(ps_search_acmod(tstg));
00754 mdef_sseq2sen_active(mdef, tstg->ssid_active,
00755 ps_search_acmod(tstg)->senone_active_vec);
00756
00757
00758 dict2pid_comsseq2sen_active(d2p, mdef, tstg->comssid_active,
00759 ps_search_acmod(tstg)->senone_active_vec);
00760
00761 return 0;
00762 }
00763
00764 static int
00765 srch_TST_rescoring(tst_search_t *tstg, int32 frmno)
00766 {
00767 int32 i;
00768 int32 n_ltree;
00769 lextree_t *lextree;
00770 vithist_t *vh;
00771
00772 vh = tstg->vithist;
00773
00774 n_ltree = tstg->n_lextree;
00775
00776 for (i = 0; i < (n_ltree * 2); i++) {
00777 lextree = (i < n_ltree)
00778 ? tstg->curugtree[i]
00779 : tstg->fillertree[i - tstg->n_lextree];
00780
00781 E_DEBUG(1,("Propagating words from lextree %d\n", i));
00782 if (lextree_hmm_propagate_leaves
00783 (lextree, vh, frmno,
00784 tstg->beam->word_thres) != LEXTREE_OPERATION_SUCCESS) {
00785 E_ERROR
00786 ("Propagation Failed for lextree_hmm_propagate_leave at tree %d\n",
00787 i);
00788 lextree_utt_end(lextree);
00789 return -1;
00790 }
00791 }
00792
00793 return 0;
00794 }
00795
00796 static void
00797 srch_utt_word_trans(tst_search_t * tstg, int32 cf)
00798 {
00799 int32 k, th;
00800 vithist_t *vh;
00801 vithist_entry_t *ve;
00802 int32 vhid, le, n_ci, score;
00803 int32 maxpscore;
00804 int32 *bs = NULL, *bv = NULL, epl;
00805 beam_t *bm;
00806 s3wid_t wid;
00807 int32 p;
00808 s3dict_t *dict;
00809 bin_mdef_t *mdef;
00810
00811
00812 maxpscore = MAX_NEG_INT32;
00813 bm = tstg->beam;
00814 vh = tstg->vithist;
00815 th = bm->bestscore + bm->hmm;
00816
00817 if (vh->bestvh[cf] < 0)
00818 return;
00819
00820 dict = ps_search_dict(tstg);
00821 mdef = ps_search_acmod(tstg)->mdef;
00822 n_ci = bin_mdef_n_ciphone(mdef);
00823
00824
00825
00826 bs = bm->wordbestscores;
00827 bv = bm->wordbestexits;
00828 epl = tstg->epl;
00829
00830 for (p = 0; p < n_ci; p++) {
00831 bs[p] = MAX_NEG_INT32;
00832 bv[p] = -1;
00833 }
00834
00835
00836 vhid = vithist_first_entry(vh, cf);
00837 le = vithist_n_entry(vh) - 1;
00838 for (; vhid <= le; vhid++) {
00839 ve = vithist_id2entry(vh, vhid);
00840 if (!vithist_entry_valid(ve))
00841 continue;
00842
00843 wid = vithist_entry_wid(ve);
00844 p = s3dict_last_phone(dict, wid);
00845 if (bin_mdef_is_fillerphone(mdef, p))
00846 p = bin_mdef_silphone(mdef);
00847
00848 score = vithist_entry_score(ve);
00849 if (score > bs[p]) {
00850 bs[p] = score;
00851 bv[p] = vhid;
00852 if (maxpscore < score) {
00853 maxpscore = score;
00854
00855 }
00856 }
00857 }
00858
00859
00860 k = tstg->n_lextrans++;
00861 k = (k % (tstg->n_lextree * epl)) / epl;
00862
00863
00864 for (p = 0; p < n_ci; p++) {
00865 if (bv[p] >= 0) {
00866 if (tstg->beam->wordend == 0
00867 || bs[p] > tstg->beam->wordend + maxpscore) {
00868
00869 lextree_enter(tstg->curugtree[k], (s3cipid_t) p, cf, bs[p],
00870 bv[p], th);
00871 }
00872 }
00873
00874 }
00875
00876
00877 lextree_enter(tstg->fillertree[k], BAD_S3CIPID, cf, vh->bestscore[cf],
00878 vh->bestvh[cf], th);
00879 }
00880
00881 static int
00882 srch_TST_propagate_graph_wd_lv2(tst_search_t *tstg, int32 frmno)
00883 {
00884 s3dict_t *dict;
00885 vithist_t *vh;
00886 histprune_t *hp;
00887 int32 maxwpf;
00888 int32 maxhistpf;
00889 int32 maxhmmpf;
00890
00891
00892 hp = tstg->histprune;
00893 vh = tstg->vithist;
00894 dict = ps_search_dict(tstg);
00895
00896 maxwpf = hp->maxwpf;
00897 maxhistpf = hp->maxhistpf;
00898 maxhmmpf = hp->maxhmmpf;
00899
00900 srch_TST_rescoring(tstg, frmno);
00901
00902 vithist_prune(vh, dict, frmno, maxwpf, maxhistpf,
00903 tstg->beam->word_thres - tstg->beam->bestwordscore);
00904
00905 srch_utt_word_trans(tstg, frmno);
00906
00907 return 0;
00908 }
00909
00910
00911 static int
00912 srch_TST_frame_windup(tst_search_t *tstg, int32 frmno)
00913 {
00914 vithist_t *vh;
00915 int32 i;
00916
00917 vh = tstg->vithist;
00918
00919
00920 vithist_frame_windup(vh, frmno, NULL, tstg->lmset, ps_search_dict(tstg));
00921
00922 for (i = 0; i < tstg->n_lextree; i++) {
00923 lextree_active_swap(tstg->curugtree[i]);
00924 lextree_active_swap(tstg->fillertree[i]);
00925 }
00926 return 0;
00927 }
00928
00929 static int
00930 tst_search_step(ps_search_t *search, int frame_idx)
00931 {
00932 tst_search_t *tstg = (tst_search_t *)search;
00933 int16 const *senscr;
00934
00935
00936 srch_TST_select_active_gmm(tstg);
00937
00938
00939 if ((senscr = acmod_score(ps_search_acmod(search), &frame_idx)) == NULL)
00940 return 0;
00941 tstg->st.n_senone_active_utt += ps_search_acmod(search)->n_senone_active;
00942
00943
00944 memset(tstg->composite_senone_scores, 0,
00945 dict2pid_n_comstate(ps_search_dict2pid(tstg)) * sizeof(*tstg->composite_senone_scores));
00946 dict2pid_comsenscr(ps_search_dict2pid(tstg), senscr, tstg->composite_senone_scores);
00947
00948
00949 srch_TST_hmm_compute_lv2(tstg, frame_idx);
00950 srch_TST_propagate_graph_ph_lv2(tstg, frame_idx);
00951 srch_TST_propagate_graph_wd_lv2(tstg, frame_idx);
00952 srch_TST_frame_windup(tstg, frame_idx);
00953
00954
00955 ++tstg->n_frame;
00956
00957
00958 return 1;
00959 }
00960
00961 static ps_lattice_t *
00962 tst_search_lattice(ps_search_t *search)
00963 {
00964 tst_search_t *tstg = (tst_search_t *)search;
00965 vithist_t *vh;
00966 glist_t *sfwid;
00967 gnode_t *gn, *gn2, *gn3;
00968 int32 min_ef_range;
00969 int32 sf, ef, n_node;
00970 int32 f, i;
00971 ps_lattice_t *dag;
00972 ps_latnode_t *dn;
00973 int32 exit_id, id;
00974
00975 vh = tstg->vithist;
00976 if (tstg->exit_id == -1)
00977 exit_id = vithist_partialutt_end(vh, tstg->lmset, ps_search_dict(tstg));
00978 else
00979 exit_id = tstg->exit_id;
00980
00981 if (exit_id < 0) {
00982 E_WARN("Failed to retrieve viterbi history.\n");
00983 return NULL;
00984 }
00985
00986
00987
00988 if (search->dag && search->dag->n_frames == tstg->n_frame)
00989 return search->dag;
00990
00991
00992 ps_lattice_free(search->dag);
00993 search->dag = NULL;
00994 dag = ps_lattice_init_search(search, tstg->n_frame);
00995
00996
00997 sfwid = (glist_t *) ckd_calloc(vh->n_frm + 1, sizeof(glist_t));
00998
00999
01000 min_ef_range = cmd_ln_int32_r(ps_search_config(search), "-min_endfr");
01001
01002 n_node = 0;
01003 sf = 0;
01004 for (i = 0; i < vh->n_entry; i++) {
01005 ps_latnode_t *dn;
01006 vithist_entry_t *ve, *ve2;
01007
01008 ve = vithist_id2entry(vh, i);
01009 if (!ve->valid)
01010 continue;
01011
01012
01013
01014
01015
01016
01017 if (ve->sf == -1) {
01018 assert(ve->ef == -1);
01019 sf = ef = 0;
01020 }
01021 else if (ve->sf == 0) {
01022 assert(ve->ef > 0);
01023 sf = ve->sf + 1;
01024 ef = ve->ef;
01025 }
01026 else {
01027 sf = ve->sf;
01028 ef = ve->ef;
01029 }
01030
01031
01032 for (gn = sfwid[sf]; gn; gn = gnode_next(gn)) {
01033 dn = (ps_latnode_t *) gnode_ptr(gn);
01034 if (dn->wid == ve->wid)
01035 break;
01036 }
01037
01038 if (!gn) {
01039 dn = listelem_malloc(dag->latnode_alloc);
01040 memset(dn, 0, sizeof(*dn));
01041 dn->wid = ve->wid;
01042
01043 dn->sf = sf;
01044 dn->fef = ef;
01045 dn->lef = ef;
01046 dn->id = -1;
01047 ++n_node;
01048
01049 sfwid[sf] = glist_add_ptr(sfwid[sf], (void *) dn);
01050 }
01051 else {
01052 dn->lef = ef;
01053 }
01054
01055 if (i == exit_id)
01056 dag->end = dn;
01057
01058
01059
01060
01061
01062 for (gn = dn->info.velist; gn; gn = gnode_next(gn)) {
01063 ve2 = (vithist_entry_t *) gnode_ptr(gn);
01064 if (ve2->ef == ve->ef)
01065 break;
01066 }
01067 if (gn) {
01068 if (ve->path.score > ve2->path.score)
01069 gnode_ptr(gn) = (void *) ve;
01070 }
01071 else
01072 dn->info.velist = glist_add_ptr(dn->info.velist, (void *) ve);
01073 }
01074
01075
01076
01077
01078
01079 id = exit_id;
01080 while (id >= 0) {
01081 vithist_entry_t *ve = vithist_id2entry(vh, id);
01082
01083
01084
01085
01086 int hacked_sf = vithist_entry_sf(ve);
01087 if (hacked_sf <= 0) ++hacked_sf;
01088 assert(hacked_sf >= 0);
01089 for (gn2 = sfwid[hacked_sf]; gn2; gn2 = gnode_next(gn2)) {
01090 ps_latnode_t *dn = (ps_latnode_t *) gnode_ptr(gn2);
01091 if (vithist_entry_wid(ve) == dn->wid)
01092 dn->id = 0;
01093 }
01094 id = vithist_entry_pred(ve);
01095 }
01096
01097
01098 dn = (ps_latnode_t *) gnode_ptr(sfwid[0]);
01099 assert(dn->wid == s3dict_startwid(ps_search_dict(tstg)));
01100 dn->id = 0;
01101 dag->start = dn;
01102
01103 dn = (ps_latnode_t *) gnode_ptr(sfwid[vh->n_frm]);
01104 assert(dn->wid == s3dict_finishwid(ps_search_dict(tstg)));
01105 dn->id = 0;
01106
01107
01108 if (dag->end == NULL) {
01109 E_WARN("Final vithist entry %d not found, using </s> node\n", exit_id);
01110 dag->end = dn;
01111 }
01112 dag->end->id = 0;
01113
01114 for (gn = (glist_t)dag->end->info.velist; gn; gn = gnode_next(gn)) {
01115 vithist_entry_t *ve2 = (vithist_entry_t *) gnode_ptr(gn);
01116 if (ve2->ef == vh->n_frm)
01117 dag->final_node_ascr = ve2->ascr;
01118 }
01119
01120
01121 i = 0;
01122 for (f = 0; f <= vh->n_frm; ++f) {
01123 for (gn = sfwid[f]; gn; gn = gnode_next(gn)) {
01124 ps_latnode_t *dn = (ps_latnode_t *) gnode_ptr(gn);
01125 if ((dn->lef - dn->fef > min_ef_range) || (dn->id >= 0)) {
01126 dn->id = i++;
01127 dn->next = dag->nodes;
01128 dag->nodes = dn;
01129 }
01130 else
01131 dn->id = -1;
01132 }
01133 }
01134
01135 for (f = 0; f < vh->n_frm; ++f) {
01136 for (gn = sfwid[f]; gn; gn = gnode_next(gn)) {
01137 ps_latnode_t *dn = (ps_latnode_t *) gnode_ptr(gn);
01138
01139 if (dn->id < 0)
01140 continue;
01141
01142 for (gn2 = (glist_t) dn->info.velist; gn2; gn2 = gnode_next(gn2)) {
01143 vithist_entry_t *ve = (vithist_entry_t *) gnode_ptr(gn2);
01144 sf = (ve->ef < 0) ? 1 : (ve->ef + 1);
01145 for (gn3 = sfwid[sf]; gn3; gn3 = gnode_next(gn3)) {
01146 ps_latnode_t *dn2 = (ps_latnode_t *) gnode_ptr(gn3);
01147 if (dn2->id >= 0)
01148 ps_lattice_link(dag, dn, dn2, ve->ascr, sf - 1);
01149 }
01150 }
01151 }
01152 }
01153
01154
01155 for (f = 0; f <= vh->n_frm; f++) {
01156 for (gn = sfwid[f]; gn; gn = gnode_next(gn)) {
01157 ps_latnode_t *dn = (ps_latnode_t *) gnode_ptr(gn);
01158 glist_free((glist_t) dn->info.velist);
01159 dn->info.velist = NULL;
01160 if (dn->id == -1)
01161 listelem_free(dag->latnode_alloc, dn);
01162 }
01163 glist_free(sfwid[f]);
01164 }
01165 ckd_free((void *)sfwid);
01166
01167 dag->n_frames = vh->n_frm;
01168
01169
01170
01171
01172
01173 ps_lattice_bypass_fillers
01174 (dag, logmath_log(ps_search_acmod(search)->lmath, tstg->fillpen->silprob),
01175 logmath_log(ps_search_acmod(search)->lmath, tstg->fillpen->fillerprob));
01176
01177 search->dag = dag;
01178
01179 return dag;
01180 }
01181
01182 static char const *
01183 tst_search_hyp(ps_search_t *base, int32 *out_score)
01184 {
01185 tst_search_t *tstg = (tst_search_t *)base;
01186 vithist_entry_t *ve;
01187 char *c;
01188 size_t len;
01189 int32 exit_id, id;
01190
01191 if (tstg->exit_id == -1)
01192 exit_id = vithist_partialutt_end(tstg->vithist, tstg->lmset, ps_search_dict(tstg));
01193 else
01194 exit_id = tstg->exit_id;
01195
01196 if (exit_id < 0) {
01197 E_WARN("Failed to retrieve viterbi history.\n");
01198 return NULL;
01199 }
01200
01201 ve = vithist_id2entry(tstg->vithist, exit_id);
01202 *out_score = ve->ascr + ve->lscr;
01203
01204 id = exit_id;
01205 len = 0;
01206 while (id >= 0) {
01207 s3wid_t wid;
01208 ve = vithist_id2entry(tstg->vithist, id);
01209 assert(ve);
01210 wid = vithist_entry_wid(ve);
01211 id = ve->path.pred;
01212 if (s3dict_filler_word(ps_search_dict(tstg), wid)
01213 || wid == s3dict_startwid(ps_search_dict(tstg))
01214 || wid == s3dict_finishwid(ps_search_dict(tstg)))
01215 continue;
01216 len += strlen(s3dict_wordstr(ps_search_dict(tstg), s3dict_basewid(ps_search_dict(tstg), wid))) + 1;
01217 }
01218
01219 ckd_free(base->hyp_str);
01220 base->hyp_str = ckd_calloc(1, len);
01221 id = exit_id;
01222 c = base->hyp_str + len - 1;
01223 while (id >= 0) {
01224 s3wid_t wid;
01225 ve = vithist_id2entry(tstg->vithist, id);
01226 assert(ve);
01227 wid = vithist_entry_wid(ve);
01228 id = ve->path.pred;
01229 if (s3dict_filler_word(ps_search_dict(tstg), wid)
01230 || wid == s3dict_startwid(ps_search_dict(tstg))
01231 || wid == s3dict_finishwid(ps_search_dict(tstg)))
01232 continue;
01233 len = strlen(s3dict_wordstr(ps_search_dict(tstg), s3dict_basewid(ps_search_dict(tstg), wid)));
01234 c -= len;
01235 memcpy(c, s3dict_wordstr(ps_search_dict(tstg), s3dict_basewid(ps_search_dict(tstg), wid)), len);
01236 if (c > base->hyp_str) {
01237 --c;
01238 *c = ' ';
01239 }
01240 }
01241
01242 return base->hyp_str;
01243 }
01244
01245 static int32
01246 tst_search_prob(ps_search_t *search)
01247 {
01248
01249 return 1;
01250 }
01251
01255 typedef struct tst_seg_s {
01256 ps_seg_t base;
01257 int32 *bpidx;
01258 int16 n_bpidx;
01259 int16 cur;
01260 } tst_seg_t;
01261
01262 static void
01263 tst_search_bp2itor(ps_seg_t *seg, int id)
01264 {
01265 tst_search_t *tstg = (tst_search_t *)seg->search;
01266 vithist_entry_t *ve;
01267
01268 ve = vithist_id2entry(tstg->vithist, id);
01269 assert(ve);
01270 seg->word = s3dict_wordstr(ps_search_dict(tstg), vithist_entry_wid(ve));
01271 seg->ef = vithist_entry_ef(ve);
01272 seg->sf = vithist_entry_sf(ve);
01273 seg->prob = 0;
01274 seg->ascr = vithist_entry_ascr(ve);
01275 seg->lscr = vithist_entry_lscr(ve);
01276 seg->lback = 0;
01277 }
01278
01279 static void
01280 tst_seg_free(ps_seg_t *seg)
01281 {
01282 tst_seg_t *itor = (tst_seg_t *)seg;
01283
01284 ckd_free(itor->bpidx);
01285 ckd_free(itor);
01286 }
01287
01288 static ps_seg_t *
01289 tst_seg_next(ps_seg_t *seg)
01290 {
01291 tst_seg_t *itor = (tst_seg_t *)seg;
01292
01293 if (++itor->cur == itor->n_bpidx) {
01294 tst_seg_free(seg);
01295 return NULL;
01296 }
01297
01298 tst_search_bp2itor(seg, itor->bpidx[itor->cur]);
01299 return seg;
01300 }
01301
01302 static ps_segfuncs_t tst_segfuncs = {
01303 tst_seg_next,
01304 tst_seg_free
01305 };
01306
01307 static ps_seg_t *
01308 tst_search_seg_iter(ps_search_t *search, int32 *out_score)
01309 {
01310 tst_search_t *tstg = (tst_search_t *)search;
01311 tst_seg_t *itor;
01312 int exit_id, id, cur;
01313
01314 if (tstg->exit_id == -1)
01315 exit_id = vithist_partialutt_end(tstg->vithist, tstg->lmset, ps_search_dict(tstg));
01316 else
01317 exit_id = tstg->exit_id;
01318 if (exit_id < 0) {
01319 E_WARN("Failed to retrieve viterbi history.\n");
01320 return NULL;
01321 }
01322
01323
01324
01325
01326
01327 itor = ckd_calloc(1, sizeof(*itor));
01328 itor->base.vt = &tst_segfuncs;
01329 itor->base.search = search;
01330 itor->base.lwf = 1.0;
01331 itor->n_bpidx = 0;
01332 id = exit_id;
01333 while (id >= 0) {
01334 vithist_entry_t *ve = vithist_id2entry(tstg->vithist, id);
01335 assert(ve);
01336 id = vithist_entry_pred(ve);
01337 ++itor->n_bpidx;
01338 }
01339 if (itor->n_bpidx == 0) {
01340 ckd_free(itor);
01341 return NULL;
01342 }
01343 itor->bpidx = ckd_calloc(itor->n_bpidx, sizeof(*itor->bpidx));
01344 cur = itor->n_bpidx - 1;
01345 id = exit_id;
01346 while (id >= 0) {
01347 vithist_entry_t *ve = vithist_id2entry(tstg->vithist, id);
01348 assert(ve);
01349 itor->bpidx[cur] = id;
01350 id = vithist_entry_pred(ve);
01351 --cur;
01352 }
01353
01354
01355 tst_search_bp2itor((ps_seg_t *)itor, itor->bpidx[0]);
01356
01357 return (ps_seg_t *)itor;
01358 }