SphinxBase 0.6

src/libsphinxbase/feat/cmn.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  * cmn.c -- Various forms of cepstral mean normalization
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.14  2006/02/24  15:57:47  egouvea
00050  * Removed cmn = NULL from the cmn_free(), since it's pointless (my bad!).
00051  * 
00052  * Removed cmn_prior, which was surrounded by #if 0/#endif, since the
00053  * function is already in cmn_prior.c
00054  * 
00055  * Revision 1.13  2006/02/23 03:47:49  arthchan2003
00056  * Used Evandro's changes. Resolved conflicts.
00057  *
00058  *
00059  * Revision 1.12  2006/02/23 00:48:23  egouvea
00060  * Replaced loops resetting vectors with the more efficient memset()
00061  *
00062  * Revision 1.11  2006/02/22 23:43:55  arthchan2003
00063  * Merged from the branch SPHINX3_5_2_RCI_IRII_BRANCH: Put data structure into the cmn_t structure.
00064  *
00065  * Revision 1.10.4.2  2005/10/17 04:45:57  arthchan2003
00066  * Free stuffs in cmn and feat corectly.
00067  *
00068  * Revision 1.10.4.1  2005/07/05 06:25:08  arthchan2003
00069  * Fixed dox-doc.
00070  *
00071  * Revision 1.10  2005/06/21 19:28:00  arthchan2003
00072  * 1, Fixed doxygen documentation. 2, Added $ keyword.
00073  *
00074  * Revision 1.3  2005/03/30 01:22:46  archan
00075  * Fixed mistakes in last updates. Add
00076  *
00077  * 
00078  * 20.Apr.2001  RAH (rhoughton@mediasite.com, ricky.houghton@cs.cmu.edu)
00079  *              Added cmn_free() and moved *mean and *var out global space and named them cmn_mean and cmn_var
00080  * 
00081  * 28-Apr-1999  M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University
00082  *              Changed the name norm_mean() to cmn().
00083  * 
00084  * 19-Jun-1996  M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University
00085  *              Changed to compute CMN over ALL dimensions of cep instead of 1..12.
00086  * 
00087  * 04-Nov-1995  M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University
00088  *              Created.
00089  */
00090 
00091 
00092 #include <stdio.h>
00093 #include <stdlib.h>
00094 #include <string.h>
00095 #include <assert.h>
00096 #include <math.h>
00097 #ifdef HAVE_CONFIG_H
00098 #include <config.h>
00099 #endif
00100 
00101 #ifdef _MSC_VER
00102 #pragma warning (disable: 4244)
00103 #endif
00104 
00105 #include "sphinxbase/ckd_alloc.h"
00106 #include "sphinxbase/err.h"
00107 #include "sphinxbase/cmn.h"
00108 
00109 /* NOTE!  These must match the enum in cmn.h */
00110 const char *cmn_type_str[] = {
00111     "none",
00112     "current",
00113     "prior"
00114 };
00115 static const int n_cmn_type_str = sizeof(cmn_type_str)/sizeof(cmn_type_str[0]);
00116 
00117 cmn_type_t
00118 cmn_type_from_str(const char *str)
00119 {
00120     int i;
00121 
00122     for (i = 0; i < n_cmn_type_str; ++i) {
00123         if (0 == strcmp(str, cmn_type_str[i]))
00124             return (cmn_type_t)i;
00125     }
00126     E_FATAL("Unknown CMN type '%s'\n", str);
00127     return CMN_NONE;
00128 }
00129 
00130 cmn_t *
00131 cmn_init(int32 veclen)
00132 {
00133     cmn_t *cmn;
00134     cmn = (cmn_t *) ckd_calloc(1, sizeof(cmn_t));
00135     cmn->veclen = veclen;
00136     cmn->cmn_mean = (mfcc_t *) ckd_calloc(veclen, sizeof(mfcc_t));
00137     cmn->cmn_var = (mfcc_t *) ckd_calloc(veclen, sizeof(mfcc_t));
00138     cmn->sum = (mfcc_t *) ckd_calloc(veclen, sizeof(mfcc_t));
00139     /* A front-end dependent magic number */
00140     cmn->cmn_mean[0] = FLOAT2MFCC(12.0);
00141     cmn->nframe = 0;
00142     E_INFO("mean[0]= %.2f, mean[1..%d]= 0.0\n",
00143            MFCC2FLOAT(cmn->cmn_mean[0]), veclen - 1);
00144 
00145     return cmn;
00146 }
00147 
00148 
00149 void
00150 cmn(cmn_t *cmn, mfcc_t ** mfc, int32 varnorm, int32 n_frame)
00151 {
00152     mfcc_t *mfcp;
00153     mfcc_t t;
00154     int32 i, f;
00155 
00156     assert(mfc != NULL);
00157 
00158     if (n_frame <= 0)
00159         return;
00160 
00161     /* If cmn->cmn_mean wasn't NULL, we need to zero the contents */
00162     memset(cmn->cmn_mean, 0, cmn->veclen * sizeof(mfcc_t));
00163 
00164     /* Find mean cep vector for this utterance */
00165     for (f = 0; f < n_frame; f++) {
00166         mfcp = mfc[f];
00167         for (i = 0; i < cmn->veclen; i++) {
00168             cmn->cmn_mean[i] += mfcp[i];
00169         }
00170     }
00171 
00172     for (i = 0; i < cmn->veclen; i++)
00173         cmn->cmn_mean[i] /= n_frame;
00174 
00175     E_INFO("CMN: ");
00176     for (i = 0; i < cmn->veclen; i++)
00177         E_INFOCONT("%5.2f ", MFCC2FLOAT(cmn->cmn_mean[i]));
00178     E_INFOCONT("\n");
00179     if (!varnorm) {
00180         /* Subtract mean from each cep vector */
00181         for (f = 0; f < n_frame; f++) {
00182             mfcp = mfc[f];
00183             for (i = 0; i < cmn->veclen; i++)
00184                 mfcp[i] -= cmn->cmn_mean[i];
00185         }
00186     }
00187     else {
00188         /* Scale cep vectors to have unit variance along each dimension, and subtract means */
00189         /* If cmn->cmn_var wasn't NULL, we need to zero the contents */
00190         memset(cmn->cmn_var, 0, cmn->veclen * sizeof(mfcc_t));
00191 
00192         for (f = 0; f < n_frame; f++) {
00193             mfcp = mfc[f];
00194 
00195             for (i = 0; i < cmn->veclen; i++) {
00196                 t = mfcp[i] - cmn->cmn_mean[i];
00197                 cmn->cmn_var[i] += MFCCMUL(t, t);
00198             }
00199         }
00200         for (i = 0; i < cmn->veclen; i++)
00201             /* Inverse Std. Dev, RAH added type case from sqrt */
00202             cmn->cmn_var[i] = FLOAT2MFCC(sqrt((float64)n_frame / MFCC2FLOAT(cmn->cmn_var[i])));
00203 
00204         for (f = 0; f < n_frame; f++) {
00205             mfcp = mfc[f];
00206             for (i = 0; i < cmn->veclen; i++)
00207                 mfcp[i] = MFCCMUL((mfcp[i] - cmn->cmn_mean[i]), cmn->cmn_var[i]);
00208         }
00209     }
00210 }
00211 
00212 /* 
00213  * RAH, free previously allocated memory
00214  */
00215 void
00216 cmn_free(cmn_t * cmn)
00217 {
00218     if (cmn != NULL) {
00219         if (cmn->cmn_var)
00220             ckd_free((void *) cmn->cmn_var);
00221 
00222         if (cmn->cmn_mean)
00223             ckd_free((void *) cmn->cmn_mean);
00224 
00225         if (cmn->sum)
00226             ckd_free((void *) cmn->sum);
00227 
00228         ckd_free((void *) cmn);
00229     }
00230 }