43 #include <sphinxbase/err.h>
44 #include <sphinxbase/ckd_alloc.h>
45 #include <sphinxbase/strfuncs.h>
46 #include <sphinxbase/pio.h>
47 #include <sphinxbase/cmd_ln.h>
50 #include "kws_search.h"
53 #define hmm_is_active(hmm) ((hmm)->frame > 0)
54 #define kws_nth_hmm(keyphrase,n) (&((keyphrase)->hmms[n]))
86 itor->
base.
word = detection->keyphrase;
87 itor->
base.
sf = detection->sf;
88 itor->
base.
ef = detection->ef;
99 gnode_t *detect_head = gnode_next(itor->
detection);
101 detect_head = gnode_next(detect_head);
124 gnode_t *detect_head = kwss->
detections->detect_list;
127 detect_head = gnode_next(detect_head);
132 itor = (
kws_seg_t *)ckd_calloc(1,
sizeof(*itor));
133 itor->
base.
vt = &kws_segfuncs;
165 for (i = 0; i < kwss->
n_pl; i++)
169 for (gn = kwss->
keyphrases; gn; gn = gnode_next(gn)) {
171 for (i = 0; i < keyphrase->n_hmms; i++) {
172 if (hmm_is_active(kws_nth_hmm(keyphrase, i)))
183 kws_search_hmm_eval(
kws_search_t * kwss, int16
const *senscr)
192 for (i = 0; i < kwss->
n_pl; ++i) {
201 for (gn = kwss->
keyphrases; gn; gn = gnode_next(gn)) {
203 for (i = 0; i < keyphrase->n_hmms; i++) {
204 hmm_t *hmm = kws_nth_hmm(keyphrase, i);
206 if (hmm_is_active(hmm)) {
230 for (gn = kwss->
keyphrases; gn; gn = gnode_next(gn)) {
232 for (i = 0; i < keyphrase->n_hmms; i++) {
233 hmm_t *hmm = kws_nth_hmm(keyphrase, i);
234 if (hmm_is_active(hmm) && hmm_bestscore(hmm) < thresh)
247 hmm_t *pl_best_hmm = NULL;
253 for (i = 0; i < kwss->
n_pl; i++)
255 best_out_score = hmm_out_score(&kwss->
pl_hmms[i]);
256 pl_best_hmm = &kwss->
pl_hmms[i];
264 for (gn = kwss->
keyphrases; gn; gn = gnode_next(gn)) {
268 if (keyphrase->n_hmms < 1)
271 last_hmm = kws_nth_hmm(keyphrase, keyphrase->n_hmms - 1);
273 if (hmm_is_active(last_hmm)
276 if (hmm_out_score(last_hmm) - hmm_out_score(pl_best_hmm)
277 >= keyphrase->threshold) {
279 int32 prob = hmm_out_score(last_hmm) - hmm_out_score(pl_best_hmm) - KWS_MAX;
280 kws_detections_add(kwss->
detections, keyphrase->word,
281 hmm_out_history(last_hmm),
283 hmm_out_score(last_hmm));
289 for (i = 0; i < kwss->
n_pl; i++) {
291 hmm_in_score(&kwss->
pl_hmms[i])) {
293 hmm_out_score(pl_best_hmm) + kwss->
plp,
294 hmm_out_history(pl_best_hmm), kwss->
frame + 1);
299 for (gn = kwss->
keyphrases; gn; gn = gnode_next(gn)) {
302 if (keyphrase->n_hmms < 1)
305 for (i = keyphrase->n_hmms - 1; i > 0; i--) {
306 hmm_t *pred_hmm = kws_nth_hmm(keyphrase, i - 1);
307 hmm_t *hmm = kws_nth_hmm(keyphrase, i);
309 if (hmm_is_active(pred_hmm)) {
310 if (!hmm_is_active(hmm)
314 hmm_out_history(pred_hmm), kwss->
frame + 1);
320 hmm_in_score(kws_nth_hmm(keyphrase, 0)))
321 hmm_enter(kws_nth_hmm(keyphrase, 0), hmm_out_score(pl_best_hmm),
327 kws_search_read_list(
kws_search_t *kwss,
const char* keyfile)
333 if ((list_file = fopen(keyfile,
"r")) == NULL) {
334 E_ERROR_SYSTEM(
"Failed to open keyphrase file '%s'", keyfile);
341 for (li = lineiter_start_clean(list_file); li; li = lineiter_next(li)) {
351 end = strlen(line) - 1;
353 if (line[end] ==
'/') {
354 while (line[begin] !=
'/' && begin > 0)
358 keyphrase->threshold = (int32) logmath_log(kwss->base.
acmod->
lmath, atof_c(line + begin + 1))
364 keyphrase->word = ckd_salloc(line);
374 kws_search_init(
const char *name,
375 const char *keyphrase,
381 ps_search_init(ps_search_base(kwss), &kws_funcs, PS_SEARCH_TYPE_KWS, name, config, acmod, dict,
387 (int32) logmath_log(acmod->
lmath,
388 cmd_ln_float64_r(config,
392 (int32) logmath_log(acmod->
lmath,
393 cmd_ln_float32_r(config,
398 (int32) logmath_log(acmod->
lmath,
399 cmd_ln_float64_r(config,
400 "-kws_threshold")) >>
403 kwss->
delay = (int32) cmd_ln_int32_r(config,
"-kws_delay");
405 E_INFO(
"KWS(beam: %d, plp: %d, default threshold %d, delay %d)\n",
409 if (kws_search_read_list(kwss, keyfile) < 0) {
410 E_ERROR(
"Failed to create kws search\n");
411 kws_search_free(ps_search_base(kwss));
417 k->word = ckd_salloc(keyphrase);
422 if (kws_search_reinit(ps_search_base(kwss),
423 ps_search_dict(kwss),
424 ps_search_dict2pid(kwss)) < 0) {
425 ps_search_free(ps_search_base(kwss));
429 ptmr_init(&kwss->
perf);
431 return ps_search_base(kwss);
443 n_speech = (double)kwss->n_tot_frame
444 / cmd_ln_int32_r(ps_search_config(kwss),
"-frate");
446 E_INFO(
"TOTAL kws %.2f CPU %.3f xRT\n",
447 kwss->
perf.t_tot_cpu,
448 kwss->
perf.t_tot_cpu / n_speech);
449 E_INFO(
"TOTAL kws %.2f wall %.3f xRT\n",
450 kwss->
perf.t_tot_elapsed,
451 kwss->
perf.t_tot_elapsed / n_speech);
460 for (gn = kwss->
keyphrases; gn; gn = gnode_next(gn)) {
462 ckd_free(keyphrase->hmms);
463 ckd_free(keyphrase->word);
475 int32 wid, pronlen, in_dict;
476 int32 n_hmms, n_wrds;
481 int32 silcipid = bin_mdef_silphone(mdef);
499 for (i = 0; i < kwss->
n_pl; ++i)
506 for (i = 0; i < kwss->
n_pl; ++i) {
509 bin_mdef_pid2ssid(search->
acmod->
mdef, i),
510 bin_mdef_pid2tmatid(search->
acmod->
mdef, i));
513 for (gn = kwss->
keyphrases; gn; gn = gnode_next(gn)) {
517 tmp_keyphrase = (
char *) ckd_salloc(keyphrase->word);
518 n_wrds = str2words(tmp_keyphrase, NULL, 0);
519 wrdptr = (
char **) ckd_calloc(n_wrds,
sizeof(*wrdptr));
520 str2words(tmp_keyphrase, wrdptr, n_wrds);
525 for (i = 0; i < n_wrds; i++) {
528 E_ERROR(
"Word '%s' in phrase '%s' is missing in the dictionary\n", wrdptr[i], keyphrase->word);
532 pronlen = dict_pronlen(dict, wid);
538 ckd_free(tmp_keyphrase);
544 ckd_free(keyphrase->hmms);
545 keyphrase->hmms = (
hmm_t *) ckd_calloc(n_hmms,
sizeof(
hmm_t));
546 keyphrase->n_hmms = n_hmms;
550 for (i = 0; i < n_wrds; i++) {
552 pronlen = dict_pronlen(dict, wid);
553 for (p = 0; p < pronlen; p++) {
558 pronlen > 1 ?
dict_pron(dict, wid, 1) : silcipid;
559 ssid = dict2pid_ldiph_lc(d2p, ci, rc, silcipid);
561 else if (p == pronlen - 1) {
565 int j = rssid->
cimap[silcipid];
566 ssid = rssid->
ssid[j];
572 tmatid = bin_mdef_pid2tmatid(mdef, ci);
580 ckd_free(tmp_keyphrase);
599 for (i = 0; i < kwss->
n_pl; ++i) {
605 ptmr_reset(&kwss->
perf);
606 ptmr_start(&kwss->
perf);
612 kws_search_step(
ps_search_t * search,
int frame_idx)
620 kws_search_sen_active(kwss);
626 kws_search_hmm_eval(kwss, senscr);
629 kws_search_hmm_prune(kwss);
632 kws_search_trans(kwss);
646 kwss->n_tot_frame += kwss->
frame;
649 ptmr_stop(&kwss->
perf);
651 cf = ps_search_acmod(kwss)->output_frame;
653 double n_speech = (double) (cf + 1)
654 / cmd_ln_int32_r(ps_search_config(kwss),
"-frate");
655 E_INFO(
"kws %.2f CPU %.3f xRT\n",
656 kwss->
perf.t_cpu, kwss->
perf.t_cpu / n_speech);
657 E_INFO(
"kws %.2f wall %.3f xRT\n",
658 kwss->
perf.t_elapsed, kwss->
perf.t_elapsed / n_speech);
665 kws_search_hyp(
ps_search_t * search, int32 * out_score)
689 for (gn = kwss->
keyphrases; gn; gn = gnode_next(gn))
693 line = (
char *)ckd_calloc(len,
sizeof(*line));
694 for (gn = kwss->
keyphrases; gn; gn = gnode_next(gn)) {
696 memcpy(&line[c], str, strlen(str));