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 30KB

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