PocketSphinx
0.6
|
00001 /* -*- c-basic-offset: 4; indent-tabs-mode: nil -*- */ 00002 /* ==================================================================== 00003 * Copyright (c) 2008 Carnegie Mellon University. All rights 00004 * reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions 00008 * are met: 00009 * 00010 * 1. Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * 00013 * 2. Redistributions in binary form must reproduce the above copyright 00014 * notice, this list of conditions and the following disclaimer in 00015 * the documentation and/or other materials provided with the 00016 * distribution. 00017 * 00018 * This work was supported in part by funding from the Defense Advanced 00019 * Research Projects Agency and the National Science Foundation of the 00020 * United States of America, and the CMU Sphinx Speech Consortium. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY ``AS IS'' AND 00023 * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 00024 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00025 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY 00026 * NOR ITS EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00027 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00028 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00029 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00030 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00031 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00032 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00033 * 00034 * ==================================================================== 00035 * 00036 */ 00037 00038 00044 /* System headers. */ 00045 #include <assert.h> 00046 #include <string.h> 00047 00048 /* SphinxBase headers. */ 00049 #include <sphinxbase/prim_type.h> 00050 #include <sphinxbase/err.h> 00051 #include <sphinxbase/cmd_ln.h> 00052 #include <sphinxbase/strfuncs.h> 00053 #include <sphinxbase/byteorder.h> 00054 #include <sphinxbase/feat.h> 00055 #include <sphinxbase/bio.h> 00056 00057 /* Local headers. */ 00058 #include "cmdln_macro.h" 00059 #include "acmod.h" 00060 #include "s2_semi_mgau.h" 00061 #include "ptm_mgau.h" 00062 #include "ms_mgau.h" 00063 00064 /* Feature and front-end parameters that may be in feat.params */ 00065 static const arg_t feat_defn[] = { 00066 waveform_to_cepstral_command_line_macro(), 00067 cepstral_to_feature_command_line_macro(), 00068 CMDLN_EMPTY_OPTION 00069 }; 00070 00071 #ifndef WORDS_BIGENDIAN 00072 #define WORDS_BIGENDIAN 1 00073 #endif 00074 00075 static int32 acmod_process_mfcbuf(acmod_t *acmod); 00076 00077 static int 00078 acmod_init_am(acmod_t *acmod) 00079 { 00080 char const *mdeffn, *tmatfn, *mllrfn; 00081 00082 /* Read model definition. */ 00083 if ((mdeffn = cmd_ln_str_r(acmod->config, "-mdef")) == NULL) { 00084 E_ERROR("Acoustic model definition is not specified neither with -mdef option nor with -hmm\n"); 00085 return -1; 00086 } 00087 00088 if ((acmod->mdef = bin_mdef_read(acmod->config, mdeffn)) == NULL) { 00089 E_ERROR("Failed to read acoustic model definition from %s\n", mdeffn); 00090 return -1; 00091 } 00092 00093 /* Read transition matrices. */ 00094 if ((tmatfn = cmd_ln_str_r(acmod->config, "-tmat")) == NULL) { 00095 E_ERROR("No tmat file specified\n"); 00096 return -1; 00097 } 00098 acmod->tmat = tmat_init(tmatfn, acmod->lmath, 00099 cmd_ln_float32_r(acmod->config, "-tmatfloor"), 00100 TRUE); 00101 00102 /* Read the acoustic models. */ 00103 if ((cmd_ln_str_r(acmod->config, "-mean") == NULL) 00104 || (cmd_ln_str_r(acmod->config, "-var") == NULL) 00105 || (cmd_ln_str_r(acmod->config, "-tmat") == NULL)) { 00106 E_ERROR("No mean/var/tmat files specified\n"); 00107 return -1; 00108 } 00109 00110 if (cmd_ln_str_r(acmod->config, "-senmgau")) { 00111 E_INFO("Using general multi-stream GMM computation\n"); 00112 acmod->mgau = ms_mgau_init(acmod->config, acmod->lmath, acmod->mdef); 00113 if (acmod->mgau == NULL) 00114 return -1; 00115 } 00116 else { 00117 E_INFO("Attempting to use SCHMM computation module\n"); 00118 if ((acmod->mgau = s2_semi_mgau_init(acmod)) == NULL) { 00119 E_INFO("Attempting to use PTHMM computation module\n"); 00120 if ((acmod->mgau = ptm_mgau_init(acmod, acmod->mdef)) == NULL) { 00121 E_INFO("Falling back to general multi-stream GMM computation\n"); 00122 acmod->mgau = ms_mgau_init(acmod->config, acmod->lmath, acmod->mdef); 00123 if (acmod->mgau == NULL) 00124 return -1; 00125 } 00126 } 00127 } 00128 00129 /* If there is an MLLR transform, apply it. */ 00130 if ((mllrfn = cmd_ln_str_r(acmod->config, "-mllr"))) { 00131 ps_mllr_t *mllr = ps_mllr_read(mllrfn); 00132 if (mllr == NULL) 00133 return -1; 00134 acmod_update_mllr(acmod, mllr); 00135 } 00136 00137 return 0; 00138 } 00139 00140 static int 00141 acmod_init_feat(acmod_t *acmod) 00142 { 00143 acmod->fcb = 00144 feat_init(cmd_ln_str_r(acmod->config, "-feat"), 00145 cmn_type_from_str(cmd_ln_str_r(acmod->config,"-cmn")), 00146 cmd_ln_boolean_r(acmod->config, "-varnorm"), 00147 agc_type_from_str(cmd_ln_str_r(acmod->config, "-agc")), 00148 1, cmd_ln_int32_r(acmod->config, "-ceplen")); 00149 if (acmod->fcb == NULL) 00150 return -1; 00151 00152 if (cmd_ln_str_r(acmod->config, "-lda")) { 00153 E_INFO("Reading linear feature transformation from %s\n", 00154 cmd_ln_str_r(acmod->config, "-lda")); 00155 if (feat_read_lda(acmod->fcb, 00156 cmd_ln_str_r(acmod->config, "-lda"), 00157 cmd_ln_int32_r(acmod->config, "-ldadim")) < 0) 00158 return -1; 00159 } 00160 00161 if (cmd_ln_str_r(acmod->config, "-svspec")) { 00162 int32 **subvecs; 00163 E_INFO("Using subvector specification %s\n", 00164 cmd_ln_str_r(acmod->config, "-svspec")); 00165 if ((subvecs = parse_subvecs(cmd_ln_str_r(acmod->config, "-svspec"))) == NULL) 00166 return -1; 00167 if ((feat_set_subvecs(acmod->fcb, subvecs)) < 0) 00168 return -1; 00169 } 00170 00171 if (cmd_ln_exists_r(acmod->config, "-agcthresh") 00172 && 0 != strcmp(cmd_ln_str_r(acmod->config, "-agc"), "none")) { 00173 agc_set_threshold(acmod->fcb->agc_struct, 00174 cmd_ln_float32_r(acmod->config, "-agcthresh")); 00175 } 00176 00177 if (acmod->fcb->cmn_struct 00178 && cmd_ln_exists_r(acmod->config, "-cmninit")) { 00179 char *c, *cc, *vallist; 00180 int32 nvals; 00181 00182 vallist = ckd_salloc(cmd_ln_str_r(acmod->config, "-cmninit")); 00183 c = vallist; 00184 nvals = 0; 00185 while (nvals < acmod->fcb->cmn_struct->veclen 00186 && (cc = strchr(c, ',')) != NULL) { 00187 *cc = '\0'; 00188 acmod->fcb->cmn_struct->cmn_mean[nvals] = FLOAT2MFCC(atof(c)); 00189 c = cc + 1; 00190 ++nvals; 00191 } 00192 if (nvals < acmod->fcb->cmn_struct->veclen && *c != '\0') { 00193 acmod->fcb->cmn_struct->cmn_mean[nvals] = FLOAT2MFCC(atof(c)); 00194 } 00195 ckd_free(vallist); 00196 } 00197 return 0; 00198 } 00199 00200 int 00201 acmod_fe_mismatch(acmod_t *acmod, fe_t *fe) 00202 { 00203 /* Output vector dimension needs to be the same. */ 00204 if (cmd_ln_int32_r(acmod->config, "-ceplen") != fe_get_output_size(fe)) { 00205 E_ERROR("Configured feature length %d doesn't match feature extraction output size %d\n", 00206 cmd_ln_int32_r(acmod->config, "-ceplen"), 00207 fe_get_output_size(fe)); 00208 return TRUE; 00209 } 00210 /* Feature parameters need to be the same. */ 00211 /* ... */ 00212 return FALSE; 00213 } 00214 00215 int 00216 acmod_feat_mismatch(acmod_t *acmod, feat_t *fcb) 00217 { 00218 /* Feature type needs to be the same. */ 00219 if (0 != strcmp(cmd_ln_str_r(acmod->config, "-feat"), feat_name(fcb))) 00220 return TRUE; 00221 /* Input vector dimension needs to be the same. */ 00222 if (cmd_ln_int32_r(acmod->config, "-ceplen") != feat_cepsize(fcb)) 00223 return TRUE; 00224 /* FIXME: Need to check LDA and stuff too. */ 00225 return FALSE; 00226 } 00227 00228 acmod_t * 00229 acmod_init(cmd_ln_t *config, logmath_t *lmath, fe_t *fe, feat_t *fcb) 00230 { 00231 acmod_t *acmod; 00232 char const *featparams; 00233 00234 acmod = ckd_calloc(1, sizeof(*acmod)); 00235 acmod->config = config; 00236 acmod->lmath = lmath; 00237 acmod->state = ACMOD_IDLE; 00238 00239 /* Look for feat.params in acoustic model dir. */ 00240 if ((featparams = cmd_ln_str_r(acmod->config, "-featparams"))) { 00241 if (cmd_ln_parse_file_r(acmod->config, feat_defn, featparams, FALSE) != NULL) { 00242 E_INFO("Parsed model-specific feature parameters from %s\n", featparams); 00243 } 00244 } 00245 00246 /* Initialize feature computation. */ 00247 if (fe) { 00248 if (acmod_fe_mismatch(acmod, fe)) 00249 goto error_out; 00250 fe_retain(fe); 00251 acmod->fe = fe; 00252 } 00253 else { 00254 /* Initialize a new front end. */ 00255 cmd_ln_retain(config); 00256 acmod->fe = fe_init_auto_r(config); 00257 if (acmod->fe == NULL) 00258 goto error_out; 00259 if (acmod_fe_mismatch(acmod, acmod->fe)) 00260 goto error_out; 00261 } 00262 if (fcb) { 00263 if (acmod_feat_mismatch(acmod, fcb)) 00264 goto error_out; 00265 feat_retain(fcb); 00266 acmod->fcb = fcb; 00267 } 00268 else { 00269 /* Initialize a new fcb. */ 00270 if (acmod_init_feat(acmod) < 0) 00271 goto error_out; 00272 } 00273 00274 /* Load acoustic model parameters. */ 00275 if (acmod_init_am(acmod) < 0) 00276 goto error_out; 00277 00278 00279 /* The MFCC buffer needs to be at least as large as the dynamic 00280 * feature window. */ 00281 acmod->n_mfc_alloc = acmod->fcb->window_size * 2 + 1; 00282 acmod->mfc_buf = (mfcc_t **) 00283 ckd_calloc_2d(acmod->n_mfc_alloc, acmod->fcb->cepsize, 00284 sizeof(**acmod->mfc_buf)); 00285 00286 /* Feature buffer has to be at least as large as MFCC buffer. */ 00287 acmod->n_feat_alloc = acmod->n_mfc_alloc + cmd_ln_int32_r(config, "-pl_window"); 00288 acmod->feat_buf = feat_array_alloc(acmod->fcb, acmod->n_feat_alloc); 00289 acmod->framepos = ckd_calloc(acmod->n_feat_alloc, sizeof(*acmod->framepos)); 00290 00291 /* Senone computation stuff. */ 00292 acmod->senone_scores = ckd_calloc(bin_mdef_n_sen(acmod->mdef), 00293 sizeof(*acmod->senone_scores)); 00294 acmod->senone_active_vec = bitvec_alloc(bin_mdef_n_sen(acmod->mdef)); 00295 acmod->senone_active = ckd_calloc(bin_mdef_n_sen(acmod->mdef), 00296 sizeof(*acmod->senone_active)); 00297 acmod->log_zero = logmath_get_zero(acmod->lmath); 00298 acmod->compallsen = cmd_ln_boolean_r(config, "-compallsen"); 00299 return acmod; 00300 00301 error_out: 00302 acmod_free(acmod); 00303 return NULL; 00304 } 00305 00306 void 00307 acmod_free(acmod_t *acmod) 00308 { 00309 if (acmod == NULL) 00310 return; 00311 00312 feat_free(acmod->fcb); 00313 fe_free(acmod->fe); 00314 00315 if (acmod->mfc_buf) 00316 ckd_free_2d((void **)acmod->mfc_buf); 00317 if (acmod->feat_buf) 00318 feat_array_free(acmod->feat_buf); 00319 00320 if (acmod->mfcfh) 00321 fclose(acmod->mfcfh); 00322 if (acmod->rawfh) 00323 fclose(acmod->rawfh); 00324 if (acmod->senfh) 00325 fclose(acmod->senfh); 00326 00327 ckd_free(acmod->framepos); 00328 ckd_free(acmod->senone_scores); 00329 ckd_free(acmod->senone_active_vec); 00330 ckd_free(acmod->senone_active); 00331 00332 if (acmod->mdef) 00333 bin_mdef_free(acmod->mdef); 00334 if (acmod->tmat) 00335 tmat_free(acmod->tmat); 00336 if (acmod->mgau) 00337 ps_mgau_free(acmod->mgau); 00338 if (acmod->mllr) 00339 ps_mllr_free(acmod->mllr); 00340 00341 ckd_free(acmod); 00342 } 00343 00344 ps_mllr_t * 00345 acmod_update_mllr(acmod_t *acmod, ps_mllr_t *mllr) 00346 { 00347 if (acmod->mllr) 00348 ps_mllr_free(acmod->mllr); 00349 acmod->mllr = mllr; 00350 ps_mgau_transform(acmod->mgau, mllr); 00351 00352 return mllr; 00353 } 00354 00355 int 00356 acmod_write_senfh_header(acmod_t *acmod, FILE *logfh) 00357 { 00358 char nsenstr[64], logbasestr[64]; 00359 00360 sprintf(nsenstr, "%d", bin_mdef_n_sen(acmod->mdef)); 00361 sprintf(logbasestr, "%f", logmath_get_base(acmod->lmath)); 00362 return bio_writehdr(logfh, 00363 "version", "0.1", 00364 "mdef_file", cmd_ln_str_r(acmod->config, "-mdef"), 00365 "n_sen", nsenstr, 00366 "logbase", logbasestr, NULL); 00367 } 00368 00369 int 00370 acmod_set_senfh(acmod_t *acmod, FILE *logfh) 00371 { 00372 if (acmod->senfh) 00373 fclose(acmod->senfh); 00374 acmod->senfh = logfh; 00375 if (logfh == NULL) 00376 return 0; 00377 return acmod_write_senfh_header(acmod, logfh); 00378 } 00379 00380 int 00381 acmod_set_mfcfh(acmod_t *acmod, FILE *logfh) 00382 { 00383 int rv = 0; 00384 00385 if (acmod->mfcfh) 00386 fclose(acmod->mfcfh); 00387 acmod->mfcfh = logfh; 00388 fwrite(&rv, 4, 1, acmod->mfcfh); 00389 return rv; 00390 } 00391 00392 int 00393 acmod_set_rawfh(acmod_t *acmod, FILE *logfh) 00394 { 00395 if (acmod->rawfh) 00396 fclose(acmod->rawfh); 00397 acmod->rawfh = logfh; 00398 return 0; 00399 } 00400 00401 void 00402 acmod_grow_feat_buf(acmod_t *acmod, int nfr) 00403 { 00404 mfcc_t ***new_feat_buf; 00405 00406 new_feat_buf = feat_array_alloc(acmod->fcb, nfr); 00407 if (acmod->n_feat_frame || acmod->grow_feat) { 00408 memcpy(new_feat_buf[0][0], acmod->feat_buf[0][0], 00409 (acmod->n_feat_alloc 00410 * feat_dimension(acmod->fcb) 00411 * sizeof(***acmod->feat_buf))); 00412 } 00413 feat_array_free(acmod->feat_buf); 00414 acmod->framepos = ckd_realloc(acmod->framepos, 00415 nfr * sizeof(*acmod->framepos)); 00416 acmod->feat_buf = new_feat_buf; 00417 acmod->n_feat_alloc = nfr; 00418 } 00419 00420 int 00421 acmod_set_grow(acmod_t *acmod, int grow_feat) 00422 { 00423 int tmp = acmod->grow_feat; 00424 acmod->grow_feat = grow_feat; 00425 00426 /* Expand feat_buf to a reasonable size to start with. */ 00427 if (grow_feat && acmod->n_feat_alloc < 128) 00428 acmod_grow_feat_buf(acmod, 128); 00429 00430 return tmp; 00431 } 00432 00433 int 00434 acmod_start_utt(acmod_t *acmod) 00435 { 00436 fe_start_utt(acmod->fe); 00437 acmod->state = ACMOD_STARTED; 00438 acmod->n_mfc_frame = 0; 00439 acmod->n_feat_frame = 0; 00440 acmod->mfc_outidx = 0; 00441 acmod->feat_outidx = 0; 00442 acmod->output_frame = 0; 00443 acmod->senscr_frame = -1; 00444 acmod->n_senone_active = 0; 00445 acmod->mgau->frame_idx = 0; 00446 return 0; 00447 } 00448 00449 int 00450 acmod_end_utt(acmod_t *acmod) 00451 { 00452 int32 nfr = 0; 00453 00454 acmod->state = ACMOD_ENDED; 00455 if (acmod->n_mfc_frame < acmod->n_mfc_alloc) { 00456 int inptr; 00457 /* Where to start writing them (circular buffer) */ 00458 inptr = (acmod->mfc_outidx + acmod->n_mfc_frame) % acmod->n_mfc_alloc; 00459 /* nfr is always either zero or one. */ 00460 fe_end_utt(acmod->fe, acmod->mfc_buf[inptr], &nfr); 00461 acmod->n_mfc_frame += nfr; 00462 /* Process whatever's left, and any leadout. */ 00463 if (nfr) 00464 nfr = acmod_process_mfcbuf(acmod); 00465 } 00466 if (acmod->mfcfh) { 00467 int32 outlen, rv; 00468 outlen = (ftell(acmod->mfcfh) - 4) / 4; 00469 if (!WORDS_BIGENDIAN) 00470 SWAP_INT32(&outlen); 00471 /* Try to seek and write */ 00472 if ((rv = fseek(acmod->mfcfh, 0, SEEK_SET)) == 0) { 00473 fwrite(&outlen, 4, 1, acmod->mfcfh); 00474 } 00475 fclose(acmod->mfcfh); 00476 acmod->mfcfh = NULL; 00477 } 00478 if (acmod->rawfh) { 00479 fclose(acmod->rawfh); 00480 acmod->rawfh = NULL; 00481 } 00482 00483 if (acmod->senfh) { 00484 fclose(acmod->senfh); 00485 acmod->senfh = NULL; 00486 } 00487 00488 return nfr; 00489 } 00490 00491 static int 00492 acmod_log_mfc(acmod_t *acmod, 00493 mfcc_t **cep, int n_frames) 00494 { 00495 int i, n; 00496 int32 *ptr = (int32 *)cep[0]; 00497 00498 n = n_frames * feat_cepsize(acmod->fcb); 00499 /* Swap bytes. */ 00500 if (!WORDS_BIGENDIAN) { 00501 for (i = 0; i < (n * sizeof(mfcc_t)); ++i) { 00502 SWAP_INT32(ptr + i); 00503 } 00504 } 00505 /* Write features. */ 00506 if (fwrite(cep[0], sizeof(mfcc_t), n, acmod->mfcfh) != n) { 00507 E_ERROR_SYSTEM("Failed to write %d values to log file", n); 00508 } 00509 00510 /* Swap them back. */ 00511 if (!WORDS_BIGENDIAN) { 00512 for (i = 0; i < (n * sizeof(mfcc_t)); ++i) { 00513 SWAP_INT32(ptr + i); 00514 } 00515 } 00516 return 0; 00517 } 00518 00519 static int 00520 acmod_process_full_cep(acmod_t *acmod, 00521 mfcc_t ***inout_cep, 00522 int *inout_n_frames) 00523 { 00524 int32 nfr; 00525 00526 /* Write to log file. */ 00527 if (acmod->mfcfh) 00528 acmod_log_mfc(acmod, *inout_cep, *inout_n_frames); 00529 00530 /* Resize feat_buf to fit. */ 00531 if (acmod->n_feat_alloc < *inout_n_frames) { 00532 feat_array_free(acmod->feat_buf); 00533 acmod->feat_buf = feat_array_alloc(acmod->fcb, *inout_n_frames); 00534 acmod->n_feat_alloc = *inout_n_frames; 00535 acmod->n_feat_frame = 0; 00536 acmod->feat_outidx = 0; 00537 } 00538 /* Make dynamic features. */ 00539 nfr = feat_s2mfc2feat_live(acmod->fcb, *inout_cep, inout_n_frames, 00540 TRUE, TRUE, acmod->feat_buf); 00541 acmod->n_feat_frame = nfr; 00542 assert(acmod->n_feat_frame <= acmod->n_feat_alloc); 00543 *inout_cep += *inout_n_frames; 00544 *inout_n_frames = 0; 00545 return nfr; 00546 } 00547 00548 static int 00549 acmod_process_full_raw(acmod_t *acmod, 00550 int16 const **inout_raw, 00551 size_t *inout_n_samps) 00552 { 00553 int32 nfr, ntail; 00554 mfcc_t **cepptr; 00555 00556 /* Write to logging file if any. */ 00557 if (acmod->rawfh) 00558 fwrite(*inout_raw, 2, *inout_n_samps, acmod->rawfh); 00559 /* Resize mfc_buf to fit. */ 00560 if (fe_process_frames(acmod->fe, NULL, inout_n_samps, NULL, &nfr) < 0) 00561 return -1; 00562 if (acmod->n_mfc_alloc < nfr + 1) { 00563 ckd_free_2d(acmod->mfc_buf); 00564 acmod->mfc_buf = ckd_calloc_2d(nfr + 1, fe_get_output_size(acmod->fe), 00565 sizeof(**acmod->mfc_buf)); 00566 acmod->n_mfc_alloc = nfr + 1; 00567 } 00568 acmod->n_mfc_frame = 0; 00569 acmod->mfc_outidx = 0; 00570 fe_start_utt(acmod->fe); 00571 if (fe_process_frames(acmod->fe, inout_raw, inout_n_samps, 00572 acmod->mfc_buf, &nfr) < 0) 00573 return -1; 00574 fe_end_utt(acmod->fe, acmod->mfc_buf[nfr], &ntail); 00575 nfr += ntail; 00576 00577 cepptr = acmod->mfc_buf; 00578 nfr = acmod_process_full_cep(acmod, &cepptr, &nfr); 00579 acmod->n_mfc_frame = 0; 00580 return nfr; 00581 } 00582 00586 static int32 00587 acmod_process_mfcbuf(acmod_t *acmod) 00588 { 00589 mfcc_t **mfcptr; 00590 int32 ncep; 00591 00592 ncep = acmod->n_mfc_frame; 00593 /* Also do this in two parts because of the circular mfc_buf. */ 00594 if (acmod->mfc_outidx + ncep > acmod->n_mfc_alloc) { 00595 int32 ncep1 = acmod->n_mfc_alloc - acmod->mfc_outidx; 00596 int saved_state = acmod->state; 00597 00598 /* Make sure we don't end the utterance here. */ 00599 if (acmod->state == ACMOD_ENDED) 00600 acmod->state = ACMOD_PROCESSING; 00601 mfcptr = acmod->mfc_buf + acmod->mfc_outidx; 00602 ncep1 = acmod_process_cep(acmod, &mfcptr, &ncep1, FALSE); 00603 /* It's possible that not all available frames were filled. */ 00604 ncep -= ncep1; 00605 acmod->n_mfc_frame -= ncep1; 00606 acmod->mfc_outidx += ncep1; 00607 acmod->mfc_outidx %= acmod->n_mfc_alloc; 00608 /* Restore original state (could this really be the end) */ 00609 acmod->state = saved_state; 00610 } 00611 mfcptr = acmod->mfc_buf + acmod->mfc_outidx; 00612 ncep = acmod_process_cep(acmod, &mfcptr, &ncep, FALSE); 00613 acmod->n_mfc_frame -= ncep; 00614 acmod->mfc_outidx += ncep; 00615 acmod->mfc_outidx %= acmod->n_mfc_alloc; 00616 return ncep; 00617 } 00618 00619 int 00620 acmod_process_raw(acmod_t *acmod, 00621 int16 const **inout_raw, 00622 size_t *inout_n_samps, 00623 int full_utt) 00624 { 00625 int32 ncep; 00626 00627 /* If this is a full utterance, process it all at once. */ 00628 if (full_utt) 00629 return acmod_process_full_raw(acmod, inout_raw, inout_n_samps); 00630 00631 /* Append MFCCs to the end of any that are previously in there 00632 * (in practice, there will probably be none) */ 00633 if (inout_n_samps && *inout_n_samps) { 00634 int16 const *prev_audio_inptr = *inout_raw; 00635 int inptr; 00636 00637 /* Total number of frames available. */ 00638 ncep = acmod->n_mfc_alloc - acmod->n_mfc_frame; 00639 /* Where to start writing them (circular buffer) */ 00640 inptr = (acmod->mfc_outidx + acmod->n_mfc_frame) % acmod->n_mfc_alloc; 00641 00642 /* Write them in two (or more) parts if there is wraparound. */ 00643 while (inptr + ncep > acmod->n_mfc_alloc) { 00644 int32 ncep1 = acmod->n_mfc_alloc - inptr; 00645 if (fe_process_frames(acmod->fe, inout_raw, inout_n_samps, 00646 acmod->mfc_buf + inptr, &ncep1) < 0) 00647 return -1; 00648 /* Write to logging file if any. */ 00649 if (acmod->rawfh) { 00650 fwrite(prev_audio_inptr, 2, 00651 *inout_raw - prev_audio_inptr, 00652 acmod->rawfh); 00653 prev_audio_inptr = *inout_raw; 00654 } 00655 /* ncep1 now contains the number of frames actually 00656 * processed. This is a good thing, but it means we 00657 * actually still might have some room left at the end of 00658 * the buffer, hence the while loop. Unfortunately it 00659 * also means that in the case where we are really 00660 * actually done, we need to get out totally, hence the 00661 * goto. */ 00662 acmod->n_mfc_frame += ncep1; 00663 ncep -= ncep1; 00664 inptr += ncep1; 00665 inptr %= acmod->n_mfc_alloc; 00666 if (ncep1 == 0) 00667 goto alldone; 00668 } 00669 assert(inptr + ncep <= acmod->n_mfc_alloc); 00670 if (fe_process_frames(acmod->fe, inout_raw, inout_n_samps, 00671 acmod->mfc_buf + inptr, &ncep) < 0) 00672 return -1; 00673 /* Write to logging file if any. */ 00674 if (acmod->rawfh) { 00675 fwrite(prev_audio_inptr, 2, 00676 *inout_raw - prev_audio_inptr, acmod->rawfh); 00677 prev_audio_inptr = *inout_raw; 00678 } 00679 acmod->n_mfc_frame += ncep; 00680 alldone: 00681 ; 00682 } 00683 00684 /* Hand things off to acmod_process_cep. */ 00685 return acmod_process_mfcbuf(acmod); 00686 } 00687 00688 int 00689 acmod_process_cep(acmod_t *acmod, 00690 mfcc_t ***inout_cep, 00691 int *inout_n_frames, 00692 int full_utt) 00693 { 00694 int32 nfeat, ncep, inptr; 00695 int orig_n_frames; 00696 00697 /* If this is a full utterance, process it all at once. */ 00698 if (full_utt) 00699 return acmod_process_full_cep(acmod, inout_cep, inout_n_frames); 00700 00701 /* Write to log file. */ 00702 if (acmod->mfcfh) 00703 acmod_log_mfc(acmod, *inout_cep, *inout_n_frames); 00704 00705 /* Maximum number of frames we're going to generate. */ 00706 orig_n_frames = ncep = nfeat = *inout_n_frames; 00707 00708 /* FIXME: This behaviour isn't guaranteed... */ 00709 if (acmod->state == ACMOD_ENDED) 00710 nfeat += feat_window_size(acmod->fcb); 00711 else if (acmod->state == ACMOD_STARTED) 00712 nfeat -= feat_window_size(acmod->fcb); 00713 00714 /* Clamp number of features to fit available space. */ 00715 if (nfeat > acmod->n_feat_alloc - acmod->n_feat_frame) { 00716 /* Grow it as needed - we have to grow it at the end of an 00717 * utterance because we can't return a short read there. */ 00718 if (acmod->grow_feat || acmod->state == ACMOD_ENDED) 00719 acmod_grow_feat_buf(acmod, acmod->n_feat_alloc + nfeat); 00720 else 00721 ncep -= (nfeat - (acmod->n_feat_alloc - acmod->n_feat_frame)); 00722 } 00723 00724 /* Where to start writing in the feature buffer. */ 00725 if (acmod->grow_feat) { 00726 /* Grow to avoid wraparound if grow_feat == TRUE. */ 00727 inptr = acmod->feat_outidx + acmod->n_feat_frame; 00728 while (inptr + nfeat >= acmod->n_feat_alloc) 00729 acmod_grow_feat_buf(acmod, acmod->n_feat_alloc * 2); 00730 } 00731 else { 00732 inptr = (acmod->feat_outidx + acmod->n_feat_frame) % acmod->n_feat_alloc; 00733 } 00734 00735 /* Write them in two parts if there is wraparound. */ 00736 if (inptr + nfeat > acmod->n_feat_alloc) { 00737 int32 ncep1 = acmod->n_feat_alloc - inptr; 00738 int saved_state = acmod->state; 00739 00740 /* Make sure we don't end the utterance here. */ 00741 if (acmod->state == ACMOD_ENDED) 00742 acmod->state = ACMOD_PROCESSING; 00743 nfeat = feat_s2mfc2feat_live(acmod->fcb, *inout_cep, 00744 &ncep1, 00745 (acmod->state == ACMOD_STARTED), 00746 (acmod->state == ACMOD_ENDED), 00747 acmod->feat_buf + inptr); 00748 if (nfeat < 0) 00749 return -1; 00750 /* Move the output feature pointer forward. */ 00751 acmod->n_feat_frame += nfeat; 00752 assert(acmod->n_feat_frame <= acmod->n_feat_alloc); 00753 inptr += nfeat; 00754 inptr %= acmod->n_feat_alloc; 00755 /* Move the input feature pointers forward. */ 00756 *inout_n_frames -= ncep1; 00757 *inout_cep += ncep1; 00758 ncep -= ncep1; 00759 /* Restore original state (could this really be the end) */ 00760 acmod->state = saved_state; 00761 } 00762 00763 nfeat = feat_s2mfc2feat_live(acmod->fcb, *inout_cep, 00764 &ncep, 00765 (acmod->state == ACMOD_STARTED), 00766 (acmod->state == ACMOD_ENDED), 00767 acmod->feat_buf + inptr); 00768 if (nfeat < 0) 00769 return -1; 00770 acmod->n_feat_frame += nfeat; 00771 assert(acmod->n_feat_frame <= acmod->n_feat_alloc); 00772 /* Move the input feature pointers forward. */ 00773 *inout_n_frames -= ncep; 00774 *inout_cep += ncep; 00775 if (acmod->state == ACMOD_STARTED) 00776 acmod->state = ACMOD_PROCESSING; 00777 return orig_n_frames - *inout_n_frames; 00778 } 00779 00780 int 00781 acmod_process_feat(acmod_t *acmod, 00782 mfcc_t **feat) 00783 { 00784 int i, inptr; 00785 00786 if (acmod->n_feat_frame == acmod->n_feat_alloc) { 00787 if (acmod->grow_feat) 00788 acmod_grow_feat_buf(acmod, acmod->n_feat_alloc * 2); 00789 else 00790 return 0; 00791 } 00792 00793 if (acmod->grow_feat) { 00794 /* Grow to avoid wraparound if grow_feat == TRUE. */ 00795 inptr = acmod->feat_outidx + acmod->n_feat_frame; 00796 while (inptr + 1 >= acmod->n_feat_alloc) 00797 acmod_grow_feat_buf(acmod, acmod->n_feat_alloc * 2); 00798 } 00799 else { 00800 inptr = (acmod->feat_outidx + acmod->n_feat_frame) % acmod->n_feat_alloc; 00801 } 00802 for (i = 0; i < feat_dimension1(acmod->fcb); ++i) 00803 memcpy(acmod->feat_buf[inptr][i], 00804 feat[i], feat_dimension2(acmod->fcb, i) * sizeof(**feat)); 00805 ++acmod->n_feat_frame; 00806 assert(acmod->n_feat_frame <= acmod->n_feat_alloc); 00807 00808 return 1; 00809 } 00810 00811 static int 00812 acmod_read_senfh_header(acmod_t *acmod) 00813 { 00814 char **name, **val; 00815 int32 swap; 00816 int i; 00817 00818 if (bio_readhdr(acmod->insenfh, &name, &val, &swap) < 0) 00819 goto error_out; 00820 for (i = 0; name[i] != NULL; ++i) { 00821 if (!strcmp(name[i], "n_sen")) { 00822 if (atoi(val[i]) != bin_mdef_n_sen(acmod->mdef)) { 00823 E_ERROR("Number of senones in senone file (%d) does not match mdef (%d)\n", 00824 atoi(val[i]), bin_mdef_n_sen(acmod->mdef)); 00825 goto error_out; 00826 } 00827 } 00828 if (!strcmp(name[i], "logbase")) { 00829 if (abs(atof(val[i]) - logmath_get_base(acmod->lmath)) > 0.001) { 00830 E_ERROR("Logbase in senone file (%f) does not match acmod (%f)\n", 00831 atof(val[i]), logmath_get_base(acmod->lmath)); 00832 goto error_out; 00833 } 00834 } 00835 } 00836 acmod->insen_swap = swap; 00837 bio_hdrarg_free(name, val); 00838 return 0; 00839 error_out: 00840 bio_hdrarg_free(name, val); 00841 return -1; 00842 } 00843 00844 int 00845 acmod_set_insenfh(acmod_t *acmod, FILE *senfh) 00846 { 00847 acmod->insenfh = senfh; 00848 if (senfh == NULL) { 00849 acmod->n_feat_frame = 0; 00850 acmod->compallsen = cmd_ln_boolean_r(acmod->config, "-compallsen"); 00851 return 0; 00852 } 00853 acmod->compallsen = TRUE; 00854 return acmod_read_senfh_header(acmod); 00855 } 00856 00857 int 00858 acmod_rewind(acmod_t *acmod) 00859 { 00860 /* If the feature buffer is circular, this is not possible. */ 00861 if (acmod->output_frame > acmod->n_feat_alloc) { 00862 E_ERROR("Circular feature buffer cannot be rewound (output frame %d, alloc %d)\n", 00863 acmod->output_frame, acmod->n_feat_alloc); 00864 return -1; 00865 } 00866 00867 /* Frames consumed + frames available */ 00868 acmod->n_feat_frame = acmod->output_frame + acmod->n_feat_frame; 00869 00870 /* Reset output pointers. */ 00871 acmod->feat_outidx = 0; 00872 acmod->output_frame = 0; 00873 acmod->senscr_frame = -1; 00874 acmod->mgau->frame_idx = 0; 00875 00876 return 0; 00877 } 00878 00879 int 00880 acmod_advance(acmod_t *acmod) 00881 { 00882 /* Advance the output pointers. */ 00883 if (++acmod->feat_outidx == acmod->n_feat_alloc) 00884 acmod->feat_outidx = 0; 00885 --acmod->n_feat_frame; 00886 ++acmod->mgau->frame_idx; 00887 00888 return ++acmod->output_frame; 00889 } 00890 00891 int 00892 acmod_write_scores(acmod_t *acmod, int n_active, uint8 const *active, 00893 int16 const *senscr, FILE *senfh) 00894 { 00895 int16 n_active2; 00896 00897 /* Uncompressed frame format: 00898 * 00899 * (2 bytes) n_active: Number of active senones 00900 * If all senones active: 00901 * (n_active * 2 bytes) scores of active senones 00902 * 00903 * Otherwise: 00904 * (2 bytes) n_active: Number of active senones 00905 * (n_active bytes) deltas to active senones 00906 * (n_active * 2 bytes) scores of active senones 00907 */ 00908 n_active2 = n_active; 00909 if (fwrite(&n_active2, 2, 1, senfh) != 1) 00910 goto error_out; 00911 if (n_active == bin_mdef_n_sen(acmod->mdef)) { 00912 if (fwrite(senscr, 2, n_active, senfh) != n_active) 00913 goto error_out; 00914 } 00915 else { 00916 int i, n; 00917 if (fwrite(active, 1, n_active, senfh) != n_active) 00918 goto error_out; 00919 for (i = n = 0; i < n_active; ++i) { 00920 n += active[i]; 00921 if (fwrite(senscr + n, 2, 1, senfh) != 1) 00922 goto error_out; 00923 } 00924 } 00925 return 0; 00926 error_out: 00927 E_ERROR_SYSTEM("Failed to write frame to senone file"); 00928 return -1; 00929 } 00930 00934 static int 00935 acmod_read_scores_internal(acmod_t *acmod) 00936 { 00937 FILE *senfh = acmod->insenfh; 00938 int16 n_active; 00939 int rv; 00940 00941 if (acmod->n_feat_frame == acmod->n_feat_alloc) { 00942 if (acmod->grow_feat) 00943 acmod_grow_feat_buf(acmod, acmod->n_feat_alloc * 2); 00944 else 00945 return 0; 00946 } 00947 00948 if (senfh == NULL) 00949 return -1; 00950 if ((rv = fread(&n_active, 2, 1, senfh)) < 0) 00951 goto error_out; 00952 else if (rv == 0) 00953 return 0; 00954 00955 acmod->n_senone_active = n_active; 00956 if (acmod->n_senone_active == bin_mdef_n_sen(acmod->mdef)) { 00957 if ((rv = fread(acmod->senone_scores, 2, 00958 acmod->n_senone_active, senfh)) < 0) 00959 goto error_out; 00960 else if (rv != acmod->n_senone_active) 00961 return 0; 00962 } 00963 else { 00964 int i, n; 00965 if ((rv = fread(acmod->senone_active, 1, 00966 acmod->n_senone_active, senfh)) < 0) 00967 goto error_out; 00968 else if (rv != acmod->n_senone_active) 00969 return 0; 00970 for (i = 0, n = 0; i < acmod->n_senone_active; ++i) { 00971 int j, sen = n + acmod->senone_active[i]; 00972 for (j = n + 1; j < sen; ++j) 00973 acmod->senone_scores[j] = SENSCR_DUMMY; 00974 if ((rv = fread(acmod->senone_scores + sen, 2, 1, senfh)) < 0) 00975 goto error_out; 00976 else if (rv == 0) 00977 return 0; 00978 n = sen; 00979 } 00980 ++n; 00981 while (n < bin_mdef_n_sen(acmod->mdef)) 00982 acmod->senone_scores[n++] = SENSCR_DUMMY; 00983 } 00984 return 1; 00985 error_out: 00986 E_ERROR_SYSTEM("Failed to read frame from senone file"); 00987 return -1; 00988 } 00989 00990 int 00991 acmod_read_scores(acmod_t *acmod) 00992 { 00993 int inptr, rv; 00994 00995 if (acmod->grow_feat) { 00996 /* Grow to avoid wraparound if grow_feat == TRUE. */ 00997 inptr = acmod->feat_outidx + acmod->n_feat_frame; 00998 /* Has to be +1, otherwise, next time acmod_advance() is 00999 * called, this will wrap around. */ 01000 while (inptr + 1 >= acmod->n_feat_alloc) 01001 acmod_grow_feat_buf(acmod, acmod->n_feat_alloc * 2); 01002 } 01003 else { 01004 inptr = (acmod->feat_outidx + acmod->n_feat_frame) % acmod->n_feat_alloc; 01005 } 01006 01007 if ((rv = acmod_read_scores_internal(acmod)) != 1) 01008 return rv; 01009 01010 /* Set acmod->senscr_frame appropriately so that these scores 01011 get reused below in acmod_score(). */ 01012 acmod->senscr_frame = acmod->output_frame + acmod->n_feat_frame; 01013 01014 E_DEBUG(1,("Frame %d has %d active states\n", 01015 acmod->senscr_frame, acmod->n_senone_active)); 01016 01017 /* Increment the "feature frame counter" and record the file 01018 * position for the relevant frame in the (possibly circular) 01019 * buffer. */ 01020 ++acmod->n_feat_frame; 01021 acmod->framepos[inptr] = ftell(acmod->insenfh); 01022 01023 return 1; 01024 } 01025 01026 static int 01027 calc_frame_idx(acmod_t *acmod, int *inout_frame_idx) 01028 { 01029 int frame_idx; 01030 01031 /* Calculate the absolute frame index to be scored. */ 01032 if (inout_frame_idx == NULL) 01033 frame_idx = acmod->output_frame; 01034 else if (*inout_frame_idx < 0) 01035 frame_idx = acmod->output_frame + 1 + *inout_frame_idx; 01036 else 01037 frame_idx = *inout_frame_idx; 01038 01039 return frame_idx; 01040 } 01041 01042 static int 01043 calc_feat_idx(acmod_t *acmod, int frame_idx) 01044 { 01045 int n_backfr, feat_idx; 01046 01047 n_backfr = acmod->n_feat_alloc - acmod->n_feat_frame; 01048 if (frame_idx < 0 || acmod->output_frame - frame_idx > n_backfr) { 01049 E_ERROR("Frame %d outside queue of %d frames, %d alloc (%d > %d), cannot score\n", 01050 frame_idx, acmod->n_feat_frame, acmod->n_feat_alloc, 01051 acmod->output_frame - frame_idx, n_backfr); 01052 return -1; 01053 } 01054 01055 /* Get the index in feat_buf/framepos of the frame to be scored. */ 01056 feat_idx = ((acmod->feat_outidx + frame_idx - acmod->output_frame) 01057 % acmod->n_feat_alloc); 01058 if (feat_idx < 0) feat_idx += acmod->n_feat_alloc; 01059 01060 return feat_idx; 01061 } 01062 01063 mfcc_t ** 01064 acmod_get_frame(acmod_t *acmod, int *inout_frame_idx) 01065 { 01066 int frame_idx, feat_idx; 01067 01068 /* Calculate the absolute frame index requested. */ 01069 frame_idx = calc_frame_idx(acmod, inout_frame_idx); 01070 01071 /* Calculate position of requested frame in circular buffer. */ 01072 if ((feat_idx = calc_feat_idx(acmod, frame_idx)) < 0) 01073 return NULL; 01074 01075 if (inout_frame_idx) 01076 *inout_frame_idx = frame_idx; 01077 01078 return acmod->feat_buf[feat_idx]; 01079 } 01080 01081 int16 const * 01082 acmod_score(acmod_t *acmod, int *inout_frame_idx) 01083 { 01084 int frame_idx, feat_idx; 01085 01086 /* Calculate the absolute frame index to be scored. */ 01087 frame_idx = calc_frame_idx(acmod, inout_frame_idx); 01088 01089 /* If all senones are being computed, or we are using a senone file, 01090 then we can reuse existing scores. */ 01091 if ((acmod->compallsen || acmod->insenfh) 01092 && frame_idx == acmod->senscr_frame) { 01093 if (inout_frame_idx) 01094 *inout_frame_idx = frame_idx; 01095 return acmod->senone_scores; 01096 } 01097 01098 /* Calculate position of requested frame in circular buffer. */ 01099 if ((feat_idx = calc_feat_idx(acmod, frame_idx)) < 0) 01100 return NULL; 01101 01102 /* If there is an input senone file locate the appropriate frame and read it. */ 01103 if (acmod->insenfh) { 01104 fseek(acmod->insenfh, acmod->framepos[feat_idx], SEEK_SET); 01105 if (acmod_read_scores_internal(acmod) < 0) 01106 return NULL; 01107 } 01108 else { 01109 /* Build active senone list. */ 01110 acmod_flags2list(acmod); 01111 01112 /* Generate scores for the next available frame */ 01113 ps_mgau_frame_eval(acmod->mgau, 01114 acmod->senone_scores, 01115 acmod->senone_active, 01116 acmod->n_senone_active, 01117 acmod->feat_buf[feat_idx], 01118 frame_idx, 01119 acmod->compallsen); 01120 } 01121 01122 if (inout_frame_idx) 01123 *inout_frame_idx = frame_idx; 01124 acmod->senscr_frame = frame_idx; 01125 01126 /* Dump scores to the senone dump file if one exists. */ 01127 if (acmod->senfh) { 01128 if (acmod_write_scores(acmod, acmod->n_senone_active, 01129 acmod->senone_active, 01130 acmod->senone_scores, 01131 acmod->senfh) < 0) 01132 return NULL; 01133 E_DEBUG(1,("Frame %d has %d active states\n", frame_idx, acmod->n_senone_active)); 01134 } 01135 01136 return acmod->senone_scores; 01137 } 01138 01139 int 01140 acmod_best_score(acmod_t *acmod, int *out_best_senid) 01141 { 01142 int i, best; 01143 01144 best = SENSCR_DUMMY; 01145 if (acmod->compallsen) { 01146 for (i = 0; i < bin_mdef_n_sen(acmod->mdef); ++i) { 01147 if (acmod->senone_scores[i] < best) { 01148 best = acmod->senone_scores[i]; 01149 *out_best_senid = i; 01150 } 01151 } 01152 } 01153 else { 01154 int16 *senscr; 01155 senscr = acmod->senone_scores; 01156 for (i = 0; i < acmod->n_senone_active; ++i) { 01157 senscr += acmod->senone_active[i]; 01158 if (*senscr < best) { 01159 best = *senscr; 01160 *out_best_senid = i; 01161 } 01162 } 01163 } 01164 return best; 01165 } 01166 01167 01168 void 01169 acmod_clear_active(acmod_t *acmod) 01170 { 01171 if (acmod->compallsen) 01172 return; 01173 bitvec_clear_all(acmod->senone_active_vec, bin_mdef_n_sen(acmod->mdef)); 01174 acmod->n_senone_active = 0; 01175 } 01176 01177 #define MPX_BITVEC_SET(a,h,i) \ 01178 if (hmm_mpx_ssid(h,i) != BAD_SSID) \ 01179 bitvec_set((a)->senone_active_vec, hmm_mpx_senid(h,i)) 01180 #define NONMPX_BITVEC_SET(a,h,i) \ 01181 bitvec_set((a)->senone_active_vec, \ 01182 hmm_nonmpx_senid(h,i)) 01183 01184 void 01185 acmod_activate_hmm(acmod_t *acmod, hmm_t *hmm) 01186 { 01187 int i; 01188 01189 if (acmod->compallsen) 01190 return; 01191 if (hmm_is_mpx(hmm)) { 01192 switch (hmm_n_emit_state(hmm)) { 01193 case 5: 01194 MPX_BITVEC_SET(acmod, hmm, 4); 01195 MPX_BITVEC_SET(acmod, hmm, 3); 01196 case 3: 01197 MPX_BITVEC_SET(acmod, hmm, 2); 01198 MPX_BITVEC_SET(acmod, hmm, 1); 01199 MPX_BITVEC_SET(acmod, hmm, 0); 01200 break; 01201 default: 01202 for (i = 0; i < hmm_n_emit_state(hmm); ++i) { 01203 MPX_BITVEC_SET(acmod, hmm, i); 01204 } 01205 } 01206 } 01207 else { 01208 switch (hmm_n_emit_state(hmm)) { 01209 case 5: 01210 NONMPX_BITVEC_SET(acmod, hmm, 4); 01211 NONMPX_BITVEC_SET(acmod, hmm, 3); 01212 case 3: 01213 NONMPX_BITVEC_SET(acmod, hmm, 2); 01214 NONMPX_BITVEC_SET(acmod, hmm, 1); 01215 NONMPX_BITVEC_SET(acmod, hmm, 0); 01216 break; 01217 default: 01218 for (i = 0; i < hmm_n_emit_state(hmm); ++i) { 01219 NONMPX_BITVEC_SET(acmod, hmm, i); 01220 } 01221 } 01222 } 01223 } 01224 01225 int32 01226 acmod_flags2list(acmod_t *acmod) 01227 { 01228 int32 w, l, n, b, total_dists, total_words, extra_bits; 01229 bitvec_t *flagptr; 01230 01231 total_dists = bin_mdef_n_sen(acmod->mdef); 01232 if (acmod->compallsen) { 01233 acmod->n_senone_active = total_dists; 01234 return total_dists; 01235 } 01236 total_words = total_dists / BITVEC_BITS; 01237 extra_bits = total_dists % BITVEC_BITS; 01238 w = n = l = 0; 01239 for (flagptr = acmod->senone_active_vec; w < total_words; ++w, ++flagptr) { 01240 if (*flagptr == 0) 01241 continue; 01242 for (b = 0; b < BITVEC_BITS; ++b) { 01243 if (*flagptr & (1UL << b)) { 01244 int32 sen = w * BITVEC_BITS + b; 01245 int32 delta = sen - l; 01246 /* Handle excessive deltas "lossily" by adding a few 01247 extra senones to bridge the gap. */ 01248 while (delta > 255) { 01249 acmod->senone_active[n++] = 255; 01250 delta -= 255; 01251 } 01252 acmod->senone_active[n++] = delta; 01253 l = sen; 01254 } 01255 } 01256 } 01257 01258 for (b = 0; b < extra_bits; ++b) { 01259 if (*flagptr & (1UL << b)) { 01260 int32 sen = w * BITVEC_BITS + b; 01261 int32 delta = sen - l; 01262 /* Handle excessive deltas "lossily" by adding a few 01263 extra senones to bridge the gap. */ 01264 while (delta > 255) { 01265 acmod->senone_active[n++] = 255; 01266 delta -= 255; 01267 } 01268 acmod->senone_active[n++] = delta; 01269 l = sen; 01270 } 01271 } 01272 01273 acmod->n_senone_active = n; 01274 E_DEBUG(1, ("acmod_flags2list: %d active in frame %d\n", 01275 acmod->n_senone_active, acmod->output_frame)); 01276 return n; 01277 }