NormFeat.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_NormFeat_cpp)
00056 #define ALIZE_NormFeat_cpp
00057 
00058 #include <iostream>
00059 #include <fstream>
00060 #include <cstdio>
00061 #include <cassert>
00062 #include <cmath>
00063 #include <liatools.h>
00064 #include "NormFeat.h"
00065 #include "AccumulateJFAStat.h"
00066 
00067 using namespace alize;
00068 using namespace std;
00069 
00070 // Display Stats
00071 void displayStats(FrameAccGD &frameAccu,FeatureServer & fs,ostream & out,Config &config) {  
00072   const DoubleVector & featureMean = frameAccu.getMeanVect();                    // Get the mean vector
00073   const DoubleVector & featureStd = frameAccu.getStdVect();                      // Get the std vector (sqrt(cov))
00074   unsigned long vectsize=fs.getVectSize();                                       // Get the vect size (number of coeff)
00075         for (unsigned int i = 0; i < vectsize; i++) 
00076                 {out<<featureMean[i]<<" "<<featureStd[i]<< endl;}
00077 }
00078 
00079 void loadStatsFromFile(String filename,DoubleVector & extMean, DoubleVector & extCov) {
00080         Config tmp; // why is that ???? N.S.
00081         XList extStats(filename,tmp);
00082         for(unsigned long i=0;i<extStats.getLineCount();i++) {
00083                 if(extStats.getLine(i).getElementCount()!=2) cerr << "W: Stat file does not match standard format (mean cov)" << endl;
00084                 extMean[i]=extStats.getLine(i).getElement(0).toDouble();
00085                 extCov[i]=extStats.getLine(i).getElement(1).toDouble();
00086         }
00087 }
00088 // Window mode stuff
00089 bool emptyWindow(SegCluster &window){
00090   window.rewind();
00091   return (window.getSeg()==NULL);
00092 }
00093 // return the first seg of a cluster
00094 Seg * firstSeg(SegCluster &window){
00095   window.rewind();
00096   Seg *seg= window.getSeg();
00097   return seg;
00098 }
00099 // return the last seg of a cluster
00100 Seg * lastSeg(SegCluster &window){
00101   window.rewind();
00102   Seg *seg=window.getSeg();
00103   if (seg==NULL) throw Exception("empty window" , __FILE__, __LINE__);
00104   Seg *retSeg=seg;
00105   while((seg=window.getSeg())!=NULL) retSeg=seg;
00106   return retSeg;
00107 }
00108 // Compute the time interval (in s )between the first and last frames of the window
00109 double windowLength(SegCluster &window,double frameLength){
00110   double tBegin=frameIdxToTime(firstSeg(window)->begin(),frameLength);
00111   Seg *lastS=lastSeg(window);
00112   double tEnd=frameIdxToTime(lastS->begin()+lastS->length(),frameLength);
00113   return (tEnd-tBegin);
00114 }
00115 
00116 // Used in order to fill the window
00117 // Add segments and return true if the length is not reached
00118 // Do nothing and return false if the length is reached
00119 bool inWindow(Seg &seg,SegCluster &window,double windowDuration, double frameLength){     
00120   if (emptyWindow(window)) { window.addCopy(seg);return true;}
00121   if (windowLength(window,frameLength)<=windowDuration){
00122     window.addCopy(seg);
00123     return true;
00124   }
00125   return false;                             // the window is full . Do nothing
00126 }
00127 
00128 // suppress the first segment of the window
00129 void suppressFirst(SegCluster &window){
00130   window.rewind();
00131   Seg *seg=window.getSeg();
00132   if (seg!=NULL) window.remove(*seg);
00133 }
00134 // remove the first segment, add the current segment 
00135 void moveWindow(SegCluster &window,Seg &seg,Seg *&currentSeg,double duration, double frameLength){
00136   Seg *fSeg;
00137   window.addCopy(seg);
00138   if (debug) cout << "suppress seg[";
00139   do {
00140     if (debug) cout <<firstSeg(window)->begin()<<","<<firstSeg(window)->length()<<"][";
00141     suppressFirst(window);fSeg=firstSeg(window);
00142   } while ((currentSeg!=NULL)&&(fSeg->begin()<currentSeg->begin()) &&(windowLength(window,frameLength)>duration));
00143   if (debug) cout <<"] from the window and add seg["<<seg.begin()<<","<<seg.length()<<"]"<<endl;
00144   if (currentSeg==NULL) currentSeg=&seg;        // We deal with all the seg in the window before the move, next one is the added one
00145 }
00146 //compute the mean and cov for the current window
00147 void computeWindowParam(Config &config,const DoubleVector &gMean,const DoubleVector &gCov,FeatureServer & fs,
00148                         SegCluster &window,double windowDuration,double windowComp,double frameLength,
00149                         DoubleVector &mean,DoubleVector &cov){
00150   FrameAccGD frameAccu;                                                      // Defines a frame accumulator for mean and cov computation 
00151   frameAccu.reset();
00152   accumulateStatFrame(frameAccu,fs, window, config);
00153   mean = frameAccu.getMeanVect();     // Get the mean vector
00154   cov = frameAccu.getStdVect();       // Get the std vector
00155   if (debug) {cout <<"Compute param on"<<endl;showCluster(window);}
00156   double duration=windowLength(window,frameLength);
00157   if (verboseLevel>1) cout <<"Window  real time["<<duration<<"]";
00158   //if (duration>windowDuration) duration=windowDuration; ????????????????????????????????
00159   double alpha=frameIdxToTime(totalFrame(window),frameLength);
00160   if (verboseLevel>1) cout <<" data time["<<alpha <<"]";
00161   alpha/=duration;
00162   if (alpha>1) alpha =1.0;
00163   if (verboseLevel>1) cout <<" Alpha["<<alpha<<"]";
00164   alpha*=windowComp;
00165   if (verboseLevel>1) cout <<" after Compensation["<<alpha<<"]"<<endl;;
00166   for (unsigned long c=0;c<fs.getVectSize();c++){
00167     mean[c]=(alpha*mean[c])+((1-alpha)*gMean[c]);
00168     cov[c]=(alpha*cov[c]*cov[c]) +((1-alpha)*gCov[c]*gCov[c])
00169       +(((1-alpha)*alpha)*pow(mean[c]-gMean[c],2));
00170     cov[c]=sqrt(cov[c]);
00171   }
00172      
00173 }
00174 bool inMiddle(Seg * &currentSeg,SegCluster &window,double windowDuration,double frameLength){
00175   double beginW=frameIdxToTime(firstSeg(window)->begin(),frameLength); 
00176   return (frameIdxToTime(currentSeg->begin(),frameLength)<=beginW+(windowDuration/2.0)); 
00177 }
00178 bool nextSeg(Seg * &currentSeg,SegCluster &window){
00179   window.rewind();
00180   Seg *seg=NULL;
00181   while(((seg=window.getSeg())!=NULL) &&(seg->begin()!=currentSeg->begin())); // TODO ADD OPERATOR != == between seg
00182   if (seg!=NULL) currentSeg=window.getSeg();
00183   else throw Exception("currentSeg is not in the window" , __FILE__, __LINE__);
00184   if (currentSeg==NULL) return false;
00185   else return true;
00186 }
00187 
00188 // get the glocal ubm offset
00189 void getUbmOffset(RealVector <double>& ubm_offset,Matrix<double>& U,MixtureGD & world,Config & config) {
00190         if (verbose) cout << "NAP mode, get global UBM offset" << endl; 
00191         unsigned long svSize=world.getDistribCount()*world.getVectSize();
00192         ubm_offset.setSize(svSize);
00193         RealVector <double> ubm_sv(svSize,svSize);              
00194         if (verbose) cout << "Size of SVs: [" << ubm_sv.size() << "]...";
00195         modelToSv(world,ubm_sv);
00196         projectOnSubSpace(ubm_sv,U,ubm_offset);
00197 }
00198 
00199 // remove ubm offset on a frame
00200 void removeOffsetOnFrame(RealVector <double> & occ,Feature & f, RealVector <double> & ubm_offset,unsigned long nbDistrib) {
00201         for (unsigned long i=0;i<f.getVectSize();i++) {
00202                 if (verboseLevel > 4) cout << "dim " << i << ":" ;              
00203                 double _offset=0.0;// get offset for this cepstrum coeff
00204                 for (unsigned long j=0;j<nbDistrib;j++) { // get corresponding values (TODO: on top ten)        
00205                         if (verboseLevel > 4) cout << j << "["<<j*f.getVectSize()+i<<"] ";              
00206                         _offset+=ubm_offset[j*f.getVectSize()+i]*occ[j];                // to check ... propal from Anthony
00207                 }
00208                 f[i]-=_offset;
00209         }
00210 }
00211 
00212 // Compute Occ and Remove offset
00213 void featureChannelCompNAP(RealVector <double> &ubm_offset,MixtureGD & world,FeatureServer &fs,StatServer & ss,SegCluster & selectedSegments,Config &config) {
00214         MixtureGDStat &occAcc=ss.createAndStoreMixtureGDStat(world);
00215         Seg* seg;                                                                         // reset the reader at the begin of the input stream
00216         selectedSegments.rewind();      
00217         while((seg=selectedSegments.getSeg())!=NULL){                                     // For each of the selected segments
00218           unsigned long idxBeginFrame=seg->begin()+fs.getFirstFeatureIndexOfASource(seg->sourceName()); 
00219           fs.seekFeature(idxBeginFrame); 
00220           Feature f;
00221           for (unsigned long idxFrame=0;idxFrame<seg->length();idxFrame++){               // For each frame of the segment
00222                 fs.readFeature(f);
00223                 occAcc.computeAndAccumulateOcc(f);
00224                 RealVector <double> occ=occAcc.getOccVect();
00225                 removeOffsetOnFrame(occ,f,ubm_offset,world.getDistribCount());
00226           }
00227         }
00228         if (verbose) cout << "done" << endl;
00229 }
00230         
00231 int normFeat (Config & config) {
00232         
00233   String inputFeatureFileName =config.getParam("inputFeatureFilename");          // input feature - could be a simple feature file or a list of filename
00234   String labelSelectedFrames  =config.getParam("labelSelectedFrames");           // Only the frames from segments with this label  will be used
00235   bool segmentalMode=false;                                                      // the norm is done segment by segment
00236   bool fileMode=false;                                                           // the norm is done on the entire file (default)
00237   bool windowMode=false;                                                         // the norm is done time window by time window
00238   if (config.existsParam("segmentalMode"))segmentalMode=config.getParam("segmentalMode").toBool();
00239   if (config.existsParam("fileMode")) fileMode=config.getParam("fileMode").toBool(); // DEFAULT MODE
00240   if (config.existsParam("windowMode")) windowMode=config.getParam("windowMode").toBool();
00241   if (segmentalMode && windowMode) // Only one of this modes should be active
00242     throw Exception (" Incompatible modes (segmental/windowMode)" , __FILE__, __LINE__);
00243   if ((!fileMode)&&(!segmentalMode) && (!windowMode)) fileMode=true;
00244   double windowDuration=5; // Default length for window=5s
00245   double windowComp=1;     // Default compensation for window vs global means and cov (=1, no compensation)
00246   if (windowMode){
00247     if (config.existsParam("windowDuration")) windowDuration=config.getParam("windowDuration").toDouble();
00248     if (config.existsParam("windowComp")) windowComp=config.getParam("windowComp").toDouble();
00249   }
00250   bool writeAllFeature=true; // Output a vector for all input vectors (selected and not selected vectors) - DEFAULT=on
00251   if (config.existsParam("writeAllFeatures")) writeAllFeature=config.getParam("writeAllFeatures").toBool();    // Define if all the feature (selected or not) should be written 
00252   bool cms=false;
00253   bool extStat=false;
00254   bool var=false;
00255   bool warp=false;
00256   if (config.existsParam("cmsOnly")) cms=config.getParam("cmsOnly").toBool();
00257   if (config.existsParam("varOnly")) cms=config.getParam("varOnly").toBool();
00258   if (config.existsParam("warp"))    warp=config.getParam("warp").toBool();
00259 
00260   if (config.existsParam("externalStatsFilename")) extStat=true;
00261   if (cms && var) throw Exception (" cmsOnly and varOnly are not compatible)" , __FILE__, __LINE__);
00262   if (cms && warp)throw Exception (" cmsOnly and warp are not compatible)" , __FILE__, __LINE__);
00263   if (var && warp)throw Exception (" varOnly and warp are not compatible)" , __FILE__, __LINE__);
00264   if (extStat && warp)throw Exception (" externalStats and warp are not compatible)" , __FILE__, __LINE__);
00265 
00266   if (verbose){
00267     cout << "NormFeat";
00268     if (!segmentalMode && !windowMode && !fileMode) cout << "NO NORM IS SELECTED"<<endl;
00269     if (segmentalMode) cout << " Segmental Mode - Normalisation  by segment"<<endl;
00270     if (windowMode) cout << "Window mode, Window Duration["<<windowDuration<<"], Window compensation ["<<windowComp<<"]"<<endl;
00271     if (fileMode) cout << "File Mode- Normalisation by file by file" <<endl;
00272     if (fileMode && (windowMode || segmentalMode)) cout <<" a global 0,1 norm is applied after segmental/window mode"<<endl;
00273     if (extStat) cout << "Loading statistics from external file: ["<<config.getParam("externalStatsFilename")<<"]"<<endl;
00274     if (cms) cout <<"CMS: mean only mode"<<endl;
00275     if (var) cout <<"VAR: variance only mode"<<endl;
00276     if (warp) cout <<"Warping mode"<<endl;
00277     if (!(cms) && (!var) && (!warp)) cout << "var and mean normalisation"<< endl; 
00278 
00279   }
00280   double frameLength=0.01; // length of a frame ins, by default 10 ms
00281   if (config.existsParam("frameLength")) frameLength=config.getParam("frameLength").toDouble();
00282   // Warping mode global variables and initialisation
00283   Histo gaussHisto; // Targeted distribution histogram
00284   Histo *rawHistoT;  // Tab of histo. Used to compute the raw histo
00285                    // coeff by coeff
00286   unsigned long nbBin=40;
00287   bool warp01=false;
00288   if (config.existsParam("warpBinCount")) nbBin=config.getParam("warpBinCount").toLong();
00289   if (warp){
00290       if (config.existsParam("warpGaussHistoFilename")) gaussHisto.load(config.getParam("warpGaussHistoFilename"));
00291       else {
00292           unsigned long gaussHistoSampleCount=50000;
00293           unsigned long gaussHistoBinCount=100;
00294           gaussHisto=makeGausHisto(gaussHistoSampleCount,0, 1,gaussHistoBinCount);      // Make the targeted distribution          
00295       }
00296       initHistoTab(rawHistoT,1,1);  // Make an empty histo by coeff
00297                                     // TODO(suppress)
00298       if (config.existsParam("warpAdd01Norm")) warp01=config.getParam("warpAdd01Norm").toBool();
00299 }
00300  
00301   // Begin !!
00302   XLine inputFeatureFileNameList;                                                // The (feature) input filename list
00303   if ( inputFeatureFileName.endsWith(".lst")){                                   // If the file parameter is the name of a XList file
00304         XList inputFileNameXList(inputFeatureFileName,config);                   // Read the filename list file
00305         inputFeatureFileNameList=inputFileNameXList.getAllElements();            // And put the filename in a list if the file is a list of feature filenames
00306   }
00307   else {                                                                         // It was a simple feature file and not a filename list
00308     inputFeatureFileNameList.addElement(inputFeatureFileName);                   // add the filename in the list
00309   }
00310   try{
00311         String *file;
00312         while ((file=inputFeatureFileNameList.getElement())!= NULL){                         // Loop on each feature file
00313                 String & featureFileName=(*file);                                            // Current file basename
00314                 FeatureServer fs(config,featureFileName);
00315                 DoubleVector extMean(fs.getVectSize(),fs.getVectSize()); // Init double vectors, does it have to be so harmful!!!
00316                 DoubleVector extCov(fs.getVectSize(),fs.getVectSize());
00317                 if (extStat) {
00318                   loadStatsFromFile(config.getParam("externalStatsFilename"),extMean, extCov);
00319                 }
00320                 // Begin the real work, file by file
00321                 SegServer segmentsServer;                                              // Create the segment server for managing the segments/clusters
00322                 LabelServer labelServer;                                               // Create the label server, for indexing the segments/clusters
00323                 initializeClusters(featureFileName,segmentsServer,labelServer,config); // Reading the segmentation files for each feature input file
00324                 verifyClusterFile(segmentsServer,fs,config);                           // Verify if the segments ending before the end of the feature files...
00325                 unsigned long codeSelectedFrame=labelServer.getLabelIndexByString(labelSelectedFrames);// Get the index of the cluster with in interest audio segments
00326                 if (verbose) cout << "NormFeat file normalisation["<<featureFileName<<"]"<<endl;
00327                 SegCluster& selectedSegments=segmentsServer.getCluster(codeSelectedFrame); // The general cluster of the selected/used segments   
00328                 SegServer segServerWindow;                                                 // specific segment server for window mode
00329                 SegCluster& window=segServerWindow.createCluster(0,labelSelectedFrames,selectedSegments.sourceName());  // the window
00330                 //
00331                 if (debug || (verboseLevel>2)){
00332                   DoubleVector globalMean;
00333                   DoubleVector globalCov;
00334                   FrameAccGD globalFrameAcc;
00335                   unsigned long nbFrame=computeMeanCov(config,fs,selectedSegments,globalMean,globalCov); // Compute the global mean and covariance
00336                   cout <<"global mean and cov before norm, number of frame= ["<<nbFrame<<"]"<<endl;
00337                   for (unsigned i=0; i < fs.getVectSize(); i++)cout << "mean[" << i << "=" << globalMean[i] << "]\tcov[" << globalCov[i] << "]" << endl;
00338                 }
00339                 // SEGMENTAL MODE
00340                 if (segmentalMode) {                                                       // Segmental mode (the norm is done seg by seg)
00341                   Seg *seg;
00342                   selectedSegments.rewind(); 
00343                   while((seg=selectedSegments.getSeg())!=NULL) {                     // For each of the selected segments
00344                     if (debug) cout << "current Seg["<<seg->begin()<<","<<seg->length()<<"]"<<endl;
00345                     if (!warp){
00346                       DoubleVector mean,cov;
00347                       if(extStat) {                                                    // load external stats from file (NS)
00348                         mean=extMean;
00349                         cov=extCov;
00350                       }
00351                       else {
00352                         FrameAccGD frameAccu;                                                      // Defines a frame accumulator for mean and cov computation
00353                         frameAccu.reset();                                                         // reset the frame accumulator
00354                         accumulateStatFrame(frameAccu,fs, seg, config);
00355                         mean = frameAccu.getMeanVect();     // Get the mean vector
00356                         cov = frameAccu.getStdVect();       // Get the std vector (sqrt(cov)) (remove const and ref to modify)
00357                       }
00358                       if (cms) cov.setAllValues(1.0);   // remove cov effect if cms only (N.S) 
00359                       if (var) mean.setAllValues(0.0);      // remove effects if var only (jfb)
00360                       computeZeroOne(mean,cov,fs,seg,config);
00361                     } // end of mean and/or cov normalisation
00362                     if (warp){ // Gaussian warping mode
00363                         freezeHistoTab(rawHistoT); //TODO replace by
00364                         initHistoTab(rawHistoT,fs.getVectSize(),nbBin);//Reset
00365                         accumulateHistoFrame(rawHistoT,fs,seg,config);
00366                         computeHistoTab(rawHistoT,fs.getVectSize());
00367                         computeWarp(rawHistoT,gaussHisto,fs,seg,config);
00368                     } // end of warping mode
00369                   } // end of a given segment
00370                 } // end of classical segmental mode
00371                 // WINDOW MODE
00372                 if (windowMode){ // JFB March 20 2006
00373                   // compute the global mean and cov
00374                   FrameAccGD frameAccu;                                                      // Defines a frame accumulator for mean and cov computation
00375                   frameAccu.reset();    
00376                   accumulateStatFrame(frameAccu, fs, selectedSegments, config); 
00377                   DoubleVector gMean,gCov;             // global (on all semected segments) mean and cov vectors
00378                   gMean= frameAccu.getMeanVect();      // Get the mean vector
00379                   gCov = frameAccu.getStdVect();       // Get the std vector (sqrt(cov)) (remove const and ref to modify)
00380                   DoubleVector mean,cov;               // mean and cov estimations for a given window
00381                   Seg *currentSeg=NULL;                // the central segment, where the transformation should be applied
00382                   Seg *seg;
00383                   selectedSegments.rewind(); 
00384                   while((seg=selectedSegments.getSeg())!=NULL) {      // For each of the selected segments
00385                     if (debug){
00386                       cout <<"selected Seg["<<seg->begin()<<","<<seg->length()<<"]"<<endl;
00387                       cout <<"current seg";
00388                       if (currentSeg==NULL) cout <<" NULL"<<endl;
00389                       else cout <<"["<<currentSeg->begin()<<","<<currentSeg->length()<<"]"<<endl;
00390                       cout <<"window"<<endl;
00391                       showCluster(window);
00392                     }
00393                     if (inWindow(*seg,window,windowDuration,frameLength)){// add segments until the window length is reached
00394                       if (currentSeg==NULL) currentSeg=seg;
00395                     }
00396                     else{                                                 // Normal stuff: the window is full, compute the norm, suppress the first segment
00397                       bool empty=emptyWindow(window);
00398                       if (empty) {window.addCopy(*seg);currentSeg=seg;}   // special case where one seg is the window (is larger than the time constraint)
00399                       if (!warp){                                         // compute the mean and cov for the window (mean and cov normalisation modes)
00400                           computeWindowParam(config,gMean,gCov,fs,window,windowDuration,windowComp,frameLength,mean,cov); 
00401                           if (cms) cov.setAllValues(1.0);                     // remove cov effect if cms only (N.S) 
00402                           if (var) mean.setAllValues(0.0);               // remove effects if var only (jfb)      
00403                       }
00404                       else {                                             // warping mode, compute the histos
00405                           freezeHistoTab(rawHistoT); //TODO replace by
00406                           initHistoTab(rawHistoT,fs.getVectSize(),nbBin);//Reset
00407                           accumulateHistoFrame(rawHistoT,fs,window,config);
00408                           computeHistoTab(rawHistoT,fs.getVectSize());
00409                         
00410                       }
00411           
00412                       bool ok=true;
00413                       while ((ok) && (inMiddle(currentSeg,window,windowDuration,frameLength))){             // until we reach the middle of the window 
00414                         if (debug) cout << "Apply norm on Seg ["<<currentSeg->begin()<<","<<currentSeg->length()<<"]"<<endl;
00415                         if (!warp) // mean and cov normalisation modes
00416                             computeZeroOne(mean,cov,fs,currentSeg,config);// compute the norm for the current segment
00417                         else       // warping mode
00418                             computeWarp(rawHistoT,gaussHisto,fs,currentSeg,config);
00419                         ok=nextSeg(currentSeg,window);
00420                       }          
00421                       if (empty) suppressFirst(window);
00422                       else moveWindow(window,*seg,currentSeg,windowDuration,frameLength);        // remove the first segments, add the current segment 
00423                     }
00424                   } 
00425                   // Deal with the last window
00426                   if (debug) cout <<"Deal with last window"<<endl;
00427                   if (!emptyWindow(window)){
00428                       if (!warp){ // mean and norm normalisation modes
00429                           computeWindowParam(config,gMean,gCov,fs,window,windowDuration,windowComp,frameLength,mean,cov); // compute the mean and cov for the current window
00430                           if (cms) cov.setAllValues(1.0);                 // remove cov effect if cms only (N.S) 
00431                           if (var) mean.setAllValues(0.0);           // remove effects if var only (jfb)
00432                       }
00433                       else { // warping mode
00434                           initHistoTab(rawHistoT,fs.getVectSize(),nbBin);//Reset
00435                           accumulateHistoFrame(rawHistoT,fs,window,config);
00436                           computeHistoTab(rawHistoT,fs.getVectSize());
00437                       }
00438                       
00439                       do{
00440                           if (debug) cout << "Apply norm on Seg ["<<currentSeg->begin()<<","<<currentSeg->length()<<"]"<<endl;
00441                           if (!warp) computeZeroOne(mean,cov,fs,currentSeg,config);    // compute the norm for the current segment
00442                           else computeWarp(rawHistoT,gaussHisto,fs,currentSeg,config); // warping mode
00443                       }
00444                       while (nextSeg(currentSeg,window));        // until the end;
00445                       
00446                   }
00447                 }
00448                 if (fileMode){                                   // cluster mode (the norm is done on the complete cluster
00449                     if (!warp){ // mean and cov normalisation modes
00450                         DoubleVector mean,cov;
00451                         if(extStat) {// load external stats from file (NS)
00452                             mean=extMean;
00453                             cov=extCov;}
00454                         else {
00455                             FrameAccGD frameAccu;                                                      // Defines a frame accumulator for mean and cov computation
00456                             frameAccu.reset();   
00457                             accumulateStatFrame(frameAccu,fs, selectedSegments, config); 
00458                             mean = frameAccu.getMeanVect();     // Get the mean vector
00459                             cov  = frameAccu.getStdVect();      // Get the std vector (sqrt(cov)) (remove const and ref to modify)
00460                         }
00461                         if (cms) cov.setAllValues(1.0); // remove cov effect if cms only (N.S) 
00462                         if (var) mean.setAllValues(0.0);      // remove effects if var only (jfb)
00463                         computeZeroOne(mean,cov,fs, selectedSegments, config);
00464                     }
00465                     else{    // Warping mode
00466                         freezeHistoTab(rawHistoT); //TODO replace by
00467                         initHistoTab(rawHistoT,fs.getVectSize(),nbBin);//Reset
00468                         accumulateHistoFrame(rawHistoT,fs,selectedSegments,config);
00469                         computeHistoTab(rawHistoT,fs.getVectSize());
00470                         rawHistoT[0].saveGnuplot("toto");
00471                         computeWarp(rawHistoT,gaussHisto,fs,selectedSegments,config);
00472                     } 
00473                 }                                   
00474                 // Warp optionnal additional normalisation
00475                 if (warp && warp01){
00476                     DoubleVector mean,cov;
00477                     FrameAccGD frameAccu;                                                      // Defines a frame accumulator for mean and cov computation
00478                     frameAccu.reset();   
00479                     accumulateStatFrame(frameAccu,fs, selectedSegments, config); 
00480                     mean = frameAccu.getMeanVect();     // Get the mean vector
00481                     cov  = frameAccu.getStdVect();      
00482                     computeZeroOne(mean,cov,fs, selectedSegments, config);  
00483                 }
00484                 // Output the normalized features - Take care: only the saveFeatureFileExtension parameter make a difference between the input and output files
00485                 if (!(config.existsParam("featureFlags")))
00486                     config.setParam("featureFlags",fs.getFeatureFlags().getString());// Put the file flag in the config (could be different for each file   
00487                 cout << "Writing to: " << featureFileName << endl;
00488                 FeatureFileWriter w(featureFileName, config);                             // build a featurefile writer to output the features (real features)
00489                 if (writeAllFeature) {                                                    // Output all the features- feature count id the same
00490                     SegServer fakeSegServer;                                          // Create a new fake segment server
00491                     fakeSegServer.createCluster(0);                                   // Create a new cluster
00492                     SegCluster& fakeSeg=fakeSegServer.getCluster(0);                  // Get the cluster               
00493                     fakeSeg.add(fakeSegServer.createSeg(0,fs.getFeatureCount(),codeSelectedFrame,
00494                                                         labelSelectedFrames,featureFileName));                            // Add a segment with all the features
00495                     outputFeatureFile(config,fs,fakeSeg,w);                       // output all the features - giving the same file length
00496                 }
00497                 else
00498                     outputFeatureFile(config,fs,selectedSegments, w);    // Output only the selected features - giving a shorter output 
00499                 if (debug || (verboseLevel>2)){
00500                     DoubleVector globalMean;
00501                     DoubleVector globalCov;
00502                     FrameAccGD globalFrameAcc;
00503                     unsigned long nbFrame=computeMeanCov(config,fs,selectedSegments,globalMean,globalCov); // Compute the global mean and covariance
00504                     cout <<"global mean and cov after norm, number of frame= ["<<nbFrame<<"]"<<endl;
00505                     for (unsigned i=0; i < fs.getVectSize(); i++)cout << "mean[" << i << "=" << globalMean[i] << "]\tcov[" << globalCov[i] << "]" << endl;
00506                 }
00507                 // Freeze
00508                 if (warp) freezeHistoTab(rawHistoT);
00509         }// End feature file loop
00510 
00511   }// end try
00512   
00513   catch (Exception & e)
00514       {
00515           cout << e.toString ().c_str () << endl;
00516       }
00517   return 0;
00518 }
00519 
00520 int infoFeat (Config & config) {
00521         
00522   String inputFeatureFileName =config.getParam("inputFeatureFilename");          // input feature - could be a simple feature file or a list of filename
00523   String labelSelectedFrames  =config.getParam("labelSelectedFrames");           // Only the frames from segments with this label  will be used
00524   bool segmentalMode=false;
00525   if (config.existsParam("segmentalMode"))segmentalMode=config.getParam("segmentalMode").toBool(); // selected mode for segmental computation (1 norm by file or by segment)
00526   if (verbose){
00527     cout << "NormFeat -- Display Stats on Feature";
00528     if (segmentalMode) cout << " Segmental Mode - Normalisation  by segment"<<endl;
00529     else cout << "File Mode - Normalisation by file by file" <<endl;
00530   }
00531   XLine inputFeatureFileNameList;                                                // The (feature) input filename list
00532   if ( inputFeatureFileName.endsWith(".lst")){                                   // If the file parameter is the name of a XList file
00533         XList inputFileNameXList(inputFeatureFileName,config);                       // Read the filename list file
00534         inputFeatureFileNameList=inputFileNameXList.getAllElements();                       // And put the filename in a list if the file is a list of feature filenames
00535   }
00536   else {                                               // It was a simple feature file and not a filename list
00537     inputFeatureFileNameList.addElement(inputFeatureFileName);                   // add the filename in the list
00538   }
00539   try{
00540     MixtureServer ms(config); 
00541  
00542     String *file;
00543     while ((file=inputFeatureFileNameList.getElement())!= NULL){                   // Loop on each feature file
00544       String & featureFileName=(*file);                                            // Current file basename
00545       FeatureServer fs(config,featureFileName);                                    // Reading the feature file
00546       SegServer segmentsServer;                                                             // Create the segment server for managing the segments/clusters
00547       LabelServer labelServer;                                                              // Create the lable server, for indexing the segments/clusters
00548       initializeClusters(featureFileName,segmentsServer,labelServer,config);               // Reading the segmentation files for each feature input file
00549       verifyClusterFile(segmentsServer,fs,config);                                          // Verify if the segments ending before the end of the feature files...
00550       unsigned long codeSelectedFrame=labelServer.getLabelIndexByString(labelSelectedFrames);            // Get the index of the cluster with in interest audio segments
00551       if (verbose)cout << "Display Stats for file ["<<featureFileName<<"]"<< endl;
00552       SegCluster& selectedSegments=segmentsServer.getCluster(codeSelectedFrame);        // Gives the cluster of the selected/used segments   
00553       FrameAccGD frameAccu;                                                             // Defines a frame accumulator for mean and cov computation
00554       frameAccu.reset();                                                                // reset the frame accumulator
00555       Seg *seg;                                                                         // current selectd segment
00556       selectedSegments.rewind();                                                        // reset the reader at the begin of the input stream
00557       while((seg=selectedSegments.getSeg())!=NULL){                                     // For each of the selected segments
00558         accumulateStatFrame(frameAccu,fs,seg,config);                   // Accumulate the stat for the segment
00559         if (segmentalMode){                                                             // Normalize segment by segment mode is selected
00560         cout << "Warning: Display Stats only for seg: " << seg->begin() << " " << seg->begin()+seg->length() << endl;
00561         displayStats(frameAccu,fs,cout,config);                      // Display Stats
00562         frameAccu.reset();                                                            // Reset the accumulator for the next segment      
00563         }
00564       }
00565       if (!segmentalMode){                                                              // The mean/cov are computed on all the segments
00566         selectedSegments.rewind();                                                      // reset the reader at the begin of the input stream
00567         globalMeanCov (fs,selectedSegments,frameAccu,config);
00568         String filename=fs.getNameOfASource(0);
00569         ofstream out((filename+".stat").c_str());
00570         cout << "Warning: Saving Stats only in " << filename << ".stat" << endl;
00571         displayStats(frameAccu,fs,out,config);                      // Display Stats
00572         out.close();
00573         }
00574         }
00575  }// end try
00576   catch (Exception & e)
00577       {
00578         cout << e.toString ().c_str () << endl;
00579       }
00580   return 0;
00581 }
00582 
00583 int featMap (Config & config) {
00584 
00585 String inputFeatureFileName =config.getParam("inputFeatureFilename");          // input feature - could be a simple feature file or a list of filename
00586 String labelSelectedFrames  =config.getParam("labelSelectedFrames");           // Only the frames from segments with this label  will be used
00587 bool writeAllFeature=(config.getParam("writeAllFeatures")=="true");            // Define if all the feature (selected or not) should be written
00588   if (config.getParam_debug()) debug=true;  else debug=false;
00589   if (config.existsParam("verbose")) verbose=true; else verbose=false; 
00590 if (verbose){
00591         cout << "NormFeat: FeatureMapping Mode - Normalisation by file by file" <<endl;
00592 }
00593 XLine inputFeatureFileNameList;                                                                         // The (feature) input filename list
00594 if ( inputFeatureFileName.endsWith(".lst")) {                                                    // If the file parameter is the name of a XList file
00595         XList inputFileNameXList(inputFeatureFileName,config);                          // Read the filename list file
00596         inputFeatureFileNameList=inputFileNameXList.getAllElements();                       // And put the filename in a list if the file is a list of feature filenames
00597 }
00598 else {                                               // It was a simple feature file and not a filename list
00599         inputFeatureFileNameList.addElement(inputFeatureFileName);                   // add the filename in the list
00600 }
00601 try{
00602         MixtureServer ms(config); 
00603         ms.loadMixtureGD(config.getParam("inputRootModelFilename"));                                            // Load the model to map to
00604         ms.loadMixtureGD(config.getParam("inputSubFilename"));
00605         
00606         String *file;
00607         while ((file=inputFeatureFileNameList.getElement())!= NULL){                   // Loop on each feature file
00608                 String & featureFileName=(*file);                                            // Current file basename
00609                 FeatureServer fs(config,featureFileName);                                    // Reading the feature file
00610                 SegServer segmentsServer;                                                             // Create the segment server for managing the segments/clusters
00611                 LabelServer labelServer;                                                              // Create the lable server, for indexing the segments/clusters
00612                 initializeClusters(featureFileName,segmentsServer,labelServer,config);               // Reading the segmentation files for each feature input file
00613                 verifyClusterFile(segmentsServer,fs,config);                                          // Verify if the segments ending before the end of the feature files...
00614                 unsigned long codeSelectedFrame=labelServer.getLabelIndexByString(labelSelectedFrames);            // Get the index of the cluster with in interest audio segments
00615                 if (verbose) cout << "Feature Mapping file normalisation["<<featureFileName<<"]"<< endl;
00616                 SegCluster& selectedSegments=segmentsServer.getCluster(codeSelectedFrame);        // Gives the cluster of the selected/used segments   
00617                 FrameAccGD frameAccu;                                                             // Defines a frame accumulator for mean and cov computation
00618                 frameAccu.reset();                                                                // reset the frame accumulator
00619                 featureMapping(ms,fs,selectedSegments,config); // perform mapping on the whole segment
00620                 
00621                 // Output the normalized features - Take care: only the saveFeatureFileExtension parameter make a difference between the input and output files
00622                 if (!(config.existsParam("featureFlags")))
00623                         config.setParam("featureFlags",fs.getFeatureFlags().getString());                 // Put the file flag in the config (could be different for each file   
00624                         //config.setParam("featureServerMask",config.getParam("outputFeatureServerMask")); // To be replaced 
00625                 FeatureFileWriter w(featureFileName, config);                                        // build a featurefile writer to output the features
00626                 
00627                 if (writeAllFeature) {                                                            // Output all the features- feature count id the same
00628                         SegServer fakeSegServer;                                                        // Create a new fake segment server
00629                         fakeSegServer.createCluster(0);                                                 // Create a new cluster
00630                         SegCluster& fakeSeg=fakeSegServer.getCluster(0);                                // Get the cluster               
00631                         fakeSeg.add(fakeSegServer.createSeg(0,fs.getFeatureCount(),codeSelectedFrame,
00632                                                             labelSelectedFrames,featureFileName));       // Add a segment with all the features
00633                         outputFeatureFile(config,fs,fakeSeg,w);                                 // output all the features - giving the same file length
00634                 }
00635                 else
00636                 outputFeatureFile(config,fs,selectedSegments, w);                       // Output only the selected features - giving a shorter output 
00637         }                                                                                   // End feature file loop
00638 } // end try
00639 catch (Exception & e)
00640 {
00641         cout << e.toString ().c_str () << endl;
00642 }
00643 return 0;
00644 }
00645 
00646 void featureWarping(Matrix <double> table,FeatureServer & fs,SegCluster & selectedSegments,Config & config) {
00647   Seg *seg;                                                                         // current selectd segment
00648   selectedSegments.rewind();                                                      // reset the reader at the begin of the input stream
00649   while((seg=selectedSegments.getSeg())!=NULL){                                   // For each of the selected segments
00650         unsigned long begin=seg->begin()+fs.getFirstFeatureIndexOfASource(seg->sourceName()); // Idx of the first frame of the current file in the feature server
00651         fs.seekFeature(begin);
00652         Feature f;
00653         for (unsigned long idxFrame=0;idxFrame<seg->length();idxFrame++){                          // for all the features of the segment
00654         fs.readFeature(f,0);            
00655         // do it
00656         fs.writeFeature(f);
00657         }
00658   }     
00659 }
00660 
00661 int featWarp (Config & config) {
00662 
00663 String inputFeatureFileName =config.getParam("inputFeatureFilename");          // input feature - could be a simple feature file or a list of filename
00664 String labelSelectedFrames  =config.getParam("labelSelectedFrames");           // Only the frames from segments with this label  will be used
00665 bool writeAllFeature=(config.getParam("writeAllFeatures")=="true");            // Define if all the feature (selected or not) should be written
00666   if (config.getParam_debug()) debug=true;  else debug=false;
00667   if (config.existsParam("verbose")) verbose=true; else verbose=false; 
00668 if (verbose){
00669         cout << "NormFeat: FeatureWarping Mode - Normalisation by file by file" <<endl;
00670 }
00671 XLine inputFeatureFileNameList;                                                                         // The (feature) input filename list
00672 if ( inputFeatureFileName.endsWith(".lst")) {                                                    // If the file parameter is the name of a XList file
00673         XList inputFileNameXList(inputFeatureFileName,config);                          // Read the filename list file
00674         inputFeatureFileNameList=inputFileNameXList.getAllElements();                       // And put the filename in a list if the file is a list of feature filenames
00675 }
00676 else {                                               // It was a simple feature file and not a filename list
00677         inputFeatureFileNameList.addElement(inputFeatureFileName);                   // add the filename in the list
00678 }
00679 try{
00680         MixtureServer ms(config); 
00681         ms.loadMixtureGD(config.getParam("inputRootModelFilename"));                                            // Load the model to map to
00682         ms.loadMixtureGD(config.getParam("inputSubFilename"));
00683         
00684         String *file;
00685         while ((file=inputFeatureFileNameList.getElement())!= NULL){                   // Loop on each feature file
00686                 String & featureFileName=(*file);                                            // Current file basename
00687                 FeatureServer fs(config,featureFileName);                                    // Reading the feature file
00688                 SegServer segmentsServer;                                                             // Create the segment server for managing the segments/clusters
00689                 LabelServer labelServer;                                                              // Create the lable server, for indexing the segments/clusters
00690                 initializeClusters(featureFileName,segmentsServer,labelServer,config);               // Reading the segmentation files for each feature input file
00691                 verifyClusterFile(segmentsServer,fs,config);                                          // Verify if the segments ending before the end of the feature files...
00692                 unsigned long codeSelectedFrame=labelServer.getLabelIndexByString(labelSelectedFrames);            // Get the index of the cluster with in interest audio segments
00693                 if (verbose) cout << "Feature Warping file normalisation["<<featureFileName<<"]"<< endl;
00694                 SegCluster& selectedSegments=segmentsServer.getCluster(codeSelectedFrame);        // Gives the cluster of the selected/used segments   
00695                 Matrix <double> table;
00696                 table.load("table");
00697                 featureWarping(table,fs,selectedSegments,config); // perform mapping on the whole segment
00698                 
00699                 // Output the normalized features - Take care: only the saveFeatureFileExtension parameter make a difference between the input and output files
00700                 if (!(config.existsParam("featureFlags")))
00701                         config.setParam("featureFlags",fs.getFeatureFlags().getString());                 // Put the file flag in the config (could be different for each file   
00702                         //config.setParam("featureServerMask",config.getParam("outputFeatureServerMask")); // To be replaced 
00703                 FeatureFileWriter w(featureFileName, config);                                        // build a featurefile writer to output the features
00704                 
00705                 if (writeAllFeature) {                                                            // Output all the features- feature count id the same
00706                         SegServer fakeSegServer;                                                        // Create a new fake segment server
00707                         fakeSegServer.createCluster(0);                                                 // Create a new cluster
00708                         SegCluster& fakeSeg=fakeSegServer.getCluster(0);                                // Get the cluster               
00709                         fakeSeg.add(fakeSegServer.createSeg(0,fs.getFeatureCount(),codeSelectedFrame,
00710                                                             labelSelectedFrames,featureFileName));       // Add a segment with all the features
00711                         outputFeatureFile(config,fs,fakeSeg,w);                                 // output all the features - giving the same file length
00712                 }
00713                 else
00714                 outputFeatureFile(config,fs,selectedSegments, w);                       // Output only the selected features - giving a shorter output 
00715         }                                                                                   // End feature file loop
00716 } // end try
00717 catch (Exception & e)
00718 {
00719         cout << e.toString ().c_str () << endl;
00720 }
00721 return 0;
00722 }
00723 
00724 int normFeatNAP (Config & config) {
00725 
00726 String inputFeatureFileName =config.getParam("inputFeatureFilename");          // input feature - could be a simple feature file or a list of filename
00727 String labelSelectedFrames  =config.getParam("labelSelectedFrames");           // Only the frames from segments with this label  will be used
00728 bool writeAllFeature=(config.getParam("writeAllFeatures")=="true");            // Define if all the feature (selected or not) should be written
00729   if (config.getParam_debug()) debug=true;  else debug=false;
00730   if (config.existsParam("verbose")) verbose=true; else verbose=false; 
00731 if (verbose){
00732         cout << "NormFeat: NAP Mode - Normalisation by file by file" <<endl;
00733 }
00734 XLine inputFeatureFileNameList;                                                                         // The (feature) input filename list
00735 if ( inputFeatureFileName.endsWith(".lst")) {                                                    // If the file parameter is the name of a XList file
00736         XList inputFileNameXList(inputFeatureFileName,config);                          // Read the filename list file
00737         inputFeatureFileNameList=inputFileNameXList.getAllElements();                       // And put the filename in a list if the file is a list of feature filenames
00738 }
00739 else {                                               // It was a simple feature file and not a filename list
00740         inputFeatureFileNameList.addElement(inputFeatureFileName);                   // add the filename in the list
00741 }
00742 try{
00743         MixtureServer ms(config); 
00744         StatServer ss(config);
00745         MixtureGD & world=ms.loadMixtureGD(config.getParam("inputWorldFilename"));                                              // Load the world model
00746         // Compute UBM channel effect
00747         RealVector <double> ubm_offset; // for nap
00748         Matrix <double> channelMatrix;
00749         channelMatrix.load(config.getParam("initChannelMatrix"),config);
00750         getUbmOffset(ubm_offset,channelMatrix,world,config);
00751         
00752 
00753         String *file;
00754         while ((file=inputFeatureFileNameList.getElement())!= NULL){                   // Loop on each feature file
00755                 String & featureFileName=(*file);                                            // Current file basename
00756                 FeatureServer fs(config,featureFileName);                                    // Reading the feature file
00757                 SegServer segmentsServer;                                                             // Create the segment server for managing the segments/clusters
00758                 LabelServer labelServer;                                                              // Create the lable server, for indexing the segments/clusters
00759                 initializeClusters(featureFileName,segmentsServer,labelServer,config);               // Reading the segmentation files for each feature input file
00760                 verifyClusterFile(segmentsServer,fs,config);                                          // Verify if the segments ending before the end of the feature files...
00761                 unsigned long codeSelectedFrame=labelServer.getLabelIndexByString(labelSelectedFrames);            // Get the index of the cluster with in interest audio segments
00762                 if (verbose) cout << "Eigenchannel file normalisation["<<featureFileName<<"]"<< endl;
00763                 SegCluster& selectedSegments=segmentsServer.getCluster(codeSelectedFrame);        // Gives the cluster of the selected/used segments   
00764                 FrameAccGD frameAccu;                                                             // Defines a frame accumulator for mean and cov computation
00765                 frameAccu.reset();                                                                // reset the frame accumulator
00766                 featureChannelCompNAP(ubm_offset,world,fs,ss,selectedSegments,config); // perform compensation on the whole segment
00767                 
00768                 // Output the normalized features - Take care: only the saveFeatureFileExtension parameter make a difference between the input and output files
00769                 if (!(config.existsParam("featureFlags")))
00770                         config.setParam("featureFlags",fs.getFeatureFlags().getString());                 // Put the file flag in the config (could be different for each file   
00771                         //config.setParam("featureServerMask",config.getParam("outputFeatureServerMask")); // To be replaced 
00772                 FeatureFileWriter w(featureFileName, config);                                        // build a featurefile writer to output the features
00773                 
00774                 if (writeAllFeature) {                                                            // Output all the features- feature count id the same
00775                         SegServer fakeSegServer;                                                        // Create a new fake segment server
00776                         fakeSegServer.createCluster(0);                                                 // Create a new cluster
00777                         SegCluster& fakeSeg=fakeSegServer.getCluster(0);                                // Get the cluster               
00778                         fakeSeg.add(fakeSegServer.createSeg(0,fs.getFeatureCount(),codeSelectedFrame,
00779                                                             labelSelectedFrames,featureFileName));       // Add a segment with all the features
00780                         outputFeatureFile(config,fs,fakeSeg,w);                                 // output all the features - giving the same file length
00781                 }
00782                 else
00783                 outputFeatureFile(config,fs,selectedSegments, w);                       // Output only the selected features - giving a shorter output 
00784         }                                                                                   // End feature file loop
00785 } // end try
00786 catch (Exception & e)
00787 {
00788         cout << e.toString ().c_str () << endl;
00789 }
00790 return 0;
00791 }
00792 
00793 int normFeatFA (Config & config) {
00794 
00795 String inputFeatureFileName =config.getParam("inputFeatureFilename");          // input feature - could be a simple feature file or a list of filename
00796 String labelSelectedFrames  =config.getParam("labelSelectedFrames");           // Only the frames from segments with this label  will be used
00797 bool writeAllFeature=(config.getParam("writeAllFeatures")=="true");            // Define if all the feature (selected or not) should be written
00798 if (verbose)    cout << "(NormFeat) EigenChannel Mode - Normalisation by file by file" <<endl;
00799 
00800 XLine inputFeatureFileNameList;                                                                         // The (feature) input filename list
00801 if ( inputFeatureFileName.endsWith(".lst")) {                                                    // If the file parameter is the name of a XList file
00802         XList inputFileNameXList(inputFeatureFileName,config);                          // Read the filename list file
00803         inputFeatureFileNameList=inputFileNameXList.getAllElements();                       // And put the filename in a list if the file is a list of feature filenames
00804 }
00805 else {                                               // It was a simple feature file and not a filename list
00806         inputFeatureFileNameList.addElement(inputFeatureFileName);                   // add the filename in the list
00807 }
00808 try{
00809         String *file;
00810         while ((file=inputFeatureFileNameList.getElement())!= NULL){                   // Loop on each feature file
00811                 String & featureFilename=(*file);                                            // Current file basename
00812                 if (verbose) cout << "(NormFeat) Eigenchannel file normalisation["<<featureFilename<<"]"<< endl;
00813                 FeatureServer fs(config,featureFilename);
00814                 String labelSelectedFrames=config.getParam("labelSelectedFrames");
00815                 
00816                 SegServer segmentsServer;
00817                 LabelServer labelServer;
00818                 initializeClusters(featureFilename,segmentsServer,labelServer,config);
00819                 verifyClusterFile(segmentsServer,fs,config);
00820                 unsigned long codeSelectedFrame=labelServer.getLabelIndexByString(labelSelectedFrames);
00821                 SegCluster& selectedSegments=segmentsServer.getCluster(codeSelectedFrame);  
00822 
00823                 selectedSegments.rewind();
00824   
00825                 FactorAnalysisStat FAAcc(featureFilename,fs,config);        
00826                 FAAcc.estimateXYAndNorm(selectedSegments,fs,config);
00827                 cms(featureFilename,fs,config);
00828 
00829                 // Output the normalized features - Take care: only the saveFeatureFileExtension parameter make a difference between the input and output files
00830                 if (!(config.existsParam("featureFlags")))
00831                         config.setParam("featureFlags",fs.getFeatureFlags().getString());                 // Put the file flag in the config (could be different for each file   
00832                 FeatureFileWriter w(featureFilename, config);                                        // build a featurefile writer to output the features
00833                 
00834                 if (writeAllFeature) {                                                            // Output all the features- feature count id the same
00835                         SegServer fakeSegServer;                                                        // Create a new fake segment server
00836                         fakeSegServer.createCluster(0);                                                 // Create a new cluster
00837                         SegCluster& fakeSeg=fakeSegServer.getCluster(0);                                // Get the cluster               
00838                         fakeSeg.add(fakeSegServer.createSeg(0,fs.getFeatureCount(),codeSelectedFrame,
00839                                                             labelSelectedFrames,featureFilename));       // Add a segment with all the features
00840                         outputFeatureFile(config,fs,fakeSeg,w);                                 // output all the features - giving the same file length
00841                 }
00842                 else
00843                 outputFeatureFile(config,fs,selectedSegments, w);                       // Output only the selected features - giving a shorter output 
00844         }                                                                                   // End feature file loop
00845 } // end try
00846 catch (Exception & e)
00847 {
00848         cout << e.toString ().c_str () << endl;
00849 }
00850 return 0;
00851 }
00852 
00853 //-------------------------------------------------------------------------------------------------------
00854 //      Perform LFA normalisation of the features (Substract the Channel component in the feature space)
00855 //-------------------------------------------------------------------------------------------------------
00856 int normFeatLFA (Config & config) {
00857 
00858         String inputFeatureFileName =config.getParam("inputFeatureFilename");          // input feature - could be a simple feature file or a list of filename
00859 
00860         String labelSelectedFrames  =config.getParam("labelSelectedFrames");           // Only the frames from segments with this label  will be used
00861         bool writeAllFeature=(config.getParam("writeAllFeatures")=="true");            // Define if all the feature (selected or not) should be written
00862         if (verbose)    cout << "(NormFeat) Feature LFA Mode - Normalisation file by file" <<endl;
00863 
00864         XLine inputFeatureFileNameList;                                                                         // The (feature) input filename list
00865         if ( inputFeatureFileName.endsWith(".lst")) {                                           // If the file parameter is the name of a XList file
00866                 XList inputFileNameXList(inputFeatureFileName,config);                  // Read the filename list file
00867                 inputFeatureFileNameList=inputFileNameXList.getAllElements();   // And put the filename in a list if the file is a list of feature filenames
00868         }
00869         else {                                                                                                                          // It was a simple feature file and not a filename list
00870                 inputFeatureFileNameList.addElement(inputFeatureFileName);              // add the filename in the list
00871         }
00872 
00873 try{
00874         String *file;
00875                 
00876         //Load Eigenchannel Matrix
00877         Matrix<double> U;
00878         String uName = config.getParam("matrixFilesPath") + config.getParam("eigenChannelMatrix") + config.getParam("loadMatrixFilesExtension");
00879         U.load (uName, config);
00880 
00881         while ((file=inputFeatureFileNameList.getElement())!= NULL){                   // Loop on each feature file
00882 
00883                 String & featureFilename=(*file);                                            // Current file basename
00884                 if (verbose) cout << "(NormFeat) Eigenchannel file normalisation["<<featureFilename<<"]"<< endl;
00885 
00886                 FeatureServer fs(config,featureFilename);
00887 
00888                 String labelSelectedFrames=config.getParam("labelSelectedFrames");
00889                 
00890                 SegServer segmentsServer;
00891                 LabelServer labelServer;
00892                 initializeClusters(featureFilename,segmentsServer,labelServer,config);
00893 
00894                 verifyClusterFile(segmentsServer,fs,config);
00895 
00896                 unsigned long codeSelectedFrame=labelServer.getLabelIndexByString(labelSelectedFrames);
00897                 SegCluster& selectedSegments=segmentsServer.getCluster(codeSelectedFrame);  
00898                 selectedSegments.rewind();
00899 
00900                 JFAAcc jfaAcc(featureFilename,config);
00901 
00902                 jfaAcc.loadEC(U, config);
00903 
00905                 jfaAcc.computeAndAccumulateJFAStat(config);
00906 
00907                 jfaAcc.substractMplusDZByChannel();
00908 
00909                 jfaAcc.substractMplusUX();
00910 
00912                 jfaAcc.estimateUEUT(config);
00913 
00915                 jfaAcc.estimateAndInverseL_EC(config);
00916 
00918                 jfaAcc.estimateX(config);
00919 
00920                 jfaAcc.estimateZMAP(config.getParam("regulationFactor").toLong());
00921 
00923                 jfaAcc.substractUXfromFeatures(fs,config);
00924 
00925                 if(config.getParam("cms").toBool()){
00926                         cms(featureFilename,fs,config);
00927                 }
00928 
00929                 // Output the normalized features - Take care: only the saveFeatureFileExtension parameter make a difference between the input and output files
00930                 if (!(config.existsParam("featureFlags")))
00931                         config.setParam("featureFlags",fs.getFeatureFlags().getString());                               // Put the file flag in the config (could be different for each file   
00932                 FeatureFileWriter w(featureFilename, config);                                                                           // build a featurefile writer to output the features
00933 
00934                 if (writeAllFeature) {                                                                                                                          // Output all the features- feature count id the same
00935                         SegServer fakeSegServer;                                                        // Create a new fake segment server
00936                         fakeSegServer.createCluster(0);                                                 // Create a new cluster
00937                         SegCluster& fakeSeg=fakeSegServer.getCluster(0);                                // Get the cluster               
00938                         fakeSeg.add(fakeSegServer.createSeg(0,fs.getFeatureCount(),codeSelectedFrame,
00939                                                             labelSelectedFrames,featureFilename));                                              // Add a segment with all the features
00940                         outputFeatureFile(config,fs,fakeSeg,w);                                                                         // output all the features - giving the same file length
00941                 }
00942                 else
00943                 outputFeatureFile(config,fs,selectedSegments, w);                                                                       // Output only the selected features - giving a shorter output 
00944         }                                                                                                                                                                               // End feature file loop
00945 } // end try
00946 catch (Exception & e)
00947 {
00948         cout << e.toString ().c_str () << endl;
00949 }
00950 return 0;
00951 }
00952 
00953 
00954 
00955 #endif // !defined(ALIZE_NormFeat_cpp)
00956