eSpeak NG is an open source speech synthesizer that supports more than hundred languages and accents.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

speak_lib.cpp 27KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108
  1. /***************************************************************************
  2. * Copyright (C) 2005 to 2007 by Jonathan Duddington *
  3. * email: [email protected] *
  4. * *
  5. * This program is free software; you can redistribute it and/or modify *
  6. * it under the terms of the GNU General Public License as published by *
  7. * the Free Software Foundation; either version 3 of the License, or *
  8. * (at your option) any later version. *
  9. * *
  10. * This program is distributed in the hope that it will be useful, *
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  13. * GNU General Public License for more details. *
  14. * *
  15. * You should have received a copy of the GNU General Public License *
  16. * along with this program; if not, write see: *
  17. * <http://www.gnu.org/licenses/>. *
  18. ***************************************************************************/
  19. #include "StdAfx.h"
  20. #include "stdio.h"
  21. #include "ctype.h"
  22. #include "string.h"
  23. #include "stdlib.h"
  24. #include "wchar.h"
  25. #include "locale.h"
  26. #include <assert.h>
  27. #include <time.h>
  28. #include "speech.h"
  29. #include "sys/stat.h"
  30. #ifndef PLATFORM_WINDOWS
  31. #include <unistd.h>
  32. #endif
  33. #include "speak_lib.h"
  34. #include "voice.h"
  35. #include "phoneme.h"
  36. #include "synthesize.h"
  37. #include "translate.h"
  38. #include "debug.h"
  39. #include "fifo.h"
  40. #include "event.h"
  41. #include "wave.h"
  42. unsigned char *outbuf=NULL;
  43. extern espeak_VOICE *voice_selected;
  44. espeak_EVENT *event_list=NULL;
  45. int event_list_ix=0;
  46. int n_event_list;
  47. long count_samples;
  48. void* my_audio=NULL;
  49. static unsigned int my_unique_identifier=0;
  50. static void* my_user_data=NULL;
  51. static espeak_AUDIO_OUTPUT my_mode=AUDIO_OUTPUT_SYNCHRONOUS;
  52. static int synchronous_mode = 1;
  53. t_espeak_callback* synth_callback = NULL;
  54. int (* uri_callback)(int, const char *, const char *) = NULL;
  55. char path_home[120];
  56. voice_t voicedata;
  57. voice_t *voice = &voicedata;
  58. #ifdef USE_ASYNC
  59. static int dispatch_audio(short* outbuf, int length, espeak_EVENT* event)
  60. {//======================================================================
  61. ENTER("dispatch_audio");
  62. int a_wave_can_be_played = fifo_is_command_enabled();
  63. SHOW("*** dispatch_audio > uid=%d, [write=%p (%d bytes)], sample=%d, a_wave_can_be_played = %d\n",
  64. (event) ? event->unique_identifier : 0, wave_test_get_write_buffer(), 2*length,
  65. (event) ? event->sample : 0,
  66. a_wave_can_be_played);
  67. switch(my_mode)
  68. {
  69. case AUDIO_OUTPUT_PLAYBACK:
  70. {
  71. if (outbuf && length && a_wave_can_be_played)
  72. {
  73. wave_write (my_audio, (char*)outbuf, 2*length);
  74. }
  75. while(a_wave_can_be_played) {
  76. // TBD: some event are filtered here but some insight might be given
  77. // TBD: in synthesise.cpp for avoiding to create WORDs with size=0.
  78. // TBD: For example sentence "or ALT)." returns three words
  79. // "or", "ALT" and "".
  80. // TBD: the last one has its size=0.
  81. if (event && (event->type == espeakEVENT_WORD) && (event->length==0))
  82. {
  83. break;
  84. }
  85. espeak_ERROR a_error = event_declare(event);
  86. if (a_error != EE_BUFFER_FULL)
  87. {
  88. break;
  89. }
  90. SHOW_TIME("dispatch_audio > EE_BUFFER_FULL\n");
  91. usleep(10000);
  92. a_wave_can_be_played = fifo_is_command_enabled();
  93. }
  94. }
  95. break;
  96. case AUDIO_OUTPUT_RETRIEVAL:
  97. if (synth_callback)
  98. {
  99. synth_callback(outbuf, length, event);
  100. }
  101. break;
  102. case AUDIO_OUTPUT_SYNCHRONOUS:
  103. case AUDIO_OUTPUT_SYNCH_PLAYBACK:
  104. break;
  105. }
  106. if (!a_wave_can_be_played)
  107. {
  108. SHOW_TIME("dispatch_audio > synth must be stopped!\n");
  109. }
  110. SHOW_TIME("LEAVE dispatch_audio\n");
  111. return (a_wave_can_be_played==0); // 1 = stop synthesis
  112. }
  113. static int create_events(short* outbuf, int length, espeak_EVENT* event, uint32_t the_write_pos)
  114. {//=====================================================================
  115. int finished;
  116. int i=0;
  117. // The audio data are written to the output device.
  118. // The list of events in event_list (index: event_list_ix) is read:
  119. // Each event is declared to the "event" object which stores them internally.
  120. // The event object is responsible of calling the external callback
  121. // as soon as the relevant audio sample is played.
  122. do
  123. { // for each event
  124. espeak_EVENT* event;
  125. if (event_list_ix == 0)
  126. {
  127. event = NULL;
  128. }
  129. else
  130. {
  131. event = event_list + i;
  132. SHOW("Synthesize: event->sample(%d) + %d = %d\n", event->sample, the_write_pos, event->sample + the_write_pos);
  133. event->sample += the_write_pos;
  134. }
  135. SHOW("*** Synthesize: i=%d (event_list_ix=%d), length=%d\n",i,event_list_ix,length);
  136. finished = dispatch_audio((short *)outbuf, length, event);
  137. length = 0; // the wave data are played once.
  138. i++;
  139. } while((i < event_list_ix) && !finished);
  140. return finished;
  141. }
  142. int sync_espeak_terminated_msg( uint unique_identifier, void* user_data)
  143. {//=====================================================================
  144. ENTER("sync_espeak_terminated_msg");
  145. int finished=0;
  146. memset(event_list, 0, 2*sizeof(espeak_EVENT));
  147. event_list[0].type = espeakEVENT_MSG_TERMINATED;
  148. event_list[0].unique_identifier = unique_identifier;
  149. event_list[0].user_data = user_data;
  150. event_list[1].type = espeakEVENT_LIST_TERMINATED;
  151. if (my_mode==AUDIO_OUTPUT_PLAYBACK)
  152. {
  153. while(1)
  154. {
  155. espeak_ERROR a_error = event_declare(event_list);
  156. if (a_error != EE_BUFFER_FULL)
  157. {
  158. break;
  159. }
  160. SHOW_TIME("sync_espeak_terminated_msg > EE_BUFFER_FULL\n");
  161. usleep(10000);
  162. }
  163. }
  164. else
  165. {
  166. if (synth_callback)
  167. {
  168. finished=synth_callback(NULL,0,event_list);
  169. }
  170. }
  171. return finished;
  172. }
  173. #endif
  174. static void select_output(espeak_AUDIO_OUTPUT output_type)
  175. {//=======================================================
  176. my_mode = output_type;
  177. my_audio = NULL;
  178. synchronous_mode = 1;
  179. option_waveout = 1; // inhibit portaudio callback from wavegen.cpp
  180. switch(my_mode)
  181. {
  182. case AUDIO_OUTPUT_PLAYBACK:
  183. synchronous_mode = 0;
  184. #ifdef USE_ASYNC
  185. wave_init();
  186. wave_set_callback_is_output_enabled( fifo_is_command_enabled);
  187. my_audio = wave_open("alsa");
  188. event_init();
  189. #endif
  190. break;
  191. case AUDIO_OUTPUT_RETRIEVAL:
  192. synchronous_mode = 0;
  193. break;
  194. case AUDIO_OUTPUT_SYNCHRONOUS:
  195. break;
  196. case AUDIO_OUTPUT_SYNCH_PLAYBACK:
  197. option_waveout = 0;
  198. WavegenInitSound();
  199. break;
  200. }
  201. } // end of select_output
  202. int GetFileLength(const char *filename)
  203. {//====================================
  204. struct stat statbuf;
  205. if(stat(filename,&statbuf) != 0)
  206. return(0);
  207. if((statbuf.st_mode & S_IFMT) == S_IFDIR)
  208. // if(S_ISDIR(statbuf.st_mode))
  209. return(-2); // a directory
  210. return(statbuf.st_size);
  211. } // end of GetFileLength
  212. char *Alloc(int size)
  213. {//==================
  214. char *p;
  215. if((p = (char *)malloc(size)) == NULL)
  216. fprintf(stderr,"Can't allocate memory\n");
  217. return(p);
  218. }
  219. void Free(void *ptr)
  220. {//=================
  221. if(ptr != NULL)
  222. free(ptr);
  223. }
  224. static void init_path(const char *path)
  225. {//====================================
  226. #ifdef PLATFORM_WINDOWS
  227. HKEY RegKey;
  228. unsigned long size;
  229. unsigned long var_type;
  230. char *env;
  231. unsigned char buf[100];
  232. if(path != NULL)
  233. {
  234. sprintf(path_home,"%s/espeak-data",path);
  235. return;
  236. }
  237. if((env = getenv("ESPEAK_DATA_PATH")) != NULL)
  238. {
  239. sprintf(path_home,"%s/espeak-data",env);
  240. if(GetFileLength(path_home) == -2)
  241. return; // an espeak-data directory exists
  242. }
  243. buf[0] = 0;
  244. RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Speech\\Voices\\Tokens\\eSpeak", 0, KEY_READ, &RegKey);
  245. size = sizeof(buf);
  246. var_type = REG_SZ;
  247. RegQueryValueEx(RegKey, "path", 0, &var_type, buf, &size);
  248. sprintf(path_home,"%s\\espeak-data",buf);
  249. #else
  250. char *env;
  251. if(path != NULL)
  252. {
  253. snprintf(path_home,sizeof(path_home),"%s/espeak-data",path);
  254. return;
  255. }
  256. // if((env = getenv("ESPEAK_DATA_PATH")) != NULL)
  257. // {
  258. // snprintf(path_home,sizeof(path_home),"%s/espeak-data",env);
  259. // if(GetFileLength(path_home) == -2)
  260. // return; // an espeak-data directory exists
  261. // }
  262. snprintf(path_home,sizeof(path_home),"%s/espeak-data",getenv("HOME"));
  263. if(access(path_home,R_OK) != 0)
  264. {
  265. strcpy(path_home,PATH_ESPEAK_DATA);
  266. }
  267. #endif
  268. }
  269. static int initialise(void)
  270. {//========================
  271. int param;
  272. int result;
  273. #ifndef __WIN32__
  274. LoadConfig(); // causes problem on Windows, don't know why
  275. #endif
  276. WavegenInit(22050,0); // 22050
  277. if((result = LoadPhData()) != 1)
  278. {
  279. if(result == -1)
  280. fprintf(stderr,"Failed to load espeak-data\n");
  281. else
  282. fprintf(stderr,"Wrong version of espeak-data 0x%x (expects 0x%x)\n",result,version_phdata);
  283. }
  284. voice_selected = NULL;
  285. SynthesizeInit();
  286. InitNamedata();
  287. for(param=0; param<N_SPEECH_PARAM; param++)
  288. param_stack[0].parameter[param] = param_defaults[param];
  289. return(0);
  290. }
  291. static espeak_ERROR Synthesize(unsigned int unique_identifier, const void *text, int flags)
  292. {//========================================================================================
  293. // Fill the buffer with output sound
  294. ENTER("Synthesize");
  295. int length;
  296. int finished = 0;
  297. int count_buffers = 0;
  298. uint32_t a_write_pos=0;
  299. #ifdef DEBUG_ENABLED
  300. if (text)
  301. {
  302. SHOW("Synthesize > uid=%d, flags=%d, >>>text=%s<<<\n", unique_identifier, flags, text);
  303. }
  304. #endif
  305. if((outbuf==NULL) || (event_list==NULL))
  306. return(EE_INTERNAL_ERROR); // espeak_Initialize() has not been called
  307. option_multibyte = flags & 7;
  308. option_ssml = flags & espeakSSML;
  309. option_phoneme_input = flags & espeakPHONEMES;
  310. option_endpause = flags & espeakENDPAUSE;
  311. count_samples = 0;
  312. #ifdef USE_ASYNC
  313. if(my_mode == AUDIO_OUTPUT_PLAYBACK)
  314. {
  315. a_write_pos = wave_get_write_position(my_audio);
  316. }
  317. #endif
  318. if(translator == NULL)
  319. {
  320. SetVoiceByName("default");
  321. }
  322. SpeakNextClause(NULL,text,0);
  323. if(my_mode == AUDIO_OUTPUT_SYNCH_PLAYBACK)
  324. {
  325. for(;;)
  326. {
  327. #ifdef PLATFORM_WINDOWS
  328. Sleep(300); // 0.3s
  329. #else
  330. #ifdef USE_NANOSLEEP
  331. struct timespec period;
  332. struct timespec remaining;
  333. period.tv_sec = 0;
  334. period.tv_nsec = 300000000; // 0.3 sec
  335. nanosleep(&period,&remaining);
  336. #else
  337. sleep(1);
  338. #endif
  339. #endif
  340. if(SynthOnTimer() != 0)
  341. break;
  342. }
  343. return(EE_OK);
  344. }
  345. for(;;)
  346. {
  347. SHOW("Synthesize > %s\n","for (next)");
  348. out_ptr = outbuf;
  349. out_end = &outbuf[outbuf_size];
  350. event_list_ix = 0;
  351. WavegenFill(0);
  352. length = (out_ptr - outbuf)/2;
  353. count_samples += length;
  354. event_list[event_list_ix].type = espeakEVENT_LIST_TERMINATED; // indicates end of event list
  355. count_buffers++;
  356. if (my_mode==AUDIO_OUTPUT_PLAYBACK)
  357. {
  358. #ifdef USE_ASYNC
  359. finished = create_events((short *)outbuf, length, event_list, a_write_pos);
  360. length = 0; // the wave data are played once.
  361. #endif
  362. }
  363. else
  364. {
  365. finished = synth_callback((short *)outbuf, length, event_list);
  366. }
  367. if(finished)
  368. {
  369. SpeakNextClause(NULL,0,2); // stop
  370. break;
  371. }
  372. if(Generate(phoneme_list,&n_phoneme_list,1)==0)
  373. {
  374. if(WcmdqUsed() == 0)
  375. {
  376. // don't process the next clause until the previous clause has finished generating speech.
  377. // This ensures that <audio> tag (which causes end-of-clause) is at a sound buffer boundary
  378. event_list[0].type = espeakEVENT_LIST_TERMINATED;
  379. if(SpeakNextClause(NULL,NULL,1)==0)
  380. {
  381. #ifdef USE_ASYNC
  382. if (my_mode==AUDIO_OUTPUT_PLAYBACK)
  383. {
  384. dispatch_audio(NULL, 0, NULL); // TBD: test case
  385. }
  386. else
  387. {
  388. synth_callback(NULL, 0, event_list); // NULL buffer ptr indicates end of data
  389. }
  390. #else
  391. synth_callback(NULL, 0, event_list); // NULL buffer ptr indicates end of data
  392. #endif
  393. break;
  394. }
  395. }
  396. }
  397. }
  398. return(EE_OK);
  399. } // end of Synthesize
  400. #ifdef DEBUG_ENABLED
  401. static const char* label[] = {
  402. "END_OF_EVENT_LIST",
  403. "WORD",
  404. "SENTENCE",
  405. "MARK",
  406. "PLAY",
  407. "END"};
  408. #endif
  409. void MarkerEvent(int type, unsigned int char_position, int value, unsigned char *out_ptr)
  410. {//======================================================================================
  411. // type: 1=word, 2=sentence, 3=named mark, 4=play audio, 5=end
  412. ENTER("MarkerEvent");
  413. espeak_EVENT *ep;
  414. double time;
  415. if((event_list == NULL) || (event_list_ix >= (n_event_list-2)))
  416. return;
  417. ep = &event_list[event_list_ix++];
  418. ep->type = (espeak_EVENT_TYPE)type;
  419. ep->unique_identifier = my_unique_identifier;
  420. ep->user_data = my_user_data;
  421. ep->text_position = char_position & 0xffff;
  422. ep->length = char_position >> 24;
  423. time = (double(count_samples + (out_ptr - out_start)/2)*1000.0)/samplerate;
  424. ep->audio_position = int(time);
  425. ep->sample = (count_samples + (out_ptr - out_start)/2);
  426. SHOW("MarkerEvent > count_samples=%d, out_ptr=%x, out_start=0x%x\n",count_samples, out_ptr, out_start);
  427. SHOW("*** MarkerEvent > type=%s, uid=%d, text_pos=%d, length=%d, audio_position=%d, sample=%d\n",
  428. label[ep->type], ep->unique_identifier, ep->text_position, ep->length,
  429. ep->audio_position, ep->sample);
  430. if((type == espeakEVENT_MARK) || (type == espeakEVENT_PLAY))
  431. ep->id.name = &namedata[value];
  432. else
  433. ep->id.number = value;
  434. } // end of MarkerEvent
  435. espeak_ERROR sync_espeak_Synth(unsigned int unique_identifier, const void *text, size_t size,
  436. unsigned int position, espeak_POSITION_TYPE position_type,
  437. unsigned int end_position, unsigned int flags, void* user_data)
  438. {//===========================================================================
  439. ENTER("sync_espeak_Synth");
  440. SHOW("sync_espeak_Synth > position=%d, position_type=%d, end_position=%d, flags=%d, user_data=0x%x, text=%s\n", position, position_type, end_position, flags, user_data, text);
  441. espeak_ERROR aStatus;
  442. InitText(flags);
  443. my_unique_identifier = unique_identifier;
  444. my_user_data = user_data;
  445. switch(position_type)
  446. {
  447. case POS_CHARACTER:
  448. skip_characters = position;
  449. break;
  450. case POS_WORD:
  451. skip_words = position;
  452. break;
  453. case POS_SENTENCE:
  454. skip_sentences = position;
  455. break;
  456. }
  457. if(skip_characters || skip_words || skip_sentences)
  458. skipping_text = 1;
  459. end_character_position = end_position;
  460. aStatus = Synthesize(unique_identifier, text, flags);
  461. #ifdef USE_ASYNC
  462. wave_flush(my_audio);
  463. #endif
  464. SHOW_TIME("LEAVE sync_espeak_Synth");
  465. return aStatus;
  466. } // end of sync_espeak_Synth
  467. espeak_ERROR sync_espeak_Synth_Mark(unsigned int unique_identifier, const void *text, size_t size,
  468. const char *index_mark, unsigned int end_position,
  469. unsigned int flags, void* user_data)
  470. {//=========================================================================
  471. espeak_ERROR aStatus;
  472. InitText(flags);
  473. my_unique_identifier = unique_identifier;
  474. my_user_data = user_data;
  475. if(index_mark != NULL)
  476. {
  477. strncpy0(skip_marker, index_mark, sizeof(skip_marker));
  478. skipping_text = 1;
  479. }
  480. end_character_position = end_position;
  481. aStatus = Synthesize(unique_identifier, text, flags | espeakSSML);
  482. SHOW_TIME("LEAVE sync_espeak_Synth_Mark");
  483. return (aStatus);
  484. } // end of sync_espeak_Synth_Mark
  485. void sync_espeak_Key(const char *key)
  486. {//==================================
  487. // symbolic name, symbolicname_character - is there a system resource of symbolic names per language?
  488. my_unique_identifier = 0;
  489. my_user_data = NULL;
  490. Synthesize(0, key,0); // for now, just say the key name as passed
  491. }
  492. void sync_espeak_Char(wchar_t character)
  493. {//=====================================
  494. // is there a system resource of character names per language?
  495. char buf[80];
  496. my_unique_identifier = 0;
  497. my_user_data = NULL;
  498. sprintf(buf,"<say-as interpret-as=\"tts:char\">&#%d;</say-as>",character);
  499. Synthesize(0, buf,espeakSSML);
  500. }
  501. void sync_espeak_SetPunctuationList(const wchar_t *punctlist)
  502. {//==========================================================
  503. // Set the list of punctuation which are spoken for "some".
  504. my_unique_identifier = 0;
  505. my_user_data = NULL;
  506. wcsncpy(option_punctlist, punctlist, N_PUNCTLIST);
  507. option_punctlist[N_PUNCTLIST-1] = 0;
  508. } // end of sync_espeak_SetPunctuationList
  509. #pragma GCC visibility push(default)
  510. ESPEAK_API void espeak_SetSynthCallback(t_espeak_callback* SynthCallback)
  511. {//======================================================================
  512. ENTER("espeak_SetSynthCallback");
  513. synth_callback = SynthCallback;
  514. #ifdef USE_ASYNC
  515. event_set_callback(synth_callback);
  516. #endif
  517. }
  518. ESPEAK_API void espeak_SetUriCallback(int (* UriCallback)(int, const char*, const char *))
  519. {//=======================================================================================
  520. ENTER("espeak_SetUriCallback");
  521. uri_callback = UriCallback;
  522. }
  523. ESPEAK_API int espeak_Initialize(espeak_AUDIO_OUTPUT output_type, int buf_length, const char *path, int options)
  524. {//=============================================================================================================
  525. ENTER("espeak_Initialize");
  526. int param;
  527. // It seems that the wctype functions don't work until the locale has been set
  528. // to something other than the default "C". Then, not only Latin1 but also the
  529. // other characters give the correct results with iswalpha() etc.
  530. #ifdef PLATFORM_RISCOS
  531. setlocale(LC_CTYPE,"ISO8859-1");
  532. #else
  533. if(setlocale(LC_CTYPE,"en_US.UTF-8") == NULL)
  534. {
  535. if(setlocale(LC_CTYPE,"UTF-8") == NULL)
  536. setlocale(LC_CTYPE,"");
  537. }
  538. #endif
  539. init_path(path);
  540. initialise();
  541. select_output(output_type);
  542. // buflength is in mS, allocate 2 bytes per sample
  543. if(buf_length == 0)
  544. buf_length = 200;
  545. outbuf_size = (buf_length * samplerate)/500;
  546. outbuf = (unsigned char*)realloc(outbuf,outbuf_size);
  547. if((out_start = outbuf) == NULL)
  548. return(EE_INTERNAL_ERROR);
  549. // allocate space for event list. Allow 200 events per second
  550. n_event_list = (buf_length*200)/1000;
  551. if((event_list = (espeak_EVENT *)realloc(event_list,sizeof(espeak_EVENT) * n_event_list)) == NULL)
  552. return(EE_INTERNAL_ERROR);
  553. option_phonemes = 0;
  554. option_phoneme_events = (options & 1);
  555. SetVoiceByName("default");
  556. for(param=0; param<N_SPEECH_PARAM; param++)
  557. param_stack[0].parameter[param] = param_defaults[param];
  558. SetParameter(espeakRATE,170,0);
  559. SetParameter(espeakVOLUME,100,0);
  560. SetParameter(espeakCAPITALS,option_capitals,0);
  561. SetParameter(espeakPUNCTUATION,option_punctuation,0);
  562. WavegenSetVoice(voice);
  563. #ifdef USE_ASYNC
  564. fifo_init();
  565. #endif
  566. return(samplerate);
  567. }
  568. ESPEAK_API espeak_ERROR espeak_Synth(const void *text, size_t size,
  569. unsigned int position,
  570. espeak_POSITION_TYPE position_type,
  571. unsigned int end_position, unsigned int flags,
  572. unsigned int* unique_identifier, void* user_data)
  573. {//=====================================================================================
  574. ENTER("espeak_Synth");
  575. SHOW("espeak_Synth > position=%d, position_type=%d, end_position=%d, flags=%d, user_data=0x%x, text=%s\n", position, position_type, end_position, flags, user_data, text);
  576. espeak_ERROR a_error=EE_INTERNAL_ERROR;
  577. static unsigned int temp_identifier;
  578. if (unique_identifier == NULL)
  579. {
  580. unique_identifier = &temp_identifier;
  581. }
  582. *unique_identifier = 0;
  583. if(synchronous_mode)
  584. {
  585. return(sync_espeak_Synth(0,text,size,position,position_type,end_position,flags,user_data));
  586. }
  587. #ifdef USE_ASYNC
  588. // Create the text command
  589. t_espeak_command* c1 = create_espeak_text(text, size, position, position_type, end_position, flags, user_data);
  590. // Retrieve the unique identifier
  591. *unique_identifier = c1->u.my_text.unique_identifier;
  592. // Create the "terminated msg" command (same uid)
  593. t_espeak_command* c2 = create_espeak_terminated_msg(*unique_identifier, user_data);
  594. // Try to add these 2 commands (single transaction)
  595. if (c1 && c2)
  596. {
  597. a_error = fifo_add_commands(c1, c2);
  598. if (a_error != EE_OK)
  599. {
  600. delete_espeak_command(c1);
  601. delete_espeak_command(c2);
  602. c1=c2=NULL;
  603. }
  604. }
  605. else
  606. {
  607. delete_espeak_command(c1);
  608. delete_espeak_command(c2);
  609. }
  610. #endif
  611. return a_error;
  612. } // end of espeak_Synth
  613. ESPEAK_API espeak_ERROR espeak_Synth_Mark(const void *text, size_t size,
  614. const char *index_mark,
  615. unsigned int end_position,
  616. unsigned int flags,
  617. unsigned int* unique_identifier,
  618. void* user_data)
  619. {//=========================================================================
  620. ENTER("espeak_Synth_Mark");
  621. SHOW("espeak_Synth_Mark > index_mark=%s, end_position=%d, flags=%d, text=%s\n", index_mark, end_position, flags, text);
  622. espeak_ERROR a_error=EE_OK;
  623. static unsigned int temp_identifier;
  624. if (unique_identifier == NULL)
  625. {
  626. unique_identifier = &temp_identifier;
  627. }
  628. *unique_identifier = 0;
  629. if(synchronous_mode)
  630. {
  631. return(sync_espeak_Synth_Mark(0,text,size,index_mark,end_position,flags,user_data));
  632. }
  633. #ifdef USE_ASYNC
  634. // Create the mark command
  635. t_espeak_command* c1 = create_espeak_mark(text, size, index_mark, end_position,
  636. flags, user_data);
  637. // Retrieve the unique identifier
  638. *unique_identifier = c1->u.my_mark.unique_identifier;
  639. // Create the "terminated msg" command (same uid)
  640. t_espeak_command* c2 = create_espeak_terminated_msg(*unique_identifier, user_data);
  641. // Try to add these 2 commands (single transaction)
  642. if (c1 && c2)
  643. {
  644. a_error = fifo_add_commands(c1, c2);
  645. if (a_error != EE_OK)
  646. {
  647. delete_espeak_command(c1);
  648. delete_espeak_command(c2);
  649. c1=c2=NULL;
  650. }
  651. }
  652. else
  653. {
  654. delete_espeak_command(c1);
  655. delete_espeak_command(c2);
  656. }
  657. #endif
  658. return a_error;
  659. } // end of espeak_Synth_Mark
  660. ESPEAK_API espeak_ERROR espeak_Key(const char *key)
  661. {//================================================
  662. ENTER("espeak_Key");
  663. // symbolic name, symbolicname_character - is there a system resource of symbolicnames per language
  664. espeak_ERROR a_error = EE_OK;
  665. if(synchronous_mode)
  666. {
  667. sync_espeak_Key(key);
  668. return(EE_OK);
  669. }
  670. #ifdef USE_ASYNC
  671. t_espeak_command* c = create_espeak_key( key);
  672. a_error = fifo_add_command(c);
  673. if (a_error != EE_OK)
  674. {
  675. delete_espeak_command(c);
  676. }
  677. #endif
  678. return a_error;
  679. }
  680. ESPEAK_API espeak_ERROR espeak_Char(wchar_t character)
  681. {//===========================================
  682. ENTER("espeak_Char");
  683. // is there a system resource of character names per language?
  684. #ifdef USE_ASYNC
  685. espeak_ERROR a_error;
  686. if(synchronous_mode)
  687. {
  688. sync_espeak_Char(character);
  689. return(EE_OK);
  690. }
  691. t_espeak_command* c = create_espeak_char( character);
  692. a_error = fifo_add_command(c);
  693. if (a_error != EE_OK)
  694. {
  695. delete_espeak_command(c);
  696. }
  697. return a_error;
  698. #else
  699. sync_espeak_Char(character);
  700. return(EE_OK);
  701. #endif
  702. }
  703. ESPEAK_API espeak_ERROR espeak_SetVoiceByName(const char *name)
  704. {//===================================================
  705. ENTER("espeak_SetVoiceByName");
  706. #ifdef USE_ASYNC
  707. espeak_ERROR a_error;
  708. if(synchronous_mode)
  709. {
  710. return(SetVoiceByName(name));
  711. }
  712. t_espeak_command* c = create_espeak_voice_name(name);
  713. a_error = fifo_add_command(c);
  714. if (a_error != EE_OK)
  715. {
  716. delete_espeak_command(c);
  717. }
  718. return a_error;
  719. #else
  720. return(SetVoiceByName(name));
  721. #endif
  722. } // end of espeak_SetVoiceByName
  723. ESPEAK_API espeak_ERROR espeak_SetVoiceByProperties(espeak_VOICE *voice_selector)
  724. {//=====================================================================
  725. ENTER("espeak_SetVoiceByProperties");
  726. #ifdef USE_ASYNC
  727. espeak_ERROR a_error;
  728. if(synchronous_mode)
  729. {
  730. return(SetVoiceByProperties(voice_selector));
  731. }
  732. t_espeak_command* c = create_espeak_voice_spec( voice_selector);
  733. a_error = fifo_add_command(c);
  734. if (a_error != EE_OK)
  735. {
  736. delete_espeak_command(c);
  737. }
  738. return a_error;
  739. #else
  740. return(SetVoiceByProperties(voice_selector));
  741. #endif
  742. } // end of espeak_SetVoiceByProperties
  743. ESPEAK_API int espeak_GetParameter(espeak_PARAMETER parameter, int current)
  744. {//========================================================================
  745. ENTER("espeak_GetParameter");
  746. // current: 0=default value, 1=current value
  747. if(current)
  748. {
  749. return(param_stack[0].parameter[parameter]);
  750. }
  751. else
  752. {
  753. return(param_defaults[parameter]);
  754. }
  755. } // end of espeak_GetParameter
  756. ESPEAK_API espeak_ERROR espeak_SetParameter(espeak_PARAMETER parameter, int value, int relative)
  757. {//=============================================================================================
  758. ENTER("espeak_SetParameter");
  759. #ifdef USE_ASYNC
  760. espeak_ERROR a_error;
  761. if(synchronous_mode)
  762. {
  763. SetParameter(parameter,value,relative);
  764. return(EE_OK);
  765. }
  766. t_espeak_command* c = create_espeak_parameter(parameter, value, relative);
  767. a_error = fifo_add_command(c);
  768. if (a_error != EE_OK)
  769. {
  770. delete_espeak_command(c);
  771. }
  772. return a_error;
  773. #else
  774. SetParameter(parameter,value,relative);
  775. return(EE_OK);
  776. #endif
  777. }
  778. ESPEAK_API espeak_ERROR espeak_SetPunctuationList(const wchar_t *punctlist)
  779. {//================================================================
  780. ENTER("espeak_SetPunctuationList");
  781. // Set the list of punctuation which are spoken for "some".
  782. #ifdef USE_ASYNC
  783. espeak_ERROR a_error;
  784. if(synchronous_mode)
  785. {
  786. sync_espeak_SetPunctuationList(punctlist);
  787. return(EE_OK);
  788. }
  789. t_espeak_command* c = create_espeak_punctuation_list( punctlist);
  790. a_error = fifo_add_command(c);
  791. if (a_error != EE_OK)
  792. {
  793. delete_espeak_command(c);
  794. }
  795. return a_error;
  796. #else
  797. sync_espeak_SetPunctuationList(punctlist);
  798. return(EE_OK);
  799. #endif
  800. } // end of espeak_SetPunctuationList
  801. ESPEAK_API void espeak_SetPhonemeTrace(int value, FILE *stream)
  802. {//============================================================
  803. ENTER("espeak_SetPhonemes");
  804. /* Controls the output of phoneme symbols for the text
  805. value=0 No phoneme output (default)
  806. value=1 Output the translated phoneme symbols for the text
  807. value=2 as (1), but also output a trace of how the translation was done (matching rules and list entries)
  808. */
  809. option_phonemes = value;
  810. f_trans = stream;
  811. if(stream == NULL)
  812. f_trans = stdout;
  813. } // end of espeak_SetPhonemes
  814. ESPEAK_API void espeak_CompileDictionary(const char *path, FILE *log)
  815. {//==================================================================
  816. ENTER("espeak_CompileDictionary");
  817. CompileDictionary(path,dictionary_name,log,NULL);
  818. } // end of espeak_CompileDirectory
  819. ESPEAK_API espeak_ERROR espeak_Cancel(void)
  820. {//===============================
  821. #ifdef USE_ASYNC
  822. ENTER("espeak_Cancel");
  823. fifo_stop();
  824. event_clear_all();
  825. if(my_mode == AUDIO_OUTPUT_PLAYBACK)
  826. {
  827. wave_close(my_audio);
  828. }
  829. SHOW_TIME("espeak_Cancel > LEAVE");
  830. #endif
  831. return EE_OK;
  832. } // end of espeak_Cancel
  833. ESPEAK_API int espeak_IsPlaying(void)
  834. {//==================================
  835. // ENTER("espeak_IsPlaying");
  836. #ifdef USE_ASYNC
  837. if((my_mode == AUDIO_OUTPUT_PLAYBACK) && wave_is_busy(my_audio))
  838. return(1);
  839. return(fifo_is_busy());
  840. #else
  841. return(0);
  842. #endif
  843. } // end of espeak_IsPlaying
  844. ESPEAK_API espeak_ERROR espeak_Synchronize(void)
  845. {//=============================================
  846. #ifdef USE_ASYNC
  847. SHOW_TIME("espeak_Synchronize > ENTER");
  848. while (espeak_IsPlaying())
  849. {
  850. usleep(20000);
  851. }
  852. #endif
  853. SHOW_TIME("espeak_Synchronize > LEAVE");
  854. return EE_OK;
  855. } // end of espeak_Synchronize
  856. extern void FreePhData(void);
  857. ESPEAK_API espeak_ERROR espeak_Terminate(void)
  858. {//===========================================
  859. ENTER("espeak_Terminate");
  860. #ifdef USE_ASYNC
  861. fifo_stop();
  862. fifo_terminate();
  863. event_terminate();
  864. if(my_mode == AUDIO_OUTPUT_PLAYBACK)
  865. {
  866. wave_close(my_audio);
  867. wave_terminate();
  868. }
  869. #endif
  870. Free(event_list);
  871. event_list = NULL;
  872. Free(outbuf);
  873. outbuf = NULL;
  874. FreePhData();
  875. return EE_OK;
  876. } // end of espeak_Terminate
  877. ESPEAK_API const char *espeak_Info(void *)
  878. {//=======================================
  879. return(version_string);
  880. }
  881. #pragma GCC visibility pop