MixtureFileWriter.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_MixtureFileWriter_cpp)
00056 #define ALIZE_MixtureFileWriter_cpp
00057 
00058 #include "MixtureFileWriter.h"
00059 #include "MixtureGD.h"
00060 #include "MixtureGF.h"
00061 #include "DistribGD.h"
00062 #include "DistribGF.h"
00063 #include "Exception.h"
00064 #include "Config.h"
00065 #include <cmath>
00066 
00067 using namespace alize;
00068 typedef MixtureFileWriter W;
00069 
00070 //-------------------------------------------------------------------------
00071 W::MixtureFileWriter(const FileName& f, const Config& c)
00072 :FileWriter(getFullFileName(c, f)), _config(c) {}
00073 //-------------------------------------------------------------------------
00074 String W::getFullFileName(const Config& c, const FileName& f) const
00075 {   // protected
00076   if (f.beginsWith("/") || f.beginsWith("./"))
00077     return f;
00078   return c.getParam_mixtureFilesPath() + f
00079        + c.getParam_saveMixtureFileExtension();
00080 }
00081 //-------------------------------------------------------------------------
00082 void W::writeMixture(const Mixture& m)
00083 {
00084   MixtureFileWriterFormat format;
00085   if (!_config.existsParam_saveMixtureFileFormat
00086        && _fileName.endsWith(".xml"))
00087     format = MixtureFileWriterFormat_XML;
00088   else 
00089     format = _config.getParam_saveMixtureFileFormat();
00090 
00091   if (m.getClassName() == "MixtureGD")
00092   {
00093     switch (format)
00094     {
00095       case MixtureFileWriterFormat_XML:
00096         open(); //can throw IOException
00097         writeMixtureGD_XML((const MixtureGD&)m);
00098         close();
00099         return;
00100       case MixtureFileWriterFormat_RAW:
00101         open(); //can throw IOException
00102         writeMixtureGD_RAW((const MixtureGD&)m);
00103         close();
00104         return;
00105       case MixtureFileWriterFormat_ETAT:
00106         open(); //can throw IOException
00107         writeMixtureGD_ETAT((const MixtureGD&)m);
00108         close();
00109         return;
00110     }
00111   }
00112   else if (m.getClassName() == "MixtureGF")
00113   {
00114     switch (format)
00115     {
00116       case MixtureFileWriterFormat_XML:
00117         open(); //can throw IOException
00118         writeMixtureGF_XML((const MixtureGF&)m);
00119         close();
00120         return;
00121       case MixtureFileWriterFormat_RAW:
00122         open(); //can throw IOException
00123         writeMixtureGF_RAW((const MixtureGF&)m);
00124         close();
00125         return;
00126       case MixtureFileWriterFormat_ETAT:
00127         throw Exception("function not implemented", __FILE__, __LINE__);
00128     }
00129   }
00130   
00131   throw Exception("I don't know how to save a " + m.getClassName()
00132                     + " object", __FILE__, __LINE__);
00133 }
00134 //-------------------------------------------------------------------------
00135 void W::writeMixtureGD_XML(const MixtureGD& m)
00136 {
00137   unsigned long i, c, vectSize = m.getVectSize();
00138   writeString("<MixtureGD");
00139   writeAttribute("version", "1");
00140   writeAttribute("id", m.getId());
00141   writeAttribute("distribCount", m.getDistribCount());
00142   writeAttribute("vectSize", vectSize);
00143   writeString(">");
00144 
00145   for (i=0; i< m.getDistribCount(); i++)
00146   {
00147     DistribGD& d = m.getDistrib(i);
00148 
00149     writeString("\n\t<DistribGD");
00150     writeAttribute("i", i);
00151     writeAttribute("weight", m.weight(i));
00152     writeAttribute("cst", d.getCst());
00153     writeAttribute("det", d.getDet());
00154     writeString(">");
00155 
00156     for (c=0; c<vectSize; c++)
00157     {
00158       writeString("\n\t\t<covInv");
00159       writeAttribute("i", c);
00160       writeString(">" + String::valueOf(d.getCovInv(c)) + "</covInv>");
00161     }
00162 
00163     for (c=0; c<vectSize; c++)
00164     {
00165       writeString("\n\t\t<mean");
00166       writeAttribute("i", c);
00167       writeString(">" + String::valueOf(d.getMean(c)) + "</mean>");
00168     }
00169 
00170     writeString("\n\t</DistribGD>");
00171   }
00172   writeString("\n</MixtureGD>");
00173 }
00174 //-------------------------------------------------------------------------
00175 void W::writeMixtureGF_XML(const MixtureGF& m)
00176 {
00177   unsigned long i, c, vectSize = m.getVectSize();
00178   writeString("<MixtureGF");
00179   writeAttribute("version", "1");
00180   writeAttribute("id", m.getId());
00181   writeAttribute("distribCount", m.getDistribCount());
00182   writeAttribute("vectSize", vectSize);
00183   writeString(">");
00184 
00185   for (i=0; i< m.getDistribCount(); i++)
00186   {
00187     DistribGF& d = m.getDistrib(i);
00188 
00189     writeString("\n\t<DistribGF");
00190     writeAttribute("i", i);
00191     writeAttribute("weight", m.weight(i));
00192     writeAttribute("cst", d.getCst());
00193     writeAttribute("det", d.getDet());
00194     writeString(">");
00195 
00196     for (c=0; c<vectSize; c++)
00197       for (unsigned long cc=0; cc<vectSize; cc++)
00198       {
00199         writeString("\n\t\t<covInv");
00200         writeAttribute("i", c);
00201         writeAttribute("j", cc);
00202         writeString(">" + String::valueOf(d.getCovInv(c, cc)) + "</covInv>");
00203       }
00204 
00205     for (c=0; c<vectSize; c++)
00206     {
00207       writeString("\n\t\t<mean");
00208       writeAttribute("i", c);
00209       writeString(">" + String::valueOf(d.getMean(c)) + "</mean>");
00210     }
00211 
00212     writeString("\n\t</DistribGF>");
00213   }
00214   writeString("\n</MixtureGF>");
00215 }
00216 //-------------------------------------------------------------------------
00217 void W::writeMixtureGD_RAW(const MixtureGD& m)
00218 {
00219   unsigned long v, c;
00220   writeUInt4(m.getDistribCount());
00221   writeUInt4(m.getVectSize());
00222   for (c=0; c<m.getDistribCount(); c++)
00223     writeDouble(m.weight(c));
00224   for (c=0; c<m.getDistribCount(); c++)
00225   {
00226     DistribGD& d = m.getDistrib(c);
00227     writeDouble(d.getCst());
00228     writeDouble(d.getDet());
00229     writeChar((char)0); // not used
00230     for (v=0; v<m.getVectSize(); v++)
00231       writeDouble(d.getCovInv(v));
00232 
00233     for (v=0; v<m.getVectSize(); v++)
00234       writeDouble(d.getMean(v));
00235   }
00236 }
00237 //-------------------------------------------------------------------------
00238 void W::writeMixtureGD_ETAT(const MixtureGD& m)
00239 {
00240   writeUInt4(3); // aux = LHM_STATE_FILE = 3
00241   unsigned long i,d, c;
00242   // tag = file name ?
00243   for (i=0; i<_fileName.length() && i<63; i++)
00244     writeString(_fileName[i]);
00245   for (; i<64; i++)
00246     writeChar('\0');
00247   writeUInt4(0); // num = unknown
00248   writeUInt4(0); // nbt = unknown
00249   writeDouble(0.0); // logVrais = unknown
00250   writeUInt4(0); // id = unknown
00251   writeUInt4(m.getDistribCount()); // nb_pdf
00252   for (d=0; d<m.getDistribCount(); d++)
00253     writeDouble(log(m.weight(d)));
00254   for (d=0; d<m.getDistribCount(); d++)
00255   {
00256     writeUInt4(d);
00257     writeShort(0); // type = LHM_GAUSS = 0
00258     writeShort((short)m.getVectSize()); // tpar
00259     DistribGD& dis = m.getDistrib(d);
00260     for (c=0; c<dis.getVectSize(); c++)
00261       writeDouble(dis.getMean(c));
00262     for (c=0; c<dis.getVectSize(); c++)
00263       writeDouble(dis.getCov(c));
00264     writeDouble(-2.0*log(dis.getCst()));
00265   }
00266 }
00267 //-------------------------------------------------------------------------
00268 void W::writeMixtureGF_RAW(const MixtureGF& m)
00269 {
00270   unsigned long v, vv, c, vectSize = m.getVectSize();
00271   writeUInt4(m.getDistribCount());
00272   writeUInt4(m.getVectSize());
00273   for (c=0; c<m.getDistribCount(); c++)
00274   { writeDouble(m.weight(c)); }
00275   for (c=0; c<m.getDistribCount(); c++)
00276   {
00277     DistribGF& d = m.getDistrib(c);
00278     writeDouble(d.getCst());
00279     writeDouble(d.getDet());
00280     writeChar(d.getCovMatrix().size()!=0?(char)1:(char)0);
00281     if (d.getCovMatrix().size()!=0)
00282       for (v=0; v<vectSize; v++)
00283         for (vv=0; vv<vectSize; vv++)
00284           writeDouble(d.getCov(v, vv));
00285     for (v=0; v<vectSize; v++)
00286       for (vv=0; vv<vectSize; vv++)
00287         writeDouble(d.getCovInv(v, vv));
00288 
00289     for (v=0; v<m.getVectSize(); v++)
00290       writeDouble(d.getMean(v));
00291   }
00292 }
00293 //-------------------------------------------------------------------------
00294 String W::getClassName() const { return "MixtureFileWriter"; }
00295 //-------------------------------------------------------------------------
00296 W::~MixtureFileWriter() {}
00297 //-------------------------------------------------------------------------
00298 
00299 #endif // !defined(ALIZE_MixtureFileWriter_cpp)
00300