vpcompare.cpp

This example shows how to use the SVoicePrintComparatorI interface for speaker identification.

00001 /*****************************************************************
00002  *  BSAPI Voice-print Comparator Example                         *
00003  *                                                               *
00004  *  Author      : Petr Schwarz, Pavel Matejka, Tomas Cipr        *
00005  *  Copyright   : (C) 2006-2012 by Phonexia s.r.o                *
00006  *                                                               *
00007  *  For more info, please contact us at support@phonexia.com     *
00008  *****************************************************************/
00009 
00010 #include <stdio.h>
00011 #include <stdlib.h>
00012 #include <stdarg.h>
00013 #include <string.h>
00014 #include <assert.h>
00015 #include <float.h>
00016 #include <errno.h>
00017 #include <math.h>
00018 #include <locale.h>
00019 
00020 #include <vector>
00021 #include <algorithm>
00022 
00023 #include "bsapi.h"
00024 #include "getopt.h"
00025 
00026 #ifdef WIN32
00027   #define DIRSEP "\\"
00028 #else
00029   #define DIRSEP "/"
00030 #endif
00031 
00032 // compile time program options
00033 #define SID_LOCALE                "C"             // use "" for environment's default locale
00034 #define SID_MIN_LEN_TO_PROCESS    3.0f            // in seconds
00035 #define SID_BELOW_MIN_LEN_TEXT    "(too short)"
00036 #define SID_OUT_COLUMN_CHARS      "snkl"
00037 
00038 // default option values
00039 #define SID_DEF_VPRINT_EXT        "vp"
00040 #define SID_DEF_SCORE_SHARPNESS   1.0f
00041 #define SID_DEF_ADAPT_CONST       1.0f
00042 
00043 inline float GetSpeechLengthSec(SVoicePrintI *pVoicePrint)
00044 {
00045   return pVoicePrint->GetNFrames() / 100.0f;
00046 }
00047 
00048 inline bool IsTooShort(SVoicePrintI *pVoicePrint)
00049 {
00050   return (GetSpeechLengthSec(pVoicePrint) < SID_MIN_LEN_TO_PROCESS);
00051 }
00052 
00053 inline float RescaleScore(float score, float scale = 1.0f)
00054 {
00055   return (100.0f / (1.0f + expf(-(scale * score))));
00056 }
00057 
00058 // This is an error handling object. If an error occurs, a message is sent to this object at first.
00059 // Then the running function will exit with the false or 0 return value. The object also accepts
00060 // warning and logging messages.
00061 class ErrorHandler : public SErrorCallbackI 
00062 {
00063   public:
00064     ErrorHandler() : mVerbose(false) {;}
00065     virtual void BSAPI_METHOD OnTextMessage(SUnknownI *pSender, message_type type, unsigned int messageId, const char *pMessage)
00066     {
00067       unsigned int iid = pSender ? pSender->GetIID() : SIID_UNDEFINED;
00068       switch(type)
00069       {
00070         case mtError:
00071           fprintf(stderr, "ERROR: %s - %s\n", BSAPIInterfaceId2Text(iid), pMessage);
00072           break;
00073         case mtWarning:
00074           fprintf(stderr, "WARNING: %s - %s\n", BSAPIInterfaceId2Text(iid), pMessage);
00075           break;
00076         case mtLog:
00077           LogMessage(pMessage);
00078           break;
00079       }
00080     }
00081 
00082     void LogMessage(const char *pMessage, ...)
00083     {
00084       if (mVerbose)
00085       {
00086         va_list ap;
00087         va_start(ap, pMessage);
00088         vfprintf(stderr, pMessage, ap);
00089         fprintf(stderr, "\n");
00090         va_end(ap);
00091       }
00092     }
00093 
00094     void SetVerbose(bool verbose) {mVerbose = verbose;}
00095 
00096   protected:
00097     bool mVerbose;
00098 } gErrorHandler;
00099 
00100 class ScoreSorter
00101 {
00102   public:
00103     ScoreSorter() : mpScores(0), mpSet(0), mSuppressTooShort(false) {}
00104 
00105     void SetScores(float *pScores, size_t length)
00106     {
00107       mpScores = pScores;
00108 
00109       mIndices.resize(length);
00110       for (size_t i = 0; i < mIndices.size(); i++)
00111         mIndices[i] = i;
00112     }
00113 
00114     void SetVoicePrints(SVoicePrintSetI *pSet, bool suppressTooShort)
00115     {
00116       mpSet = pSet;
00117       mSuppressTooShort = suppressTooShort;
00118     }
00119 
00120     void Sort()
00121     {
00122       sort(mIndices.begin(), mIndices.end(), *this);
00123     }
00124 
00125     int GetIndex(int nthBest) const
00126     {
00127       return mIndices[nthBest];
00128     }
00129 
00130     bool operator() (int i, int j)
00131     {
00132       assert(mpScores != 0 && mpSet != 0);
00133       float score1 = (IsTooShort(mpSet->GetByIndex(i)) && !mSuppressTooShort) ? -FLT_MAX : mpScores[i];
00134       float score2 = (IsTooShort(mpSet->GetByIndex(j)) && !mSuppressTooShort) ? -FLT_MAX : mpScores[j];
00135       return (score1 > score2);
00136     }
00137 
00138   private:
00139     std::vector<int> mIndices;
00140     float *mpScores;
00141     SVoicePrintSetI *mpSet;
00142     bool mSuppressTooShort;
00143 };
00144 
00145 void help()
00146 {
00147   puts("\n Voice-print comparator                                              ");
00148   printf(" %s\n", BSAPIVersion());
00149   puts(" ===================================================================== ");
00150   puts("                                                                       ");
00151   puts(" USAGE: vpcompare [options] input1 [input2]                            ");
00152   puts("                                                                       ");
00153   puts(" system configuration:                                                 ");
00154   puts("   -c file            configuration file                               ");
00155   puts("   -m dir             model directory                                  ");
00156   puts("   -v                 verbose mode                                     ");
00157   puts("                                                                       ");
00158   puts(" comparison mode:                                                      ");
00159   puts("   input:                                                              ");
00160   puts("     -f               compare two voice-print files                    ");
00161   puts("     -l               compare two lists of voice-print files           ");
00162   puts("     -d               compare two directories of voice-print files     ");
00163   puts("     -e str [vp]      extension of voice-print file                    ");
00164   puts("                                                                       ");
00165   puts("   output:                                                             ");
00166   puts("     -o file          output score file                                ");
00167   puts("     -n               dump voice-print file names to the score file    ");
00168   puts("     -u               suppress the 'too short' output                  ");
00169   puts("     -k columns       enable column output format (see columns)        ");
00170   puts("     -b num           for each voice-print from input1 dump only N     ");
00171   puts("                      best scores from input2                          ");
00172   puts("     -t num           for each voice-print from input1 dump only scores");
00173   puts("                      from input2 which are greater than threshold     ");
00174   puts("     -z num [1.0]     score sharpness (positive number)                ");
00175   puts("                                                                       ");
00176   puts("   columns:           (columns to print are specified by string of     ");
00177   puts("                       the characters below, e.g. lsn)                 ");
00178   puts("      s               raw score                                        ");
00179   puts("      n               score normalized to <0, 100>                     ");
00180   puts("      k               speech length of input1 voice-print              ");
00181   puts("      l               speech length of input2 voice-print              ");
00182   puts("                                                                       ");
00183   puts(" training mode (enabled by option -g):                                 ");
00184   puts("     -x               use counts (of voice-prints) for adaptation      ");
00185   puts("     -a num [1.0]     adaptation constant <0.0, 1.0>                   ");
00186   puts("                      0.0 ... old models are used only                 ");
00187   puts("                      1.0 ... new models are used only                 ");
00188   puts("   input:                                                              ");
00189   puts("     -l               train from two-column list file; speaker name in ");
00190   puts("                      first column, voice-print file in second column  ");
00191   puts("     -d               train from directory with subdirectories each    ");
00192   puts("                      corresponding to a single speaker                ");
00193   puts("     -e str [vp]      extension of voice-print file                    ");
00194   puts("                                                                       ");
00195   puts("   output:                                                             ");
00196   puts("     -g dir           output model directory                           ");
00197   puts("                                                                       ");
00198   puts(" example:                                                              ");
00199   puts("   vpcompare -c settings/compare -f file1.vp file2.vp                  ");
00200   puts("   vpcompare -c settings/compare -l -o score.txt list1.txt list2.txt   ");
00201   puts("   vpcompare -c settings/compare -d -e 'vp' -o score.txt dir1 dir2     ");
00202   puts("   vpcompare -c settings/compare -d -e 'vp' -g models dir1             ");
00203   puts("                                                                       ");
00204 }
00205 
00206 void DumpColWiseLine(FILE *pFileHandle, float score, SVoicePrintI *pVoicePrint1, SVoicePrintI *pVoicePrint2,
00207   const char *pColumnFmt, float sharpness, bool suppressTooShort)
00208 {
00209   fprintf(pFileHandle, "%s\t%s", pVoicePrint1->GetSegmentId(), pVoicePrint2->GetSegmentId());
00210   for (const char *pc = pColumnFmt; *pc != '\0'; pc++)
00211   {
00212     switch (*pc)
00213     {
00214       case 's':
00215         if ((IsTooShort(pVoicePrint1) || IsTooShort(pVoicePrint2)) && !suppressTooShort)
00216           fprintf(pFileHandle, "\t-inf");
00217         else
00218           fprintf(pFileHandle, "\t%.3f", score);
00219         break;
00220 
00221       case 'n':
00222         if ((IsTooShort(pVoicePrint1) || IsTooShort(pVoicePrint2)) && !suppressTooShort)
00223           fprintf(pFileHandle, "\t0.000");
00224         else
00225           fprintf(pFileHandle, "\t%.3f", RescaleScore(score, sharpness));
00226         break;
00227 
00228       case 'k':
00229         fprintf(pFileHandle, "\t%.3f", GetSpeechLengthSec(pVoicePrint1));
00230         break;
00231 
00232       case 'l':
00233         fprintf(pFileHandle, "\t%.3f", GetSpeechLengthSec(pVoicePrint2));
00234         break;
00235     }
00236   }
00237 
00238   if ((IsTooShort(pVoicePrint1) || IsTooShort(pVoicePrint2)) && !suppressTooShort)
00239     fprintf(pFileHandle, "\t%s", SID_BELOW_MIN_LEN_TEXT);
00240 
00241   fprintf(pFileHandle, "\n");
00242 }
00243 
00244 void DumpColWiseNBest(FILE *pFileHandle, SFloatMatrixI *pScores, SVoicePrintSetI *pSet1, SVoicePrintSetI *pSet2,
00245   const char *pColumnFmt, float sharpness, bool suppressTooShort, int nBest)
00246 {
00247   ScoreSorter score_sorter;
00248 
00249   for (int i = 0; i < pSet1->GetNVoicePrints(); i++)
00250   {
00251     int nscores = pScores->GetNColumns();
00252     float *pscores = pScores->GetRowMem(i);
00253     score_sorter.SetScores(pscores, nscores);
00254     score_sorter.SetVoicePrints(pSet2, suppressTooShort);
00255     score_sorter.Sort();
00256     SVoicePrintI *pvoice_print1 = pSet1->GetByIndex(i);
00257     for (int j = 0; j < std::min(nBest, nscores); j++)
00258     {
00259       int index = score_sorter.GetIndex(j);
00260       DumpColWiseLine(pFileHandle, pscores[index], pvoice_print1, pSet2->GetByIndex(index),
00261                       pColumnFmt, sharpness, suppressTooShort);
00262     }
00263   }
00264 }
00265 
00266 void DumpColWiseBest(FILE *pFileHandle, SFloatMatrixI *pScores, SVoicePrintSetI *pSet1, SVoicePrintSetI *pSet2,
00267   const char *pColumnFmt, float sharpness, bool suppressTooShort)
00268 {
00269   for (int i = 0; i < pSet1->GetNVoicePrints(); i++)
00270   {
00271     assert(pSet2->GetNVoicePrints() > 0);
00272 
00273     float best_score = -FLT_MAX;
00274     SVoicePrintI *pbest_vprint = 0;
00275     float *pscores = pScores->GetRowMem(i);
00276     for (int j = 0; j < pSet2->GetNVoicePrints(); j++)
00277     {
00278       if ((pscores[j] > best_score) && 
00279           ((!IsTooShort(pSet1->GetByIndex(i)) && !IsTooShort(pSet2->GetByIndex(j))) || suppressTooShort))
00280       {
00281         best_score = pScores->Get(i, j);
00282         pbest_vprint = pSet2->GetByIndex(j);
00283       }
00284     }
00285 
00286     DumpColWiseLine(pFileHandle, best_score, pSet1->GetByIndex(i), pbest_vprint ? pbest_vprint : pSet2->GetByIndex(0),
00287                     pColumnFmt, sharpness, suppressTooShort);
00288   }
00289 }
00290 
00291 void DumpColWiseThr(FILE *pFileHandle, SFloatMatrixI *pScores, SVoicePrintSetI *pSet1, SVoicePrintSetI *pSet2,
00292   const char *pColumnFmt, float sharpness, bool suppressTooShort, float scoreThreshold)
00293 {
00294   for (int i = 0; i < pSet1->GetNVoicePrints(); i++)
00295   {
00296     float *pscores = pScores->GetRowMem(i);
00297     SVoicePrintI *pvoice_print1 = pSet1->GetByIndex(i);
00298     for (int j = 0; j < pSet2->GetNVoicePrints(); j++)
00299     {
00300       if ((RescaleScore(pscores[j], sharpness) >= scoreThreshold) && 
00301           ((!IsTooShort(pvoice_print1) && !IsTooShort(pSet2->GetByIndex(j))) || suppressTooShort))
00302       {
00303         DumpColWiseLine(pFileHandle, pscores[j], pvoice_print1, pSet2->GetByIndex(j),
00304                         pColumnFmt, sharpness, suppressTooShort);
00305       }
00306     }
00307   }
00308 }
00309 
00310 void DumpColWise(FILE *pFileHandle, SFloatMatrixI *pScores, SVoicePrintSetI *pSet1, SVoicePrintSetI *pSet2,
00311   const char *pColumnFmt, float sharpness, bool suppressTooShort)
00312 {
00313   for (int i = 0; i < pSet1->GetNVoicePrints(); i++)
00314   {
00315     float *pscores = pScores->GetRowMem(i);
00316     SVoicePrintI *pvoice_print1 = pSet1->GetByIndex(i);
00317     for (int j = 0; j < pSet2->GetNVoicePrints(); j++)
00318     {
00319       DumpColWiseLine(pFileHandle, pscores[j], pvoice_print1, pSet2->GetByIndex(j),
00320                       pColumnFmt, sharpness, suppressTooShort);
00321     }
00322   }
00323 }
00324 
00325 void DumpRowWise(FILE *pFileHandle, SFloatMatrixI *pScores, SVoicePrintSetI *pSet1, SVoicePrintSetI *pSet2, 
00326   bool dumpNames, bool suppressTooShort)
00327 {
00328   if(dumpNames)
00329   {
00330     for(int i = 0; i < pSet2->GetNVoicePrints(); i++)
00331       fprintf(pFileHandle, "\t%s", pSet2->GetByIndex(i)->GetSegmentId());
00332     fprintf(pFileHandle, "\n");
00333   }
00334 
00335   bool too_short2 = false;
00336   float *prow = pScores->GetMem();
00337   for(int i = 0; i < pSet1->GetNVoicePrints(); i++)
00338   {
00339     if(dumpNames)
00340       fprintf(pFileHandle, "%s\t", pSet1->GetByIndex(i)->GetSegmentId());
00341     for(int j = 0; j < pSet2->GetNVoicePrints(); j++)
00342     {
00343       if(IsTooShort(pSet2->GetByIndex(j)))
00344         too_short2 = true;
00345       if(j != 0)
00346         fprintf(pFileHandle, "\t");
00347       if((IsTooShort(pSet1->GetByIndex(i)) || IsTooShort(pSet2->GetByIndex(j))) && !suppressTooShort)
00348         fprintf(pFileHandle, "-inf");
00349       else
00350         fprintf(pFileHandle, "%e", prow[j]);
00351     }
00352     if (IsTooShort(pSet1->GetByIndex(i)) && !suppressTooShort)
00353       fprintf(pFileHandle, "\t%s", SID_BELOW_MIN_LEN_TEXT);
00354     fprintf(pFileHandle, "\n");
00355     prow += pScores->GetStride();
00356   }
00357 
00358   if(too_short2 && !suppressTooShort)
00359   {
00360     if(dumpNames)
00361       fprintf(pFileHandle, "\t");
00362     for(int i = 0; i < pSet2->GetNVoicePrints(); i++)
00363     {
00364       if(i != 0)
00365         fprintf(pFileHandle, "\t");
00366       if(IsTooShort(pSet2->GetByIndex(i)))
00367         fprintf(pFileHandle, "%s", SID_BELOW_MIN_LEN_TEXT);
00368     }
00369     fprintf(pFileHandle, "\n");
00370   }
00371 }
00372 
00373 bool SaveScores(const char *pFile, SFloatMatrixI *pScores, SVoicePrintSetI *pSet1, SVoicePrintSetI *pSet2,
00374   const char *pColumnFmt, float sharpness, int nBestScores, float scoreThreshold, bool dumpNames, bool suppressTooShort)
00375 {
00376   assert(pScores->GetNRows() == pSet1->GetNVoicePrints() && pScores->GetNColumns() == pSet2->GetNVoicePrints());
00377 
00378   setlocale(LC_ALL, SID_LOCALE);
00379 
00380   FILE *pf = fopen(pFile, "w");
00381   if (!pf)
00382   {
00383     fprintf(stderr, "ERROR: Can not create '%s'.\n", pFile);
00384     return false;
00385   }
00386 
00387   switch (nBestScores)
00388   {
00389     case 0:
00390       if (scoreThreshold > 0.0f)
00391         DumpColWiseThr(pf, pScores, pSet1, pSet2, (pColumnFmt ? pColumnFmt : "n"), sharpness, suppressTooShort, scoreThreshold);
00392       else if (pColumnFmt)
00393         DumpColWise(pf, pScores, pSet1, pSet2, pColumnFmt, sharpness, suppressTooShort);
00394       else
00395         DumpRowWise(pf, pScores, pSet1, pSet2, dumpNames, suppressTooShort);
00396       break;
00397 
00398     case 1:
00399       DumpColWiseBest(pf, pScores, pSet1, pSet2, (pColumnFmt ? pColumnFmt : "n"), sharpness, suppressTooShort);
00400       break;
00401 
00402     default:
00403       DumpColWiseNBest(pf, pScores, pSet1, pSet2, (pColumnFmt ? pColumnFmt : "n"), sharpness, suppressTooShort, nBestScores);
00404       break;
00405   }
00406 
00407   fclose(pf);
00408   return true;
00409 }
00410 
00411 int main(int argc, char *argv[])
00412 {
00413   // initial configuration variables
00414   const char *pconfig_file = "settings/compare.bs";
00415   const char *pinput1      = 0;
00416   const char *pinput2      = 0;
00417   const char *pvprint_ext  = SID_DEF_VPRINT_EXT;
00418   const char *poutput_file = 0;
00419   const char *pcolumn_fmt  = 0;
00420   const char *pmodel_dir   = 0;
00421   const char *pout_model_dir = 0;
00422   bool process_files   = false;
00423   bool process_lists   = false;
00424   bool process_dirs    = false;
00425   int  nbest_scores    = 0;
00426   float score_thr      = 0.0f;
00427   bool dump_names      = false;
00428   bool supp_too_short  = false;
00429   float sharpness      = SID_DEF_SCORE_SHARPNESS;
00430   float adapt_const    = SID_DEF_ADAPT_CONST;
00431   bool use_counts      = false;
00432 
00433   // command line parsing
00434   if(argc == 1)
00435   {
00436     help();
00437     return 0;
00438   }
00439 
00440   optind = 0;
00441   while (1)
00442   {
00443     int c = getopt(argc, argv, const_cast<char *>("c:uvflde:o:nk:t:z:b:m:g:a:x"));
00444     if(c == -1)
00445       break;
00446 
00447     switch(c)
00448     {
00449       case 'c':
00450         pconfig_file = optarg;
00451         break;
00452       case 'm':
00453         pmodel_dir = optarg;
00454         break;
00455       case 'g':
00456         pout_model_dir = optarg;
00457         break;
00458       case 'o':
00459         poutput_file = optarg;
00460         break;
00461       case 'l':
00462         process_lists = true;
00463         break;
00464       case 'd':
00465         process_dirs = true;
00466         break;
00467       case 'f':
00468         process_files = true;
00469         break;
00470       case 'e':
00471         pvprint_ext = optarg;
00472         break;
00473       case 'n':
00474         dump_names = true;
00475         break;
00476       case 'u':
00477         supp_too_short = true;
00478         break;
00479       case 'x':
00480         use_counts = true;
00481         break;
00482       case 'b':
00483         if(sscanf(optarg, "%d", &nbest_scores) != 1 || nbest_scores < 0)
00484         {
00485           fprintf(stderr, "ERROR: Invalid number of best scores to print '%s'. "
00486                           "Must be positive integer.\n", optarg);
00487           return 1;
00488         }
00489         break;
00490       case 't':
00491         if(sscanf(optarg, "%f", &score_thr) != 1 || score_thr < 0.0f || score_thr > 100.0f)
00492         {
00493           fprintf(stderr, "ERROR: Wrong value of score threshold '%s'. Must be number in <0,100>.\n", optarg);
00494           return 1;
00495         }
00496         break;
00497       case 'k':
00498         pcolumn_fmt = optarg;
00499         if (strspn(pcolumn_fmt, SID_OUT_COLUMN_CHARS) != strlen(pcolumn_fmt))
00500         {
00501           fprintf(stderr, "ERROR: Wrong format of output columns string. "
00502           "The set of allowed characters is '%s'.\n", SID_OUT_COLUMN_CHARS);
00503           return 1;
00504         }
00505         break;
00506       case 'z':
00507         if(sscanf(optarg, "%f", &sharpness) != 1 || sharpness < 0.0f)
00508         {
00509           fprintf(stderr, "ERROR: Wrong value of score sharpness '%s'. Must be positive number.\n", optarg);
00510           return 1;
00511         }
00512         break;
00513       case 'a':
00514         if(sscanf(optarg, "%f", &adapt_const) != 1 || adapt_const < 0.0f || adapt_const > 1.0f)
00515         {
00516           fprintf(stderr, "ERROR: Wrong value of adaptation constant '%s'. Must be number in <0.0, 1.0>.\n", optarg);
00517           return 1;
00518         }
00519         break;
00520       case 'v':
00521         gErrorHandler.SetVerbose(true);
00522         break;
00523       case 1: // non-option arguments
00524         if(!pinput1)
00525         {
00526           pinput1 = optarg;
00527         }
00528         else if(!pinput2)
00529         {
00530           pinput2 = optarg;
00531         }
00532         else
00533         {
00534           fprintf(stderr, "ERROR: Only two files, lists or directories can be compared at the same time.\n");
00535           return 1;
00536         }
00537         break;
00538       case '?':
00539         fprintf(stderr, "ERROR: Command line parsing error.\n");
00540         return 1;
00541       default :
00542         fprintf(stderr, "ERROR: Command line parsing error. Unexpected argument '%s'.\n", optarg);
00543         return 1;
00544     }
00545   }
00546 
00547 
00548   if((process_files && process_dirs) || (process_files && process_lists) || (process_lists && process_dirs))
00549   {
00550     fprintf(stderr, "ERROR: Only one of -f, -l, -d options can be used at the same time.\n");
00551     return 1;
00552   }
00553 
00554   if(!pinput1 || (!pout_model_dir && !pinput2))
00555   {
00556     fprintf(stderr, "ERROR: Missing input. Two inputs should be specified for comparison mode and one input for training mode.\n");
00557     return 1;
00558   }
00559 
00560   if(!process_dirs && !process_lists && pout_model_dir)
00561   {
00562     fprintf(stderr, "ERROR: Training is enabled but not the input list file nor the input directory is set.\n");
00563     return 1;
00564   }
00565 
00566   if(!process_files && !process_dirs && !process_lists)
00567     process_files = true;
00568 
00569   // register license file for SSpeakerIDI
00570   SLicenseManagerI *plicman = BSAPIGetLicenseManager();
00571   if (plicman)
00572   {
00573     plicman->SetErrorHandler(&gErrorHandler);
00574     plicman->RegisterLicenseFile("license.dat");
00575   }
00576 
00577   // ask for an instance of voice-print extractor
00578   SVoicePrintComparatorI *pvp_compare = static_cast<SVoicePrintComparatorI *>(BSAPICreateInstance(SIID_VPRINTCOMPARATOR));
00579   if(!pvp_compare)
00580   {
00581     return 1;
00582   }
00583 
00584   // tell the instance where to send error messages
00585   pvp_compare->SetErrorHandler(&gErrorHandler);
00586 
00587   // read configuration file and configure the instance
00588   char pdefault_cfg[1024];
00589   sprintf(pdefault_cfg, "settings%sconfig", DIRSEP);  // Visual C does not have snprintf
00590   if(!pvp_compare->Init((pconfig_file ? pconfig_file : pdefault_cfg)))
00591   {
00592     pvp_compare->Release();
00593     return 1;
00594   }
00595 
00596   if(pmodel_dir)
00597     pvp_compare->SetModelDirectory(pmodel_dir);
00598 
00599   if(pout_model_dir)
00600   {
00601     // training mode
00602     pvp_compare->SetOutputModelDirectory(pout_model_dir);
00603 
00604     STwoSetComparisonI *pcomparer = pvp_compare->GetTwoSetComparator();
00605     if(!pcomparer)
00606     {
00607       pvp_compare->Release();
00608       return 1;
00609     }
00610 
00611     if(pcomparer->GetIID() == SIID_TWOCOVMODEL)
00612     {
00613       STwoCovarianceModelI *ptwo_cov_model = static_cast<STwoCovarianceModelI *>(pcomparer);
00614       ptwo_cov_model->SetAdaptConst(adapt_const);
00615       ptwo_cov_model->SetUseCounts(use_counts);
00616     }
00617 
00618     if(process_lists)
00619     {
00620       assert(pinput1);
00621       if (!pvp_compare->TrainFromList(pinput1))
00622       {
00623         pvp_compare->Release();
00624         return 1;
00625       }
00626     }
00627     else
00628     {
00629       assert(process_dirs && pinput1);
00630       if (!pvp_compare->TrainFromDirectory(pinput1, pvprint_ext))
00631       {
00632         pvp_compare->Release();
00633         return 1;
00634       }
00635     }
00636   }
00637   else
00638   {
00639     // comparison mode
00640     SFloatMatrixI *pscores = static_cast<SFloatMatrixI *>(BSAPICreateInstance(SIID_FLOATMATRIX));
00641     if(!pscores)
00642     {
00643       fprintf(stderr, "ERROR: Memory allocation error.\n");
00644       pvp_compare->Release();
00645       return 1;
00646     }
00647     pscores->SetErrorHandler(&gErrorHandler);
00648 
00649     if(process_files)
00650     {
00651       float score = 0.0f;
00652       if(!pvp_compare->Compare2VoicePrintFiles(pinput1, pinput2, &score))
00653       {
00654         pscores->Release();
00655         pvp_compare->Release();
00656         return 1;
00657       }
00658       printf("Score: %e\n", score);
00659     }
00660     else if(process_lists || process_dirs)
00661     {
00662       if(!poutput_file)
00663       {
00664         fprintf(stderr, "ERROR: An output file must be specified (-o).\n");
00665         pscores->Release();
00666         pvp_compare->Release();
00667         return 1;
00668       }
00669 
00670       SVoicePrintSetI *pset1 = static_cast<SVoicePrintSetI *>(BSAPICreateInstance(SIID_VPRINTSET));
00671       if(!pset1)
00672       {
00673         fprintf(stderr, "ERROR: Memory allocation error.\n");
00674         pscores->Release();
00675         pvp_compare->Release();
00676         return 1;
00677       }
00678 
00679       pset1->SetErrorHandler(&gErrorHandler);
00680 
00681       SVoicePrintSetI *pset2 = static_cast<SVoicePrintSetI *>(BSAPICreateInstance(SIID_VPRINTSET));
00682       if(!pset2)
00683       {
00684         fprintf(stderr, "ERROR: Memory allocation error.\n");
00685         pset1->Release();
00686         pscores->Release();
00687         pvp_compare->Release();
00688         return 1;
00689       }
00690 
00691       pset2->SetErrorHandler(&gErrorHandler);
00692 
00693       if(process_lists)
00694       {
00695         if(!pset1->LoadFromList(pinput1))
00696         {
00697           pset1->Release();
00698           pset2->Release();
00699           pscores->Release();
00700           pvp_compare->Release();
00701           return 1;
00702         }
00703 
00704         if(!pset2->LoadFromList(pinput2))
00705         {
00706           pset1->Release();
00707           pset2->Release();
00708           pscores->Release();
00709           pvp_compare->Release();
00710           return 1;
00711         }
00712       }
00713       else // process_dirs
00714       {
00715         if(!pset1->LoadFromDirectory(pinput1, pvprint_ext))
00716         {
00717           pset1->Release();
00718           pset2->Release();
00719           pscores->Release();
00720           pvp_compare->Release();
00721           return 1;
00722         }
00723 
00724         if(!pset2->LoadFromDirectory(pinput2, pvprint_ext))
00725         {
00726           pset1->Release();
00727           pset2->Release();
00728           pscores->Release();
00729           pvp_compare->Release();
00730           return 1;
00731         }
00732       }
00733 
00734       if(!pvp_compare->Compare2VoicePrintSets(pset1, pset2, pscores))
00735       {
00736         pset1->Release();
00737         pset2->Release();
00738         pscores->Release();
00739         pvp_compare->Release();
00740         return 1;
00741       }
00742 
00743       if(!SaveScores(poutput_file, pscores, pset1, pset2, pcolumn_fmt, sharpness, nbest_scores, score_thr, dump_names, supp_too_short))
00744       {
00745         pset1->Release();
00746         pset2->Release();
00747         pscores->Release();
00748         pvp_compare->Release();
00749         return 1;
00750       }
00751 
00752       pset1->Release();
00753       pset2->Release();
00754     }
00755 
00756     pscores->Release();
00757   }
00758 
00759   pvp_compare->Release();
00760   return 0;
00761 }

Generated on Wed Apr 11 10:00:17 2012 for BSAPI by  doxygen 1.4.7