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.

wave_sada.cpp 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595
  1. /***************************************************************************
  2. * Copyright (C) 2008, Sun Microsystems, Inc. *
  3. * eSpeak driver for Solaris Audio Device Architecture (SADA) *
  4. * Written by Willie Walker, based on the eSpeak PulseAudio driver *
  5. * from Gilles Casse *
  6. * *
  7. * This program is free software; you can redistribute it and/or modify *
  8. * it under the terms of the GNU General Public License as published by *
  9. * the Free Software Foundation; either version 3 of the License, or *
  10. * (at your option) any later version. *
  11. * *
  12. * This program is distributed in the hope that it will be useful, *
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  15. * GNU General Public License for more details. *
  16. * *
  17. * You should have received a copy of the GNU General Public License *
  18. * along with this program; if not, write to the *
  19. * Free Software Foundation, Inc., *
  20. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  21. ***************************************************************************/
  22. #include "speech.h"
  23. #ifdef USE_ASYNC
  24. // This source file is only used for asynchronious modes
  25. #include <errno.h>
  26. #include <string.h>
  27. #include <stropts.h>
  28. #include <assert.h>
  29. #include <stdlib.h>
  30. #include <unistd.h>
  31. #include <fcntl.h>
  32. #include <sys/audioio.h>
  33. #include "wave.h"
  34. #include "debug.h"
  35. enum {ONE_BILLION=1000000000};
  36. #define SAMPLE_RATE 22050
  37. #define SAMPLE_SIZE 16
  38. #ifdef USE_SADA
  39. static t_wave_callback* my_callback_is_output_enabled=NULL;
  40. static const char *sun_audio_device = "/dev/audio";
  41. static int sun_audio_fd = -1;
  42. // The total number of 16-bit samples sent to be played via the
  43. // wave_write method.
  44. //
  45. static uint32_t total_samples_sent;
  46. // The total number of samples sent to be played via the wave_write
  47. // method, but which were never played because of a call to
  48. // wave_close.
  49. //
  50. static uint32_t total_samples_skipped;
  51. // The last known playing index after a call to wave_close.
  52. //
  53. static uint32_t last_play_position=0;
  54. //>
  55. // wave_init
  56. //
  57. // DESCRIPTION:
  58. //
  59. // initializes the audio subsytem.
  60. //
  61. // GLOBALS USED/MODIFIED:
  62. //
  63. // sun_audio_fd: modified to hold the file descriptor of the opened
  64. // audio device.
  65. //
  66. //<wave_init
  67. void wave_init() {
  68. ENTER("wave_init");
  69. audio_info_t ainfo;
  70. char *audio_device = NULL;
  71. audio_device = getenv("AUDIODEV");
  72. if (audio_device != NULL) {
  73. if ((sun_audio_fd = open(audio_device, O_WRONLY)) < 0) {
  74. SHOW("wave_init() could not open: %s (%d)\n",
  75. audio_device, sun_audio_fd);
  76. }
  77. }
  78. if (sun_audio_fd < 0) {
  79. if ((sun_audio_fd = open(sun_audio_device, O_WRONLY)) < 0) {
  80. SHOW("wave_init() could not open: %s (%d)\n",
  81. sun_audio_device, sun_audio_fd);
  82. }
  83. }
  84. SHOW("wave_init() sun_audio_fd: %d\n", sun_audio_fd);
  85. if (sun_audio_fd < 0) {
  86. return;
  87. }
  88. ioctl(sun_audio_fd, AUDIO_GETINFO, &ainfo);
  89. SHOW("wave_init() play buffer size: %d\n", ainfo.play.buffer_size);
  90. ainfo.play.encoding = AUDIO_ENCODING_LINEAR;
  91. ainfo.play.channels = 1;
  92. ainfo.play.sample_rate = SAMPLE_RATE;
  93. ainfo.play.precision = SAMPLE_SIZE;
  94. if (ioctl(sun_audio_fd, AUDIO_SETINFO, &ainfo) == -1) {
  95. SHOW("wave_init() failed to set audio params: %s\n", strerror(errno));
  96. close(sun_audio_fd);
  97. return;
  98. }
  99. }
  100. //>
  101. // wave_open
  102. //
  103. // DESCRIPTION:
  104. //
  105. // opens the audio subsystem given a specific API (e.g., "alsa",
  106. // "oss", ...). We ignore the_api and just return the sun_audio_fd we
  107. // opened in wave_init. This return value will be passed in as the
  108. // theHandler parameter in all other methods.
  109. //
  110. // PARAMETERS:
  111. //
  112. // the_api: "alsa", "oss" (ignored)
  113. //
  114. // GLOBALS USED/MODIFIED:
  115. //
  116. // sun_audio_fd: used as return value
  117. //
  118. // RETURNS:
  119. //
  120. // sun_audio_fd opened in wave_init, which is passed in as theHandler
  121. // parameter in all other methods
  122. //
  123. //<wave_open
  124. void* wave_open(const char* the_api)
  125. {
  126. ENTER("wave_open");
  127. return((void*) sun_audio_fd);
  128. }
  129. //>
  130. // wave_write
  131. //
  132. // DESCRIPTION:
  133. //
  134. // Meant to be asynchronous, it supplies the wave sample to the lower
  135. // audio layer and returns. The sample is played later on. [[[WDW -
  136. // we purposely do not open the audio device as non-blocking because
  137. // managing that would be a pain. So, we rely a lot upon fifo.cpp and
  138. // event.cpp to not overload us, allowing us to get away with a
  139. // blocking write. event.cpp:polling_thread in particular appears to
  140. // use get_remaining_time to prevent flooding.]]]
  141. //
  142. // PARAMETERS:
  143. //
  144. // theHandler: the audio device file descriptor
  145. // theMono16BitsWaveBuffer: the audio data
  146. // theSize: the number of bytes (not 16-bit samples)
  147. //
  148. // GLOBALS USED/MODIFIED:
  149. //
  150. // total_samples_sent: modified based upon 16-bit samples sent
  151. //
  152. // RETURNS:
  153. //
  154. // the number of bytes (not 16-bit samples) sent
  155. //
  156. //<wave_write
  157. size_t wave_write(void* theHandler,
  158. char* theMono16BitsWaveBuffer,
  159. size_t theSize)
  160. {
  161. size_t num;
  162. ENTER("wave_write");
  163. if (my_callback_is_output_enabled && (0==my_callback_is_output_enabled())) {
  164. SHOW_TIME("wave_write > my_callback_is_output_enabled: no!");
  165. return 0;
  166. }
  167. #if defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN
  168. {
  169. // BIG-ENDIAN, swap the order of bytes in each sound sample
  170. int c;
  171. char *out_ptr;
  172. char *out_end;
  173. out_ptr = (char *)theMono16BitsWaveBuffer;
  174. out_end = out_ptr + theSize;
  175. while(out_ptr < out_end)
  176. {
  177. c = out_ptr[0];
  178. out_ptr[0] = out_ptr[1];
  179. out_ptr[1] = c;
  180. out_ptr += 2;
  181. }
  182. }
  183. #endif
  184. num = write((int) theHandler, theMono16BitsWaveBuffer, theSize);
  185. // Keep track of the total number of samples sent -- we use this in
  186. // wave_get_read_position and also use it to help calculate the
  187. // total_samples_skipped in wave_close.
  188. //
  189. total_samples_sent += num / 2;
  190. if (num < theSize) {
  191. SHOW("ERROR: wave_write only wrote %d of %d bytes\n", num, theSize);
  192. } else {
  193. SHOW("wave_write wrote %d bytes\n", theSize);
  194. }
  195. SHOW_TIME("wave_write > LEAVE");
  196. return num;
  197. }
  198. //>
  199. // wave_close
  200. //
  201. // DESCRIPTION:
  202. //
  203. // Does what SADA normally would call a flush, which means to cease
  204. // all audio production in progress and throw any remaining audio
  205. // away. [[[WDW - see comment in wave_flush.]]]
  206. //
  207. // PARAMETERS:
  208. //
  209. // theHandler: the audio device file descriptor
  210. //
  211. // GLOBALS USED/MODIFIED:
  212. //
  213. // last_play_position: modified to reflect play position the last time
  214. // this method was called
  215. // total_samples_sent: used to help calculate total_samples_skipped
  216. // total_samples_skipped: modified to hold the total number of 16-bit
  217. // samples sent to wave_write, but which were
  218. // never played
  219. // sun_audio_fd: used because some calls to wave_close seem to
  220. // pass a NULL for theHandler for some odd reason
  221. //
  222. // RETURNS:
  223. //
  224. // The result of the ioctl call (non-0 means failure)
  225. //
  226. //<wave_close
  227. int wave_close(void* theHandler)
  228. {
  229. int ret;
  230. audio_info_t ainfo;
  231. int audio_fd = (int) theHandler;
  232. if (!audio_fd) {
  233. audio_fd = sun_audio_fd;
  234. }
  235. ENTER("wave_close");
  236. // [[[WDW: maybe do a pause/resume ioctl???]]]
  237. ret = ioctl(audio_fd, I_FLUSH, FLUSHRW);
  238. ioctl(audio_fd, AUDIO_GETINFO, &ainfo);
  239. // Calculate the number of samples that won't get
  240. // played. We also keep track of the last_play_position
  241. // because wave_close can be called multiple times
  242. // before another call to wave_write.
  243. //
  244. if (last_play_position != ainfo.play.samples) {
  245. last_play_position = ainfo.play.samples;
  246. total_samples_skipped = total_samples_sent - last_play_position;
  247. }
  248. SHOW_TIME("wave_close > LEAVE");
  249. return ret;
  250. }
  251. //>
  252. // wave_is_busy
  253. //
  254. // DESCRIPTION:
  255. //
  256. // Returns a non-0 value if audio is being played.
  257. //
  258. // PARAMETERS:
  259. //
  260. // theHandler: the audio device file descriptor
  261. //
  262. // GLOBALS USED/MODIFIED:
  263. //
  264. // sun_audio_fd: used because some calls to wave_is_busy seem to
  265. // pass a NULL for theHandler for some odd reason
  266. //
  267. // RETURNS:
  268. //
  269. // A non-0 value if audio is being played
  270. //
  271. //<wave_is_busy
  272. int wave_is_busy(void* theHandler)
  273. {
  274. audio_info_t ainfo;
  275. int audio_fd = (int) theHandler;
  276. if (!audio_fd) {
  277. audio_fd = sun_audio_fd;
  278. }
  279. ENTER("wave_is_busy");
  280. ioctl(audio_fd, AUDIO_GETINFO, &ainfo);
  281. SHOW("wave_is_busy: active=%d", ainfo.play.active);
  282. SHOW_TIME("wave_is_busy > LEAVE");
  283. return ainfo.play.active;
  284. }
  285. //>
  286. // wave_terminate
  287. //
  288. // DESCRIPTION:
  289. //
  290. // Used to end our session with eSpeak.
  291. //
  292. // GLOBALS USED/MODIFIED:
  293. //
  294. // sun_audio_fd: modified - closed and set to -1
  295. //
  296. //<wave_terminate
  297. void wave_terminate()
  298. {
  299. ENTER("wave_terminate");
  300. close(sun_audio_fd);
  301. sun_audio_fd = -1;
  302. SHOW_TIME("wave_terminate > LEAVE");
  303. }
  304. //>
  305. // wave_flush
  306. //
  307. // DESCRIPTION:
  308. //
  309. // Appears to want to tell the audio subsystem to make sure it plays
  310. // the audio. In our case, the system is already doing this, so this
  311. // is basically a no-op. [[[WDW - if you do a drain, you block, so
  312. // don't do that. In addition the typical SADA notion of flush is
  313. // currently handled by wave_close. I think this is most likely just
  314. // terminology conflict between eSpeak and SADA.]]]
  315. //
  316. // PARAMETERS:
  317. //
  318. // theHandler: the audio device file descriptor
  319. //
  320. //<wave_flush
  321. void wave_flush(void* theHandler)
  322. {
  323. ENTER("wave_flush");
  324. //ioctl((int) theHandler, AUDIO_DRAIN, 0);
  325. SHOW_TIME("wave_flush > LEAVE");
  326. }
  327. //>
  328. // wave_set_callback_is_output_enabled
  329. //
  330. // DESCRIPTION:
  331. //
  332. // Sets the callback to call from wave_write before it sends data to
  333. // be played. It helps wave_write determine if the data should be
  334. // thrown away or not.
  335. //
  336. // PARAMETERS:
  337. //
  338. // cb: the callback to call from wave_write
  339. //
  340. //<wave_set_callback_is_output_enabled
  341. void wave_set_callback_is_output_enabled(t_wave_callback* cb)
  342. {
  343. my_callback_is_output_enabled = cb;
  344. }
  345. //>
  346. // wave_test_get_write_buffer
  347. //
  348. // DESCRIPTION:
  349. //
  350. // Unnecessary and is used for debug output from
  351. // speak_lib.cpp:dispatch_audio.
  352. //
  353. // RETURNS:
  354. //
  355. // NULL
  356. //
  357. //<wave_test_get_write_buffer
  358. void *wave_test_get_write_buffer()
  359. {
  360. return NULL;
  361. }
  362. //>
  363. // wave_get_read_position
  364. //
  365. // DESCRIPTION:
  366. //
  367. // Concerns the sample which is currently played by the audio layer,
  368. // where 'sample' is a small buffer of synthesized wave data,
  369. // identified so that the user callback could be called when the
  370. // 'sample' is really played. The identifier is returned by
  371. // wave_get_write_position. This method is unused.
  372. //
  373. // PARAMETERS:
  374. //
  375. // theHandler: the audio device file descriptor
  376. //
  377. // RETURNS:
  378. //
  379. // The total number of 16-bit samples played by the audio system
  380. // so far.
  381. //
  382. //<wave_get_read_position
  383. uint32_t wave_get_read_position(void* theHandler)
  384. {
  385. audio_info_t ainfo;
  386. ENTER("wave_get_read_position");
  387. ioctl((int) theHandler, AUDIO_GETINFO, &ainfo);
  388. SHOW("wave_get_read_position: %d\n", ainfo.play.samples);
  389. SHOW_TIME("wave_get_read_position > LEAVE");
  390. return ainfo.play.samples;
  391. }
  392. //>
  393. // wave_get_write_position
  394. //
  395. // DESCRIPTION:
  396. //
  397. // Returns an identifier for a new sample, where 'sample' is a small
  398. // buffer of synthesized wave data, identified so that the user
  399. // callback could be called when the 'sample' is really played. This
  400. // implementation views the audio as one long continuous stream of
  401. // 16-bit samples.
  402. //
  403. // PARAMETERS:
  404. //
  405. // theHandler: the audio device file descriptor
  406. //
  407. // GLOBALS USED/MODIFIED:
  408. //
  409. // total_samples_sent: used as the return value
  410. //
  411. // RETURNS:
  412. //
  413. // total_samples_sent, which is the index for the end of this long
  414. // continuous stream. [[[WDW: with a unit32_t managing 16-bit
  415. // samples at 22050Hz, we have about 54 hours of play time before
  416. // the index wraps back to 0. We don't handle that wrapping, so
  417. // the behavior after 54 hours of play time is undefined.]]]
  418. //
  419. //<wave_get_write_position
  420. uint32_t wave_get_write_position(void* theHandler)
  421. {
  422. ENTER("wave_get_write_position");
  423. SHOW("wave_get_write_position: %d\n", total_samples_sent);
  424. SHOW_TIME("wave_get_write_position > LEAVE");
  425. return total_samples_sent;
  426. }
  427. //>
  428. // wave_get_remaining_time
  429. //
  430. // DESCRIPTION:
  431. //
  432. // Returns the remaining time (in ms) before the sample is played.
  433. // The sample in this case is a return value from a previous call to
  434. // wave_get_write_position.
  435. //
  436. // PARAMETERS:
  437. //
  438. // sample: an index returned from wave_get_write_position representing
  439. // an index into the long continuous stream of 16-bit samples
  440. // time: a return value representing the delay in milliseconds until
  441. // sample is played. A value of 0 means the sample is either
  442. // currently being played or it has already been played.
  443. //
  444. // GLOBALS USED/MODIFIED:
  445. //
  446. // sun_audio_fd: used to determine total number of samples played by
  447. // the audio system
  448. // total_samples_skipped: used in remaining time calculation
  449. //
  450. // RETURNS:
  451. //
  452. // Time in milliseconds before the sample is played or 0 if the sample
  453. // is currently playing or has already been played.
  454. //
  455. //<wave_get_remaining_time
  456. int wave_get_remaining_time(uint32_t sample, uint32_t* time)
  457. {
  458. uint32_t a_time=0;
  459. uint32_t actual_index;
  460. audio_info_t ainfo;
  461. ENTER("wave_get_remaining_time");
  462. if (!time) {
  463. return(-1);
  464. SHOW_TIME("wave_get_remaining_time > LEAVE");
  465. }
  466. ioctl(sun_audio_fd, AUDIO_GETINFO, &ainfo);
  467. // See if this sample has already been played or is currently
  468. // playing.
  469. //
  470. actual_index = sample - total_samples_skipped;
  471. if ((sample < total_samples_skipped) ||
  472. (actual_index <= ainfo.play.samples)) {
  473. *time = 0;
  474. } else {
  475. a_time = ((actual_index - ainfo.play.samples) * 1000) / SAMPLE_RATE;
  476. *time = (uint32_t) a_time;
  477. }
  478. SHOW("wave_get_remaining_time for %d: %d\n", sample, *time);
  479. SHOW_TIME("wave_get_remaining_time > LEAVE");
  480. return 0;
  481. }
  482. #else
  483. // notdef USE_SADA
  484. void wave_init() {}
  485. void* wave_open(const char* the_api) {return (void *)1;}
  486. size_t wave_write(void* theHandler, char* theMono16BitsWaveBuffer, size_t theSize) {return theSize;}
  487. int wave_close(void* theHandler) {return 0;}
  488. int wave_is_busy(void* theHandler) {return 0;}
  489. void wave_terminate() {}
  490. uint32_t wave_get_read_position(void* theHandler) {return 0;}
  491. uint32_t wave_get_write_position(void* theHandler) {return 0;}
  492. void wave_flush(void* theHandler) {}
  493. typedef int (t_wave_callback)(void);
  494. void wave_set_callback_is_output_enabled(t_wave_callback* cb) {}
  495. extern void* wave_test_get_write_buffer() {return NULL;}
  496. int wave_get_remaining_time(uint32_t sample, uint32_t* time)
  497. {
  498. if (!time) return(-1);
  499. *time = (uint32_t)0;
  500. return 0;
  501. }
  502. #endif // of USE_PORTAUDIO
  503. //>
  504. //<clock_gettime2, add_time_in_ms
  505. void clock_gettime2(struct timespec *ts)
  506. {
  507. struct timeval tv;
  508. if (!ts)
  509. {
  510. return;
  511. }
  512. assert (gettimeofday(&tv, NULL) != -1);
  513. ts->tv_sec = tv.tv_sec;
  514. ts->tv_nsec = tv.tv_usec*1000;
  515. }
  516. void add_time_in_ms(struct timespec *ts, int time_in_ms)
  517. {
  518. if (!ts)
  519. {
  520. return;
  521. }
  522. uint64_t t_ns = (uint64_t)ts->tv_nsec + 1000000 * (uint64_t)time_in_ms;
  523. while(t_ns >= ONE_BILLION)
  524. {
  525. SHOW("event > add_time_in_ms ns: %d sec %Lu nsec \n", ts->tv_sec, t_ns);
  526. ts->tv_sec += 1;
  527. t_ns -= ONE_BILLION;
  528. }
  529. ts->tv_nsec = (long int)t_ns;
  530. }
  531. #endif // USE_ASYNC
  532. //>