Tizen 2.0 Release
[platform/core/uifw/libttssmt.git] / src / _SlpSmtApis.cpp
1 /*\r
2  * Samsung TTS\r
3  * Copyright 2012  Samsung Electronics Co., Ltd\r
4  *\r
5  * Licensed under the Flora License, Version 1.0 (the License);\r
6  * you may not use this file except in compliance with the License.\r
7  * You may obtain a copy of the License at\r
8  *\r
9  * http://floralicense.org/license/\r
10  *\r
11  * Unless required by applicable law or agreed to in writing, software\r
12  * distributed under the License is distributed on an AS IS BASIS,\r
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
14  * See the License for the specific language governing permissions and\r
15  * limitations under the License.\r
16  */\r
17 \r
18 #include "SMTApis.h"\r
19 \r
20 #include "_SlpSmtApis.h"\r
21 #include <stdio.h>\r
22 #include <stdlib.h>\r
23 #include <string.h>\r
24 \r
25 #include <pthread.h>\r
26 \r
27 \r
28 \r
29 \r
30 #define PCM_BUFFER_SIZE    640000\r
31 \r
32 // Not supported yet {\r
33 #define TTSPE_LANG_CANTONESE    "zh_HK"\r
34 #define TTSPE_LANG_TAIWAN       "zh_TW"\r
35 #define TTSPE_LANG_RUSSIAN      "ru_RU"\r
36 #define TTSPE_LANG_JAPANESE     "ja_JP"\r
37 #define TTSPE_LANG_NETHERLANDS  "nl_NL"\r
38 #define TTSPE_LANG_PORTUGUESE   "pt_PT"\r
39 #define TTSPE_LANG_GREEK        "el_GR"\r
40 #define TTSPE_LANG_TURKEY       "tr_TR"\r
41 // Not supported yet }\r
42 \r
43 \r
44 \r
45 \r
46 \r
47 \r
48 \r
49 \r
50 \r
51 \r
52 typedef struct __TypeVoiceInfo _TypeVoiceInfo;\r
53 struct __TypeVoiceInfo\r
54 {\r
55   char const         * const pszLanguage;\r
56   unsigned int          const sszLanguage;\r
57   ttsp_voice_type_e const eVoiceType;\r
58 \r
59 };\r
60 \r
61 \r
62 static char const _pszKorean              [] = "ko_KR";\r
63 static char const _pszUSEnglish           [] = "en_US";\r
64 static char const _pszChinese             [] = "zh_CN";\r
65 \r
66 \r
67 static char const _pszUKEnglish           [] = "en_GB";\r
68 static char const _pszGerman              [] = "de_DE";\r
69 static char const _pszSpanish             [] = "es_ES";\r
70 static char const _pszFrench              [] = "fr_FR";\r
71 static char const _pszItalian             [] = "it_IT";\r
72 \r
73 static unsigned int const _sszKorean                 = sizeof(_pszKorean);\r
74 static unsigned int const _sszUSEnglish              = sizeof(_pszUSEnglish);\r
75 static unsigned int const _sszChinese                = sizeof(_pszChinese);\r
76 static unsigned int const _sszUKEnglish              = sizeof(_pszUKEnglish);\r
77 static unsigned int const _sszGerman                 = sizeof(_pszGerman);\r
78 static unsigned int const _sszSpanish                = sizeof(_pszSpanish);\r
79 static unsigned int const _sszFrench                 = sizeof(_pszFrench);\r
80 static unsigned int const _sszItalian                = sizeof(_pszItalian);\r
81 \r
82 \r
83 static const _TypeVoiceInfo _pVoiceInfos[] =\r
84 {\r
85   { _pszKorean              , _sszKorean              , TTSP_VOICE_TYPE_FEMALE },\r
86   { _pszUSEnglish           , _sszUSEnglish           , TTSP_VOICE_TYPE_FEMALE },\r
87   { _pszChinese             , _sszChinese             , TTSP_VOICE_TYPE_FEMALE },\r
88 \r
89   { _pszUKEnglish           , _sszUKEnglish           , TTSP_VOICE_TYPE_FEMALE },\r
90   { _pszGerman              , _sszGerman              , TTSP_VOICE_TYPE_FEMALE },\r
91   { _pszSpanish             , _sszSpanish             , TTSP_VOICE_TYPE_FEMALE },\r
92   { _pszFrench              , _sszFrench              , TTSP_VOICE_TYPE_FEMALE },\r
93   { _pszItalian             , _sszItalian             , TTSP_VOICE_TYPE_FEMALE },\r
94 };\r
95 \r
96 #define _nVoiceInfos   (sizeof(_pVoiceInfos) / sizeof(_pVoiceInfos[0]))\r
97 \r
98 // index of VoiceInfos\r
99 #define VOICE_INDEX_KOREAN_WOMAN         0\r
100 #define VOICE_INDEX_USENGLISH_WOMAN       1\r
101 #define VOICE_INDEX_CHINESE_WOMAN          2\r
102 #define VOICE_INDEX_UKENGLISH_WOMAN        3\r
103 #define VOICE_INDEX_GERMAN_WOMAN           4\r
104 #define VOICE_INDEX_SPANISH_WOMAN          5\r
105 #define VOICE_INDEX_FRENCH_WOMAN           6\r
106 #define VOICE_INDEX_ITALIAN_WOMAN          7\r
107 \r
108 \r
109 \r
110 \r
111 typedef struct _TypeThreadQueueNode TypeThreadQueueNode;\r
112 struct _TypeThreadQueueNode\r
113 {\r
114   int                   iVoiceInfo;\r
115   char                * pszTextUtf8;\r
116   void                * pUserParam;\r
117   TypeThreadQueueNode * pNext;\r
118 };\r
119 \r
120 static struct _global\r
121 {\r
122   ttspe_result_cb      pfnCallback;\r
123   ttsp_speed_e        eSpeechSpeed;\r
124   int                  iVoiceInfo;\r
125   bool                 bStop;\r
126   bool                 bSentenceDone;\r
127 \r
128   // thread\r
129   int                  ThreadId;\r
130   pthread_t            Thread;\r
131   pthread_mutex_t      ThreadLock;\r
132   pthread_mutex_t      MainThreadFinalizeLock;\r
133   TypeThreadQueueNode* ThreadQueue_pHead;\r
134   TypeThreadQueueNode* ThreadQueue_pTail;\r
135 \r
136 } _g =\r
137 {\r
138   NULL                     , // pfnCallback\r
139 \r
140   TTSP_SPEED_NORMAL       , // eSpeechSpeed\r
141   -1                       , // iVoiceInfo, initial value means INVALID INDEX\r
142   false                    , // bStop\r
143   true                     , // bSentenceDone\r
144 \r
145   -1                       , // ThreadId\r
146   0                        , // Thread\r
147   PTHREAD_MUTEX_INITIALIZER, // ThreadLock\r
148   PTHREAD_MUTEX_INITIALIZER, // MainThreadFinalizeLock\r
149   NULL                     , // ThreadQueue_pHead\r
150   NULL                     , // ThreadQueue_pTail\r
151 };\r
152 \r
153 static void                 _PushThreadData (int const iVoiceInfo, char const * pszTextUtf8, void* pUserParam);\r
154 static TypeThreadQueueNode* _PopThreadData  (void);\r
155 static bool                 _bEmptyThreadData(void);\r
156 static void                 _CleanThreadData(void);\r
157 static void *               _Synthesize     (void* NotUsed); // Thread routine\r
158 \r
159 \r
160 static int  _ChangeVoice         (int const iVoiceInfo);\r
161 static void _SetSpeechSpeed      (void);\r
162 static void _CallBack            (ttsp_result_event_e eEvent, unsigned int const nPCMs, void * pPCMs, void* pUserParam);\r
163 static int _Synthesize_SamsungTTS(char const * const pszTextUtf8, void* pUserParam, int const FramePeriod);\r
164 \r
165 \r
166 \r
167 \r
168 char const * SLPSMT_GetPszKorean              (void) { return _pszKorean              ; }\r
169 char const * SLPSMT_GetPszUSEnglish           (void) { return _pszUSEnglish           ; }\r
170 char const * SLPSMT_GetPszChinese             (void) { return _pszChinese             ; }\r
171 char const * SLPSMT_GetPszUKEnglish           (void) { return _pszUKEnglish           ; }\r
172 char const * SLPSMT_GetPszGerman              (void) { return _pszGerman              ; }\r
173 char const * SLPSMT_GetPszSpanish             (void) { return _pszSpanish             ; }\r
174 char const * SLPSMT_GetPszFrench              (void) { return _pszFrench              ; }\r
175 char const * SLPSMT_GetPszItalian             (void) { return _pszItalian             ; }\r
176 \r
177 int          SLPSMT_GetWorkingThreadId(void) { return _g.ThreadId; }\r
178 \r
179 \r
180 \r
181 \r
182 int SLPSMT_StopSynthesis(void)\r
183 {\r
184   printf(">> SLPSMT_StopSynthesis()\n");\r
185   _g.bStop         = true;\r
186   _g.bSentenceDone = true;\r
187   _CleanThreadData();\r
188   return TTSP_ERROR_NONE;\r
189 }\r
190 \r
191 int SLPSMT_SynthesizeText(int const iVoiceInfo, char const * pszTextUtf8, void * const pUserParam)\r
192 {\r
193   if (! _g.pfnCallback)                { return TTSP_ERROR_INVALID_STATE; }\r
194   if (! pszTextUtf8 || ! *pszTextUtf8) { return TTSP_ERROR_INVALID_PARAMETER; }\r
195 \r
196   printf(">> SLPSMT_SynthesizeText()\n");\r
197   printf(">>>> iVoiceInfo  : %d\n", iVoiceInfo );\r
198   printf(">>>> pszTextUtf8 : %s\n", pszTextUtf8);\r
199 \r
200   _g.bStop = false;\r
201 \r
202   _PushThreadData(iVoiceInfo, pszTextUtf8, pUserParam);\r
203 \r
204   if (_g.ThreadId < 0)\r
205   {\r
206     _g.ThreadId = pthread_create(& _g.Thread, NULL, _Synthesize, pUserParam);\r
207     if (_g.ThreadId < 0)\r
208     {\r
209       printf(">>>  Fail to create thread\n");\r
210       return TTSP_ERROR_OPERATION_FAILED;\r
211     }\r
212   }\r
213   return TTSP_ERROR_NONE;\r
214 }\r
215 \r
216 \r
217 \r
218 \r
219 \r
220 \r
221 \r
222 ttspe_voice_info_s * _gpVoiceInfos  = NULL;\r
223 \r
224 int SLPSMT_SetVoiceList(ttspe_voice_list_s * p)\r
225 {\r
226   if (! _gpVoiceInfos)\r
227   {\r
228     unsigned int i;\r
229 \r
230     _gpVoiceInfos = (ttspe_voice_info_s*) calloc(_nVoiceInfos, sizeof(ttspe_voice_info_s));\r
231     if (! _gpVoiceInfos) { return TTSP_ERROR_OUT_OF_MEMORY; }\r
232 \r
233     for (i=0 ; i<_nVoiceInfos ; i++)\r
234     {\r
235       _gpVoiceInfos[i].lang   = strdup(_pVoiceInfos[i].pszLanguage);\r
236       _gpVoiceInfos[i].vctype =        _pVoiceInfos[i].eVoiceType  ;\r
237     }\r
238   }\r
239   p->voice_info = _gpVoiceInfos;\r
240   p->size       = _nVoiceInfos;\r
241   return TTSP_ERROR_NONE;\r
242 }\r
243 \r
244 void SLPSMT_SetSpeechSpeed(ttsp_speed_e const eSpeechSpeed)\r
245 {\r
246   switch (eSpeechSpeed)\r
247   {\r
248     case TTSP_SPEED_VERY_FAST :\r
249     case TTSP_SPEED_FAST      :\r
250     case TTSP_SPEED_SLOW      :\r
251     case TTSP_SPEED_VERY_SLOW :\r
252     case TTSP_SPEED_NORMAL    : _g.eSpeechSpeed = eSpeechSpeed;       break;\r
253     default                    : _g.eSpeechSpeed = TTSP_SPEED_NORMAL; break;\r
254   }\r
255 }\r
256 \r
257 int SLPSMT_GetiVoiceInfo(char* const pszLanguage, ttsp_voice_type_e const eVoiceType)\r
258 {\r
259   int i;\r
260   for (i=0 ; i<_nVoiceInfos ; i++)\r
261   {\r
262     if (             eVoiceType == _pVoiceInfos[i].eVoiceType\r
263         && ! strcmp(pszLanguage ,  _pVoiceInfos[i].pszLanguage)\r
264     )\r
265     {\r
266       return i;\r
267     }\r
268   }\r
269   return -1;\r
270 }\r
271 \r
272 int SLPSMT_Initialize(ttspe_result_cb pfnCallBack)\r
273 {\r
274   if (pfnCallBack)\r
275   {\r
276     _g.pfnCallback = pfnCallBack;\r
277     return TTSP_ERROR_NONE;\r
278   }\r
279   return TTSP_ERROR_INVALID_STATE;\r
280 }\r
281 \r
282 int SLPSMT_Finalize(void)\r
283 {\r
284   printf(">>>> SLPSMT_Finalize() called.\n");\r
285 \r
286   _g.bStop = true;\r
287   _CleanThreadData();\r
288 \r
289   pthread_mutex_lock  (& _g.MainThreadFinalizeLock);       // <---- lock\r
290   SMTFinalize();\r
291   pthread_mutex_unlock(& _g.MainThreadFinalizeLock);       // <---- unlock\r
292 \r
293   if (_gpVoiceInfos)\r
294   {\r
295     unsigned int i;\r
296     for (i=0 ; i<_nVoiceInfos ; i++)\r
297     {\r
298       if (_gpVoiceInfos[i].lang) { free(_gpVoiceInfos[i].lang); }\r
299     }\r
300     free(_gpVoiceInfos);\r
301   }\r
302 \r
303   _g.pfnCallback  = NULL;\r
304   _g.eSpeechSpeed = TTSP_SPEED_NORMAL;\r
305   _g.iVoiceInfo   = -1;\r
306   _g.ThreadId     = -1;\r
307 \r
308   printf(">>>> SLPSMT_Finalize() returns.\n");\r
309   return TTSP_ERROR_NONE;\r
310 }\r
311 \r
312 \r
313 \r
314 \r
315 static void _PushThreadData(int const iVoiceInfo, char const * pszTextUtf8, void* pUserParam)\r
316 // iVoiceInfo  should be correct.\r
317 // pszTextUtf8 should not be NULL.\r
318 {\r
319   bool   b = false;\r
320   char * pszDuplicatedTextUtf8;\r
321 \r
322   pthread_mutex_lock  (& _g.ThreadLock);       // <---- lock\r
323 \r
324   pszDuplicatedTextUtf8 = strdup(pszTextUtf8);\r
325   if (pszDuplicatedTextUtf8)\r
326   {\r
327     TypeThreadQueueNode* p = (TypeThreadQueueNode*) calloc (1, sizeof(TypeThreadQueueNode));\r
328     if (p)\r
329     {\r
330       p->iVoiceInfo  = iVoiceInfo;\r
331       p->pszTextUtf8 = pszDuplicatedTextUtf8;\r
332       p->pUserParam  = pUserParam;\r
333       if (! _g.ThreadQueue_pHead) { _g.ThreadQueue_pHead        = p; }\r
334       if (  _g.ThreadQueue_pTail) { _g.ThreadQueue_pTail->pNext = p; }\r
335       _g.ThreadQueue_pTail = p;\r
336       b = true;\r
337     }\r
338 \r
339     if (! b) { free(pszDuplicatedTextUtf8); }\r
340   }\r
341 \r
342   if (! b) { printf(">>>__PushThreadData, out of memory\n"); }\r
343 \r
344   pthread_mutex_unlock(& _g.ThreadLock);       // <---- unlock\r
345 }\r
346 \r
347 static TypeThreadQueueNode* _PopThreadData(void)\r
348 {\r
349   TypeThreadQueueNode* p;\r
350 \r
351   pthread_mutex_lock  (& _g.ThreadLock);       // <---- lock\r
352 \r
353   p = _g.ThreadQueue_pHead;\r
354   if (_g.ThreadQueue_pHead) { _g.ThreadQueue_pHead = _g.ThreadQueue_pHead->pNext; }\r
355   if (p == _g.ThreadQueue_pTail) { _g.ThreadQueue_pTail = NULL; }\r
356 \r
357   pthread_mutex_unlock(& _g.ThreadLock);       // <---- unlock\r
358 \r
359   return p;\r
360 }\r
361 \r
362 static bool _bEmptyThreadData(void)\r
363 {\r
364   bool b = true;\r
365   pthread_mutex_lock  (& _g.ThreadLock);       // <---- lock\r
366 \r
367   if (_g.ThreadQueue_pHead) { b = false; }\r
368 \r
369   pthread_mutex_unlock(& _g.ThreadLock);       // <---- unlock\r
370   return b;\r
371 }\r
372 \r
373 \r
374 static void _CleanThreadData(void)\r
375 {\r
376   pthread_mutex_lock  (& _g.ThreadLock);       // <---- lock\r
377 \r
378   while (_g.ThreadQueue_pHead)\r
379   {\r
380     TypeThreadQueueNode* const p = _g.ThreadQueue_pHead;\r
381     _g.ThreadQueue_pHead = p->pNext;\r
382     free(p->pszTextUtf8);\r
383     free(p);\r
384   }\r
385   _g.ThreadQueue_pHead = NULL;\r
386   _g.ThreadQueue_pTail = NULL;\r
387 \r
388   pthread_mutex_unlock(& _g.ThreadLock);       // <---- unlock\r
389 }\r
390 \r
391 static void * _Synthesize(void* NotUsed)\r
392 {\r
393   unsigned int const FramePeriod = (unsigned int) SMTGetFramePeriod();\r
394   TypeThreadQueueNode* p = _PopThreadData();\r
395 \r
396   for ( ; p ; p=_PopThreadData())\r
397   {\r
398     int  const   iVoiceInfo  = p->iVoiceInfo;\r
399     char const * pszTextUtf8 = p->pszTextUtf8;\r
400     void       * pUserParam  = p->pUserParam;\r
401 \r
402     if (_g.pfnCallback)\r
403     {\r
404       int r = SMT_SUCCESS;\r
405 \r
406       printf(">>>> Thread, _Synthesize(), iVoiceInfo = %d\n", iVoiceInfo);\r
407       printf(">>>>>> pszTextUtf8 = %s\n", pszTextUtf8);\r
408 \r
409       if (iVoiceInfo != _g.iVoiceInfo)\r
410       {\r
411         r = _ChangeVoice(iVoiceInfo);\r
412         printf(">>>>>> iVoiceInfo was changed.\n");\r
413       }\r
414 \r
415       if (r == SMT_SUCCESS)\r
416       {\r
417         _SetSpeechSpeed();\r
418 \r
419         printf(">>>>>> Set speech-speed\n");\r
420 \r
421         pthread_mutex_lock  (& _g.MainThreadFinalizeLock);       // <---- lock\r
422 \r
423         r = _Synthesize_SamsungTTS(pszTextUtf8, pUserParam, FramePeriod);\r
424 \r
425         pthread_mutex_unlock(& _g.MainThreadFinalizeLock);       // <---- unlock\r
426 \r
427       }\r
428       printf(">>>Thread, _Synthesize() done\n");\r
429     }\r
430 \r
431     free(p->pszTextUtf8);\r
432     free(p);\r
433   } // end of while loop\r
434 \r
435   _g.ThreadId = -1;\r
436   return (void*) 1;\r
437 }\r
438 \r
439 //\r
440 // END\r
441 //\r
442 // functions managing < Thread Queue >\r
443 //\r
444 \r
445 \r
446 \r
447 \r
448 \r
449 \r
450 \r
451 \r
452 //\r
453 // functions managing < Engine Switching >\r
454 //\r
455 // BEGIN\r
456 //\r
457 \r
458 static int _ChangeVoice(int const iVoiceInfo)\r
459 {\r
460   int          r;\r
461   bool         bSamsungTTS = false;\r
462   bool         bSvoxTTS    = false;\r
463   char const * pszLanguage = NULL;\r
464   char const * pszContury  = NULL;\r
465 \r
466    switch (iVoiceInfo)\r
467   {\r
468     case VOICE_INDEX_KOREAN_WOMAN               : SMTSet_Language(eKOREAN              ,  1, 0);                break;\r
469     case VOICE_INDEX_USENGLISH_WOMAN            : SMTSet_Language(eUSENGLISH           ,  1, 0);                        break;\r
470     case VOICE_INDEX_CHINESE_WOMAN              : SMTSet_Language(eCHINESE             ,  1, 0);                      break;\r
471 \r
472     case VOICE_INDEX_UKENGLISH_WOMAN            : SMTSet_Language(eGBENGLISH          ,  1, 0);                 break;\r
473     case VOICE_INDEX_GERMAN_WOMAN               : SMTSet_Language(eGERMAN              ,  1, 0);                        break;\r
474     case VOICE_INDEX_SPANISH_WOMAN              : SMTSet_Language(eSPANISH             ,  1, 0);                        break;\r
475     case VOICE_INDEX_FRENCH_WOMAN               : SMTSet_Language(eFRENCH              ,  1, 0);                        break;\r
476     case VOICE_INDEX_ITALIAN_WOMAN                      : SMTSet_Language(eITALIAN              ,  1, 0);                       break;\r
477 \r
478     default : break; // This case has already been checked.\r
479   }\r
480 \r
481   _g.iVoiceInfo = iVoiceInfo;\r
482 \r
483     SMTFinalize();\r
484     r = SMTInitialize();\r
485 \r
486   if (r != SMT_SUCCESS) { printf(">>>  _ChangeVoice() returns %d.\n", r); }\r
487 \r
488   return r;\r
489 }\r
490 \r
491 static void _SetSpeechSpeed(void)\r
492 {\r
493     switch (_g.eSpeechSpeed)\r
494     {\r
495       case TTSP_SPEED_VERY_FAST : SMTSetSpeechSpeed(eSMTSpeechSpeed_VeryFast);  break;\r
496       case TTSP_SPEED_FAST      : SMTSetSpeechSpeed(eSMTSpeechSpeed_Fast    );  break;\r
497       case TTSP_SPEED_SLOW      : SMTSetSpeechSpeed(eSMTSpeechSpeed_Slow    );  break;\r
498       case TTSP_SPEED_VERY_SLOW : SMTSetSpeechSpeed(eSMTSpeechSpeed_VerySlow);  break;\r
499       case TTSP_SPEED_NORMAL    : SMTSetSpeechSpeed(eSMTSpeechSpeed_Normal  );  break;\r
500     }\r
501 }\r
502 \r
503 static void _CallBack(ttsp_result_event_e eEvent, unsigned int const nPCMs, void * pPCMs, void* pUserParam)\r
504 {\r
505   unsigned int const n = nPCMs * sizeof(short);\r
506 \r
507 \r
508   printf(">>>  callback, pUserParam = 0x%x\n", (unsigned int) pUserParam);\r
509   printf(">>>  callback, event=");\r
510 \r
511   switch (eEvent)\r
512   {\r
513     case TTSP_RESULT_EVENT_CONTINUE :\r
514       if (_g.bSentenceDone)\r
515       {\r
516         eEvent = TTSP_RESULT_EVENT_START;\r
517         _g.bSentenceDone = false;\r
518       }\r
519       break;\r
520 \r
521     case TTSP_RESULT_EVENT_FINISH :\r
522       _g.bSentenceDone = true;\r
523       break;\r
524   }\r
525 \r
526 #if 1\r
527   if (nPCMs)\r
528   {\r
529     static int iWave = 0;\r
530     static char pszWave[100];\r
531 \r
532     printf("@@@ saving wave file @@@\n");\r
533     sprintf(pszWave, "/mnt/nfs/tts/play%d.wav", iWave++);\r
534     SMTSaveWave(pszWave, (short*) pPCMs, nPCMs * 2);\r
535   }\r
536 #endif\r
537 \r
538   switch (eEvent)\r
539   {\r
540     case TTSP_RESULT_EVENT_START   : printf("TTSPE_CBEVENT_SYNTH_START\n");     break;\r
541     case TTSP_RESULT_EVENT_CONTINUE: printf("TTSPE_CBEVENT_SYNTH_CONTINUE\n");  break;\r
542     case TTSP_RESULT_EVENT_FINISH  : printf("TTSPE_CBEVENT_SYNTH_FINISH\n");    break;\r
543     case TTSP_RESULT_EVENT_CANCEL  : printf("TTSPE_CBEVENT_SYNTH_CANCEL\n");    break;\r
544     case TTSP_RESULT_EVENT_FAIL    : printf("TTSPE_CBEVENT_SYNTH_FAIL\n");      break;\r
545     default                          : printf("invalid\n");                       break;\r
546   }\r
547 \r
548   if (eEvent==TTSP_RESULT_EVENT_FINISH && ! _bEmptyThreadData())\r
549   {\r
550     printf(">>> There is another input text.\n");\r
551     printf(">>> TTSPE_CBEVENT_SYNTH_FINISH was chanage into TTSPE_CBEVENT_SYNTH_CONTINUE.\n");\r
552     eEvent = TTSP_RESULT_EVENT_CONTINUE;\r
553   }\r
554 \r
555   printf(">>> data size = %d\n", n);\r
556   printf(">> >> Here we jump into the callback function.\n");\r
557 \r
558   int const cbreturn = _g.pfnCallback(eEvent, pPCMs, n, pUserParam);\r
559   printf(">> >> Here we return from the callback function.\n");\r
560   printf(">> >> callback function return value = %d\n", cbreturn);\r
561   if (-1 == cbreturn)\r
562   {\r
563     printf(">>> Callback function returns TTS_CALLBACK_HALT.\n");\r
564     _g.bStop         = true;\r
565     _g.bSentenceDone = true;\r
566   }\r
567 }\r
568 \r
569 static int _Synthesize_SamsungTTS(char const * const pszTextUtf8, void* pUserParam, int const FramePeriod)\r
570 {\r
571   static short pPcmBuffer[PCM_BUFFER_SIZE];\r
572 \r
573   int          r = SMTInputText(pszTextUtf8);\r
574   unsigned int i = 0;\r
575 \r
576   if (r != SMT_SUCCESS)\r
577   {\r
578     _CleanThreadData();\r
579     printf(">>>  SMTInputText() returns %d.\n", r);\r
580   }\r
581 \r
582 \r
583   while (r == SMT_SUCCESS)\r
584   {\r
585     r = SMTSynthesize(& pPcmBuffer[i]);\r
586     if (_g.bStop)\r
587     {\r
588       _CleanThreadData();\r
589       _CallBack(TTSP_RESULT_EVENT_CANCEL, i, pPcmBuffer, pUserParam);\r
590       break;\r
591     }\r
592     else\r
593     {\r
594       switch (r)\r
595       {\r
596         case SMT_SYNTHESIS_FRAME_GENERATED:\r
597           if (i + FramePeriod == PCM_BUFFER_SIZE)\r
598           {\r
599             _CallBack(TTSP_RESULT_EVENT_CONTINUE, PCM_BUFFER_SIZE, pPcmBuffer, pUserParam);\r
600             i = 0;\r
601           }\r
602           else\r
603           {\r
604             i += FramePeriod;\r
605           }\r
606           break;\r
607 \r
608         case SMT_SYNTHESIS_PAUSE_DONE    :\r
609         case SMT_SYNTHESIS_SENTENCE_DONE :\r
610           r = SMT_SUCCESS;\r
611           break;\r
612 \r
613         case SMT_SYNTHESIS_ALL_DONE :\r
614           _CallBack(TTSP_RESULT_EVENT_FINISH, i, pPcmBuffer, pUserParam);\r
615           break;\r
616 \r
617         default :\r
618           _CleanThreadData();\r
619 \r
620           printf(">>>  SMTSynthesize() returns %d\n", r);\r
621 \r
622           _CallBack(TTSP_RESULT_EVENT_FAIL, i, pPcmBuffer, pUserParam);\r
623           break;\r
624       }\r
625     }\r
626 \r
627   } // end of while loop\r
628 \r
629   return r;\r
630 }\r
631 \r
632 //\r
633 // END\r
634 //\r
635 // functions managing < Engine Switching >\r
636 //\r