44 #include <sphinxbase/bio.h>
50 #define MIXW_PARAM_VERSION "1.0"
51 #define SPDEF_PARAM_VERSION "1.2"
53 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ == 199901L)
54 #define LOGMATH_INLINE inline
55 #elif defined(__GNUC__)
56 #define LOGMATH_INLINE static inline
57 #elif defined(_MSC_VER)
58 #define LOGMATH_INLINE __inline
60 #define LOGMATH_INLINE static
64 senone_mgau_map_read(
senone_t * s,
char const *file_name)
67 int32 byteswap, chksum_present, n_gauden_present;
71 char **argname, **argval;
75 E_INFO(
"Reading senone gauden-codebook map file: %s\n", file_name);
77 if ((fp = fopen(file_name,
"rb")) == NULL)
78 E_FATAL_SYSTEM(
"Failed to open map file '%s' for reading", file_name);
81 if (bio_readhdr(fp, &argname, &argval, &byteswap) < 0)
82 E_FATAL(
"Failed to read header from file '%s'\n", file_name);
87 for (i = 0; argname[i]; i++) {
88 if (strcmp(argname[i],
"version") == 0) {
89 if (strcmp(argval[i], SPDEF_PARAM_VERSION) != 0) {
90 E_WARN(
"Version mismatch(%s): %s, expecting %s\n",
91 file_name, argval[i], SPDEF_PARAM_VERSION);
95 if (sscanf(argval[i],
"%f", &v) != 1)
96 E_FATAL(
"%s: Bad version no. string: %s\n", file_name,
99 n_gauden_present = (v > 1.1) ? 1 : 0;
101 else if (strcmp(argname[i],
"chksum0") == 0) {
105 bio_hdrarg_free(argname, argval);
106 argname = argval = NULL;
111 if (n_gauden_present) {
112 E_INFO(
"Reading number of codebooks from %s\n", file_name);
114 (&(s->
n_gauden),
sizeof(int32), 1, fp, byteswap, &chksum) != 1)
115 E_FATAL(
"fread(%s) (#gauden) failed\n", file_name);
119 if (bio_fread_1d(&ptr,
sizeof(uint32), &(s->
n_sen), fp,
120 byteswap, &chksum) < 0) {
121 E_FATAL(
"bio_fread_1d(%s) failed\n", file_name);
124 E_INFO(
"Mapping %d senones to %d codebooks\n", s->
n_sen, s->
n_gauden);
127 if (!n_gauden_present) {
129 for (i = 0; i < s->
n_sen; i++)
135 bio_verify_chksum(fp, byteswap, chksum);
137 if (fread(&eofchk, 1, 1, fp) == 1)
138 E_FATAL(
"More data than expected in %s: %d\n", file_name, eofchk);
142 E_INFO(
"Read %d->%d senone-codebook mappings\n", s->
n_sen,
150 senone_mixw_read(
senone_t * s,
char const *file_name, logmath_t *lmath)
154 int32 byteswap, chksum_present;
157 int32 i, f, c, p, n_err;
158 char **argname, **argval;
160 E_INFO(
"Reading senone mixture weights: %s\n", file_name);
162 if ((fp = fopen(file_name,
"rb")) == NULL)
163 E_FATAL_SYSTEM(
"Failed to open mixture weights file '%s' for reading", file_name);
166 if (bio_readhdr(fp, &argname, &argval, &byteswap) < 0)
167 E_FATAL(
"Failed to read header from file '%s'\n", file_name);
171 for (i = 0; argname[i]; i++) {
172 if (strcmp(argname[i],
"version") == 0) {
173 if (strcmp(argval[i], MIXW_PARAM_VERSION) != 0)
174 E_WARN(
"Version mismatch(%s): %s, expecting %s\n",
175 file_name, argval[i], MIXW_PARAM_VERSION);
177 else if (strcmp(argname[i],
"chksum0") == 0) {
181 bio_hdrarg_free(argname, argval);
182 argname = argval = NULL;
187 if ((bio_fread(&(s->
n_sen),
sizeof(int32), 1, fp, byteswap, &chksum) !=
190 (bio_fread(&(s->
n_feat),
sizeof(int32), 1, fp, byteswap, &chksum)
192 || (bio_fread(&(s->
n_cw),
sizeof(int32), 1, fp, byteswap, &chksum)
194 || (bio_fread(&i,
sizeof(int32), 1, fp, byteswap, &chksum) != 1)) {
195 E_FATAL(
"bio_fread(%s) (arraysize) failed\n", file_name);
199 (
"%s: #float32s(%d) doesn't match dimensions: %d x %d x %d\n",
208 E_FATAL(
"mixwfloor (%e) not in range (0, 1)\n", s->
mixwfloor);
211 E_INFO(
"Truncating senone logs3(pdf) values by %d bits\n",
SENSCR_SHIFT);
218 E_INFO(
"Not transposing mixture weights in memory\n");
224 E_INFO(
"Transposing mixture weights in memory\n");
231 pdf = (float32 *) ckd_calloc(s->
n_cw,
sizeof(float32));
235 for (i = 0; i < s->
n_sen; i++) {
236 for (f = 0; f < s->
n_feat; f++) {
238 ((
void *) pdf,
sizeof(float32), s->
n_cw, fp, byteswap,
241 E_FATAL(
"bio_fread(%s) (arraydata) failed\n", file_name);
245 if (vector_sum_norm(pdf, s->
n_cw) <= 0.0)
248 vector_sum_norm(pdf, s->
n_cw);
251 for (c = 0; c < s->
n_cw; c++) {
252 p = -(logmath_log(lmath, pdf[c]));
257 (p < (255 << SENSCR_SHIFT)) ? (p >>
SENSCR_SHIFT) : 255;
260 (p < (255 << SENSCR_SHIFT)) ? (p >>
SENSCR_SHIFT) : 255;
265 E_WARN(
"Weight normalization failed for %d senones\n", n_err);
270 bio_verify_chksum(fp, byteswap, chksum);
272 if (fread(&eofchk, 1, 1, fp) == 1)
273 E_FATAL(
"More data than expected in %s\n", file_name);
278 (
"Read mixture weights for %d senones: %d features x %d codewords\n",
286 senone_init(
gauden_t *g,
char const *mixwfile,
char const *sen2mgau_map_file,
287 float32 mixwfloor, logmath_t *lmath,
bin_mdef_t *mdef)
297 if (sen2mgau_map_file) {
298 if (!(strcmp(sen2mgau_map_file,
".semi.") == 0
299 || strcmp(sen2mgau_map_file,
".ptm.") == 0
300 || strcmp(sen2mgau_map_file,
".cont.") == 0)) {
301 senone_mgau_map_read(s, sen2mgau_map_file);
307 sen2mgau_map_file =
".semi.";
308 else if (s->
n_gauden == bin_mdef_n_ciphone(mdef))
309 sen2mgau_map_file =
".ptm.";
311 sen2mgau_map_file =
".cont.";
314 senone_mixw_read(s, mixwfile, lmath);
316 if (strcmp(sen2mgau_map_file,
".semi.") == 0) {
318 E_INFO(
"Mapping all senones to one codebook\n");
321 else if (strcmp(sen2mgau_map_file,
".ptm.") == 0) {
323 E_INFO(
"Mapping senones to context-independent phone codebooks\n");
325 for (i = 0; i < s->
n_sen; i++)
326 s->
mgau[i] = bin_mdef_sen2cimap(mdef, i);
328 else if (strcmp(sen2mgau_map_file,
".cont.") == 0
329 || strcmp(sen2mgau_map_file,
".s3cont.") == 0) {
331 E_INFO(
"Mapping senones to individual codebooks\n");
333 E_FATAL(
"#senone=%d; must be >1\n", s->
n_sen);
336 for (i = 0; i < s->
n_sen; i++)
343 E_FATAL(
"#senones inconsistent: %d in %s; %d in %s\n",
344 n, sen2mgau_map_file, s->
n_sen, mixwfile);
357 ckd_free_3d((
void *) s->
pdf);
362 logmath_free(s->
lmath);
382 assert((
id >= 0) && (id < s->n_sen));
383 assert((n_top > 0) && (n_top <= s->n_cw));
387 for (f = 0; f < s->
n_feat; f++) {
394 ? (fden + -s->
pdf[
id][f][fdist[0].
id])
395 : (fden + -s->
pdf[f][fdist[0].id][id]);
396 E_DEBUG(1, (
"fden[%d][%d] l+= %d + %d = %d\n",
397 id, f, -(fscr - fden), -(fden-top), -(fscr-top)));
399 for (t = 1; t < n_top; t++) {
402 (fden + -s->
pdf[
id][f][fdist[t].id]) :
403 (fden + -s->
pdf[f][fdist[t].id][id]);
404 fscr = logmath_add(s->
lmath, fscr, fwscr);
405 E_DEBUG(1, (
"fden[%d][%d] l+= %d + %d = %d\n",
406 id, f, -(fwscr - fden), -(fden-top), -(fscr-top)));