mirror of
https://github.com/godotengine/godot.git
synced 2025-10-20 08:23:29 +00:00
Merge pull request #61316 from bruvzg/tts_3x
[3.x] Backport text-to-speech support.
This commit is contained in:
commit
0bed7ea63f
45 changed files with 3905 additions and 2 deletions
|
@ -64,6 +64,90 @@ void OS_JavaScript::request_quit_callback() {
|
|||
}
|
||||
}
|
||||
|
||||
bool OS_JavaScript::tts_is_speaking() const {
|
||||
return godot_js_tts_is_speaking();
|
||||
}
|
||||
|
||||
bool OS_JavaScript::tts_is_paused() const {
|
||||
return godot_js_tts_is_paused();
|
||||
}
|
||||
|
||||
void OS_JavaScript::update_voices_callback(int p_size, const char **p_voice) {
|
||||
get_singleton()->voices.clear();
|
||||
for (int i = 0; i < p_size; i++) {
|
||||
Vector<String> tokens = String::utf8(p_voice[i]).split(";", true, 2);
|
||||
if (tokens.size() == 2) {
|
||||
Dictionary voice_d;
|
||||
voice_d["name"] = tokens[1];
|
||||
voice_d["id"] = tokens[1];
|
||||
voice_d["language"] = tokens[0];
|
||||
get_singleton()->voices.push_back(voice_d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Array OS_JavaScript::tts_get_voices() const {
|
||||
godot_js_tts_get_voices(update_voices_callback);
|
||||
return voices;
|
||||
}
|
||||
|
||||
void OS_JavaScript::tts_speak(const String &p_text, const String &p_voice, int p_volume, float p_pitch, float p_rate, int p_utterance_id, bool p_interrupt) {
|
||||
if (p_interrupt) {
|
||||
tts_stop();
|
||||
}
|
||||
|
||||
if (p_text.empty()) {
|
||||
tts_post_utterance_event(OS::TTS_UTTERANCE_CANCELED, p_utterance_id);
|
||||
return;
|
||||
}
|
||||
|
||||
CharString string = p_text.utf8();
|
||||
utterance_ids[p_utterance_id] = string;
|
||||
|
||||
godot_js_tts_speak(string.get_data(), p_voice.utf8().get_data(), CLAMP(p_volume, 0, 100), CLAMP(p_pitch, 0.f, 2.f), CLAMP(p_rate, 0.1f, 10.f), p_utterance_id, OS_JavaScript::_js_utterance_callback);
|
||||
}
|
||||
|
||||
void OS_JavaScript::tts_pause() {
|
||||
godot_js_tts_pause();
|
||||
}
|
||||
|
||||
void OS_JavaScript::tts_resume() {
|
||||
godot_js_tts_resume();
|
||||
}
|
||||
|
||||
void OS_JavaScript::tts_stop() {
|
||||
for (Map<int, CharString>::Element *E = utterance_ids.front(); E; E = E->next()) {
|
||||
tts_post_utterance_event(OS::TTS_UTTERANCE_CANCELED, E->key());
|
||||
}
|
||||
utterance_ids.clear();
|
||||
godot_js_tts_stop();
|
||||
}
|
||||
|
||||
void OS_JavaScript::_js_utterance_callback(int p_event, int p_id, int p_pos) {
|
||||
OS_JavaScript *ds = (OS_JavaScript *)OS::get_singleton();
|
||||
if (ds->utterance_ids.has(p_id)) {
|
||||
int pos = 0;
|
||||
if ((TTSUtteranceEvent)p_event == OS::TTS_UTTERANCE_BOUNDARY) {
|
||||
// Convert position from UTF-8 to UTF-32.
|
||||
const CharString &string = ds->utterance_ids[p_id];
|
||||
for (int i = 0; i < MIN(p_pos, string.length()); i++) {
|
||||
uint8_t c = string[i];
|
||||
if ((c & 0xe0) == 0xc0) {
|
||||
i += 1;
|
||||
} else if ((c & 0xf0) == 0xe0) {
|
||||
i += 2;
|
||||
} else if ((c & 0xf8) == 0xf0) {
|
||||
i += 3;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
} else if ((TTSUtteranceEvent)p_event != OS::TTS_UTTERANCE_STARTED) {
|
||||
ds->utterance_ids.erase(p_id);
|
||||
}
|
||||
ds->tts_post_utterance_event((TTSUtteranceEvent)p_event, p_id, pos);
|
||||
}
|
||||
}
|
||||
|
||||
// Files drop (implemented in JS for now).
|
||||
void OS_JavaScript::drop_files_callback(char **p_filev, int p_filec) {
|
||||
OS_JavaScript *os = get_singleton();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue