alizeString.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_String_cpp)
00056 #define ALIZE_String_cpp
00057 
00058 #if defined(_WIN32)
00059 #define _CRT_SECURE_NO_WARNINGS
00060 #endif
00061 
00062 #include <new>
00063 #include <cstring>
00064 #include <iostream>
00065 #include <sstream>
00066 #include <iomanip>
00067 #include "alizeString.h"
00068 #include "Exception.h"
00069 
00070 using namespace alize;
00071 typedef String S;
00072 
00073 //-------------------------------------------------------------------------
00074 S::String(const char* c)
00075 :Object()
00076 {
00077   unsigned long length = (unsigned long)strlen(c);
00078   create(length, length+length+1, c);
00079 }
00080 //-------------------------------------------------------------------------
00081 S::String(const String& s)
00082 :Object()
00083 {
00084   create(s._length, s._length+s._length+1, s._string);
00085 }
00086 //-------------------------------------------------------------------------
00087 S& S::duplicate() const
00088 {
00089   S* p = new (std::nothrow) S(*this);
00090   assertMemoryIsAllocated(p, __FILE__, __LINE__);
00091   return *p;
00092 }
00093 //-------------------------------------------------------------------------
00094 S S::valueOf(unsigned long v)
00095 {
00096   std::ostringstream o;
00097   o << v << std::ends;
00098   return o.str().c_str();
00099 }
00100 //-------------------------------------------------------------------------
00101 S S::valueOf(long v)
00102 {
00103   std::ostringstream o;
00104   o << v << std::ends;
00105   return o.str().c_str();
00106 }
00107 //-------------------------------------------------------------------------
00108 S S::valueOf(double v)
00109 {
00110   std::ostringstream o;
00111   o << std::setprecision(19) << v << std::ends;
00112   return o.str().c_str();
00113 }
00114 //-------------------------------------------------------------------------
00115 S S::valueOf(unsigned int v)
00116 {
00117   std::ostringstream o;
00118   o << v << std::ends;
00119   return o.str().c_str();
00120 }
00121 //-------------------------------------------------------------------------
00122 S S::valueOf(int v)
00123 {
00124   std::ostringstream o;
00125   o << v << std::ends;
00126   return o.str().c_str();
00127 }
00128 //-------------------------------------------------------------------------
00129 S S::valueOf(bool value) { return value?"true":"false"; }
00130 //-------------------------------------------------------------------------
00131 double S::toDouble() const
00132 {
00133   // return atof(_string);
00134   double v;
00135   std::istringstream stream(_string);
00136   stream >> v;
00137   if (stream.fail())
00138     throw Exception("cannot convert '" + *this
00139                     + "' to double float", __FILE__, __LINE__);
00140   return v;
00141 }
00142 //-------------------------------------------------------------------------
00143 bool S::toBool() const
00144 {
00145   if (strcmp(_string, "true") == 0)
00146     return true;
00147   if (strcmp(_string, "false") == 0)
00148     return false;
00149   throw Exception("cannot convert '" + *this
00150                     + "' to boolean", __FILE__, __LINE__);
00151   return true;
00152 }
00153 //-------------------------------------------------------------------------
00154 long S::toLong() const
00155 {
00156   long v;
00157   std::istringstream stream(_string);
00158   stream >> v;
00159   if (stream.fail())
00160     throw Exception("cannot convert '" + *this
00161                     + "' to long integer", __FILE__, __LINE__);
00162   return v;
00163 }
00164 //-------------------------------------------------------------------------
00165 unsigned long S::toULong() const
00166 {
00167   unsigned long v;
00168   std::istringstream stream(_string);
00169   stream >> v;
00170   if (stream.fail())
00171     throw Exception("cannot convert '" + *this
00172                     + "' to unsigned long integer", __FILE__, __LINE__);
00173   return v;
00174 }
00175 //-------------------------------------------------------------------------
00176 const S& S::operator=(const String& s)
00177 {
00178   if (_string != s._string)
00179   {
00180     if (_capacity < s._length+1)
00181     {
00182       delete[] _string;
00183       create(s._length, s._length+s._length+1, s._string);
00184     }
00185     else
00186     {
00187       _length = s._length;
00188       strcpy(_string, s._string);
00189     }
00190   }
00191   assert(_length == s._length);
00192   return *this;
00193 }
00194 //-------------------------------------------------------------------------
00195 const S& S::operator=(const char* s)
00196 {
00197   unsigned long len = (unsigned long)strlen(s);
00198   if (_string != s)
00199   {
00200     if (_capacity < len+1)
00201     {
00202       delete[] _string;
00203       create(len, len+len+1, s);
00204     }
00205     else
00206     {
00207       _length = len;
00208       strcpy(_string, s);
00209     }
00210   }
00211   assert(_length == len);
00212   return *this;
00213 }
00214 //-------------------------------------------------------------------------
00215 S& S::operator+=(const String& s)
00216 {
00217   char* oldString = _string;
00218   unsigned long newLength = _length+s._length;
00219   if (_capacity < newLength+1)
00220   {
00221     create(newLength, newLength+newLength+1, oldString);
00222     delete [] oldString;
00223   }
00224   strcat(_string, s._string);
00225   _length = newLength;
00226   return *this;
00227 }
00228 //-------------------------------------------------------------------------
00229 S& S::operator+=(const char* s)
00230 {
00231   char* oldString = _string;
00232   unsigned long newLength = _length+strlen(s);
00233   if (_capacity < newLength+1)
00234   {
00235     create(newLength, newLength+newLength+1, oldString);
00236     delete [] oldString;
00237   }
00238   strcat(_string, s);
00239   _length = newLength;
00240   return *this;
00241 }
00242 //-------------------------------------------------------------------------
00243 S S::operator+(const String& s) const
00244 {
00245   String x(*this);
00246   x += s;
00247   return x;
00248 }
00249 //-------------------------------------------------------------------------
00250 S S::operator+(const char* s) const
00251 {
00252   String x(*this);
00253   x += s;
00254   return x;
00255 }
00256 //-------------------------------------------------------------------------
00257 bool S::operator==(const String& s) const
00258 {
00259   return strcmp(_string, s._string) == 0;
00260 }
00261 //-------------------------------------------------------------------------
00262 bool S::operator!=(const String& s) const
00263 {
00264   return strcmp(_string, s._string) != 0;
00265 }
00266 //-------------------------------------------------------------------------
00267 bool S::operator==(const char* s) const
00268 {
00269   return strcmp(_string, s) == 0;
00270 }
00271 //-------------------------------------------------------------------------
00272 bool S::operator!=(const char* s) const
00273 {
00274   return strcmp(_string, s) != 0;
00275 }
00276 //-------------------------------------------------------------------------
00277 bool S::operator<(const String& s) const
00278 {
00279   return strcmp(_string, s._string) < 0;
00280 }
00281 //-------------------------------------------------------------------------
00282 bool S::operator<=(const String& s) const
00283 {
00284   return strcmp(_string, s._string) <= 0;
00285 }
00286 //-------------------------------------------------------------------------
00287 bool S::operator>(const String& s) const
00288 {
00289   return strcmp(_string, s._string) > 0;
00290 }
00291 //-------------------------------------------------------------------------
00292 bool S::operator>=(const String& s) const
00293 {
00294   return strcmp(_string, s._string) >= 0;
00295 }
00296 //-------------------------------------------------------------------------
00297 unsigned long String::length() const { return _length; }
00298 //-------------------------------------------------------------------------
00299 S S::operator[](unsigned long index) const
00300 {
00301   if (index >= _length)
00302     return "";
00303   char oneChar[] = {0, 0};
00304   oneChar[0] = _string[index];
00305   return oneChar;
00306 }
00307 //-------------------------------------------------------------------------
00308 void S::reset() { _length = 0; _string[0] = 0; }
00309 //-------------------------------------------------------------------------
00310 bool S::isEmpty() const { return _length == 0; }
00311 //-------------------------------------------------------------------------
00312 bool S::endsWith(const String& s) const
00313                      
00314 {
00315   if (s._length == 0)
00316     return true;
00317   if (_length < s._length)
00318     return false;
00319   return strncmp(_string+(_length - s._length), s._string, s._length) == 0;
00320   
00321 }
00322 //-------------------------------------------------------------------------
00323 bool S::beginsWith(const String& s) const
00324                      
00325 {
00326   if (s._length == 0)
00327     return true;
00328   if (_length < s._length)
00329     return false;
00330   return strncmp(_string, s._string, s._length) == 0;
00331   
00332 }
00333 //-------------------------------------------------------------------------
00334 long S::find(const String& s, unsigned long start) const
00335                      
00336 {
00337   if (s._length == 0)
00338     return -1;
00339   unsigned long i;
00340   for (; start+s._length<=_length; start++)
00341   {
00342     for (i=0; i<s._length; i++)
00343     {
00344       if (_string[start+i] != s._string[i])
00345         break;
00346     }
00347     if (i == s._length)
00348       return start;
00349   }
00350   return -1;
00351 }
00352 //-------------------------------------------------------------------------
00353 S S::getToken(unsigned long index, const String& separator) const
00354 {
00355   if (separator.length() != 1)
00356     throw Exception("separator length must be 1", __FILE__, __LINE__);
00357   char sep = *separator.c_str();
00358 
00359   S s;
00360   long tokenCount = 0;
00361   long start = -1;
00362   long end = -1;
00363   long i;
00364   char previous = sep;
00365   long l = length();
00366   for (i=0; i<l; i++)
00367   {
00368     if ( (sep == ' ' && _string[i] != ' ' && _string[i] != '\t') ||
00369          (sep != ' ' && _string[i] != sep) )
00370     {
00371       if ( (sep == ' ' && (previous == ' ' || previous == '\t')) ||
00372            (sep != ' ' && previous == sep) )
00373       {
00374         tokenCount++;
00375         start = i;
00376         previous = '\1';
00377       }
00378     }
00379     else
00380     {
00381       if ( (sep == ' ' && previous != ' ' && previous != '\t') ||
00382            (sep != ' ' && previous != sep) )
00383       {
00384         end = i-1;
00385         previous = sep;
00386         if (tokenCount == (long)index+1)
00387           break;
00388         start = -1;
00389         end = -1;
00390       }
00391     }
00392   }
00393   if ( (sep == ' ' && previous != ' ' && previous != '\t') ||
00394     (sep != ' ' && previous != sep) )
00395     end = i-1;
00396   if (tokenCount != (long)index+1)
00397   {
00398     start = -1;
00399     end = -1;
00400   }
00401   
00402   if (start != -1)
00403   {
00404     char* string = new (std::nothrow) char[end-start+2];
00405     assertMemoryIsAllocated(string, __FILE__, __LINE__);
00406     for (i=start; i<=end; i++)
00407     { string[i-start]=_string[i]; }
00408     string[end-start+1] = 0;
00409     s = string;
00410     delete [] string;
00411   }
00412   return s;
00413 }
00414 //-------------------------------------------------------------------------
00415 const char* String::c_str() const { return _string; }
00416 //-------------------------------------------------------------------------
00417 S S::getClassName() const { return "String"; }
00418 //-------------------------------------------------------------------------
00419 S S::toString() const
00420 {
00421   return Object::toString() + "  '" + _string;
00422 }
00423 //-------------------------------------------------------------------------
00424 void S::create(unsigned long length, unsigned long capacity,
00425                               const char* c)
00426 {
00427   _length = length;
00428   _capacity = capacity<length+1?length+1:capacity;
00429   _string = new (std::nothrow) char[_capacity];
00430   assertMemoryIsAllocated(_string, __FILE__, __LINE__);
00431   strcpy(_string, c);
00432 }
00433 //-------------------------------------------------------------------------
00434 S::~String()
00435 {
00436   assert(_string != NULL);
00437   delete[] _string;
00438 }
00439 //-------------------------------------------------------------------------
00440 
00441 // global functions
00442 
00443 //-------------------------------------------------------------------------
00444 ALIZE_API S operator+(const char* c, const String& s)
00445 {
00446   String x(c);
00447   x += s;
00448   return x;
00449 }
00450 //-------------------------------------------------------------------------
00451 ALIZE_API std::ostream& operator<<(std::ostream& o, const S& s)
00452 {
00453   return o << s.c_str();
00454 }
00455 //-------------------------------------------------------------------------
00456 
00457 #endif // !defined(ALIZE_String_cpp)