/native/external/espeak/src/wave.cpp

http://eyes-free.googlecode.com/ · C++ · 1083 lines · 713 code · 157 blank · 213 comment · 110 complexity · e2724a9893fe25e701256787f0619c31 MD5 · raw file

  1. /***************************************************************************
  2. * Copyright (C) 2007, Gilles Casse <gcasse@oralux.org> *
  3. * based on AudioIO.cc (Audacity-1.2.4b) and wavegen.cpp *
  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 to the *
  17. * Free Software Foundation, Inc., *
  18. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  19. ***************************************************************************/
  20. #include "speech.h"
  21. #ifdef USE_ASYNC
  22. // This source file is only used for asynchronious modes
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include <stdlib.h>
  26. #include <math.h>
  27. #include <assert.h>
  28. #include <sys/time.h>
  29. #include <time.h>
  30. #include "portaudio.h"
  31. #ifndef PLATFORM_WINDOWS
  32. #include <unistd.h>
  33. #endif
  34. #include "wave.h"
  35. #include "debug.h"
  36. //<Definitions
  37. enum {ONE_BILLION=1000000000};
  38. #ifdef USE_PORTAUDIO
  39. #undef USE_PORTAUDIO
  40. // determine portaudio version by looking for a #define which is not in V18
  41. #ifdef paNeverDropInput
  42. #define USE_PORTAUDIO 19
  43. #else
  44. #define USE_PORTAUDIO 18
  45. #endif
  46. static t_wave_callback* my_callback_is_output_enabled=NULL;
  47. #define N_WAV_BUF 10
  48. #define SAMPLE_RATE 22050
  49. #define FRAMES_PER_BUFFER 512
  50. #define BUFFER_LENGTH (SAMPLE_RATE*2*sizeof(uint16_t))
  51. #define THRESHOLD (BUFFER_LENGTH/5)
  52. static char myBuffer[BUFFER_LENGTH];
  53. static char* myRead=NULL;
  54. static char* myWrite=NULL;
  55. static int out_channels=1;
  56. static int my_stream_could_start=0;
  57. static int mInCallbackFinishedState = false;
  58. #if (USE_PORTAUDIO == 18)
  59. static PortAudioStream *pa_stream=NULL;
  60. #endif
  61. #if (USE_PORTAUDIO == 19)
  62. static struct PaStreamParameters myOutputParameters;
  63. static PaStream *pa_stream=NULL;
  64. #endif
  65. static int userdata[4];
  66. static PaError pa_init_err=0;
  67. // time measurement
  68. // The read and write position audio stream in the audio stream are measured in ms.
  69. //
  70. // * When the stream is opened, myReadPosition and myWritePosition are cleared.
  71. // * myWritePosition is updated in wave_write.
  72. // * myReadPosition is updated in pa_callback (+ sample delay).
  73. static uint32_t myReadPosition = 0; // in ms
  74. static uint32_t myWritePosition = 0;
  75. //>
  76. //<init_buffer, get_used_mem
  77. static void init_buffer()
  78. {
  79. myWrite = myBuffer;
  80. myRead = myBuffer;
  81. memset(myBuffer,0,BUFFER_LENGTH);
  82. myReadPosition = myWritePosition = 0;
  83. SHOW("init_buffer > myRead=0x%x, myWrite=0x%x, BUFFER_LENGTH=0x%x, myReadPosition = myWritePosition = 0\n", (int)myRead, (int)myWrite, BUFFER_LENGTH);
  84. }
  85. static unsigned int get_used_mem()
  86. {
  87. char* aRead = myRead;
  88. char* aWrite = myWrite;
  89. unsigned int used = 0;
  90. assert ((aRead >= myBuffer)
  91. && (aRead <= myBuffer + BUFFER_LENGTH)
  92. && (aWrite >= myBuffer)
  93. && (aWrite <= myBuffer + BUFFER_LENGTH));
  94. if (aRead < aWrite)
  95. {
  96. used = aWrite - aRead;
  97. }
  98. else
  99. {
  100. used = aWrite + BUFFER_LENGTH - aRead;
  101. }
  102. SHOW("get_used_mem > %d\n", used);
  103. return used;
  104. }
  105. //>
  106. //<start stream
  107. static void start_stream()
  108. {
  109. PaError err;
  110. SHOW_TIME("start_stream");
  111. my_stream_could_start=0;
  112. mInCallbackFinishedState = false;
  113. err = Pa_StartStream(pa_stream);
  114. SHOW("start_stream > Pa_StartStream=%d (%s)\n", err, Pa_GetErrorText(err));
  115. #if USE_PORTAUDIO == 19
  116. if(err == paStreamIsNotStopped)
  117. {
  118. SHOW_TIME("start_stream > restart stream (begin)");
  119. // not sure why we need this, but PA v19 seems to need it
  120. err = Pa_StopStream(pa_stream);
  121. SHOW("start_stream > Pa_StopStream=%d (%s)\n", err, Pa_GetErrorText(err));
  122. err = Pa_StartStream(pa_stream);
  123. SHOW("start_stream > Pa_StartStream=%d (%s)\n", err, Pa_GetErrorText(err));
  124. SHOW_TIME("start_stream > restart stream (end)");
  125. }
  126. #endif
  127. }
  128. //>
  129. //<pa_callback
  130. /* This routine will be called by the PortAudio engine when audio is needed.
  131. ** It may called at interrupt level on some machines so don't do anything
  132. ** that could mess up the system like calling malloc() or free().
  133. */
  134. #if USE_PORTAUDIO == 18
  135. static int pa_callback(void *inputBuffer, void *outputBuffer,
  136. unsigned long framesPerBuffer, PaTimestamp outTime, void *userData )
  137. #else
  138. static int pa_callback(const void *inputBuffer, void *outputBuffer,
  139. long unsigned int framesPerBuffer, const PaStreamCallbackTimeInfo *outTime,
  140. PaStreamCallbackFlags flags, void *userData )
  141. #endif
  142. {
  143. int aResult=0; // paContinue
  144. char* aWrite = myWrite;
  145. size_t n = out_channels*sizeof(uint16_t)*framesPerBuffer;
  146. myReadPosition += framesPerBuffer;
  147. SHOW("pa_callback > myReadPosition=%u, framesPerBuffer=%lu (n=0x%x) \n",(int)myReadPosition, framesPerBuffer, n);
  148. if (aWrite >= myRead)
  149. {
  150. if((size_t)(aWrite - myRead) >= n)
  151. {
  152. memcpy(outputBuffer, myRead, n);
  153. myRead += n;
  154. }
  155. else
  156. {
  157. SHOW_TIME("pa_callback > underflow");
  158. aResult=1; // paComplete;
  159. mInCallbackFinishedState = true;
  160. size_t aUsedMem=0;
  161. aUsedMem = (size_t)(aWrite - myRead);
  162. if (aUsedMem)
  163. {
  164. memcpy(outputBuffer, myRead, aUsedMem);
  165. }
  166. char* p = (char*)outputBuffer + aUsedMem;
  167. memset(p, 0, n - aUsedMem);
  168. // myReadPosition += aUsedMem/(out_channels*sizeof(uint16_t));
  169. myRead = aWrite;
  170. }
  171. }
  172. else // myRead > aWrite
  173. {
  174. if ((size_t)(myBuffer + BUFFER_LENGTH - myRead) >= n)
  175. {
  176. memcpy(outputBuffer, myRead, n);
  177. myRead += n;
  178. }
  179. else if ((size_t)(aWrite + BUFFER_LENGTH - myRead) >= n)
  180. {
  181. int aTopMem = myBuffer + BUFFER_LENGTH - myRead;
  182. if (aTopMem)
  183. {
  184. SHOW("pa_callback > myRead=0x%x, aTopMem=0x%x\n",(int)myRead, (int)aTopMem);
  185. memcpy(outputBuffer, myRead, aTopMem);
  186. }
  187. int aRest = n - aTopMem;
  188. if (aRest)
  189. {
  190. SHOW("pa_callback > myRead=0x%x, aRest=0x%x\n",(int)myRead, (int)aRest);
  191. char* p = (char*)outputBuffer + aTopMem;
  192. memcpy(p, myBuffer, aRest);
  193. }
  194. myRead = myBuffer + aRest;
  195. }
  196. else
  197. {
  198. SHOW_TIME("pa_callback > underflow");
  199. aResult=1; // paComplete;
  200. int aTopMem = myBuffer + BUFFER_LENGTH - myRead;
  201. if (aTopMem)
  202. {
  203. SHOW("pa_callback > myRead=0x%x, aTopMem=0x%x\n",(int)myRead, (int)aTopMem);
  204. memcpy(outputBuffer, myRead, aTopMem);
  205. }
  206. int aRest = aWrite - myBuffer;
  207. if (aRest)
  208. {
  209. SHOW("pa_callback > myRead=0x%x, aRest=0x%x\n",(int)myRead, (int)aRest);
  210. char* p = (char*)outputBuffer + aTopMem;
  211. memcpy(p, myBuffer, aRest);
  212. }
  213. size_t aUsedMem = aTopMem + aRest;
  214. char* p = (char*)outputBuffer + aUsedMem;
  215. memset(p, 0, n - aUsedMem);
  216. // myReadPosition += aUsedMem/(out_channels*sizeof(uint16_t));
  217. myRead = aWrite;
  218. }
  219. }
  220. SHOW("pa_callback > myRead=%x\n",(int)myRead);
  221. // #if USE_PORTAUDIO == 18
  222. // if(aBufferEmpty)
  223. // {
  224. // static int end_timer = 0;
  225. // if(end_timer == 0)
  226. // end_timer = 4;
  227. // if(end_timer > 0)
  228. // {
  229. // end_timer--;
  230. // if(end_timer == 0)
  231. // return(1);
  232. // }
  233. // }
  234. // return(0);
  235. // #else
  236. #ifdef ARCH_BIG
  237. {
  238. // BIG-ENDIAN, swap the order of bytes in each sound sample in the portaudio buffer
  239. int c;
  240. unsigned char *out_ptr;
  241. unsigned char *out_end;
  242. out_ptr = (unsigned char *)outputBuffer;
  243. out_end = out_ptr + framesPerBuffer*2 * out_channels;
  244. while(out_ptr < out_end)
  245. {
  246. c = out_ptr[0];
  247. out_ptr[0] = out_ptr[1];
  248. out_ptr[1] = c;
  249. out_ptr += 2;
  250. }
  251. }
  252. #endif
  253. return(aResult);
  254. //#endif
  255. } // end of WaveCallBack
  256. //>
  257. void wave_flush(void* theHandler)
  258. {
  259. ENTER("wave_flush");
  260. if (my_stream_could_start)
  261. {
  262. // #define buf 1024
  263. // static char a_buffer[buf*2];
  264. // memset(a_buffer,0,buf*2);
  265. // wave_write(theHandler, a_buffer, buf*2);
  266. start_stream();
  267. }
  268. }
  269. //<wave_open_sound
  270. static int wave_open_sound()
  271. {
  272. ENTER("wave_open_sound");
  273. PaError err=paNoError;
  274. PaError active;
  275. #if USE_PORTAUDIO == 18
  276. active = Pa_StreamActive(pa_stream);
  277. #else
  278. active = Pa_IsStreamActive(pa_stream);
  279. #endif
  280. if(active == 1)
  281. {
  282. SHOW_TIME("wave_open_sound > already active");
  283. return(0);
  284. }
  285. if(active < 0)
  286. {
  287. out_channels = 1;
  288. #if USE_PORTAUDIO == 18
  289. // err = Pa_OpenDefaultStream(&pa_stream,0,1,paInt16,SAMPLE_RATE,FRAMES_PER_BUFFER,N_WAV_BUF,pa_callback,(void *)userdata);
  290. PaDeviceID playbackDevice = Pa_GetDefaultOutputDeviceID();
  291. PaError err = Pa_OpenStream( &pa_stream,
  292. /* capture parameters */
  293. paNoDevice,
  294. 0,
  295. paInt16,
  296. NULL,
  297. /* playback parameters */
  298. playbackDevice,
  299. out_channels,
  300. paInt16,
  301. NULL,
  302. /* general parameters */
  303. SAMPLE_RATE, FRAMES_PER_BUFFER, 0,
  304. //paClipOff | paDitherOff,
  305. paNoFlag,
  306. pa_callback, (void *)userdata);
  307. SHOW("wave_open_sound > Pa_OpenDefaultStream(1): err=%d (%s)\n",err, Pa_GetErrorText(err));
  308. if(err == paInvalidChannelCount)
  309. {
  310. SHOW_TIME("wave_open_sound > try stereo");
  311. // failed to open with mono, try stereo
  312. out_channels = 2;
  313. // myOutputParameters.channelCount = out_channels;
  314. PaError err = Pa_OpenStream( &pa_stream,
  315. /* capture parameters */
  316. paNoDevice,
  317. 0,
  318. paInt16,
  319. NULL,
  320. /* playback parameters */
  321. playbackDevice,
  322. out_channels,
  323. paInt16,
  324. NULL,
  325. /* general parameters */
  326. SAMPLE_RATE, FRAMES_PER_BUFFER, 0,
  327. //paClipOff | paDitherOff,
  328. paNoFlag,
  329. pa_callback, (void *)userdata);
  330. // err = Pa_OpenDefaultStream(&pa_stream,0,2,paInt16,
  331. // SAMPLE_RATE,
  332. // FRAMES_PER_BUFFER,
  333. // N_WAV_BUF,pa_callback,(void *)userdata);
  334. SHOW("wave_open_sound > Pa_OpenDefaultStream(2): err=%d (%s)\n",err, Pa_GetErrorText(err));
  335. err=0; // avoid warning
  336. }
  337. mInCallbackFinishedState = false; // v18 only
  338. #else
  339. myOutputParameters.channelCount = out_channels;
  340. unsigned long framesPerBuffer = paFramesPerBufferUnspecified;
  341. err = Pa_OpenStream(
  342. &pa_stream,
  343. NULL, /* no input */
  344. &myOutputParameters,
  345. SAMPLE_RATE,
  346. framesPerBuffer,
  347. paNoFlag,
  348. // paClipOff | paDitherOff,
  349. pa_callback,
  350. (void *)userdata);
  351. if ((err!=paNoError)
  352. && (err!=paInvalidChannelCount)) //err==paUnanticipatedHostError
  353. {
  354. fprintf(stderr, "wave_open_sound > Pa_OpenStream : err=%d (%s)\n",err,Pa_GetErrorText(err));
  355. framesPerBuffer = FRAMES_PER_BUFFER;
  356. err = Pa_OpenStream(
  357. &pa_stream,
  358. NULL, /* no input */
  359. &myOutputParameters,
  360. SAMPLE_RATE,
  361. framesPerBuffer,
  362. paNoFlag,
  363. // paClipOff | paDitherOff,
  364. pa_callback,
  365. (void *)userdata);
  366. }
  367. if(err == paInvalidChannelCount)
  368. {
  369. SHOW_TIME("wave_open_sound > try stereo");
  370. // failed to open with mono, try stereo
  371. out_channels = 2;
  372. myOutputParameters.channelCount = out_channels;
  373. err = Pa_OpenStream(
  374. &pa_stream,
  375. NULL, /* no input */
  376. &myOutputParameters,
  377. SAMPLE_RATE,
  378. framesPerBuffer,
  379. paNoFlag,
  380. // paClipOff | paDitherOff,
  381. pa_callback,
  382. (void *)userdata);
  383. // err = Pa_OpenDefaultStream(&pa_stream,0,2,paInt16,(double)SAMPLE_RATE,FRAMES_PER_BUFFER,pa_callback,(void *)userdata);
  384. }
  385. mInCallbackFinishedState = false;
  386. #endif
  387. }
  388. SHOW("wave_open_sound > %s\n","LEAVE");
  389. return (err != paNoError);
  390. }
  391. //>
  392. //<select_device
  393. #if (USE_PORTAUDIO == 19)
  394. static void update_output_parameters(int selectedDevice, const PaDeviceInfo *deviceInfo)
  395. {
  396. // const PaDeviceInfo *pdi = Pa_GetDeviceInfo(i);
  397. myOutputParameters.device = selectedDevice;
  398. // myOutputParameters.channelCount = pdi->maxOutputChannels;
  399. myOutputParameters.channelCount = 1;
  400. myOutputParameters.sampleFormat = paInt16;
  401. // Latency greater than 100ms for avoiding glitches
  402. // (e.g. when moving a window in a graphical desktop)
  403. // deviceInfo = Pa_GetDeviceInfo(selectedDevice);
  404. if (deviceInfo)
  405. {
  406. double aLatency = deviceInfo->defaultLowOutputLatency;
  407. double aCoeff = round(0.100 / aLatency);
  408. // myOutputParameters.suggestedLatency = aCoeff * aLatency; // to avoid glitches ?
  409. myOutputParameters.suggestedLatency = aLatency; // for faster response ?
  410. SHOW("Device=%d, myOutputParameters.suggestedLatency=%f, aCoeff=%f\n",
  411. selectedDevice,
  412. myOutputParameters.suggestedLatency,
  413. aCoeff);
  414. }
  415. else
  416. {
  417. myOutputParameters.suggestedLatency = (double)0.1; // 100ms
  418. SHOW("Device=%d, myOutputParameters.suggestedLatency=%f (default)\n",
  419. selectedDevice,
  420. myOutputParameters.suggestedLatency);
  421. }
  422. //pdi->defaultLowOutputLatency;
  423. myOutputParameters.hostApiSpecificStreamInfo = NULL;
  424. }
  425. #endif
  426. static void select_device(const char* the_api)
  427. {
  428. ENTER("select_device");
  429. #if (USE_PORTAUDIO == 19)
  430. int numDevices = Pa_GetDeviceCount();
  431. if( numDevices < 0 )
  432. {
  433. SHOW( "ERROR: Pa_CountDevices returned 0x%x\n", numDevices );
  434. assert(0);
  435. }
  436. PaDeviceIndex i=0, selectedIndex=0, defaultAlsaIndex=numDevices;
  437. const PaDeviceInfo *deviceInfo=NULL;
  438. const PaDeviceInfo *selectedDeviceInfo=NULL;
  439. if(option_device_number >= 0)
  440. {
  441. selectedIndex = option_device_number;
  442. selectedDeviceInfo = Pa_GetDeviceInfo(selectedIndex);
  443. }
  444. if(selectedDeviceInfo == NULL)
  445. {
  446. for( i=0; i<numDevices; i++ )
  447. {
  448. deviceInfo = Pa_GetDeviceInfo( i );
  449. if (deviceInfo == NULL)
  450. {
  451. break;
  452. }
  453. const PaHostApiInfo *hostInfo = Pa_GetHostApiInfo( deviceInfo->hostApi );
  454. if (hostInfo && hostInfo->type == paALSA)
  455. {
  456. // Check (once) the default output device
  457. if (defaultAlsaIndex == numDevices)
  458. {
  459. defaultAlsaIndex = hostInfo->defaultOutputDevice;
  460. const PaDeviceInfo *deviceInfo = Pa_GetDeviceInfo( defaultAlsaIndex );
  461. update_output_parameters(defaultAlsaIndex, deviceInfo);
  462. if (Pa_IsFormatSupported(NULL, &myOutputParameters, SAMPLE_RATE) == 0)
  463. {
  464. SHOW( "select_device > ALSA (default), name=%s (#%d)\n", deviceInfo->name, defaultAlsaIndex);
  465. selectedIndex = defaultAlsaIndex;
  466. selectedDeviceInfo = deviceInfo;
  467. break;
  468. }
  469. }
  470. // if the default output device does not match,
  471. // look for the device with the highest number of output channels
  472. SHOW( "select_device > ALSA, i=%d (numDevices=%d)\n", i, numDevices);
  473. update_output_parameters(i, deviceInfo);
  474. if (Pa_IsFormatSupported(NULL, &myOutputParameters, SAMPLE_RATE) == 0)
  475. {
  476. SHOW( "select_device > ALSA, name=%s (#%d)\n", deviceInfo->name, i);
  477. if (!selectedDeviceInfo
  478. || (selectedDeviceInfo->maxOutputChannels < deviceInfo->maxOutputChannels))
  479. {
  480. selectedIndex = i;
  481. selectedDeviceInfo = deviceInfo;
  482. }
  483. }
  484. }
  485. }
  486. }
  487. if (selectedDeviceInfo)
  488. {
  489. update_output_parameters(selectedIndex, selectedDeviceInfo);
  490. }
  491. else
  492. {
  493. i = Pa_GetDefaultOutputDevice();
  494. deviceInfo = Pa_GetDeviceInfo( i );
  495. update_output_parameters(i, deviceInfo);
  496. }
  497. #endif
  498. }
  499. //>
  500. // int wave_Close(void* theHandler)
  501. // {
  502. // SHOW_TIME("WaveCloseSound");
  503. // // PaError active;
  504. // // check whether speaking has finished, and close the stream
  505. // if(pa_stream != NULL)
  506. // {
  507. // Pa_CloseStream(pa_stream);
  508. // pa_stream = NULL;
  509. // init_buffer();
  510. // // #if USE_PORTAUDIO == 18
  511. // // active = Pa_StreamActive(pa_stream);
  512. // // #else
  513. // // active = Pa_IsStreamActive(pa_stream);
  514. // // #endif
  515. // // if(active == 0)
  516. // // {
  517. // // SHOW_TIME("WaveCloseSound > ok, not active");
  518. // // Pa_CloseStream(pa_stream);
  519. // // pa_stream = NULL;
  520. // // return(1);
  521. // // }
  522. // }
  523. // return(0);
  524. // }
  525. //<wave_set_callback_is_output_enabled
  526. void wave_set_callback_is_output_enabled(t_wave_callback* cb)
  527. {
  528. my_callback_is_output_enabled = cb;
  529. }
  530. //>
  531. //<wave_init
  532. // TBD: the arg could be "alsa", "oss",...
  533. void wave_init()
  534. {
  535. ENTER("wave_init");
  536. PaError err;
  537. pa_stream = NULL;
  538. mInCallbackFinishedState = false;
  539. init_buffer();
  540. // PortAudio sound output library
  541. err = Pa_Initialize();
  542. pa_init_err = err;
  543. if(err != paNoError)
  544. {
  545. SHOW_TIME("wave_init > Failed to initialise the PortAudio sound");
  546. }
  547. }
  548. //>
  549. //<wave_open
  550. void* wave_open(const char* the_api)
  551. {
  552. ENTER("wave_open");
  553. static int once=0;
  554. // TBD: the_api (e.g. "alsa") is not used at the moment
  555. // select_device is called once
  556. if (!once)
  557. {
  558. select_device("alsa");
  559. once=1;
  560. }
  561. return((void*)1);
  562. }
  563. //>
  564. //<copyBuffer
  565. static size_t copyBuffer(char* dest, char* src, size_t theSizeInBytes)
  566. {
  567. size_t bytes_written=0;
  568. if(out_channels==1)
  569. {
  570. SHOW("copyBuffer > memcpy %x (%d bytes)\n", (int)myWrite, theSizeInBytes);
  571. memcpy(dest, src, theSizeInBytes);
  572. bytes_written = theSizeInBytes;
  573. }
  574. else
  575. {
  576. SHOW("copyBuffer > memcpy %x (%d bytes)\n", (int)myWrite, 2*theSizeInBytes);
  577. unsigned int i;
  578. uint16_t* a_dest = (uint16_t*)dest;
  579. uint16_t* a_src = (uint16_t*)src;
  580. for(i=0; i<theSizeInBytes/2; i++)
  581. {
  582. a_dest[2*i] = a_src[i];
  583. a_dest[2*i + 1] = a_src[i];
  584. }
  585. bytes_written = 2*theSizeInBytes;
  586. }
  587. return bytes_written;
  588. }
  589. //>
  590. //<wave_write
  591. size_t wave_write(void* theHandler, char* theMono16BitsWaveBuffer, size_t theSize)
  592. {
  593. ENTER("wave_write");
  594. size_t bytes_written = 0;
  595. size_t bytes_to_write = (out_channels==1) ? theSize : theSize*2;
  596. my_stream_could_start = 0;
  597. if(pa_stream == NULL)
  598. {
  599. SHOW_TIME("wave_write > wave_open_sound\n");
  600. if (0 != wave_open_sound())
  601. {
  602. SHOW_TIME("wave_write > wave_open_sound fails!");
  603. return 0;
  604. }
  605. my_stream_could_start=1;
  606. }
  607. else if (!wave_is_busy(NULL))
  608. {
  609. my_stream_could_start = 1;
  610. }
  611. assert(BUFFER_LENGTH >= bytes_to_write);
  612. if (myWrite >= myBuffer + BUFFER_LENGTH)
  613. {
  614. myWrite = myBuffer;
  615. }
  616. size_t aTotalFreeMem=0;
  617. char* aRead = myRead;
  618. SHOW("wave_write > aRead=%x, myWrite=%x\n", (int)aRead, (int)myWrite);
  619. while (1)
  620. {
  621. if (my_callback_is_output_enabled
  622. && (0==my_callback_is_output_enabled()))
  623. {
  624. SHOW_TIME("wave_write > my_callback_is_output_enabled: no!");
  625. return 0;
  626. }
  627. aRead = myRead;
  628. if (myWrite >= aRead)
  629. {
  630. aTotalFreeMem = aRead + BUFFER_LENGTH - myWrite;
  631. }
  632. else
  633. {
  634. aTotalFreeMem = aRead - myWrite;
  635. }
  636. if (aTotalFreeMem>1)
  637. {
  638. // -1 because myWrite must be different of aRead
  639. // otherwise buffer would be considered as empty
  640. aTotalFreeMem -= 1;
  641. }
  642. if (aTotalFreeMem >= bytes_to_write)
  643. {
  644. break;
  645. }
  646. // SHOW_TIME("wave_write > wait");
  647. SHOW("wave_write > wait: aTotalFreeMem=%d\n", aTotalFreeMem);
  648. SHOW("wave_write > aRead=%x, myWrite=%x\n", (int)aRead, (int)myWrite);
  649. usleep(10000);
  650. }
  651. aRead = myRead;
  652. if (myWrite >= aRead)
  653. {
  654. SHOW_TIME("wave_write > myWrite > aRead");
  655. size_t aFreeMem = myBuffer + BUFFER_LENGTH - myWrite;
  656. if (aFreeMem >= bytes_to_write)
  657. {
  658. myWrite += copyBuffer(myWrite, theMono16BitsWaveBuffer, theSize);
  659. }
  660. else
  661. {
  662. int bytes_written = copyBuffer(myWrite, theMono16BitsWaveBuffer, aFreeMem);
  663. myWrite = myBuffer;
  664. myWrite += copyBuffer(myWrite, theMono16BitsWaveBuffer+aFreeMem, bytes_to_write-bytes_written);
  665. }
  666. }
  667. else
  668. {
  669. SHOW_TIME("wave_write > myWrite <= aRead");
  670. myWrite += copyBuffer(myWrite, theMono16BitsWaveBuffer, theSize);
  671. }
  672. bytes_written = theSize;
  673. myWritePosition += theSize/sizeof(uint16_t); // add number of samples
  674. if (my_stream_could_start && (get_used_mem() >= out_channels * sizeof(uint16_t) * FRAMES_PER_BUFFER))
  675. {
  676. start_stream();
  677. }
  678. SHOW_TIME("wave_write > LEAVE");
  679. return bytes_written;
  680. }
  681. //>
  682. //<wave_close
  683. int wave_close(void* theHandler)
  684. {
  685. SHOW_TIME("wave_close > ENTER");
  686. static int aStopStreamCount = 0;
  687. #if (USE_PORTAUDIO == 19)
  688. if( pa_stream == NULL )
  689. {
  690. SHOW_TIME("wave_close > LEAVE (NULL stream)");
  691. return 0;
  692. }
  693. if( Pa_IsStreamStopped( pa_stream ) )
  694. {
  695. SHOW_TIME("wave_close > LEAVE (stopped)");
  696. return 0;
  697. }
  698. #else
  699. if( pa_stream == NULL )
  700. {
  701. SHOW_TIME("wave_close > LEAVE (NULL stream)");
  702. return 0;
  703. }
  704. if( Pa_StreamActive( pa_stream ) == false && mInCallbackFinishedState == false )
  705. {
  706. SHOW_TIME("wave_close > LEAVE (not active)");
  707. return 0;
  708. }
  709. #endif
  710. // Avoid race condition by making sure this function only
  711. // gets called once at a time
  712. aStopStreamCount++;
  713. if (aStopStreamCount != 1)
  714. {
  715. SHOW_TIME("wave_close > LEAVE (stopStreamCount)");
  716. return 0;
  717. }
  718. // Comment from Audacity-1.2.4b adapted to the eSpeak context.
  719. //
  720. // We got here in one of two ways:
  721. //
  722. // 1. The calling program calls the espeak_Cancel function and we
  723. // therefore want to stop as quickly as possible.
  724. // So we use AbortStream(). If this is
  725. // the case the portaudio stream is still in the Running state
  726. // (see PortAudio state machine docs).
  727. //
  728. // 2. The callback told PortAudio to stop the stream since it had
  729. // reached the end of the selection.
  730. // The event polling thread discovered this by noticing that
  731. // wave_is_busy() returned false.
  732. // wave_is_busy() (which calls Pa_GetStreamActive()) will not return
  733. // false until all buffers have finished playing, so we can call
  734. // AbortStream without losing any samples. If this is the case
  735. // we are in the "callback finished state" (see PortAudio state
  736. // machine docs).
  737. //
  738. // The moral of the story: We can call AbortStream safely, without
  739. // losing samples.
  740. //
  741. // DMM: This doesn't seem to be true; it seems to be necessary to
  742. // call StopStream if the callback brought us here, and AbortStream
  743. // if the user brought us here.
  744. //
  745. #if (USE_PORTAUDIO == 19)
  746. if (pa_stream)
  747. {
  748. Pa_AbortStream( pa_stream );
  749. SHOW_TIME("wave_close > Pa_AbortStream (end)");
  750. Pa_CloseStream( pa_stream );
  751. SHOW_TIME("wave_close > Pa_CloseStream (end)");
  752. pa_stream = NULL;
  753. mInCallbackFinishedState = false;
  754. }
  755. #else
  756. if (pa_stream)
  757. {
  758. if (mInCallbackFinishedState)
  759. {
  760. Pa_StopStream( pa_stream );
  761. SHOW_TIME("wave_close > Pa_StopStream (end)");
  762. }
  763. else
  764. {
  765. Pa_AbortStream( pa_stream );
  766. SHOW_TIME("wave_close > Pa_AbortStream (end)");
  767. }
  768. Pa_CloseStream( pa_stream );
  769. SHOW_TIME("wave_close > Pa_CloseStream (end)");
  770. pa_stream = NULL;
  771. mInCallbackFinishedState = false;
  772. }
  773. #endif
  774. init_buffer();
  775. aStopStreamCount = 0; // last action
  776. SHOW_TIME("wave_close > LEAVE");
  777. return 0;
  778. }
  779. // int wave_close(void* theHandler)
  780. // {
  781. // ENTER("wave_close");
  782. // if(pa_stream != NULL)
  783. // {
  784. // PaError err = Pa_AbortStream(pa_stream);
  785. // SHOW_TIME("wave_close > Pa_AbortStream (end)");
  786. // SHOW("wave_close Pa_AbortStream > err=%d\n",err);
  787. // while(1)
  788. // {
  789. // PaError active;
  790. // #if USE_PORTAUDIO == 18
  791. // active = Pa_StreamActive(pa_stream);
  792. // #else
  793. // active = Pa_IsStreamActive(pa_stream);
  794. // #endif
  795. // if (active != 1)
  796. // {
  797. // break;
  798. // }
  799. // SHOW("wave_close > active=%d\n",err);
  800. // usleep(10000); /* sleep until playback has finished */
  801. // }
  802. // err = Pa_CloseStream( pa_stream );
  803. // SHOW_TIME("wave_close > Pa_CloseStream (end)");
  804. // SHOW("wave_close Pa_CloseStream > err=%d\n",err);
  805. // pa_stream = NULL;
  806. // init_buffer();
  807. // }
  808. // return 0;
  809. // }
  810. //>
  811. //<wave_is_busy
  812. int wave_is_busy(void* theHandler)
  813. {
  814. PaError active=0;
  815. SHOW_TIME("wave_is_busy");
  816. if (pa_stream)
  817. {
  818. #if USE_PORTAUDIO == 18
  819. active = Pa_StreamActive(pa_stream)
  820. && (mInCallbackFinishedState == false);
  821. #else
  822. active = Pa_IsStreamActive(pa_stream)
  823. && (mInCallbackFinishedState == false);
  824. #endif
  825. }
  826. SHOW("wave_is_busy: %d\n",active);
  827. return (active==1);
  828. }
  829. //>
  830. //<wave_terminate
  831. void wave_terminate()
  832. {
  833. ENTER("wave_terminate");
  834. Pa_Terminate();
  835. }
  836. //>
  837. //<wave_get_read_position, wave_get_write_position, wave_get_remaining_time
  838. uint32_t wave_get_read_position(void* theHandler)
  839. {
  840. SHOW("wave_get_read_position > myReadPosition=%u\n", myReadPosition);
  841. return myReadPosition;
  842. }
  843. uint32_t wave_get_write_position(void* theHandler)
  844. {
  845. SHOW("wave_get_write_position > myWritePosition=%u\n", myWritePosition);
  846. return myWritePosition;
  847. }
  848. int wave_get_remaining_time(uint32_t sample, uint32_t* time)
  849. {
  850. double a_time=0;
  851. if (!time || !pa_stream)
  852. {
  853. SHOW("event get_remaining_time> %s\n","audio device not available");
  854. return -1;
  855. }
  856. if (sample > myReadPosition)
  857. {
  858. // TBD: take in account time suplied by portaudio V18 API
  859. a_time = sample - myReadPosition;
  860. a_time = 0.5 + (a_time * 1000.0) / SAMPLE_RATE;
  861. }
  862. else
  863. {
  864. a_time = 0;
  865. }
  866. SHOW("wave_get_remaining_time > sample=%d, time=%d\n", sample, (uint32_t)a_time);
  867. *time = (uint32_t)a_time;
  868. return 0;
  869. }
  870. //>
  871. //<wave_test_get_write_buffer
  872. void *wave_test_get_write_buffer()
  873. {
  874. return myWrite;
  875. }
  876. #else
  877. // notdef USE_PORTAUDIO
  878. void wave_init() {}
  879. void* wave_open(const char* the_api) {return (void *)1;}
  880. size_t wave_write(void* theHandler, char* theMono16BitsWaveBuffer, size_t theSize) {return theSize;}
  881. int wave_close(void* theHandler) {return 0;}
  882. int wave_is_busy(void* theHandler) {return 0;}
  883. void wave_terminate() {}
  884. uint32_t wave_get_read_position(void* theHandler) {return 0;}
  885. uint32_t wave_get_write_position(void* theHandler) {return 0;}
  886. void wave_flush(void* theHandler) {}
  887. typedef int (t_wave_callback)(void);
  888. void wave_set_callback_is_output_enabled(t_wave_callback* cb) {}
  889. extern void* wave_test_get_write_buffer() {return NULL;}
  890. int wave_get_remaining_time(uint32_t sample, uint32_t* time)
  891. {
  892. if (!time) return(-1);
  893. *time = (uint32_t)0;
  894. return 0;
  895. }
  896. #endif // of USE_PORTAUDIO
  897. //>
  898. //<clock_gettime2, add_time_in_ms
  899. void clock_gettime2(struct timespec *ts)
  900. {
  901. struct timeval tv;
  902. if (!ts)
  903. {
  904. return;
  905. }
  906. assert (gettimeofday(&tv, NULL) != -1);
  907. ts->tv_sec = tv.tv_sec;
  908. ts->tv_nsec = tv.tv_usec*1000;
  909. }
  910. void add_time_in_ms(struct timespec *ts, int time_in_ms)
  911. {
  912. if (!ts)
  913. {
  914. return;
  915. }
  916. uint64_t t_ns = (uint64_t)ts->tv_nsec + 1000000 * (uint64_t)time_in_ms;
  917. while(t_ns >= ONE_BILLION)
  918. {
  919. SHOW("event > add_time_in_ms ns: %d sec %Lu nsec \n", ts->tv_sec, t_ns);
  920. ts->tv_sec += 1;
  921. t_ns -= ONE_BILLION;
  922. }
  923. ts->tv_nsec = (long int)t_ns;
  924. }
  925. #endif // USE_ASYNC
  926. //>