static void feat_compute_utt(feat_t *fcb, mfcc_t **mfc, int32 nfr, int32 win, mfcc_t ***feat) { int32 i; cep_dump_dbg(fcb, mfc, nfr, "Incoming features (after padding)"); feat_cmn(fcb, mfc, nfr, 1, 1); feat_agc(fcb, mfc, nfr, 1, 1); /* Create feature vectors */ for (i = win; i < nfr - win; i++) { fcb->compute_feat(fcb, mfc + i, feat[i - win]); } feat_print_dbg(fcb, feat, nfr - win * 2, "After dynamic feature computation"); if (fcb->lda) { feat_lda_transform(fcb, feat, nfr - win * 2); feat_print_dbg(fcb, feat, nfr - win * 2, "After LDA"); } if (fcb->subvecs) { feat_subvec_project(fcb, feat, nfr - win * 2); feat_print_dbg(fcb, feat, nfr - win * 2, "After subvector projection"); } }
int32 feat_s2mfc2feat_live(feat_t * fcb, mfcc_t ** uttcep, int32 *inout_ncep, int32 beginutt, int32 endutt, mfcc_t *** ofeat) { int32 win, cepsize, nbufcep; int32 i, j, nfeatvec; int32 zero = 0; /* Avoid having to check this everywhere. */ if (inout_ncep == 0) inout_ncep = &zero; /* Special case for entire utterances. */ if (beginutt && endutt && *inout_ncep > 0) return feat_s2mfc2feat_block_utt(fcb, uttcep, *inout_ncep, ofeat); win = feat_window_size(fcb); cepsize = feat_cepsize(fcb); /* Empty the input buffer on start of utterance. */ if (beginutt) fcb->bufpos = fcb->curpos; /* Calculate how much data is in the buffer already. */ nbufcep = fcb->bufpos - fcb->curpos; if (nbufcep < 0) nbufcep = fcb->bufpos + LIVEBUFBLOCKSIZE - fcb->curpos; /* Add any data that we have to replicate. */ if (beginutt && *inout_ncep > 0) nbufcep += win; if (endutt) nbufcep += win; /* Only consume as much input as will fit in the buffer. */ if (nbufcep + *inout_ncep > LIVEBUFBLOCKSIZE) { /* We also can't overwrite the trailing window, hence the * reason why win is subtracted here. */ *inout_ncep = LIVEBUFBLOCKSIZE - nbufcep - win; /* Cancel end of utterance processing. */ endutt = FALSE; } /* FIXME: Don't modify the input! */ feat_cmn(fcb, uttcep, *inout_ncep, beginutt, endutt); feat_agc(fcb, uttcep, *inout_ncep, beginutt, endutt); /* Replicate first frame into the first win frames if we're at the * beginning of the utterance and there was some actual input to * deal with. (FIXME: Not entirely sure why that condition) */ if (beginutt && *inout_ncep > 0) { for (i = 0; i < win; i++) { memcpy(fcb->cepbuf[fcb->bufpos++], uttcep[0], cepsize * sizeof(mfcc_t)); fcb->bufpos %= LIVEBUFBLOCKSIZE; } /* Move the current pointer past this data. */ fcb->curpos = fcb->bufpos; nbufcep -= win; } /* Copy in frame data to the circular buffer. */ for (i = 0; i < *inout_ncep; ++i) { memcpy(fcb->cepbuf[fcb->bufpos++], uttcep[i], cepsize * sizeof(mfcc_t)); fcb->bufpos %= LIVEBUFBLOCKSIZE; ++nbufcep; } /* Replicate last frame into the last win frames if we're at the * end of the utterance (even if there was no input, so we can * flush the output). */ if (endutt) { int32 tpos; /* Index of last input frame. */ if (fcb->bufpos == 0) tpos = LIVEBUFBLOCKSIZE - 1; else tpos = fcb->bufpos - 1; for (i = 0; i < win; ++i) { memcpy(fcb->cepbuf[fcb->bufpos++], fcb->cepbuf[tpos], cepsize * sizeof(mfcc_t)); fcb->bufpos %= LIVEBUFBLOCKSIZE; } } /* We have to leave the trailing window of frames. */ nfeatvec = nbufcep - win; if (nfeatvec <= 0) return 0; /* Do nothing. */ for (i = 0; i < nfeatvec; ++i) { /* Handle wraparound cases. */ if (fcb->curpos - win < 0 || fcb->curpos + win >= LIVEBUFBLOCKSIZE) { /* Use tmpcepbuf for this case. Actually, we just need the pointers. */ for (j = -win; j <= win; ++j) { int32 tmppos = (fcb->curpos + j + LIVEBUFBLOCKSIZE) % LIVEBUFBLOCKSIZE; fcb->tmpcepbuf[win + j] = fcb->cepbuf[tmppos]; } fcb->compute_feat(fcb, fcb->tmpcepbuf + win, ofeat[i]); } else { fcb->compute_feat(fcb, fcb->cepbuf + fcb->curpos, ofeat[i]); } /* Move the read pointer forward. */ ++fcb->curpos; fcb->curpos %= LIVEBUFBLOCKSIZE; } if (fcb->lda) feat_lda_transform(fcb, ofeat, nfeatvec); if (fcb->subvecs) feat_subvec_project(fcb, ofeat, nfeatvec); return nfeatvec; }