Skip to content

Commit

Permalink
small maintenance
Browse files Browse the repository at this point in the history
* Fix issue in atomics function registrations, forgot to uppercase enum usage there.

* Release ttsObj JNI local reference when tts_voice object is destroyed.

* Astyle TTS.java and tts.cpp.

* Fix speech not interrupting when menus wrap in menu.nvgt.
  • Loading branch information
samtupy committed Oct 4, 2024
1 parent cc7e779 commit 41b57a9
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 48 deletions.
24 changes: 9 additions & 15 deletions jni/src/main/java/com/samtupy/nvgt/TTS.java
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,8 @@ public void onInit(int status) {
tts.setSpeechRate(1.0f);
AudioAttributes audioAttributes = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY).setContentType(AudioAttributes.CONTENT_TYPE_SPEECH).build();
tts.setAudioAttributes(audioAttributes);
} else {
} else
isTTSInitialized = false;
}
isTTSInitializedLatch.countDown();
}
});
Expand All @@ -106,9 +105,8 @@ public boolean isActive() {
}

public boolean isSpeaking() {
if (isActive()) {
if (isActive())
return tts.isSpeaking();
}
return false;
}

Expand All @@ -117,16 +115,15 @@ public boolean speak(String text, boolean interrupt) {
Bundle params = new Bundle();
params.putFloat(TextToSpeech.Engine.KEY_PARAM_VOLUME, ttsVolume);
params.putFloat(TextToSpeech.Engine.KEY_PARAM_PAN, ttsPan);
if (text.length() > tts.getMaxSpeechInputLength()) {
if (text.length() > tts.getMaxSpeechInputLength())
return false;
}
return tts.speak(text, interrupt? TextToSpeech.QUEUE_FLUSH : TextToSpeech.QUEUE_ADD, params, null) == TextToSpeech.SUCCESS;
return tts.speak(text, interrupt ? TextToSpeech.QUEUE_FLUSH : TextToSpeech.QUEUE_ADD, params, null) == TextToSpeech.SUCCESS;
}
return false;
}

public boolean silence() {
return isActive()? tts.stop() == TextToSpeech.SUCCESS : false;
return isActive() ? tts.stop() == TextToSpeech.SUCCESS : false;
}

