Package: espeak-ng / 1.49.2+dfsg-8

fix-cancel Patch series | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
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
@@ -336,6 +336,10 @@ static void *say_thread(void *p)
 		}
 
 		if (my_stop_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
@@ -92,6 +92,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;
@@ -528,6 +550,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 void strncpy0(char *to, const char *from, int size);