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_Hmm_cpp) 00056 #define ALIZE_Hmm_cpp 00057 00058 #include <alize.h> 00059 #include "Hmm.h" 00060 00061 using namespace alize; 00062 using namespace std; 00063 00064 // Class hmm 00065 00066 // -------------------------------------------------------------------------------- 00067 00068 unsigned long hmm::getNbState(){ 00069 return (tabState.size()); 00070 } 00071 00072 // -------------------------------------------------------------------------------- 00073 void hmm::setDensity(String fileName, unsigned long nModel) 00074 { 00075 tabState.setObject(ms->loadMixtureGD(fileName),nModel); 00076 } 00077 00078 // -------------------------------------------------------------------------------- 00079 MixtureGD& hmm::getDensity(unsigned long nModel) 00080 { 00081 return (static_cast<MixtureGD&>(tabState.getObject(nModel))); 00082 } 00083 00084 // -------------------------------------------------------------------------------- 00085 void hmm::setDensity(MixtureGD& m, unsigned long nModel) 00086 { 00087 // A MODIFIER POUR DETRUIRE SI NECESSAIRE LA MIXTURE CREE AUPARAVANT ! 00088 unsigned long temp; 00089 00090 temp=ms->getMixtureIndex(static_cast<MixtureGD&>(tabState.getObject(nModel)).getId()); 00091 ms->deleteMixtures(temp,temp); 00092 ms->deleteUnusedDistribs(); 00093 tabState.setObject(ms->duplicateMixture(m,DUPL_DISTRIB),nModel); 00094 } 00095 00096 00097 //------------------------------------------------------------------------------- 00098 const String &hmm::getStateName(unsigned long nModel){ 00099 return tabStateName.getElement(nModel,false); 00100 } 00101 00102 //------------------------------------------------------------------------------- 00103 void hmm::setStateName(unsigned long nModel, String s){ 00104 tabStateName.getElement(nModel)=s; 00105 } 00106 00107 //-------------------------------------------------------------------------- 00108 unsigned long hmm::LoadState(String fileName) 00109 { 00110 tabState.addObject(ms->loadMixtureGD(fileName)); 00111 tabStateName.addElement(fileName); 00112 transitions.setSize(tabState.size()*tabState.size()); 00113 00114 return (tabState.size()); 00115 } 00116 00117 //-------------------------------------------------------------------------- 00118 unsigned long hmm::LoadState(String fileName,String name) 00119 { 00120 tabState.addObject(ms->loadMixtureGD(fileName)); 00121 tabStateName.addElement(name); 00122 transitions.setSize(tabState.size()*tabState.size()); 00123 00124 return (tabState.size()); 00125 } 00126 00127 00128 //-------------------------------------------------------------------------- 00129 unsigned long hmm::LoadState(MixtureGD& m,String name) 00130 { 00131 tabState.addObject(ms->duplicateMixture(m,DUPL_DISTRIB)); 00132 tabStateName.addElement(name); 00133 transitions.setSize(tabState.size()*tabState.size()); 00134 00135 return (tabState.size()); 00136 } 00137 00138 //-------------------------------------------------------------------------- 00139 unsigned long hmm::addState(String nameState) 00140 { 00141 tabState.addObject(ms->createMixtureGD()); 00142 tabStateName.addElement(nameState); 00143 transitions.setSize(tabState.size()*tabState.size()); 00144 00145 return (tabState.size()); 00146 } 00147 //----------------------------------------------------------------------------------- 00148 double hmm::getTransition(int i,int j){ 00149 return transitions[i+j*tabState.size()]; 00150 00151 } 00152 //----------------------------------------------------------------------------------- 00153 void hmm::getTransition(DoubleVector &tmpTrans){ 00154 00155 tmpTrans.setSize(tabState.size()*tabState.size()); 00156 for(unsigned long i=0;i<tabState.size();i++) 00157 for(unsigned long j=0;j<tabState.size();j++){ 00158 tmpTrans[i+j*tabState.size()]=transitions[i+j*tabState.size()]; 00159 } 00160 } 00161 00162 //------------------------------------------------------------------------------------- 00163 void hmm::setTransition(double a,int i,int j){ 00164 transitions[i+j*tabState.size()]=a; 00165 } 00166 00167 //-------------------------------------------------------------------------------------- 00168 void hmm::reset(void){ 00169 unsigned long temp; 00170 for(unsigned long i=0;i<tabState.size();i++){ 00171 temp=ms->getMixtureIndex(static_cast<MixtureGD&>(tabState.getObject(i)).getId()); 00172 ms->deleteMixtures(temp,temp); 00173 } 00174 ms->deleteUnusedDistribs(); 00175 tabState.clear(); 00176 tabStateName.reset(); 00177 transitions.clear(); 00178 } 00179 //---------------------------------------------------------------------------------- 00180 unsigned long hmm::deleteState(unsigned long indice){ 00181 unsigned long temp; 00182 temp=ms->getMixtureIndex(static_cast<MixtureGD&>(tabState.getObject(indice)).getId()); // TODO, change for the mixture delete function 00183 ms->deleteMixtures(temp,temp); 00184 ms->deleteUnusedDistribs(); 00185 tabState.removeObjects(indice,indice); 00186 tabStateName.deleteElement(tabStateName.getElement(indice)); 00187 transitions.setSize(tabState.size()*tabState.size()); 00188 return temp; // TODO VERIFY THE RETURN VALUE - JFB 00189 } 00190 00191 00192 // -------------------------------------------------------------------------------- 00193 hmm::hmm(MixtureServer & m, Config &config) 00194 :ms(&m),conf(&config) 00195 { 00196 } 00197 //--------------------------------------------------------------------- 00198 const hmm& hmm::operator=(const hmm& hmmc) 00199 { 00200 assign(hmmc); 00201 return *this; 00202 } 00203 //------------------------------------------------------------------------- 00204 void hmm::assign(const hmm& hmmc){ 00205 this->reset(); 00206 ms=hmmc.ms; 00207 conf=hmmc.conf; 00208 tabStateName=hmmc.tabStateName; 00209 //copie des données 00210 transitions=hmmc.transitions; 00211 for(unsigned long i=0;i<hmmc.tabState.size();i++) { 00212 tabState.addObject(ms->duplicateMixtureGD(static_cast<MixtureGD&>( hmmc.tabState.getObject(i)),DUPL_DISTRIB)); 00213 } 00214 } 00215 00216 //----------------------------------------------------------------------- 00217 hmm::~hmm() { } 00218 00219 //------------------------------------------------------------------------- 00220 hmm::hmm(const hmm& h){ 00221 assign(h); 00222 } 00223 //------------------------------------------------------------------------ 00224 void hmm::load() 00225 { 00226 //TO DO 00227 } 00228 00229 //------------------------------------------------------------------------- 00230 void hmm::save() 00231 { 00232 //TO DO 00233 } 00234 00235 00236 // Return a copy of the transition matrix - should be included into hmm class - TODO 00237 /*DoubleVector ©Transition(hmm& cHmm) 00238 { 00239 DoubleVector transitions; 00240 transitions.setSize(cHmm.getNbState()*cHmm.getNbState()); 00241 for(int i=0;i<cHmm.getNbState();i++) 00242 for(int j=0;j<cHmm.getNbState();j++){ 00243 transitions[i+j*cHmm.getNbState()]=cHmm.getTransition(i,j); 00244 } 00245 return transitions; 00246 } 00247 */ 00248 00249 00250 #endif 00251
1.7.2