Home | History | Annotate | Download | only in src
      1 /*---------------------------------------------------------------------------*
      2  *  AcousticModelsImpl.c  *
      3  *                                                                           *
      4  *  Copyright 2007, 2008 Nuance Communciations, Inc.                               *
      5  *                                                                           *
      6  *  Licensed under the Apache License, Version 2.0 (the 'License');          *
      7  *  you may not use this file except in compliance with the License.         *
      8  *                                                                           *
      9  *  You may obtain a copy of the License at                                  *
     10  *      http://www.apache.org/licenses/LICENSE-2.0                           *
     11  *                                                                           *
     12  *  Unless required by applicable law or agreed to in writing, software      *
     13  *  distributed under the License is distributed on an 'AS IS' BASIS,        *
     14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
     15  *  See the License for the specific language governing permissions and      *
     16  *  limitations under the License.                                           *
     17  *                                                                           *
     18  *---------------------------------------------------------------------------*/
     19 
     20 
     21 #ifndef lint
     22 #endif /* lint */
     23 
     24 #include "ESR_Session.h"
     25 #include "IntArrayList.h"
     26 #include "LCHAR.h"
     27 #include "passert.h"
     28 #include "plog.h"
     29 #include "pmemory.h"
     30 #include "SR_AcousticModels.h"
     31 #include "SR_AcousticModelsImpl.h"
     32 #include "pstdio.h"
     33 #include "SR_EventLog.h"
     34 
     35 #define MTAG NULL
     36 
     37 #define CHKINTARRAY(rc, list, operation) rc = operation; \
     38   if (rc!=ESR_SUCCESS) \
     39   { \
     40     IntArrayListDestroy(list); \
     41     list = NULL; \
     42     PLogError(ESR_rc2str(rc)); \
     43     return rc; \
     44   }
     45 
     46 
     47 
     48 
     49 /**
     50  * Initializes acoustic-models properties to default values.
     51  *
     52  * Replaces setup_acoustic_parameters()
     53  */
     54 ESR_ReturnCode SR_AcousticModels_ToSession()
     55 {
     56   ESR_ReturnCode rc;
     57 
     58   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Acoustic.dimen", 16));
     59   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Acoustic.skip", 5));
     60   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Acoustic.stay", 5));
     61   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Acoustic.whole_skip", 10));
     62   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Acoustic.whole_stay", 10));
     63   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Acoustic.durscale", 5));
     64   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Acoustic.frame_period", 10));
     65   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Acoustic.minvar", 1));
     66   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Acoustic.maxvar", 64000));
     67   CHKLOG(rc, ESR_SessionSetBoolIfEmpty("CREC.Acoustic.load_all_at_once", ESR_FALSE));
     68   CHKLOG(rc, ESR_SessionSetLCHARIfEmpty("CREC.Acoustic.load_models", L("all")));
     69   return ESR_SUCCESS;
     70 CLEANUP:
     71   return rc;
     72 }
     73 
     74 /**
     75  * Initializes pattern properties to default values.
     76  *
     77  * Replaces setup_pattern_parameters()
     78  */
     79 ESR_ReturnCode SR_AcousticModels_PatternToSession()
     80 {
     81   ESR_ReturnCode rc;
     82 
     83   /* Old comment: Remember to keep "ca_pip.h" up to date with these parameters... */
     84 
     85   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Pattern.dimen", 16));
     86   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Pattern.whole_dimen", 0));
     87   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Pattern.start", 0));
     88   CHKLOG(rc, ESR_SessionSetBoolIfEmpty("CREC.Pattern.chelt_imelda", ESR_FALSE));
     89   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Pattern.vfrlimit", 100));
     90   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Pattern.vfrthresh", 0));
     91   CHKLOG(rc, ESR_SessionSetFloatIfEmpty("CREC.Pattern.mix_score_scale", 0.46f));
     92   CHKLOG(rc, ESR_SessionSetFloatIfEmpty("CREC.Pattern.imelda_scale", 16));
     93   CHKLOG(rc, ESR_SessionSetFloatIfEmpty("CREC.Pattern.uni_score_scale", 0.46f));
     94   CHKLOG(rc, ESR_SessionSetFloatIfEmpty("CREC.Pattern.uni_score_offset", 0));
     95   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Pattern.forget_speech", 40));
     96   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Pattern.forget_background", 100));
     97   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Pattern.rel_low", 15));
     98   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Pattern.rel_high", 30));
     99 
    100   /* Gap: longest stop gap */
    101   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Pattern.gap_period", 16));
    102 
    103   /* Click: longest isolated high-amplitude insert in silence */
    104   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Pattern.click_period", 6));
    105 
    106   /* Breath: longest isolated medium amplitude */
    107   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Pattern.breath_period", 50));
    108   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Pattern.extend_annotation", 0));
    109   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Pattern.min_initial_quiet_frames", 0));
    110   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Pattern.min_annotation_frames", 0));
    111   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Pattern.max_annotation_frames", 800));
    112   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Pattern.min_segment_rel_c0", 800));
    113   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Pattern.delete_leading_segments", 0));
    114   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Pattern.leading_segment_min_frames", 0));
    115   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Pattern.leading_segment_max_frames", 20));
    116   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Pattern.leading_segment_min_silence_gap_frames", 20));
    117   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Pattern.leading_segment_accept_if_not_found", 0));
    118 
    119 #if DO_SUBTRACTED_SEGMENTATION
    120   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Pattern.snr_holdoff", 0));
    121   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Pattern.min_acceptable_snr", 0));
    122 #endif
    123 
    124   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Pattern.param", 0));
    125   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Pattern.beep_size", 0));
    126   CHKLOG(rc, ESR_SessionSetIntIfEmpty("CREC.Pattern.beep_threshold", 0));
    127 
    128   return ESR_SUCCESS;
    129 
    130 CLEANUP:
    131   return rc;
    132 }
    133 
    134 /**
    135  * Populates legacy pattern parameters from the session.
    136  *
    137  * Replaces setup_pattern_parameters()
    138  */
    139 ESR_ReturnCode SR_AcousticModels_LoadLegacyPatternParameters(CA_PatInputParams* params)
    140 {
    141   ESR_ReturnCode rc;
    142 
    143   passert(params != NULL);
    144   params->is_loaded = ESR_FALSE;
    145   CHKLOG(rc, ESR_SessionGetInt("CREC.Pattern.dimen", &params->dimen));
    146   CHKLOG(rc, ESR_SessionGetInt("CREC.Pattern.whole_dimen", &params->whole_dimen));
    147   CHKLOG(rc, ESR_SessionGetInt("CREC.Pattern.start", &params->feat_start));
    148   CHKLOG(rc, ESR_SessionGetFloat("CREC.Pattern.mix_score_scale", &params->mix_score_scale));
    149   CHKLOG(rc, ESR_SessionGetFloat("CREC.Pattern.imelda_scale", &params->imelda_scale));
    150   CHKLOG(rc, ESR_SessionGetFloat("CREC.Pattern.uni_score_scale", &params->uni_score_scale));
    151   CHKLOG(rc, ESR_SessionGetFloat("CREC.Pattern.uni_score_offset", &params->uni_score_offset));
    152   CHKLOG(rc, ESR_SessionGetInt("CREC.Pattern.forget_speech", &params->forget_speech));
    153   CHKLOG(rc, ESR_SessionGetInt("CREC.Pattern.forget_background", &params->forget_background));
    154   CHKLOG(rc, ESR_SessionGetInt("CREC.Pattern.rel_low", &params->rel_low));
    155   CHKLOG(rc, ESR_SessionGetInt("CREC.Pattern.rel_high", &params->rel_high));
    156   CHKLOG(rc, ESR_SessionGetInt("CREC.Pattern.gap_period", &params->gap_period));
    157   CHKLOG(rc, ESR_SessionGetInt("CREC.Pattern.click_period", &params->click_period));
    158   CHKLOG(rc, ESR_SessionGetInt("CREC.Pattern.breath_period", &params->breath_period));
    159   CHKLOG(rc, ESR_SessionGetInt("CREC.Pattern.extend_annotation", &params->extend_annotation));
    160   CHKLOG(rc, ESR_SessionGetInt("CREC.Pattern.min_initial_quiet_frames", &params->min_initial_quiet_frames));
    161   CHKLOG(rc, ESR_SessionGetInt("CREC.Pattern.min_annotation_frames", &params->min_annotation_frames));
    162   CHKLOG(rc, ESR_SessionGetInt("CREC.Pattern.max_annotation_frames", &params->max_annotation_frames));
    163   CHKLOG(rc, ESR_SessionGetInt("CREC.Pattern.min_segment_rel_c0", &params->min_segment_rel_c0));
    164   CHKLOG(rc, ESR_SessionGetInt("CREC.Pattern.delete_leading_segments", &params->delete_leading_segments));
    165   CHKLOG(rc, ESR_SessionGetInt("CREC.Pattern.leading_segment_min_frames", &params->leading_segment_min_frames));
    166   CHKLOG(rc, ESR_SessionGetInt("CREC.Pattern.leading_segment_max_frames", &params->leading_segment_max_frames));
    167   CHKLOG(rc, ESR_SessionGetInt("CREC.Pattern.leading_segment_min_silence_gap_frames", &params->leading_segment_min_silence_gap_frames));
    168   CHKLOG(rc, ESR_SessionGetInt("CREC.Pattern.leading_segment_accept_if_not_found", &params->leading_segment_accept_if_not_found));
    169 
    170 #if DO_SUBTRACTED_SEGMENTATION
    171   CHKLOG(rc, ESR_SessionGetInt("CREC.Pattern.snr_holdoff", &params->snr_holdoff));
    172   CHKLOG(rc, ESR_SessionGetInt("CREC.Pattern.min_acceptable_snr", &params->min_acceptable_snr));
    173 #endif
    174 
    175   CHKLOG(rc, ESR_SessionGetInt("CREC.Pattern.param", &params->param));
    176   CHKLOG(rc, ESR_SessionGetInt("CREC.Pattern.beep_size", &params->beep_size));
    177   CHKLOG(rc, ESR_SessionGetInt("CREC.Pattern.beep_threshold", &params->beep_threshold));
    178 
    179   params->is_loaded = ESR_TRUE;
    180   return ESR_SUCCESS;
    181 
    182 CLEANUP:
    183   return rc;
    184 }
    185 
    186 /**
    187  * Generate legacy AcousticModels parameter structure from ESR_Session.
    188  *
    189  * @param params Resulting structure
    190  */
    191 ESR_ReturnCode SR_AcousticModels_GetLegacyParameters(CA_AcoustInputParams* params)
    192 {
    193   ESR_ReturnCode rc;
    194   size_t maxLabel = MAX_LABEL;
    195 
    196   passert(params != NULL);
    197   params->is_loaded = ESR_FALSE;
    198   CHKLOG(rc, ESR_SessionGetInt("CREC.Acoustic.dimen", &params->dimen));
    199   CHKLOG(rc, ESR_SessionGetInt("CREC.Acoustic.skip", &params->skip_penalty));
    200   CHKLOG(rc, ESR_SessionGetInt("CREC.Acoustic.stay", &params->stay_penalty));
    201   CHKLOG(rc, ESR_SessionGetInt("CREC.Acoustic.whole_skip", &params->whole_skip_penalty));
    202   CHKLOG(rc, ESR_SessionGetInt("CREC.Acoustic.whole_stay", &params->whole_stay_penalty));
    203   CHKLOG(rc, ESR_SessionGetInt("CREC.Acoustic.durscale", &params->dur_scale));
    204   CHKLOG(rc, ESR_SessionGetInt("CREC.Acoustic.frame_period", &params->frame_period));
    205   CHKLOG(rc, ESR_SessionGetInt("CREC.Acoustic.minvar", &params->min_var));
    206   CHKLOG(rc, ESR_SessionGetInt("CREC.Acoustic.maxvar", &params->max_var));
    207   CHKLOG(rc, ESR_SessionGetBool("CREC.Acoustic.load_all_at_once", &params->load_all));
    208   CHKLOG(rc, ESR_SessionGetLCHAR("CREC.Acoustic.load_models", params->load_models, &maxLabel));
    209   params->is_loaded = ESR_TRUE;
    210   return ESR_SUCCESS;
    211 CLEANUP:
    212   return rc;
    213 }
    214 
    215 int LogArbdataVersion(unsigned int ver)
    216 {
    217   ESR_ReturnCode rc;
    218   SR_EventLog* eventLog;
    219   size_t osi_log_level = 0;
    220   ESR_BOOL exists = ESR_FALSE;
    221 
    222   CHKLOG(rc, ESR_SessionExists(&exists));
    223   if (exists)
    224   {
    225     rc = ESR_SessionGetProperty(L("eventlog"), (void **)&eventLog, TYPES_SR_EVENTLOG);
    226     if ((rc != ESR_NO_MATCH_ERROR) && (rc != ESR_SUCCESS))
    227     {
    228       PLogError(ESR_rc2str(rc));
    229       goto CLEANUP;
    230     }
    231     if (eventLog)
    232     {
    233       rc = ESR_SessionGetSize_t(L("SREC.Recognizer.osi_log_level"), &osi_log_level);
    234       if ((rc != ESR_NO_MATCH_ERROR) && (rc != ESR_SUCCESS))
    235       {
    236         PLogError(ESR_rc2str(rc));
    237         goto CLEANUP;
    238       }
    239       if (osi_log_level > 0)
    240       {
    241         rc = SR_EventLogTokenSize_t(eventLog, L("VER"), ver);
    242         rc = SR_EventLogEvent(eventLog, L("ESRarbd"));
    243       }
    244     }
    245   }
    246 CLEANUP:
    247   return 0;
    248 }
    249 
    250 
    251 
    252 ESR_ReturnCode SR_AcousticModelsLoad(const LCHAR* filename, SR_AcousticModels** self)
    253 {
    254   int use_image;
    255   LCHAR arbfile[P_PATH_MAX];
    256   CA_AcoustInputParams* acousticParams;
    257   CA_Acoustic* acoustic;
    258   LCHAR modelFilename[P_PATH_MAX];
    259   SR_AcousticModelsImpl* impl;
    260   size_t len;
    261   ESR_ReturnCode rc;
    262 
    263   impl = NEW(SR_AcousticModelsImpl, MTAG);
    264   if (impl == NULL)
    265   {
    266     PLogError(L("ESR_OUT_OF_MEMORY"));
    267     return ESR_OUT_OF_MEMORY;
    268   }
    269   impl->Interface.destroy = &SR_AcousticModels_Destroy;
    270   impl->Interface.save = &SR_AcousticModels_Save;
    271   impl->Interface.setParameter = &SR_AcousticModels_SetParameter;
    272   impl->Interface.getParameter = &SR_AcousticModels_GetParameter;
    273   impl->Interface.getCount = &SR_AcousticModels_GetCount;
    274   impl->Interface.getID = &SR_AcousticModels_GetID;
    275   impl->Interface.setID = &SR_AcousticModels_SetID;
    276   impl->Interface.getArbdata = &SR_AcousticModels_GetArbdata;
    277   impl->setupPattern = &SR_AcousticModels_SetupPattern;
    278   impl->unsetupPattern = &SR_AcousticModels_UnsetupPattern;
    279   impl->getLegacyParameters = &SR_AcousticModels_GetLegacyParameters;
    280   impl->parameters = NULL;
    281   impl->pattern = NULL;
    282   impl->acoustic = NULL;
    283   impl->arbdata = NULL;
    284   impl->contents = NULL;
    285   impl->size = 0;
    286   acousticParams = NULL;
    287   acoustic = NULL;
    288 
    289   rc = SR_AcousticModels_PatternToSession();
    290   if (rc != ESR_SUCCESS)
    291   {
    292     PLogError(ESR_rc2str(rc));
    293     goto CLEANUP;
    294   }
    295   rc = SR_AcousticModels_ToSession();
    296   if (rc != ESR_SUCCESS)
    297   {
    298     PLogError(ESR_rc2str(rc));
    299     goto CLEANUP;
    300   }
    301   rc = ArrayListCreate(&impl->acoustic);
    302   if (rc != ESR_SUCCESS)
    303   {
    304     PLogError(ESR_rc2str(rc));
    305     goto CLEANUP;
    306   }
    307 
    308   acousticParams = CA_AllocateAcousticParameters();
    309   if (acousticParams == NULL)
    310   {
    311     rc = ESR_OUT_OF_MEMORY;
    312     PLogError(ESR_rc2str(rc));
    313     goto CLEANUP;
    314   }
    315   rc = impl->getLegacyParameters(acousticParams);
    316   if (rc != ESR_SUCCESS)
    317   {
    318     PLogError(ESR_rc2str(rc));
    319     goto CLEANUP;
    320   }
    321 
    322   rc = ESR_SessionGetInt(L("cmdline.use_image"), &use_image);
    323   if (rc != ESR_SUCCESS)
    324   {
    325     PLogError(ESR_rc2str(rc));
    326     goto CLEANUP;
    327   }
    328 
    329   while (ESR_TRUE)
    330   {
    331     int i;
    332     // skip space to next relative pathname
    333     while (LISSPACE(*filename)) filename++;
    334     if (*filename == L('\0')) break;
    335     // copy the relative pathname
    336     for (i = 0; *filename != L('\0') && !LISSPACE(*filename); i++)
    337     {
    338       modelFilename[i] = *filename++;
    339     }
    340     modelFilename[i] = L('\0');
    341 
    342     if (LSTRLEN(modelFilename) == 0 || modelFilename[0] == '#')
    343       continue;
    344     rc = lstrtrim(modelFilename);
    345     if (rc != ESR_SUCCESS)
    346     {
    347       PLogError(ESR_rc2str(rc));
    348       goto CLEANUP;
    349     }
    350 
    351     len = P_PATH_MAX;
    352     CHKLOG(rc, ESR_SessionPrefixWithBaseDirectory(modelFilename, &len));
    353     acoustic = CA_AllocateAcoustic();
    354     if (acoustic == NULL)
    355     {
    356       rc = ESR_OUT_OF_MEMORY;
    357       PLogError(ESR_rc2str(rc));
    358       goto CLEANUP;
    359     }
    360     if (use_image == 1)
    361     {
    362       rc = ESR_INVALID_STATE;
    363       PLogError(ESR_rc2str(rc));
    364       goto CLEANUP;
    365     }
    366     else if (use_image == 2)
    367     {
    368       if (!CA_LoadAcousticSub(acoustic, modelFilename, 0))
    369       {
    370         rc = ESR_INVALID_STATE;
    371         PLogError(ESR_rc2str(rc));
    372         goto CLEANUP;
    373       }
    374     }
    375     else
    376     {
    377             /* TODO: Is this being used? */
    378       if (!CA_LoadAcousticSub(acoustic, modelFilename, acousticParams))
    379       {
    380         rc = ESR_INVALID_STATE;
    381         PLogError(ESR_rc2str(rc));
    382         goto CLEANUP;
    383       }
    384     }
    385     rc = ArrayListAdd(impl->acoustic, acoustic);
    386     if (rc != ESR_SUCCESS)
    387     {
    388       PLogError(ESR_rc2str(rc));
    389       goto CLEANUP;
    390     }
    391 
    392   }
    393   len = P_PATH_MAX;
    394   rc = ESR_SessionGetLCHAR(L("cmdline.arbfile"), (LCHAR*) & arbfile, &len);
    395   if (rc != ESR_SUCCESS)
    396   {
    397     PLogError(ESR_rc2str(rc));
    398     goto CLEANUP;
    399   }
    400   len = P_PATH_MAX;
    401   CHKLOG(rc, ESR_SessionPrefixWithBaseDirectory(arbfile, &len));
    402   impl->arbdata = CA_LoadArbdata(arbfile);
    403   if (impl->arbdata == NULL)
    404   {
    405     rc = ESR_OUT_OF_MEMORY;
    406     goto CLEANUP;
    407   }
    408   len = CA_ArbdataGetModelVersionID(impl->arbdata);
    409   LogArbdataVersion(len);
    410 
    411   CA_FreeAcousticParameters(acousticParams);
    412   *self = (SR_AcousticModels*) impl;
    413 
    414   return ESR_SUCCESS;
    415 CLEANUP:
    416   if (acousticParams != NULL)
    417     CA_FreeAcousticParameters(acousticParams);
    418   impl->Interface.destroy(&impl->Interface);
    419   return rc;
    420 }
    421 
    422 ESR_ReturnCode SR_AcousticModels_Destroy(SR_AcousticModels* self)
    423 {
    424   SR_AcousticModelsImpl* impl = (SR_AcousticModelsImpl*) self;
    425   CA_Acoustic* acoustic;
    426   ESR_ReturnCode rc;
    427   size_t size, i;
    428 
    429   if (impl->pattern != NULL)
    430   {
    431     CHKLOG(rc, impl->acoustic->getSize(impl->acoustic, &size));
    432     for (i = 0; i < size; ++i)
    433     {
    434       CHKLOG(rc, impl->acoustic->get(impl->acoustic, i, (void **)&acoustic));
    435       CA_ClearPatternForAcoustic(impl->pattern, acoustic);
    436     }
    437     CA_UnloadPattern(impl->pattern);
    438     CA_FreePattern(impl->pattern);
    439     impl->pattern = NULL;
    440   }
    441 
    442   if (impl->acoustic != NULL)
    443   {
    444     CHKLOG(rc, impl->acoustic->getSize(impl->acoustic, &size));
    445     for (i = 0; i < size; ++i)
    446     {
    447       CHKLOG(rc, impl->acoustic->get(impl->acoustic, 0, (void **)&acoustic));
    448       CHKLOG(rc, impl->acoustic->removeAtIndex(impl->acoustic, 0));
    449 
    450       /* Free acoustic models */
    451       CA_UnloadAcoustic(acoustic);
    452       CA_FreeAcoustic(acoustic);
    453     }
    454 
    455     CHKLOG(rc, impl->acoustic->destroy(impl->acoustic));
    456     impl->acoustic = NULL;
    457   }
    458 
    459   if (impl->arbdata != NULL)
    460   {
    461     CA_FreeArbdata(impl->arbdata);
    462     impl->arbdata = NULL;
    463   }
    464 
    465   FREE(impl);
    466   return ESR_SUCCESS;
    467 CLEANUP:
    468   return rc;
    469 }
    470 
    471 ESR_ReturnCode SR_AcousticModels_Save(SR_AcousticModels* self, const LCHAR* filename)
    472 {
    473   /*SR_AcousticModelsImpl* impl = (SR_AcousticModelsImpl*) self;*/
    474 
    475   /* CA_WriteAcousticImage(impl->acoustic, filename, 0); */
    476   return ESR_SUCCESS;
    477 }
    478 
    479 ESR_ReturnCode SR_AcousticModels_SetParameter(SR_AcousticModels* self, const LCHAR* key, LCHAR* value)
    480 {
    481   SR_AcousticModelsImpl* impl = (SR_AcousticModelsImpl*) self;
    482   LCHAR* temp;
    483   ESR_ReturnCode rc;
    484 
    485   rc = HashMapGet(impl->parameters, key, (void **)&temp);
    486   if (rc == ESR_SUCCESS)
    487   {
    488     /* Key already exists, remove old value if necessary */
    489     if (LSTRCMP(temp, value) == 0)
    490       return ESR_SUCCESS;
    491     CHKLOG(rc, HashMapRemove(impl->parameters, key));
    492     FREE(temp);
    493   }
    494   else if (rc != ESR_NO_MATCH_ERROR)
    495   {
    496     PLogError(ESR_rc2str(rc));
    497     goto CLEANUP;
    498   }
    499 
    500   /* Allocate and put new key */
    501   temp = MALLOC(sizeof(LCHAR) * (LSTRLEN(value) + 1), MTAG);
    502   if (temp == NULL)
    503   {
    504     rc = ESR_OUT_OF_MEMORY;
    505     PLogError(ESR_rc2str(rc));
    506     goto CLEANUP;
    507   }
    508   CHKLOG(rc, impl->parameters->put(impl->parameters, key, temp));
    509   return ESR_SUCCESS;
    510 CLEANUP:
    511   FREE(temp);
    512   return rc;
    513 }
    514 
    515 ESR_ReturnCode SR_AcousticModels_GetParameter(SR_AcousticModels* self, const LCHAR* key, LCHAR* value, size_t* len)
    516 {
    517   SR_AcousticModelsImpl* impl = (SR_AcousticModelsImpl*) self;
    518   LCHAR* temp;
    519   ESR_ReturnCode rc;
    520 
    521   rc = HashMapGet(impl->parameters, key, (void **)&temp);
    522   if (rc == ESR_NO_MATCH_ERROR)
    523     CHKLOG(rc, ESR_SessionGetLCHAR(key, value, len));
    524   if (rc != ESR_SUCCESS)
    525   {
    526     PLogError(ESR_rc2str(rc));
    527     return rc;
    528   }
    529   if (LSTRLEN(temp) + 1 > *len)
    530   {
    531     *len = LSTRLEN(temp) + 1;
    532     PLogError(L("ESR_BUFFER_OVERFLOW"));
    533     return ESR_BUFFER_OVERFLOW;
    534   }
    535   *len = LSTRLEN(temp) + 1;
    536   LSTRCPY(value, temp);
    537   return ESR_SUCCESS;
    538 CLEANUP:
    539   return rc;
    540 }
    541 
    542 ESR_ReturnCode SR_AcousticModels_GetCount(SR_AcousticModels* self, size_t* size)
    543 {
    544   SR_AcousticModelsImpl* impl = (SR_AcousticModelsImpl*) self;
    545   ESR_ReturnCode rc;
    546 
    547   CHKLOG(rc, ArrayListGetSize(impl->acoustic, size));
    548   return ESR_SUCCESS;
    549 CLEANUP:
    550   return rc;
    551 }
    552 
    553 ESR_ReturnCode SR_AcousticModels_GetID(SR_AcousticModels* self, size_t index,
    554                                        SR_AcousticModelID* id, size_t* size)
    555 {
    556   /* TODO: complete */
    557   return ESR_SUCCESS;
    558 }
    559 
    560 ESR_ReturnCode SR_AcousticModels_SetID(SR_AcousticModels* self, size_t index,
    561                                        SR_AcousticModelID* id)
    562 {
    563   /* TODO: complete */
    564   return ESR_SUCCESS;
    565 }
    566 
    567 void* SR_AcousticModels_GetArbdata(SR_AcousticModels* self)
    568 {
    569 	SR_AcousticModelsImpl* impl = (SR_AcousticModelsImpl*)self;
    570 	return impl? (void*)impl->arbdata : NULL;
    571 }
    572 
    573 /**
    574  * When AcousticModels are associated with a Recognizer, they initialize their
    575  * Pattern objects using that Recognizer.
    576  *
    577  * @param self SR_AcousticModels handle
    578  * @param recognizer The recognizer
    579  */
    580 ESR_ReturnCode SR_AcousticModels_SetupPattern(SR_AcousticModels* self,
    581     SR_Recognizer* recognizer)
    582 {
    583   CA_PatInputParams* patternParams = NULL;
    584   LCHAR mulname[P_PATH_MAX];
    585   LCHAR ldaname[P_PATH_MAX];
    586   SR_RecognizerImpl* recog;
    587   SR_AcousticModelsImpl* impl = (SR_AcousticModelsImpl*) self;
    588   CA_Acoustic* acoustic;
    589   size_t i, size, len;
    590   int dimen;
    591   ESR_ReturnCode rc;
    592   ESR_BOOL isPatternLoaded = ESR_FALSE;
    593 
    594   if (recognizer == NULL)
    595   {
    596     PLogError(L("ESR_INVALID_ARGUMENT"));
    597     return ESR_INVALID_ARGUMENT;
    598   }
    599   recog = (SR_RecognizerImpl*) recognizer;
    600 
    601   impl->pattern = CA_AllocatePattern();
    602   if (impl->pattern == NULL)
    603   {
    604     rc = ESR_OUT_OF_MEMORY;
    605     PLogError(ESR_rc2str(rc));
    606     goto CLEANUP;
    607   }
    608   patternParams = CA_AllocatePatternParameters();
    609   if (patternParams == NULL)
    610   {
    611     rc = ESR_OUT_OF_MEMORY;
    612     PLogError(ESR_rc2str(rc));
    613     goto CLEANUP;
    614   }
    615 
    616   CHKLOG(rc, SR_AcousticModels_LoadLegacyPatternParameters(patternParams));
    617   dimen = CA_GetFrontendUtteranceDimension(recog->frontend);
    618 
    619   LSTRCPY(mulname, L(""));
    620 
    621   len = P_PATH_MAX;
    622   CHKLOG(rc, ESR_SessionGetLCHAR(L("cmdline.lda"), (LCHAR*) &ldaname, &len));
    623   len = P_PATH_MAX;
    624   CHKLOG(rc, ESR_SessionPrefixWithBaseDirectory(ldaname, &len));
    625 
    626   CA_LoadPattern(impl->pattern, patternParams, dimen, mulname, ldaname);
    627   isPatternLoaded = ESR_TRUE;
    628   CHKLOG(rc, impl->acoustic->getSize(impl->acoustic, &size));
    629   for (i = 0; i < size; ++i)
    630   {
    631     CHKLOG(rc, impl->acoustic->get(impl->acoustic, i, (void **)&acoustic));
    632     CA_SetupPatternForAcoustic(impl->pattern, acoustic);
    633   }
    634   CA_FreePatternParameters(patternParams);
    635   return ESR_SUCCESS;
    636 CLEANUP:
    637   if (impl->pattern != NULL)
    638   {
    639     if (isPatternLoaded == ESR_TRUE)
    640       CA_UnloadPattern(impl->pattern);
    641     CA_FreePattern(impl->pattern);
    642   }
    643   if (patternParams != NULL)
    644     CA_FreePatternParameters(patternParams);
    645   return rc;
    646 }
    647 
    648 /**
    649  * When AcousticModels are deassociated with a Recognizer, they deinitialize their
    650  * Pattern objects.
    651  *
    652  * @param self SR_AcousticModels handle
    653  */
    654 ESR_ReturnCode SR_AcousticModels_UnsetupPattern(SR_AcousticModels* self)
    655 {
    656   SR_AcousticModelsImpl* impl = (SR_AcousticModelsImpl*) self;
    657   CA_Acoustic* acoustic;
    658   size_t i, size;
    659   ESR_ReturnCode rc;
    660 
    661   CHKLOG(rc, impl->acoustic->getSize(impl->acoustic, &size));
    662   for (i = 0; i < size; ++i)
    663   {
    664     CHKLOG(rc, impl->acoustic->get(impl->acoustic, i, (void **)&acoustic));
    665     CA_ClearPatternForAcoustic(impl->pattern, acoustic);
    666   }
    667   CA_UnloadPattern(impl->pattern);
    668   CA_FreePattern(impl->pattern);
    669   impl->pattern = NULL;
    670   return ESR_SUCCESS;
    671 CLEANUP:
    672   return rc;
    673 }
    674