From 108c28ae08bdffd4861f42cdf42374bb00c77bb7 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Tue, 1 Mar 2022 01:28:38 +0100 Subject: [PATCH] Throttle on EE_BUFFER_FULL errors When espeak returns EE_BUFFER_FULL we should just wait a bit before retrying. Also, we don't want to lose the current entry. We however want to wake up as soon as possible on stop request. --- src/espeak.c | 24 ++++++++++++++++++++---- src/espeakup.c | 1 + src/espeakup.h | 1 + src/softsynth.c | 1 + 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/espeak.c b/src/espeak.c index 135c6b5..b4b58ca 100644 --- a/src/espeak.c +++ b/src/espeak.c @@ -325,16 +325,16 @@ static void reinitialize_espeak(struct synth_t *s) return; } +static struct espeak_entry_t *current = NULL; static void queue_process_entry(struct synth_t *s) { - espeak_ERROR error; + espeak_ERROR error = EE_OK; char markbuff[50]; - static struct espeak_entry_t *current = NULL; if (current != queue_peek(synth_queue)) { if (current) free_espeak_entry(current); - current = (struct espeak_entry_t *) queue_remove(synth_queue); + current = queue_peek(synth_queue); } pthread_mutex_unlock(&queue_guard); @@ -386,9 +386,25 @@ static void queue_process_entry(struct synth_t *s) break; } + pthread_mutex_lock(&queue_guard); if (error == EE_OK) { + /* Processed, drop it */ + struct espeak_entry_t *unqueued = queue_remove(synth_queue); + assert(unqueued == current); free_espeak_entry(current); current = NULL; + } else { + if (error == EE_BUFFER_FULL) + { + /* Give speak a little break before retrying */ + struct timespec timeout; + clock_gettime(CLOCK_REALTIME, &timeout); + timeout.tv_sec++; + /* But wake up immediately if we have to stop */ + pthread_cond_timedwait(&wake_stop, &queue_guard, &timeout); + } + else + fprintf(stderr, "espeak error: %d\n", error); } } @@ -450,6 +466,7 @@ void *espeak_thread(void *arg) pthread_cond_wait(&runner_awake, &queue_guard); if (stop_requested) { + current = NULL; stop_speech(); synth_queue_clear(); stop_requested = 0; @@ -458,7 +475,6 @@ void *espeak_thread(void *arg) while (should_run && queue_peek(synth_queue) && !stop_requested) { queue_process_entry(s); - pthread_mutex_lock(&queue_guard); } } pthread_cond_signal(&stop_acknowledged); diff --git a/src/espeakup.c b/src/espeakup.c index 86b3a88..baeee11 100644 --- a/src/espeakup.c +++ b/src/espeakup.c @@ -40,6 +40,7 @@ volatile int should_run = 1; espeak_AUDIO_OUTPUT audio_mode; pthread_cond_t runner_awake = PTHREAD_COND_INITIALIZER; +pthread_cond_t wake_stop = PTHREAD_COND_INITIALIZER; pthread_cond_t stop_acknowledged = PTHREAD_COND_INITIALIZER; pthread_mutex_t queue_guard = PTHREAD_MUTEX_INITIALIZER; diff --git a/src/espeakup.h b/src/espeakup.h index 58d0f6e..62a5ca8 100644 --- a/src/espeakup.h +++ b/src/espeakup.h @@ -99,6 +99,7 @@ extern int self_pipe_fds[2]; #define PIPE_WRITE_FD (self_pipe_fds[1]) extern pthread_cond_t runner_awake; +extern pthread_cond_t wake_stop; extern pthread_cond_t stop_acknowledged; extern pthread_mutex_t queue_guard; diff --git a/src/softsynth.c b/src/softsynth.c index 9eb75a4..ca2e47e 100644 --- a/src/softsynth.c +++ b/src/softsynth.c @@ -228,6 +228,7 @@ static void request_espeak_stop(void) pthread_mutex_lock(&queue_guard); stop_requested = 1; pthread_cond_signal(&runner_awake); // Wake runner, if necessary. + pthread_cond_signal(&wake_stop); // Wake runner, if necessary. while (should_run && stop_requested) // wait for acknowledgement. pthread_cond_wait(&stop_acknowledged, &queue_guard);