MixtureFileReaderAmiral.cpp

Go to the documentation of this file.
00001 /*
00002         This file is part of ALIZE which is an open-source tool for 
00003         speaker recognition.
00004 
00005     ALIZE is free software: you can redistribute it and/or modify
00006     it under the terms of the GNU Lesser General Public License as 
00007     published by the Free Software Foundation, either version 3 of 
00008     the License, or any later version.
00009 
00010     ALIZE is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013     GNU Lesser General Public License for more details.
00014 
00015     You should have received a copy of the GNU Lesser General Public 
00016     License along with ALIZE.
00017     If not, see <http://www.gnu.org/licenses/>.
00018         
00019         ALIZE is a development project initiated by the ELISA consortium
00020         [alize.univ-avignon.fr/] and funded by the French Research 
00021         Ministry in the framework of the TECHNOLANGUE program 
00022         [www.technolangue.net]
00023 
00024         The ALIZE project team wants to highlight the limits of voice
00025         authentication in a forensic context.
00026         The "Person  Authentification by Voice: A Need of Caution" paper 
00027         proposes a good overview of this point (cf. "Person  
00028         Authentification by Voice: A Need of Caution", Bonastre J.F., 
00029         Bimbot F., Boe L.J., Campbell J.P., Douglas D.A., Magrin-
00030         chagnolleau I., Eurospeech 2003, Genova].
00031         The conclusion of the paper of the paper is proposed bellow:
00032         [Currently, it is not possible to completely determine whether the 
00033         similarity between two recordings is due to the speaker or to other 
00034         factors, especially when: (a) the speaker does not cooperate, (b) there 
00035         is no control over recording equipment, (c) recording conditions are not 
00036         known, (d) one does not know whether the voice was disguised and, to a 
00037         lesser extent, (e) the linguistic content of the message is not 
00038         controlled. Caution and judgment must be exercised when applying speaker 
00039         recognition techniques, whether human or automatic, to account for these 
00040         uncontrolled factors. Under more constrained or calibrated situations, 
00041         or as an aid for investigative purposes, judicious application of these 
00042         techniques may be suitable, provided they are not considered as infallible.
00043         At the present time, there is no scientific process that enables one to 
00044         uniquely characterize a person=92s voice or to identify with absolute 
00045         certainty an individual from his or her voice.]
00046         Contact Jean-Francois Bonastre for more information about the licence or
00047         the use of ALIZE
00048 
00049         Copyright (C) 2003-2010
00050         Laboratoire d'informatique d'Avignon [lia.univ-avignon.fr]
00051         ALIZE admin [alize@univ-avignon.fr]
00052         Jean-Francois Bonastre [jean-francois.bonastre@univ-avignon.fr]
00053 */
00054 
00055 #if !defined(ALIZE_MixtureFileReaderAmiral_cpp)
00056 #define ALIZE_MixtureFileReaderAmiral_cpp
00057 
00058 #include <new>
00059 #include "MixtureFileReaderAmiral.h"
00060 #include "Mixture.h"
00061 #include "MixtureGD.h"
00062 #include "DistribGD.h"
00063 #include "Exception.h"
00064 #include "Config.h"
00065 #include "FileReader.h"
00066 
00067 using namespace alize;
00068 typedef MixtureFileReaderAmiral R;
00069 
00070 //-------------------------------------------------------------------------
00071 R::MixtureFileReaderAmiral(const FileName& f, const Config& c, BigEndian be)
00072 :MixtureFileReaderAbstract(&FileReader::create(f, getPath(f, c),
00073  getExt(f, c), getBigEndian(c, be)), c) {}
00074 //-------------------------------------------------------------------------
00075 R& R::create(const FileName& f, const Config& c, BigEndian be)
00076 {
00077   R* p = new (std::nothrow) R(f, c, be);
00078   assertMemoryIsAllocated(p, __FILE__, __LINE__);
00079   return *p;
00080 }
00081 //-------------------------------------------------------------------------
00082 const Mixture& R::readMixture()
00083 {
00084   assert(_pReader != NULL);
00085   if (_pReader->readString(24) != "LIA Modele Multidistrib.")
00086     throw InvalidDataException("Invalid file", __FILE__, __LINE__,
00087                   _pReader->getFullFileName());
00088   _pReader->readChar(); // '0'
00089   _pReader->swap() = (_pReader->readInt2() != 1);
00090   if (_pReader->readChar() == 2) // version
00091     readVersion2();
00092   else
00093     throw InvalidDataException("Invalid file", __FILE__, __LINE__,
00094                   _pReader->getFullFileName());
00095   return *_pMixture;
00096 }
00097 //-------------------------------------------------------------------------
00098 const MixtureGD& R::readMixtureGD()
00099 {
00100   assert(_pReader != NULL);
00101   if (_pReader->readString(24) != "LIA Modele Multidistrib.")
00102     throw InvalidDataException("Invalid file", __FILE__, __LINE__,
00103                   _pReader->getFullFileName());
00104   _pReader->readChar(); // '0'
00105   _pReader->swap() = (_pReader->readInt2() != 1);
00106   if (_pReader->readChar() == 2) // version
00107     readVersionGD2();
00108   else
00109     throw InvalidDataException("Invalid file", __FILE__, __LINE__,
00110                   _pReader->getFullFileName());
00111   return *static_cast<MixtureGD*>(_pMixture);
00112 }
00113 //-------------------------------------------------------------------------
00114 void R::readVersionGD2() // private
00115 {
00116   unsigned long c;
00117   MixtureGD* pMix = NULL;
00118   assert(_pReader != NULL);
00119 
00120   try
00121   {
00122     // Taille du modele
00123     _pReader->readInt4();
00124 
00125     // taille zone commentaire
00126     long t = _pReader->readInt4();
00127 
00128     // commentaires + identite (voir MM_io.c)
00129     if (t > 0)
00130     {
00131       _pReader->readString(t);
00132       //readChar(); // '0'
00133     }
00134 
00135     // nombre de distributions
00136     unsigned long distribCount = _pReader->readInt4();
00137   
00138     // taille du vecteur
00139     _vectSize = _pReader->readInt2();
00140 
00141     // Nbre de trames d'apprentissage
00142     _pReader->readUInt4();
00143 
00144     // distribution weights
00145     DoubleVector weightVector;
00146     for (c=0; c<distribCount; c++)
00147     { weightVector.addValue(_pReader->readDouble()); }
00148 
00149     for (c=0; c<distribCount; c++)
00150     {
00151       if (_pReader->readChar() == 1) // type de distribution 1 = GAUSSIAN
00152       {
00153         _pReader->readDouble(); // cst
00154 
00155         char typeMatrice = _pReader->readChar();
00156 
00157         if (typeMatrice == 1) // 1 = matrice diag
00158         {
00159           if (pMix == NULL)
00160             pMix = &MixtureGD::create(K::k, _pReader->getFileName(),
00161                         _vectSize, distribCount);
00162           pMix->weight(c) = weightVector[c];
00163           readDistribGD(pMix->getDistrib(c));
00164         }
00165         else // autres types de matrices
00166           throw InvalidDataException("Matrix is not diagonal",
00167                      __FILE__, __LINE__, _pReader->getFullFileName());
00168       }
00169       else // autres types de distributions
00170         throw InvalidDataException("Distribution is not Gaussian",
00171                     __FILE__, __LINE__, _pReader->getFullFileName());
00172     }
00173     _pMixture = pMix;
00174   }
00175   catch (Exception&)
00176   {
00177     if (pMix != NULL)
00178        delete pMix;
00179     throw; // do not use 'throw e'
00180   }
00181 }
00182 //-------------------------------------------------------------------------
00183 void R::readVersion2() // private
00184 {
00185   unsigned long c;
00186   _pMixture = NULL;
00187   assert(_pReader != NULL);
00188   try
00189   {
00190     // Taille du modele
00191     _pReader->readInt4();
00192 
00193     // taille zone commentaire
00194     long t = _pReader->readInt4();
00195 
00196     // commentaires + identite (voir MM_io.c)
00197     if (t > 0)
00198       _pReader->readString(t);
00199 
00200     // nombre de distributions
00201     unsigned long distribCount = _pReader->readInt4();
00202   
00203     // taille du vecteur
00204     _vectSize = _pReader->readInt2();
00205 
00206     // Nbre de trames d'apprentissage
00207     _pReader->readUInt4();
00208 
00209     // distribution weights
00210     DoubleVector weightVector;
00211     for (c=0; c<distribCount; c++)
00212     { weightVector.addValue(_pReader->readDouble()); }
00213 
00214     for (c=0; c<distribCount; c++)
00215     {
00216       if (_pReader->readChar() == 1) // type de distribution 1 = GAUSSIAN
00217       {
00218         _pReader->readDouble(); // cst
00219 
00220         char typeMatrice = _pReader->readChar();
00221 
00222         if (typeMatrice == 1) // 1 = matrice diag
00223         {
00224           if (_pMixture == NULL)
00225             _pMixture = &MixtureGD::create(K::k, _pReader->getFileName()
00226                          ,_vectSize, distribCount);
00227           _pMixture->weight(c) = weightVector[c];
00228           readDistribGD(static_cast<DistribGD&>
00229                       (_pMixture->getDistrib(c)));
00230         }
00231         else if (typeMatrice == 0) // 0 = matrice full
00232         {
00233           throw InvalidDataException("Unknown matrix type",
00234                       __FILE__, __LINE__, _pReader->getFullFileName());
00235         }
00236         else // autres types de matrices
00237           throw InvalidDataException("Unknown matrix type",
00238                       __FILE__, __LINE__, _pReader->getFullFileName());
00239       }
00240       else // autres types de distributions
00241         throw InvalidDataException("Unknown distribution type",
00242                       __FILE__, __LINE__, _pReader->getFullFileName());
00243     }
00244   }
00245   catch (Exception&)
00246   {
00247     if (_pMixture != NULL)
00248        delete _pMixture;
00249     throw; // do not use 'throw e'
00250   }
00251 }
00252 //-------------------------------------------------------------------------
00253 void R::readDistribGD(DistribGD& distrib)
00254 {
00255   assert(distrib.getVectSize() == _vectSize);
00256   assert(_pReader != NULL);
00257   unsigned long i;
00258   // covariance
00259   for (i = 0; i < _vectSize; i++)
00260   { distrib.setCov(_pReader->readDouble(), i); }
00261 
00262   // covariance inverse
00263   for (i = 0; i < _vectSize; i++)
00264   { _pReader->readDouble(); }
00265 
00266   // moyenne
00267   for (i = 0; i < _vectSize; i++)
00268   { distrib.setMean(_pReader->readDouble(), i); }
00269 
00270   // determinant
00271   _pReader->readDouble();
00272 
00273   // somme des coeff d'appartenance des
00274   // trames d'apprentissage a la distribution
00275   _pReader->readDouble();
00276 
00277   // calcul det, cst, cov inv
00278   distrib.computeAll();
00279 }
00280 //-------------------------------------------------------------------------
00281 String R::getClassName() const { return "MixtureFileReaderAmiral"; }
00282 //-------------------------------------------------------------------------
00283 R::~MixtureFileReaderAmiral() {}
00284 //-------------------------------------------------------------------------
00285 
00286 #endif // !defined(ALIZE_MixtureFileReaderAmiral_cpp)
00287