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.cpp 28KB

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