• Main Page
  • Related Pages
  • Data Structures
  • Files
  • File List
  • Globals

src/libsphinxbase/feat/feat.c

00001 /* -*- c-basic-offset: 4; indent-tabs-mode: nil -*- */
00002 /* ====================================================================
00003  * Copyright (c) 1999-2004 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  * feat.c -- Feature vector description and cepstra->feature computation.
00039  *
00040  * **********************************************
00041  * CMU ARPA Speech Project
00042  *
00043  * Copyright (c) 1996 Carnegie Mellon University.
00044  * ALL RIGHTS RESERVED.
00045  * **********************************************
00046  * 
00047  * HISTORY
00048  * $Log$
00049  * Revision 1.22  2006/02/23  03:59:40  arthchan2003
00050  * Merged from branch SPHINX3_5_2_RCI_IRII_BRANCH: a, Free buffers correctly. b, Fixed dox-doc.
00051  * 
00052  * Revision 1.21.4.3  2005/10/17 04:45:57  arthchan2003
00053  * Free stuffs in cmn and feat corectly.
00054  *
00055  * Revision 1.21.4.2  2005/09/26 02:19:57  arthchan2003
00056  * Add message to show the directory which the feature is searched for.
00057  *
00058  * Revision 1.21.4.1  2005/07/03 22:55:50  arthchan2003
00059  * More correct deallocation in feat.c. The cmn deallocation is still not correct at this point.
00060  *
00061  * Revision 1.21  2005/06/22 03:29:35  arthchan2003
00062  * Makefile.am s  for all subdirectory of libs3decoder/
00063  *
00064  * Revision 1.4  2005/04/21 23:50:26  archan
00065  * Some more refactoring on the how reporting of structures inside kbcore_t is done, it is now 50% nice. Also added class-based LM test case into test-decode.sh.in.  At this moment, everything in search mode 5 is already done.  It is time to test the idea whether the search can really be used.
00066  *
00067  * Revision 1.3  2005/03/30 01:22:46  archan
00068  * Fixed mistakes in last updates. Add
00069  *
00070  * 
00071  * 20.Apr.2001  RAH (rhoughton@mediasite.com, ricky.houghton@cs.cmu.edu)
00072  *              Adding feat_free() to free allocated memory
00073  *
00074  * 02-Jan-2001  Rita Singh (rsingh@cs.cmu.edu) at Carnegie Mellon University
00075  *              Modified feat_s2mfc2feat_block() to handle empty buffers at
00076  *              the end of an utterance
00077  *
00078  * 30-Dec-2000  Rita Singh (rsingh@cs.cmu.edu) at Carnegie Mellon University
00079  *              Added feat_s2mfc2feat_block() to allow feature computation
00080  *              from sequences of blocks of cepstral vectors
00081  *
00082  * 12-Jun-98    M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University
00083  *              Major changes to accommodate arbitrary feature input types.  Added
00084  *              feat_read(), moved various cep2feat functions from other files into
00085  *              this one.  Also, made this module object-oriented with the feat_t type.
00086  *              Changed definition of s2mfc_read to let the caller manage MFC buffers.
00087  * 
00088  * 03-Oct-96    M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University
00089  *              Added unistd.h include.
00090  * 
00091  * 02-Oct-96    M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University
00092  *              Added check for sf argument to s2mfc_read being within file size.
00093  * 
00094  * 18-Sep-96    M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University
00095  *              Added sf, ef parameters to s2mfc_read().
00096  * 
00097  * 10-Jan-96    M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University
00098  *              Added feat_cepsize().
00099  *              Added different feature-handling (s2_4x, s3_1x39 at this point).
00100  *              Moved feature-dependent functions to feature-dependent files.
00101  * 
00102  * 09-Jan-96    M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University
00103  *              Moved constant declarations from feat.h into here.
00104  * 
00105  * 04-Nov-95    M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University
00106  *              Created.
00107  */
00108 
00109 
00110 /*
00111  * This module encapsulates different feature streams used by the Sphinx group.  New
00112  * stream types can be added by augmenting feat_init() and providing an accompanying
00113  * compute_feat function.  It also provides a "generic" feature vector definition for
00114  * handling "arbitrary" speech input feature types (see the last section in feat_init()).
00115  * In this case the speech input data should already be feature vectors; no computation,
00116  * such as MFC->feature conversion, is available or needed.
00117  */
00118 
00119 #include <assert.h>
00120 #include <string.h>
00121 #ifdef HAVE_CONFIG_H
00122 #include <config.h>
00123 #endif
00124 
00125 #ifdef _MSC_VER
00126 #pragma warning (disable: 4244 4996)
00127 #endif
00128 
00129 #include "fe.h"
00130 #include "feat.h"
00131 #include "bio.h"
00132 #include "pio.h"
00133 #include "cmn.h"
00134 #include "agc.h"
00135 #include "err.h"
00136 #include "ckd_alloc.h"
00137 #include "prim_type.h"
00138 
00139 #define FEAT_VERSION    "1.0"
00140 #define FEAT_DCEP_WIN           2
00141 
00142 #ifdef DUMP_FEATURES
00143 static void
00144 cep_dump_dbg(feat_t *fcb, mfcc_t **mfc, int32 nfr, const char *text)
00145 {
00146     int32 i, j;
00147 
00148     E_INFO("%s\n", text);
00149     for (i = 0; i < nfr; i++) {
00150         for (j = 0; j < fcb->cepsize; j++) {
00151             fprintf(stderr, "%f ", MFCC2FLOAT(mfc[i][j]));
00152         }
00153         fprintf(stderr, "\n");
00154     }
00155 }
00156 static void
00157 feat_print_dbg(feat_t *fcb, mfcc_t ***feat, int32 nfr, const char *text)
00158 {
00159     E_INFO("%s\n", text);
00160     feat_print(fcb, feat, nfr, stderr);
00161 }
00162 #else /* !DUMP_FEATURES */
00163 #define cep_dump_dbg(fcb,mfc,nfr,text)
00164 #define feat_print_dbg(fcb,mfc,nfr,text)
00165 #endif
00166 
00167 int32 **
00168 parse_subvecs(char const *str)
00169 {
00170     char const *strp;
00171     int32 n, n2, l;
00172     glist_t dimlist;            /* List of dimensions in one subvector */
00173     glist_t veclist;            /* List of dimlists (subvectors) */
00174     int32 **subvec;
00175     gnode_t *gn, *gn2;
00176 
00177     veclist = NULL;
00178 
00179     strp = str;
00180     for (;;) {
00181         dimlist = NULL;
00182 
00183         for (;;) {
00184             if (sscanf(strp, "%d%n", &n, &l) != 1)
00185                 E_FATAL("'%s': Couldn't read int32 @pos %d\n", str,
00186                         strp - str);
00187             strp += l;
00188 
00189             if (*strp == '-') {
00190                 strp++;
00191 
00192                 if (sscanf(strp, "%d%n", &n2, &l) != 1)
00193                     E_FATAL("'%s': Couldn't read int32 @pos %d\n", str,
00194                             strp - str);
00195                 strp += l;
00196             }
00197             else
00198                 n2 = n;
00199 
00200             if ((n < 0) || (n > n2))
00201                 E_FATAL("'%s': Bad subrange spec ending @pos %d\n", str,
00202                         strp - str);
00203 
00204             for (; n <= n2; n++) {
00205                 gnode_t *gn;
00206                 for (gn = dimlist; gn; gn = gnode_next(gn))
00207                     if (gnode_int32(gn) == n)
00208                         break;
00209                 if (gn != NULL)
00210                     E_FATAL("'%s': Duplicate dimension ending @pos %d\n",
00211                             str, strp - str);
00212 
00213                 dimlist = glist_add_int32(dimlist, n);
00214             }
00215 
00216             if ((*strp == '\0') || (*strp == '/'))
00217                 break;
00218 
00219             if (*strp != ',')
00220                 E_FATAL("'%s': Bad delimiter @pos %d\n", str, strp - str);
00221 
00222             strp++;
00223         }
00224 
00225         veclist = glist_add_ptr(veclist, (void *) dimlist);
00226 
00227         if (*strp == '\0')
00228             break;
00229 
00230         assert(*strp == '/');
00231         strp++;
00232     }
00233 
00234     /* Convert the glists to arrays; remember the glists are in reverse order of the input! */
00235     n = glist_count(veclist);   /* #Subvectors */
00236     subvec = (int32 **) ckd_calloc(n + 1, sizeof(int32 *));     /* +1 for sentinel */
00237     subvec[n] = NULL;           /* sentinel */
00238 
00239     for (--n, gn = veclist; (n >= 0) && gn; gn = gnode_next(gn), --n) {
00240         gn2 = (glist_t) gnode_ptr(gn);
00241 
00242         n2 = glist_count(gn2);  /* Length of this subvector */
00243         if (n2 <= 0)
00244             E_FATAL("'%s': 0-length subvector\n", str);
00245 
00246         subvec[n] = (int32 *) ckd_calloc(n2 + 1, sizeof(int32));        /* +1 for sentinel */
00247         subvec[n][n2] = -1;     /* sentinel */
00248 
00249         for (--n2; (n2 >= 0) && gn2; gn2 = gnode_next(gn2), --n2)
00250             subvec[n][n2] = gnode_int32(gn2);
00251         assert((n2 < 0) && (!gn2));
00252     }
00253     assert((n < 0) && (!gn));
00254 
00255     /* Free the glists */
00256     for (gn = veclist; gn; gn = gnode_next(gn)) {
00257         gn2 = (glist_t) gnode_ptr(gn);
00258         glist_free(gn2);
00259     }
00260     glist_free(veclist);
00261 
00262     return subvec;
00263 }
00264 
00265 void
00266 subvecs_free(int32 **subvecs)
00267 {
00268     int32 **sv;
00269 
00270     for (sv = subvecs; sv && *sv; ++sv)
00271         ckd_free(*sv);
00272     ckd_free(subvecs);
00273 }
00274 
00275 int
00276 feat_set_subvecs(feat_t *fcb, int32 **subvecs)
00277 {
00278     int32 **sv;
00279     int32 n_sv, n_dim, i;
00280 
00281     if (subvecs == NULL) {
00282         subvecs_free(fcb->subvecs);
00283         ckd_free(fcb->sv_buf);
00284         ckd_free(fcb->sv_len);
00285         fcb->n_sv = 0;
00286         fcb->subvecs = NULL;
00287         fcb->sv_len = NULL;
00288         fcb->sv_buf = NULL;
00289         fcb->sv_dim = 0;
00290         return 0;
00291     }
00292 
00293     if (fcb->n_stream != 1) {
00294         E_ERROR("Subvector specifications require single-stream features!");
00295         return -1;
00296     }
00297 
00298     n_sv = 0;
00299     n_dim = 0;
00300     for (sv = subvecs; sv && *sv; ++sv) {
00301         int32 *d;
00302 
00303         for (d = *sv; d && *d != -1; ++d) {
00304             ++n_dim;
00305         }
00306         ++n_sv;
00307     }
00308     if (n_dim > (int)feat_dimension(fcb)) {
00309         E_ERROR("Total dimensionality of subvector specification %d "
00310                 "> feature dimensionality %d\n", n_dim, feat_dimension(fcb));
00311         return -1;
00312     }
00313 
00314     fcb->n_sv = n_sv;
00315     fcb->subvecs = subvecs;
00316     fcb->sv_len = ckd_calloc(n_sv, sizeof(*fcb->sv_len));
00317     fcb->sv_buf = ckd_calloc(n_dim, sizeof(*fcb->sv_buf));
00318     fcb->sv_dim = n_dim;
00319     for (i = 0; i < n_sv; ++i) {
00320         int32 *d;
00321         for (d = subvecs[i]; d && *d != -1; ++d) {
00322             ++fcb->sv_len[i];
00323         }
00324     }
00325 
00326     return 0;
00327 }
00328 
00332 static void
00333 feat_subvec_project(feat_t *fcb, mfcc_t ***inout_feat, uint32 nfr)
00334 {
00335     uint32 i;
00336 
00337     if (fcb->subvecs == NULL)
00338         return;
00339     for (i = 0; i < nfr; ++i) {
00340         mfcc_t *out;
00341         int32 j;
00342 
00343         out = fcb->sv_buf;
00344         for (j = 0; j < fcb->n_sv; ++j) {
00345             int32 *d;
00346             for (d = fcb->subvecs[j]; d && *d != -1; ++d) {
00347                 *out++ = inout_feat[i][0][*d];
00348             }
00349         }
00350         memcpy(inout_feat[i][0], fcb->sv_buf, fcb->sv_dim * sizeof(*fcb->sv_buf));
00351     }
00352 }
00353 
00354 /*
00355  * Read specified segment [sf-win..ef+win] of Sphinx-II format mfc file read and return
00356  * #frames read.  Return -1 if error.
00357  */
00358 int32
00359 feat_s2mfc_read(char *file, int32 win,
00360                 int32 sf, int32 ef,
00361                 mfcc_t ***out_mfc,
00362                 int32 maxfr,
00363                 int32 cepsize)
00364 {
00365     FILE *fp;
00366     int32 n_float32;
00367     float32 *float_feat;
00368     struct stat statbuf;
00369     int32 i, n, byterev;
00370     int32 start_pad, end_pad;
00371     mfcc_t **mfc;
00372 
00373     /* Initialize the output pointer to NULL, so that any attempts to
00374        free() it if we fail before allocating it will not segfault! */
00375     if (out_mfc)
00376         *out_mfc = NULL;
00377     E_INFO("Reading mfc file: '%s'[%d..%d]\n", file, sf, ef);
00378     if (ef >= 0 && ef <= sf) {
00379         E_ERROR("%s: End frame (%d) <= Start frame (%d)\n", file, ef, sf);
00380         return -1;
00381     }
00382 
00383     /* Find filesize; HACK!! To get around intermittent NFS failures, use stat_retry */
00384     if ((stat_retry(file, &statbuf) < 0)
00385         || ((fp = fopen(file, "rb")) == NULL)) {
00386         E_ERROR("stat_retry/fopen(%s) failed\n", file);
00387         return -1;
00388     }
00389 
00390     /* Read #floats in header */
00391     if (fread_retry(&n_float32, sizeof(int32), 1, fp) != 1) {
00392         E_ERROR("%s: fread(#floats) failed\n", file);
00393         fclose(fp);
00394         return -1;
00395     }
00396 
00397     /* Check if n_float32 matches file size */
00398     byterev = 0;
00399     if ((int32) (n_float32 * sizeof(float32) + 4) != (int32) statbuf.st_size) { /* RAH, typecast both sides to remove compile warning */
00400         n = n_float32;
00401         SWAP_INT32(&n);
00402 
00403         if ((int32) (n * sizeof(float32) + 4) != (int32) (statbuf.st_size)) {   /* RAH, typecast both sides to remove compile warning */
00404             E_ERROR
00405                 ("%s: Header size field: %d(%08x); filesize: %d(%08x)\n",
00406                  file, n_float32, n_float32, statbuf.st_size,
00407                  statbuf.st_size);
00408             fclose(fp);
00409             return -1;
00410         }
00411 
00412         n_float32 = n;
00413         byterev = 1;
00414     }
00415     if (n_float32 <= 0) {
00416         E_ERROR("%s: Header size field (#floats) = %d\n", file, n_float32);
00417         fclose(fp);
00418         return -1;
00419     }
00420 
00421     /* Convert n to #frames of input */
00422     n = n_float32 / cepsize;
00423     if (n * cepsize != n_float32) {
00424         E_ERROR("Header size field: %d; not multiple of %d\n", n_float32,
00425                 cepsize);
00426         fclose(fp);
00427         return -1;
00428     }
00429 
00430     /* Check start and end frames */
00431     if (sf > 0) {
00432         if (sf >= n) {
00433             E_ERROR("%s: Start frame (%d) beyond file size (%d)\n", file,
00434                     sf, n);
00435             fclose(fp);
00436             return -1;
00437         }
00438     }
00439     if (ef < 0)
00440         ef = n-1;
00441     else if (ef >= n) {
00442         E_WARN("%s: End frame (%d) beyond file size (%d), will truncate\n",
00443                file, ef, n);
00444         ef = n-1;
00445     }
00446 
00447     /* Add window to start and end frames */
00448     sf -= win;
00449     ef += win;
00450     if (sf < 0) {
00451         start_pad = -sf;
00452         sf = 0;
00453     }
00454     else
00455         start_pad = 0;
00456     if (ef >= n) {
00457         end_pad = ef - n + 1;
00458         ef = n - 1;
00459     }
00460     else
00461         end_pad = 0;
00462 
00463     /* Limit n if indicated by [sf..ef] */
00464     if ((ef - sf + 1) < n)
00465         n = (ef - sf + 1);
00466     if (maxfr > 0 && n + start_pad + end_pad > maxfr) {
00467         E_ERROR("%s: Maximum output size(%d frames) < actual #frames(%d)\n",
00468                 file, maxfr, n + start_pad + end_pad);
00469         fclose(fp);
00470         return -1;
00471     }
00472 
00473     /* If no output buffer was supplied, then skip the actual data reading. */
00474     if (out_mfc != NULL) {
00475         /* Position at desired start frame and read actual MFC data */
00476         mfc = (mfcc_t **)ckd_calloc_2d(n + start_pad + end_pad, cepsize, sizeof(mfcc_t));
00477         if (sf > 0)
00478             fseek(fp, sf * cepsize * sizeof(float32), SEEK_CUR);
00479         n_float32 = n * cepsize;
00480 #ifdef FIXED_POINT
00481         float_feat = ckd_calloc(n_float32, sizeof(float32));
00482 #else
00483         float_feat = mfc[start_pad];
00484 #endif
00485         if (fread_retry(float_feat, sizeof(float32), n_float32, fp) != n_float32) {
00486             E_ERROR("%s: fread(%dx%d) (MFC data) failed\n", file, n, cepsize);
00487             fclose(fp);
00488             return -1;
00489         }
00490         if (byterev) {
00491             for (i = 0; i < n_float32; i++) {
00492                 SWAP_FLOAT32(&float_feat[i]);
00493             }
00494         }
00495 #ifdef FIXED_POINT
00496         for (i = 0; i < n_float32; ++i) {
00497             mfc[start_pad][i] = FLOAT2MFCC(float_feat[i]);
00498         }
00499         ckd_free(float_feat);
00500 #endif
00501 
00502         /* Replicate start and end frames if necessary. */
00503         for (i = 0; i < start_pad; ++i)
00504             memcpy(mfc[i], mfc[start_pad], cepsize * sizeof(mfcc_t));
00505         for (i = 0; i < end_pad; ++i)
00506             memcpy(mfc[start_pad + n + i], mfc[start_pad + n - 1],
00507                    cepsize * sizeof(mfcc_t));
00508 
00509         *out_mfc = mfc;
00510     }
00511 
00512     fclose(fp);
00513     return n + start_pad + end_pad;
00514 }
00515 
00516 mfcc_t ***
00517 feat_array_alloc(feat_t * fcb, int32 nfr)
00518 {
00519     int32 i, j, k;
00520     mfcc_t *data, *d, ***feat;
00521 
00522     assert(fcb);
00523     assert(nfr > 0);
00524     assert(feat_dimension(fcb) > 0);
00525 
00526     /* Make sure to use the dimensionality of the features *before*
00527        LDA and subvector projection. */
00528     k = 0;
00529     for (i = 0; i < fcb->n_stream; ++i)
00530         k += fcb->stream_len[i];
00531     assert(k >= (int)feat_dimension(fcb));
00532     assert(k >= fcb->sv_dim);
00533 
00534     feat =
00535         (mfcc_t ***) ckd_calloc_2d(nfr, feat_dimension1(fcb), sizeof(mfcc_t *));
00536     data = (mfcc_t *) ckd_calloc(nfr * k, sizeof(mfcc_t));
00537 
00538     for (i = 0; i < nfr; i++) {
00539         d = data + i * k;
00540         for (j = 0; j < feat_dimension1(fcb); j++) {
00541             feat[i][j] = d;
00542             d += feat_dimension2(fcb, j);
00543         }
00544     }
00545 
00546     return feat;
00547 }
00548 
00549 void
00550 feat_array_free(mfcc_t ***feat)
00551 {
00552     ckd_free(feat[0][0]);
00553     ckd_free_2d((void **)feat);
00554 }
00555 
00556 static void
00557 feat_s2_4x_cep2feat(feat_t * fcb, mfcc_t ** mfc, mfcc_t ** feat)
00558 {
00559     mfcc_t *f;
00560     mfcc_t *w, *_w;
00561     mfcc_t *w1, *w_1, *_w1, *_w_1;
00562     mfcc_t d1, d2;
00563     int32 i, j;
00564 
00565     assert(fcb);
00566     assert(feat_cepsize(fcb) == 13);
00567     assert(feat_n_stream(fcb) == 4);
00568     assert(feat_stream_len(fcb, 0) == 12);
00569     assert(feat_stream_len(fcb, 1) == 24);
00570     assert(feat_stream_len(fcb, 2) == 3);
00571     assert(feat_stream_len(fcb, 3) == 12);
00572     assert(feat_window_size(fcb) == 4);
00573 
00574     /* CEP; skip C0 */
00575     memcpy(feat[0], mfc[0] + 1, (feat_cepsize(fcb) - 1) * sizeof(mfcc_t));
00576 
00577     /*
00578      * DCEP(SHORT): mfc[2] - mfc[-2]
00579      * DCEP(LONG):  mfc[4] - mfc[-4]
00580      */
00581     w = mfc[2] + 1;             /* +1 to skip C0 */
00582     _w = mfc[-2] + 1;
00583 
00584     f = feat[1];
00585     for (i = 0; i < feat_cepsize(fcb) - 1; i++) /* Short-term */
00586         f[i] = w[i] - _w[i];
00587 
00588     w = mfc[4] + 1;             /* +1 to skip C0 */
00589     _w = mfc[-4] + 1;
00590 
00591     for (j = 0; j < feat_cepsize(fcb) - 1; i++, j++)    /* Long-term */
00592         f[i] = w[j] - _w[j];
00593 
00594     /* D2CEP: (mfc[3] - mfc[-1]) - (mfc[1] - mfc[-3]) */
00595     w1 = mfc[3] + 1;            /* Final +1 to skip C0 */
00596     _w1 = mfc[-1] + 1;
00597     w_1 = mfc[1] + 1;
00598     _w_1 = mfc[-3] + 1;
00599 
00600     f = feat[3];
00601     for (i = 0; i < feat_cepsize(fcb) - 1; i++) {
00602         d1 = w1[i] - _w1[i];
00603         d2 = w_1[i] - _w_1[i];
00604 
00605         f[i] = d1 - d2;
00606     }
00607 
00608     /* POW: C0, DC0, D2C0; differences computed as above for rest of cep */
00609     f = feat[2];
00610     f[0] = mfc[0][0];
00611     f[1] = mfc[2][0] - mfc[-2][0];
00612 
00613     d1 = mfc[3][0] - mfc[-1][0];
00614     d2 = mfc[1][0] - mfc[-3][0];
00615     f[2] = d1 - d2;
00616 }
00617 
00618 
00619 static void
00620 feat_s3_1x39_cep2feat(feat_t * fcb, mfcc_t ** mfc, mfcc_t ** feat)
00621 {
00622     mfcc_t *f;
00623     mfcc_t *w, *_w;
00624     mfcc_t *w1, *w_1, *_w1, *_w_1;
00625     mfcc_t d1, d2;
00626     int32 i;
00627 
00628     assert(fcb);
00629     assert(feat_cepsize(fcb) == 13);
00630     assert(feat_n_stream(fcb) == 1);
00631     assert(feat_stream_len(fcb, 0) == 39);
00632     assert(feat_window_size(fcb) == 3);
00633 
00634     /* CEP; skip C0 */
00635     memcpy(feat[0], mfc[0] + 1, (feat_cepsize(fcb) - 1) * sizeof(mfcc_t));
00636     /*
00637      * DCEP: mfc[2] - mfc[-2];
00638      */
00639     f = feat[0] + feat_cepsize(fcb) - 1;
00640     w = mfc[2] + 1;             /* +1 to skip C0 */
00641     _w = mfc[-2] + 1;
00642 
00643     for (i = 0; i < feat_cepsize(fcb) - 1; i++)
00644         f[i] = w[i] - _w[i];
00645 
00646     /* POW: C0, DC0, D2C0 */
00647     f += feat_cepsize(fcb) - 1;
00648 
00649     f[0] = mfc[0][0];
00650     f[1] = mfc[2][0] - mfc[-2][0];
00651 
00652     d1 = mfc[3][0] - mfc[-1][0];
00653     d2 = mfc[1][0] - mfc[-3][0];
00654     f[2] = d1 - d2;
00655 
00656     /* D2CEP: (mfc[3] - mfc[-1]) - (mfc[1] - mfc[-3]) */
00657     f += 3;
00658 
00659     w1 = mfc[3] + 1;            /* Final +1 to skip C0 */
00660     _w1 = mfc[-1] + 1;
00661     w_1 = mfc[1] + 1;
00662     _w_1 = mfc[-3] + 1;
00663 
00664     for (i = 0; i < feat_cepsize(fcb) - 1; i++) {
00665         d1 = w1[i] - _w1[i];
00666         d2 = w_1[i] - _w_1[i];
00667 
00668         f[i] = d1 - d2;
00669     }
00670 }
00671 
00672 
00673 static void
00674 feat_s3_cep(feat_t * fcb, mfcc_t ** mfc, mfcc_t ** feat)
00675 {
00676     assert(fcb);
00677     assert(feat_n_stream(fcb) == 1);
00678     assert(feat_window_size(fcb) == 0);
00679 
00680     /* CEP */
00681     memcpy(feat[0], mfc[0], feat_cepsize(fcb) * sizeof(mfcc_t));
00682 }
00683 
00684 
00685 static void
00686 feat_s3_cep_dcep(feat_t * fcb, mfcc_t ** mfc, mfcc_t ** feat)
00687 {
00688     mfcc_t *f;
00689     mfcc_t *w, *_w;
00690     int32 i;
00691 
00692     assert(fcb);
00693     assert(feat_n_stream(fcb) == 1);
00694     assert(feat_stream_len(fcb, 0) == feat_cepsize(fcb) * 2);
00695     assert(feat_window_size(fcb) == 2);
00696 
00697     /* CEP */
00698     memcpy(feat[0], mfc[0], feat_cepsize(fcb) * sizeof(mfcc_t));
00699 
00700     /*
00701      * DCEP: mfc[2] - mfc[-2];
00702      */
00703     f = feat[0] + feat_cepsize(fcb);
00704     w = mfc[2];
00705     _w = mfc[-2];
00706 
00707     for (i = 0; i < feat_cepsize(fcb); i++)
00708         f[i] = w[i] - _w[i];
00709 }
00710 
00711 static void
00712 feat_1s_c_d_dd_cep2feat(feat_t * fcb, mfcc_t ** mfc, mfcc_t ** feat)
00713 {
00714     mfcc_t *f;
00715     mfcc_t *w, *_w;
00716     mfcc_t *w1, *w_1, *_w1, *_w_1;
00717     mfcc_t d1, d2;
00718     int32 i;
00719 
00720     assert(fcb);
00721     assert(feat_n_stream(fcb) == 1);
00722     assert(feat_stream_len(fcb, 0) == feat_cepsize(fcb) * 3);
00723     assert(feat_window_size(fcb) == FEAT_DCEP_WIN + 1);
00724 
00725     /* CEP */
00726     memcpy(feat[0], mfc[0], feat_cepsize(fcb) * sizeof(mfcc_t));
00727 
00728     /*
00729      * DCEP: mfc[w] - mfc[-w], where w = FEAT_DCEP_WIN;
00730      */
00731     f = feat[0] + feat_cepsize(fcb);
00732     w = mfc[FEAT_DCEP_WIN];
00733     _w = mfc[-FEAT_DCEP_WIN];
00734 
00735     for (i = 0; i < feat_cepsize(fcb); i++)
00736         f[i] = w[i] - _w[i];
00737 
00738     /* 
00739      * D2CEP: (mfc[w+1] - mfc[-w+1]) - (mfc[w-1] - mfc[-w-1]), 
00740      * where w = FEAT_DCEP_WIN 
00741      */
00742     f += feat_cepsize(fcb);
00743 
00744     w1 = mfc[FEAT_DCEP_WIN + 1];
00745     _w1 = mfc[-FEAT_DCEP_WIN + 1];
00746     w_1 = mfc[FEAT_DCEP_WIN - 1];
00747     _w_1 = mfc[-FEAT_DCEP_WIN - 1];
00748 
00749     for (i = 0; i < feat_cepsize(fcb); i++) {
00750         d1 = w1[i] - _w1[i];
00751         d2 = w_1[i] - _w_1[i];
00752 
00753         f[i] = d1 - d2;
00754     }
00755 }
00756 
00757 static void
00758 feat_1s_c_d_ld_dd_cep2feat(feat_t * fcb, mfcc_t ** mfc, mfcc_t ** feat)
00759 {
00760     mfcc_t *f;
00761     mfcc_t *w, *_w;
00762     mfcc_t *w1, *w_1, *_w1, *_w_1;
00763     mfcc_t d1, d2;
00764     int32 i;
00765 
00766     assert(fcb);
00767     assert(feat_n_stream(fcb) == 1);
00768     assert(feat_stream_len(fcb, 0) == feat_cepsize(fcb) * 4);
00769     assert(feat_window_size(fcb) == FEAT_DCEP_WIN * 2);
00770 
00771     /* CEP */
00772     memcpy(feat[0], mfc[0], feat_cepsize(fcb) * sizeof(mfcc_t));
00773 
00774     /*
00775      * DCEP: mfc[w] - mfc[-w], where w = FEAT_DCEP_WIN;
00776      */
00777     f = feat[0] + feat_cepsize(fcb);
00778     w = mfc[FEAT_DCEP_WIN];
00779     _w = mfc[-FEAT_DCEP_WIN];
00780 
00781     for (i = 0; i < feat_cepsize(fcb); i++)
00782         f[i] = w[i] - _w[i];
00783 
00784     /*
00785      * LDCEP: mfc[w] - mfc[-w], where w = FEAT_DCEP_WIN * 2;
00786      */
00787     f += feat_cepsize(fcb);
00788     w = mfc[FEAT_DCEP_WIN * 2];
00789     _w = mfc[-FEAT_DCEP_WIN * 2];
00790 
00791     for (i = 0; i < feat_cepsize(fcb); i++)
00792         f[i] = w[i] - _w[i];
00793 
00794     /* 
00795      * D2CEP: (mfc[w+1] - mfc[-w+1]) - (mfc[w-1] - mfc[-w-1]), 
00796      * where w = FEAT_DCEP_WIN 
00797      */
00798     f += feat_cepsize(fcb);
00799 
00800     w1 = mfc[FEAT_DCEP_WIN + 1];
00801     _w1 = mfc[-FEAT_DCEP_WIN + 1];
00802     w_1 = mfc[FEAT_DCEP_WIN - 1];
00803     _w_1 = mfc[-FEAT_DCEP_WIN - 1];
00804 
00805     for (i = 0; i < feat_cepsize(fcb); i++) {
00806         d1 = w1[i] - _w1[i];
00807         d2 = w_1[i] - _w_1[i];
00808 
00809         f[i] = d1 - d2;
00810     }
00811 }
00812 
00813 static void
00814 feat_copy(feat_t * fcb, mfcc_t ** mfc, mfcc_t ** feat)
00815 {
00816     int32 win, i, j;
00817 
00818     win = feat_window_size(fcb);
00819 
00820     /* Concatenate input features */
00821     for (i = -win; i <= win; ++i) {
00822         uint32 spos = 0;
00823 
00824         for (j = 0; j < feat_n_stream(fcb); ++j) {
00825             uint32 stream_len;
00826 
00827             /* Unscale the stream length by the window. */
00828             stream_len = feat_stream_len(fcb, j) / (2 * win + 1);
00829             memcpy(feat[j] + ((i + win) * stream_len),
00830                    mfc[i] + spos,
00831                    stream_len * sizeof(mfcc_t));
00832             spos += stream_len;
00833         }
00834     }
00835 }
00836 
00837 feat_t *
00838 feat_init(char const *type, cmn_type_t cmn, int32 varnorm,
00839           agc_type_t agc, int32 breport, int32 cepsize)
00840 {
00841     feat_t *fcb;
00842     int32 i, l, k;
00843     __BIGSTACKVARIABLE__ char wd[16384];
00844     char *strp;
00845 
00846     if (cepsize == 0)
00847         cepsize = 13;
00848     if (breport)
00849         E_INFO
00850             ("Initializing feature stream to type: '%s', ceplen=%d, CMN='%s', VARNORM='%s', AGC='%s'\n",
00851              type, cepsize, cmn_type_str[cmn], varnorm ? "yes" : "no", agc_type_str[agc]);
00852 
00853     fcb = (feat_t *) ckd_calloc(1, sizeof(feat_t));
00854     fcb->refcount = 1;
00855     fcb->name = (char *) ckd_salloc(type);
00856     if (strcmp(type, "s2_4x") == 0) {
00857         /* Sphinx-II format 4-stream feature (Hack!! hardwired constants below) */
00858         if (cepsize != 13) {
00859             E_ERROR("s2_4x features require cepsize == 13\n");
00860             ckd_free(fcb);
00861             return NULL;
00862         }
00863         fcb->cepsize = 13;
00864         fcb->n_stream = 4;
00865         fcb->stream_len = (int32 *) ckd_calloc(4, sizeof(int32));
00866         fcb->stream_len[0] = 12;
00867         fcb->stream_len[1] = 24;
00868         fcb->stream_len[2] = 3;
00869         fcb->stream_len[3] = 12;
00870         fcb->out_dim = 51;
00871         fcb->window_size = 4;
00872         fcb->compute_feat = feat_s2_4x_cep2feat;
00873     }
00874     else if (strcmp(type, "s3_1x39") == 0) {
00875         /* 1-stream cep/dcep/pow/ddcep (Hack!! hardwired constants below) */
00876         if (cepsize != 13) {
00877             E_ERROR("s2_4x features require cepsize == 13\n");
00878             ckd_free(fcb);
00879             return NULL;
00880         }
00881         fcb->cepsize = 13;
00882         fcb->n_stream = 1;
00883         fcb->stream_len = (int32 *) ckd_calloc(1, sizeof(int32));
00884         fcb->stream_len[0] = 39;
00885         fcb->out_dim = 39;
00886         fcb->window_size = 3;
00887         fcb->compute_feat = feat_s3_1x39_cep2feat;
00888     }
00889     else if (strncmp(type, "1s_c_d_dd", 9) == 0) {
00890         fcb->cepsize = cepsize;
00891         fcb->n_stream = 1;
00892         fcb->stream_len = (int32 *) ckd_calloc(1, sizeof(int32));
00893         fcb->stream_len[0] = cepsize * 3;
00894         fcb->out_dim = cepsize * 3;
00895         fcb->window_size = FEAT_DCEP_WIN + 1; /* ddcep needs the extra 1 */
00896         fcb->compute_feat = feat_1s_c_d_dd_cep2feat;
00897     }
00898     else if (strncmp(type, "1s_c_d_ld_dd", 12) == 0) {
00899         fcb->cepsize = cepsize;
00900         fcb->n_stream = 1;
00901         fcb->stream_len = (int32 *) ckd_calloc(1, sizeof(int32));
00902         fcb->stream_len[0] = cepsize * 4;
00903         fcb->out_dim = cepsize * 4;
00904         fcb->window_size = FEAT_DCEP_WIN * 2;
00905         fcb->compute_feat = feat_1s_c_d_ld_dd_cep2feat;
00906     }
00907     else if (strncmp(type, "cep_dcep", 8) == 0 || strncmp(type, "1s_c_d", 6) == 0) {
00908         /* 1-stream cep/dcep */
00909         fcb->cepsize = cepsize;
00910         fcb->n_stream = 1;
00911         fcb->stream_len = (int32 *) ckd_calloc(1, sizeof(int32));
00912         fcb->stream_len[0] = feat_cepsize(fcb) * 2;
00913         fcb->out_dim = fcb->stream_len[0];
00914         fcb->window_size = 2;
00915         fcb->compute_feat = feat_s3_cep_dcep;
00916     }
00917     else if (strncmp(type, "cep", 3) == 0 || strncmp(type, "1s_c", 4) == 0) {
00918         /* 1-stream cep */
00919         fcb->cepsize = cepsize;
00920         fcb->n_stream = 1;
00921         fcb->stream_len = (int32 *) ckd_calloc(1, sizeof(int32));
00922         fcb->stream_len[0] = feat_cepsize(fcb);
00923         fcb->out_dim = fcb->stream_len[0];
00924         fcb->window_size = 0;
00925         fcb->compute_feat = feat_s3_cep;
00926     }
00927     else {
00928         char *mtype = ckd_salloc(type);
00929         /*
00930          * Generic definition: Format should be %d,%d,%d,...,%d (i.e.,
00931          * comma separated list of feature stream widths; #items =
00932          * #streams).  An optional window size (frames will be
00933          * concatenated) is also allowed, which can be specified with
00934          * a colon after the list of feature streams.
00935          */
00936         l = strlen(mtype);
00937         k = 0;
00938         for (i = 1; i < l - 1; i++) {
00939             if (mtype[i] == ',') {
00940                 mtype[i] = ' ';
00941                 k++;
00942             }
00943             else if (mtype[i] == ':') {
00944                 mtype[i] = '\0';
00945                 fcb->window_size = atoi(mtype + i + 1);
00946                 break;
00947             }
00948         }
00949         k++;                    /* Presumably there are (#commas+1) streams */
00950         fcb->n_stream = k;
00951         fcb->stream_len = (int32 *) ckd_calloc(k, sizeof(int32));
00952 
00953         /* Scan individual feature stream lengths */
00954         strp = mtype;
00955         i = 0;
00956         fcb->out_dim = 0;
00957         fcb->cepsize = 0;
00958         while (sscanf(strp, "%s%n", wd, &l) == 1) {
00959             strp += l;
00960             if ((i >= fcb->n_stream)
00961                 || (sscanf(wd, "%d", &(fcb->stream_len[i])) != 1)
00962                 || (fcb->stream_len[i] <= 0))
00963                 E_FATAL("Bad feature type argument\n");
00964             /* Input size before windowing */
00965             fcb->cepsize += fcb->stream_len[i];
00966             if (fcb->window_size > 0)
00967                 fcb->stream_len[i] *= (fcb->window_size * 2 + 1);
00968             /* Output size after windowing */
00969             fcb->out_dim += fcb->stream_len[i];
00970             i++;
00971         }
00972         if (i != fcb->n_stream)
00973             E_FATAL("Bad feature type argument\n");
00974 
00975         /* Input is already the feature stream */
00976         fcb->compute_feat = feat_copy;
00977         ckd_free(mtype);
00978     }
00979 
00980     if (cmn != CMN_NONE)
00981         fcb->cmn_struct = cmn_init(feat_cepsize(fcb));
00982     fcb->cmn = cmn;
00983     fcb->varnorm = varnorm;
00984     if (agc != AGC_NONE) {
00985         fcb->agc_struct = agc_init();
00986         /*
00987          * No need to check if agc is set to EMAX; agc_emax_set() changes only emax related things
00988          * Moreover, if agc is not NONE and block mode is used, feat_agc() SILENTLY
00989          * switches to EMAX
00990          */
00991         /* HACK: hardwired initial estimates based on use of CMN (from Sphinx2) */
00992         agc_emax_set(fcb->agc_struct, (cmn != CMN_NONE) ? 5.0 : 10.0);
00993     }
00994     fcb->agc = agc;
00995     fcb->cepbuf = (mfcc_t **) ckd_calloc_2d(LIVEBUFBLOCKSIZE,
00996                                             feat_cepsize(fcb),
00997                                             sizeof(mfcc_t));
00998     /* This one is actually just an array of pointers to "flatten out"
00999      * wraparounds. */
01000     fcb->tmpcepbuf = ckd_calloc(2 * feat_window_size(fcb) + 1,
01001                                 sizeof(*fcb->tmpcepbuf));
01002     return fcb;
01003 }
01004 
01005 
01006 void
01007 feat_print(feat_t * fcb, mfcc_t *** feat, int32 nfr, FILE * fp)
01008 {
01009     int32 i, j, k;
01010 
01011     for (i = 0; i < nfr; i++) {
01012         fprintf(fp, "%8d:\n", i);
01013 
01014         for (j = 0; j < feat_dimension1(fcb); j++) {
01015             fprintf(fp, "\t%2d:", j);
01016 
01017             for (k = 0; k < feat_dimension2(fcb, j); k++)
01018                 fprintf(fp, " %8.4f", MFCC2FLOAT(feat[i][j][k]));
01019             fprintf(fp, "\n");
01020         }
01021     }
01022 
01023     fflush(fp);
01024 }
01025 
01026 static void
01027 feat_cmn(feat_t *fcb, mfcc_t **mfc, int32 nfr, int32 beginutt, int32 endutt)
01028 {
01029     cmn_type_t cmn_type = fcb->cmn;
01030 
01031     if (!(beginutt && endutt)
01032         && cmn_type != CMN_NONE) /* Only cmn_prior in block computation mode. */
01033         cmn_type = CMN_PRIOR;
01034 
01035     switch (cmn_type) {
01036     case CMN_CURRENT:
01037         cmn(fcb->cmn_struct, mfc, fcb->varnorm, nfr);
01038         break;
01039     case CMN_PRIOR:
01040         cmn_prior(fcb->cmn_struct, mfc, fcb->varnorm, nfr);
01041         if (endutt)
01042             cmn_prior_update(fcb->cmn_struct);
01043         break;
01044     default:
01045         ;
01046     }
01047     cep_dump_dbg(fcb, mfc, nfr, "After CMN");
01048 }
01049 
01050 static void
01051 feat_agc(feat_t *fcb, mfcc_t **mfc, int32 nfr, int32 beginutt, int32 endutt)
01052 {
01053     agc_type_t agc_type = fcb->agc;
01054 
01055     if (!(beginutt && endutt)
01056         && agc_type != AGC_NONE) /* Only agc_emax in block computation mode. */
01057         agc_type = AGC_EMAX;
01058 
01059     switch (agc_type) {
01060     case AGC_MAX:
01061         agc_max(fcb->agc_struct, mfc, nfr);
01062         break;
01063     case AGC_EMAX:
01064         agc_emax(fcb->agc_struct, mfc, nfr);
01065         if (endutt)
01066             agc_emax_update(fcb->agc_struct);
01067         break;
01068     case AGC_NOISE:
01069         agc_noise(fcb->agc_struct, mfc, nfr);
01070         break;
01071     default:
01072         ;
01073     }
01074     cep_dump_dbg(fcb, mfc, nfr, "After AGC");
01075 }
01076 
01077 static void
01078 feat_compute_utt(feat_t *fcb, mfcc_t **mfc, int32 nfr, int32 win, mfcc_t ***feat)
01079 {
01080     int32 i;
01081 
01082     cep_dump_dbg(fcb, mfc, nfr, "Incoming features (after padding)");
01083     feat_cmn(fcb, mfc, nfr, 1, 1);
01084     feat_agc(fcb, mfc, nfr, 1, 1);
01085 
01086     /* Create feature vectors */
01087     for (i = win; i < nfr - win; i++) {
01088         fcb->compute_feat(fcb, mfc + i, feat[i - win]);
01089     }
01090 
01091     feat_print_dbg(fcb, feat, nfr - win * 2, "After dynamic feature computation");
01092 
01093     if (fcb->lda) {
01094         feat_lda_transform(fcb, feat, nfr - win * 2);
01095         feat_print_dbg(fcb, feat, nfr - win * 2, "After LDA");
01096     }
01097 
01098     if (fcb->subvecs) {
01099         feat_subvec_project(fcb, feat, nfr - win * 2);
01100         feat_print_dbg(fcb, feat, nfr - win * 2, "After subvector projection");
01101     }
01102 }
01103 
01104 int32
01105 feat_s2mfc2feat(feat_t * fcb, const char *file, const char *dir, const char *cepext,
01106                 int32 sf, int32 ef, mfcc_t *** feat, int32 maxfr)
01107 {
01108     __BIGSTACKVARIABLE__ char path[16384];
01109     int32 win, nfr;
01110     int32 file_length, cepext_length;
01111     mfcc_t **mfc;
01112 
01113     if (cepext == NULL)
01114         cepext = "";
01115 
01116     if (fcb->cepsize <= 0) {
01117         E_ERROR("Bad cepsize: %d\n", fcb->cepsize);
01118         return -1;
01119     }
01120 
01121 
01122     /* 
01123      * Create mfc filename, combining file, dir and extension if
01124      * necessary
01125      */
01126 
01127     /*
01128      * First we decide about the path. If dir is defined, then use
01129      * it. Otherwise. assume the filename already contains the path.
01130      */
01131 
01132     if (dir != NULL) {
01133         sprintf(path, "%s/%s", dir, file);
01134         E_INFO("At directory %s\n", dir);
01135     }
01136     else {
01137         strcpy(path, file);
01138         E_INFO("At directory . (current directory)\n", dir);
01139     }
01140 
01141     /*
01142      * Now include the cepext, if it's not already part of the filename.
01143      */
01144     file_length = strlen(file);
01145     cepext_length = strlen(cepext);
01146     if ((file_length <= cepext_length)
01147         || (strcmp(file + file_length - cepext_length, cepext) != 0)) {
01148         strcat(path, cepext);
01149     }
01150 
01151     win = feat_window_size(fcb);
01152     /* Pad maxfr with win, so we read enough raw feature data to
01153      * calculate the requisite number of dynamic features. */
01154     if (maxfr >= 0)
01155         maxfr += win * 2;
01156 
01157     if (feat != NULL) {
01158         /* Read mfc file including window or padding if necessary. */
01159         nfr = feat_s2mfc_read(path, win, sf, ef, &mfc, maxfr, fcb->cepsize);
01160         if (nfr < 0) {
01161             ckd_free_2d((void **) mfc);
01162             return -1;
01163         }
01164         /* Actually compute the features */
01165         feat_compute_utt(fcb, mfc, nfr, win, feat);
01166         ckd_free_2d((void **) mfc);
01167     }
01168     else {
01169         /* Just calculate the number of frames we would need. */
01170         nfr = feat_s2mfc_read(path, win, sf, ef, NULL, maxfr, fcb->cepsize);
01171         if (nfr < 0)
01172             return nfr;
01173     }
01174 
01175 
01176     return (nfr - win * 2);
01177 }
01178 
01179 static int32
01180 feat_s2mfc2feat_block_utt(feat_t * fcb, mfcc_t ** uttcep,
01181                           int32 nfr, mfcc_t *** ofeat)
01182 {
01183     mfcc_t **cepbuf;
01184     int32 i, win, cepsize;
01185 
01186     win = feat_window_size(fcb);
01187     cepsize = feat_cepsize(fcb);
01188 
01189     /* Copy and pad out the utterance (this requires that the
01190      * feature computation functions always access the buffer via
01191      * the frame pointers, which they do)  */
01192     cepbuf = ckd_calloc(nfr + win * 2, sizeof(mfcc_t *));
01193     memcpy(cepbuf + win, uttcep, nfr * sizeof(mfcc_t *));
01194     for (i = 0; i < win; ++i) {
01195         cepbuf[i] = ckd_calloc(cepsize, sizeof(mfcc_t));
01196         memcpy(cepbuf[i], uttcep[0], cepsize * sizeof(mfcc_t));
01197         cepbuf[nfr + win + i] = ckd_calloc(cepsize, sizeof(mfcc_t));
01198         memcpy(cepbuf[nfr + win + i], uttcep[nfr - 1], cepsize * sizeof(mfcc_t));
01199     }
01200     /* Compute as usual. */
01201     feat_compute_utt(fcb, cepbuf, nfr + win * 2, win, ofeat);
01202     /* Free arrays of pointers. */
01203     for (i = 0; i < win; ++i) {
01204         ckd_free(cepbuf[i]);
01205         ckd_free(cepbuf[nfr + win + i]);
01206     }
01207     ckd_free(cepbuf);
01208     return nfr;
01209 }
01210 
01211 int32
01212 feat_s2mfc2feat_live(feat_t * fcb, mfcc_t ** uttcep, int32 *inout_ncep,
01213                      int32 beginutt, int32 endutt, mfcc_t *** ofeat)
01214 {
01215     int32 win, cepsize, nbufcep;
01216     int32 i, j, nfeatvec;
01217     int32 zero = 0;
01218 
01219     /* Avoid having to check this everywhere. */
01220     if (inout_ncep == NULL) inout_ncep = &zero;
01221 
01222     /* Special case for entire utterances. */
01223     if (beginutt && endutt && *inout_ncep > 0)
01224         return feat_s2mfc2feat_block_utt(fcb, uttcep, *inout_ncep, ofeat);
01225 
01226     win = feat_window_size(fcb);
01227     cepsize = feat_cepsize(fcb);
01228 
01229     /* Empty the input buffer on start of utterance. */
01230     if (beginutt)
01231         fcb->bufpos = fcb->curpos;
01232 
01233     /* Calculate how much data is in the buffer already. */
01234     nbufcep = fcb->bufpos - fcb->curpos;
01235     if (nbufcep < 0)
01236         nbufcep = fcb->bufpos + LIVEBUFBLOCKSIZE - fcb->curpos;
01237     /* Add any data that we have to replicate. */
01238     if (beginutt && *inout_ncep > 0)
01239         nbufcep += win;
01240     if (endutt)
01241         nbufcep += win;
01242 
01243     /* Only consume as much input as will fit in the buffer. */
01244     if (nbufcep + *inout_ncep > LIVEBUFBLOCKSIZE) {
01245         /* We also can't overwrite the trailing window, hence the
01246          * reason why win is subtracted here. */
01247         *inout_ncep = LIVEBUFBLOCKSIZE - nbufcep - win;
01248         /* Cancel end of utterance processing. */
01249         endutt = FALSE;
01250     }
01251 
01252     /* FIXME: Don't modify the input! */
01253     feat_cmn(fcb, uttcep, *inout_ncep, beginutt, endutt);
01254     feat_agc(fcb, uttcep, *inout_ncep, beginutt, endutt);
01255 
01256     /* Replicate first frame into the first win frames if we're at the
01257      * beginning of the utterance and there was some actual input to
01258      * deal with.  (FIXME: Not entirely sure why that condition) */
01259     if (beginutt && *inout_ncep > 0) {
01260         for (i = 0; i < win; i++) {
01261             memcpy(fcb->cepbuf[fcb->bufpos++], uttcep[0],
01262                    cepsize * sizeof(mfcc_t));
01263             fcb->bufpos %= LIVEBUFBLOCKSIZE;
01264         }
01265         /* Move the current pointer past this data. */
01266         fcb->curpos = fcb->bufpos;
01267         nbufcep -= win;
01268     }
01269 
01270     /* Copy in frame data to the circular buffer. */
01271     for (i = 0; i < *inout_ncep; ++i) {
01272         memcpy(fcb->cepbuf[fcb->bufpos++], uttcep[i],
01273                cepsize * sizeof(mfcc_t));
01274         fcb->bufpos %= LIVEBUFBLOCKSIZE;
01275         ++nbufcep;
01276     }
01277 
01278     /* Replicate last frame into the last win frames if we're at the
01279      * end of the utterance (even if there was no input, so we can
01280      * flush the output). */
01281     if (endutt) {
01282         int32 tpos; /* Index of last input frame. */
01283         if (fcb->bufpos == 0)
01284             tpos = LIVEBUFBLOCKSIZE - 1;
01285         else
01286             tpos = fcb->bufpos - 1;
01287         for (i = 0; i < win; ++i) {
01288             memcpy(fcb->cepbuf[fcb->bufpos++], fcb->cepbuf[tpos],
01289                    cepsize * sizeof(mfcc_t));
01290             fcb->bufpos %= LIVEBUFBLOCKSIZE;
01291         }
01292     }
01293 
01294     /* We have to leave the trailing window of frames. */
01295     nfeatvec = nbufcep - win;
01296     if (nfeatvec <= 0)
01297         return 0; /* Do nothing. */
01298 
01299     for (i = 0; i < nfeatvec; ++i) {
01300         /* Handle wraparound cases. */
01301         if (fcb->curpos - win < 0 || fcb->curpos + win >= LIVEBUFBLOCKSIZE) {
01302             /* Use tmpcepbuf for this case.  Actually, we just need the pointers. */
01303             for (j = -win; j <= win; ++j) {
01304                 int32 tmppos =
01305                     (fcb->curpos + j + LIVEBUFBLOCKSIZE) % LIVEBUFBLOCKSIZE;
01306                 fcb->tmpcepbuf[win + j] = fcb->cepbuf[tmppos];
01307             }
01308             fcb->compute_feat(fcb, fcb->tmpcepbuf + win, ofeat[i]);
01309         }
01310         else {
01311             fcb->compute_feat(fcb, fcb->cepbuf + fcb->curpos, ofeat[i]);
01312         }
01313         /* Move the read pointer forward. */
01314         ++fcb->curpos;
01315         fcb->curpos %= LIVEBUFBLOCKSIZE;
01316     }
01317 
01318     if (fcb->lda)
01319         feat_lda_transform(fcb, ofeat, nfeatvec);
01320 
01321     if (fcb->subvecs)
01322         feat_subvec_project(fcb, ofeat, nfeatvec);
01323 
01324     return nfeatvec;
01325 }
01326 
01327 feat_t *
01328 feat_retain(feat_t *f)
01329 {
01330     ++f->refcount;
01331     return f;
01332 }
01333 
01334 int
01335 feat_free(feat_t * f)
01336 {
01337     if (f == NULL)
01338         return 0;
01339     if (--f->refcount > 0)
01340         return f->refcount;
01341 
01342     if (f->cepbuf)
01343         ckd_free_2d((void **) f->cepbuf);
01344     ckd_free(f->tmpcepbuf);
01345 
01346     if (f->name) {
01347         ckd_free((void *) f->name);
01348     }
01349     if (f->lda)
01350         ckd_free_3d((void ***) f->lda);
01351 
01352     ckd_free(f->stream_len);
01353     ckd_free(f->sv_len);
01354     ckd_free(f->sv_buf);
01355     subvecs_free(f->subvecs);
01356 
01357     cmn_free(f->cmn_struct);
01358     agc_free(f->agc_struct);
01359 
01360     ckd_free(f);
01361     return 0;
01362 }
01363 
01364 
01365 void
01366 feat_report(feat_t * f)
01367 {
01368     int i;
01369     E_INFO_NOFN("Initialization of feat_t, report:\n");
01370     E_INFO_NOFN("Feature type         = %s\n", f->name);
01371     E_INFO_NOFN("Cepstral size        = %d\n", f->cepsize);
01372     E_INFO_NOFN("Number of streams    = %d\n", f->n_stream);
01373     for (i = 0; i < f->n_stream; i++) {
01374         E_INFO_NOFN("Vector size of stream[%d]: %d\n", i,
01375                     f->stream_len[i]);
01376     }
01377     E_INFO_NOFN("Number of subvectors = %d\n", f->n_sv);
01378     for (i = 0; i < f->n_sv; i++) {
01379         int32 *sv;
01380 
01381         E_INFO_NOFN("Components of subvector[%d]:", i);
01382         for (sv = f->subvecs[i]; sv && *sv != -1; ++sv)
01383             E_INFOCONT(" %d", *sv);
01384         E_INFOCONT("\n");
01385     }
01386     E_INFO_NOFN("Whether CMN is used  = %d\n", f->cmn);
01387     E_INFO_NOFN("Whether AGC is used  = %d\n", f->agc);
01388     E_INFO_NOFN("Whether variance is normalized = %d\n", f->varnorm);
01389     E_INFO_NOFN("\n");
01390 }

Generated on Fri Jan 14 2011 for SphinxBase by  doxygen 1.7.1