ShiftedDeltaFeat.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_ShiftedDeltaFeat_cpp)
00056 #define ALIZE_ShiftedDeltaFeat_cpp
00057 
00058 #include <iostream>
00059 #include <fstream>
00060 #include <cstdio>
00061 #include <cassert>
00062 #include <cmath>
00063 #include <liatools.h>
00064 #include "ShiftedDeltaFeat.h"
00065 
00066 using namespace alize;
00067 using namespace std;
00068 
00069 //---------------------------------------------------------------------------------------------------------------
00079 int ShiftedDeltaFeat (Config & config) {
00080   unsigned int numCeps = 0 ;    // N
00081   unsigned int deltaDelay ;             // d
00082   unsigned int timeAdvance ;    // P
00083   unsigned int deltaBlocks ;    // k
00084   bool keepCepstra = true ;             //default
00085  
00086   String inputFeatureFileName =config.getParam("inputFeatureFilename");          // input feature - could be a simple feature file or a list of filename
00087   if (config.existsParam("vectSize")) numCeps = config.getParam("vectSize").toLong();
00088   deltaDelay  = config.getParam("SDCdeltaDelay").toLong();
00089   timeAdvance = config.getParam("SDCtimeAdvance").toLong();
00090   deltaBlocks = config.getParam("SDCdeltaBlocks").toLong();
00091   if (config.existsParam("SDCkeepCepstra")) keepCepstra = config.getParam("SDCkeepCepstra").toBool();
00092   if (verbose){
00093     cout << "ShiftedDeltaFeat: SDC parameters (N-d-P-k) are: ["<<numCeps<<"-"<<deltaDelay<<"-"<<timeAdvance<<"-"<<deltaBlocks<<"]" << endl;
00094   }
00095   if(debug) cout << "SDC parameters: SDCkeepCepstra["<<keepCepstra<<"] vectSize=numCeps["<<numCeps<<"] SDCdeltaDelay["<<deltaDelay<<"] SDCtimeAdvance["<<timeAdvance<<"] SDCdeltaBlocks["<<deltaBlocks<<"]" << endl;
00096   
00097   
00098   // Begin !!
00099   XLine inputFeatureFileNameList;                                                // The (feature) input filename list
00100   if ( inputFeatureFileName.endsWith(".lst")){                                   // If the file parameter is the name of a XList file
00101         XList inputFileNameXList(inputFeatureFileName,config);                       // Read the filename list file
00102         inputFeatureFileNameList=inputFileNameXList.getAllElements();                    // And put the filename in a list if the file is a list of feature filenames
00103   }
00104   else {                                                                         // It was a simple feature file and not a filename list
00105     inputFeatureFileNameList.addElement(inputFeatureFileName);                   // add the filename in the list
00106   }
00107   try{
00108         String *file;
00109         while ((file=inputFeatureFileNameList.getElement())!= NULL){                 // Loop on each feature file
00110                 
00111                 String & featureFileName=(*file);                                        // Current file basename
00112                 FeatureServer fs(config,featureFileName);
00113                 if(!numCeps) numCeps = fs.getVectSize();
00114                 unsigned long numFeats = fs.getFeatureCount() ;
00115 
00116                 Feature lowerFeat ;     //feature -d of a delta block
00117                 Feature upperFeat ;     //feature +d of a delta block
00118                 unsigned int cepFeatsInBase = (keepCepstra) ? numCeps : 0 ;             //number of additional feature values (if keeping cepstra)
00119                 unsigned int shiftedDeltaVectSize = cepFeatsInBase + (deltaBlocks*numCeps) ;
00120 
00121                 Config configOut( config) ;
00122                 configOut.setParam("vectSize", String::valueOf(shiftedDeltaVectSize) ) ;
00123                 configOut.setParam("featureServerMask", "0-"+String::valueOf(shiftedDeltaVectSize-1)) ;
00124                 cout << "ShiftedDeltaFeat: numCeps["<<numCeps<<"] vectSize["<<fs.getVectSize()<<"] numFeats["<<fs.getFeatureCount()<<"] keepCeps["<<keepCepstra<<"] cepsInBase["<<cepFeatsInBase<<"] OUTnumFeats["<<shiftedDeltaVectSize<<"] OUTcfgVectSize["<<configOut.getParam("vectSize")<<"]" <<endl;
00125                 //FeatureServer fsOut(configOut,featureFileName);
00126                 FeatureServer fsOut(configOut);
00127                 if(debug) cout << "FeatureServer fsOut instantiated" << endl ;
00128 
00129                 // Output the SDC features - Take care: only the saveFeatureFileExtension parameter make a difference between the input and output files
00130                 if (!(configOut.existsParam("featureFlags")))
00131                         configOut.setParam("featureFlags",fs.getFeatureFlags().getString());// Put the file flag in the config (could be different for each file   
00132                 cout << "Writing to: " << featureFileName << endl;
00133                 FeatureFileWriter w(featureFileName, configOut);                             // build a featurefile writer to output the features (real features)
00134                 
00135                 // Begin the real work, file by file
00136 
00137                 /*
00138                  * SDC formula is:
00139                  * 
00140                  * ShDeltaO_h(t) = O_h( t + i*P + d) - O_h( t + i*P - d)   ;  i = 0, 1, 2 ... k-1  ;  O_h is the input featureVector
00141                  */
00142                 
00143                 /*for cropping at start and end of file:*/// since we have -d, first t is d and last is Total-d; to avoid looking into nowhere
00144                 /*for cropping at start and end of file:*///for( unsigned long currentTime=deltaDelay; (currentTime+((deltaBlocks-1)*timeAdvance)+deltaDelay)<numFeats; currentTime++)
00145                 // LOOP over t - for all features in the input file - generates the same number of feature in output
00146                 for( unsigned long currentTime=0; currentTime<numFeats; currentTime++) {
00147 
00148                         // initialize a (big) featureVector with k*N or k*N+N features
00149                         Feature shiftedDeltaFeature( shiftedDeltaVectSize) ;
00150 
00151                         // TODO ev include feature to keep whole input vector in output - not only masked part
00152                         // TODO   this adds the possibility to have ceps, energy, (ev. acceleration) and SDCs (without energy/accel) all together 
00153 
00154                         if( cepFeatsInBase > 0) {
00155                                 assert( cepFeatsInBase==numCeps) ;
00156                                 Feature cepFeats;
00157                                 fs.seekFeature( currentTime) ;
00158                                 fs.readFeature( cepFeats,0) ;   //TODO chkret
00159                                 //TODO replace loop by fct call - new fct
00160                                 for( unsigned int i=0; i<numCeps; i++) {
00161                                         shiftedDeltaFeature[i] = cepFeats[i] ;  //TODO optimize with memcopy
00162                                 }
00163                         }
00164 
00165                         // LOOP over i from 0 to (k-1)*P
00166                         for( unsigned int currentDeltaBlock=0; currentDeltaBlock<deltaBlocks; currentDeltaBlock++) {
00167                                 // time of lower (t-d) and upper (t+d) feature
00168                                          int lowerTime = currentTime + (currentDeltaBlock*timeAdvance) - deltaDelay ;   // t + i*P - d
00169                                 unsigned int upperTime = currentTime + (currentDeltaBlock*timeAdvance) + deltaDelay ;   // t + i*P + d
00170 
00171                                 // for begin and end of file, correct times as to simulate repeating edge vectors beyond limits
00172                                 if( lowerTime < 0        ) lowerTime = 0 ;
00173                                 if( (unsigned long)lowerTime >= numFeats) lowerTime = numFeats-1 ;
00174                                 if( upperTime                >= numFeats) upperTime = numFeats-1 ;  //last vector is numFeats-1
00175                                 //if (debug || (verboseLevel>2)) cout << "t["<<currentTime<<"] block["<<currentDeltaBlock<<"] lowerT["<<lowerTime<<"] 2d["<<(2*deltaDelay)<<"]" <<endl ;
00176                                 if (debug || (verboseLevel>2)) cout << "t["<<currentTime<<"] block["<<currentDeltaBlock<<"] lowerT["<<lowerTime<<"] upperT["<<upperTime<<"]" <<endl ;
00177 
00178                                 // fetch cepstral features
00179                                 fs.seekFeature( lowerTime) ;
00180                                 //fs.readFeature( lowerFeat, 2*deltaDelay);     // O_h( t + i*P - d)    //TODO chkret
00181                                 fs.readFeature( lowerFeat, 0);                          // O_h( t + i*P - d)    //TODO chkret
00182                                 if (debug || (verboseLevel>2)) { cout << " lowerFeat[" ; for(unsigned int i=0; i<lowerFeat.getVectSize();i++){ cout<<lowerFeat[i]<<" " ;} ; cout <<"]"<< endl; }
00183                                 fs.seekFeature( upperTime) ;
00184                                 fs.readFeature( upperFeat);                             // O_h( t + i*P + d)    //TODO chkret
00185                                 if (debug || (verboseLevel>2)) { cout << " upperFeat[" ; for(unsigned int i=0; i<upperFeat.getVectSize();i++){ cout<<upperFeat[i]<<" " ;} ; cout <<"]"<< endl; } 
00186 
00187                                 // calculate delta
00188                                 Feature deltaBlockFeature( numCeps) ;
00189                                 for( unsigned int i=0; i<numCeps; i++) {
00190                                         deltaBlockFeature[i] = upperFeat[i] - lowerFeat[i] ;
00191                                 }
00192                                 if (debug || (verboseLevel>2)) { cout << "  deltaFeat[" ; for(unsigned int i=0; i<deltaBlockFeature.getVectSize();i++){ cout<<deltaBlockFeature[i]<<" " ;} ; cout <<"]"<< endl; }
00193 
00194                                 // calculate position to append deltas to output vector: i*N (or N + i*N)
00195                                 unsigned int blockBase = cepFeatsInBase + (currentDeltaBlock*numCeps) ;
00196                                 if (debug || (verboseLevel>2)) cout << " blkBase["<<blockBase<<"] cepsInBase["<<cepFeatsInBase<<"] curD Blk["<<currentDeltaBlock<<"]" << endl;
00197 
00198                                 // append features to new (big) featureVector (at position i*N (or N + i*N) )
00199                                 //TODO replace loop by fct call - same new fct as above
00200                                 for( unsigned int i=0; i<deltaBlockFeature.getVectSize(); i++) {
00201                                         shiftedDeltaFeature[blockBase+i] = deltaBlockFeature[i] ;       //TODO optimize with memcopy
00202                                 }
00203                                 if (debug || (verboseLevel>2)) { cout << "  ShDltFeat[" ; for(unsigned int i=0; i<shiftedDeltaFeature.getVectSize();i++){ cout<<shiftedDeltaFeature[i]<<" " ;} ; cout <<"]"<< endl; }
00204                         }
00205 
00206                         // save (big) featureVector to file
00207                         if (debug || (verboseLevel>2)){ cout << "WRITE: t["<<currentTime<<"] ShDltFeat[" ; for(unsigned int i=0; i<shiftedDeltaFeature.getVectSize();i++){ cout<<shiftedDeltaFeature[i]<<" " ;} ; cout <<"]"<< endl; }
00208                         w.writeFeature( shiftedDeltaFeature) ;
00209                 }
00211                 if (debug || (verboseLevel>2)){ cout <<"SDC, number of frames= ["<<fsOut.getFeatureCount()<<"]"<<endl; }
00212 
00213         }// End feature file loop
00214 
00215   }// end try
00216   
00217   catch (Exception & e)
00218       {
00219           cout << e.toString ().c_str () << endl;
00220       }
00221   return 0;
00222 }
00223 
00224 
00225 #endif // !defined(ALIZE_ShiftedDeltaFeat_cpp)
00226