public String getVoice() {
Expand Down Expand Up @@ -163,9 +160,8 @@ public void setVolume(float volume) {

@Override
public void finalize() {
if (isActive()) {
if (isActive())
tts.shutdown();
}
}

public List<String> getVoices() {
Expand All @@ -176,14 +172,12 @@ public boolean setVoice(String name) {
if (isActive()) {
Set<Voice> voices = tts.getVoices();
Optional<Voice> desiredVoice = voices.stream().filter(voice -> voice.getName().equals(name)).findFirst();
if (desiredVoice.isPresent()) {
if (desiredVoice.isPresent())
return tts.setVoice(desiredVoice.get()) == TextToSpeech.SUCCESS;
} else {
else
return false;
}
} else {
} else
return false;
}
}

public int getMaxSpeechInputLength() {
Expand Down
1 change: 1 addition & 0 deletions release/include/menu.nvgt
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ class menu {
return 0;
}
play(wrap_sound);
stop_speech();
wait(wrap_delay);
f.set_list_position(0, int(args["key"]) == KEY_DOWN? 0 : f.get_list_count(0) -1, true);
return 1;
Expand Down
34 changes: 17 additions & 17 deletions src/threading.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,26 +275,26 @@ template<typename atomic_type, typename divisible_type> void register_atomic_typ
engine->RegisterObjectBehaviour(type_name.c_str(), asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(atomics_construct<atomic_type>), asCALL_CDECL_OBJFIRST);
engine->RegisterObjectBehaviour(type_name.c_str(), asBEHAVE_DESTRUCT, "void f()", asFUNCTION(atomics_destruct<atomic_type>), asCALL_CDECL_OBJFIRST);
engine->RegisterObjectMethod(type_name.c_str(), "bool is_lock_free()", asMETHODPR(atomic_type, is_lock_free, () const noexcept, bool), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("void store(%s val, memory_order order = memory_order_seq_cst)", regular_type_name).c_str(), asMETHODPR(atomic_type, store, (divisible_type, std::memory_order) noexcept, void), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("void store(%s val, memory_order order = MEMORY_ORDER_SEQ_CST)", regular_type_name).c_str(), asMETHODPR(atomic_type, store, (divisible_type, std::memory_order) noexcept, void), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("%s opAssign(%s val)", regular_type_name, regular_type_name).c_str(), asMETHODPR(atomic_type, operator=, (divisible_type) noexcept, divisible_type), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("%s load(memory_order order = memory_order_seq_cst)", regular_type_name).c_str(), asMETHODPR(atomic_type, load, (std::memory_order) const noexcept, divisible_type), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("%s load(memory_order order = MEMORY_ORDER_SEQ_CST)", regular_type_name).c_str(), asMETHODPR(atomic_type, load, (std::memory_order) const noexcept, divisible_type), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("%s opImplConv()", regular_type_name).c_str(), asMETHODPR(atomic_type, operator divisible_type, () const noexcept, divisible_type), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("%s exchange(%s desired, memory_order order = memory_order_seq_cst)", regular_type_name, regular_type_name).c_str(), asMETHODPR(atomic_type, exchange, (divisible_type, std::memory_order) noexcept, divisible_type), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("%s exchange(%s desired, memory_order order = MEMORY_ORDER_SEQ_CST)", regular_type_name, regular_type_name).c_str(), asMETHODPR(atomic_type, exchange, (divisible_type, std::memory_order) noexcept, divisible_type), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("bool compare_exchange_weak(%s& expected, %s desired, memory_order success, memory_order failure)", regular_type_name, regular_type_name).c_str(), asMETHODPR(atomic_type, compare_exchange_weak, (divisible_type&, divisible_type, std::memory_order, std::memory_order) noexcept, bool), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("bool compare_exchange_weak(%s& expected, %s desired, memory_order order = memory_order_seq_cst)", regular_type_name, regular_type_name).c_str(), asMETHODPR(atomic_type, compare_exchange_weak, (divisible_type&, divisible_type, std::memory_order) noexcept, bool), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("bool compare_exchange_weak(%s& expected, %s desired, memory_order order = MEMORY_ORDER_SEQ_CST)", regular_type_name, regular_type_name).c_str(), asMETHODPR(atomic_type, compare_exchange_weak, (divisible_type&, divisible_type, std::memory_order) noexcept, bool), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("bool compare_exchange_strong(%s& expected, %s desired, memory_order success, memory_order failure)", regular_type_name, regular_type_name).c_str(), asMETHODPR(atomic_type, compare_exchange_strong, (divisible_type&, divisible_type, std::memory_order, std::memory_order) noexcept, bool), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("bool compare_exchange_strong(%s& expected, %s desired, memory_order order = memory_order_seq_cst)", regular_type_name, regular_type_name).c_str(), asMETHODPR(atomic_type, compare_exchange_strong, (divisible_type&, divisible_type, std::memory_order) noexcept, bool), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("void wait(%s old, memory_order order = memory_order_seq_cst)", regular_type_name).c_str(), asMETHODPR(atomic_type, wait, (divisible_type, std::memory_order) const noexcept, void), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("bool compare_exchange_strong(%s& expected, %s desired, memory_order order = MEMORY_ORDER_SEQ_CST)", regular_type_name, regular_type_name).c_str(), asMETHODPR(atomic_type, compare_exchange_strong, (divisible_type&, divisible_type, std::memory_order) noexcept, bool), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("void wait(%s old, memory_order order = MEMORY_ORDER_SEQ_CST)", regular_type_name).c_str(), asMETHODPR(atomic_type, wait, (divisible_type, std::memory_order) const noexcept, void), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), "void notify_one()", asMETHODPR(atomic_type, notify_one, () noexcept, void), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), "void notify_all()", asMETHODPR(atomic_type, notify_all, () noexcept, void), asCALL_THISCALL);
// Begin type-specific atomics
if constexpr((std::is_integral_v<divisible_type> || std::is_floating_point_v<divisible_type>) && !std::is_same_v<divisible_type, bool>) {
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("%s fetch_add(%s arg, memory_order order = memory_order_seq_cst)", regular_type_name, regular_type_name).c_str(), asMETHODPR(atomic_type, fetch_add, (divisible_type, std::memory_order) noexcept, divisible_type), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("%s fetch_sub(%s arg, memory_order order = memory_order_seq_cst)", regular_type_name, regular_type_name).c_str(), asMETHODPR(atomic_type, fetch_sub, (divisible_type, std::memory_order) noexcept, divisible_type), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("%s fetch_add(%s arg, memory_order order = MEMORY_ORDER_SEQ_CST)", regular_type_name, regular_type_name).c_str(), asMETHODPR(atomic_type, fetch_add, (divisible_type, std::memory_order) noexcept, divisible_type), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("%s fetch_sub(%s arg, memory_order order = MEMORY_ORDER_SEQ_CST)", regular_type_name, regular_type_name).c_str(), asMETHODPR(atomic_type, fetch_sub, (divisible_type, std::memory_order) noexcept, divisible_type), asCALL_THISCALL);
#ifdef __cpp_lib_atomic_min_max // Only available in C++26 mode or later
if constexpr(std::is_integral_v<divisible_type>) {
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("%s fetch_max(%s arg, memory_order order = memory_order_seq_cst)", regular_type_name, regular_type_name).c_str(), asMETHODPR(atomic_type, fetch_max, (divisible_type, std::memory_order) noexcept, divisible_type), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("%s fetch_min(%s arg, memory_order order = memory_order_seq_cst)", regular_type_name, regular_type_name).c_str(), asMETHODPR(atomic_type, fetch_min, (divisible_type, std::memory_order) noexcept, divisible_type), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("%s fetch_max(%s arg, memory_order order = MEMORY_ORDER_SEQ_CST)", regular_type_name, regular_type_name).c_str(), asMETHODPR(atomic_type, fetch_max, (divisible_type, std::memory_order) noexcept, divisible_type), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("%s fetch_min(%s arg, memory_order order = MEMORY_ORDER_SEQ_CST)", regular_type_name, regular_type_name).c_str(), asMETHODPR(atomic_type, fetch_min, (divisible_type, std::memory_order) noexcept, divisible_type), asCALL_THISCALL);
}
#endif
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("%s opAddAssign(%s arg)", regular_type_name, regular_type_name).c_str(), asMETHODPR(atomic_type, operator+=, (divisible_type) noexcept, divisible_type), asCALL_THISCALL);
Expand All @@ -304,9 +304,9 @@ template<typename atomic_type, typename divisible_type> void register_atomic_typ
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("%s opPostInc(%s arg)", regular_type_name, regular_type_name).c_str(), asMETHODPR(atomic_type, operator++, (int) noexcept, divisible_type), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("%s opPreDec()", regular_type_name).c_str(), asMETHODPR(atomic_type, operator--, () noexcept, divisible_type), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("%s opPostDec(%s arg)", regular_type_name, regular_type_name).c_str(), asMETHODPR(atomic_type, operator--, (int) noexcept, divisible_type), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("%s fetch_and(%s arg, memory_order order = memory_order_seq_cst)", regular_type_name, regular_type_name).c_str(), asMETHODPR(atomic_type, fetch_and, (divisible_type, std::memory_order) noexcept, divisible_type), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("%s fetch_or(%s arg, memory_order order = memory_order_seq_cst)", regular_type_name, regular_type_name).c_str(), asMETHODPR(atomic_type, fetch_or, (divisible_type, std::memory_order) noexcept, divisible_type), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("%s fetch_xor(%s arg, memory_order order = memory_order_seq_cst)", regular_type_name, regular_type_name).c_str(), asMETHODPR(atomic_type, fetch_xor, (divisible_type, std::memory_order) noexcept, divisible_type), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("%s fetch_and(%s arg, memory_order order = MEMORY_ORDER_SEQ_CST)", regular_type_name, regular_type_name).c_str(), asMETHODPR(atomic_type, fetch_and, (divisible_type, std::memory_order) noexcept, divisible_type), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("%s fetch_or(%s arg, memory_order order = MEMORY_ORDER_SEQ_CST)", regular_type_name, regular_type_name).c_str(), asMETHODPR(atomic_type, fetch_or, (divisible_type, std::memory_order) noexcept, divisible_type), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("%s fetch_xor(%s arg, memory_order order = MEMORY_ORDER_SEQ_CST)", regular_type_name, regular_type_name).c_str(), asMETHODPR(atomic_type, fetch_xor, (divisible_type, std::memory_order) noexcept, divisible_type), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("%s opAndAssign(%s arg)", regular_type_name, regular_type_name).c_str(), asMETHODPR(atomic_type, operator&=, (divisible_type) noexcept, divisible_type), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("%s opOrAssign(%s arg)", regular_type_name, regular_type_name).c_str(), asMETHODPR(atomic_type, operator|=, (divisible_type) noexcept, divisible_type), asCALL_THISCALL);
engine->RegisterObjectMethod(type_name.c_str(), Poco::format("%s opXorAssign(%s arg)", regular_type_name, regular_type_name).c_str(), asMETHODPR(atomic_type, operator^=, (divisible_type) noexcept, divisible_type), asCALL_THISCALL);
Expand All @@ -327,10 +327,10 @@ void RegisterAtomics(asIScriptEngine* engine) {
engine->RegisterObjectType("atomic_flag", sizeof(std::atomic_flag), asOBJ_VALUE | asOBJ_POD | asGetTypeTraits<std::atomic_flag>());
engine->RegisterObjectBehaviour("atomic_flag", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(atomics_construct<std::atomic_flag>), asCALL_CDECL_OBJFIRST);
engine->RegisterObjectBehaviour("atomic_flag", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(atomics_destruct<std::atomic_flag>), asCALL_CDECL_OBJFIRST);
engine->RegisterObjectMethod("atomic_flag", "bool test(memory_order order = memory_order_seq_cst)", asMETHODPR(std::atomic_flag, test, (std::memory_order) const noexcept, bool), asCALL_THISCALL);
engine->RegisterObjectMethod("atomic_flag", "void clear(memory_order order = memory_order_seq_cst)", asMETHODPR(std::atomic_flag, clear, (std::memory_order), void), asCALL_THISCALL);
engine->RegisterObjectMethod("atomic_flag", "bool test_and_set(memory_order order = memory_order_seq_cst)", asMETHODPR(std::atomic_flag, test_and_set, (std::memory_order) noexcept, bool), asCALL_THISCALL);
engine->RegisterObjectMethod("atomic_flag", "void wait(bool old, memory_order order = memory_order_seq_cst)", asMETHODPR(std::atomic_flag, wait, (bool, std::memory_order) const noexcept, void), asCALL_THISCALL);
engine->RegisterObjectMethod("atomic_flag", "bool test(memory_order order = MEMORY_ORDER_SEQ_CST)", asMETHODPR(std::atomic_flag, test, (std::memory_order) const noexcept, bool), asCALL_THISCALL);
engine->RegisterObjectMethod("atomic_flag", "void clear(memory_order order = MEMORY_ORDER_SEQ_CST)", asMETHODPR(std::atomic_flag, clear, (std::memory_order), void), asCALL_THISCALL);
engine->RegisterObjectMethod("atomic_flag", "bool test_and_set(memory_order order = MEMORY_ORDER_SEQ_CST)", asMETHODPR(std::atomic_flag, test_and_set, (std::memory_order) noexcept, bool), asCALL_THISCALL);
engine->RegisterObjectMethod("atomic_flag", "void wait(bool old, memory_order order = MEMORY_ORDER_SEQ_CST)", asMETHODPR(std::atomic_flag, wait, (bool, std::memory_order) const noexcept, void), asCALL_THISCALL);
engine->RegisterObjectMethod("atomic_flag", "void notify_one()", asMETHOD(std::atomic_flag, notify_one), asCALL_THISCALL);
engine->RegisterObjectMethod("atomic_flag", "void notify_all()", asMETHOD(std::atomic_flag, notify_all), asCALL_THISCALL);
register_atomic_type<std::atomic_int, int>(engine, "atomic_int", "int");
Expand Down
33 changes: 17 additions & 16 deletions src/tts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@
#endif
#include <obfuscate.h>
#ifdef __APPLE__
#include "apple.h"
#include "apple.h"
#endif
#include "riffheader.h"
#include "tts.h"
#include "UI.h"
#ifdef __ANDROID__
#include <jni.h>
#include <Poco/Exception.h>
#include <Poco/Format.h>
#include <SDL3/SDL.h>
#include <jni.h>
#include <Poco/Exception.h>
#include <Poco/Format.h>
#include <SDL3/SDL.h>
#endif

char* minitrim(char* data, unsigned long* bufsize, int bitrate, int channels) {
Expand Down Expand Up @@ -127,6 +127,9 @@ void tts_voice::destroy() {
if (!inst) return;
delete inst;
inst = nullptr;
#elif defined(__ANDROID__)
env->DeleteLocalRef(TTSObj);
TTSObj = nullptr;
#endif
destroyed = true;
voice_index = -1;
Expand Down Expand Up @@ -169,9 +172,8 @@ bool tts_voice::speak(const std::string& text, bool interrupt) {
}
}
#elif defined(__APPLE__)
else {
else
return inst->speak(text, interrupt);
}
#elif defined (__ANDROID__)
else {
jstring jtext = env->NewStringUTF(text.c_str());
Expand Down Expand Up @@ -236,9 +238,8 @@ bool tts_voice::speak_to_file(const std::string& filename, const std::string& te
return false; // not implemented yet.
}
#elif defined(__ANDROID__)
else {
else
return false;
}
#endif
char* ptr = minitrim(data, &bufsize, bitrate, channels);
FILE* f = fopen(filename.c_str(), "wb");
Expand Down Expand Up @@ -298,7 +299,7 @@ bool tts_voice::speak_wait(const std::string& text, bool interrupt) {
#ifdef __APPLE__
while (voice_index == builtin_index && BASS_ChannelIsActive(audioout) == BASS_ACTIVE_PLAYING || inst->isSpeaking())
#elif defined(__ANDROID__)
while (voice_index == builtin_index && BASS_ChannelIsActive(audioout) == BASS_ACTIVE_PLAYING || get_speaking())
while (voice_index == builtin_index && BASS_ChannelIsActive(audioout) == BASS_ACTIVE_PLAYING || get_speaking())
#else
while (BASS_ChannelIsActive(audioout) == BASS_ACTIVE_PLAYING)
#endif
Expand All @@ -323,7 +324,7 @@ int tts_voice::get_rate() {
#elif defined(__APPLE__)
return inst->getRate() * 7;
#elif defined (__ANDROID__)
return static_cast<int>((env->CallFloatMethod(TTSObj, midGetRate) -1) * 10.0);
return static_cast<int>((env->CallFloatMethod(TTSObj, midGetRate) - 1) * 10.0);
#endif
return 0;
}
Expand All @@ -334,7 +335,7 @@ int tts_voice::get_pitch() {
#elif defined(__APPLE__)
return inst->getPitch();
#elif defined (__ANDROID__)
return static_cast<int>((env->CallFloatMethod(TTSObj, midGetPitch) -1) * 10.0);
return static_cast<int>((env->CallFloatMethod(TTSObj, midGetPitch) - 1) * 10.0);
#endif
return 0;
}
Expand All @@ -349,7 +350,7 @@ int tts_voice::get_volume() {
#elif defined(__APPLE__)
return inst->getRate();
#elif defined(__ANDROID__)
return static_cast<int>(env->CallFloatMethod(TTSObj, midGetVolume)-100.0);
return static_cast<int>(env->CallFloatMethod(TTSObj, midGetVolume) - 100.0);
#endif
return 0;
}
Expand All @@ -361,7 +362,7 @@ void tts_voice::set_rate(int rate) {
#elif defined(__APPLE__)
inst->setRate(rate / 7.0);
#elif defined(__ANDROID__)
env->CallBooleanMethod(TTSObj, midSetRate, (static_cast<float>(rate)/10.0) +1.0);
env->CallBooleanMethod(TTSObj, midSetRate, (static_cast<float>(rate) / 10.0) + 1.0);
#endif
}
void tts_voice::set_pitch(int pitch) {
Expand All @@ -371,7 +372,7 @@ void tts_voice::set_pitch(int pitch) {
#elif defined(__APPLE__)
inst->setPitch(pitch);
#elif defined(__ANDROID__)
env->CallBooleanMethod(TTSObj, midSetPitch, (static_cast<float>(pitch)/10.0) +1.0);
env->CallBooleanMethod(TTSObj, midSetPitch, (static_cast<float>(pitch) / 10.0) + 1.0);
#endif
return;
}
Expand All @@ -383,7 +384,7 @@ void tts_voice::set_volume(int volume) {
#elif defined(__APPLE__)
inst->setVolume(volume);
#elif defined(__ANDROID__)
env->CallBooleanMethod(TTSObj, midSetVolume, static_cast<float>(volume)+100.0);
env->CallBooleanMethod(TTSObj, midSetVolume, static_cast<float>(volume) + 100.0);
#endif
}
bool tts_voice::set_voice(int voice) {
Expand Down

0 comments on commit 41b57a9

Please sign in to comment.