45 #if defined(__ADSPBLACKFIN__)
46 #elif !defined(_WIN32_WCE)
47 #include <sys/types.h>
51 #define M_PI 3.14159265358979323846
55 #include <sphinx_config.h>
56 #include <sphinxbase/cmd_ln.h>
57 #include <sphinxbase/fixpoint.h>
58 #include <sphinxbase/ckd_alloc.h>
59 #include <sphinxbase/bio.h>
60 #include <sphinxbase/err.h>
61 #include <sphinxbase/prim_type.h>
66 #include "posixwin32.h"
71 &ptm_mgau_mllr_transform,
75 #define COMPUTE_GMM_MAP(_idx) \
76 diff[_idx] = obs[_idx] - mean[_idx]; \
77 sqdiff[_idx] = MFCCMUL(diff[_idx], diff[_idx]); \
78 compl[_idx] = MFCCMUL(sqdiff[_idx], var[_idx]);
79 #define COMPUTE_GMM_REDUCE(_idx) \
80 d = GMMSUB(d, compl[_idx]);
83 insertion_sort_topn(
ptm_topn_t *topn,
int i, int32 d)
92 for (j = i - 1; j >= 0 && d > topn[j].
score; j--) {
93 topn[j + 1] = topn[j];
99 eval_topn(
ptm_mgau_t *s,
int cb,
int feat, mfcc_t *z)
104 topn = s->
f->
topn[cb][feat];
107 for (i = 0; i < s->max_topn; i++) {
108 mfcc_t *mean, diff[4], sqdiff[4], compl[4];
114 mean = s->
g->
mean[cb][feat][0] + cw * ceplen;
115 var = s->
g->
var[cb][feat][0] + cw * ceplen;
116 d = s->
g->
det[cb][feat][cw];
118 for (j = 0; j < ceplen % 4; ++j) {
119 diff[0] = *obs++ - *mean++;
120 sqdiff[0] = MFCCMUL(diff[0], diff[0]);
121 compl[0] = MFCCMUL(sqdiff[0], *var);
127 for (;j < ceplen; j += 4) {
132 COMPUTE_GMM_REDUCE(0);
133 COMPUTE_GMM_REDUCE(1);
134 COMPUTE_GMM_REDUCE(2);
135 COMPUTE_GMM_REDUCE(3);
140 insertion_sort_topn(topn, i, (int32)d);
143 return topn[0].
score;
152 for (*cur = worst - 1; *cur >= best && intd >= (*cur)->
score; --*cur)
153 memcpy(*cur + 1, *cur,
sizeof(**cur));
156 (*cur)->score = intd;
160 eval_cb(
ptm_mgau_t *s,
int cb,
int feat, mfcc_t *z)
164 mfcc_t *var, *det, *detP, *detE;
167 best = topn = s->
f->
topn[cb][feat];
168 worst = topn + (s->max_topn - 1);
169 mean = s->
g->
mean[cb][feat][0];
170 var = s->
g->
var[cb][feat][0];
171 det = s->
g->
det[cb][feat];
175 for (detP = det; detP < detE; ++detP) {
176 mfcc_t diff[4], sqdiff[4], compl[4];
183 thresh = (mfcc_t) worst->
score;
190 for (j = 0; (j < ceplen % 4) && (d >= thresh); ++j) {
191 diff[0] = *obs++ - *mean++;
192 sqdiff[0] = MFCCMUL(diff[0], diff[0]);
193 compl[0] = MFCCMUL(sqdiff[0], *var++);
199 for (; j < ceplen && d >= thresh; j += 4) {
204 COMPUTE_GMM_REDUCE(0);
205 COMPUTE_GMM_REDUCE(1);
206 COMPUTE_GMM_REDUCE(2);
207 COMPUTE_GMM_REDUCE(3);
214 mean += (ceplen - j);
220 for (i = 0; i < s->max_topn; i++) {
222 if (topn[i].cw == cw)
227 insertion_sort_cb(&cur, worst, best, cw, (int32)d);
237 ptm_mgau_codebook_eval(
ptm_mgau_t *s, mfcc_t **z,
int frame)
242 for (i = 0; i < s->
g->
n_mgau; ++i)
243 for (j = 0; j < s->
g->
n_feat; ++j)
244 eval_topn(s, i, j, z[j]);
247 if (frame % s->ds_ratio)
251 for (i = 0; i < s->
g->
n_mgau; ++i) {
254 for (j = 0; j < s->
g->
n_feat; ++j) {
255 eval_cb(s, i, j, z[j]);
267 for (j = 0; j < s->
g->
n_feat; ++j) {
268 int32 norm = 0x7fffffff;
269 for (i = 0; i < s->
g->
n_mgau; ++i) {
275 assert(norm != 0x7fffffff);
276 for (i = 0; i < s->
g->
n_mgau; ++i) {
280 for (k = 0; k < s->max_topn; ++k) {
294 ptm_mgau_calc_cb_active(
ptm_mgau_t *s, uint8 *senone_active,
295 int32 n_senone_active,
int compallsen)
304 for (lastsen = i = 0; i < n_senone_active; ++i) {
305 int sen = senone_active[i] + lastsen;
310 E_DEBUG(1, (
"Active codebooks:"));
311 for (i = 0; i < s->
g->
n_mgau; ++i) {
314 E_DEBUGCONT(1, (
" %d", i));
316 E_DEBUGCONT(1, (
"\n"));
324 ptm_mgau_senone_eval(
ptm_mgau_t *s, int16 *senone_scores,
325 uint8 *senone_active, int32 n_senone_active,
328 int i, lastsen, bestscore;
330 memset(senone_scores, 0, s->
n_sen *
sizeof(*senone_scores));
337 n_senone_active = s->
n_sen;
338 bestscore = 0x7fffffff;
339 for (lastsen = i = 0; i < n_senone_active; ++i) {
346 sen = senone_active[i] + lastsen;
356 for (f = 0; f < s->
g->
n_feat; ++f) {
357 for (j = 0; j < s->max_topn; ++j) {
365 for (f = 0; f < s->
g->
n_feat; ++f) {
368 topn = s->
f->
topn[cb][f];
369 for (j = 0; j < s->max_topn; ++j) {
373 int dcw = s->
mixw[f][topn[j].
cw][sen/2];
374 dcw = (dcw & 1) ? dcw >> 4 : dcw & 0x0f;
375 mixw = s->mixw_cb[dcw];
378 mixw = s->
mixw[f][topn[j].
cw][sen];
381 fden = mixw + topn[j].
score;
384 mixw + topn[j].
score);
385 E_DEBUG(3, (
"fden[%d][%d] l+= %d + %d = %d\n",
386 sen, f, mixw, topn[j].score, fden));
390 if (ascore < bestscore) bestscore = ascore;
391 senone_scores[sen] = ascore;
395 for (i = 0; i < s->
n_sen; ++i) {
396 senone_scores[i] -= bestscore;
407 int16 *senone_scores,
408 uint8 *senone_active,
409 int32 n_senone_active,
410 mfcc_t ** featbuf, int32 frame,
423 s->
f = s->
hist + fast_eval_idx;
427 if (frame >= ps_mgau_base(ps)->frame_idx) {
432 if (fast_eval_idx == 0)
435 lastf = s->
hist + fast_eval_idx - 1;
437 memcpy(s->
f->
topn[0][0], lastf->
topn[0][0],
441 ptm_mgau_calc_cb_active(s, senone_active, n_senone_active, compallsen);
443 ptm_mgau_codebook_eval(s, featbuf, frame);
446 ptm_mgau_senone_eval(s, senone_scores, senone_active,
447 n_senone_active, compallsen);
458 int32 do_swap, do_mmap;
459 size_t filesize, offset;
463 int n_sen = bin_mdef_n_sen(mdef);
467 do_mmap = cmd_ln_boolean_r(s->
config,
"-mmap");
469 if ((fp = fopen(file,
"rb")) == NULL)
472 E_INFO(
"Loading senones from dump file %s\n", file);
474 if (fread(&n,
sizeof(int32), 1, fp) != 1) {
475 E_ERROR_SYSTEM(
"Failed to read title size from %s", file);
480 if (n < 1 || n > 999) {
482 if (n < 1 || n > 999) {
483 E_ERROR(
"Title length %x in dump file %s out of range\n", n, file);
488 if (fread(line,
sizeof(
char), n, fp) != n) {
489 E_ERROR_SYSTEM(
"Cannot read title");
492 if (line[n - 1] !=
'\0') {
493 E_ERROR(
"Bad title in dump file\n");
496 E_INFO(
"%s\n", line);
499 if (fread(&n,
sizeof(n), 1, fp) != 1) {
500 E_ERROR_SYSTEM(
"Failed to read header size from %s", file);
503 if (do_swap) SWAP_INT32(&n);
504 if (fread(line,
sizeof(
char), n, fp) != n) {
505 E_ERROR_SYSTEM(
"Cannot read header");
508 if (line[n - 1] !=
'\0') {
509 E_ERROR(
"Bad header in dump file\n");
515 if (fread(&n,
sizeof(n), 1, fp) != 1) {
516 E_ERROR_SYSTEM(
"Failed to read header string size from %s", file);
519 if (do_swap) SWAP_INT32(&n);
522 if (fread(line,
sizeof(
char), n, fp) != n) {
523 E_ERROR_SYSTEM(
"Cannot read header");
527 if (!strncmp(line,
"feature_count ", strlen(
"feature_count "))) {
528 n_feat = atoi(line + strlen(
"feature_count "));
530 if (!strncmp(line,
"mixture_count ", strlen(
"mixture_count "))) {
531 n_density = atoi(line + strlen(
"mixture_count "));
533 if (!strncmp(line,
"model_count ", strlen(
"model_count "))) {
534 n_sen = atoi(line + strlen(
"model_count "));
536 if (!strncmp(line,
"cluster_count ", strlen(
"cluster_count "))) {
537 n_clust = atoi(line + strlen(
"cluster_count "));
539 if (!strncmp(line,
"cluster_bits ", strlen(
"cluster_bits "))) {
540 n_bits = atoi(line + strlen(
"cluster_bits "));
549 if (fread(&r,
sizeof(r), 1, fp) != 1) {
550 E_ERROR_SYSTEM(
"Cannot read #rows");
553 if (do_swap) SWAP_INT32(&r);
554 if (fread(&c,
sizeof(c), 1, fp) != 1) {
555 E_ERROR_SYSTEM(
"Cannot read #columns");
558 if (do_swap) SWAP_INT32(&c);
559 E_INFO(
"Rows: %d, Columns: %d\n", r, c);
563 E_ERROR(
"Number of feature streams mismatch: %d != %d\n",
568 E_ERROR(
"Number of densities mismatch: %d != %d\n",
572 if (n_sen != s->
n_sen) {
573 E_ERROR(
"Number of senones mismatch: %d != %d\n",
578 if (!((n_clust == 0) || (n_clust == 15) || (n_clust == 16))) {
579 E_ERROR(
"Cluster count must be 0, 15, or 16\n");
585 if (!((n_bits == 8) || (n_bits == 4))) {
586 E_ERROR(
"Cluster count must be 4 or 8\n");
591 E_INFO(
"Using memory-mapped I/O for senones\n");
594 fseek(fp, 0, SEEK_END);
595 filesize = ftell(fp);
596 fseek(fp, offset, SEEK_SET);
600 s->sendump_mmap = mmio_file_read(file);
603 s->mixw_cb = ((uint8 *) mmio_file_ptr(s->sendump_mmap)) + offset;
610 s->mixw_cb = ckd_calloc(1, n_clust);
611 if (fread(s->mixw_cb, 1, n_clust, fp) != (
size_t) n_clust) {
612 E_ERROR(
"Failed to read %d bytes from sendump\n", n_clust);
619 if (s->sendump_mmap) {
620 s->
mixw = ckd_calloc_2d(n_feat, n_density,
sizeof(*s->
mixw));
621 for (n = 0; n < n_feat; n++) {
624 step = (step + 1) / 2;
625 for (i = 0; i < r; i++) {
626 s->
mixw[n][i] = ((uint8 *) mmio_file_ptr(s->sendump_mmap)) + offset;
632 s->
mixw = ckd_calloc_3d(n_feat, n_density, n_sen,
sizeof(***s->
mixw));
634 for (n = 0; n < n_feat; n++) {
637 step = (step + 1) / 2;
638 for (i = 0; i < r; i++) {
639 if (fread(s->
mixw[n][i],
sizeof(***s->
mixw), step, fp)
641 E_ERROR(
"Failed to read %d bytes from sendump\n", step);
656 read_mixw(
ptm_mgau_t * s,
char const *file_name,
double SmoothMin)
658 char **argname, **argval;
661 int32 byteswap, chksum_present;
670 E_INFO(
"Reading mixture weights file '%s'\n", file_name);
672 if ((fp = fopen(file_name,
"rb")) == NULL)
673 E_FATAL(
"Failed to open mixture file '%s' for reading: %s\n", file_name, strerror(errno));
676 if (bio_readhdr(fp, &argname, &argval, &byteswap) < 0)
677 E_FATAL(
"Failed to read header from '%s'\n", file_name);
681 for (i = 0; argname[i]; i++) {
682 if (strcmp(argname[i],
"version") == 0) {
683 if (strcmp(argval[i], MGAU_MIXW_VERSION) != 0)
684 E_WARN(
"Version mismatch(%s): %s, expecting %s\n",
685 file_name, argval[i], MGAU_MIXW_VERSION);
687 else if (strcmp(argname[i],
"chksum0") == 0) {
691 bio_hdrarg_free(argname, argval);
692 argname = argval = NULL;
697 if ((bio_fread(&n_sen,
sizeof(int32), 1, fp, byteswap, &chksum) != 1)
698 || (bio_fread(&n_feat,
sizeof(int32), 1, fp, byteswap, &chksum) !=
700 || (bio_fread(&n_comp,
sizeof(int32), 1, fp, byteswap, &chksum) !=
702 || (bio_fread(&n,
sizeof(int32), 1, fp, byteswap, &chksum) != 1)) {
703 E_FATAL(
"bio_fread(%s) (arraysize) failed\n", file_name);
706 E_FATAL(
"#Features streams(%d) != %d\n", n_feat, s->
g->
n_feat);
707 if (n != n_sen * n_feat * n_comp) {
709 (
"%s: #float32s(%d) doesn't match header dimensions: %d x %d x %d\n",
710 file_name, i, n_sen, n_feat, n_comp);
720 n_sen,
sizeof(***s->
mixw));
723 pdf = (float32 *) ckd_calloc(n_comp,
sizeof(float32));
727 for (i = 0; i < n_sen; i++) {
728 for (f = 0; f < n_feat; f++) {
729 if (bio_fread((
void *) pdf,
sizeof(float32),
730 n_comp, fp, byteswap, &chksum) != n_comp) {
731 E_FATAL(
"bio_fread(%s) (arraydata) failed\n", file_name);
735 if (vector_sum_norm(pdf, n_comp) <= 0.0)
737 vector_floor(pdf, n_comp, SmoothMin);
738 vector_sum_norm(pdf, n_comp);
741 for (c = 0; c < n_comp; c++) {
744 qscr = -logmath_log(s->lmath_8b, pdf[c]);
747 s->
mixw[f][c][i] = qscr;
752 E_WARN(
"Weight normalization failed for %d senones\n", n_err);
757 bio_verify_chksum(fp, byteswap, chksum);
759 if (fread(&eofchk, 1, 1, fp) == 1)
760 E_FATAL(
"More data than expected in %s\n", file_name);
764 E_INFO(
"Read %d x %d x %d mixture weights\n", n_sen, n_feat, n_comp);
773 char const *sendump_path;
776 s = ckd_calloc(1,
sizeof(*s));
779 s->lmath = logmath_retain(acmod->
lmath);
782 if (s->lmath_8b == NULL)
785 if (logmath_get_width(s->lmath_8b) != 1) {
786 E_ERROR(
"Log base %f is too small to represent add table in 8 bits\n",
787 logmath_get_base(s->lmath_8b));
792 if ((s->
g = gauden_init(cmd_ln_str_r(s->
config,
"-mean"),
793 cmd_ln_str_r(s->
config,
"-var"),
794 cmd_ln_float32_r(s->
config,
"-varfloor"),
800 E_INFO(
"Number of codebooks exceeds 256: %d\n", s->
g->
n_mgau);
803 if (s->
g->
n_mgau != bin_mdef_n_ciphone(mdef)) {
804 E_INFO(
"Number of codebooks doesn't match number of ciphones, doesn't look like PTM: %d %d\n", s->
g->
n_mgau, bin_mdef_n_ciphone(mdef));
808 if (s->
g->
n_feat != feat_dimension1(acmod->
fcb)) {
809 E_ERROR(
"Number of streams does not match: %d != %d\n",
813 for (i = 0; i < s->
g->
n_feat; ++i) {
814 if (s->
g->
featlen[i] != feat_dimension2(acmod->
fcb, i)) {
815 E_ERROR(
"Dimension of stream %d does not match: %d != %d\n",
821 if ((sendump_path = cmd_ln_str_r(s->
config,
"-sendump"))) {
822 if (read_sendump(s, acmod->
mdef, sendump_path) < 0) {
827 if (read_mixw(s, cmd_ln_str_r(s->
config,
"-mixw"),
828 cmd_ln_float32_r(s->
config,
"-mixwfloor")) < 0) {
832 s->ds_ratio = cmd_ln_int32_r(s->
config,
"-ds");
833 s->max_topn = cmd_ln_int32_r(s->
config,
"-topn");
834 E_INFO(
"Maximum top-N: %d\n", s->max_topn);
839 for (i = 0; i < s->
n_sen; ++i)
840 s->
sen2cb[i] = bin_mdef_sen2cimap(acmod->
mdef, i);
855 for (j = 0; j < s->
g->
n_mgau; ++j) {
856 for (k = 0; k < s->
g->
n_feat; ++k) {
857 for (m = 0; m < s->max_topn; ++m) {
871 ps->
vt = &ptm_mgau_funcs;
874 ptm_mgau_free(ps_mgau_base(s));
883 return gauden_mllr_transform(s->
g, mllr, s->
config);
891 logmath_free(s->lmath);
892 logmath_free(s->lmath_8b);
893 if (s->sendump_mmap) {
894 ckd_free_2d(s->
mixw);
895 mmio_file_unmap(s->sendump_mmap);
898 ckd_free_3d(s->
mixw);