allphone_search.c
/* ====================================================================
* Copyright (c) 2014 Carnegie Mellon University. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY ``AS IS'' AND
* ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY
* NOR ITS EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* ====================================================================
*
*/
/*
* allphone_search.c -- Search for phonetic decoding.
*/
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <sphinxbase/err.h>
#include <sphinxbase/ckd_alloc.h>
#include <sphinxbase/strfuncs.h>
#include <sphinxbase/pio.h>
#include <sphinxbase/cmd_ln.h>
#include "pocketsphinx_internal.h"
#include "allphone_search.h"
static ps_lattice_t *
allphone_search_lattice(ps_search_t * search)
{
//cap
return NULL;
}
static int
allphone_search_prob(ps_search_t * search)
{
return 0;
}
static void
allphone_backtrace(allphone_search_t * allphs, int32 f);
static void
allphone_search_seg_free(ps_seg_t * seg)
{
ckd_free(seg);
}
static void
allphone_search_fill_iter(ps_seg_t *seg, phseg_t *phseg)
{
seg->sf = phseg->sf;
seg->ef = phseg->ef;
seg->ascr = phseg->score;
seg->lscr = phseg->tscore;
seg->word = bin_mdef_ciphone_str(ps_search_acmod(seg->search)->mdef, phseg->ci);
}
static ps_seg_t *
allphone_search_seg_next(ps_seg_t * seg)
{
phseg_iter_t *itor = (phseg_iter_t *) seg;
phseg_t *phseg;
itor->seg = itor->seg->next;
if (itor->seg == NULL) {
allphone_search_seg_free(seg);
return NULL;
}
phseg = gnode_ptr(itor->seg);
allphone_search_fill_iter(seg, phseg);
return seg;
}
static ps_segfuncs_t fsg_segfuncs = {
/* seg_next */ allphone_search_seg_next,
/* seg_free */ allphone_search_seg_free
};
static ps_seg_t *
allphone_search_seg_iter(ps_search_t * search, int32 * out_score)
{
allphone_search_t *allphs = (allphone_search_t *) search;
phseg_iter_t *iter;
allphone_backtrace(allphs, allphs->frame - 1);
if (allphs->segments == NULL)
return NULL;
iter = ckd_calloc(1, sizeof(phseg_iter_t));
iter->base.vt = &fsg_segfuncs;
iter->base.search = search;
iter->seg = allphs->segments;
allphone_search_fill_iter((ps_seg_t *)iter, gnode_ptr(iter->seg));
return (ps_seg_t *) iter;
}
static ps_searchfuncs_t allphone_funcs = {
/* start: */ allphone_search_start,
/* step: */ allphone_search_step,
/* finish: */ allphone_search_finish,
/* reinit: */ allphone_search_reinit,
/* free: */ allphone_search_free,
/* lattice: */ allphone_search_lattice,
/* hyp: */ allphone_search_hyp,
/* prob: */ allphone_search_prob,
/* seg_iter: */ allphone_search_seg_iter,
};
static phmm_t *
phmm_lookup(allphone_search_t * allphs, s3pid_t pid)
{
phmm_t *p;
bin_mdef_t *mdef;
phmm_t **ci_phmm;
mdef = ((ps_search_t *) allphs)->acmod->mdef;
ci_phmm = allphs->ci_phmm;
for (p = ci_phmm[bin_mdef_pid2ci(mdef, pid)]; p; p = p->next) {
if (mdef_pid2tmatid(mdef, p->pid) == mdef_pid2tmatid(mdef, pid))
if (mdef_pid2ssid(mdef, p->pid) == mdef_pid2ssid(mdef, pid))
return p;
}
//not found
return NULL;
}
static int32
phmm_link(allphone_search_t * allphs)
{
s3cipid_t ci, rc;
phmm_t *p, *p2;
int32 *rclist;
int32 i, n_link;
plink_t *l;
bin_mdef_t *mdef;
phmm_t **ci_phmm;
mdef = ((ps_search_t *) allphs)->acmod->mdef;
ci_phmm = allphs->ci_phmm;
rclist = (int32 *) ckd_calloc(mdef->n_ciphone + 1, sizeof(int32));
/* Create successor links between PHMM nodes */
n_link = 0;
for (ci = 0; ci < mdef->n_ciphone; ci++) {
for (p = ci_phmm[ci]; p; p = p->next) {
/* Build rclist for p */
i = 0;
for (rc = 0; rc < mdef->n_ciphone; rc++) {
if (bitvec_is_set(p->rc, rc))
rclist[i++] = rc;
}
rclist[i] = BAD_S3CIPID;
/* For each rc in rclist, transition to PHMMs for rc if left context = ci */
for (i = 0; IS_S3CIPID(rclist[i]); i++) {
for (p2 = ci_phmm[rclist[i]]; p2; p2 = p2->next) {
if (bitvec_is_set(p2->lc, ci)) {
/* transition from p to p2 */
l = (plink_t *) ckd_calloc(1, sizeof(*l));
l->phmm = p2;
l->next = p->succlist;
p->succlist = l;
n_link++;
}
}
}
}
}
ckd_free(rclist);
return n_link;
}
static int
phmm_build(allphone_search_t * allphs)
{
phmm_t *p, **pid2phmm;
bin_mdef_t *mdef;
int32 lrc_size;
uint32 *lc, *rc;
s3pid_t pid;
s3cipid_t ci;
s3cipid_t *filler;
int n_phmm, n_link;
int i, nphone;
mdef = ((ps_search_t *) allphs)->acmod->mdef;
allphs->ci_phmm =
(phmm_t **) ckd_calloc(bin_mdef_n_ciphone(mdef), sizeof(phmm_t *));
pid2phmm =
(phmm_t **) ckd_calloc(bin_mdef_n_phone(mdef), sizeof(phmm_t *));
/* For each unique ciphone/triphone entry in mdef, create a PHMM node */
n_phmm = 0;
nphone = allphs->ci_only ? bin_mdef_n_ciphone(mdef) : bin_mdef_n_phone(mdef);
E_INFO("Building PHMM net of %d phones\n", nphone);
for (pid = 0; pid < nphone; pid++) {
if ((p = phmm_lookup(allphs, pid)) == NULL) {
//not found, should be created
p = (phmm_t *) ckd_calloc(1, sizeof(*p));
hmm_init(allphs->hmmctx, &(p->hmm), FALSE,
mdef_pid2ssid(mdef, pid), mdef->phone[pid].tmat);
p->pid = pid;
p->ci = bin_mdef_pid2ci(mdef, pid);
p->succlist = NULL;
p->next = allphs->ci_phmm[p->ci];
allphs->ci_phmm[p->ci] = p;
n_phmm++;
}
pid2phmm[pid] = p;
}
/* Fill out bitvecs of each PHMM node, alloc continuous memory chunk for context bitvectors */
lrc_size = bitvec_size(bin_mdef_n_ciphone(mdef));
lc = ckd_calloc(n_phmm * 2 * lrc_size, sizeof(bitvec_t));
rc = lc + (n_phmm * lrc_size);
for (ci = 0; ci < mdef->n_ciphone; ci++) {
for (p = allphs->ci_phmm[ci]; p; p = p->next) {
p->lc = lc;
lc += lrc_size;
p->rc = rc;
rc += lrc_size;
}
}
/* Fill out lc and rc bitmaps (remember to map all fillers to each other!!) */
filler =
(s3cipid_t *) ckd_calloc(bin_mdef_n_ciphone(mdef) + 1,
sizeof(s3cipid_t));
/* Connect fillers */
i = 0;
for (ci = 0; ci < bin_mdef_n_ciphone(mdef); ci++) {
p = pid2phmm[ci];
bitvec_set_all(p->lc, bin_mdef_n_ciphone(mdef));
bitvec_set_all(p->rc, bin_mdef_n_ciphone(mdef));
if (mdef->phone[ci].info.ci.filler) {
filler[i++] = ci;
}
}
filler[i] = BAD_S3CIPID;
/* Loop over cdphones only if ci_only is not set */
for (pid = bin_mdef_n_ciphone(mdef); pid < nphone;
pid++) {
p = pid2phmm[pid];
if (mdef->phone[mdef->phone[pid].info.cd.ctx[1]].info.ci.filler) {
for (i = 0; IS_S3CIPID(filler[i]); i++)
bitvec_set(p->lc, filler[i]);
}
else
bitvec_set(p->lc, mdef->phone[pid].info.cd.ctx[1]);
if (mdef->phone[mdef->phone[pid].info.cd.ctx[2]].info.ci.filler) {
for (i = 0; IS_S3CIPID(filler[i]); i++)
bitvec_set(p->rc, filler[i]);
}
else
bitvec_set(p->rc, mdef->phone[pid].info.cd.ctx[2]);
}
ckd_free(pid2phmm);
ckd_free(filler);
/* Create links between PHMM nodes */
n_link = phmm_link(allphs);
E_INFO("%d nodes, %d links\n", n_phmm, n_link);
return 0;
}
static void
phmm_free(allphone_search_t * allphs)
{
s3cipid_t ci;
bin_mdef_t *mdef;
if (!allphs->ci_phmm)
//nothing to free
return;
ckd_free(allphs->ci_phmm[0]->lc);
mdef = ((ps_search_t *) allphs)->acmod->mdef;
for (ci = 0; ci < mdef_n_ciphone(mdef); ++ci) {
phmm_t *p, *next;
for (p = allphs->ci_phmm[ci]; p; p = next) {
plink_t *l, *lnext;
next = p->next;
for (l = p->succlist; l; l = lnext) {
lnext = l->next;
ckd_free(l);
}
hmm_deinit(&(p->hmm));
ckd_free(p);
}
}
ckd_free(allphs->ci_phmm);
}
static int32
phmm_eval_all(allphone_search_t * allphs, const int16 * senscr)
{
s3cipid_t ci;
phmm_t *p;
int32 best;
bin_mdef_t *mdef;
phmm_t **ci_phmm;
mdef = ((ps_search_t *) allphs)->acmod->mdef;
ci_phmm = allphs->ci_phmm;
best = WORST_SCORE;
hmm_context_set_senscore(allphs->hmmctx, senscr);
for (ci = 0; ci < mdef->n_ciphone; ci++) {
for (p = ci_phmm[(unsigned) ci]; p; p = p->next) {
if (hmm_frame(&(p->hmm)) == allphs->frame) {
int32 score;
allphs->n_hmm_eval++;
score = hmm_vit_eval((hmm_t *) p);
if (score > best)
best = score;
}
}
}
return best;
}
static void
phmm_exit(allphone_search_t * allphs, int32 best)
{
s3cipid_t ci;
phmm_t *p;
int32 th, nf;
history_t *h;
blkarray_list_t *history;
bin_mdef_t *mdef;
int32 curfrm;
phmm_t **ci_phmm;
int32 *ci2lmwid;
th = best + allphs->pbeam;
history = allphs->history;
mdef = ps_search_acmod(allphs)->mdef;
curfrm = allphs->frame;
ci_phmm = allphs->ci_phmm;
ci2lmwid = allphs->ci2lmwid;
nf = curfrm + 1;
for (ci = 0; ci < mdef->n_ciphone; ci++) {
for (p = ci_phmm[(unsigned) ci]; p; p = p->next) {
if (hmm_frame(&(p->hmm)) == curfrm) {
if (hmm_bestscore(&(p->hmm)) >= th) {
h = (history_t *) ckd_calloc(1, sizeof(*h));
h->ef = curfrm;
h->phmm = p;
h->hist = hmm_out_history(&(p->hmm));
h->score = hmm_out_score(&(p->hmm));
if (!allphs->lm) {
h->tscore = allphs->inspen;
}
else {
if (h->hist > 0) {
int32 n_used;
history_t *pred =
blkarray_list_get(history, h->hist);
if (pred->hist > 0) {
history_t *pred_pred =
blkarray_list_get(history,
h->hist);
h->tscore =
ngram_tg_score(allphs->lm,
ci2lmwid
[pred_pred->phmm->ci],
ci2lmwid[pred->
phmm->ci],
ci2lmwid[p->ci],
&n_used) >>
SENSCR_SHIFT;
}
else {
h->tscore =
ngram_bg_score(allphs->lm,
ci2lmwid
[pred->phmm->ci],
ci2lmwid[p->ci],
&n_used) >>
SENSCR_SHIFT;
}
}
else {
/*
* This is the beginning SIL and in srch_allphone_begin()
* it's inscore is set to 0.
*/
h->tscore = 0;
}
}
blkarray_list_append(history, h);
/* Mark PHMM active in next frame */
hmm_frame(&(p->hmm)) = nf;
}
else {
/* Reset state scores */
hmm_clear(&(p->hmm));
}
}
}
}
}
static void
phmm_trans(allphone_search_t * allphs, int32 best,
int32 frame_history_start)
{
history_t *h;
phmm_t *from, *to;
plink_t *l;
int32 newscore, nf, curfrm;
int32 *ci2lmwid;
int32 hist_idx;
curfrm = allphs->frame;
nf = curfrm + 1;
ci2lmwid = allphs->ci2lmwid;
/* Transition from exited nodes to initial states of HMMs */
for (hist_idx = frame_history_start;
hist_idx < blkarray_list_n_valid(allphs->history); hist_idx++) {
h = blkarray_list_get(allphs->history, hist_idx);
from = h->phmm;
for (l = from->succlist; l; l = l->next) {
int32 tscore;
to = l->phmm;
/* No LM, just use uniform (insertion penalty). */
if (!allphs->lm)
tscore = allphs->inspen;
/* If they are not in the LM, kill this
* transition. */
else if (ci2lmwid[to->ci] == NGRAM_INVALID_WID)
continue;
else {
int32 n_used;
if (h->hist > 0) {
history_t *pred =
blkarray_list_get(allphs->history, h->hist);
tscore =
ngram_tg_score(allphs->lm,
ci2lmwid[pred->phmm->ci],
ci2lmwid[from->ci],
ci2lmwid[to->ci],
&n_used) >> SENSCR_SHIFT;
}
else {
tscore = ngram_bg_score(allphs->lm,
ci2lmwid[from->ci],
ci2lmwid[to->ci],
&n_used) >> SENSCR_SHIFT;
}
}
newscore = h->score + tscore;
if ((newscore > best + allphs->beam)
&& (newscore > hmm_in_score(&(to->hmm)))) {
hmm_enter(&(to->hmm), newscore, hist_idx, nf);
}
}
}
}
ps_search_t *
allphone_search_init(const char *name,
ngram_model_t * lm,
cmd_ln_t * config,
acmod_t * acmod, dict_t * dict, dict2pid_t * d2p)
{
int i;
bin_mdef_t *mdef;
allphone_search_t *allphs;
static char *lmname = "default";
allphs = (allphone_search_t *) ckd_calloc(1, sizeof(*allphs));
ps_search_init(ps_search_base(allphs), &allphone_funcs, PS_SEARCH_TYPE_ALLPHONE, name, config, acmod,
dict, d2p);
mdef = acmod->mdef;
allphs->hmmctx = hmm_context_init(bin_mdef_n_emit_state(mdef),
acmod->tmat->tp, NULL, mdef->sseq);
if (allphs->hmmctx == NULL) {
ps_search_free(ps_search_base(allphs));
return NULL;
}
allphs->ci_only = cmd_ln_boolean_r(config, "-allphone_ci");
allphs->lw = cmd_ln_float32_r(config, "-lw");
phmm_build(allphs);
if (lm) {
//language model is defined
allphs->lm = ngram_model_set_init(config, &lm, &lmname, NULL, 1);
if (!allphs->lm) {
E_ERROR
("Failed to initialize ngram model set for phoneme decoding");
allphone_search_free((ps_search_t *) allphs);
return NULL;
}
allphs->ci2lmwid =
(int32 *) ckd_calloc(mdef->n_ciphone,
sizeof(*allphs->ci2lmwid));
for (i = 0; i < mdef->n_ciphone; i++) {
allphs->ci2lmwid[i] =
ngram_wid(allphs->lm,
(char *) bin_mdef_ciphone_str(mdef, i));
/* Map filler phones to silence if not found */
if (allphs->ci2lmwid[i] == NGRAM_INVALID_WID
&& bin_mdef_ciphone_str(mdef, i))
allphs->ci2lmwid[i] =
ngram_wid(allphs->lm,
(char *) bin_mdef_ciphone_str(mdef,
mdef_silphone
(mdef)));
}
}
else {
E_WARN
("Failed to load language model specified in -allphone, doing unconstrained phone-loop decoding\n");
allphs->inspen =
(int32) (logmath_log
(acmod->lmath, cmd_ln_float32_r(config, "-pip"))
* allphs->lw) >> SENSCR_SHIFT;
}
allphs->n_tot_frame = 0;
allphs->frame = -1;
allphs->segments = NULL;
/* Get search pruning parameters */
allphs->beam
=
(int32) logmath_log(acmod->lmath,
cmd_ln_float64_r(config, "-beam"))
>> SENSCR_SHIFT;
allphs->pbeam
=
(int32) logmath_log(acmod->lmath,
cmd_ln_float64_r(config, "-pbeam"))
>> SENSCR_SHIFT;
/* LM related weights/penalties */
allphs->history = blkarray_list_init();
/* Acoustic score scale for posterior probabilities. */
allphs->ascale = 1.0 / cmd_ln_float32_r(config, "-ascale");
E_INFO("Allphone(beam: %d, pbeam: %d)\n", allphs->beam, allphs->pbeam);
ptmr_init(&allphs->perf);
return (ps_search_t *) allphs;
}
int
allphone_search_reinit(ps_search_t * search, dict_t * dict,
dict2pid_t * d2p)
{
allphone_search_t *allphs = (allphone_search_t *) search;
/* Free old dict2pid, dict */
ps_search_base_reinit(search, dict, d2p);
if (!allphs->lm) {
E_WARN
("-lm argument missing; doing unconstrained phone-loop decoding\n");
allphs->inspen =
(int32) (logmath_log
(search->acmod->lmath,
cmd_ln_float32_r(search->config,
"-pip")) *
allphs->lw) >> SENSCR_SHIFT;
}
return 0;
}
void
allphone_search_free(ps_search_t * search)
{
allphone_search_t *allphs = (allphone_search_t *) search;
double n_speech = (double)allphs->n_tot_frame
/ cmd_ln_int32_r(ps_search_config(allphs), "-frate");
E_INFO("TOTAL fwdflat %.2f CPU %.3f xRT\n",
allphs->perf.t_tot_cpu,
allphs->perf.t_tot_cpu / n_speech);
E_INFO("TOTAL fwdflat %.2f wall %.3f xRT\n",
allphs->perf.t_tot_elapsed,
allphs->perf.t_tot_elapsed / n_speech);
ps_search_base_free(search);
hmm_context_free(allphs->hmmctx);
phmm_free(allphs);
if (allphs->lm)
ngram_model_free(allphs->lm);
if (allphs->ci2lmwid)
ckd_free(allphs->ci2lmwid);
blkarray_list_free(allphs->history);
ckd_free(allphs);
}
int
allphone_search_start(ps_search_t * search)
{
allphone_search_t *allphs;
bin_mdef_t *mdef;
s3cipid_t ci;
phmm_t *p;
allphs = (allphone_search_t *) search;
mdef = search->acmod->mdef;
/* Reset all HMMs. */
for (ci = 0; ci < bin_mdef_n_ciphone(mdef); ci++) {
for (p = allphs->ci_phmm[(unsigned) ci]; p; p = p->next) {
hmm_clear(&(p->hmm));
}
}
allphs->n_hmm_eval = 0;
allphs->n_sen_eval = 0;
/* Free history nodes, if any */
blkarray_list_reset(allphs->history);
/* Initialize start state of the SILENCE PHMM */
allphs->frame = 0;
ci = bin_mdef_silphone(mdef);
if (NOT_S3CIPID(ci))
E_FATAL("Cannot find CI-phone %s\n", S3_SILENCE_CIPHONE);
for (p = allphs->ci_phmm[ci]; p && (p->pid != ci); p = p->next);
if (!p)
E_FATAL("Cannot find HMM for %s\n", S3_SILENCE_CIPHONE);
hmm_enter(&(p->hmm), 0, 0, allphs->frame);
ptmr_reset(&allphs->perf);
ptmr_start(&allphs->perf);
return 0;
}
static void
allphone_search_sen_active(allphone_search_t * allphs)
{
acmod_t *acmod;
bin_mdef_t *mdef;
phmm_t *p;
int32 ci;
acmod = ps_search_acmod(allphs);
mdef = acmod->mdef;
acmod_clear_active(acmod);
for (ci = 0; ci < bin_mdef_n_ciphone(mdef); ci++)
for (p = allphs->ci_phmm[ci]; p; p = p->next)
if (hmm_frame(&(p->hmm)) == allphs->frame)
acmod_activate_hmm(acmod, &(p->hmm));
}
int
allphone_search_step(ps_search_t * search, int frame_idx)
{
int32 bestscr, frame_history_start;
const int16 *senscr;
allphone_search_t *allphs = (allphone_search_t *) search;
acmod_t *acmod = search->acmod;
if (!acmod->compallsen)
allphone_search_sen_active(allphs);
senscr = acmod_score(acmod, &frame_idx);
allphs->n_sen_eval += acmod->n_senone_active;
bestscr = phmm_eval_all(allphs, senscr);
frame_history_start = blkarray_list_n_valid(allphs->history);
phmm_exit(allphs, bestscr);
phmm_trans(allphs, bestscr, frame_history_start);
allphs->frame++;
return 0;
}
static int32
ascore(allphone_search_t * allphs, history_t * h)
{
int32 score = h->score;
if (h->hist > 0) {
history_t *pred = blkarray_list_get(allphs->history, h->hist);
score -= pred->score;
}
return score - h->tscore;
}
static void
allphone_clear_segments(allphone_search_t * allphs)
{
gnode_t *gn;
for (gn = allphs->segments; gn; gn = gn->next) {
ckd_free(gnode_ptr(gn));
}
glist_free(allphs->segments);
allphs->segments = NULL;
}
static void
allphone_backtrace(allphone_search_t * allphs, int32 f)
{
int32 best, hist_idx, best_idx;
int32 frm, last_frm;
history_t *h;
phseg_t *s;
/* Clear old list */
allphone_clear_segments(allphs);
frm = last_frm = f;
/* Find the first history entry for the requested frame */
hist_idx = blkarray_list_n_valid(allphs->history) - 1;
while (hist_idx > 0) {
h = blkarray_list_get(allphs->history, hist_idx);
if (h->ef <= f) {
frm = last_frm = h->ef;
break;
}
hist_idx--;
}
if (hist_idx < 0)
return;
/* Find bestscore */
best = (int32) 0x80000000;
best_idx = -1;
while (frm == last_frm && hist_idx > 0) {
h = blkarray_list_get(allphs->history, hist_idx);
frm = h->ef;
if (h->score > best && frm == last_frm) {
best = h->score;
best_idx = hist_idx;
}
hist_idx--;
}
if (best_idx < 0)
return;
/* Backtrace */
while (best_idx > 0) {
h = blkarray_list_get(allphs->history, best_idx);
s = (phseg_t *) ckd_calloc(1, sizeof(phseg_t));
s->ci = h->phmm->ci;
s->sf =
(h->hist >
0) ? ((history_t *) blkarray_list_get(allphs->history,
h->hist))->ef + 1 : 0;
s->ef = h->ef;
s->score = ascore(allphs, h);
s->tscore = h->tscore;
allphs->segments = glist_add_ptr(allphs->segments, s);
best_idx = h->hist;
}
return;
}
int
allphone_search_finish(ps_search_t * search)
{
allphone_search_t *allphs;
int32 cf, n_hist;
allphs = (allphone_search_t *) search;
allphs->n_tot_frame += allphs->frame;
n_hist = blkarray_list_n_valid(allphs->history);
E_INFO
("%d frames, %d HMMs (%d/fr), %d senones (%d/fr), %d history entries (%d/fr)\n",
allphs->frame, allphs->n_hmm_eval,
(allphs->frame > 0) ? allphs->n_hmm_eval / allphs->frame : 0,
allphs->n_sen_eval,
(allphs->frame > 0) ? allphs->n_sen_eval / allphs->frame : 0,
n_hist, (allphs->frame > 0) ? n_hist / allphs->frame : 0);
/* Now backtrace. */
allphone_backtrace(allphs, allphs->frame - 1);
/* Print out some statistics. */
ptmr_stop(&allphs->perf);
/* This is the number of frames processed. */
cf = ps_search_acmod(allphs)->output_frame;
if (cf > 0) {
double n_speech = (double) (cf + 1)
/ cmd_ln_int32_r(ps_search_config(allphs), "-frate");
E_INFO("allphone %.2f CPU %.3f xRT\n",
allphs->perf.t_cpu, allphs->perf.t_cpu / n_speech);
E_INFO("allphone %.2f wall %.3f xRT\n",
allphs->perf.t_elapsed, allphs->perf.t_elapsed / n_speech);
}
return 0;
}
char const *
allphone_search_hyp(ps_search_t * search, int32 * out_score,
int32 * out_is_final)
{
allphone_search_t *allphs;
phseg_t *p;
gnode_t *gn;
const char *phone_str;
bin_mdef_t *mdef;
int len, hyp_idx, phone_idx;
allphs = (allphone_search_t *) search;
mdef = search->acmod->mdef;
/* Create hypothesis */
if (search->hyp_str)
ckd_free(search->hyp_str);
search->hyp_str = NULL;
allphone_backtrace(allphs, allphs->frame - 1);
if (allphs->segments == NULL) {
return NULL;
}
len = glist_count(allphs->segments) * 10; // maximum length of one phone with spacebar
search->hyp_str = (char *) ckd_calloc(len, sizeof(*search->hyp_str));
hyp_idx = 0;
for (gn = allphs->segments; gn; gn = gn->next) {
p = gnode_ptr(gn);
phone_str = bin_mdef_ciphone_str(mdef, p->ci);
phone_idx = 0;
while (phone_str[phone_idx] != '\0')
search->hyp_str[hyp_idx++] = phone_str[phone_idx++];
search->hyp_str[hyp_idx++] = ' ';
}
search->hyp_str[--hyp_idx] = '\0';
E_INFO("Hyp: %s\n", search->hyp_str);
return search->hyp_str;
}
pocketsphinx_internal.h
Internal implementation of PocketSphinx decoder.
history_s
History (paths) information at any point in allphone Viterbi search.
Definition: allphone_search.h:81
phmm_s::next
struct phmm_s * next
Next unique PHMM for same parent basephone.
Definition: allphone_search.h:66
ps_search_s
Base structure for search module.
Definition: pocketsphinx_internal.h:98
allphone_search_s::perf
ptmr_t perf
Performance counter.
Definition: allphone_search.h:134
hmm_init
void hmm_init(hmm_context_t *ctx, hmm_t *hmm, int mpx, int ssid, int tmatid)
Populate a previously-allocated HMM structure, allocating internal data.
Definition: hmm.c:89
phmm_s::ci
s3cipid_t ci
Parent basephone for this PHMM.
Definition: allphone_search.h:63
blkarray_list_s
Definition: blkarray_list.h:79
allphone_search_s::n_sen_eval
int32 n_sen_eval
Total senones evaluated this utt.
Definition: allphone_search.h:127
bin_mdef_ciphone_str
const char * bin_mdef_ciphone_str(bin_mdef_t *m, int32 ci)
In: ciphone id for which name wanted.
Definition: bin_mdef.c:737
ps_search_base_reinit
void ps_search_base_reinit(ps_search_t *search, dict_t *dict, dict2pid_t *d2p)
Re-initialize base structure with new dictionary.
Definition: pocketsphinx.c:1441
acmod_s::n_senone_active
int n_senone_active
Number of active GMMs.
Definition: acmod.h:169
ps_search_s::acmod
acmod_t * acmod
Acoustic model.
Definition: pocketsphinx_internal.h:106
hmm_t
An individual HMM among the HMM search space.
tmat_t::tp
uint8 *** tp
The transition matrices; kept in the same scale as acoustic scores; tp[tmatid][from-state][to-state]...
Definition: tmat.h:107
ps_seg_s::vt
ps_segfuncs_t * vt
V-table of seg methods.
Definition: pocketsphinx_internal.h:179
acmod_s::lmath
logmath_t * lmath
Log-math computation.
Definition: acmod.h:151
bin_mdef_s::sseq
uint16 ** sseq
Unique senone sequences (2D array built at load time)
Definition: bin_mdef.h:134
hmm_deinit
void hmm_deinit(hmm_t *hmm)
Free an HMM structure, releasing internal data (but not the HMM structure itself).
Definition: hmm.c:111
ps_seg_s::lscr
int32 lscr
Language model score.
Definition: pocketsphinx_internal.h:185
phmm_s::pid
s3pid_t pid
Phone id (temp.
Definition: allphone_search.h:62
mdef_entry_s::tmat
int32 tmat
Transition matrix ID.
Definition: bin_mdef.h:75
acmod_activate_hmm
void acmod_activate_hmm(acmod_t *acmod, hmm_t *hmm)
Activate senones associated with an HMM.
Definition: acmod.c:1233
history_s::hist
int32 hist
Previous history entry.
Definition: allphone_search.h:86
phmm_s::lc
bitvec_t * lc
Set (bit-vector) of left context phones seen for this PHMM.
Definition: allphone_search.h:64
history_s::score
int32 score
Path score for this path.
Definition: allphone_search.h:83
BAD_S3CIPID
#define BAD_S3CIPID
Ci phone id.
Definition: s3types.h:64
ps_seg_s::word
char const * word
Word string (pointer into dictionary hash)
Definition: pocketsphinx_internal.h:181
ps_seg_s::search
ps_search_t * search
Search object from whence this came.
Definition: pocketsphinx_internal.h:180
ps_search_init
void ps_search_init(ps_search_t *search, ps_searchfuncs_t *vt, const char *type, const char *name, cmd_ln_t *config, acmod_t *acmod, dict_t *dict, dict2pid_t *d2p)
Initialize base structure.
Definition: pocketsphinx.c:1397
allphone_search_s::ci2lmwid
int32 * ci2lmwid
Mapping of CI phones to LM word IDs.
Definition: allphone_search.h:117
allphone_search_s::inspen
int32 inspen
Language weights.
Definition: allphone_search.h:120
bin_mdef_s
Definition: bin_mdef.h:117
hmm_vit_eval
int32 hmm_vit_eval(hmm_t *hmm)
Viterbi evaluation of given HMM.
Definition: hmm.c:789
mdef_entry_s::ci
struct mdef_entry_s::@0::@1 ci
< CI phone information - attributes (just "filler" for now)
history_s::ef
frame_idx_t ef
End frame.
Definition: allphone_search.h:85
acmod_s::compallsen
uint8 compallsen
Compute all senones?
Definition: acmod.h:188
phmm_s::rc
bitvec_t * rc
Set (bit-vector) of right context phones seen for this PHMM.
Definition: allphone_search.h:65
hmm_context_init
hmm_context_t * hmm_context_init(int32 n_emit_state, uint8 **const *tp, int16 const *senscore, uint16 *const *sseq)
Create an HMM context.
Definition: hmm.c:56
ps_search_base_free
void ps_search_base_free(ps_search_t *search)
Free search.
Definition: pocketsphinx.c:1428
allphone_search_s
Implementation of allphone search structure.
Definition: allphone_search.h:110
acmod_s::config
cmd_ln_t * config
Configuration.
Definition: acmod.h:150
s3cipid_t
int16 s3cipid_t
Size definitions for more semantially meaningful units.
Definition: s3types.h:63
WORST_SCORE
#define WORST_SCORE
Large "bad" score.
Definition: hmm.h:84
acmod_s::tmat
tmat_t * tmat
Transition matrices.
Definition: acmod.h:160
ps_seg_s::ef
frame_idx_t ef
End frame.
Definition: pocketsphinx_internal.h:183
ps_seg_s::ascr
int32 ascr
Acoustic score.
Definition: pocketsphinx_internal.h:184
history_s::tscore
int32 tscore
Transition score for this path.
Definition: allphone_search.h:84
allphone_search_s::hmmctx
hmm_context_t * hmmctx
HMM context.
Definition: allphone_search.h:113
hmm_enter
void hmm_enter(hmm_t *h, int32 score, int32 histid, int frame)
Enter an HMM with the given path score and history ID.
Definition: hmm.c:201
phseg_iter_s
Segment iterator over list of phseg.
Definition: allphone_search.h:102
acmod_clear_active
void acmod_clear_active(acmod_t *acmod)
Clear set of active senones.
Definition: acmod.c:1217
S3_SILENCE_CIPHONE
#define S3_SILENCE_CIPHONE
Hard-coded silence CI phone name.
Definition: mdef.h:81
plink_s::next
struct plink_s * next
Next link for parent PHMM node.
Definition: allphone_search.h:75
hmm_context_set_senscore
#define hmm_context_set_senscore(ctx, senscr)
Change the senone score array for a context.
Definition: hmm.h:227
SENSCR_SHIFT
#define SENSCR_SHIFT
Shift count for senone scores.
Definition: hmm.h:73
dict_t
a structure for a dictionary.
Definition: dict.h:76
allphone_search_s::ascale
float32 ascale
Acoustic score scale for posterior probabilities.
Definition: allphone_search.h:123
allphone_search_s::n_tot_frame
int32 n_tot_frame
Total number of frames processed.
Definition: allphone_search.h:125
allphone_search_s::lm
ngram_model_t * lm
Ngram model set.
Definition: allphone_search.h:114
ps_lattice_s
Word graph structure used in bestpath/nbest search.
Definition: ps_lattice_internal.h:61
phmm_s::hmm
hmm_t hmm
Base HMM structure.
Definition: allphone_search.h:61
hmm_clear
void hmm_clear(hmm_t *h)
Reset the states of the HMM to the invalid condition.
Definition: hmm.c:183
ps_search_s::hyp_str
char * hyp_str
Current hypothesis string.
Definition: pocketsphinx_internal.h:109
allphone_search_s::ci_only
int32 ci_only
Use context-independent phones for decoding.
Definition: allphone_search.h:115
allphone_search_s::n_hmm_eval
int32 n_hmm_eval
Total HMMs evaluated this utt.
Definition: allphone_search.h:126
phmm_s::succlist
struct plink_s * succlist
List of predecessor PHMM nodes.
Definition: allphone_search.h:67
phmm_s
Models a single unique <senone-sequence, tmat> pair.
Definition: allphone_search.h:60
history_s::phmm
phmm_t * phmm
PHMM ending this path.
Definition: allphone_search.h:82
plink_s::phmm
phmm_t * phmm
Successor PHMM node.
Definition: allphone_search.h:74
hmm_context_free
void hmm_context_free(hmm_context_t *ctx)
Free an HMM context.
Definition: hmm.c:80
allphone_search_s::pbeam
int32 pbeam
Effective beams after applying beam_factor.
Definition: allphone_search.h:119
acmod_s::mdef
bin_mdef_t * mdef
Model definition.
Definition: acmod.h:159
ps_searchfuncs_s
V-table for search algorithm.
Definition: pocketsphinx_internal.h:82
bin_mdef_s::phone
mdef_entry_t * phone
All phone structures.
Definition: bin_mdef.h:133
allphone_search_s::history
blkarray_list_t * history
List of history nodes allocated in each frame.
Definition: allphone_search.h:130
ps_seg_s
Base structure for hypothesis segmentation iterator.
Definition: pocketsphinx_internal.h:178
bin_mdef_s::n_ciphone
int32 n_ciphone
Number of base (CI) phones.
Definition: bin_mdef.h:119
ps_search_s::config
cmd_ln_t * config
Configuration.
Definition: pocketsphinx_internal.h:105
allphone_search_s::ci_phmm
phmm_t ** ci_phmm
PHMM lists (for each CI phone)
Definition: allphone_search.h:116
ps_segfuncs_s
Definition: pocketsphinx_internal.h:170
acmod_s
Acoustic model structure.
Definition: acmod.h:148
phseg_s
Phone level segmentation information.
Definition: allphone_search.h:92
dict2pid_t
Building composite triphone (as well as word internal triphones) with the dictionary.
Definition: dict2pid.h:84
plink_s
List of links from a PHMM node to its successors; one link per successor.
Definition: allphone_search.h:73
ps_seg_s::sf
frame_idx_t sf
Start frame.
Definition: pocketsphinx_internal.h:182
acmod_score
int16 const * acmod_score(acmod_t *acmod, int *inout_frame_idx)
Score one frame of data.
Definition: acmod.c:1126
allphone_search_s::frame
frame_idx_t frame
Current frame.
Definition: allphone_search.h:122