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 */
54ESR_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;
70CLEANUP:
71  return rc;
72}
73
74/**
75 * Initializes pattern properties to default values.
76 *
77 * Replaces setup_pattern_parameters()
78 */
79ESR_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
130CLEANUP:
131  return rc;
132}
133
134/**
135 * Populates legacy pattern parameters from the session.
136 *
137 * Replaces setup_pattern_parameters()
138 */
139ESR_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
182CLEANUP:
183  return rc;
184}
185
186/**
187 * Generate legacy AcousticModels parameter structure from ESR_Session.
188 *
189 * @param params Resulting structure
190 */
191ESR_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;
211CLEANUP:
212  return rc;
213}
214
215int 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  }
246CLEANUP:
247  return 0;
248}
249
250
251
252ESR_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;
415CLEANUP:
416  if (acousticParams != NULL)
417    CA_FreeAcousticParameters(acousticParams);
418  impl->Interface.destroy(&impl->Interface);
419  return rc;
420}
421
422ESR_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;
467CLEANUP:
468  return rc;
469}
470
471ESR_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
479ESR_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;
510CLEANUP:
511  FREE(temp);
512  return rc;
513}
514
515ESR_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;
538CLEANUP:
539  return rc;
540}
541
542ESR_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;
549CLEANUP:
550  return rc;
551}
552
553ESR_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
560ESR_ReturnCode SR_AcousticModels_SetID(SR_AcousticModels* self, size_t index,
561                                       SR_AcousticModelID* id)
562{
563  /* TODO: complete */
564  return ESR_SUCCESS;
565}
566
567void* 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 */
580ESR_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;
636CLEANUP:
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 */
654ESR_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;
671CLEANUP:
672  return rc;
673}
674