• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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