NormFeatWindowMode.cpp

Go to the documentation of this file.
00001 /*
00002 This file is part of LIA_RAL which is a set of software based on ALIZE
00003 toolkit for speaker recognition. ALIZE toolkit is required to use LIA_RAL.
00004 
00005 LIA_RAL project is a development project was initiated by the computer
00006 science laboratory of Avignon / France (Laboratoire Informatique d'Avignon -
00007 LIA) [http://lia.univ-avignon.fr <http://lia.univ-avignon.fr/>]. Then it
00008 was supported by two national projects of the French Research Ministry:
00009         - TECHNOLANGUE program [http://www.technolangue.net]
00010         - MISTRAL program [http://mistral.univ-avignon.fr]
00011 
00012 LIA_RAL is free software: you can redistribute it and/or modify
00013 it under the terms of the GNU Lesser General Public License as
00014 published by the Free Software Foundation, either version 3 of
00015 the License, or any later version.
00016 
00017 LIA_RAL is distributed in the hope that it will be useful,
00018 but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00020 GNU Lesser General Public License for more details.
00021 
00022 You should have received a copy of the GNU Lesser General Public
00023 License along with LIA_RAL.
00024 If not, see [http://www.gnu.org/licenses/].
00025 
00026 The LIA team as well as the LIA_RAL project team wants to highlight the
00027 limits of voice authentication in a forensic context.
00028 The "Person Authentification by Voice: A Need of Caution" paper
00029 proposes a good overview of this point (cf. "Person
00030 Authentification by Voice: A Need of Caution", Bonastre J.F.,
00031 Bimbot F., Boe L.J., Campbell J.P., Douglas D.A., Magrin-
00032 chagnolleau I., Eurospeech 2003, Genova].
00033 The conclusion of the paper of the paper is proposed bellow:
00034 [Currently, it is not possible to completely determine whether the
00035 similarity between two recordings is due to the speaker or to other
00036 factors, especially when: (a) the speaker does not cooperate, (b) there
00037 is no control over recording equipment, (c) recording conditions are not
00038 known, (d) one does not know whether the voice was disguised and, to a
00039 lesser extent, (e) the linguistic content of the message is not
00040 controlled. Caution and judgment must be exercised when applying speaker
00041 recognition techniques, whether human or automatic, to account for these
00042 uncontrolled factors. Under more constrained or calibrated situations,
00043 or as an aid for investigative purposes, judicious application of these
00044 techniques may be suitable, provided they are not considered as infallible.
00045 At the present time, there is no scientific process that enables one to
00046 uniquely characterize a persones voice or to identify with absolute
00047 certainty an individual from his or her voice.]
00048 
00049 Copyright (C) 2004-2010
00050 Laboratoire d'informatique d'Avignon [http://lia.univ-avignon.fr]
00051 LIA_RAL admin [alize@univ-avignon.fr]
00052 Jean-Francois Bonastre [jean-francois.bonastre@univ-avignon.fr]
00053 */
00054 
00055 #if !defined(ALIZE_NormFeatWindowMode_cpp)
00056 #define ALIZE_NormFeatWindowMode_cpp
00057 
00058 #include <iostream>
00059 #include <fstream>
00060 #include <cstdio>
00061 #include <cassert>
00062 #include <cmath>
00063 #include <liatools.h>
00064 #include "NormFeatWindowMode.h"
00065 
00066 using namespace alize;
00067 using namespace std;
00068 
00069 
00070 
00071 //VERSION WITHOUT MEMORY
00072 void computeCMVnorm(Feature &f, DoubleVector &cMean, DoubleVector &cCov ){
00073         
00074                 
00075         for (unsigned long c = 0; c < cMean.size(); c++)
00076         {
00077             f[c] = (f[c] - cMean[c])/cCov[c];
00078         }       
00079 }
00080 
00081 
00082 
00083 //INIT CMVNorm on a matrix of windowFrame Features (RefVector)
00084 
00085 void loadMeanAndCovParam(RefVector <Feature> &windowFrameAcc, DoubleVector &cMean,DoubleVector &cCov, long &windowDuration )
00086 {
00087     FrameAccGD local;
00088     //create local Feature
00089     Feature f(cMean.size());
00090     int i = 0;
00091         
00092     if(windowFrameAcc.size() == (unsigned long)windowDuration) 
00093     {
00094         while(i < windowDuration)
00095         {
00096            f = windowFrameAcc[i];
00097            local.accumulate(f);
00098            i++;
00099         }
00100         cMean = local.getMeanVect();
00101         cCov  = local.getStdVect();
00102         local.reset();
00103         
00104     }
00105     else
00106     {
00107         cout << "Pb with buffer length" <<endl;
00108     }
00109    
00110 }
00111 
00112 //Update CMVNorm parameters when adding a new feature in the window (faster execution than loadMeanAndCovParam)
00113 
00114 void updateMeanAndCovParam(Feature &f, DoubleVector &cMean,DoubleVector &cCov, long &windowDuration, long &frameCount, long &lookHead )
00115 {       
00116     //Update window mean & var parameters
00117         
00118     //Forget factor Beta, need almost double precision
00119     double Beta;
00120     //Do not update mean & var parameters as current feature was already processed   
00121     if(frameCount < lookHead)
00122     {
00123         Beta = 1.0;    
00124     }
00125     //Update mean & var parameters for "not seen" feature  
00126     else
00127     {
00128         Beta = (((double)windowDuration - 1) / (double)windowDuration) ;
00129     }
00130     
00131     for (unsigned long i = 0; i < cMean.size(); i++)
00132     {
00133         cMean[i] = Beta * cMean[i]  + (1 - Beta)*f[i];
00134         cCov[i]  = sqrt( cCov[i] * cCov[i] * Beta + (1 - Beta) * (f[i]*f[i])); 
00135         
00136     }
00137     
00138    
00139 }
00140 
00141 
00142 //COMPUTE parameters on a windowDuration window, update the window by deleting the 1st frame and adding the current frame
00143 void computeCMVparameters(Feature &f, long &windowDuration, RefVector <Feature> &windowFrameAcc, DoubleVector &cMean, DoubleVector &cCov, long &frameCount  )
00144 {       
00145         // suppress one frame & add the current frame
00146         
00147         loadMeanAndCovParam(windowFrameAcc,cMean,cCov,windowDuration );
00148         
00149         windowFrameAcc.removeObject(0);
00150         windowFrameAcc.addObject(f);
00151         
00152         
00153 }
00154 
00155 
00156 /*
00157 Variance and Mean cepstral normalization
00158 
00159 Init : used zero padding + initDelay frames before norm OR init from a reference vector (TO DO)                                                                              
00160 For updating norm statistics a forget factor is used = windowFrame-1/windowFrame
00161 
00162 TAKE CARE : works only on voiced feature, doesn't use labels
00163 
00164 */
00165 int normFeatOnlineMode (Config & config) {
00166         
00167   String inputFeatureFileName =config.getParam("inputFeatureFilename");          // input feature - could be a simple feature file or a list of filename
00168   String labelSelectedFrames  =config.getParam("labelSelectedFrames");           // Only the frames from segments with this label  will be used 
00169  
00170   long windowDuration = 300, // Default length for window = 3s
00171        frameCount = 0,
00172        lookHead   = 0;
00173   bool  initWithDelay = false;
00174   
00175   if (config.existsParam("initWithDelay"))
00176   { 
00177       lookHead = config.getParam("initWithDelay").toLong();
00178       initWithDelay = true;
00179         
00180   }
00181 
00182   if(lookHead > windowDuration)
00183   {
00184       cout << "BAD INIT DELAY, SET TO WINDOW DURATION"<<endl;
00185       lookHead = windowDuration;
00186   }
00187   
00188   bool writeAllFeature    = true; // Output a vector for all input vectors (selected and not selected vectors) - DEFAULT=on
00189   if (config.existsParam("writeAllFeatures"))
00190   {
00191       writeAllFeature=config.getParam("writeAllFeatures").toBool();    // Define if all the feature (selected or not) should be written 
00192   }
00193   
00194   if (verbose){
00195     cout << "NormFeatWindowMode";
00196     cout << " Window mode, Window Duration["<<windowDuration<<"]"<<endl;
00197     cout << "var and mean normalisation"<< endl; 
00198   }
00199   double frameLength = 0.01; // length of a frame ins, by default 10 ms
00200   
00201   if (config.existsParam("frameLength")) frameLength=config.getParam("frameLength").toDouble();
00202  
00203   
00204         
00205   RefVector <Feature> memFrameAcc;
00206   RefVector <Feature> windowFrameAcc;
00207   
00208   XLine inputFeatureFileNameList;                                                // The (feature) input filename list
00209   if ( inputFeatureFileName.endsWith(".lst")){                                   // If the file parameter is the name of a XList file
00210         XList inputFileNameXList(inputFeatureFileName,config);                   // Read the filename list file
00211         inputFeatureFileNameList=inputFileNameXList.getAllElements();            // And put the filename in a list if the file is a list of feature filenames
00212   }
00213   else {                                                                         // It was a simple feature file and not a filename list
00214     inputFeatureFileNameList.addElement(inputFeatureFileName);                   // add the filename in the list
00215   }
00216   try{
00217         String *file;
00218         
00219           // Loop on each feature file
00220         while ((file=inputFeatureFileNameList.getElement())!= NULL)
00221         {                         
00222             String & featureFileName=(*file);
00223             FeatureFileReader fr(featureFileName, config);
00224                 
00225             if (!(config.existsParam("featureFlags")))
00226                 config.setParam("featureFlags",fr.getFeatureFlags().getString());
00227             
00228             if (config.existsParam("windowDuration"))
00229             {     
00230                 windowDuration = config.getParam("windowDuration").toLong();
00231             }
00232   
00233             cout << "Normalizing " << featureFileName << endl;
00234             FeatureFileWriter w(featureFileName, config);                             // build a featurefile writer to output the features (real features)
00235                 
00236          
00237             // current mean and cov vectors  
00238             DoubleVector cMean(fr.getVectSize(),fr.getVectSize()),cCov(fr.getVectSize(),fr.getVectSize());             
00239             frameCount = 0;
00240             // Loop on each feature
00241             
00242             // AT START ZERO PADDING + COPY OF LOOKHEAD DATA
00243             if(initWithDelay)
00244             {
00245                 while(frameCount < windowDuration)
00246                 {   
00247                     Feature &f = *new Feature(fr.getVectSize());
00248                     
00249                     //ZERO PADDING
00250                     if ( frameCount < (windowDuration - lookHead))
00251                     {
00252                         f.reset(); 
00253                     }
00254                     else 
00255                     {
00256                         if(!fr.readFeature(f))
00257                         {       
00258                                 //Case when lookhead > file size : window size = file size
00259                                 cout << "Reach end of file, new window size :  " << frameCount<<endl;
00260                                 windowDuration=frameCount;
00261                                 break;
00262                         }
00263                     }
00264                 
00265                     windowFrameAcc.addObject(f);
00266                     frameCount++;
00267                 }
00268                 
00269                 
00270                 loadMeanAndCovParam(windowFrameAcc,cMean,cCov,windowDuration);
00271                 //END FILL 1st WINDOW (buffer)
00272                   
00273             }
00274             // AT START INIT WITH A MEAN VECTOR
00275             else
00276             {
00277                  // TO DO  
00278             }
00279             //START NORM        
00280             fr.seekFeature(0);
00281             frameCount = 0;
00282            
00283             Feature ftmp;
00284             //NORMALISE FEATURES                    
00285             while(fr.readFeature(ftmp))
00286             {    
00287                 Feature &f = *new Feature(ftmp);
00288                 frameCount++;
00289                 //UPDATE PARAMETERS 
00290                 updateMeanAndCovParam(f, cMean,cCov, windowDuration, frameCount, lookHead );
00291                 //computeCMVparameters(f, windowDuration, windowFrameAcc, cMean, cCov, frameCount  );
00292                 //NORMALISE FEATURE                 
00293                 computeCMVnorm(f, cMean, cCov);
00294                 //cout <<"Frame Count :"<<frameCount<<endl;
00295                 w.writeFeature(f);
00296                 delete &f; //DELETE THIS IF USE OF computeCMVparameters
00297                 
00298             }
00299             windowFrameAcc.deleteAllObjects();
00300             
00301             
00302         }//END LOOP ON FILES
00303  }      
00304                 
00305 
00306   catch (Exception & e)
00307   {
00308       cout << e.toString ().c_str () << endl;
00309   }
00310   return 0;
00311 }
00312                 
00313                 
00314 
00315 #endif // !defined(ALIZE_NormFeatWindowMode_cpp)