Browse Source

[Linux/TTS] Cache TTS voice list.

bruvzg 2 years ago
parent
commit
e15f37945b
2 changed files with 41 additions and 24 deletions
  1. 33 24
      platform/linuxbsd/tts_linux.cpp
  2. 8 0
      platform/linuxbsd/tts_linux.h

+ 33 - 24
platform/linuxbsd/tts_linux.cpp

@@ -101,6 +101,24 @@ void TTS_Linux::speech_event_callback(size_t p_msg_id, size_t p_client_id, SPDNo
 	}
 }
 
+void TTS_Linux::_load_voices() {
+	if (!voices_loaded) {
+		SPDVoice **spd_voices = spd_list_synthesis_voices(synth);
+		if (spd_voices != nullptr) {
+			SPDVoice **voices_ptr = spd_voices;
+			while (*voices_ptr != nullptr) {
+				VoiceInfo vi;
+				vi.language = String::utf8((*voices_ptr)->language);
+				vi.variant = String::utf8((*voices_ptr)->variant);
+				voices[String::utf8((*voices_ptr)->name)] = vi;
+				voices_ptr++;
+			}
+			free_spd_voices(spd_voices);
+		}
+		voices_loaded = true;
+	}
+}
+
 void TTS_Linux::_speech_event(size_t p_msg_id, size_t p_client_id, int p_type) {
 	_THREAD_SAFE_METHOD_
 
@@ -123,18 +141,13 @@ void TTS_Linux::_speech_event(size_t p_msg_id, size_t p_client_id, int p_type) {
 		// Inject index mark after each word.
 		String text;
 		String language;
-		SPDVoice **voices = spd_list_synthesis_voices(synth);
-		if (voices != nullptr) {
-			SPDVoice **voices_ptr = voices;
-			while (*voices_ptr != nullptr) {
-				if (String::utf8((*voices_ptr)->name) == message.voice) {
-					language = String::utf8((*voices_ptr)->language);
-					break;
-				}
-				voices_ptr++;
-			}
-			free_spd_voices(voices);
+
+		_load_voices();
+		const VoiceInfo *voice = voices.getptr(message.voice);
+		if (voice) {
+			language = voice->language;
 		}
+
 		PackedInt32Array breaks = TS->string_get_word_breaks(message.text, language);
 		for (int i = 0; i < breaks.size(); i += 2) {
 			const int start = breaks[i];
@@ -174,21 +187,17 @@ Array TTS_Linux::get_voices() const {
 	_THREAD_SAFE_METHOD_
 
 	ERR_FAIL_COND_V(!synth, Array());
+	const_cast<TTS_Linux *>(this)->_load_voices();
+
 	Array list;
-	SPDVoice **voices = spd_list_synthesis_voices(synth);
-	if (voices != nullptr) {
-		SPDVoice **voices_ptr = voices;
-		while (*voices_ptr != nullptr) {
-			Dictionary voice_d;
-			voice_d["name"] = String::utf8((*voices_ptr)->name);
-			voice_d["id"] = String::utf8((*voices_ptr)->name);
-			voice_d["language"] = String::utf8((*voices_ptr)->language) + "_" + String::utf8((*voices_ptr)->variant);
-			list.push_back(voice_d);
-
-			voices_ptr++;
-		}
-		free_spd_voices(voices);
+	for (const KeyValue<String, VoiceInfo> &E : voices) {
+		Dictionary voice_d;
+		voice_d["name"] = E.key;
+		voice_d["id"] = E.key;
+		voice_d["language"] = E.value.language + "_" + E.value.variant;
+		list.push_back(voice_d);
 	}
+
 	return list;
 }
 

+ 8 - 0
platform/linuxbsd/tts_linux.h

@@ -55,6 +55,13 @@ class TTS_Linux : public Object {
 	int last_msg_id = -1;
 	HashMap<int, int> ids;
 
+	struct VoiceInfo {
+		String language;
+		String variant;
+	};
+	bool voices_loaded = false;
+	HashMap<String, VoiceInfo> voices;
+
 	Thread init_thread;
 
 	static void speech_init_thread_func(void *p_userdata);
@@ -64,6 +71,7 @@ class TTS_Linux : public Object {
 	static TTS_Linux *singleton;
 
 protected:
+	void _load_voices();
 	void _speech_event(size_t p_msg_id, size_t p_client_id, int p_type);
 	void _speech_index_mark(size_t p_msg_id, size_t p_client_id, int p_type, const String &p_index_mark);