1/*---------------------------------------------------------------------------*
2 *  syn_srec.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#include <stdlib.h>
21#include <string.h>
22#ifndef _RTT
23#include <stdio.h>
24#endif
25
26#ifdef unix
27#include <unistd.h>
28#endif
29#include <assert.h>
30
31#ifndef _RTT
32#include "duk_io.h"
33#endif
34
35#include "simapi.h"
36#include "pendian.h"
37#include "portable.h"
38#include "srec_context.h"
39#include "ESR_Session.h"
40
41static void free_buffer(char* buffer, const char* allocname)
42{
43  FREE(buffer);
44}
45
46int CA_AttachArbdataToSyntax(CA_Syntax* syntax, CA_Arbdata* allotree)
47{
48  int rc;
49  rc = FST_AttachArbdata(syntax->synx, (srec_arbdata*)allotree);
50  return rc;
51}
52
53int CA_AddWordToSyntax(CA_Syntax* syntax, const char* slot,
54                       const char *phrase, const char* pronunciation,
55                       const int weight)
56{
57  int rc;
58  rc = FST_AddWordToGrammar(syntax->synx, slot, phrase, pronunciation, weight);
59  return rc;
60}
61
62int CA_ResetSyntax(CA_Syntax* syntax)
63{
64  int rc;
65  rc = FST_ResetGrammar(syntax->synx);
66  return rc;
67}
68
69int  CA_CompileSyntax(CA_Syntax *hSyntax)
70{
71  return FST_PrepareContext(hSyntax->synx);
72}
73
74int CA_LoadSyntaxAsExtensible(CA_Syntax *hSyntax, /*CA_Arbdata* arbdata,*/
75                              char *synbase, int num_words_to_add)
76{
77  int rc;
78  TRY_CA_EXCEPT
79  ASSERT(hSyntax);
80  if (hSyntax->setup_count > 0)
81    SERVICE_ERROR(SYNTAX_ALREADY_SETUP);
82
83  rc = FST_LoadContext(synbase, &hSyntax->synx, num_words_to_add);
84  return rc ? 1 : 0;
85  BEG_CATCH_CA_EXCEPT
86  END_CATCH_CA_EXCEPT(hSyntax)
87}
88
89/* this belongs part of the srec_context! */
90/**
91 * @todo document
92 */
93typedef struct
94{
95  asr_int32_t image_format;
96  asr_int32_t image_size;
97  asr_int32_t sizes_signature;
98}
99context_image_header;
100
101int CA_LoadSyntaxFromImage(CA_Syntax *hSyntax, const LCHAR* filename)
102{
103  int result;
104  PFile* fp = NULL;
105  ESR_BOOL isLittleEndian;
106
107  /*
108#if __BYTE_ORDER==__LITTLE_ENDIAN
109   isLittleEndian = ESR_TRUE;
110#else
111   isLittleEndian = ESR_FALSE;
112#endif
113  */
114  isLittleEndian = ESR_TRUE;
115
116  fp = pfopen ( filename, L("rb") );
117/*  CHKLOG(rc, PFileSystemCreatePFile(filename, isLittleEndian, &fp));
118  CHKLOG(rc, PFileOpen(fp, L("rb")));*/
119
120  if ( fp == NULL )
121    goto CLEANUP;
122
123  result = FST_LoadContextFromImage(&hSyntax->synx, fp);
124  pfclose(fp);
125  return result ? 1 : 0;
126CLEANUP:
127  if (fp)
128    pfclose (fp);
129  return 1;
130}
131
132int CA_DumpSyntax(CA_Syntax* hSyntax, const char* basename)
133{
134  int result, totrc = 0;
135  PFile* fp;
136  char buf[256];
137  /*ESR_ReturnCode rc;*/
138
139  sprintf(buf, "%s.PCLG.txt", basename);
140  fp = pfopen ( buf, L("wb") );
141/*  CHKLOG(rc, PFileSystemCreatePFile(buf, ESR_TRUE, &fp));
142  CHKLOG(rc, PFileOpen(fp, L("wb")));*/
143
144  if ( fp == NULL )
145    goto CLEANUP;
146
147  result = FST_DumpGraph(hSyntax->synx, fp);
148  pfclose(fp);
149  totrc += result;
150
151  sprintf(buf, "%s.map", basename);
152  fp = pfopen ( buf, L("wb") );
153/*  CHKLOG(rc, PFileSystemCreatePFile(buf, ESR_TRUE, &fp));
154  CHKLOG(rc, PFileOpen(fp, L("wb")));*/
155
156  if ( fp == NULL )
157    goto CLEANUP;
158
159  result = FST_DumpWordMap(fp, hSyntax->synx->olabels);
160  pfclose(fp);
161  totrc += result;
162
163  sprintf(buf, "%s.Grev2.det.txt", basename);
164  fp = pfopen ( buf, L("wb") );
165/*  CHKLOG(rc, PFileSystemCreatePFile(buf, ESR_TRUE, &fp));
166  CHKLOG(rc, PFileOpen(fp, L("wb")));*/
167
168  if ( fp == NULL )
169    goto CLEANUP;
170
171  if (0)
172    result = FST_DumpReverseWordGraph(hSyntax->synx, fp);
173  pfclose(fp);
174  totrc += result;
175
176  return totrc ? 1 : 0;
177CLEANUP:
178  return 0;
179}
180
181int CA_DumpSyntaxAsImage(CA_Syntax* hSyntax, const char* imagename, int version_number)
182{
183  int result;
184  PFile* fp;
185  /*ESR_ReturnCode rc;*/
186  ESR_BOOL isLittleEndian;
187
188  isLittleEndian = ESR_TRUE;
189
190  fp = pfopen ( imagename, L("wb") );
191/*  CHKLOG(rc, PFileSystemCreatePFile(imagename, isLittleEndian, &fp));
192  CHKLOG(rc, PFileOpen(fp, L("wb")));*/
193
194  if ( fp == NULL )
195    goto CLEANUP;
196
197  if (version_number == 2)
198  {
199    result = FST_DumpContextAsImageV2(hSyntax->synx, fp);
200  }
201  else
202  {
203    PLogError("invalid version number %d\n", version_number);
204    result = FST_FAILED_ON_INVALID_ARGS;
205  }
206  pfclose(fp);
207  return result ? 1 : 0;
208CLEANUP:
209  return 0;
210}
211
212/* from syn_file.c */
213
214CA_Syntax *CA_AllocateSyntax(void)
215{
216  CA_Syntax *hSyntax = NULL;
217  TRY_CA_EXCEPT
218  hSyntax = (CA_Syntax *) CALLOC_CLR(1, sizeof(CA_Syntax), "ca.hSyntax");
219  hSyntax->has_groups = False;
220  hSyntax->has_rules = False;
221  hSyntax->setup_count = 0;
222  hSyntax->ca_rtti = CA_SYNTAX_SIGNATURE;
223  hSyntax->synx = 0;
224  return (hSyntax);
225
226  BEG_CATCH_CA_EXCEPT
227  END_CATCH_CA_EXCEPT(hSyntax)
228}
229
230void CA_FreeSyntax(CA_Syntax *hSyntax)
231{
232  TRY_CA_EXCEPT
233  ASSERT(hSyntax);
234  if (hSyntax->setup_count > 0)
235    SERVICE_ERROR(SYNTAX_ALREADY_SETUP);
236  /* todo: free hSyntax internals */
237  FST_UnloadContext((srec_context*)(hSyntax->synx));
238  hSyntax->synx = 0;
239  FREE((char *) hSyntax);
240  return;
241
242  BEG_CATCH_CA_EXCEPT
243  END_CATCH_CA_EXCEPT(hSyntax)
244}
245
246CA_Arbdata* CA_LoadArbdata(const char* filename)
247{
248  CA_Arbdata* ca_arbdata = NULL;
249  int rc;
250
251#ifdef SREC_ENGINE_VERBOSE_LOGGING
252  PLogMessage(L("CA_LoadArbdata ... from file %s"), filename);
253#endif
254  rc = read_arbdata_from_stream((srec_arbdata**) & ca_arbdata, (char *)filename, 0);
255  return ca_arbdata;
256}
257
258unsigned int CA_ArbdataGetModelVersionID(CA_Arbdata* ca_arbdata)
259{
260  return version_arbdata_models((srec_arbdata*)ca_arbdata);
261}
262
263int CA_ArbdataGetModelIdsForPron(CA_Arbdata* ca_arbdata,
264								 const char* pronunciation,  /* WB assumed at the edges */
265								 int pronunciation_len,
266								 modelID* pmodelIds)
267{
268	srec_arbdata *allotree = (srec_arbdata*)ca_arbdata;
269	return get_modelids_for_pron( allotree,
270                         pronunciation, pronunciation_len,
271                          pmodelIds);
272}
273
274int CA_ArbdataGetModelIdsForPIC(CA_Arbdata* ca_arbdata, const char lphon,
275								const char cphon,
276								const char rphon)
277{
278  phonemeID lphon_ID, cphon_ID, rphon_ID;
279  srec_arbdata *allotree = (srec_arbdata*)ca_arbdata;
280  if(lphon==WBPHONEME_CODE){
281#if !USE_WWTRIPHONE
282    lphon_ID = (phonemeID)allotree->phoneme_index[ SILENCE_CODE];
283#else
284    lphon_ID = WBPHONEME_CODE; //(phonemeID)allotree->phoneme_index[ WBPHONEME_CODE];
285#endif
286  }
287  else
288    lphon_ID = (phonemeID)allotree->phoneme_index[(const unsigned char)lphon];
289  cphon_ID = (phonemeID)allotree->phoneme_index[(const unsigned char)cphon];
290  if(rphon==WBPHONEME_CODE){
291#if !USE_WWTRIPHONE
292    rphon_ID = (phonemeID)allotree->phoneme_index[ SILENCE_CODE];
293#else
294    rphon_ID = WBPHONEME_CODE; //(phonemeID)allotree->phoneme_index[ WBPHONEME_CODE];
295#endif
296  }
297  else
298    rphon_ID = (phonemeID)allotree->phoneme_index[(const unsigned char)rphon];
299  return (modelID)get_modelid_for_pic(allotree, lphon_ID, cphon_ID, rphon_ID);
300}
301
302void CA_FreeArbdata(CA_Arbdata* ca_arbdata)
303{
304  free_buffer((char*)ca_arbdata, "srec.arbdata");
305}
306/* from syn_basi.c */
307
308int CA_SetupSyntaxForRecognizer(CA_Syntax *hSyntax, CA_Recog *hRecog)
309{
310  int rc;
311  const char* rule = "ROOT";
312  rc = activate_grammar_for_recognition(hRecog->recm, hSyntax->synx, rule);
313  return rc;
314}
315
316int CA_IsEnrollmentSyntax(CA_Syntax *hSyntax)
317{
318  return FST_IsVoiceEnrollment( hSyntax->synx);
319}
320
321int CA_CeilingSyntaxForRecognizer(CA_Syntax *hSyntax, CA_Recog *hRecog)
322{
323  if(!hSyntax || !hRecog)
324	  return 1;
325  if(!hSyntax->synx || !hRecog->recm)
326	  return 1;
327  hSyntax->synx->max_searchable_nodes = hRecog->recm->max_fsm_nodes;
328  hSyntax->synx->max_searchable_arcs  = hRecog->recm->max_fsm_arcs;
329  return 0;
330}
331
332/* checks if the phrase is in the grammar node, 0=in 1=not.in */
333int CA_CheckTranscription(CA_Syntax *hSyntax, const char *transcription, int no)
334{
335  int rc;
336  char literal[512];
337  size_t max_literal_len = 512;
338  srec_context* context = hSyntax->synx;
339  rc = FST_CheckPath(context, transcription, literal, max_literal_len);
340  if (rc == 0) strcpy((char*)transcription, literal);
341  return rc;
342}
343
344/*---------------------------------------------------------------------------*
345 *                                                                           *
346 * do nothing functions                                                      *
347 *                                                                           *
348 *---------------------------------------------------------------------------*/
349
350/* from syn_basi.c */
351
352
353void CA_ClearSyntaxForRecognizer(CA_Syntax *hSyntax, CA_Recog *hRecog)
354{
355  int rc;
356  hSyntax = NULL; /* not used */
357  rc = clear_grammars_for_recognition(hRecog->recm);
358  return;
359}
360