From 7e065ac8d778770e4dba903f93076a254e8f81e6 Mon Sep 17 00:00:00 2001 From: Demur Rumed Date: Sat, 19 Apr 2025 16:15:30 +0000 Subject: [PATCH] dlopen --- soh/CMakeLists.txt | 1 - .../ESpeakSpeechSynthesizer.cpp | 45 ++++++++++++++----- .../ESpeakSpeechSynthesizer.h | 19 +++++++- 3 files changed, 52 insertions(+), 13 deletions(-) diff --git a/soh/CMakeLists.txt b/soh/CMakeLists.txt index b3faf9fa2..07109a918 100644 --- a/soh/CMakeLists.txt +++ b/soh/CMakeLists.txt @@ -324,7 +324,6 @@ endif() if (ESPEAK) add_compile_definitions(ESPEAK=1) - target_link_libraries(${PROJECT_NAME} PUBLIC espeak-ng) endif() target_include_directories(${PROJECT_NAME} PRIVATE assets diff --git a/soh/soh/Enhancements/speechsynthesizer/ESpeakSpeechSynthesizer.cpp b/soh/soh/Enhancements/speechsynthesizer/ESpeakSpeechSynthesizer.cpp index b7dc3d932..f92959ff1 100644 --- a/soh/soh/Enhancements/speechsynthesizer/ESpeakSpeechSynthesizer.cpp +++ b/soh/soh/Enhancements/speechsynthesizer/ESpeakSpeechSynthesizer.cpp @@ -1,26 +1,49 @@ #include "ESpeakSpeechSynthesizer.h" -extern "C" { -#include -} +#include +#include ESpeakSpeechSynthesizer::ESpeakSpeechSynthesizer() { } bool ESpeakSpeechSynthesizer::DoInit() { - return espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 100, NULL, 0) != -1; + void* espeak = dlopen("libespeak-ng.so", RTLD_LAZY | RTLD_LOCAL); + if (espeak != NULL) { + 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->Terminate = (speak_Terminate)dlsym(espeak, "espeak_Terminate"); + if (this->Initialize == NULL || this->SetVoiceByProperties == NULL || this->Synth == NULL || + this->Terminate == NULL) { + lusprintf(__FILE__, __LINE__, 2, "Failed to load espeak-ng"); + dlclose(espeak); + return false; + } else { + this->espeak = espeak; + return this->Initialize(AUDIO_OUTPUT_PLAYBACK, 100, NULL, 0) != -1; + } + } + return true; } void ESpeakSpeechSynthesizer::DoUninitialize() { - espeak_Terminate(); + if (this->espeak != NULL) { + this->Terminate(); + dlclose(this->espeak); + this->espeak = NULL; + } } void ESpeakSpeechSynthesizer::Speak(const char* text, const char* language) { - if (language != this->mLanguage) { - espeak_VOICE voice = { .languages = language }; - if (espeak_SetVoiceByProperties(&voice)) { - return; + if (this->espeak == NULL) { + lusprintf(__FILE__, __LINE__, 2, "Spoken Text (%s): %s", language, text); + } else { + if (language != this->mLanguage) { + espeak_VOICE voice = { .languages = language }; + if (this->SetVoiceByProperties(&voice)) { + return; + } + this->mLanguage = language; } - this->mLanguage = language; + this->Synth(text, 100, 0, POS_CHARACTER, 0, espeakCHARS_UTF8, NULL, NULL); } - espeak_Synth(text, 100, 0, POS_CHARACTER, 0, espeakCHARS_UTF8, NULL, NULL); } diff --git a/soh/soh/Enhancements/speechsynthesizer/ESpeakSpeechSynthesizer.h b/soh/soh/Enhancements/speechsynthesizer/ESpeakSpeechSynthesizer.h index a7f454946..0844b9293 100644 --- a/soh/soh/Enhancements/speechsynthesizer/ESpeakSpeechSynthesizer.h +++ b/soh/soh/Enhancements/speechsynthesizer/ESpeakSpeechSynthesizer.h @@ -2,6 +2,18 @@ #include "SpeechSynthesizer.h" +extern "C" { +#include + +// C23 typeof could help here +typedef ESPEAK_API int (*speak_Initialize)(espeak_AUDIO_OUTPUT output, int buflength, const char* path, int options); +typedef ESPEAK_API espeak_ERROR (*speak_Terminate)(void); +typedef ESPEAK_API espeak_ERROR (*speak_SetVoiceByProperties)(espeak_VOICE* voice_spec); +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); +} + class ESpeakSpeechSynthesizer : public SpeechSynthesizer { public: ESpeakSpeechSynthesizer(); @@ -13,5 +25,10 @@ class ESpeakSpeechSynthesizer : public SpeechSynthesizer { void DoUninitialize(void); private: - const char* mLanguage; + const char* mLanguage = NULL; + void* espeak = NULL; + speak_Initialize Initialize = NULL; + speak_SetVoiceByProperties SetVoiceByProperties = NULL; + speak_Synth Synth = NULL; + speak_Terminate Terminate = NULL; };