SegServer.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_SegServer_cpp)
00056 #define ALIZE_SegServer_cpp
00057 
00058 #include <new>
00059 #include "SegServer.h"
00060 #include "Exception.h"
00061 #include "SegServerFileWriter.h"
00062 #include "SegServerFileReaderRaw.h"
00063 #include "Config.h"
00064 
00065 using namespace alize;
00066 
00067 //-------------------------------------------------------------------------
00068 SegServer::SegServer()
00069 :Object(), _nextClusterId(0) {}
00070 //-------------------------------------------------------------------------
00071 SegServer::SegServer(const SegServer& ss)
00072 :Object() { assign(ss); }
00073 //-------------------------------------------------------------------------
00074 const SegServer& SegServer::operator=(const SegServer& ss)
00075 {
00076   assign(ss);
00077   return *this;
00078 }
00079 //-------------------------------------------------------------------------
00080 void SegServer::assign(const SegServer& ss)
00081 {
00082   removeAllSegs();
00083   removeAllClusters();
00084   _map = ss._map;
00085   _nextClusterId = ss._nextClusterId;
00086   _serverName = ss._serverName;
00087   unsigned long i;
00088   for (i=0; i<ss._segVect.size(); i++)
00089   { _segVect.addObject(ss.getSeg(i).duplicate(K::k, *this)); }
00090   for (i=0; i<ss._clusterVect.size(); i++)
00091   {
00092     const SegCluster& cl = ss.getCluster(i);
00093     SegCluster& newCluster = cl.duplicate(K::k, *this);
00094     newCluster.setId(K::k, cl.getId());
00095     _clusterVect.addObject(newCluster);
00096     for (unsigned long j=0; j<cl.getCount(); j++)
00097     { newCluster.add(matchingSegAbstract(cl.get(j))); }
00098   }
00099 }
00100 //-------------------------------------------------------------------------
00101 SegAbstract& SegServer::matchingSegAbstract(const SegAbstract& s) const
00102 {  // private
00103   unsigned long i;
00104   const SegServer& ss = s.getServer();
00105   for (i=0; i<ss.getSegCount(); i++)
00106   {
00107     if (ss.getSeg(i).isSameObject(s))
00108       return getSeg(i);
00109   }
00110   for (i=0; i<ss.getClusterCount(); i++)
00111   {
00112     if (ss.getCluster(i).isSameObject(s))
00113       return getCluster(i);
00114   }
00115   assert(false);
00116   return getSeg(0); // never called
00117 }
00118 //-------------------------------------------------------------------------
00119 void SegServer::assertServerOwns(const SegAbstract& s) const // private
00120 {
00121   if (!s.getServer().isSameObject(*this))
00122     throw Exception("The segment does not belong to the server",
00123           __FILE__, __LINE__);
00124 }
00125 //-------------------------------------------------------------------------
00126 SegServer& SegServer::create() // static
00127 {
00128   SegServer* p = new (std::nothrow) SegServer();
00129   assertMemoryIsAllocated(p, __FILE__, __LINE__);
00130   return *p;
00131 }
00132 //-------------------------------------------------------------------------
00133 Seg& SegServer::createSeg(unsigned long b, unsigned long l,
00134              unsigned long lc, const String& s, const String& sn)
00135 {
00136   Seg& seg = Seg::create(K::k, *this, b, l, lc, s, sn);
00137   _segVect.addObject(seg);
00138   return seg;
00139 }
00140 //-------------------------------------------------------------------------
00141 Seg& SegServer::duplicateSeg(const Seg& s)
00142 {
00143   Seg& seg = s.duplicate(K::k, *this);
00144   _segVect.addObject(seg);
00145   return seg;
00146 }
00147 //-------------------------------------------------------------------------
00148 SegCluster& SegServer::createCluster(unsigned long lc, const String& s,
00149                                                           const String& sn)
00150 {
00151   SegCluster& cluster = SegCluster::create(K::k, *this, lc, s, sn);
00152   while ( getClusterIndexById(_nextClusterId) > 0)
00153     _nextClusterId++;
00154   cluster.setId(K::k, _nextClusterId);
00155   _map[_nextClusterId] = _clusterVect.addObject(cluster);
00156   _nextClusterId++;
00157   return cluster;
00158 }
00159 //-------------------------------------------------------------------------
00160 void SegServer::remove(SegAbstract& s)
00161 {
00162   assertServerOwns(s);
00163   s.removeAllOwners(K::k);
00164   if (dynamic_cast<const Seg*>(&s) != NULL)
00165     _segVect.removeObject(static_cast<Seg&>(s));
00166   else
00167   {
00168     SegCluster& cl = static_cast<SegCluster&>(s);
00169     cl.removeAll();
00170     _clusterVect.removeObject(cl);
00171     _map.erase(cl.getId());
00172   }
00173   delete &s;
00174 }
00175 //-------------------------------------------------------------------------
00176 void SegServer::removeAllSegs()
00177 {
00178   while (getSegCount() != 0)
00179     remove(getSeg(getSegCount()-1));
00180 }
00181 //-------------------------------------------------------------------------
00182 void SegServer::removeAllClusters()
00183 {
00184   while (getClusterCount() != 0)
00185     remove(getCluster(getClusterCount()-1));
00186   _nextClusterId = 0;
00187 }
00188 //-------------------------------------------------------------------------
00189 Seg& SegServer::getSeg(unsigned long idx) const
00190 { return _segVect.getObject(idx); }
00191 //-------------------------------------------------------------------------
00192 unsigned long SegServer::getSegCount() const { return _segVect.size(); }
00193 //-------------------------------------------------------------------------
00194 SegCluster& SegServer::getCluster(unsigned long idx) const
00195 { return _clusterVect.getObject(idx); }
00196 //-------------------------------------------------------------------------
00197 long SegServer::getClusterIndexById(unsigned long id) const
00198 {
00199   it_t i = _map.find(id);
00200   if (i == _map.end())
00201     return -1;
00202   return i->second;
00203 }
00204 //-------------------------------------------------------------------------
00205 void SegServer::setClusterId(SegCluster& cl, unsigned long id)
00206 {
00207   it_t i = _map.find(id);
00208   if (i != _map.end() && !getCluster(i->second).isSameObject(cl))
00209     throw Exception("Cluster with id='" + String::valueOf(id) +
00210           "' already exists in the server", __FILE__, __LINE__);
00211   unsigned long oldId = cl.getId();
00212   unsigned long idx = _map.find(oldId)->second;
00213   _map.erase(oldId);
00214   _map[id] = idx;
00215   cl.setId(K::k, id);
00216 }
00217 //-------------------------------------------------------------------------
00218 SegCluster& SegServer::getClusterById(unsigned long id) const
00219 {
00220   it_t i = _map.find(id);
00221   if (i == _map.end())
00222     throw Exception("Cluster with id='" + String::valueOf(id) +
00223           "' does not exist in the server", __FILE__, __LINE__);
00224   return getCluster(i->second);
00225 }
00226 //-------------------------------------------------------------------------
00227 unsigned long SegServer::getIndex(const SegAbstract& s) const
00228 {
00229   assertServerOwns(s);
00230   if (dynamic_cast<const Seg*>(&s) != NULL)
00231   {
00232     for (unsigned long i=0; i<_segVect.size(); i++)
00233     {
00234       if (_segVect.getObject(i).isSameObject(s))
00235         return i;
00236     }
00237   }
00238   else if (dynamic_cast<const SegCluster*>(&s) != NULL)
00239   {
00240     for (unsigned long i=0; i<_segVect.size(); i++)
00241     {
00242       if (_clusterVect.getObject(i).isSameObject(s))
00243         return i;
00244     }
00245   }
00246   else
00247     throw Exception("Unexpected object", __FILE__, __LINE__);
00248   return 0; // never called
00249 }
00250 //-------------------------------------------------------------------------
00251 unsigned long SegServer::getClusterCount() const
00252 { return _clusterVect.size(); }
00253 //-------------------------------------------------------------------------
00254 void SegServer::setServerName(const String& s) { _serverName = s; }
00255 //-------------------------------------------------------------------------
00256 const String& SegServer::getServerName() const { return _serverName; }
00257 //-------------------------------------------------------------------------
00258 void SegServer::save(const FileName& f, const Config& c) const
00259 { SegServerFileWriter(f, c).writeSegServer(*this); }
00260 //-------------------------------------------------------------------------
00261 void SegServer::load(const FileName& f, const Config& c)
00262 {
00263   if (f.endsWith(".xml"))
00264   {
00265     //SegServerFileReaderXml r(f, c);
00266     //r.readSegServer(*this);
00267     //return;
00268     throw Exception("cannot read XML format for seg server",
00269                           __FILE__, __LINE__);
00270   }
00271   switch (c.getParam_loadSegServerFileFormat())
00272   {
00273     case SegServerFileReaderFormat_XML:
00274     {
00275       //SegServerFileReaderXml r(f, c);
00276       //r.readSegServer(*this);
00277       //break;
00278     }
00279     case SegServerFileReaderFormat_RAW:
00280     {
00281       SegServerFileReaderRaw r(f, c);
00282       r.readSegServer(*this);
00283       break;
00284     }
00285     case SegServerFileReaderFormat_LIUM:
00286     {
00287       //SegServerFileReaderXml r(f, c);
00288       //r.readSegServer(*this);
00289       //break;
00290     }
00291     default:
00292       throw Exception("Unable to read this seg server file format",
00293         __FILE__, __LINE__);
00294   }
00295 }
00296 //-------------------------------------------------------------------------
00297 String SegServer::getClassName() const { return "SegServer"; }
00298 //-------------------------------------------------------------------------
00299 String SegServer::toString() const
00300 {
00301   return Object::toString() + "\n  name = '" + _serverName + "'"
00302     + "\n  seg count = " + String::valueOf(getSegCount())
00303     + "\n  cluster count = " + String::valueOf(getClusterCount());
00304 }
00305 //-------------------------------------------------------------------------
00306 SegServer::~SegServer()
00307 {
00308   removeAllClusters();
00309   removeAllSegs();
00310 }
00311 //-------------------------------------------------------------------------
00312 
00313 #endif // !defined(ALIZE_SegServer_cpp)