PocketSphinx  5prealpha
acmod.c
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* ====================================================================
3  * Copyright (c) 2008 Carnegie Mellon University. All rights
4  * reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in
15  * the documentation and/or other materials provided with the
16  * distribution.
17  *
18  * This work was supported in part by funding from the Defense Advanced
19  * Research Projects Agency and the National Science Foundation of the
20  * United States of America, and the CMU Sphinx Speech Consortium.
21  *
22  * THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY ``AS IS'' AND
23  * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
24  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY
26  * NOR ITS EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  *
34  * ====================================================================
35  *
36  */
37 
38 
44 /* System headers. */
45 #include <assert.h>
46 #include <string.h>
47 #include <math.h>
48 
49 /* SphinxBase headers. */
50 #include <sphinxbase/prim_type.h>
51 #include <sphinxbase/err.h>
52 #include <sphinxbase/cmd_ln.h>
53 #include <sphinxbase/strfuncs.h>
54 #include <sphinxbase/byteorder.h>
55 #include <sphinxbase/feat.h>
56 #include <sphinxbase/bio.h>
57 
58 /* Local headers. */
59 #include "cmdln_macro.h"
60 #include "acmod.h"
61 #include "s2_semi_mgau.h"
62 #include "ptm_mgau.h"
63 #include "ms_mgau.h"
64 
65 #ifndef WORDS_BIGENDIAN
66 #define WORDS_BIGENDIAN 1
67 #endif
68 
69 static int32 acmod_process_mfcbuf(acmod_t *acmod);
70 
71 static int
72 acmod_init_am(acmod_t *acmod)
73 {
74  char const *mdeffn, *tmatfn, *mllrfn, *hmmdir;
75 
76  /* Read model definition. */
77  if ((mdeffn = cmd_ln_str_r(acmod->config, "-mdef")) == NULL) {
78  if ((hmmdir = cmd_ln_str_r(acmod->config, "-hmm")) == NULL)
79  E_ERROR("Acoustic model definition is not specified either "
80  "with -mdef option or with -hmm\n");
81  else
82  E_ERROR("Folder '%s' does not contain acoustic model "
83  "definition 'mdef'\n", hmmdir);
84 
85  return -1;
86  }
87 
88  if ((acmod->mdef = bin_mdef_read(acmod->config, mdeffn)) == NULL) {
89  E_ERROR("Failed to read acoustic model definition from %s\n", mdeffn);
90  return -1;
91  }
92 
93  /* Read transition matrices. */
94  if ((tmatfn = cmd_ln_str_r(acmod->config, "-tmat")) == NULL) {
95  E_ERROR("No tmat file specified\n");
96  return -1;
97  }
98  acmod->tmat = tmat_init(tmatfn, acmod->lmath,
99  cmd_ln_float32_r(acmod->config, "-tmatfloor"),
100  TRUE);
101 
102  /* Read the acoustic models. */
103  if ((cmd_ln_str_r(acmod->config, "-mean") == NULL)
104  || (cmd_ln_str_r(acmod->config, "-var") == NULL)
105  || (cmd_ln_str_r(acmod->config, "-tmat") == NULL)) {
106  E_ERROR("No mean/var/tmat files specified\n");
107  return -1;
108  }
109 
110  if (cmd_ln_str_r(acmod->config, "-senmgau")) {
111  E_INFO("Using general multi-stream GMM computation\n");
112  acmod->mgau = ms_mgau_init(acmod, acmod->lmath, acmod->mdef);
113  if (acmod->mgau == NULL)
114  return -1;
115  }
116  else {
117  E_INFO("Attempting to use PTM computation module\n");
118  if ((acmod->mgau = ptm_mgau_init(acmod, acmod->mdef)) == NULL) {
119  E_INFO("Attempting to use semi-continuous computation module\n");
120  if ((acmod->mgau = s2_semi_mgau_init(acmod)) == NULL) {
121  E_INFO("Falling back to general multi-stream GMM computation\n");
122  acmod->mgau = ms_mgau_init(acmod, acmod->lmath, acmod->mdef);
123  if (acmod->mgau == NULL)
124  return -1;
125  }
126  }
127  }
128 
129  /* If there is an MLLR transform, apply it. */
130  if ((mllrfn = cmd_ln_str_r(acmod->config, "-mllr"))) {
131  ps_mllr_t *mllr = ps_mllr_read(mllrfn);
132  if (mllr == NULL)
133  return -1;
134  acmod_update_mllr(acmod, mllr);
135  }
136 
137  return 0;
138 }
139 
140 static int
141 acmod_init_feat(acmod_t *acmod)
142 {
143  acmod->fcb =
144  feat_init(cmd_ln_str_r(acmod->config, "-feat"),
145  cmn_type_from_str(cmd_ln_str_r(acmod->config,"-cmn")),
146  cmd_ln_boolean_r(acmod->config, "-varnorm"),
147  agc_type_from_str(cmd_ln_str_r(acmod->config, "-agc")),
148  1, cmd_ln_int32_r(acmod->config, "-ceplen"));
149  if (acmod->fcb == NULL)
150  return -1;
151 
152  if (cmd_ln_str_r(acmod->config, "-lda")) {
153  E_INFO("Reading linear feature transformation from %s\n",
154  cmd_ln_str_r(acmod->config, "-lda"));
155  if (feat_read_lda(acmod->fcb,
156  cmd_ln_str_r(acmod->config, "-lda"),
157  cmd_ln_int32_r(acmod->config, "-ldadim")) < 0)
158  return -1;
159  }
160 
161  if (cmd_ln_str_r(acmod->config, "-svspec")) {
162  int32 **subvecs;
163  E_INFO("Using subvector specification %s\n",
164  cmd_ln_str_r(acmod->config, "-svspec"));
165  if ((subvecs = parse_subvecs(cmd_ln_str_r(acmod->config, "-svspec"))) == NULL)
166  return -1;
167  if ((feat_set_subvecs(acmod->fcb, subvecs)) < 0)
168  return -1;
169  }
170 
171  if (cmd_ln_exists_r(acmod->config, "-agcthresh")
172  && 0 != strcmp(cmd_ln_str_r(acmod->config, "-agc"), "none")) {
173  agc_set_threshold(acmod->fcb->agc_struct,
174  cmd_ln_float32_r(acmod->config, "-agcthresh"));
175  }
176 
177  if (acmod->fcb->cmn_struct
178  && cmd_ln_exists_r(acmod->config, "-cmninit")) {
179  char *c, *cc, *vallist;
180  int32 nvals;
181 
182  vallist = ckd_salloc(cmd_ln_str_r(acmod->config, "-cmninit"));
183  c = vallist;
184  nvals = 0;
185  while (nvals < acmod->fcb->cmn_struct->veclen
186  && (cc = strchr(c, ',')) != NULL) {
187  *cc = '\0';
188  acmod->fcb->cmn_struct->cmn_mean[nvals] = FLOAT2MFCC(atof_c(c));
189  c = cc + 1;
190  ++nvals;
191  }
192  if (nvals < acmod->fcb->cmn_struct->veclen && *c != '\0') {
193  acmod->fcb->cmn_struct->cmn_mean[nvals] = FLOAT2MFCC(atof_c(c));
194  }
195  ckd_free(vallist);
196  }
197  return 0;
198 }
199 
200 int
201 acmod_fe_mismatch(acmod_t *acmod, fe_t *fe)
202 {
203  /* Output vector dimension needs to be the same. */
204  if (cmd_ln_int32_r(acmod->config, "-ceplen") != fe_get_output_size(fe)) {
205  E_ERROR("Configured feature length %d doesn't match feature "
206  "extraction output size %d\n",
207  cmd_ln_int32_r(acmod->config, "-ceplen"),
208  fe_get_output_size(fe));
209  return TRUE;
210  }
211  /* Feature parameters need to be the same. */
212  /* ... */
213  return FALSE;
214 }
215 
216 int
217 acmod_feat_mismatch(acmod_t *acmod, feat_t *fcb)
218 {
219  /* Feature type needs to be the same. */
220  if (0 != strcmp(cmd_ln_str_r(acmod->config, "-feat"), feat_name(fcb)))
221  return TRUE;
222  /* Input vector dimension needs to be the same. */
223  if (cmd_ln_int32_r(acmod->config, "-ceplen") != feat_cepsize(fcb))
224  return TRUE;
225  /* FIXME: Need to check LDA and stuff too. */
226  return FALSE;
227 }
228 
229 acmod_t *
230 acmod_init(cmd_ln_t *config, logmath_t *lmath, fe_t *fe, feat_t *fcb)
231 {
232  acmod_t *acmod;
233 
234  acmod = ckd_calloc(1, sizeof(*acmod));
235  acmod->config = cmd_ln_retain(config);
236  acmod->lmath = lmath;
237  acmod->state = ACMOD_IDLE;
238 
239  /* Initialize feature computation. */
240  if (fe) {
241  if (acmod_fe_mismatch(acmod, fe))
242  goto error_out;
243  fe_retain(fe);
244  acmod->fe = fe;
245  }
246  else {
247  /* Initialize a new front end. */
248  acmod->fe = fe_init_auto_r(config);
249  if (acmod->fe == NULL)
250  goto error_out;
251  if (acmod_fe_mismatch(acmod, acmod->fe))
252  goto error_out;
253  }
254  if (fcb) {
255  if (acmod_feat_mismatch(acmod, fcb))
256  goto error_out;
257  feat_retain(fcb);
258  acmod->fcb = fcb;
259  }
260  else {
261  /* Initialize a new fcb. */
262  if (acmod_init_feat(acmod) < 0)
263  goto error_out;
264  }
265 
266  /* Load acoustic model parameters. */
267  if (acmod_init_am(acmod) < 0)
268  goto error_out;
269 
270 
271  /* The MFCC buffer needs to be at least as large as the dynamic
272  * feature window. */
273  acmod->n_mfc_alloc = acmod->fcb->window_size * 2 + 1;
274  acmod->mfc_buf = (mfcc_t **)
275  ckd_calloc_2d(acmod->n_mfc_alloc, acmod->fcb->cepsize,
276  sizeof(**acmod->mfc_buf));
277 
278  /* Feature buffer has to be at least as large as MFCC buffer. */
279  acmod->n_feat_alloc = acmod->n_mfc_alloc + cmd_ln_int32_r(config, "-pl_window");
280  acmod->feat_buf = feat_array_alloc(acmod->fcb, acmod->n_feat_alloc);
281  acmod->framepos = ckd_calloc(acmod->n_feat_alloc, sizeof(*acmod->framepos));
282 
283  acmod->utt_start_frame = 0;
284 
285  /* Senone computation stuff. */
286  acmod->senone_scores = ckd_calloc(bin_mdef_n_sen(acmod->mdef),
287  sizeof(*acmod->senone_scores));
288  acmod->senone_active_vec = bitvec_alloc(bin_mdef_n_sen(acmod->mdef));
289  acmod->senone_active = ckd_calloc(bin_mdef_n_sen(acmod->mdef),
290  sizeof(*acmod->senone_active));
291  acmod->log_zero = logmath_get_zero(acmod->lmath);
292  acmod->compallsen = cmd_ln_boolean_r(config, "-compallsen");
293  return acmod;
294 
295 error_out:
296  acmod_free(acmod);
297  return NULL;
298 }
299 
300 void
302 {
303  if (acmod == NULL)
304  return;
305 
306  feat_free(acmod->fcb);
307  fe_free(acmod->fe);
308  cmd_ln_free_r(acmod->config);
309 
310  if (acmod->mfc_buf)
311  ckd_free_2d((void **)acmod->mfc_buf);
312  if (acmod->feat_buf)
313  feat_array_free(acmod->feat_buf);
314 
315  if (acmod->mfcfh)
316  fclose(acmod->mfcfh);
317  if (acmod->rawfh)
318  fclose(acmod->rawfh);
319  if (acmod->senfh)
320  fclose(acmod->senfh);
321 
322  ckd_free(acmod->framepos);
323  ckd_free(acmod->senone_scores);
324  ckd_free(acmod->senone_active_vec);
325  ckd_free(acmod->senone_active);
326  ckd_free(acmod->rawdata);
327 
328  if (acmod->mdef)
329  bin_mdef_free(acmod->mdef);
330  if (acmod->tmat)
331  tmat_free(acmod->tmat);
332  if (acmod->mgau)
333  ps_mgau_free(acmod->mgau);
334  if (acmod->mllr)
335  ps_mllr_free(acmod->mllr);
336 
337  ckd_free(acmod);
338 }
339 
340 ps_mllr_t *
342 {
343  if (acmod->mllr)
344  ps_mllr_free(acmod->mllr);
345  acmod->mllr = mllr;
346  ps_mgau_transform(acmod->mgau, mllr);
347 
348  return mllr;
349 }
350 
351 int
352 acmod_write_senfh_header(acmod_t *acmod, FILE *logfh)
353 {
354  char nsenstr[64], logbasestr[64];
355 
356  sprintf(nsenstr, "%d", bin_mdef_n_sen(acmod->mdef));
357  sprintf(logbasestr, "%f", logmath_get_base(acmod->lmath));
358  return bio_writehdr(logfh,
359  "version", "0.1",
360  "mdef_file", cmd_ln_str_r(acmod->config, "-mdef"),
361  "n_sen", nsenstr,
362  "logbase", logbasestr, NULL);
363 }
364 
365 int
366 acmod_set_senfh(acmod_t *acmod, FILE *logfh)
367 {
368  if (acmod->senfh)
369  fclose(acmod->senfh);
370  acmod->senfh = logfh;
371  if (logfh == NULL)
372  return 0;
373  return acmod_write_senfh_header(acmod, logfh);
374 }
375 
376 int
377 acmod_set_mfcfh(acmod_t *acmod, FILE *logfh)
378 {
379  int rv = 0;
380 
381  if (acmod->mfcfh)
382  fclose(acmod->mfcfh);
383  acmod->mfcfh = logfh;
384  fwrite(&rv, 4, 1, acmod->mfcfh);
385  return rv;
386 }
387 
388 int
389 acmod_set_rawfh(acmod_t *acmod, FILE *logfh)
390 {
391  if (acmod->rawfh)
392  fclose(acmod->rawfh);
393  acmod->rawfh = logfh;
394  return 0;
395 }
396 
397 void
398 acmod_grow_feat_buf(acmod_t *acmod, int nfr)
399 {
400  if (nfr > MAX_N_FRAMES)
401  E_FATAL("Decoder can not process more than %d frames at once, "
402  "requested %d\n", MAX_N_FRAMES, nfr);
403 
404  acmod->feat_buf = feat_array_realloc(acmod->fcb, acmod->feat_buf,
405  acmod->n_feat_alloc, nfr);
406  acmod->framepos = ckd_realloc(acmod->framepos,
407  nfr * sizeof(*acmod->framepos));
408  acmod->n_feat_alloc = nfr;
409 }
410 
411 int
412 acmod_set_grow(acmod_t *acmod, int grow_feat)
413 {
414  int tmp = acmod->grow_feat;
415  acmod->grow_feat = grow_feat;
416 
417  /* Expand feat_buf to a reasonable size to start with. */
418  if (grow_feat && acmod->n_feat_alloc < 128)
419  acmod_grow_feat_buf(acmod, 128);
420 
421  return tmp;
422 }
423 
424 int
426 {
427  fe_start_utt(acmod->fe);
428  acmod->state = ACMOD_STARTED;
429  acmod->n_mfc_frame = 0;
430  acmod->n_feat_frame = 0;
431  acmod->mfc_outidx = 0;
432  acmod->feat_outidx = 0;
433  acmod->output_frame = 0;
434  acmod->senscr_frame = -1;
435  acmod->n_senone_active = 0;
436  acmod->mgau->frame_idx = 0;
437  acmod->rawdata_pos = 0;
438 
439  return 0;
440 }
441 
442 int
444 {
445  int32 nfr = 0;
446 
447  acmod->state = ACMOD_ENDED;
448  if (acmod->n_mfc_frame < acmod->n_mfc_alloc) {
449  int inptr;
450  /* Where to start writing them (circular buffer) */
451  inptr = (acmod->mfc_outidx + acmod->n_mfc_frame) % acmod->n_mfc_alloc;
452  /* nfr is always either zero or one. */
453  fe_end_utt(acmod->fe, acmod->mfc_buf[inptr], &nfr);
454  acmod->n_mfc_frame += nfr;
455 
456  /* Process whatever's left, and any leadout or update stats if needed. */
457  if (nfr)
458  nfr = acmod_process_mfcbuf(acmod);
459  else
460  feat_update_stats(acmod->fcb);
461  }
462  if (acmod->mfcfh) {
463  long outlen;
464  int32 rv;
465  outlen = (ftell(acmod->mfcfh) - 4) / 4;
466  if (!WORDS_BIGENDIAN)
467  SWAP_INT32(&outlen);
468  /* Try to seek and write */
469  if ((rv = fseek(acmod->mfcfh, 0, SEEK_SET)) == 0) {
470  fwrite(&outlen, 4, 1, acmod->mfcfh);
471  }
472  fclose(acmod->mfcfh);
473  acmod->mfcfh = NULL;
474  }
475  if (acmod->rawfh) {
476  fclose(acmod->rawfh);
477  acmod->rawfh = NULL;
478  }
479 
480  if (acmod->senfh) {
481  fclose(acmod->senfh);
482  acmod->senfh = NULL;
483  }
484 
485  return nfr;
486 }
487 
488 static int
489 acmod_log_mfc(acmod_t *acmod,
490  mfcc_t **cep, int n_frames)
491 {
492  int i, n;
493  int32 *ptr = (int32 *)cep[0];
494 
495  n = n_frames * feat_cepsize(acmod->fcb);
496  /* Swap bytes. */
497  if (!WORDS_BIGENDIAN) {
498  for (i = 0; i < (n * sizeof(mfcc_t)); ++i) {
499  SWAP_INT32(ptr + i);
500  }
501  }
502  /* Write features. */
503  if (fwrite(cep[0], sizeof(mfcc_t), n, acmod->mfcfh) != n) {
504  E_ERROR_SYSTEM("Failed to write %d values to log file", n);
505  }
506 
507  /* Swap them back. */
508  if (!WORDS_BIGENDIAN) {
509  for (i = 0; i < (n * sizeof(mfcc_t)); ++i) {
510  SWAP_INT32(ptr + i);
511  }
512  }
513  return 0;
514 }
515 
516 static int
517 acmod_process_full_cep(acmod_t *acmod,
518  mfcc_t ***inout_cep,
519  int *inout_n_frames)
520 {
521  int32 nfr;
522 
523  /* Write to log file. */
524  if (acmod->mfcfh)
525  acmod_log_mfc(acmod, *inout_cep, *inout_n_frames);
526 
527  /* Resize feat_buf to fit. */
528  if (acmod->n_feat_alloc < *inout_n_frames) {
529 
530  if (*inout_n_frames > MAX_N_FRAMES)
531  E_FATAL("Batch processing can not process more than %d frames "
532  "at once, requested %d\n", MAX_N_FRAMES, *inout_n_frames);
533 
534  feat_array_free(acmod->feat_buf);
535  acmod->feat_buf = feat_array_alloc(acmod->fcb, *inout_n_frames);
536  acmod->n_feat_alloc = *inout_n_frames;
537  acmod->n_feat_frame = 0;
538  acmod->feat_outidx = 0;
539  }
540  /* Make dynamic features. */
541  nfr = feat_s2mfc2feat_live(acmod->fcb, *inout_cep, inout_n_frames,
542  TRUE, TRUE, acmod->feat_buf);
543  acmod->n_feat_frame = nfr;
544  assert(acmod->n_feat_frame <= acmod->n_feat_alloc);
545  *inout_cep += *inout_n_frames;
546  *inout_n_frames = 0;
547 
548  return nfr;
549 }
550 
551 static int
552 acmod_process_full_raw(acmod_t *acmod,
553  int16 const **inout_raw,
554  size_t *inout_n_samps)
555 {
556  int32 nfr, ntail;
557  mfcc_t **cepptr;
558 
559  /* Write to logging file if any. */
560  if (*inout_n_samps + acmod->rawdata_pos < acmod->rawdata_size) {
561  memcpy(acmod->rawdata + acmod->rawdata_pos, *inout_raw, *inout_n_samps * sizeof(int16));
562  acmod->rawdata_pos += *inout_n_samps;
563  }
564  if (acmod->rawfh)
565  fwrite(*inout_raw, sizeof(int16), *inout_n_samps, acmod->rawfh);
566  /* Resize mfc_buf to fit. */
567  if (fe_process_frames(acmod->fe, NULL, inout_n_samps, NULL, &nfr, NULL) < 0)
568  return -1;
569  if (acmod->n_mfc_alloc < nfr + 1) {
570  ckd_free_2d(acmod->mfc_buf);
571  acmod->mfc_buf = ckd_calloc_2d(nfr + 1, fe_get_output_size(acmod->fe),
572  sizeof(**acmod->mfc_buf));
573  acmod->n_mfc_alloc = nfr + 1;
574  }
575  acmod->n_mfc_frame = 0;
576  acmod->mfc_outidx = 0;
577  fe_start_utt(acmod->fe);
578  if (fe_process_frames(acmod->fe, inout_raw, inout_n_samps,
579  acmod->mfc_buf, &nfr, NULL) < 0)
580  return -1;
581  fe_end_utt(acmod->fe, acmod->mfc_buf[nfr], &ntail);
582  nfr += ntail;
583 
584  cepptr = acmod->mfc_buf;
585  nfr = acmod_process_full_cep(acmod, &cepptr, &nfr);
586  acmod->n_mfc_frame = 0;
587  return nfr;
588 }
589 
593 static int32
594 acmod_process_mfcbuf(acmod_t *acmod)
595 {
596  mfcc_t **mfcptr;
597  int32 ncep;
598 
599  ncep = acmod->n_mfc_frame;
600  /* Also do this in two parts because of the circular mfc_buf. */
601  if (acmod->mfc_outidx + ncep > acmod->n_mfc_alloc) {
602  int32 ncep1 = acmod->n_mfc_alloc - acmod->mfc_outidx;
603  int saved_state = acmod->state;
604 
605  /* Make sure we don't end the utterance here. */
606  if (acmod->state == ACMOD_ENDED)
607  acmod->state = ACMOD_PROCESSING;
608  mfcptr = acmod->mfc_buf + acmod->mfc_outidx;
609  ncep1 = acmod_process_cep(acmod, &mfcptr, &ncep1, FALSE);
610  /* It's possible that not all available frames were filled. */
611  ncep -= ncep1;
612  acmod->n_mfc_frame -= ncep1;
613  acmod->mfc_outidx += ncep1;
614  acmod->mfc_outidx %= acmod->n_mfc_alloc;
615  /* Restore original state (could this really be the end) */
616  acmod->state = saved_state;
617  }
618  mfcptr = acmod->mfc_buf + acmod->mfc_outidx;
619  ncep = acmod_process_cep(acmod, &mfcptr, &ncep, FALSE);
620  acmod->n_mfc_frame -= ncep;
621  acmod->mfc_outidx += ncep;
622  acmod->mfc_outidx %= acmod->n_mfc_alloc;
623  return ncep;
624 }
625 
626 int
628  int16 const **inout_raw,
629  size_t *inout_n_samps,
630  int full_utt)
631 {
632  int32 ncep;
633  int32 out_frameidx;
634  int16 const *prev_audio_inptr;
635 
636  /* If this is a full utterance, process it all at once. */
637  if (full_utt)
638  return acmod_process_full_raw(acmod, inout_raw, inout_n_samps);
639 
640  /* Append MFCCs to the end of any that are previously in there
641  * (in practice, there will probably be none) */
642  if (inout_n_samps && *inout_n_samps) {
643  int inptr;
644  int32 processed_samples;
645 
646  prev_audio_inptr = *inout_raw;
647  /* Total number of frames available. */
648  ncep = acmod->n_mfc_alloc - acmod->n_mfc_frame;
649  /* Where to start writing them (circular buffer) */
650  inptr = (acmod->mfc_outidx + acmod->n_mfc_frame) % acmod->n_mfc_alloc;
651 
652  /* Write them in two (or more) parts if there is wraparound. */
653  while (inptr + ncep > acmod->n_mfc_alloc) {
654  int32 ncep1 = acmod->n_mfc_alloc - inptr;
655  if (fe_process_frames(acmod->fe, inout_raw, inout_n_samps,
656  acmod->mfc_buf + inptr, &ncep1, &out_frameidx) < 0)
657  return -1;
658 
659  if (out_frameidx > 0)
660  acmod->utt_start_frame = out_frameidx;
661 
662  processed_samples = *inout_raw - prev_audio_inptr;
663  if (processed_samples + acmod->rawdata_pos < acmod->rawdata_size) {
664  memcpy(acmod->rawdata + acmod->rawdata_pos, prev_audio_inptr, processed_samples * sizeof(int16));
665  acmod->rawdata_pos += processed_samples;
666  }
667  /* Write to logging file if any. */
668  if (acmod->rawfh) {
669  fwrite(prev_audio_inptr, sizeof(int16),
670  processed_samples,
671  acmod->rawfh);
672  }
673  prev_audio_inptr = *inout_raw;
674 
675  /* ncep1 now contains the number of frames actually
676  * processed. This is a good thing, but it means we
677  * actually still might have some room left at the end of
678  * the buffer, hence the while loop. Unfortunately it
679  * also means that in the case where we are really
680  * actually done, we need to get out totally, hence the
681  * goto. */
682  acmod->n_mfc_frame += ncep1;
683  ncep -= ncep1;
684  inptr += ncep1;
685  inptr %= acmod->n_mfc_alloc;
686  if (ncep1 == 0)
687  goto alldone;
688  }
689 
690  assert(inptr + ncep <= acmod->n_mfc_alloc);
691  if (fe_process_frames(acmod->fe, inout_raw, inout_n_samps,
692  acmod->mfc_buf + inptr, &ncep, &out_frameidx) < 0)
693  return -1;
694 
695  if (out_frameidx > 0)
696  acmod->utt_start_frame = out_frameidx;
697 
698 
699  processed_samples = *inout_raw - prev_audio_inptr;
700  if (processed_samples + acmod->rawdata_pos < acmod->rawdata_size) {
701  memcpy(acmod->rawdata + acmod->rawdata_pos, prev_audio_inptr, processed_samples * sizeof(int16));
702  acmod->rawdata_pos += processed_samples;
703  }
704  if (acmod->rawfh) {
705  fwrite(prev_audio_inptr, sizeof(int16),
706  processed_samples, acmod->rawfh);
707  }
708  prev_audio_inptr = *inout_raw;
709  acmod->n_mfc_frame += ncep;
710  alldone:
711  ;
712  }
713 
714  /* Hand things off to acmod_process_cep. */
715  return acmod_process_mfcbuf(acmod);
716 }
717 
718 int
720  mfcc_t ***inout_cep,
721  int *inout_n_frames,
722  int full_utt)
723 {
724  int32 nfeat, ncep, inptr;
725  int orig_n_frames;
726 
727  /* If this is a full utterance, process it all at once. */
728  if (full_utt)
729  return acmod_process_full_cep(acmod, inout_cep, inout_n_frames);
730 
731  /* Write to log file. */
732  if (acmod->mfcfh)
733  acmod_log_mfc(acmod, *inout_cep, *inout_n_frames);
734 
735  /* Maximum number of frames we're going to generate. */
736  orig_n_frames = ncep = nfeat = *inout_n_frames;
737 
738  /* FIXME: This behaviour isn't guaranteed... */
739  if (acmod->state == ACMOD_ENDED)
740  nfeat += feat_window_size(acmod->fcb);
741  else if (acmod->state == ACMOD_STARTED)
742  nfeat -= feat_window_size(acmod->fcb);
743 
744  /* Clamp number of features to fit available space. */
745  if (nfeat > acmod->n_feat_alloc - acmod->n_feat_frame) {
746  /* Grow it as needed - we have to grow it at the end of an
747  * utterance because we can't return a short read there. */
748  if (acmod->grow_feat || acmod->state == ACMOD_ENDED)
749  acmod_grow_feat_buf(acmod, acmod->n_feat_alloc + nfeat);
750  else
751  ncep -= (nfeat - (acmod->n_feat_alloc - acmod->n_feat_frame));
752  }
753 
754  /* Where to start writing in the feature buffer. */
755  if (acmod->grow_feat) {
756  /* Grow to avoid wraparound if grow_feat == TRUE. */
757  inptr = acmod->feat_outidx + acmod->n_feat_frame;
758  while (inptr + nfeat >= acmod->n_feat_alloc)
759  acmod_grow_feat_buf(acmod, acmod->n_feat_alloc * 2);
760  }
761  else {
762  inptr = (acmod->feat_outidx + acmod->n_feat_frame) % acmod->n_feat_alloc;
763  }
764 
765 
766  /* FIXME: we can't split the last frame drop properly to be on the bounary,
767  * so just return
768  */
769  if (inptr + nfeat > acmod->n_feat_alloc && acmod->state == ACMOD_ENDED) {
770  *inout_n_frames -= ncep;
771  *inout_cep += ncep;
772  return 0;
773  }
774 
775  /* Write them in two parts if there is wraparound. */
776  if (inptr + nfeat > acmod->n_feat_alloc) {
777  int32 ncep1 = acmod->n_feat_alloc - inptr;
778 
779  /* Make sure we don't end the utterance here. */
780  nfeat = feat_s2mfc2feat_live(acmod->fcb, *inout_cep,
781  &ncep1,
782  (acmod->state == ACMOD_STARTED),
783  FALSE,
784  acmod->feat_buf + inptr);
785  if (nfeat < 0)
786  return -1;
787  /* Move the output feature pointer forward. */
788  acmod->n_feat_frame += nfeat;
789  assert(acmod->n_feat_frame <= acmod->n_feat_alloc);
790  inptr += nfeat;
791  inptr %= acmod->n_feat_alloc;
792  /* Move the input feature pointers forward. */
793  *inout_n_frames -= ncep1;
794  *inout_cep += ncep1;
795  ncep -= ncep1;
796  }
797 
798  nfeat = feat_s2mfc2feat_live(acmod->fcb, *inout_cep,
799  &ncep,
800  (acmod->state == ACMOD_STARTED),
801  (acmod->state == ACMOD_ENDED),
802  acmod->feat_buf + inptr);
803  if (nfeat < 0)
804  return -1;
805  acmod->n_feat_frame += nfeat;
806  assert(acmod->n_feat_frame <= acmod->n_feat_alloc);
807  /* Move the input feature pointers forward. */
808  *inout_n_frames -= ncep;
809  *inout_cep += ncep;
810  if (acmod->state == ACMOD_STARTED)
811  acmod->state = ACMOD_PROCESSING;
812 
813  return orig_n_frames - *inout_n_frames;
814 }
815 
816 int
818  mfcc_t **feat)
819 {
820  int i, inptr;
821 
822  if (acmod->n_feat_frame == acmod->n_feat_alloc) {
823  if (acmod->grow_feat)
824  acmod_grow_feat_buf(acmod, acmod->n_feat_alloc * 2);
825  else
826  return 0;
827  }
828 
829  if (acmod->grow_feat) {
830  /* Grow to avoid wraparound if grow_feat == TRUE. */
831  inptr = acmod->feat_outidx + acmod->n_feat_frame;
832  while (inptr + 1 >= acmod->n_feat_alloc)
833  acmod_grow_feat_buf(acmod, acmod->n_feat_alloc * 2);
834  }
835  else {
836  inptr = (acmod->feat_outidx + acmod->n_feat_frame) % acmod->n_feat_alloc;
837  }
838  for (i = 0; i < feat_dimension1(acmod->fcb); ++i)
839  memcpy(acmod->feat_buf[inptr][i],
840  feat[i], feat_dimension2(acmod->fcb, i) * sizeof(**feat));
841  ++acmod->n_feat_frame;
842  assert(acmod->n_feat_frame <= acmod->n_feat_alloc);
843 
844  return 1;
845 }
846 
847 static int
848 acmod_read_senfh_header(acmod_t *acmod)
849 {
850  char **name, **val;
851  int32 swap;
852  int i;
853 
854  if (bio_readhdr(acmod->insenfh, &name, &val, &swap) < 0)
855  goto error_out;
856  for (i = 0; name[i] != NULL; ++i) {
857  if (!strcmp(name[i], "n_sen")) {
858  if (atoi(val[i]) != bin_mdef_n_sen(acmod->mdef)) {
859  E_ERROR("Number of senones in senone file (%d) does not "
860  "match mdef (%d)\n", atoi(val[i]),
861  bin_mdef_n_sen(acmod->mdef));
862  goto error_out;
863  }
864  }
865 
866  if (!strcmp(name[i], "logbase")) {
867  if (fabs(atof_c(val[i]) - logmath_get_base(acmod->lmath)) > 0.001) {
868  E_ERROR("Logbase in senone file (%f) does not match acmod "
869  "(%f)\n", atof_c(val[i]),
870  logmath_get_base(acmod->lmath));
871  goto error_out;
872  }
873  }
874  }
875  acmod->insen_swap = swap;
876  bio_hdrarg_free(name, val);
877  return 0;
878 error_out:
879  bio_hdrarg_free(name, val);
880  return -1;
881 }
882 
883 int
884 acmod_set_insenfh(acmod_t *acmod, FILE *senfh)
885 {
886  acmod->insenfh = senfh;
887  if (senfh == NULL) {
888  acmod->n_feat_frame = 0;
889  acmod->compallsen = cmd_ln_boolean_r(acmod->config, "-compallsen");
890  return 0;
891  }
892  acmod->compallsen = TRUE;
893  return acmod_read_senfh_header(acmod);
894 }
895 
896 int
898 {
899  /* If the feature buffer is circular, this is not possible. */
900  if (acmod->output_frame > acmod->n_feat_alloc) {
901  E_ERROR("Circular feature buffer cannot be rewound (output frame %d, "
902  "alloc %d)\n", acmod->output_frame, acmod->n_feat_alloc);
903  return -1;
904  }
905 
906  /* Frames consumed + frames available */
907  acmod->n_feat_frame = acmod->output_frame + acmod->n_feat_frame;
908 
909  /* Reset output pointers. */
910  acmod->feat_outidx = 0;
911  acmod->output_frame = 0;
912  acmod->senscr_frame = -1;
913  acmod->mgau->frame_idx = 0;
914 
915  return 0;
916 }
917 
918 int
920 {
921  /* Advance the output pointers. */
922  if (++acmod->feat_outidx == acmod->n_feat_alloc)
923  acmod->feat_outidx = 0;
924  --acmod->n_feat_frame;
925  ++acmod->mgau->frame_idx;
926 
927  return ++acmod->output_frame;
928 }
929 
930 int
931 acmod_write_scores(acmod_t *acmod, int n_active, uint8 const *active,
932  int16 const *senscr, FILE *senfh)
933 {
934  int16 n_active2;
935 
936  /* Uncompressed frame format:
937  *
938  * (2 bytes) n_active: Number of active senones
939  * If all senones active:
940  * (n_active * 2 bytes) scores of active senones
941  *
942  * Otherwise:
943  * (2 bytes) n_active: Number of active senones
944  * (n_active bytes) deltas to active senones
945  * (n_active * 2 bytes) scores of active senones
946  */
947  n_active2 = n_active;
948  if (fwrite(&n_active2, 2, 1, senfh) != 1)
949  goto error_out;
950  if (n_active == bin_mdef_n_sen(acmod->mdef)) {
951  if (fwrite(senscr, 2, n_active, senfh) != n_active)
952  goto error_out;
953  }
954  else {
955  int i, n;
956  if (fwrite(active, 1, n_active, senfh) != n_active)
957  goto error_out;
958  for (i = n = 0; i < n_active; ++i) {
959  n += active[i];
960  if (fwrite(senscr + n, 2, 1, senfh) != 1)
961  goto error_out;
962  }
963  }
964  return 0;
965 error_out:
966  E_ERROR_SYSTEM("Failed to write frame to senone file");
967  return -1;
968 }
969 
973 static int
974 acmod_read_scores_internal(acmod_t *acmod)
975 {
976  FILE *senfh = acmod->insenfh;
977  int16 n_active;
978  size_t rv;
979 
980  if (acmod->n_feat_frame == acmod->n_feat_alloc) {
981  if (acmod->grow_feat)
982  acmod_grow_feat_buf(acmod, acmod->n_feat_alloc * 2);
983  else
984  return 0;
985  }
986 
987  if (senfh == NULL)
988  return -1;
989 
990  if ((rv = fread(&n_active, 2, 1, senfh)) != 1)
991  goto error_out;
992 
993  acmod->n_senone_active = n_active;
994  if (acmod->n_senone_active == bin_mdef_n_sen(acmod->mdef)) {
995  if ((rv = fread(acmod->senone_scores, 2,
996  acmod->n_senone_active, senfh)) != acmod->n_senone_active)
997  goto error_out;
998  }
999  else {
1000  int i, n;
1001 
1002  if ((rv = fread(acmod->senone_active, 1,
1003  acmod->n_senone_active, senfh)) != acmod->n_senone_active)
1004  goto error_out;
1005 
1006  for (i = 0, n = 0; i < acmod->n_senone_active; ++i) {
1007  int j, sen = n + acmod->senone_active[i];
1008  for (j = n + 1; j < sen; ++j)
1009  acmod->senone_scores[j] = SENSCR_DUMMY;
1010 
1011  if ((rv = fread(acmod->senone_scores + sen, 2, 1, senfh)) != 1)
1012  goto error_out;
1013 
1014  n = sen;
1015  }
1016 
1017  n++;
1018  while (n < bin_mdef_n_sen(acmod->mdef))
1019  acmod->senone_scores[n++] = SENSCR_DUMMY;
1020  }
1021  return 1;
1022 
1023 error_out:
1024  if (ferror(senfh)) {
1025  E_ERROR_SYSTEM("Failed to read frame from senone file");
1026  return -1;
1027  }
1028  return 0;
1029 }
1030 
1031 int
1033 {
1034  int inptr, rv;
1035 
1036  if (acmod->grow_feat) {
1037  /* Grow to avoid wraparound if grow_feat == TRUE. */
1038  inptr = acmod->feat_outidx + acmod->n_feat_frame;
1039  /* Has to be +1, otherwise, next time acmod_advance() is
1040  * called, this will wrap around. */
1041  while (inptr + 1 >= acmod->n_feat_alloc)
1042  acmod_grow_feat_buf(acmod, acmod->n_feat_alloc * 2);
1043  }
1044  else {
1045  inptr = (acmod->feat_outidx + acmod->n_feat_frame) %
1046  acmod->n_feat_alloc;
1047  }
1048 
1049  if ((rv = acmod_read_scores_internal(acmod)) != 1)
1050  return rv;
1051 
1052  /* Set acmod->senscr_frame appropriately so that these scores
1053  get reused below in acmod_score(). */
1054  acmod->senscr_frame = acmod->output_frame + acmod->n_feat_frame;
1055 
1056  E_DEBUG(1,("Frame %d has %d active states\n",
1057  acmod->senscr_frame, acmod->n_senone_active));
1058 
1059  /* Increment the "feature frame counter" and record the file
1060  * position for the relevant frame in the (possibly circular)
1061  * buffer. */
1062  ++acmod->n_feat_frame;
1063  acmod->framepos[inptr] = ftell(acmod->insenfh);
1064 
1065  return 1;
1066 }
1067 
1068 static int
1069 calc_frame_idx(acmod_t *acmod, int *inout_frame_idx)
1070 {
1071  int frame_idx;
1072 
1073  /* Calculate the absolute frame index to be scored. */
1074  if (inout_frame_idx == NULL)
1075  frame_idx = acmod->output_frame;
1076  else if (*inout_frame_idx < 0)
1077  frame_idx = acmod->output_frame + 1 + *inout_frame_idx;
1078  else
1079  frame_idx = *inout_frame_idx;
1080 
1081  return frame_idx;
1082 }
1083 
1084 static int
1085 calc_feat_idx(acmod_t *acmod, int frame_idx)
1086 {
1087  int n_backfr, feat_idx;
1088 
1089  n_backfr = acmod->n_feat_alloc - acmod->n_feat_frame;
1090  if (frame_idx < 0 || acmod->output_frame - frame_idx > n_backfr) {
1091  E_ERROR("Frame %d outside queue of %d frames, %d alloc (%d > %d), "
1092  "cannot score\n", frame_idx, acmod->n_feat_frame,
1093  acmod->n_feat_alloc, acmod->output_frame - frame_idx,
1094  n_backfr);
1095  return -1;
1096  }
1097 
1098  /* Get the index in feat_buf/framepos of the frame to be scored. */
1099  feat_idx = (acmod->feat_outidx + frame_idx - acmod->output_frame) %
1100  acmod->n_feat_alloc;
1101  if (feat_idx < 0)
1102  feat_idx += acmod->n_feat_alloc;
1103 
1104  return feat_idx;
1105 }
1106 
1107 mfcc_t **
1108 acmod_get_frame(acmod_t *acmod, int *inout_frame_idx)
1109 {
1110  int frame_idx, feat_idx;
1111 
1112  /* Calculate the absolute frame index requested. */
1113  frame_idx = calc_frame_idx(acmod, inout_frame_idx);
1114 
1115  /* Calculate position of requested frame in circular buffer. */
1116  if ((feat_idx = calc_feat_idx(acmod, frame_idx)) < 0)
1117  return NULL;
1118 
1119  if (inout_frame_idx)
1120  *inout_frame_idx = frame_idx;
1121 
1122  return acmod->feat_buf[feat_idx];
1123 }
1124 
1125 int16 const *
1126 acmod_score(acmod_t *acmod, int *inout_frame_idx)
1127 {
1128  int frame_idx, feat_idx;
1129 
1130  /* Calculate the absolute frame index to be scored. */
1131  frame_idx = calc_frame_idx(acmod, inout_frame_idx);
1132 
1133  /* If all senones are being computed, or we are using a senone file,
1134  then we can reuse existing scores. */
1135  if ((acmod->compallsen || acmod->insenfh)
1136  && frame_idx == acmod->senscr_frame) {
1137  if (inout_frame_idx)
1138  *inout_frame_idx = frame_idx;
1139  return acmod->senone_scores;
1140  }
1141 
1142  /* Calculate position of requested frame in circular buffer. */
1143  if ((feat_idx = calc_feat_idx(acmod, frame_idx)) < 0)
1144  return NULL;
1145 
1146  /*
1147  * If there is an input senone file locate the appropriate frame and read
1148  * it.
1149  */
1150  if (acmod->insenfh) {
1151  fseek(acmod->insenfh, acmod->framepos[feat_idx], SEEK_SET);
1152  if (acmod_read_scores_internal(acmod) < 0)
1153  return NULL;
1154  }
1155  else {
1156  /* Build active senone list. */
1157  acmod_flags2list(acmod);
1158 
1159  /* Generate scores for the next available frame */
1160  ps_mgau_frame_eval(acmod->mgau,
1161  acmod->senone_scores,
1162  acmod->senone_active,
1163  acmod->n_senone_active,
1164  acmod->feat_buf[feat_idx],
1165  frame_idx,
1166  acmod->compallsen);
1167  }
1168 
1169  if (inout_frame_idx)
1170  *inout_frame_idx = frame_idx;
1171  acmod->senscr_frame = frame_idx;
1172 
1173  /* Dump scores to the senone dump file if one exists. */
1174  if (acmod->senfh) {
1175  if (acmod_write_scores(acmod, acmod->n_senone_active,
1176  acmod->senone_active,
1177  acmod->senone_scores,
1178  acmod->senfh) < 0)
1179  return NULL;
1180  E_DEBUG(1,("Frame %d has %d active states\n", frame_idx,
1181  acmod->n_senone_active));
1182  }
1183 
1184  return acmod->senone_scores;
1185 }
1186 
1187 int
1188 acmod_best_score(acmod_t *acmod, int *out_best_senid)
1189 {
1190  int i, best;
1191 
1192  best = SENSCR_DUMMY;
1193  if (acmod->compallsen) {
1194  for (i = 0; i < bin_mdef_n_sen(acmod->mdef); ++i) {
1195  if (acmod->senone_scores[i] < best) {
1196  best = acmod->senone_scores[i];
1197  *out_best_senid = i;
1198  }
1199  }
1200  }
1201  else {
1202  int16 *senscr;
1203  senscr = acmod->senone_scores;
1204  for (i = 0; i < acmod->n_senone_active; ++i) {
1205  senscr += acmod->senone_active[i];
1206  if (*senscr < best) {
1207  best = *senscr;
1208  *out_best_senid = i;
1209  }
1210  }
1211  }
1212  return best;
1213 }
1214 
1215 
1216 void
1218 {
1219  if (acmod->compallsen)
1220  return;
1221  bitvec_clear_all(acmod->senone_active_vec, bin_mdef_n_sen(acmod->mdef));
1222  acmod->n_senone_active = 0;
1223 }
1224 
1225 #define MPX_BITVEC_SET(a,h,i) \
1226  if (hmm_mpx_ssid(h,i) != BAD_SSID) \
1227  bitvec_set((a)->senone_active_vec, hmm_mpx_senid(h,i))
1228 #define NONMPX_BITVEC_SET(a,h,i) \
1229  bitvec_set((a)->senone_active_vec, \
1230  hmm_nonmpx_senid(h,i))
1231 
1232 void
1234 {
1235  int i;
1236 
1237  if (acmod->compallsen)
1238  return;
1239  if (hmm_is_mpx(hmm)) {
1240  switch (hmm_n_emit_state(hmm)) {
1241  case 5:
1242  MPX_BITVEC_SET(acmod, hmm, 4);
1243  MPX_BITVEC_SET(acmod, hmm, 3);
1244  case 3:
1245  MPX_BITVEC_SET(acmod, hmm, 2);
1246  MPX_BITVEC_SET(acmod, hmm, 1);
1247  MPX_BITVEC_SET(acmod, hmm, 0);
1248  break;
1249  default:
1250  for (i = 0; i < hmm_n_emit_state(hmm); ++i) {
1251  MPX_BITVEC_SET(acmod, hmm, i);
1252  }
1253  }
1254  }
1255  else {
1256  switch (hmm_n_emit_state(hmm)) {
1257  case 5:
1258  NONMPX_BITVEC_SET(acmod, hmm, 4);
1259  NONMPX_BITVEC_SET(acmod, hmm, 3);
1260  case 3:
1261  NONMPX_BITVEC_SET(acmod, hmm, 2);
1262  NONMPX_BITVEC_SET(acmod, hmm, 1);
1263  NONMPX_BITVEC_SET(acmod, hmm, 0);
1264  break;
1265  default:
1266  for (i = 0; i < hmm_n_emit_state(hmm); ++i) {
1267  NONMPX_BITVEC_SET(acmod, hmm, i);
1268  }
1269  }
1270  }
1271 }
1272 
1273 int32
1275 {
1276  int32 w, l, n, b, total_dists, total_words, extra_bits;
1277  bitvec_t *flagptr;
1278 
1279  total_dists = bin_mdef_n_sen(acmod->mdef);
1280  if (acmod->compallsen) {
1281  acmod->n_senone_active = total_dists;
1282  return total_dists;
1283  }
1284  total_words = total_dists / BITVEC_BITS;
1285  extra_bits = total_dists % BITVEC_BITS;
1286  w = n = l = 0;
1287  for (flagptr = acmod->senone_active_vec; w < total_words; ++w, ++flagptr) {
1288  if (*flagptr == 0)
1289  continue;
1290  for (b = 0; b < BITVEC_BITS; ++b) {
1291  if (*flagptr & (1UL << b)) {
1292  int32 sen = w * BITVEC_BITS + b;
1293  int32 delta = sen - l;
1294  /* Handle excessive deltas "lossily" by adding a few
1295  extra senones to bridge the gap. */
1296  while (delta > 255) {
1297  acmod->senone_active[n++] = 255;
1298  delta -= 255;
1299  }
1300  acmod->senone_active[n++] = delta;
1301  l = sen;
1302  }
1303  }
1304  }
1305 
1306  for (b = 0; b < extra_bits; ++b) {
1307  if (*flagptr & (1UL << b)) {
1308  int32 sen = w * BITVEC_BITS + b;
1309  int32 delta = sen - l;
1310  /* Handle excessive deltas "lossily" by adding a few
1311  extra senones to bridge the gap. */
1312  while (delta > 255) {
1313  acmod->senone_active[n++] = 255;
1314  delta -= 255;
1315  }
1316  acmod->senone_active[n++] = delta;
1317  l = sen;
1318  }
1319  }
1320 
1321  acmod->n_senone_active = n;
1322  E_DEBUG(1, ("acmod_flags2list: %d active in frame %d\n",
1323  acmod->n_senone_active, acmod->output_frame));
1324  return n;
1325 }
1326 
1327 int32
1329 {
1330  return acmod->utt_start_frame;
1331 }
1332 
1333 void
1335 {
1336  fe_start_stream(acmod->fe);
1337  acmod->utt_start_frame = 0;
1338 }
1339 
1340 void
1341 acmod_set_rawdata_size(acmod_t *acmod, int32 size)
1342 {
1343  assert(size >= 0);
1344  acmod->rawdata_size = size;
1345  if (acmod->rawdata_size > 0) {
1346  ckd_free(acmod->rawdata);
1347  acmod->rawdata = ckd_calloc(size, sizeof(int16));
1348  }
1349 }
1350 
1351 void
1352 acmod_get_rawdata(acmod_t *acmod, int16 **buffer, int32 *size)
1353 {
1354  if (buffer) {
1355  *buffer = acmod->rawdata;
1356  }
1357  if (size) {
1358  *size = acmod->rawdata_pos;
1359  }
1360 }
1361 
(Sphinx 3.0 specific) A module that wraps up the code of gauden and senone because they are closely r...
FILE * insenfh
Input senone score file.
Definition: acmod.h:178
void acmod_get_rawdata(acmod_t *acmod, int16 **buffer, int32 *size)
Retrieves the raw data collected during utterance decoding.
Definition: acmod.c:1352
uint8 grow_feat
Whether to grow feat_buf.
Definition: acmod.h:189
ps_mgau_t * mgau
Model parameters.
Definition: acmod.h:161
int acmod_read_scores(acmod_t *acmod)
Read one frame of scores from senone score dump file.
Definition: acmod.c:1032
Not in an utterance.
Definition: acmod.h:68
uint8 * senone_active
Array of deltas to active GMMs.
Definition: acmod.h:167
long * framepos
File positions of recent frames in senone file.
Definition: acmod.h:179
Utterance started, no data yet.
Definition: acmod.h:69
int acmod_set_insenfh(acmod_t *acmod, FILE *senfh)
Set up a senone score dump file for input.
Definition: acmod.c:884
int32 acmod_stream_offset(acmod_t *acmod)
Get the offset of the utterance start of the current stream, helpful for stream-wide timing...
Definition: acmod.c:1328
int acmod_rewind(acmod_t *acmod)
Rewind the current utterance, allowing it to be rescored.
Definition: acmod.c:897
int16 * senone_scores
GMM scores for current frame.
Definition: acmod.h:165
ps_mllr_t * acmod_update_mllr(acmod_t *acmod, ps_mllr_t *mllr)
Adapt acoustic model using a linear transform.
Definition: acmod.c:341
int acmod_process_cep(acmod_t *acmod, mfcc_t ***inout_cep, int *inout_n_frames, int full_utt)
Feed acoustic feature data into the acoustic model for scoring.
Definition: acmod.c:719
Utterance in progress.
Definition: acmod.h:70
int n_senone_active
Number of active GMMs.
Definition: acmod.h:169
An individual HMM among the HMM search space.
void acmod_set_rawdata_size(acmod_t *acmod, int32 size)
Sets the limit of the raw audio data to store.
Definition: acmod.c:1341
void acmod_start_stream(acmod_t *acmod)
Reset the current stream.
Definition: acmod.c:1334
logmath_t * lmath
Log-math computation.
Definition: acmod.h:151
fe_t * fe
Acoustic feature computation.
Definition: acmod.h:155
frame_idx_t n_mfc_frame
Number of frames active in mfc_buf.
Definition: acmod.h:196
void acmod_activate_hmm(acmod_t *acmod, hmm_t *hmm)
Activate senones associated with an HMM.
Definition: acmod.c:1233
Utterance ended, still buffering.
Definition: acmod.h:71
FILE * rawfh
File for writing raw audio data.
Definition: acmod.h:175
mfcc_t ** mfc_buf
Temporary buffer of acoustic features.
Definition: acmod.h:173
frame_idx_t utt_start_frame
Index of the utterance start in the stream, all timings are relative to that.
Definition: acmod.h:192
void tmat_free(tmat_t *t)
RAH, add code to remove memory allocated by tmat_init.
Definition: tmat.c:332
frame_idx_t n_feat_alloc
Number of frames allocated in feat_buf.
Definition: acmod.h:198
mfcc_t *** feat_buf
Temporary buffer of dynamic features.
Definition: acmod.h:174
tmat_t * tmat_init(char const *tmatfile, logmath_t *lmath, float64 tpfloor, int32 breport)
Initialize transition matrix.
Definition: tmat.c:191
int acmod_set_senfh(acmod_t *acmod, FILE *logfh)
Start logging senone scores to a filehandle.
Definition: acmod.c:366
#define MAX_N_FRAMES
Maximum number of frames in index, should be in sync with above.
Definition: hmm.h:69
int acmod_set_rawfh(acmod_t *acmod, FILE *logfh)
Start logging raw audio to a filehandle.
Definition: acmod.c:389
ps_mllr_t * mllr
Speaker transformation.
Definition: acmod.h:162
Fast phonetically-tied mixture evaluation.
POCKETSPHINX_EXPORT ps_mllr_t * ps_mllr_read(char const *file)
Read a speaker-adaptive linear transform from a file.
Definition: ps_mllr.c:52
uint8 compallsen
Compute all senones?
Definition: acmod.h:188
POCKETSPHINX_EXPORT bin_mdef_t * bin_mdef_read(cmd_ln_t *config, const char *filename)
Read a binary mdef from a file.
Definition: bin_mdef.c:323
int acmod_process_feat(acmod_t *acmod, mfcc_t **feat)
Feed dynamic feature data into the acoustic model for scoring.
Definition: acmod.c:817
int acmod_write_senfh_header(acmod_t *acmod, FILE *logfh)
Write senone dump file header.
Definition: acmod.c:352
cmd_ln_t * config
Configuration.
Definition: acmod.h:150
frame_idx_t output_frame
Index of next frame of dynamic features.
Definition: acmod.h:194
int acmod_write_scores(acmod_t *acmod, int n_active, uint8 const *active, int16 const *senscr, FILE *senfh)
Write a frame of senone scores to a dump file.
Definition: acmod.c:931
tmat_t * tmat
Transition matrices.
Definition: acmod.h:160
int32 acmod_flags2list(acmod_t *acmod)
Build active list from.
Definition: acmod.c:1274
POCKETSPHINX_EXPORT int ps_mllr_free(ps_mllr_t *mllr)
Release a pointer to a linear transform.
Definition: ps_mllr.c:145
int acmod_end_utt(acmod_t *acmod)
Mark the end of an utterance.
Definition: acmod.c:443
int acmod_advance(acmod_t *acmod)
Advance the frame index.
Definition: acmod.c:919
uint8 state
State of utterance processing.
Definition: acmod.h:187
int acmod_set_mfcfh(acmod_t *acmod, FILE *logfh)
Start logging MFCCs to a filehandle.
Definition: acmod.c:377
void acmod_free(acmod_t *acmod)
Finalize an acoustic model.
Definition: acmod.c:301
void acmod_clear_active(acmod_t *acmod)
Clear set of active senones.
Definition: acmod.c:1217
#define SENSCR_DUMMY
Dummy senone score value for unintentionally active states.
Definition: acmod.h:77
Feature space linear transform structure.
Definition: acmod.h:82
frame_idx_t feat_outidx
Start of active frames in feat_buf.
Definition: acmod.h:200
mfcc_t ** acmod_get_frame(acmod_t *acmod, int *inout_frame_idx)
Get a frame of dynamic feature data.
Definition: acmod.c:1108
feat_t * fcb
Dynamic feature computation.
Definition: acmod.h:156
int log_zero
Zero log-probability value.
Definition: acmod.h:170
FILE * senfh
File for writing senone score data.
Definition: acmod.h:177
frame_idx_t mfc_outidx
Start of active frames in mfc_buf.
Definition: acmod.h:197
frame_idx_t n_mfc_alloc
Number of frames allocated in mfc_buf.
Definition: acmod.h:195
int acmod_process_raw(acmod_t *acmod, int16 const **inout_raw, size_t *inout_n_samps, int full_utt)
TODO: Set queue length for utterance processing.
Definition: acmod.c:627
int bin_mdef_free(bin_mdef_t *m)
Release a pointer to a binary mdef.
Definition: bin_mdef.c:272
uint8 insen_swap
Whether to swap input senone score.
Definition: acmod.h:190
int acmod_start_utt(acmod_t *acmod)
Mark the start of an utterance.
Definition: acmod.c:425
int senscr_frame
Frame index for senone_scores.
Definition: acmod.h:168
bin_mdef_t * mdef
Model definition.
Definition: acmod.h:159
int acmod_best_score(acmod_t *acmod, int *out_best_senid)
Get best score and senone index for current frame.
Definition: acmod.c:1188
acmod_t * acmod_init(cmd_ln_t *config, logmath_t *lmath, fe_t *fe, feat_t *fcb)
Initialize an acoustic model.
Definition: acmod.c:230
frame_idx_t n_feat_frame
Number of frames active in feat_buf.
Definition: acmod.h:199
Acoustic model structures for PocketSphinx.
FILE * mfcfh
File for writing acoustic feature data.
Definition: acmod.h:176
Acoustic model structure.
Definition: acmod.h:148
int acmod_set_grow(acmod_t *acmod, int grow_feat)
Set memory allocation policy for utterance processing.
Definition: acmod.c:412
int16 const * acmod_score(acmod_t *acmod, int *inout_frame_idx)
Score one frame of data.
Definition: acmod.c:1126
int frame_idx
frame counter.
Definition: acmod.h:115
bitvec_t * senone_active_vec
Active GMMs in current frame.
Definition: acmod.h:166