acmod_t * acmod_copy(acmod_t *other) { acmod_t *acmod; acmod = ckd_calloc(1, sizeof(*acmod)); acmod->refcount = 1; acmod->config = cmd_ln_retain(other->config); acmod->lmath = logmath_retain(other->lmath); acmod->mdef = bin_mdef_retain(other->mdef); acmod->tmat = tmat_retain(other->tmat); acmod->mgau = ps_mgau_copy(other->mgau); acmod->fb = featbuf_retain(other->fb); acmod->fcb = other->fcb; /* Implicitly retained with fb, I think */ /* Senone computation stuff. */ acmod->senone_scores = ckd_calloc(bin_mdef_n_sen(acmod->mdef), sizeof(*acmod->senone_scores)); acmod->senone_active_vec = bitvec_alloc(bin_mdef_n_sen(acmod->mdef)); acmod->senone_active = ckd_calloc(bin_mdef_n_sen(acmod->mdef), sizeof(*acmod->senone_active)); acmod->log_zero = logmath_get_zero(acmod->lmath); acmod->compallsen = cmd_ln_boolean_r(acmod->config, "-compallsen"); acmod->feat_buf = feat_array_alloc(acmod->fcb, 1); return acmod; }
acmod_t * acmod_init(cmd_ln_t *config, logmath_t *lmath, featbuf_t *fb) { acmod_t *acmod; acmod = ckd_calloc(1, sizeof(*acmod)); acmod->refcount = 1; acmod->config = cmd_ln_retain(config); acmod->lmath = logmath_retain(lmath); acmod->fb = featbuf_retain(fb); acmod->fcb = featbuf_get_fcb(acmod->fb); /* Load acoustic model parameters. */ if (acmod_init_am(acmod) < 0) goto error_out; /* Senone computation stuff. */ acmod->senone_scores = ckd_calloc(bin_mdef_n_sen(acmod->mdef), sizeof(*acmod->senone_scores)); acmod->senone_active_vec = bitvec_alloc(bin_mdef_n_sen(acmod->mdef)); acmod->senone_active = ckd_calloc(bin_mdef_n_sen(acmod->mdef), sizeof(*acmod->senone_active)); acmod->log_zero = logmath_get_zero(acmod->lmath); acmod->compallsen = cmd_ln_boolean_r(config, "-compallsen"); acmod->feat_buf = feat_array_alloc(acmod->fcb, 1); return acmod; error_out: acmod_free(acmod); return NULL; }
int32 ngram_model_init(ngram_model_t *base, ngram_funcs_t *funcs, logmath_t *lmath, int32 n, int32 n_unigram) { base->refcount = 1; base->funcs = funcs; base->n = n; /* If this was previously initialized... */ if (base->n_counts == NULL) base->n_counts = ckd_calloc(3, sizeof(*base->n_counts)); /* Don't reset weights if logmath object hasn't changed. */ if (base->lmath != lmath) { /* Set default values for weights. */ base->lw = 1.0; base->log_wip = 0; /* i.e. 1.0 */ base->log_uw = 0; /* i.e. 1.0 */ base->log_uniform = logmath_log(lmath, 1.0 / n_unigram); base->log_uniform_weight = logmath_get_zero(lmath); base->log_zero = logmath_get_zero(lmath); base->lmath = lmath; } /* Allocate or reallocate space for word strings. */ if (base->word_str) { /* Free all previous word strings if they were allocated. */ if (base->writable) { int32 i; for (i = 0; i < base->n_words; ++i) { ckd_free(base->word_str[i]); base->word_str[i] = NULL; } } base->word_str = ckd_realloc(base->word_str, n_unigram * sizeof(char *)); } else base->word_str = ckd_calloc(n_unigram, sizeof(char *)); /* NOTE: They are no longer case-insensitive since we are allowing * other encodings for word strings. Beware. */ if (base->wid) hash_table_empty(base->wid); else base->wid = hash_table_new(n_unigram, FALSE); base->n_counts[0] = base->n_1g_alloc = base->n_words = n_unigram; return 0; }
static int32 lm3g_template_raw_score(ngram_model_t *base, int32 wid, int32 *history, int32 n_hist, int32 *n_used) { NGRAM_MODEL_TYPE *model = (NGRAM_MODEL_TYPE *)base; int32 score; switch (n_hist) { case 0: /* Access mode: unigram */ *n_used = 1; /* Undo insertion penalty. */ score = model->lm3g.unigrams[wid].prob1.l - base->log_wip; /* Undo language weight. */ score = (int32)(score / base->lw); /* Undo unigram interpolation */ if (strcmp(base->word_str[wid], "<s>") != 0) { /* FIXME: configurable start_sym */ /* This operation is numerically unstable, so try to avoid it * as possible */ if (base->log_uniform + base->log_uniform_weight > logmath_get_zero(base->lmath)) { score = logmath_log(base->lmath, logmath_exp(base->lmath, score) - logmath_exp(base->lmath, base->log_uniform + base->log_uniform_weight)); } } return score; case 1: score = lm3g_bg_score(model, history[0], wid, n_used); break; case 2: default: /* Anything greater than 2 is the same as a trigram for now. */ score = lm3g_tg_score(model, history[1], history[0], wid, n_used); break; } /* FIXME (maybe): This doesn't undo unigram weighting in backoff cases. */ return (int32)((score - base->log_wip) / base->lw); }
acmod_t * acmod_init(cmd_ln_t *config, logmath_t *lmath, fe_t *fe, feat_t *fcb) { acmod_t *acmod; char const *featparams; acmod = ckd_calloc(1, sizeof(*acmod)); acmod->config = cmd_ln_retain(config); acmod->lmath = lmath; acmod->state = ACMOD_IDLE; /* Look for feat.params in acoustic model dir. */ if ((featparams = cmd_ln_str_r(acmod->config, "-featparams"))) { if (NULL != cmd_ln_parse_file_r(acmod->config, feat_defn, featparams, FALSE)) E_INFO("Parsed model-specific feature parameters from %s\n", featparams); } /* Initialize feature computation. */ if (fe) { if (acmod_fe_mismatch(acmod, fe)) goto error_out; fe_retain(fe); acmod->fe = fe; } else { /* Initialize a new front end. */ acmod->fe = fe_init_auto_r(config); if (acmod->fe == NULL) goto error_out; if (acmod_fe_mismatch(acmod, acmod->fe)) goto error_out; } if (fcb) { if (acmod_feat_mismatch(acmod, fcb)) goto error_out; feat_retain(fcb); acmod->fcb = fcb; } else { /* Initialize a new fcb. */ if (acmod_init_feat(acmod) < 0) goto error_out; } /* Load acoustic model parameters. */ if (acmod_init_am(acmod) < 0) goto error_out; /* The MFCC buffer needs to be at least as large as the dynamic * feature window. */ acmod->n_mfc_alloc = acmod->fcb->window_size * 2 + 1; acmod->mfc_buf = (mfcc_t **) ckd_calloc_2d(acmod->n_mfc_alloc, acmod->fcb->cepsize, sizeof(**acmod->mfc_buf)); /* Feature buffer has to be at least as large as MFCC buffer. */ acmod->n_feat_alloc = acmod->n_mfc_alloc + cmd_ln_int32_r(config, "-pl_window"); acmod->feat_buf = feat_array_alloc(acmod->fcb, acmod->n_feat_alloc); acmod->framepos = ckd_calloc(acmod->n_feat_alloc, sizeof(*acmod->framepos)); acmod->utt_start_frame = 0; /* Senone computation stuff. */ acmod->senone_scores = ckd_calloc(bin_mdef_n_sen(acmod->mdef), sizeof(*acmod->senone_scores)); acmod->senone_active_vec = bitvec_alloc(bin_mdef_n_sen(acmod->mdef)); acmod->senone_active = ckd_calloc(bin_mdef_n_sen(acmod->mdef), sizeof(*acmod->senone_active)); acmod->log_zero = logmath_get_zero(acmod->lmath); acmod->compallsen = cmd_ln_boolean_r(config, "-compallsen"); return acmod; error_out: acmod_free(acmod); return NULL; }
int test_decode(ps_decoder_t *ps) { FILE *rawfh; int16 buf[2048]; size_t nread; int16 const *bptr; int nfr; ps_lattice_t *dag; acmod_t *acmod; ngram_search_t *ngs; int i, j; ps_latlink_t *link; ps_latnode_t *node; latlink_list_t *x; int32 norm, post; ngs = (ngram_search_t *)ps->search; acmod = ps->acmod; /* Decode stuff and build a DAG. */ TEST_ASSERT(rawfh = fopen(DATADIR "/goforward.raw", "rb")); TEST_EQUAL(0, acmod_start_utt(acmod)); ngram_fwdtree_start(ngs); while (!feof(rawfh)) { nread = fread(buf, sizeof(*buf), 2048, rawfh); bptr = buf; while ((nfr = acmod_process_raw(acmod, &bptr, &nread, FALSE)) > 0) { while (acmod->n_feat_frame > 0) { ngram_fwdtree_search(ngs, acmod->output_frame); acmod_advance(acmod); } } } ngram_fwdtree_finish(ngs); printf("FWDTREE: %s\n", ngram_search_bp_hyp(ngs, ngram_search_find_exit(ngs, -1, NULL, NULL))); TEST_ASSERT(acmod_end_utt(acmod) >= 0); fclose(rawfh); dag = ngram_search_lattice(ps->search); if (dag == NULL) { E_ERROR("Failed to build DAG!\n"); return -1; } /* Write lattice to disk. */ TEST_EQUAL(0, ps_lattice_write(dag, "test_posterior.lat")); /* Do a bunch of checks on the DAG generation and traversal code: */ /* Verify that forward and backward iteration give the same number of edges. */ i = j = 0; for (link = ps_lattice_traverse_edges(dag, NULL, NULL); link; link = ps_lattice_traverse_next(dag, NULL)) { ++i; } for (link = ps_lattice_reverse_edges(dag, NULL, NULL); link; link = ps_lattice_reverse_next(dag, NULL)) { ++j; } printf("%d forward edges, %d reverse edges\n", i, j); TEST_EQUAL(i,j); /* Verify that the same links are reachable via entries and exits. */ for (node = dag->nodes; node; node = node->next) { for (x = node->exits; x; x = x->next) x->link->alpha = -42; } for (node = dag->nodes; node; node = node->next) { for (x = node->entries; x; x = x->next) TEST_EQUAL(x->link->alpha, -42); } /* Verify that forward iteration is properly ordered. */ for (link = ps_lattice_traverse_edges(dag, NULL, NULL); link; link = ps_lattice_traverse_next(dag, NULL)) { link->alpha = 0; for (x = link->from->entries; x; x = x->next) { TEST_EQUAL(x->link->alpha, 0); } } /* Verify that backward iteration is properly ordered. */ for (node = dag->nodes; node; node = node->next) { for (x = node->exits; x; x = x->next) x->link->alpha = -42; } for (link = ps_lattice_reverse_edges(dag, NULL, NULL); link; link = ps_lattice_reverse_next(dag, NULL)) { link->alpha = 0; for (x = link->to->exits; x; x = x->next) { TEST_EQUAL(x->link->alpha, 0); } } /* Find and print best path. */ link = ps_lattice_bestpath(dag, ngs->lmset, 1.0, 1.0/20.0); printf("BESTPATH: %s\n", ps_lattice_hyp(dag, link)); /* Calculate betas. */ post = ps_lattice_posterior(dag, ngs->lmset, 1.0/20.0); printf("Best path score: %d\n", link->path_scr + dag->final_node_ascr); printf("P(S|O) = %d\n", post); /* Verify that sum of final alphas and initial alphas+betas is * sufficiently similar. */ norm = logmath_get_zero(acmod->lmath); for (x = dag->start->exits; x; x = x->next) norm = logmath_add(acmod->lmath, norm, x->link->beta + x->link->alpha); E_INFO("Sum of final alphas+betas = %d\n", dag->norm); E_INFO("Sum of initial alphas+betas = %d\n", norm); TEST_EQUAL_LOG(dag->norm, norm); /* Print posterior probabilities for each link in best path. */ while (link) { printf("P(%s,%d) = %d = %f\n", dict_wordstr(ps->search->dict, link->from->wid), link->ef, link->alpha + link->beta - dag->norm, logmath_exp(acmod->lmath, link->alpha + link->beta - dag->norm)); link = link->best_prev; } return 0; }