1 /*---------------------------------------------------------------------------*
2 * SWIslts.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 #define _IN_SWI_SLTS__
21
22 #ifdef SWISLTS_USE_STATIC_API
23 #define SWISLTS_FNEXPORT
24 #else
25 #ifdef WIN32
26 #include <windows.h>
27 #define SWISLTS_FNEXPORT __declspec(dllexport)
28 #else
29 #define SWISLTS_FNEXPORT
30 #endif
31 #endif
32
33 #include <stdlib.h>
34
35
36 #include <string.h>
37
38 #include "pmemory.h"
39 #include "PFile.h"
40 #include "plog.h"
41
42 #include "SWIslts.h"
43 #include "lts.h"
44
45 /**
46 * Phone map table
47 */
48 typedef struct SLTS_PhoneMap_t{
49 LCHAR *src;
50 LCHAR *des;
51 } SLTS_PhoneMap;
52
53 #define INF_SILENCE_OPTIONAL (const char *)"&"
54
55 static const SLTS_PhoneMap g_aPhoneMap[] = {
56 {"PS", "&"},
57 {"SS0", ""},
58 {"SS1", ""},
59 {"SS2", ""},
60 {"WS", "&"}
61 };
62 static const int g_numPhones = sizeof(g_aPhoneMap) / sizeof(g_aPhoneMap[0]);
63
64 #ifdef USE_STATIC_SLTS
65 #define MAX_INPUT_LEN 255
66 static SLTS_Engine g_sltsEngine;
67 static SWIsltsWrapper g_sltsWrapper;
68 #endif
69
70 #define MAX_PRON_LEN 255
71 #define MAX_PHONE_LEN 4
72
73 static SWIsltsResult GetPhoneStr(SLTS_Engine *pEng, char *apszPhones[], int num_phones, char *pszPhoneStr, size_t *len);
74
SWIsltsGetWrapper(SWIsltsWrapper ** ppLtsWrap)75 SWISLTS_FNEXPORT SWIsltsResult SWIsltsGetWrapper(SWIsltsWrapper **ppLtsWrap)
76 {
77 if (ppLtsWrap != NULL) {
78 #ifdef USE_STATIC_SLTS
79 *ppLtsWrap = &g_sltsWrapper;
80 #else
81 *ppLtsWrap = MALLOC(sizeof(SWIsltsWrapper), MTAG);
82 if (*ppLtsWrap == NULL) {
83 return SWIsltsErrAllocResource;
84 }
85 #endif
86 (*ppLtsWrap)->init = SWIsltsInit;
87 (*ppLtsWrap)->term = SWIsltsTerm;
88 (*ppLtsWrap)->open = SWIsltsOpen;
89 (*ppLtsWrap)->close = SWIsltsClose;
90 (*ppLtsWrap)->textToPhone = SWIsltsTextToPhone;
91 }
92 return SWIsltsSuccess;
93 }
94
SWIsltsReleaseWrapper(SWIsltsWrapper * pLtsWrap)95 SWISLTS_FNEXPORT SWIsltsResult SWIsltsReleaseWrapper(SWIsltsWrapper *pLtsWrap)
96 {
97 #ifndef USE_STATIC_SLTS
98 if (pLtsWrap != NULL) {
99 FREE(pLtsWrap);
100 pLtsWrap = NULL;
101 }
102 #endif
103 return SWIsltsSuccess;
104 }
105
106 /* External Core SLTS API implementation */
SWIsltsInit()107 SWISLTS_FNEXPORT SWIsltsResult SWIsltsInit()
108 {
109 return SWIsltsSuccess;
110 }
111
SWIsltsTerm()112 SWISLTS_FNEXPORT SWIsltsResult SWIsltsTerm()
113 {
114 return SWIsltsSuccess;
115 }
116
117 /* create a new instance of SLTS */
SWIsltsOpen(SWIsltsHand * phLts,const char * data_filename)118 SWISLTS_FNEXPORT SWIsltsResult SWIsltsOpen(SWIsltsHand *phLts,
119 const char *data_filename)
120 {
121 SLTS_Engine * pEng;
122 SWIsltsResult nRes = SWIsltsSuccess;
123
124 if ((phLts == NULL)
125 #ifndef USE_STATIC_SLTS
126 || (data_filename == NULL)
127 #endif
128 )
129 {
130 return SWIsltsInvalidParam;
131 }
132
133 #ifdef USE_STATIC_SLTS
134 pEng = &g_sltsEngine;
135 #else
136 pEng = CALLOC(1, sizeof(SLTS_Engine), MTAG);
137 if (pEng == NULL) {
138 return SWIsltsErrAllocResource;
139 }
140 #endif
141
142 /* initialize */
143 nRes = create_lts((char *)data_filename, &pEng->m_hLts);
144 if (nRes != SWIsltsSuccess) {
145 PLogError(L("create_lts with the model file (%s) fails with return code %d\n"), (char *)data_filename, nRes);
146 goto CLEAN_UP;
147 }
148
149 *phLts = (SWIsltsHand)pEng;
150
151 return SWIsltsSuccess;
152
153 CLEAN_UP:
154 if (*phLts != NULL) {
155 SWIsltsClose(*phLts);
156 }
157
158 return nRes;
159 }
160
161 /* deletes given instance of SLTS */
SWIsltsClose(SWIsltsHand hLts)162 SWISLTS_FNEXPORT SWIsltsResult SWIsltsClose(SWIsltsHand hLts)
163 {
164 SLTS_Engine *pEng = (SLTS_Engine *)hLts;
165 if (pEng == NULL) {
166 return SWIsltsInvalidParam;
167 }
168
169 /* clean up internal buffers and slts structure */
170 if (pEng->m_hLts) {
171 free_lts(pEng->m_hLts);
172 }
173 pEng->m_hLts = NULL;
174
175 #ifndef USE_STATIC_SLTS
176 FREE(pEng);
177 #endif
178
179 pEng = NULL;
180
181 return SWIsltsSuccess;
182 }
183
184 /* send phones to internal buffer */
SWIsltsTextToPhone(SWIsltsHand hLts,const char * text,char * output_phone_string[],int * output_phone_len,int max_phone_len)185 SWISLTS_FNEXPORT SWIsltsResult SWIsltsTextToPhone(SWIsltsHand hLts,
186 const char *text,
187 char *output_phone_string[],
188 int *output_phone_len,
189 int max_phone_len)
190 {
191 int i;
192 SWIsltsResult nRes = SWIsltsSuccess;
193 #ifdef USE_STATIC_SLTS
194 char new_text[MAX_INPUT_LEN];
195 #else
196 char *new_text;
197 #endif
198
199 SLTS_Engine *pEng;
200 if (hLts == NULL) {
201 return SWIsltsInvalidParam;
202 }
203
204 if (text == NULL) {
205 return SWIsltsInvalidParam;
206 }
207
208 /* check that the output phone string param is allocated */
209 for(i=0; i<max_phone_len; i++){
210 if(output_phone_string[i] == NULL)
211 return SWIsltsInvalidParam;
212 }
213
214 pEng = (SLTS_Engine *)hLts;
215
216 /* get rid newlines, tabs, and spaces, if any */
217 #ifdef USE_STATIC_SLTS
218 if((strlen(text)+1) > MAX_INPUT_LEN){
219 return SWIsltsMaxInputExceeded;
220 }
221 #else
222 new_text = MALLOC((strlen(text)+1)*sizeof(char), MTAG);
223 if (new_text == NULL) {
224 PLogError(L("SWISLTS_OUT_OF_MEMORY"));
225 return SWIsltsErrAllocResource;
226 }
227 #endif
228
229 strcpy(new_text, text);
230 i = strlen(new_text)-1;
231 while(new_text[i] == '\n' || new_text[i] == ' ' || new_text[i] == '\t') i--;
232 new_text[i+1] = '\0';
233
234 /* now check if the input string is empty */
235 if(strlen(new_text) == 0){
236 *output_phone_len = 0;
237 nRes = SWIsltsEmptyPhoneString;
238 goto CLEAN_UP;
239 }
240
241 *output_phone_len = max_phone_len;
242 nRes = run_lts(pEng->m_hLts, pEng->m_hDict, new_text, output_phone_string, output_phone_len);
243 if (nRes != SWIsltsSuccess) {
244 goto CLEAN_UP;
245 }
246
247 #ifndef USE_STATIC_SLTS
248 if(new_text){
249 FREE(new_text);
250 }
251 new_text = NULL;
252 #endif
253
254 return SWIsltsSuccess;
255
256 CLEAN_UP:
257
258 #ifndef USE_STATIC_SLTS
259 if(new_text){
260 FREE(new_text);
261 }
262 new_text = NULL;
263 #endif
264
265 return nRes;
266 }
267
SWIsltsG2PGetWordTranscriptions(SWIsltsHand hLts,const char * text,SWIsltsTranscription ** ppTranscriptions,int * pnNbrOfTranscriptions)268 SWISLTS_FNEXPORT SWIsltsResult SWIsltsG2PGetWordTranscriptions(SWIsltsHand hLts,
269 const char *text,
270 SWIsltsTranscription **ppTranscriptions,
271 int *pnNbrOfTranscriptions)
272 {
273 SWIsltsResult nRes = SWIsltsSuccess;
274 char PHONE_STRING[MAX_PRON_LEN][MAX_PHONE_LEN];
275 char * phone_string[MAX_PRON_LEN];
276 SLTS_Engine * pEng = (SLTS_Engine *)hLts;
277 int i;
278 int num_phones = 0;
279 SWIsltsTranscription * pTranscription = NULL;
280 int nNbrOfTranscriptions = 0;
281 int * pnNbrOfTranscriptionsToSave = NULL;
282 LCHAR * pBlock = NULL;
283
284 for( i = 0; i < MAX_PRON_LEN; i++ ) {
285 phone_string[i] = PHONE_STRING[i];
286 }
287
288 nRes = SWIsltsTextToPhone(hLts, text, phone_string, &num_phones, MAX_PRON_LEN);
289 if( nRes != SWIsltsSuccess ) {
290 PLogError(L("SWIsltsTextToPhone( ) fails with return code %d\n"), nRes);
291 goto CLEAN_UP;
292 }
293 #if DEBUG
294 pfprintf(PSTDOUT,"number of phones: %d\n ", num_phones);
295 for( i = 0; i < num_phones; i++ ) {
296 pfprintf(PSTDOUT,"%s ", phone_string[i]);
297 }
298 pfprintf(PSTDOUT,"\n ");
299 #endif
300
301 /* only one transcription available from seti */
302 nNbrOfTranscriptions = 1;
303 pBlock = (LCHAR *)CALLOC(sizeof(int) + nNbrOfTranscriptions * sizeof(SWIsltsTranscription), sizeof(LCHAR), MTAG);
304 if (pBlock == NULL) {
305 PLogError(L("SWISLTS_OUT_OF_MEMORY"));
306 nRes = SWIsltsErrAllocResource;
307 goto CLEAN_UP;
308 }
309 pnNbrOfTranscriptionsToSave = (int *)pBlock;
310 pTranscription = (SWIsltsTranscription *)(pBlock + sizeof(int));
311
312 *ppTranscriptions = pTranscription;
313 *pnNbrOfTranscriptions = *pnNbrOfTranscriptionsToSave = nNbrOfTranscriptions;
314
315 /* extra +1 for double-null at the end */
316 pTranscription->pBuffer = MALLOC(MAX_PHONE_LEN * (num_phones + 1+1), MTAG);
317 if( pTranscription->pBuffer == NULL ) {
318 PLogError(L("SWISLTS_OUT_OF_MEMORY"));
319 nRes = SWIsltsErrAllocResource;
320 goto CLEAN_UP;
321 }
322
323 nRes = GetPhoneStr(pEng, phone_string, num_phones, (char *)pTranscription->pBuffer, &(pTranscription->nSizeOfBuffer));
324 if( nRes != SWIsltsSuccess ) {
325 PLogError(L("SWIsltsInternalErr: GetPhoneStr( ) fails with return code %d\n"), nRes);
326 goto CLEAN_UP;
327 }
328
329 return SWIsltsSuccess;
330
331 CLEAN_UP:
332
333 *ppTranscriptions = NULL;
334 *pnNbrOfTranscriptions = 0;
335
336 for( i = 0; i < nNbrOfTranscriptions; i++ ) {
337 if(pTranscription[i].pBuffer) {
338 FREE(pTranscription[i].pBuffer);
339 }
340 }
341 FREE(pTranscription);
342
343 return nRes;
344 }
345
346
SWIsltsG2PFreeWordTranscriptions(SWIsltsHand hLts,SWIsltsTranscription * pTranscriptions)347 SWISLTS_FNEXPORT SWIsltsResult SWIsltsG2PFreeWordTranscriptions(SWIsltsHand hLts,
348 SWIsltsTranscription *pTranscriptions)
349 {
350 SWIsltsResult nRes = SWIsltsSuccess;
351 int nNbrOfTranscriptions;
352 int i;
353 LCHAR * pBuffer = NULL;
354
355 if( pTranscriptions == NULL ) {
356 return SWIsltsInvalidParam;
357 }
358
359 pBuffer = ((LCHAR *)pTranscriptions - sizeof(int));
360 nNbrOfTranscriptions = (int)*pBuffer;
361
362 for( i = 0; i < nNbrOfTranscriptions; i++ ) {
363 if( pTranscriptions[i].pBuffer ) {
364 FREE(pTranscriptions[i].pBuffer);
365 }
366 }
367 FREE(pBuffer);
368
369 return nRes;
370 }
371
GetPhoneStr(SLTS_Engine * pEng,char * apszPhones[],int num_phones,char * pszPhoneStr,size_t * len)372 static SWIsltsResult GetPhoneStr(SLTS_Engine *pEng, char *apszPhones[], int num_phones, char *pszPhoneStr, size_t *len)
373 {
374 int i, j;
375 int nFound;
376 SWIsltsResult nRes = SWIsltsSuccess;
377 const char * pszLastPhone = NULL;
378
379 *pszPhoneStr = '\0';
380
381 for( i = 0; i < num_phones; i++ ) {
382 nFound = 0;
383 for ( j = 0; j < g_numPhones && nFound == 0; j++ ) {
384 if( strcmp(apszPhones[i], g_aPhoneMap[j].src) == 0 ) {
385 nFound = 1;
386 if( strcmp(g_aPhoneMap[j].des, INF_SILENCE_OPTIONAL) == 0 ) {
387 if( *pszPhoneStr != '\0' && strcmp(pszLastPhone, INF_SILENCE_OPTIONAL) != 0 ) {
388 strcat(pszPhoneStr, g_aPhoneMap[j].des);
389 }
390 }
391 else if( g_aPhoneMap[j].des != '\0' ) {
392 strcat(pszPhoneStr, g_aPhoneMap[j].des);
393 }
394 pszLastPhone = g_aPhoneMap[j].des;
395 }
396 }
397 if( nFound == 0 ) {
398 strcat(pszPhoneStr, apszPhones[i]);
399 pszLastPhone = apszPhones[i];
400 }
401 }
402
403 *len = strlen(pszPhoneStr) + 1;
404 // add the double-null per SREC/Vocon convention
405 pszPhoneStr[ *len] = 0;
406
407 return nRes;
408 }
409