/[zanavi_public1]/navit/navit/support/espeak/wave.c
ZANavi

Contents of /navit/navit/support/espeak/wave.c

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
svn:executable *

   
Visit the ZANavi Wiki