Home | History | Annotate | Download | only in src
      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 
     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 
     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 */
    107 SWISLTS_FNEXPORT SWIsltsResult SWIsltsInit()
    108 {
    109   return SWIsltsSuccess;
    110 }
    111 
    112 SWISLTS_FNEXPORT SWIsltsResult SWIsltsTerm()
    113 {
    114   return SWIsltsSuccess;
    115 }
    116 
    117 /* create a new instance of SLTS */
    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 */
    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 */
    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 
    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 
    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 
    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