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

Generated on Tue Aug 17 2010 for SphinxBase by  doxygen 1.7.1