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.

espeak_command.cpp 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703
  1. /***************************************************************************
  2. * Copyright (C) 2007, Gilles Casse <[email protected]> *
  3. * *
  4. * This program is free software; you can redistribute it and/or modify *
  5. * it under the terms of the GNU General Public License as published by *
  6. * the Free Software Foundation; either version 3 of the License, or *
  7. * (at your option) any later version. *
  8. * *
  9. * This program is distributed in the hope that it will be useful, *
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  12. * GNU General Public License for more details. *
  13. * *
  14. * You should have received a copy of the GNU General Public License *
  15. * along with this program; if not, write to the *
  16. * Free Software Foundation, Inc., *
  17. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  18. ***************************************************************************/
  19. #include "speech.h"
  20. #ifdef USE_ASYNC
  21. // This source file is only used for asynchronious modes
  22. #include "espeak_command.h"
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <assert.h>
  26. #include <wchar.h>
  27. #include "debug.h"
  28. static unsigned int my_current_text_id=0;
  29. //<create_espeak_text
  30. t_espeak_command* create_espeak_text(const void *text, size_t size, unsigned int position, espeak_POSITION_TYPE position_type, unsigned int end_position, unsigned int flags, void* user_data)
  31. {
  32. ENTER("create_espeak_text");
  33. int a_error=1;
  34. void* a_text = NULL;
  35. t_espeak_text* data = NULL;
  36. t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command));
  37. if (!text || !size || !a_command)
  38. {
  39. goto text_error;
  40. }
  41. a_text = malloc( size );
  42. if (!a_text)
  43. {
  44. goto text_error;
  45. }
  46. memcpy(a_text, text, size);
  47. a_command->type = ET_TEXT;
  48. a_command->state = CS_UNDEFINED;
  49. data = &(a_command->u.my_text);
  50. data->unique_identifier = ++my_current_text_id;
  51. data->text = a_text;
  52. data->size = size;
  53. data->position = position;
  54. data->position_type = position_type;
  55. data->end_position = end_position;
  56. data->flags = flags;
  57. data->user_data = user_data;
  58. a_error=0;
  59. SHOW("ET_TEXT malloc text=%x, command=%x (uid=%d)\n", a_text, a_command, data->unique_identifier);
  60. text_error:
  61. if (a_error)
  62. {
  63. if (a_text)
  64. {
  65. free (a_text);
  66. }
  67. if (a_command)
  68. {
  69. free (a_command);
  70. }
  71. a_command = NULL;
  72. }
  73. SHOW("command=0x%x\n", a_command);
  74. return a_command;
  75. }
  76. //>
  77. t_espeak_command* create_espeak_terminated_msg(unsigned int unique_identifier, void* user_data)
  78. {
  79. ENTER("create_espeak_terminated_msg");
  80. int a_error=1;
  81. t_espeak_terminated_msg* data = NULL;
  82. t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command));
  83. if (!a_command)
  84. {
  85. goto msg_error;
  86. }
  87. a_command->type = ET_TERMINATED_MSG;
  88. a_command->state = CS_UNDEFINED;
  89. data = &(a_command->u.my_terminated_msg);
  90. data->unique_identifier = unique_identifier;
  91. data->user_data = user_data;
  92. a_error=0;
  93. SHOW("ET_TERMINATED_MSG command=%x (uid=%d, user_data=0x%x)\n", a_command, unique_identifier, (int)user_data);
  94. msg_error:
  95. if (a_error)
  96. {
  97. if (a_command)
  98. {
  99. free (a_command);
  100. }
  101. a_command = NULL;
  102. }
  103. SHOW("command=0x%x\n", a_command);
  104. return a_command;
  105. }
  106. //<create_espeak_mark
  107. t_espeak_command* create_espeak_mark(const void *text, size_t size, const char *index_mark, unsigned int end_position, unsigned int flags, void* user_data)
  108. {
  109. ENTER("create_espeak_mark");
  110. int a_error=1;
  111. void* a_text = NULL;
  112. char *a_index_mark = NULL;
  113. t_espeak_mark* data = NULL;
  114. t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command));
  115. if (!text || !size || !index_mark || !a_command)
  116. {
  117. goto mark_error;
  118. }
  119. a_text = malloc( size );
  120. if (!a_text)
  121. {
  122. goto mark_error;
  123. }
  124. memcpy(a_text, text, size);
  125. a_index_mark = strdup( index_mark);
  126. a_command->type = ET_MARK;
  127. a_command->state = CS_UNDEFINED;
  128. data = &(a_command->u.my_mark);
  129. data->unique_identifier = ++my_current_text_id;
  130. data->text = a_text;
  131. data->size = size;
  132. data->index_mark = a_index_mark;
  133. data->end_position = end_position;
  134. data->flags = flags;
  135. data->user_data = user_data;
  136. a_error=0;
  137. mark_error:
  138. if (a_error)
  139. {
  140. if (a_text)
  141. {
  142. free (a_text);
  143. }
  144. if (a_command)
  145. {
  146. free (a_command);
  147. }
  148. a_command = NULL;
  149. if (a_index_mark)
  150. {
  151. free (a_index_mark);
  152. }
  153. }
  154. SHOW("ET_MARK malloc text=%x, command=%x (uid=%d)\n", a_text, a_command, data->unique_identifier);
  155. return a_command;
  156. }
  157. //>
  158. //< create_espeak_key, create_espeak_char
  159. t_espeak_command* create_espeak_key(const char *key_name)
  160. {
  161. ENTER("create_espeak_key");
  162. int a_error=1;
  163. t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command));
  164. if (!key_name || !a_command)
  165. {
  166. goto key_error;
  167. }
  168. a_command->type = ET_KEY;
  169. a_command->state = CS_UNDEFINED;
  170. a_command->u.my_key = strdup( key_name);
  171. a_error=0;
  172. key_error:
  173. if (a_error)
  174. {
  175. if (a_command)
  176. {
  177. free (a_command);
  178. }
  179. a_command = NULL;
  180. }
  181. SHOW("command=0x%x\n", a_command);
  182. return a_command;
  183. }
  184. t_espeak_command* create_espeak_char(wchar_t character)
  185. {
  186. ENTER("create_espeak_char");
  187. int a_error=1;
  188. t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command));
  189. if (!a_command)
  190. {
  191. goto char_error;
  192. }
  193. a_command->type = ET_CHAR;
  194. a_command->state = CS_UNDEFINED;
  195. a_command->u.my_char = character;
  196. a_error=0;
  197. char_error:
  198. if (a_error)
  199. {
  200. if (a_command)
  201. {
  202. free (a_command);
  203. }
  204. a_command = NULL;
  205. }
  206. SHOW("command=0x%x\n", a_command);
  207. return a_command;
  208. }
  209. //>
  210. //< create_espeak_parameter
  211. t_espeak_command* create_espeak_parameter(espeak_PARAMETER parameter, int value, int relative)
  212. {
  213. ENTER("create_espeak_parameter");
  214. int a_error=1;
  215. t_espeak_parameter* data = NULL;
  216. t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command));
  217. if (!a_command)
  218. {
  219. goto param_error;
  220. }
  221. a_command->type = ET_PARAMETER;
  222. a_command->state = CS_UNDEFINED;
  223. data = &(a_command->u.my_param);
  224. data->parameter = parameter;
  225. data->value = value;
  226. data->relative = relative;
  227. a_error=0;
  228. param_error:
  229. if (a_error)
  230. {
  231. if (a_command)
  232. {
  233. free (a_command);
  234. }
  235. a_command = NULL;
  236. }
  237. SHOW("command=0x%x\n", a_command);
  238. return a_command;
  239. }
  240. //>
  241. //< create_espeak_punctuation_list
  242. t_espeak_command* create_espeak_punctuation_list(const wchar_t *punctlist)
  243. {
  244. ENTER("create_espeak_punctuation_list");
  245. int a_error=1;
  246. // wchar_t *a_list = NULL;
  247. t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command));
  248. if (!punctlist || !a_command)
  249. {
  250. goto list_error;
  251. }
  252. a_command->type = ET_PUNCTUATION_LIST;
  253. a_command->state = CS_UNDEFINED;
  254. {
  255. size_t len = (wcslen(punctlist) + 1)*sizeof(wchar_t);
  256. wchar_t* a_list = (wchar_t*)malloc(len);
  257. memcpy(a_list, punctlist, len);
  258. a_command->u.my_punctuation_list = a_list;
  259. }
  260. a_error=0;
  261. list_error:
  262. if (a_error)
  263. {
  264. if (a_command)
  265. {
  266. free (a_command);
  267. }
  268. a_command = NULL;
  269. }
  270. SHOW("command=0x%x\n", a_command);
  271. return a_command;
  272. }
  273. //>
  274. //< create_espeak_voice_name, create_espeak_voice_spec
  275. t_espeak_command* create_espeak_voice_name(const char *name)
  276. {
  277. ENTER("create_espeak_voice_name");
  278. int a_error=1;
  279. t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command));
  280. if (!name || !a_command)
  281. {
  282. goto name_error;
  283. }
  284. a_command->type = ET_VOICE_NAME;
  285. a_command->state = CS_UNDEFINED;
  286. a_command->u.my_voice_name = strdup( name);
  287. a_error=0;
  288. name_error:
  289. if (a_error)
  290. {
  291. if (a_command)
  292. {
  293. free (a_command);
  294. }
  295. a_command = NULL;
  296. }
  297. SHOW("command=0x%x\n", a_command);
  298. return a_command;
  299. }
  300. t_espeak_command* create_espeak_voice_spec(espeak_VOICE *voice)
  301. {
  302. ENTER("create_espeak_voice_spec");
  303. int a_error=1;
  304. t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command));
  305. if (!voice || !a_command)
  306. {
  307. goto spec_error;
  308. }
  309. a_command->type = ET_VOICE_SPEC;
  310. a_command->state = CS_UNDEFINED;
  311. {
  312. espeak_VOICE* data = &(a_command->u.my_voice_spec);
  313. memcpy(data, voice, sizeof(espeak_VOICE));
  314. if (voice->name)
  315. {
  316. data->name = strdup(voice->name);
  317. }
  318. if (voice->languages)
  319. {
  320. data->languages = strdup(voice->languages);
  321. }
  322. if (voice->identifier)
  323. {
  324. data->identifier = strdup(voice->identifier);
  325. }
  326. a_error=0;
  327. }
  328. spec_error:
  329. if (a_error)
  330. {
  331. if (a_command)
  332. {
  333. free (a_command);
  334. }
  335. a_command = NULL;
  336. }
  337. SHOW("command=0x%x\n", a_command);
  338. return a_command;
  339. }
  340. //>
  341. //< delete_espeak_command
  342. int delete_espeak_command( t_espeak_command* the_command)
  343. {
  344. ENTER("delete_espeak_command");
  345. int a_status = 0;
  346. if (the_command)
  347. {
  348. switch(the_command->type)
  349. {
  350. case ET_TEXT:
  351. if (the_command->u.my_text.text)
  352. {
  353. SHOW("delete_espeak_command > ET_TEXT free text=%x, command=%x, uid=%d\n", the_command->u.my_text.text, the_command, the_command->u.my_text.unique_identifier);
  354. free(the_command->u.my_text.text);
  355. }
  356. break;
  357. case ET_MARK:
  358. if (the_command->u.my_mark.text)
  359. {
  360. free(the_command->u.my_mark.text);
  361. }
  362. if (the_command->u.my_mark.index_mark)
  363. {
  364. free((void*)(the_command->u.my_mark.index_mark));
  365. }
  366. break;
  367. case ET_TERMINATED_MSG:
  368. {
  369. // if the terminated msg is pending,
  370. // it must be processed here for informing the calling program
  371. // that its message is finished.
  372. // This can be important for cleaning the related user data.
  373. t_espeak_terminated_msg* data = &(the_command->u.my_terminated_msg);
  374. if (the_command->state == CS_PENDING)
  375. {
  376. the_command->state = CS_PROCESSED;
  377. SHOW("delete_espeak_command > ET_TERMINATED_MSG callback (command=0x%x, uid=%d) \n", the_command, data->unique_identifier);
  378. sync_espeak_terminated_msg( data->unique_identifier, data->user_data);
  379. }
  380. }
  381. break;
  382. case ET_KEY:
  383. if (the_command->u.my_key)
  384. {
  385. free((void*)(the_command->u.my_key));
  386. }
  387. break;
  388. case ET_CHAR:
  389. case ET_PARAMETER:
  390. // No allocation
  391. break;
  392. case ET_PUNCTUATION_LIST:
  393. if (the_command->u.my_punctuation_list)
  394. {
  395. free((void*)(the_command->u.my_punctuation_list));
  396. }
  397. break;
  398. case ET_VOICE_NAME:
  399. if (the_command->u.my_voice_name)
  400. {
  401. free((void*)(the_command->u.my_voice_name));
  402. }
  403. break;
  404. case ET_VOICE_SPEC:
  405. {
  406. espeak_VOICE* data = &(the_command->u.my_voice_spec);
  407. if (data->name)
  408. {
  409. free(data->name);
  410. }
  411. if (data->languages)
  412. {
  413. free(data->languages);
  414. }
  415. if (data->identifier)
  416. {
  417. free(data->identifier);
  418. }
  419. }
  420. break;
  421. default:
  422. assert(0);
  423. }
  424. SHOW("delete_espeak_command > free command=0x%x\n", the_command);
  425. free(the_command);
  426. a_status = 1;
  427. }
  428. return a_status;
  429. }
  430. //>
  431. //< process_espeak_command
  432. void process_espeak_command( t_espeak_command* the_command)
  433. {
  434. ENTER("process_espeak_command");
  435. SHOW("command=0x%x\n", the_command);
  436. if (the_command == NULL)
  437. {
  438. return;
  439. }
  440. the_command->state = CS_PROCESSED;
  441. switch(the_command->type)
  442. {
  443. case ET_TEXT:
  444. {
  445. t_espeak_text* data = &(the_command->u.my_text);
  446. sync_espeak_Synth( data->unique_identifier, data->text, data->size,
  447. data->position, data->position_type,
  448. data->end_position, data->flags, data->user_data);
  449. }
  450. break;
  451. case ET_MARK:
  452. {
  453. t_espeak_mark* data = &(the_command->u.my_mark);
  454. sync_espeak_Synth_Mark( data->unique_identifier, data->text, data->size,
  455. data->index_mark, data->end_position, data->flags,
  456. data->user_data);
  457. }
  458. break;
  459. case ET_TERMINATED_MSG:
  460. {
  461. t_espeak_terminated_msg* data = &(the_command->u.my_terminated_msg);
  462. sync_espeak_terminated_msg( data->unique_identifier, data->user_data);
  463. }
  464. break;
  465. case ET_KEY:
  466. {
  467. const char* data = the_command->u.my_key;
  468. sync_espeak_Key(data);
  469. }
  470. break;
  471. case ET_CHAR:
  472. {
  473. const wchar_t data = the_command->u.my_char;
  474. sync_espeak_Char( data);
  475. }
  476. break;
  477. case ET_PARAMETER:
  478. {
  479. t_espeak_parameter* data = &(the_command->u.my_param);
  480. SetParameter( data->parameter, data->value, data->relative);
  481. }
  482. break;
  483. case ET_PUNCTUATION_LIST:
  484. {
  485. const wchar_t* data = the_command->u.my_punctuation_list;
  486. sync_espeak_SetPunctuationList( data);
  487. }
  488. break;
  489. case ET_VOICE_NAME:
  490. {
  491. const char* data = the_command->u.my_voice_name;
  492. SetVoiceByName( data);
  493. }
  494. break;
  495. case ET_VOICE_SPEC:
  496. {
  497. espeak_VOICE* data = &(the_command->u.my_voice_spec);
  498. SetVoiceByProperties(data);
  499. }
  500. break;
  501. default:
  502. assert(0);
  503. break;
  504. }
  505. }
  506. //>
  507. //< process_espeak_command
  508. void display_espeak_command( t_espeak_command* the_command)
  509. {
  510. ENTER("display_espeak_command");
  511. #ifdef DEBUG_ENABLED
  512. if (the_command == NULL)
  513. {
  514. SHOW("display_espeak_command > command=%s\n","NULL");
  515. return;
  516. }
  517. SHOW("display_espeak_command > state=%d\n",the_command->state);
  518. switch(the_command->type)
  519. {
  520. case ET_TEXT:
  521. {
  522. t_espeak_text* data = &(the_command->u.my_text);
  523. SHOW("display_espeak_command > (0x%x) uid=%d, TEXT=%s, user_data=0x%x\n", the_command, data->unique_identifier, (char*)data->text, (int)(data->user_data));
  524. }
  525. break;
  526. case ET_MARK:
  527. {
  528. t_espeak_mark* data = &(the_command->u.my_mark);
  529. SHOW("display_espeak_command > (0x%x) uid=%d, MARK=%s, user_data=0x%x\n", the_command, data->unique_identifier, (char*)data->text, (int)(data->user_data));
  530. }
  531. break;
  532. case ET_KEY:
  533. {
  534. const char* data = the_command->u.my_key;
  535. SHOW("display_espeak_command > (0x%x) KEY=%c\n", the_command, data);
  536. }
  537. break;
  538. case ET_TERMINATED_MSG:
  539. {
  540. t_espeak_terminated_msg* data = &(the_command->u.my_terminated_msg);
  541. SHOW("display_espeak_command > (0x%x) TERMINATED_MSG uid=%d, user_data=0x%x, state=%d\n",
  542. the_command, data->unique_identifier, data->user_data,
  543. the_command->state);
  544. }
  545. break;
  546. case ET_CHAR:
  547. {
  548. const wchar_t data = the_command->u.my_char;
  549. SHOW("display_espeak_command > (0x%x) CHAR=%c\n", the_command, (char)data);
  550. }
  551. break;
  552. case ET_PARAMETER:
  553. {
  554. t_espeak_parameter* data = &(the_command->u.my_param);
  555. SHOW("display_espeak_command > (0x%x) PARAMETER=%d, value=%d, relative=%d\n",
  556. the_command, data->parameter, data->value, data->relative);
  557. }
  558. break;
  559. case ET_PUNCTUATION_LIST:
  560. {
  561. const wchar_t* data = the_command->u.my_punctuation_list;
  562. sync_espeak_SetPunctuationList( data);
  563. SHOW("display_espeak_command > (0x%x) PUNCTLIST=%s\n", the_command, (char*)data);
  564. }
  565. break;
  566. case ET_VOICE_NAME:
  567. {
  568. const char* data = the_command->u.my_voice_name;
  569. SHOW("display_espeak_command > (0x%x) VOICE_NAME=%s\n", the_command, data);
  570. }
  571. break;
  572. case ET_VOICE_SPEC:
  573. {
  574. SHOW("display_espeak_command > (0x%x) VOICE_SPEC", the_command);
  575. }
  576. break;
  577. default:
  578. assert(0);
  579. break;
  580. }
  581. #endif
  582. }
  583. #endif
  584. //>