mirror of
https://github.com/HarbourMasters/Shipwright
synced 2026-09-29 03:17:52 -04:00
Interrupt espeak on a new utterance (#7207)
The SAPI and AVSpeechSynthesizer backends both drop what they are saying when a new utterance arrives (SPF_PURGEBEFORESPEAK, stopSpeakingAtBoundary). espeak never did, so on Linux every menu item scrolled past queued another utterance with no way to skip ahead. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -13,9 +13,10 @@ bool ESpeakSpeechSynthesizer::DoInit() {
|
||||
this->Initialize = (speak_Initialize)dlsym(espeak, "espeak_Initialize");
|
||||
this->SetVoiceByProperties = (speak_SetVoiceByProperties)dlsym(espeak, "espeak_SetVoiceByProperties");
|
||||
this->Synth = (speak_Synth)dlsym(espeak, "espeak_Synth");
|
||||
this->Cancel = (speak_Cancel)dlsym(espeak, "espeak_Cancel");
|
||||
this->Terminate = (speak_Terminate)dlsym(espeak, "espeak_Terminate");
|
||||
if (this->Initialize == NULL || this->SetVoiceByProperties == NULL || this->Synth == NULL ||
|
||||
this->Terminate == NULL) {
|
||||
this->Cancel == NULL || this->Terminate == NULL) {
|
||||
SPDLOG_INFO("Failed to load espeak-ng");
|
||||
dlclose(espeak);
|
||||
return false;
|
||||
@@ -39,6 +40,10 @@ void ESpeakSpeechSynthesizer::Speak(const char* text, const char* language) {
|
||||
if (this->espeak == NULL) {
|
||||
SPDLOG_INFO("Spoken Text ({}): {}", language, text);
|
||||
} else {
|
||||
// Match the SAPI and AVSpeechSynthesizer backends, which both drop what they are saying when a new
|
||||
// utterance arrives. Without this, scrolling a menu queues one utterance per item with no way to skip.
|
||||
this->Cancel();
|
||||
|
||||
if (language != this->mLanguage) {
|
||||
espeak_VOICE voice = { .languages = language };
|
||||
if (this->SetVoiceByProperties(&voice)) {
|
||||
|
||||
@@ -12,6 +12,7 @@ typedef ESPEAK_API espeak_ERROR (*speak_SetVoiceByProperties)(espeak_VOICE* voic
|
||||
typedef ESPEAK_API espeak_ERROR (*speak_Synth)(const void* text, size_t size, unsigned int position,
|
||||
espeak_POSITION_TYPE position_type, unsigned int end_position,
|
||||
unsigned int flags, unsigned int* unique_identifier, void* user_data);
|
||||
typedef ESPEAK_API espeak_ERROR (*speak_Cancel)(void);
|
||||
}
|
||||
|
||||
class ESpeakSpeechSynthesizer : public SpeechSynthesizer {
|
||||
@@ -30,5 +31,6 @@ class ESpeakSpeechSynthesizer : public SpeechSynthesizer {
|
||||
speak_Initialize Initialize = NULL;
|
||||
speak_SetVoiceByProperties SetVoiceByProperties = NULL;
|
||||
speak_Synth Synth = NULL;
|
||||
speak_Cancel Cancel = NULL;
|
||||
speak_Terminate Terminate = NULL;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user