commit f9ab812e00549640ebf7d6f9416e151827ce5294
Author: Reece H. Dunn <msclrhd@gmail.com>
Date:   Sat Dec 24 09:00:55 2016 +0000

    issue 172: fix sluggish speech for stopped speech.
    
    This restores the behaviour removed in commit
    ca831d236a4eed5648254329554affac143a1740.
    
    When using eSpeak for audio and eSpeak in a server, using the async
    speech requests, that code stopped the audio as soon as possible
    from a cancel request. This allows servers like brltty to be more
    responsive.

--- a/src/libespeak-ng/fifo.c
+++ b/src/libespeak-ng/fifo.c
@@ -244,6 +244,10 @@ static espeak_ng_STATUS close_stream()
 			status = a_status;
 
 		if (a_stop_is_required) {
+			// stop the audio early, to be more responsive when using eSpeak NG
+			// for audio.
+			close_audio();
+
 			// acknowledge the stop request
 			a_status = sem_post(&my_sem_stop_is_acknowledged);
 			if (status == ENS_OK)
--- a/src/libespeak-ng/speech.c
+++ b/src/libespeak-ng/speech.c
@@ -81,6 +81,15 @@ int (*phoneme_callback)(const char *) =
 char path_home[N_PATH_HOME]; // this is the espeak-ng-data directory
 extern int saved_parameters[N_SPEECH_PARAM]; // Parameters saved on synthesis start
 
+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
+}
+
 static int dispatch_audio(short *outbuf, int length, espeak_EVENT *event)
 {
 	int a_wave_can_be_played = 1;
--- a/src/libespeak-ng/speech.h
+++ b/src/libespeak-ng/speech.h
@@ -65,6 +65,8 @@ typedef struct {
 } MNEM_TAB;
 int LookupMnem(MNEM_TAB *table, const char *string);
 
+void close_audio(void);
+
 extern char path_home[N_PATH_HOME];    // this is the espeak-ng-data directory
 
 extern ESPEAK_NG_API void strncpy0(char *to, const char *from, int size);


commit a48576a3640f9014760888bb30a924a3e2163e57
Author: Reece H. Dunn <msclrhd@gmail.com>
Date:   Fri Dec 23 18:56:58 2016 +0000

    Return ENS_SPEECH_STOPPED from Synthesize when the speech callback returns >1 to stop the audio.

diff --git a/src/include/espeak-ng/espeak_ng.h b/src/include/espeak-ng/espeak_ng.h
index cdf27ec5..942fe175 100644
--- a/src/include/espeak-ng/espeak_ng.h
+++ b/src/include/espeak-ng/espeak_ng.h
@@ -55,6 +55,7 @@ typedef enum {
 	ENS_UNSUPPORTED_PHON_FORMAT  = 0x10000BFF,
 	ENS_NO_SPECT_FRAMES          = 0x10000CFF,
 	ENS_EMPTY_PHONEME_MANIFEST   = 0x10000DFF,
+	ENS_SPEECH_STOPPED           = 0x10000EFF,
 } espeak_ng_STATUS;
 
 typedef enum {
diff --git a/src/libespeak-ng/espeak_api.c b/src/libespeak-ng/espeak_api.c
index 6ff855b8..ec926791 100644
--- a/src/libespeak-ng/espeak_api.c
+++ b/src/libespeak-ng/espeak_api.c
@@ -37,6 +37,7 @@ static espeak_ERROR status_to_espeak_error(espeak_ng_STATUS status)
 	switch (status)
 	{
 	case ENS_OK:                     return EE_OK;
+	case ENS_SPEECH_STOPPED:         return EE_OK;
 	case ENS_VOICE_NOT_FOUND:        return EE_NOT_FOUND;
 	case ENS_MBROLA_NOT_FOUND:       return EE_NOT_FOUND;
 	case ENS_MBROLA_VOICE_NOT_FOUND: return EE_NOT_FOUND;
diff --git a/src/libespeak-ng/speech.c b/src/libespeak-ng/speech.c
index a021bfc5..73d89a4d 100644
--- a/src/libespeak-ng/speech.c
+++ b/src/libespeak-ng/speech.c
@@ -410,7 +410,7 @@ static espeak_ng_STATUS Synthesize(unsigned int unique_identifier, const void *t
 			finished = synth_callback((short *)outbuf, length, event_list);
 		if (finished) {
 			SpeakNextClause(NULL, 0, 2); // stop
-			break;
+			return ENS_SPEECH_STOPPED;
 		}
 
 		if (Generate(phoneme_list, &n_phoneme_list, 1) == 0) {
@@ -428,12 +428,11 @@ static espeak_ng_STATUS Synthesize(unsigned int unique_identifier, const void *t
 							return ENS_AUDIO_ERROR;
 					} else if (synth_callback)
 						synth_callback(NULL, 0, event_list); // NULL buffer ptr indicates end of data
-					break;
+					return ENS_OK;
 				}
 			}
 		}
 	}
-	return ENS_OK;
 }
 
 void MarkerEvent(int type, unsigned int char_position, int value, int value2, unsigned char *out_ptr)


commit bc674081cd0e787e364989baab82df0ce883abec
Author: Reece H. Dunn <msclrhd@gmail.com>
Date:   Fri Dec 23 19:17:18 2016 +0000

    Check the return from synth_callback in the second call to that function in Synthesize.

diff --git a/src/libespeak-ng/speech.c b/src/libespeak-ng/speech.c
index 73d89a4d..f181420c 100644
--- a/src/libespeak-ng/speech.c
+++ b/src/libespeak-ng/speech.c
@@ -423,11 +423,16 @@ static espeak_ng_STATUS Synthesize(unsigned int unique_identifier, const void *t
 				event_list[0].user_data = my_user_data;
 
 				if (SpeakNextClause(NULL, NULL, 1) == 0) {
+					finished = 0;
 					if ((my_mode & ENOUTPUT_MODE_SPEAK_AUDIO) == ENOUTPUT_MODE_SPEAK_AUDIO) {
 						if (dispatch_audio(NULL, 0, NULL) < 0)
 							return ENS_AUDIO_ERROR;
 					} else if (synth_callback)
-						synth_callback(NULL, 0, event_list); // NULL buffer ptr indicates end of data
+						finished = synth_callback(NULL, 0, event_list); // NULL buffer ptr indicates end of data
+					if (finished) {
+						SpeakNextClause(NULL, 0, 2); // stop
+						return ENS_SPEECH_STOPPED;
+					}
 					return ENS_OK;
 				}
 			}

commit d2478cc453750e4081e0b6eaeca1442b8abaa92f
Author: Reece H. Dunn <msclrhd@gmail.com>
Date:   Fri Dec 23 19:34:13 2016 +0000

    Flush the audio if speech has stopped, drain the audio if speech is still active.

diff --git a/src/libespeak-ng/speech.c b/src/libespeak-ng/speech.c
index f181420c..ef26dc48 100644
--- a/src/libespeak-ng/speech.c
+++ b/src/libespeak-ng/speech.c
@@ -503,7 +503,9 @@ espeak_ng_STATUS sync_espeak_Synth(unsigned int unique_identifier, const void *t
 	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) {
-		int error = audio_object_drain(my_audio);
+		int error = (aStatus == ENS_SPEECH_STOPPED)
+		          ? audio_object_flush(my_audio)
+		          : audio_object_drain(my_audio);
 		if (error != 0)
 			fprintf(stderr, "error: %s\n", audio_object_strerror(my_audio, error));
 	}
