kws_search.c
/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*- */
/* ====================================================================
* Copyright (c) 2013 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.
*
* ====================================================================
*
*/
/*
* kws_search.c -- Search object for key phrase spotting.
*/
#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 "kws_search.h"
#define hmm_is_active(hmm) ((hmm)->frame > 0)
#define kws_nth_hmm(keyphrase,n) (&((keyphrase)->hmms[n]))
/* Value selected experimentally as maximum difference between triphone
score and phone loop score, used in confidence computation to make sure
that confidence value is less than 1. This might be different for
different models. Corresponds to threshold of about 1e+50 */
#define KWS_MAX 1500
static ps_lattice_t *
kws_search_lattice(ps_search_t * search)
{
return NULL;
}
static int
kws_search_prob(ps_search_t * search)
{
return 0;
}
static void
kws_seg_free(ps_seg_t *seg)
{
kws_seg_t *itor = (kws_seg_t *)seg;
ckd_free(itor);
}
static void
kws_seg_fill(kws_seg_t *itor)
{
kws_detection_t* detection = (kws_detection_t*)gnode_ptr(itor->detection);
itor->base.word = detection->keyphrase;
itor->base.sf = detection->sf;
itor->base.ef = detection->ef;
itor->base.prob = detection->prob;
itor->base.ascr = detection->ascr;
itor->base.lscr = 0;
}
static ps_seg_t *
kws_seg_next(ps_seg_t *seg)
{
kws_seg_t *itor = (kws_seg_t *)seg;
gnode_t *detect_head = gnode_next(itor->detection);
while (detect_head != NULL && ((kws_detection_t*)gnode_ptr(detect_head))->ef > itor->last_frame)
detect_head = gnode_next(detect_head);
itor->detection = detect_head;
if (!itor->detection) {
kws_seg_free(seg);
return NULL;
}
kws_seg_fill(itor);
return seg;
}
static ps_segfuncs_t kws_segfuncs = {
/* seg_next */ kws_seg_next,
/* seg_free */ kws_seg_free
};
static ps_seg_t *
kws_search_seg_iter(ps_search_t * search)
{
kws_search_t *kwss = (kws_search_t *)search;
kws_seg_t *itor;
gnode_t *detect_head = kwss->detections->detect_list;
while (detect_head != NULL && ((kws_detection_t*)gnode_ptr(detect_head))->ef > kwss->frame - kwss->delay)
detect_head = gnode_next(detect_head);
if (!detect_head)
return NULL;
itor = (kws_seg_t *)ckd_calloc(1, sizeof(*itor));
itor->base.vt = &kws_segfuncs;
itor->base.search = search;
itor->base.lwf = 1.0;
itor->detection = detect_head;
itor->last_frame = kwss->frame - kwss->delay;
kws_seg_fill(itor);
return (ps_seg_t *)itor;
}
static ps_searchfuncs_t kws_funcs = {
/* start: */ kws_search_start,
/* step: */ kws_search_step,
/* finish: */ kws_search_finish,
/* reinit: */ kws_search_reinit,
/* free: */ kws_search_free,
/* lattice: */ kws_search_lattice,
/* hyp: */ kws_search_hyp,
/* prob: */ kws_search_prob,
/* seg_iter: */ kws_search_seg_iter,
};
/* Activate senones for scoring */
static void
kws_search_sen_active(kws_search_t * kwss)
{
int i;
gnode_t *gn;
acmod_clear_active(ps_search_acmod(kwss));
/* active phone loop hmms */
for (i = 0; i < kwss->n_pl; i++)
acmod_activate_hmm(ps_search_acmod(kwss), &kwss->pl_hmms[i]);
/* activate hmms in active nodes */
for (gn = kwss->keyphrases; gn; gn = gnode_next(gn)) {
kws_keyphrase_t *keyphrase = gnode_ptr(gn);
for (i = 0; i < keyphrase->n_hmms; i++) {
if (hmm_is_active(kws_nth_hmm(keyphrase, i)))
acmod_activate_hmm(ps_search_acmod(kwss), kws_nth_hmm(keyphrase, i));
}
}
}
/*
* Evaluate all the active HMMs.
* (Executed once per frame.)
*/
static void
kws_search_hmm_eval(kws_search_t * kwss, int16 const *senscr)
{
int32 i;
gnode_t *gn;
int32 bestscore = WORST_SCORE;
hmm_context_set_senscore(kwss->hmmctx, senscr);
/* evaluate hmms from phone loop */
for (i = 0; i < kwss->n_pl; ++i) {
hmm_t *hmm = &kwss->pl_hmms[i];
int32 score;
score = hmm_vit_eval(hmm);
if (score BETTER_THAN bestscore)
bestscore = score;
}
/* evaluate hmms for active nodes */
for (gn = kwss->keyphrases; gn; gn = gnode_next(gn)) {
kws_keyphrase_t *keyphrase = gnode_ptr(gn);
for (i = 0; i < keyphrase->n_hmms; i++) {
hmm_t *hmm = kws_nth_hmm(keyphrase, i);
if (hmm_is_active(hmm)) {
int32 score;
score = hmm_vit_eval(hmm);
if (score BETTER_THAN bestscore)
bestscore = score;
}
}
}
kwss->bestscore = bestscore;
}
/*
* (Beam) prune the just evaluated HMMs, determine which ones remain
* active. Executed once per frame.
*/
static void
kws_search_hmm_prune(kws_search_t * kwss)
{
int32 thresh, i;
gnode_t *gn;
thresh = kwss->bestscore + kwss->beam;
for (gn = kwss->keyphrases; gn; gn = gnode_next(gn)) {
kws_keyphrase_t *keyphrase = gnode_ptr(gn);
for (i = 0; i < keyphrase->n_hmms; i++) {
hmm_t *hmm = kws_nth_hmm(keyphrase, i);
if (hmm_is_active(hmm) && hmm_bestscore(hmm) < thresh)
hmm_clear(hmm);
}
}
}
static void
kws_search_trans(kws_search_t * kwss)
{
hmm_t *pl_best_hmm = NULL;
int32 best_out_score = WORST_SCORE;
int i;
gnode_t *gn;
/* select best hmm in phone-loop to be a predecessor */
for (i = 0; i < kwss->n_pl; i++)
if (hmm_out_score(&kwss->pl_hmms[i]) BETTER_THAN best_out_score) {
best_out_score = hmm_out_score(&kwss->pl_hmms[i]);
pl_best_hmm = &kwss->pl_hmms[i];
}
/* out probs are not ready yet */
if (!pl_best_hmm)
return;
/* Check whether keyphrase wasn't spotted yet */
for (gn = kwss->keyphrases; gn; gn = gnode_next(gn)) {
kws_keyphrase_t *keyphrase = gnode_ptr(gn);
hmm_t *last_hmm;
if (keyphrase->n_hmms < 1)
continue;
last_hmm = kws_nth_hmm(keyphrase, keyphrase->n_hmms - 1);
if (hmm_is_active(last_hmm)
&& hmm_out_score(pl_best_hmm) BETTER_THAN WORST_SCORE) {
if (hmm_out_score(last_hmm) - hmm_out_score(pl_best_hmm)
>= keyphrase->threshold) {
int32 prob = hmm_out_score(last_hmm) - hmm_out_score(pl_best_hmm) - KWS_MAX;
kws_detections_add(kwss->detections, keyphrase->word,
hmm_out_history(last_hmm),
kwss->frame, prob,
hmm_out_score(last_hmm));
} /* keyphrase is spotted */
} /* last hmm of keyphrase is active */
} /* keyphrase loop */
/* Make transition for all phone loop hmms */
for (i = 0; i < kwss->n_pl; i++) {
if (hmm_out_score(pl_best_hmm) + kwss->plp BETTER_THAN
hmm_in_score(&kwss->pl_hmms[i])) {
hmm_enter(&kwss->pl_hmms[i],
hmm_out_score(pl_best_hmm) + kwss->plp,
hmm_out_history(pl_best_hmm), kwss->frame + 1);
}
}
/* Activate new keyphrase nodes, enter their hmms */
for (gn = kwss->keyphrases; gn; gn = gnode_next(gn)) {
kws_keyphrase_t *keyphrase = gnode_ptr(gn);
if (keyphrase->n_hmms < 1)
continue;
for (i = keyphrase->n_hmms - 1; i > 0; i--) {
hmm_t *pred_hmm = kws_nth_hmm(keyphrase, i - 1);
hmm_t *hmm = kws_nth_hmm(keyphrase, i);
if (hmm_is_active(pred_hmm)) {
if (!hmm_is_active(hmm)
|| hmm_out_score(pred_hmm) BETTER_THAN
hmm_in_score(hmm))
hmm_enter(hmm, hmm_out_score(pred_hmm),
hmm_out_history(pred_hmm), kwss->frame + 1);
}
}
/* Enter keyphrase start node from phone loop */
if (hmm_out_score(pl_best_hmm) BETTER_THAN
hmm_in_score(kws_nth_hmm(keyphrase, 0)))
hmm_enter(kws_nth_hmm(keyphrase, 0), hmm_out_score(pl_best_hmm),
kwss->frame, kwss->frame + 1);
}
}
static int
kws_search_read_list(kws_search_t *kwss, const char* keyfile)
{
FILE *list_file;
lineiter_t *li;
char *line;
if ((list_file = fopen(keyfile, "r")) == NULL) {
E_ERROR_SYSTEM("Failed to open keyphrase file '%s'", keyfile);
return -1;
}
kwss->keyphrases = NULL;
/* read keyphrases */
for (li = lineiter_start_clean(list_file); li; li = lineiter_next(li)) {
size_t begin, end;
kws_keyphrase_t *keyphrase;
if (li->len == 0)
continue;
keyphrase = ckd_calloc(1, sizeof(kws_keyphrase_t));
line = li->buf;
end = strlen(line) - 1;
begin = end - 1;
if (line[end] == '/') {
while (line[begin] != '/' && begin > 0)
begin--;
line[end] = 0;
line[begin] = 0;
keyphrase->threshold = (int32) logmath_log(kwss->base.acmod->lmath, atof_c(line + begin + 1))
>> SENSCR_SHIFT;
} else {
keyphrase->threshold = kwss->def_threshold;
}
keyphrase->word = ckd_salloc(line);
kwss->keyphrases = glist_add_ptr(kwss->keyphrases, keyphrase);
}
fclose(list_file);
return 0;
}
ps_search_t *
kws_search_init(const char *name,
const char *keyphrase,
const char *keyfile,
cmd_ln_t * config,
acmod_t * acmod, dict_t * dict, dict2pid_t * d2p)
{
kws_search_t *kwss = (kws_search_t *) ckd_calloc(1, sizeof(*kwss));
ps_search_init(ps_search_base(kwss), &kws_funcs, PS_SEARCH_TYPE_KWS, name, config, acmod, dict,
d2p);
kwss->detections = (kws_detections_t *)ckd_calloc(1, sizeof(*kwss->detections));
kwss->beam =
(int32) logmath_log(acmod->lmath,
cmd_ln_float64_r(config,
"-beam")) >> SENSCR_SHIFT;
kwss->plp =
(int32) logmath_log(acmod->lmath,
cmd_ln_float32_r(config,
"-kws_plp")) >> SENSCR_SHIFT;
kwss->def_threshold =
(int32) logmath_log(acmod->lmath,
cmd_ln_float64_r(config,
"-kws_threshold")) >>
SENSCR_SHIFT;
kwss->delay = (int32) cmd_ln_int32_r(config, "-kws_delay");
E_INFO("KWS(beam: %d, plp: %d, default threshold %d, delay %d)\n",
kwss->beam, kwss->plp, kwss->def_threshold, kwss->delay);
if (keyfile) {
if (kws_search_read_list(kwss, keyfile) < 0) {
E_ERROR("Failed to create kws search\n");
kws_search_free(ps_search_base(kwss));
return NULL;
}
} else {
kws_keyphrase_t *k = ckd_calloc(1, sizeof(kws_keyphrase_t));
k->threshold = kwss->def_threshold;
k->word = ckd_salloc(keyphrase);
kwss->keyphrases = glist_add_ptr(NULL, k);
}
/* Reinit for provided keyphrase */
if (kws_search_reinit(ps_search_base(kwss),
ps_search_dict(kwss),
ps_search_dict2pid(kwss)) < 0) {
ps_search_free(ps_search_base(kwss));
return NULL;
}
ptmr_init(&kwss->perf);
return ps_search_base(kwss);
}
void
kws_search_free(ps_search_t * search)
{
kws_search_t *kwss;
double n_speech;
gnode_t *gn;
kwss = (kws_search_t *) search;
n_speech = (double)kwss->n_tot_frame
/ cmd_ln_int32_r(ps_search_config(kwss), "-frate");
E_INFO("TOTAL kws %.2f CPU %.3f xRT\n",
kwss->perf.t_tot_cpu,
kwss->perf.t_tot_cpu / n_speech);
E_INFO("TOTAL kws %.2f wall %.3f xRT\n",
kwss->perf.t_tot_elapsed,
kwss->perf.t_tot_elapsed / n_speech);
ps_search_base_free(search);
hmm_context_free(kwss->hmmctx);
kws_detections_reset(kwss->detections);
ckd_free(kwss->detections);
ckd_free(kwss->pl_hmms);
for (gn = kwss->keyphrases; gn; gn = gnode_next(gn)) {
kws_keyphrase_t *keyphrase = gnode_ptr(gn);
ckd_free(keyphrase->hmms);
ckd_free(keyphrase->word);
ckd_free(keyphrase);
}
glist_free(kwss->keyphrases);
ckd_free(kwss);
}
int
kws_search_reinit(ps_search_t * search, dict_t * dict, dict2pid_t * d2p)
{
char **wrdptr;
char *tmp_keyphrase;
int32 wid, pronlen, in_dict;
int32 n_hmms, n_wrds;
int32 ssid, tmatid;
int i, j, p;
kws_search_t *kwss = (kws_search_t *) search;
bin_mdef_t *mdef = search->acmod->mdef;
int32 silcipid = bin_mdef_silphone(mdef);
gnode_t *gn;
/* Free old dict2pid, dict */
ps_search_base_reinit(search, dict, d2p);
/* Initialize HMM context. */
if (kwss->hmmctx)
hmm_context_free(kwss->hmmctx);
kwss->hmmctx =
hmm_context_init(bin_mdef_n_emit_state(search->acmod->mdef),
search->acmod->tmat->tp, NULL,
search->acmod->mdef->sseq);
if (kwss->hmmctx == NULL)
return -1;
/* Initialize phone loop HMMs. */
if (kwss->pl_hmms) {
for (i = 0; i < kwss->n_pl; ++i)
hmm_deinit((hmm_t *) & kwss->pl_hmms[i]);
ckd_free(kwss->pl_hmms);
}
kwss->n_pl = bin_mdef_n_ciphone(search->acmod->mdef);
kwss->pl_hmms =
(hmm_t *) ckd_calloc(kwss->n_pl, sizeof(*kwss->pl_hmms));
for (i = 0; i < kwss->n_pl; ++i) {
hmm_init(kwss->hmmctx, (hmm_t *) & kwss->pl_hmms[i],
FALSE,
bin_mdef_pid2ssid(search->acmod->mdef, i),
bin_mdef_pid2tmatid(search->acmod->mdef, i));
}
for (gn = kwss->keyphrases; gn; gn = gnode_next(gn)) {
kws_keyphrase_t *keyphrase = gnode_ptr(gn);
/* Initialize keyphrase HMMs */
tmp_keyphrase = (char *) ckd_salloc(keyphrase->word);
n_wrds = str2words(tmp_keyphrase, NULL, 0);
wrdptr = (char **) ckd_calloc(n_wrds, sizeof(*wrdptr));
str2words(tmp_keyphrase, wrdptr, n_wrds);
/* count amount of hmms */
n_hmms = 0;
in_dict = TRUE;
for (i = 0; i < n_wrds; i++) {
wid = dict_wordid(dict, wrdptr[i]);
if (wid == BAD_S3WID) {
E_ERROR("Word '%s' in phrase '%s' is missing in the dictionary\n", wrdptr[i], keyphrase->word);
in_dict = FALSE;
break;
}
pronlen = dict_pronlen(dict, wid);
n_hmms += pronlen;
}
if (!in_dict) {
ckd_free(wrdptr);
ckd_free(tmp_keyphrase);
continue;
}
/* allocate node array */
if (keyphrase->hmms)
ckd_free(keyphrase->hmms);
keyphrase->hmms = (hmm_t *) ckd_calloc(n_hmms, sizeof(hmm_t));
keyphrase->n_hmms = n_hmms;
/* fill node array */
j = 0;
for (i = 0; i < n_wrds; i++) {
wid = dict_wordid(dict, wrdptr[i]);
pronlen = dict_pronlen(dict, wid);
for (p = 0; p < pronlen; p++) {
int32 ci = dict_pron(dict, wid, p);
if (p == 0) {
/* first phone of word */
int32 rc =
pronlen > 1 ? dict_pron(dict, wid, 1) : silcipid;
ssid = dict2pid_ldiph_lc(d2p, ci, rc, silcipid);
}
else if (p == pronlen - 1) {
/* last phone of the word */
int32 lc = dict_pron(dict, wid, p - 1);
xwdssid_t *rssid = dict2pid_rssid(d2p, ci, lc);
int j = rssid->cimap[silcipid];
ssid = rssid->ssid[j];
}
else {
/* word internal phone */
ssid = dict2pid_internal(d2p, wid, p);
}
tmatid = bin_mdef_pid2tmatid(mdef, ci);
hmm_init(kwss->hmmctx, &keyphrase->hmms[j], FALSE, ssid,
tmatid);
j++;
}
}
ckd_free(wrdptr);
ckd_free(tmp_keyphrase);
}
return 0;
}
int
kws_search_start(ps_search_t * search)
{
int i;
kws_search_t *kwss = (kws_search_t *) search;
kwss->frame = 0;
kwss->bestscore = 0;
kws_detections_reset(kwss->detections);
/* Reset and enter all phone-loop HMMs. */
for (i = 0; i < kwss->n_pl; ++i) {
hmm_t *hmm = (hmm_t *) & kwss->pl_hmms[i];
hmm_clear(hmm);
hmm_enter(hmm, 0, -1, 0);
}
ptmr_reset(&kwss->perf);
ptmr_start(&kwss->perf);
return 0;
}
int
kws_search_step(ps_search_t * search, int frame_idx)
{
int16 const *senscr;
kws_search_t *kwss = (kws_search_t *) search;
acmod_t *acmod = search->acmod;
/* Activate senones */
if (!acmod->compallsen)
kws_search_sen_active(kwss);
/* Calculate senone scores for current frame. */
senscr = acmod_score(acmod, &frame_idx);
/* Evaluate hmms in phone loop and in active keyphrase nodes */
kws_search_hmm_eval(kwss, senscr);
/* Prune hmms with low prob */
kws_search_hmm_prune(kwss);
/* Do hmms transitions */
kws_search_trans(kwss);
++kwss->frame;
return 0;
}
int
kws_search_finish(ps_search_t * search)
{
kws_search_t *kwss;
int32 cf;
kwss = (kws_search_t *) search;
kwss->n_tot_frame += kwss->frame;
/* Print out some statistics. */
ptmr_stop(&kwss->perf);
/* This is the number of frames processed. */
cf = ps_search_acmod(kwss)->output_frame;
if (cf > 0) {
double n_speech = (double) (cf + 1)
/ cmd_ln_int32_r(ps_search_config(kwss), "-frate");
E_INFO("kws %.2f CPU %.3f xRT\n",
kwss->perf.t_cpu, kwss->perf.t_cpu / n_speech);
E_INFO("kws %.2f wall %.3f xRT\n",
kwss->perf.t_elapsed, kwss->perf.t_elapsed / n_speech);
}
return 0;
}
char const *
kws_search_hyp(ps_search_t * search, int32 * out_score)
{
kws_search_t *kwss = (kws_search_t *) search;
if (out_score)
*out_score = 0;
if (search->hyp_str)
ckd_free(search->hyp_str);
search->hyp_str = kws_detections_hyp_str(kwss->detections, kwss->frame, kwss->delay);
return search->hyp_str;
}
char *
kws_search_get_keyphrases(ps_search_t * search)
{
int c, len;
kws_search_t *kwss;
char* line;
gnode_t *gn;
kwss = (kws_search_t *) search;
len = 0;
for (gn = kwss->keyphrases; gn; gn = gnode_next(gn))
len += strlen(((kws_keyphrase_t *)gnode_ptr(gn))->word) + 1;
c = 0;
line = (char *)ckd_calloc(len, sizeof(*line));
for (gn = kwss->keyphrases; gn; gn = gnode_next(gn)) {
const char *str = ((kws_keyphrase_t *)gnode_ptr(gn))->word;
memcpy(&line[c], str, strlen(str));
c += strlen(str);
line[c++] = '\n';
}
line[--c] = '\0';
return line;
}
SENSCR_SHIFT
#define SENSCR_SHIFT
Shift count for senone scores.
Definition: hmm.h:73
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:1371
xwdssid_t::cimap
s3cipid_t * cimap
Index into ssid[] above for each ci phone.
Definition: dict2pid.h:75
bin_mdef_s
Definition: bin_mdef.h:117
kws_search_s::hmmctx
hmm_context_t * hmmctx
HMM context.
Definition: kws_search.h:73
kws_search_s::keyphrases
glist_t keyphrases
Keyphrases to spot.
Definition: kws_search.h:75
kws_search_s::frame
frame_idx_t frame
Frame index.
Definition: kws_search.h:78
xwdssid_t::ssid
s3ssid_t * ssid
Senone Sequence ID list for all context ciphones.
Definition: dict2pid.h:74
ps_seg_s::sf
frame_idx_t sf
Start frame.
Definition: pocketsphinx_internal.h:182
dict2pid_internal
s3ssid_t dict2pid_internal(dict2pid_t *d2p, int32 wid, int pos)
Return the senone sequence ID for the given word position.
Definition: dict2pid.c:367
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
pocketsphinx_internal.h
ps_seg_s::vt
ps_segfuncs_t * vt
V-table of seg methods.
Definition: pocketsphinx_internal.h:179
kws_search_s::n_pl
int32 n_pl
Number of CI phones.
Definition: kws_search.h:87
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
Base structure for search module.
Definition: pocketsphinx_internal.h:98
acmod_score
const int16 * acmod_score(acmod_t *acmod, int *inout_frame_idx)
Score one frame of data.
Definition: acmod.c:1106
ps_seg_s
Base structure for hypothesis segmentation iterator.
Definition: pocketsphinx_internal.h:178
bin_mdef_s::sseq
uint16 ** sseq
Unique senone sequences (2D array built at load time)
Definition: bin_mdef.h:134
dict2pid_rssid
#define dict2pid_rssid(d, ci, lc)
Access macros; not designed for arbitrary use.
Definition: dict2pid.h:115
kws_search_s::pl_hmms
hmm_t * pl_hmms
Phone loop hmms - hmms of CI phones.
Definition: kws_search.h:88
kws_seg_s::last_frame
frame_idx_t last_frame
Last frame to raise the detection.
Definition: kws_search.h:57
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:1415
BAD_S3WID
#define BAD_S3WID
Dictionary word id.
Definition: s3types.h:90
kws_seg_s::base
ps_seg_t base
Base structure.
Definition: kws_search.h:55
ps_seg_s::word
const char * word
Word string (pointer into dictionary hash)
Definition: pocketsphinx_internal.h:181
acmod_activate_hmm
void acmod_activate_hmm(acmod_t *acmod, hmm_t *hmm)
Activate senones associated with an HMM.
Definition: acmod.c:1213
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
dict2pid_t
Building composite triphone (as well as word internal triphones) with the dictionary.
Definition: dict2pid.h:84
ps_seg_s::lscr
int32 lscr
Language model score.
Definition: pocketsphinx_internal.h:185
acmod_s::mdef
bin_mdef_t * mdef
Model definition.
Definition: acmod.h:159
ps_seg_s::search
ps_search_t * search
Search object from whence this came.
Definition: pocketsphinx_internal.h:180
kws_search_s::perf
ptmr_t perf
Performance counter.
Definition: kws_search.h:90
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
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
ps_search_s::hyp_str
char * hyp_str
Current hypothesis string.
Definition: pocketsphinx_internal.h:109
ps_seg_s::prob
int32 prob
Log posterior probability.
Definition: pocketsphinx_internal.h:186
kws_detections_s
Definition: kws_detections.h:57
ps_seg_s::ef
frame_idx_t ef
End frame.
Definition: pocketsphinx_internal.h:183
kws_seg_s::detection
gnode_t * detection
Keyphrase detection correspondent to segment.
Definition: kws_search.h:56
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:56
kws_search_s::delay
int32 delay
Delay to wait for best detection score.
Definition: kws_search.h:85
acmod_s::compallsen
uint8 compallsen
Compute all senones?
Definition: acmod.h:188
ps_search_base_free
void ps_search_base_free(ps_search_t *search)
Free search.
Definition: pocketsphinx.c:1402
kws_search_s::bestscore
int32 bestscore
For beam pruning.
Definition: kws_search.h:83
kws_detection_s
Definition: kws_detections.h:49
ps_searchfuncs_s
V-table for search algorithm.
Definition: pocketsphinx_internal.h:82
kws_search_s::detections
kws_detections_t * detections
Keyword spotting history.
Definition: kws_search.h:77
ps_seg_s::ascr
int32 ascr
Acoustic score.
Definition: pocketsphinx_internal.h:184
xwdssid_t
cross word triphone model structure
Definition: dict2pid.h:73
kws_search_s
Implementation of KWS search structure.
Definition: kws_search.h:70
ps_lattice_s
Word graph structure used in bestpath/nbest search.
Definition: ps_lattice_internal.h:61
acmod_s::lmath
logmath_t * lmath
Log-math computation.
Definition: acmod.h:151
hmm_context_set_senscore
#define hmm_context_set_senscore(ctx, senscr)
Change the senone score array for a context.
Definition: hmm.h:227
dict_pron
#define dict_pron(d, w, p)
The CI phones of the word w at position p.
Definition: dict.h:165
dict_t
a structure for a dictionary.
Definition: dict.h:76
hmm_context_free
void hmm_context_free(hmm_context_t *ctx)
Free an HMM context.
Definition: hmm.c:80
dict_wordid
POCKETSPHINX_EXPORT s3wid_t dict_wordid(dict_t *d, const char *word)
Return word id for given word string if present.
Definition: dict.c:399
hmm_vit_eval
int32 hmm_vit_eval(hmm_t *hmm)
Viterbi evaluation of given HMM.
Definition: hmm.c:789
kws_search_s::def_threshold
int32 def_threshold
default threshold for p(hyp)/p(altern) ratio
Definition: kws_search.h:84
acmod_clear_active
void acmod_clear_active(acmod_t *acmod)
Clear set of active senones.
Definition: acmod.c:1197
kws_search_s::plp
int32 plp
Phone loop probability.
Definition: kws_search.h:82
kws_seg_s
Segmentation "iterator" for KWS history.
Definition: kws_search.h:54
BETTER_THAN
#define BETTER_THAN
Is one score better than another?
Definition: hmm.h:95
acmod_s
Acoustic model structure.
Definition: acmod.h:148
ps_segfuncs_s
Definition: pocketsphinx_internal.h:170
kws_keyphrase_s
Definition: kws_search.h:60
ps_seg_s::lwf
float32 lwf
Language weight factor (for second-pass searches)
Definition: pocketsphinx_internal.h:191
acmod_s::tmat
tmat_t * tmat
Transition matrices.
Definition: acmod.h:160
ps_search_s::acmod
acmod_t * acmod
Acoustic model.
Definition: pocketsphinx_internal.h:106
WORST_SCORE
#define WORST_SCORE
Large "bad" score.
Definition: hmm.h:84