https://github.com/espeak-ng/espeak-ng/issues/172 Upstream pcaudiolib made audio_object_flush actually do the close/reopen, but this is not released yet (will be in 1.1). This however poses threading issues with ALSA: audio_object_flush is currently called in the application thread while it must be done in the say_thread for proper safety. espeak-ng 1.49.2 added a cancel_audio() function which calls audio_object_flush and is called from close_stream(). That is however not enough for the stream to get interrupted on cancel (and we don't want to use upstream's current fix mentioned above this it poses threading issues). --- src/libespeak-ng/fifo.c | 4 ++++ src/libespeak-ng/speech.c | 23 +++++++++++++++++++++++ src/libespeak-ng/speech.h | 3 +++ 3 files changed, 30 insertions(+) --- a/src/libespeak-ng/fifo.c +++ b/src/libespeak-ng/fifo.c @@ -338,6 +338,10 @@ static void *say_thread(void *p) } if (my_stop_is_required || my_terminate_is_required) { + // restart the audio early, to be more responsive when using eSpeak NG + // for audio. + close_audio(); + open_audio(); // no mutex required since the stop command is synchronous // and waiting for my_cond_stop_is_acknowledged init(1); --- a/src/libespeak-ng/speech.c +++ b/src/libespeak-ng/speech.c @@ -98,6 +98,28 @@ void cancel_audio(void) #endif } +void close_audio(void) +{ +#ifdef HAVE_PCAUDIOLIB_AUDIO_H + if ((my_mode & ENOUTPUT_MODE_SPEAK_AUDIO) == ENOUTPUT_MODE_SPEAK_AUDIO) { + audio_object_close(my_audio); + } +#endif +} + +void open_audio(void) +{ +#ifdef HAVE_PCAUDIOLIB_AUDIO_H + if ((my_mode & ENOUTPUT_MODE_SPEAK_AUDIO) == ENOUTPUT_MODE_SPEAK_AUDIO) { + int error = audio_object_open(my_audio, AUDIO_OBJECT_FORMAT_S16LE, voice_samplerate, 1); + if (error != 0) { + fprintf(stderr, "error: %s\n", audio_object_strerror(my_audio, error)); + err = ENS_AUDIO_ERROR; + } + } +#endif +} + static int dispatch_audio(short *outbuf, int length, espeak_EVENT *event) { int a_wave_can_be_played = 1; @@ -566,6 +588,7 @@ espeak_ng_STATUS sync_espeak_Synth(unsig espeak_ng_STATUS aStatus = Synthesize(unique_identifier, text, flags); #ifdef HAVE_PCAUDIOLIB_AUDIO_H if ((my_mode & ENOUTPUT_MODE_SPEAK_AUDIO) == ENOUTPUT_MODE_SPEAK_AUDIO) { + /* FIXME: This drain poses cancelling problems for end of speechs */ int error = (aStatus == ENS_SPEECH_STOPPED) ? audio_object_flush(my_audio) : audio_object_drain(my_audio); --- a/src/libespeak-ng/speech.h +++ b/src/libespeak-ng/speech.h @@ -68,6 +68,9 @@ const char *LookupMnemName(MNEM_TAB *tab void cancel_audio(void); +void close_audio(void); +void open_audio(void); + extern char path_home[N_PATH_HOME]; // this is the espeak-ng-data directory extern ESPEAK_NG_API int GetFileLength(const char *filename);