Add audio/general/text_to_speech project setting to enable/disable TTS.

This commit is contained in:
bruvzg 2023-05-22 16:41:09 +03:00 committed by Relintai
parent 44d23afab4
commit 8479340f52
15 changed files with 131 additions and 30 deletions

View File

@ -1080,6 +1080,8 @@ ProjectSettings::ProjectSettings() {
ProjectSettings::get_singleton()->set_custom_property_info("audio/general/ios/session_category", PropertyInfo(Variant::INT, "audio/general/ios/session_category", PROPERTY_HINT_ENUM, "Ambient,Multi Route,Play and Record,Playback,Record,Solo Ambient"));
GLOBAL_DEF("audio/general/ios/mix_with_others", false);
GLOBAL_DEF_RST("audio/general/text_to_speech", false);
PoolStringArray extensions = PoolStringArray();
extensions.push_back("gd");
extensions.push_back("gdshader");

View File

@ -1131,6 +1131,7 @@
- [code]id[/code] is voice identifier.
- [code]language[/code] is language code in [code]lang_Variant[/code] format. [code]lang[/code] part is a 2 or 3-letter code based on the ISO-639 standard, in lowercase. And [code]Variant[/code] part is an engine dependent string describing country, region or/and dialect.
[b]Note:[/b] This method is implemented on Android, iOS, HTML5, Linux, macOS, and Windows.
[b]Note:[/b] [member ProjectSettings.audio/general/text_to_speech] should be [code]true[/code] to use text-to-speech.
</description>
</method>
<method name="tts_get_voices_for_language" qualifiers="const">
@ -1139,6 +1140,7 @@
<description>
Returns an [PoolStringArray] of voice identifiers for the [code]language[/code].
[b]Note:[/b] This method is implemented on Android, iOS, HTML5, Linux, macOS, and Windows.
[b]Note:[/b] [member ProjectSettings.audio/general/text_to_speech] should be [code]true[/code] to use text-to-speech.
</description>
</method>
<method name="tts_is_paused" qualifiers="const">
@ -1146,6 +1148,7 @@
<description>
Returns [code]true[/code] if the synthesizer is in a paused state.
[b]Note:[/b] This method is implemented on Android, iOS, HTML5, Linux, macOS, and Windows.
[b]Note:[/b] [member ProjectSettings.audio/general/text_to_speech] should be [code]true[/code] to use text-to-speech.
</description>
</method>
<method name="tts_is_speaking" qualifiers="const">
@ -1153,6 +1156,7 @@
<description>
Returns [code]true[/code] if the synthesizer is generating speech, or have utterance waiting in the queue.
[b]Note:[/b] This method is implemented on Android, iOS, HTML5, Linux, macOS, and Windows.
[b]Note:[/b] [member ProjectSettings.audio/general/text_to_speech] should be [code]true[/code] to use text-to-speech.
</description>
</method>
<method name="tts_pause">
@ -1160,6 +1164,7 @@
<description>
Puts the synthesizer into a paused state.
[b]Note:[/b] This method is implemented on Android, iOS, HTML5, Linux, macOS, and Windows.
[b]Note:[/b] [member ProjectSettings.audio/general/text_to_speech] should be [code]true[/code] to use text-to-speech.
</description>
</method>
<method name="tts_resume">
@ -1167,6 +1172,7 @@
<description>
Resumes the synthesizer if it was paused.
[b]Note:[/b] This method is implemented on Android, iOS, HTML5, Linux, macOS, and Windows.
[b]Note:[/b] [member ProjectSettings.audio/general/text_to_speech] should be [code]true[/code] to use text-to-speech.
</description>
</method>
<method name="tts_set_utterance_callback">
@ -1180,6 +1186,7 @@
- [code]TTS_UTTERANCE_BOUNDARY[/code] callable's method should take two [int] parameters, the index of the character and the utterance id.
[b]Note:[/b] The granularity of the boundary callbacks is engine dependent.
[b]Note:[/b] This method is implemented on Android, iOS, HTML5, Linux, macOS, and Windows.
[b]Note:[/b] [member ProjectSettings.audio/general/text_to_speech] should be [code]true[/code] to use text-to-speech.
</description>
</method>
<method name="tts_speak">
@ -1201,6 +1208,7 @@
[b]Note:[/b] On Windows and Linux, utterance [code]text[/code] can use SSML markup. SSML support is engine and voice dependent. If the engine does not support SSML, you should strip out all XML markup before calling [method tts_speak].
[b]Note:[/b] The granularity of pitch, rate, and volume is engine and voice dependent. Values may be truncated.
[b]Note:[/b] This method is implemented on Android, iOS, HTML5, Linux, macOS, and Windows.
[b]Note:[/b] [member ProjectSettings.audio/general/text_to_speech] should be [code]true[/code] to use text-to-speech.
</description>
</method>
<method name="tts_stop">
@ -1208,6 +1216,7 @@
<description>
Stops synthesis in progress and removes all utterances from the queue.
[b]Note:[/b] This method is implemented on Android, iOS, HTML5, Linux, macOS, and Windows.
[b]Note:[/b] [member ProjectSettings.audio/general/text_to_speech] should be [code]true[/code] to use text-to-speech.
</description>
</method>
</methods>

View File

@ -303,6 +303,10 @@
<member name="audio/general/ios/session_category" type="int" setter="" getter="" default="0">
Sets the [url=https://developer.apple.com/documentation/avfaudio/avaudiosessioncategory]AVAudioSessionCategory[/url] on iOS. Use the [code]Playback[/code] category to get sound output, even if the phone is in silent mode.
</member>
<member name="audio/general/text_to_speech" type="bool" setter="" getter="" default="false">
If [code]true[/code], text-to-speech support is enabled, see [method OS.tts_get_voices] and [method OS.tts_speak].
[b]Note:[/b] Enabling TTS can cause addition idle CPU usage and interfere with the sleep mode, so consider disabling it if TTS is not used.
</member>
<member name="audio/mix_rate" type="int" setter="" getter="" default="44100">
The mixing rate used for audio (in Hz). In general, it's better to not touch this and leave it to the host operating system.
</member>

View File

@ -457,7 +457,9 @@ public class Pandemonium extends Fragment implements SensorEventListener, IDownl
final String[] current_command_line = command_line;
mView.queueEvent(() -> {
if (!PandemoniumLib.setup(current_command_line)) {
tts = new PandemoniumTTS(activity);
if (!PandemoniumLib.setup(current_command_line, tts)) {
pandemonium_initialized = false;
Log.e(TAG, "Unable to setup the Pandemonium engine! Aborting...");
alert(R.string.error_engine_setup_message, R.string.text_error_title, this::forceQuit);
@ -711,7 +713,6 @@ public class Pandemonium extends Fragment implements SensorEventListener, IDownl
final Activity activity = getActivity();
io = new PandemoniumIO(activity);
netUtils = new PandemoniumNetUtils(activity);
tts = new PandemoniumTTS(activity);
Context context = getContext();
directoryAccessHandler = new DirectoryAccessHandler(context);
@ -723,7 +724,7 @@ public class Pandemonium extends Fragment implements SensorEventListener, IDownl
mMagnetometer = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
mGyroscope = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
PandemoniumLib.initialize(activity, this, activity.getAssets(), io, netUtils, directoryAccessHandler, fileAccessHandler, use_apk_expansion, tts);
PandemoniumLib.initialize(activity, this, activity.getAssets(), io, netUtils, directoryAccessHandler, fileAccessHandler, use_apk_expansion);
result_callback = null;

View File

@ -53,7 +53,7 @@ public class PandemoniumLib {
/**
* Invoked on the main thread to initialize Pandemonium native layer.
*/
public static native void initialize(Activity activity, Pandemonium p_instance, AssetManager p_asset_manager, PandemoniumIO pandemoniumIO, PandemoniumNetUtils netUtils, DirectoryAccessHandler directoryAccessHandler, FileAccessHandler fileAccessHandler, boolean use_apk_expansion, GodotTTS tts);
public static native void initialize(Activity activity, Pandemonium p_instance, AssetManager p_asset_manager, PandemoniumIO pandemoniumIO, PandemoniumNetUtils netUtils, DirectoryAccessHandler directoryAccessHandler, FileAccessHandler fileAccessHandler, boolean use_apk_expansion);
/**
* Invoked on the main thread to clean up Pandemonium native layer.
@ -65,7 +65,7 @@ public class PandemoniumLib {
* Invoked on the GL thread to complete setup for the Pandemonium native layer logic.
* @param p_cmdline Command line arguments used to configure Pandemonium native layer components.
*/
public static native boolean setup(String[] p_cmdline);
public static native boolean setup(String[] p_cmdline, PandemoniumTTS tts);
/**
* Invoked on the GL thread when the underlying Android surface has changed size.

View File

@ -62,8 +62,9 @@ public class PandemoniumTTS extends UtteranceProgressListener {
final private static int EVENT_CANCEL = 2;
final private static int EVENT_BOUNDARY = 3;
final private TextToSpeech synth;
final private LinkedList<PandemoniumUtterance> queue;
final private Activity activity;
private TextToSpeech synth;
private LinkedList<PandemoniumUtterance> queue;
final private Object lock = new Object();
private PandemoniumUtterance lastUtterance;
@ -71,10 +72,7 @@ public class PandemoniumTTS extends UtteranceProgressListener {
private boolean paused;
public PandemoniumTTS(Activity p_activity) {
synth = new TextToSpeech(p_activity, null);
queue = new LinkedList<PandemoniumUtterance>();
synth.setOnUtteranceProgressListener(this);
activity = p_activity;
}
private void updateTTS() {
@ -186,6 +184,16 @@ public class PandemoniumTTS extends UtteranceProgressListener {
}
}
/**
* Initialize synth and query.
*/
public void init() {
synth = new TextToSpeech(p_activity, null);
queue = new LinkedList<PandemoniumUtterance>();
synth.setOnUtteranceProgressListener(this);
}
/**
* Adds an utterance to the queue.
*/

View File

@ -160,7 +160,7 @@ JNIEXPORT void JNICALL Java_org_pandemoniumengine_pandemonium_PandemoniumLib_set
}
}
JNIEXPORT void JNICALL Java_org_pandemoniumengine_pandemonium_PandemoniumLib_initialize(JNIEnv *env, jclass clazz, jobject p_activity, jobject p_pandemonium_instance, jobject p_asset_manager, jobject p_pandemonium_io, jobject p_net_utils, jobject p_directory_access_handler, jobject p_file_access_handler, jboolean p_use_apk_expansion, jobject p_godot_tts) {
JNIEXPORT void JNICALL Java_org_pandemoniumengine_pandemonium_PandemoniumLib_initialize(JNIEnv *env, jclass clazz, jobject p_activity, jobject p_pandemonium_instance, jobject p_asset_manager, jobject p_pandemonium_io, jobject p_net_utils, jobject p_directory_access_handler, jobject p_file_access_handler, jboolean p_use_apk_expansion) {
initialized = true;
JavaVM *jvm;
@ -179,7 +179,6 @@ JNIEXPORT void JNICALL Java_org_pandemoniumengine_pandemonium_PandemoniumLib_ini
DirAccessJAndroid::setup(p_directory_access_handler);
FileAccessFilesystemJAndroid::setup(p_file_access_handler);
NetSocketAndroid::setup(p_net_utils);
TTS_Android::setup(p_godot_tts);
os_android = new OS_Android(pandemonium_java, pandemonium_io_java, p_use_apk_expansion);
@ -193,7 +192,7 @@ JNIEXPORT void JNICALL Java_org_pandemoniumengine_pandemonium_PandemoniumLib_ond
_terminate(env, false);
}
JNIEXPORT jboolean JNICALL Java_org_pandemoniumengine_pandemonium_PandemoniumLib_setup(JNIEnv *env, jclass clazz, jobjectArray p_cmdline) {
JNIEXPORT jboolean JNICALL Java_org_pandemoniumengine_pandemonium_PandemoniumLib_setup(JNIEnv *env, jclass clazz, jobjectArray p_cmdline, jobject p_godot_tts) {
setup_android_thread();
const char **cmdline = NULL;
@ -234,7 +233,10 @@ JNIEXPORT jboolean JNICALL Java_org_pandemoniumengine_pandemonium_PandemoniumLib
return false;
}
TTS_Android::setup(p_godot_tts);
java_class_wrapper = memnew(JavaClassWrapper(pandemonium_java->get_activity()));
ClassDB::register_class<JNISingleton>();
_initialize_java_modules();
return true;

View File

@ -35,9 +35,11 @@
#include "string_android.h"
#include "thread_jandroid.h"
bool TTS_Android::initialized = false;
jobject TTS_Android::tts = 0;
jclass TTS_Android::cls = 0;
jmethodID TTS_Android::_init = 0;
jmethodID TTS_Android::_is_speaking = 0;
jmethodID TTS_Android::_is_paused = 0;
jmethodID TTS_Android::_get_voices = 0;
@ -99,23 +101,33 @@ Vector<char16_t> TTS_Android::str_to_utf16(const String &p_string) {
}
void TTS_Android::setup(jobject p_tts) {
JNIEnv *env = get_jni_env();
bool tts_enabled = GLOBAL_GET("audio/general/text_to_speech");
if (tts_enabled) {
JNIEnv *env = get_jni_env();
tts = env->NewGlobalRef(p_tts);
tts = env->NewGlobalRef(p_tts);
jclass c = env->GetObjectClass(tts);
cls = (jclass)env->NewGlobalRef(c);
jclass c = env->GetObjectClass(tts);
cls = (jclass)env->NewGlobalRef(c);
_is_speaking = env->GetMethodID(cls, "isSpeaking", "()Z");
_is_paused = env->GetMethodID(cls, "isPaused", "()Z");
_get_voices = env->GetMethodID(cls, "getVoices", "()[Ljava/lang/String;");
_speak = env->GetMethodID(cls, "speak", "(Ljava/lang/String;Ljava/lang/String;IFFIZ)V");
_pause_speaking = env->GetMethodID(cls, "pauseSpeaking", "()V");
_resume_speaking = env->GetMethodID(cls, "resumeSpeaking", "()V");
_stop_speaking = env->GetMethodID(cls, "stopSpeaking", "()V");
_init = env->GetMethodID(cls, "init", "()V");
_is_speaking = env->GetMethodID(cls, "isSpeaking", "()Z");
_is_paused = env->GetMethodID(cls, "isPaused", "()Z");
_get_voices = env->GetMethodID(cls, "getVoices", "()[Ljava/lang/String;");
_speak = env->GetMethodID(cls, "speak", "(Ljava/lang/String;Ljava/lang/String;IFFIZ)V");
_pause_speaking = env->GetMethodID(cls, "pauseSpeaking", "()V");
_resume_speaking = env->GetMethodID(cls, "resumeSpeaking", "()V");
_stop_speaking = env->GetMethodID(cls, "stopSpeaking", "()V");
if (_init) {
env->CallVoidMethod(tts, _init);
initialized = true;
}
}
}
void TTS_Android::_java_utterance_callback(int p_event, int p_id, int p_pos) {
ERR_FAIL_COND_MSG(!initialized, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
if (ids.has(p_id)) {
int pos = 0;
if ((OS::TTSUtteranceEvent)p_event == OS::TTS_UTTERANCE_BOUNDARY) {
@ -136,6 +148,7 @@ void TTS_Android::_java_utterance_callback(int p_event, int p_id, int p_pos) {
}
bool TTS_Android::is_speaking() {
ERR_FAIL_COND_V_MSG(!initialized, false, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
if (_is_speaking) {
JNIEnv *env = get_jni_env();
@ -147,6 +160,7 @@ bool TTS_Android::is_speaking() {
}
bool TTS_Android::is_paused() {
ERR_FAIL_COND_V_MSG(!initialized, false, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
if (_is_paused) {
JNIEnv *env = get_jni_env();
@ -158,6 +172,7 @@ bool TTS_Android::is_paused() {
}
Array TTS_Android::get_voices() {
ERR_FAIL_COND_V_MSG(!initialized, Array(), "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
Array list;
if (_get_voices) {
JNIEnv *env = get_jni_env();
@ -185,6 +200,7 @@ Array TTS_Android::get_voices() {
}
void TTS_Android::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) {
ERR_FAIL_COND_MSG(!initialized, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
if (p_interrupt) {
stop();
}
@ -207,6 +223,7 @@ void TTS_Android::speak(const String &p_text, const String &p_voice, int p_volum
}
void TTS_Android::pause() {
ERR_FAIL_COND_MSG(!initialized, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
if (_pause_speaking) {
JNIEnv *env = get_jni_env();
@ -216,6 +233,7 @@ void TTS_Android::pause() {
}
void TTS_Android::resume() {
ERR_FAIL_COND_MSG(!initialized, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
if (_resume_speaking) {
JNIEnv *env = get_jni_env();
@ -225,6 +243,7 @@ void TTS_Android::resume() {
}
void TTS_Android::stop() {
ERR_FAIL_COND_MSG(!initialized, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
const int *k = NULL;
while ((k = ids.next(k))) {
OS::get_singleton()->tts_post_utterance_event(OS::TTS_UTTERANCE_CANCELED, *k);

View File

@ -33,14 +33,17 @@
#include "core/variant/array.h"
#include "core/os/os.h"
#include "core/config/project_settings.h"
#include "core/string/ustring.h"
#include <jni.h>
class TTS_Android {
static bool initialized;
static jobject tts;
static jclass cls;
static jmethodID _init;
static jmethodID _is_speaking;
static jmethodID _is_paused;
static jmethodID _get_voices;

View File

@ -95,36 +95,43 @@ OSIPhone *OSIPhone::get_singleton() {
};
bool OSIPhone::tts_is_speaking() const {
ERR_FAIL_COND_V_MSG(!tts, false, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
ERR_FAIL_COND_V(!tts, false);
return [tts isSpeaking];
}
bool OSIPhone::tts_is_paused() const {
ERR_FAIL_COND_V_MSG(!tts, false, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
ERR_FAIL_COND_V(!tts, false);
return [tts isPaused];
}
Array OSIPhone::tts_get_voices() const {
ERR_FAIL_COND_V_MSG(!tts, Array(), "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
ERR_FAIL_COND_V(!tts, Array());
return [tts getVoices];
}
void OSIPhone::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) {
ERR_FAIL_COND_MSG(!tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
ERR_FAIL_COND(!tts);
[tts speak:p_text voice:p_voice volume:p_volume pitch:p_pitch rate:p_rate utterance_id:p_utterance_id interrupt:p_interrupt];
}
void OSIPhone::tts_pause() {
ERR_FAIL_COND_MSG(!tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
ERR_FAIL_COND(!tts);
[tts pauseSpeaking];
}
void OSIPhone::tts_resume() {
ERR_FAIL_COND_MSG(!tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
ERR_FAIL_COND(!tts);
[tts resumeSpeaking];
}
void OSIPhone::tts_stop() {
ERR_FAIL_COND_MSG(!tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
ERR_FAIL_COND(!tts);
[tts stopSpeaking];
}
@ -225,7 +232,10 @@ Error OSIPhone::initialize(const VideoMode &p_desired, int p_video_driver, int p
}
// Init TTS
tts = [[TTS_IOS alloc] init];
bool tts_enabled = GLOBAL_GET("audio/general/text_to_speech");
if (tts_enabled) {
tts = [[TTS_IOS alloc] init];
}
rendering_server->init();
//rendering_server->cursor_set_visible(false, 0);

View File

@ -32,6 +32,7 @@
#include "os_javascript.h"
#include "core/io/json.h"
#include "core/project_settings.h"
#include "drivers/gles2/rasterizer_gles2.h"
#ifndef GLES3_DISABLED
#include "drivers/gles3/rasterizer_gles3.h"
@ -69,10 +70,12 @@ void OS_JavaScript::request_quit_callback() {
}
bool OS_JavaScript::tts_is_speaking() const {
ERR_FAIL_COND_V_MSG(!tts, false, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
return godot_js_tts_is_speaking();
}
bool OS_JavaScript::tts_is_paused() const {
ERR_FAIL_COND_V_MSG(!tts, false, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
return godot_js_tts_is_paused();
}
@ -91,11 +94,13 @@ void OS_JavaScript::update_voices_callback(int p_size, const char **p_voice) {
}
Array OS_JavaScript::tts_get_voices() const {
ERR_FAIL_COND_V_MSG(!tts, Array(), "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
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) {
ERR_FAIL_COND_MSG(!tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
if (p_interrupt) {
tts_stop();
}
@ -112,14 +117,17 @@ void OS_JavaScript::tts_speak(const String &p_text, const String &p_voice, int p
}
void OS_JavaScript::tts_pause() {
ERR_FAIL_COND_MSG(!tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
godot_js_tts_pause();
}
void OS_JavaScript::tts_resume() {
ERR_FAIL_COND_MSG(!tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
godot_js_tts_resume();
}
void OS_JavaScript::tts_stop() {
ERR_FAIL_COND_MSG(!tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
for (Map<int, CharString>::Element *E = utterance_ids.front(); E; E = E->next()) {
tts_post_utterance_event(OS::TTS_UTTERANCE_CANCELED, E->key());
}
@ -1322,6 +1330,8 @@ OS_JavaScript *OS_JavaScript::get_singleton() {
}
OS_JavaScript::OS_JavaScript() {
tts = GLOBAL_GET("audio/general/text_to_speech");
// Expose method for requesting quit.
pandemonium_js_os_request_quit_cb(&request_quit_callback);
// Set canvas ID

View File

@ -93,6 +93,7 @@ private:
List<AudioDriverJavaScript *> audio_drivers;
RenderingServer *rendering_server;
bool tts;
bool swap_ok_cancel;
bool idb_available;
bool idb_needs_sync;

View File

@ -1593,36 +1593,43 @@ int OS_OSX::get_current_video_driver() const {
}
bool OS_OSX::tts_is_speaking() const {
ERR_FAIL_COND_V_MSG(!tts, false, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
ERR_FAIL_COND_V(!tts, false);
return [tts isSpeaking];
}
bool OS_OSX::tts_is_paused() const {
ERR_FAIL_COND_V_MSG(!tts, false, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
ERR_FAIL_COND_V(!tts, false);
return [tts isPaused];
}
Array OS_OSX::tts_get_voices() const {
ERR_FAIL_COND_V_MSG(!tts, Array(), "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
ERR_FAIL_COND_V(!tts, Array());
return [tts getVoices];
}
void OS_OSX::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) {
ERR_FAIL_COND_MSG(!tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
ERR_FAIL_COND(!tts);
[tts speak:p_text voice:p_voice volume:p_volume pitch:p_pitch rate:p_rate utterance_id:p_utterance_id interrupt:p_interrupt];
}
void OS_OSX::tts_pause() {
ERR_FAIL_COND_MSG(!tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
ERR_FAIL_COND(!tts);
[tts pauseSpeaking];
}
void OS_OSX::tts_resume() {
ERR_FAIL_COND_MSG(!tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
ERR_FAIL_COND(!tts);
[tts resumeSpeaking];
}
void OS_OSX::tts_stop() {
ERR_FAIL_COND_MSG(!tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
ERR_FAIL_COND(!tts);
[tts stopSpeaking];
}
@ -1646,7 +1653,10 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a
CGDisplayRegisterReconfigurationCallback(displays_arrangement_changed, NULL);
// Init TTS
tts = [[TTS_OSX alloc] init];
bool tts_enabled = GLOBAL_GET("audio/general/text_to_speech");
if (tts_enabled) {
tts = [[TTS_OSX alloc] init];
}
window_delegate = [[PandemoniumWindowDelegate alloc] init];

View File

@ -263,36 +263,43 @@ void OS_Windows::_touch_event(bool p_pressed, float p_x, float p_y, int idx) {
};
bool OS_Windows::tts_is_speaking() const {
ERR_FAIL_COND_V_MSG(!tts, false, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
ERR_FAIL_COND_V(!tts, false);
return tts->is_speaking();
}
bool OS_Windows::tts_is_paused() const {
ERR_FAIL_COND_V_MSG(!tts, false, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
ERR_FAIL_COND_V(!tts, false);
return tts->is_paused();
}
Array OS_Windows::tts_get_voices() const {
ERR_FAIL_COND_V_MSG(!tts, Array(), "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
ERR_FAIL_COND_V(!tts, Array());
return tts->get_voices();
}
void OS_Windows::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) {
ERR_FAIL_COND_MSG(!tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
ERR_FAIL_COND(!tts);
tts->speak(p_text, p_voice, p_volume, p_pitch, p_rate, p_utterance_id, p_interrupt);
}
void OS_Windows::tts_pause() {
ERR_FAIL_COND_MSG(!tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
ERR_FAIL_COND(!tts);
tts->pause();
}
void OS_Windows::tts_resume() {
ERR_FAIL_COND_MSG(!tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
ERR_FAIL_COND(!tts);
tts->resume();
}
void OS_Windows::tts_stop() {
ERR_FAIL_COND_MSG(!tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
ERR_FAIL_COND(!tts);
tts->stop();
}
@ -1396,7 +1403,10 @@ Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int
}
// Init TTS
tts = memnew(TTS_Windows);
bool tts_enabled = GLOBAL_GET("audio/general/text_to_speech");
if (tts_enabled) {
tts = memnew(TTS_Windows);
}
use_raw_input = true;

View File

@ -115,36 +115,43 @@ static String get_atom_name(Display *p_disp, Atom p_atom) {
#ifdef SPEECHD_ENABLED
bool OS_X11::tts_is_speaking() const {
ERR_FAIL_COND_V_MSG(!tts, false, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
ERR_FAIL_COND_V(!tts, false);
return tts->is_speaking();
}
bool OS_X11::tts_is_paused() const {
ERR_FAIL_COND_V_MSG(!tts, false, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
ERR_FAIL_COND_V(!tts, false);
return tts->is_paused();
}
Array OS_X11::tts_get_voices() const {
ERR_FAIL_COND_V_MSG(!tts, Array(), "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
ERR_FAIL_COND_V(!tts, Array());
return tts->get_voices();
}
void OS_X11::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) {
ERR_FAIL_COND_MSG(!tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
ERR_FAIL_COND(!tts);
tts->speak(p_text, p_voice, p_volume, p_pitch, p_rate, p_utterance_id, p_interrupt);
}
void OS_X11::tts_pause() {
ERR_FAIL_COND_MSG(!tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
ERR_FAIL_COND(!tts);
tts->pause();
}
void OS_X11::tts_resume() {
ERR_FAIL_COND_MSG(!tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
ERR_FAIL_COND(!tts);
tts->resume();
}
void OS_X11::tts_stop() {
ERR_FAIL_COND_MSG(!tts, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
ERR_FAIL_COND(!tts);
tts->stop();
}
@ -422,7 +429,10 @@ Error OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_a
#ifdef SPEECHD_ENABLED
// Init TTS
tts = memnew(TTS_Linux);
bool tts_enabled = GLOBAL_GET("audio/general/text_to_speech");
if (tts_enabled) {
tts = memnew(TTS_Linux);
}
#endif
rendering_server = memnew(RenderingServerRaster);
@ -897,7 +907,9 @@ void OS_X11::finalize() {
#endif
#ifdef SPEECHD_ENABLED
memdelete(tts);
if (tts) {
memdelete(tts);
}
#endif
#ifdef JOYDEV_ENABLED