summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid 'Digit' Turner <digit@google.com>2010-05-20 16:57:34 -0700
committerDavid 'Digit' Turner <digit@google.com>2010-06-11 18:02:51 -0700
commit01f2f960e73701633a169fbb2b777a4915a5b12c (patch)
tree6dac2d44f0b9df824a9fe3912e6b89d5066f7c42
parent28d01123754b10dc467a344650238ba583159ec9 (diff)
downloadframeworks_base-01f2f960e73701633a169fbb2b777a4915a5b12c.zip
frameworks_base-01f2f960e73701633a169fbb2b777a4915a5b12c.tar.gz
frameworks_base-01f2f960e73701633a169fbb2b777a4915a5b12c.tar.bz2
Improved native TTS interface header.
The purpose of this patch is to add a C-based ABI that can be exposed by the NDK for developers wanting to write a TTS Engine. This replaces the C++ ABI that is currently under frameworks/base/include/tts/TtsEngine.h but is *binary* compatible with it. As a consequence, the svox pico plugin under external/svox/pico/tts/, which links against tts/TtsEngine.h can be loaded by the TTS service properly. Another patch would modify the pico tts to use <android/tts.h>, then we will be able to get rid of <tts/TtsEngine.h> in the source tree. Change-Id: I16844cef9b5b006cc32655a29e4f9f193c8c1a91
-rw-r--r--native/include/android/tts.h308
-rwxr-xr-xpackages/TtsService/jni/Android.mk1
-rw-r--r--packages/TtsService/jni/android_tts_SynthProxy.cpp202
3 files changed, 437 insertions, 74 deletions
diff --git a/native/include/android/tts.h b/native/include/android/tts.h
new file mode 100644
index 0000000..e5c99f7
--- /dev/null
+++ b/native/include/android/tts.h
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef ANDROID_TTS_H
+#define ANDROID_TTS_H
+
+// This header defines the interface used by the Android platform
+// to access Text-To-Speech functionality in shared libraries that implement
+// speech synthesis and the management of resources associated with the
+// synthesis.
+
+// The shared library must contain a function named "android_getTtsEngine"
+// that returns an 'android_tts_engine_t' instance.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ANDROID_TTS_ENGINE_PROPERTY_CONFIG "engineConfig"
+#define ANDROID_TTS_ENGINE_PROPERTY_PITCH "pitch"
+#define ANDROID_TTS_ENGINE_PROPERTY_RATE "rate"
+#define ANDROID_TTS_ENGINE_PROPERTY_VOLUME "volume"
+
+typedef enum {
+ ANDROID_TTS_SUCCESS = 0,
+ ANDROID_TTS_FAILURE = -1,
+ ANDROID_TTS_FEATURE_UNSUPPORTED = -2,
+ ANDROID_TTS_VALUE_INVALID = -3,
+ ANDROID_TTS_PROPERTY_UNSUPPORTED = -4,
+ ANDROID_TTS_PROPERTY_SIZE_TOO_SMALL = -5,
+ ANDROID_TTS_MISSING_RESOURCES = -6
+} android_tts_result_t;
+
+typedef enum {
+ ANDROID_TTS_LANG_COUNTRY_VAR_AVAILABLE = 2,
+ ANDROID_TTS_LANG_COUNTRY_AVAILABLE = 1,
+ ANDROID_TTS_LANG_AVAILABLE = 0,
+ ANDROID_TTS_LANG_MISSING_DATA = -1,
+ ANDROID_TTS_LANG_NOT_SUPPORTED = -2
+} android_tts_support_result_t;
+
+typedef enum {
+ ANDROID_TTS_SYNTH_DONE = 0,
+ ANDROID_TTS_SYNTH_PENDING = 1
+} android_tts_synth_status_t;
+
+typedef enum {
+ ANDROID_TTS_CALLBACK_HALT = 0,
+ ANDROID_TTS_CALLBACK_CONTINUE = 1
+} android_tts_callback_status_t;
+
+// Supported audio formats
+typedef enum {
+ ANDROID_TTS_AUDIO_FORMAT_INVALID = -1,
+ ANDROID_TTS_AUDIO_FORMAT_DEFAULT = 0,
+ ANDROID_TTS_AUDIO_FORMAT_PCM_16_BIT = 1,
+ ANDROID_TTS_AUDIO_FORMAT_PCM_8_BIT = 2,
+} android_tts_audio_format_t;
+
+
+/* An android_tts_engine_t object can be anything, but must have,
+ * as its first field, a pointer to a table of functions.
+ *
+ * See the full definition of struct android_tts_engine_t_funcs_t
+ * below for details.
+ */
+typedef struct android_tts_engine_funcs_t android_tts_engine_funcs_t;
+
+typedef struct {
+ android_tts_engine_funcs_t *funcs;
+} android_tts_engine_t;
+
+/* This function must be located in the TTS Engine shared library
+ * and must return the address of an android_tts_engine_t library.
+ */
+extern android_tts_engine_t *android_getTtsEngine();
+
+// A callback type used to notify the framework of new synthetized
+// audio samples, status will be SYNTH_DONE for the last sample of
+// the last request, of SYNTH_PENDING otherwise.
+//
+// This is passed by the framework to the engine through the
+// 'engine_init' function (see below).
+//
+// The callback for synthesis completed takes:
+// @param [inout] void *& - The userdata pointer set in the original
+// synth call
+// @param [in] uint32_t - Track sampling rate in Hz
+// @param [in] uint32_t - The audio format
+// @param [in] int - The number of channels
+// @param [inout] int8_t *& - A buffer of audio data only valid during the
+// execution of the callback
+// @param [inout] size_t & - The size of the buffer
+// @param [in] tts_synth_status - indicate whether the synthesis is done, or
+// if more data is to be synthesized.
+// @return TTS_CALLBACK_HALT to indicate the synthesis must stop,
+// TTS_CALLBACK_CONTINUE to indicate the synthesis must continue if
+// there is more data to produce.
+typedef android_tts_callback_status_t (*android_tts_synth_cb_t)
+ (void **pUserData,
+ uint32_t trackSamplingHz,
+ android_tts_audio_format_t audioFormat,
+ int channelCount,
+ int8_t **pAudioBuffer,
+ size_t *pBufferSize,
+ android_tts_synth_status_t status);
+
+
+// The table of function pointers that the android_tts_engine_t must point to.
+// Note that each of these functions will take a handle to the engine itself
+// as their first parameter.
+//
+
+struct android_tts_engine_funcs_t {
+ // reserved fields, ignored by the framework
+ // they must be placed here to ensure binary compatibility
+ // of legacy binary plugins.
+ void *reserved[2];
+
+ // Initialize the TTS engine and returns whether initialization succeeded.
+ // @param synthDoneCBPtr synthesis callback function pointer
+ // @return TTS_SUCCESS, or TTS_FAILURE
+ android_tts_result_t (*init)
+ (void *engine,
+ android_tts_synth_cb_t synthDonePtr,
+ const char *engineConfig);
+
+ // Shut down the TTS engine and releases all associated resources.
+ // @return TTS_SUCCESS, or TTS_FAILURE
+ android_tts_result_t (*shutdown)
+ (void *engine);
+
+ // Interrupt synthesis and flushes any synthesized data that hasn't been
+ // output yet. This will block until callbacks underway are completed.
+ // @return TTS_SUCCESS, or TTS_FAILURE
+ android_tts_result_t (*stop)
+ (void *engine);
+
+ // Returns the level of support for the language, country and variant.
+ // @return TTS_LANG_COUNTRY_VAR_AVAILABLE if the language, country and variant are supported,
+ // and the corresponding resources are correctly installed
+ // TTS_LANG_COUNTRY_AVAILABLE if the language and country are supported and the
+ // corresponding resources are correctly installed, but there is no match for
+ // the specified variant
+ // TTS_LANG_AVAILABLE if the language is supported and the
+ // corresponding resources are correctly installed, but there is no match for
+ // the specified country and variant
+ // TTS_LANG_MISSING_DATA if the required resources to provide any level of support
+ // for the language are not correctly installed
+ // TTS_LANG_NOT_SUPPORTED if the language is not supported by the TTS engine.
+ android_tts_support_result_t (*isLanguageAvailable)
+ (void *engine,
+ const char *lang,
+ const char *country,
+ const char *variant);
+
+ // Load the resources associated with the specified language. The loaded
+ // language will only be used once a call to setLanguage() with the same
+ // language value is issued. Language and country values are coded according to the ISO three
+ // letter codes for languages and countries, as can be retrieved from a java.util.Locale
+ // instance. The variant value is encoded as the variant string retrieved from a
+ // java.util.Locale instance built with that variant data.
+ // @param lang pointer to the ISO three letter code for the language
+ // @param country pointer to the ISO three letter code for the country
+ // @param variant pointer to the variant code
+ // @return TTS_SUCCESS, or TTS_FAILURE
+ android_tts_result_t (*loadLanguage)
+ (void *engine,
+ const char *lang,
+ const char *country,
+ const char *variant);
+
+ // Load the resources associated with the specified language, country and Locale variant.
+ // The loaded language will only be used once a call to setLanguageFromLocale() with the same
+ // language value is issued. Language and country values are coded according to the ISO three
+ // letter codes for languages and countries, as can be retrieved from a java.util.Locale
+ // instance. The variant value is encoded as the variant string retrieved from a
+ // java.util.Locale instance built with that variant data.
+ // @param lang pointer to the ISO three letter code for the language
+ // @param country pointer to the ISO three letter code for the country
+ // @param variant pointer to the variant code
+ // @return TTS_SUCCESS, or TTS_FAILURE
+ android_tts_result_t (*setLanguage)
+ (void *engine,
+ const char *lang,
+ const char *country,
+ const char *variant);
+
+ // Retrieve the currently set language, country and variant, or empty strings if none of
+ // parameters have been set. Language and country are represented by their 3-letter ISO code
+ // @param[out] pointer to the retrieved 3-letter code language value
+ // @param[out] pointer to the retrieved 3-letter code country value
+ // @param[out] pointer to the retrieved variant value
+ // @return TTS_SUCCESS, or TTS_FAILURE
+ android_tts_result_t (*getLanguage)
+ (void *engine,
+ char *language,
+ char *country,
+ char *variant);
+
+ // Notifies the engine what audio parameters should be used for the synthesis.
+ // This is meant to be used as a hint, the engine implementation will set the output values
+ // to those of the synthesis format, based on a given hint.
+ // @param[inout] encoding in: the desired audio sample format
+ // out: the format used by the TTS engine
+ // @param[inout] rate in: the desired audio sample rate
+ // out: the sample rate used by the TTS engine
+ // @param[inout] channels in: the desired number of audio channels
+ // out: the number of channels used by the TTS engine
+ // @return TTS_SUCCESS, or TTS_FAILURE
+ android_tts_result_t (*setAudioFormat)
+ (void *engine,
+ android_tts_audio_format_t* pEncoding,
+ uint32_t* pRate,
+ int* pChannels);
+
+ // Set a property for the the TTS engine
+ // "size" is the maximum size of "value" for properties "property"
+ // @param property pointer to the property name
+ // @param value pointer to the property value
+ // @param size maximum size required to store this type of property
+ // @return TTS_PROPERTY_UNSUPPORTED, or TTS_SUCCESS, or TTS_FAILURE,
+ // or TTS_VALUE_INVALID
+ android_tts_result_t (*setProperty)
+ (void *engine,
+ const char *property,
+ const char *value,
+ const size_t size);
+
+ // Retrieve a property from the TTS engine
+ // @param property pointer to the property name
+ // @param[out] value pointer to the retrieved language value
+ // @param[inout] iosize in: stores the size available to store the
+ // property value.
+ // out: stores the size required to hold the language
+ // value if getLanguage() returned
+ // TTS_PROPERTY_SIZE_TOO_SMALL, unchanged otherwise
+ // @return TTS_PROPERTY_UNSUPPORTED, or TTS_SUCCESS,
+ // or TTS_PROPERTY_SIZE_TOO_SMALL
+ android_tts_result_t (*getProperty)
+ (void *engine,
+ const char *property,
+ char *value,
+ size_t *iosize);
+
+ // Synthesize the text.
+ // As the synthesis is performed, the engine invokes the callback to notify
+ // the TTS framework that it has filled the given buffer, and indicates how
+ // many bytes it wrote. The callback is called repeatedly until the engine
+ // has generated all the audio data corresponding to the text.
+ // Note about the format of the input: the text parameter may use the
+ // following elements
+ // and their respective attributes as defined in the SSML 1.0 specification:
+ // * lang
+ // * say-as:
+ // o interpret-as
+ // * phoneme
+ // * voice:
+ // o gender,
+ // o age,
+ // o variant,
+ // o name
+ // * emphasis
+ // * break:
+ // o strength,
+ // o time
+ // * prosody:
+ // o pitch,
+ // o contour,
+ // o range,
+ // o rate,
+ // o duration,
+ // o volume
+ // * mark
+ // Differences between this text format and SSML are:
+ // * full SSML documents are not supported
+ // * namespaces are not supported
+ // Text is coded in UTF-8.
+ // @param text the UTF-8 text to synthesize
+ // @param userdata pointer to be returned when the call is invoked
+ // @param buffer the location where the synthesized data must be written
+ // @param bufferSize the number of bytes that can be written in buffer
+ // @return TTS_SUCCESS or TTS_FAILURE
+ android_tts_result_t (*synthesizeText)
+ (void *engine,
+ const char *text,
+ int8_t *buffer,
+ size_t bufferSize,
+ void *userdata);
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ANDROID_TTS_H */
diff --git a/packages/TtsService/jni/Android.mk b/packages/TtsService/jni/Android.mk
index b41759a..5dc0c30 100755
--- a/packages/TtsService/jni/Android.mk
+++ b/packages/TtsService/jni/Android.mk
@@ -5,6 +5,7 @@ LOCAL_SRC_FILES:= \
android_tts_SynthProxy.cpp
LOCAL_C_INCLUDES += \
+ frameworks/base/native/include \
$(JNI_H_INCLUDE)
LOCAL_SHARED_LIBRARIES := \
diff --git a/packages/TtsService/jni/android_tts_SynthProxy.cpp b/packages/TtsService/jni/android_tts_SynthProxy.cpp
index 1d69361..8dc88db 100644
--- a/packages/TtsService/jni/android_tts_SynthProxy.cpp
+++ b/packages/TtsService/jni/android_tts_SynthProxy.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Google Inc.
+ * Copyright (C) 2009-2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,7 +23,7 @@
#include <nativehelper/jni.h>
#include <nativehelper/JNIHelp.h>
#include <android_runtime/AndroidRuntime.h>
-#include <tts/TtsEngine.h>
+#include <android/tts.h>
#include <media/AudioTrack.h>
#include <math.h>
@@ -154,7 +154,7 @@ static Mutex engineMutex;
class SynthProxyJniStorage {
public :
jobject tts_ref;
- TtsEngine* mNativeSynthInterface;
+ android_tts_engine_t* mEngine;
void* mEngineLibHandle;
AudioTrack* mAudioOut;
int8_t mPlayState;
@@ -168,7 +168,7 @@ class SynthProxyJniStorage {
SynthProxyJniStorage() {
tts_ref = NULL;
- mNativeSynthInterface = NULL;
+ mEngine = NULL;
mEngineLibHandle = NULL;
mAudioOut = NULL;
mPlayState = SYNTHPLAYSTATE_IS_STOPPED;
@@ -184,9 +184,9 @@ class SynthProxyJniStorage {
~SynthProxyJniStorage() {
//LOGV("entering ~SynthProxyJniStorage()");
killAudio();
- if (mNativeSynthInterface) {
- mNativeSynthInterface->shutdown();
- mNativeSynthInterface = NULL;
+ if (mEngine) {
+ mEngine->funcs->shutdown(mEngine);
+ mEngine = NULL;
}
if (mEngineLibHandle) {
//LOGE("~SynthProxyJniStorage(): before close library");
@@ -273,28 +273,45 @@ void prepAudioTrack(SynthProxyJniStorage* pJniData, AudioSystem::stream_type str
* Callback from TTS engine.
* Directly speaks using AudioTrack or write to file
*/
-static tts_callback_status ttsSynthDoneCB(void *& userdata, uint32_t rate,
- uint32_t format, int channel,
- int8_t *&wav, size_t &bufferSize, tts_synth_status status) {
+extern "C" android_tts_callback_status_t
+__ttsSynthDoneCB(void ** pUserdata, uint32_t rate,
+ android_tts_audio_format_t format, int channel,
+ int8_t **pWav, size_t *pBufferSize,
+ android_tts_synth_status_t status)
+{
//LOGV("ttsSynthDoneCallback: %d bytes", bufferSize);
+ AudioSystem::audio_format encoding;
- if (userdata == NULL){
+ if (*pUserdata == NULL){
LOGE("userdata == NULL");
- return TTS_CALLBACK_HALT;
+ return ANDROID_TTS_CALLBACK_HALT;
+ }
+ switch (format) {
+ case ANDROID_TTS_AUDIO_FORMAT_PCM_8_BIT:
+ encoding = AudioSystem::PCM_8_BIT;
+ break;
+ case ANDROID_TTS_AUDIO_FORMAT_PCM_16_BIT:
+ encoding = AudioSystem::PCM_16_BIT;
+ break;
+ default:
+ LOGE("Can't play, bad format");
+ return ANDROID_TTS_CALLBACK_HALT;
}
- afterSynthData_t* pForAfter = (afterSynthData_t*)userdata;
+ afterSynthData_t* pForAfter = (afterSynthData_t*) *pUserdata;
SynthProxyJniStorage* pJniData = (SynthProxyJniStorage*)(pForAfter->jniStorage);
if (pForAfter->usageMode == USAGEMODE_PLAY_IMMEDIATELY){
//LOGV("Direct speech");
- if (wav == NULL) {
+ if (*pWav == NULL) {
delete pForAfter;
+ pForAfter = NULL;
LOGV("Null: speech has completed");
+ return ANDROID_TTS_CALLBACK_HALT;
}
- if (bufferSize > 0) {
- prepAudioTrack(pJniData, pForAfter->streamType, rate, (AudioSystem::audio_format)format, channel);
+ if (*pBufferSize > 0) {
+ prepAudioTrack(pJniData, pForAfter->streamType, rate, encoding, channel);
if (pJniData->mAudioOut) {
pJniData->mPlayLock.lock();
if(pJniData->mAudioOut->stopped()
@@ -303,28 +320,31 @@ static tts_callback_status ttsSynthDoneCB(void *& userdata, uint32_t rate,
}
pJniData->mPlayLock.unlock();
if (bUseFilter) {
- applyFilter((int16_t*)wav, bufferSize/2);
+ applyFilter((int16_t*)*pWav, *pBufferSize/2);
}
- pJniData->mAudioOut->write(wav, bufferSize);
- memset(wav, 0, bufferSize);
+ pJniData->mAudioOut->write(*pWav, *pBufferSize);
+ memset(*pWav, 0, *pBufferSize);
//LOGV("AudioTrack wrote: %d bytes", bufferSize);
} else {
LOGE("Can't play, null audiotrack");
+ delete pForAfter;
+ pForAfter = NULL;
+ return ANDROID_TTS_CALLBACK_HALT;
}
}
} else if (pForAfter->usageMode == USAGEMODE_WRITE_TO_FILE) {
//LOGV("Save to file");
- if (wav == NULL) {
+ if (*pWav == NULL) {
delete pForAfter;
LOGV("Null: speech has completed");
- return TTS_CALLBACK_HALT;
+ return ANDROID_TTS_CALLBACK_HALT;
}
- if (bufferSize > 0){
+ if (*pBufferSize > 0){
if (bUseFilter) {
- applyFilter((int16_t*)wav, bufferSize/2);
+ applyFilter((int16_t*)*pWav, *pBufferSize/2);
}
- fwrite(wav, 1, bufferSize, pForAfter->outputFile);
- memset(wav, 0, bufferSize);
+ fwrite(*pWav, 1, *pBufferSize, pForAfter->outputFile);
+ memset(*pWav, 0, *pBufferSize);
}
}
// Future update:
@@ -332,7 +352,7 @@ static tts_callback_status ttsSynthDoneCB(void *& userdata, uint32_t rate,
// javaTTSFields.synthProxyMethodPost methode to notify
// playback has completed if the synthesis is done or if a marker has been reached.
- if (status == TTS_SYNTH_DONE) {
+ if (status == ANDROID_TTS_SYNTH_DONE) {
// this struct was allocated in the original android_tts_SynthProxy_speak call,
// all processing matching this call is now done.
LOGV("Speech synthesis done.");
@@ -342,16 +362,16 @@ static tts_callback_status ttsSynthDoneCB(void *& userdata, uint32_t rate,
delete pForAfter;
pForAfter = NULL;
}
- return TTS_CALLBACK_HALT;
+ return ANDROID_TTS_CALLBACK_HALT;
}
// we don't update the wav (output) parameter as we'll let the next callback
// write at the same location, we've consumed the data already, but we need
// to update bufferSize to let the TTS engine know how much it can write the
// next time it calls this function.
- bufferSize = pJniData->mBufferSize;
+ *pBufferSize = pJniData->mBufferSize;
- return TTS_CALLBACK_CONTINUE;
+ return ANDROID_TTS_CALLBACK_CONTINUE;
}
@@ -360,7 +380,7 @@ static int
android_tts_SynthProxy_setLowShelf(JNIEnv *env, jobject thiz, jboolean applyFilter,
jfloat filterGain, jfloat attenuationInDb, jfloat freqInHz, jfloat slope)
{
- int result = TTS_SUCCESS;
+ int result = ANDROID_TTS_SUCCESS;
bUseFilter = applyFilter;
if (applyFilter) {
@@ -373,7 +393,7 @@ android_tts_SynthProxy_setLowShelf(JNIEnv *env, jobject thiz, jboolean applyFilt
initializeEQ();
} else {
LOGE("Invalid slope, can't be null");
- result = TTS_FAILURE;
+ result = ANDROID_TTS_FAILURE;
}
}
@@ -385,7 +405,7 @@ static int
android_tts_SynthProxy_native_setup(JNIEnv *env, jobject thiz,
jobject weak_this, jstring nativeSoLib, jstring engConfig)
{
- int result = TTS_FAILURE;
+ int result = ANDROID_TTS_FAILURE;
bUseFilter = false;
@@ -402,18 +422,28 @@ android_tts_SynthProxy_native_setup(JNIEnv *env, jobject thiz,
if (engine_lib_handle == NULL) {
LOGE("android_tts_SynthProxy_native_setup(): engine_lib_handle == NULL");
} else {
- TtsEngine *(*get_TtsEngine)() =
- reinterpret_cast<TtsEngine* (*)()>(dlsym(engine_lib_handle, "getTtsEngine"));
+ android_tts_engine_t * (*get_TtsEngine)() =
+ reinterpret_cast<android_tts_engine_t* (*)()>(dlsym(engine_lib_handle, "android_getTtsEngine"));
+
+ // Support obsolete/legacy binary modules
+ if (get_TtsEngine == NULL) {
+ get_TtsEngine =
+ reinterpret_cast<android_tts_engine_t* (*)()>(dlsym(engine_lib_handle, "getTtsEngine"));
+ }
- pJniStorage->mNativeSynthInterface = (*get_TtsEngine)();
+ pJniStorage->mEngine = (*get_TtsEngine)();
pJniStorage->mEngineLibHandle = engine_lib_handle;
- if (pJniStorage->mNativeSynthInterface) {
+ android_tts_engine_t *engine = pJniStorage->mEngine;
+ if (engine) {
Mutex::Autolock l(engineMutex);
- pJniStorage->mNativeSynthInterface->init(ttsSynthDoneCB, engConfigString);
+ engine->funcs->init(
+ engine,
+ __ttsSynthDoneCB,
+ engConfigString);
}
- result = TTS_SUCCESS;
+ result = ANDROID_TTS_SUCCESS;
}
// we use a weak reference so the SynthProxy object can be garbage collected.
@@ -462,7 +492,7 @@ static int
android_tts_SynthProxy_isLanguageAvailable(JNIEnv *env, jobject thiz, jint jniData,
jstring language, jstring country, jstring variant)
{
- int result = TTS_LANG_NOT_SUPPORTED;
+ int result = ANDROID_TTS_LANG_NOT_SUPPORTED;
if (jniData == 0) {
LOGE("android_tts_SynthProxy_isLanguageAvailable(): invalid JNI data");
@@ -474,8 +504,10 @@ android_tts_SynthProxy_isLanguageAvailable(JNIEnv *env, jobject thiz, jint jniDa
const char *countryNativeString = env->GetStringUTFChars(country, 0);
const char *variantNativeString = env->GetStringUTFChars(variant, 0);
- if (pSynthData->mNativeSynthInterface) {
- result = pSynthData->mNativeSynthInterface->isLanguageAvailable(langNativeString,
+ android_tts_engine_t *engine = pSynthData->mEngine;
+
+ if (engine) {
+ result = engine->funcs->isLanguageAvailable(engine,langNativeString,
countryNativeString, variantNativeString);
}
env->ReleaseStringUTFChars(language, langNativeString);
@@ -487,7 +519,7 @@ android_tts_SynthProxy_isLanguageAvailable(JNIEnv *env, jobject thiz, jint jniDa
static int
android_tts_SynthProxy_setConfig(JNIEnv *env, jobject thiz, jint jniData, jstring engineConfig)
{
- int result = TTS_FAILURE;
+ int result = ANDROID_TTS_FAILURE;
if (jniData == 0) {
LOGE("android_tts_SynthProxy_setConfig(): invalid JNI data");
@@ -498,9 +530,10 @@ android_tts_SynthProxy_setConfig(JNIEnv *env, jobject thiz, jint jniData, jstrin
SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData;
const char *engineConfigNativeString = env->GetStringUTFChars(engineConfig, 0);
+ android_tts_engine_t *engine = pSynthData->mEngine;
- if (pSynthData->mNativeSynthInterface) {
- result = pSynthData->mNativeSynthInterface->setProperty(ANDROID_TTS_ENGINE_PROPERTY_CONFIG,
+ if (engine) {
+ result = engine->funcs->setProperty(engine,ANDROID_TTS_ENGINE_PROPERTY_CONFIG,
engineConfigNativeString, strlen(engineConfigNativeString));
}
env->ReleaseStringUTFChars(engineConfig, engineConfigNativeString);
@@ -512,7 +545,7 @@ static int
android_tts_SynthProxy_setLanguage(JNIEnv *env, jobject thiz, jint jniData,
jstring language, jstring country, jstring variant)
{
- int result = TTS_LANG_NOT_SUPPORTED;
+ int result = ANDROID_TTS_LANG_NOT_SUPPORTED;
if (jniData == 0) {
LOGE("android_tts_SynthProxy_setLanguage(): invalid JNI data");
@@ -525,9 +558,10 @@ android_tts_SynthProxy_setLanguage(JNIEnv *env, jobject thiz, jint jniData,
const char *langNativeString = env->GetStringUTFChars(language, 0);
const char *countryNativeString = env->GetStringUTFChars(country, 0);
const char *variantNativeString = env->GetStringUTFChars(variant, 0);
+ android_tts_engine_t *engine = pSynthData->mEngine;
- if (pSynthData->mNativeSynthInterface) {
- result = pSynthData->mNativeSynthInterface->setLanguage(langNativeString,
+ if (engine) {
+ result = engine->funcs->setLanguage(engine, langNativeString,
countryNativeString, variantNativeString);
}
env->ReleaseStringUTFChars(language, langNativeString);
@@ -541,7 +575,7 @@ static int
android_tts_SynthProxy_loadLanguage(JNIEnv *env, jobject thiz, jint jniData,
jstring language, jstring country, jstring variant)
{
- int result = TTS_LANG_NOT_SUPPORTED;
+ int result = ANDROID_TTS_LANG_NOT_SUPPORTED;
if (jniData == 0) {
LOGE("android_tts_SynthProxy_loadLanguage(): invalid JNI data");
@@ -552,9 +586,10 @@ android_tts_SynthProxy_loadLanguage(JNIEnv *env, jobject thiz, jint jniData,
const char *langNativeString = env->GetStringUTFChars(language, 0);
const char *countryNativeString = env->GetStringUTFChars(country, 0);
const char *variantNativeString = env->GetStringUTFChars(variant, 0);
+ android_tts_engine_t *engine = pSynthData->mEngine;
- if (pSynthData->mNativeSynthInterface) {
- result = pSynthData->mNativeSynthInterface->loadLanguage(langNativeString,
+ if (engine) {
+ result = engine->funcs->loadLanguage(engine, langNativeString,
countryNativeString, variantNativeString);
}
env->ReleaseStringUTFChars(language, langNativeString);
@@ -569,7 +604,7 @@ static int
android_tts_SynthProxy_setSpeechRate(JNIEnv *env, jobject thiz, jint jniData,
jint speechRate)
{
- int result = TTS_FAILURE;
+ int result = ANDROID_TTS_FAILURE;
if (jniData == 0) {
LOGE("android_tts_SynthProxy_setSpeechRate(): invalid JNI data");
@@ -584,9 +619,10 @@ android_tts_SynthProxy_setSpeechRate(JNIEnv *env, jobject thiz, jint jniData,
SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData;
LOGI("setting speech rate to %d", speechRate);
+ android_tts_engine_t *engine = pSynthData->mEngine;
- if (pSynthData->mNativeSynthInterface) {
- result = pSynthData->mNativeSynthInterface->setProperty("rate", buffer, bufSize);
+ if (engine) {
+ result = engine->funcs->setProperty(engine, "rate", buffer, bufSize);
}
return result;
@@ -597,7 +633,7 @@ static int
android_tts_SynthProxy_setPitch(JNIEnv *env, jobject thiz, jint jniData,
jint pitch)
{
- int result = TTS_FAILURE;
+ int result = ANDROID_TTS_FAILURE;
if (jniData == 0) {
LOGE("android_tts_SynthProxy_setPitch(): invalid JNI data");
@@ -612,9 +648,10 @@ android_tts_SynthProxy_setPitch(JNIEnv *env, jobject thiz, jint jniData,
SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData;
LOGI("setting pitch to %d", pitch);
+ android_tts_engine_t *engine = pSynthData->mEngine;
- if (pSynthData->mNativeSynthInterface) {
- result = pSynthData->mNativeSynthInterface->setProperty("pitch", buffer, bufSize);
+ if (engine) {
+ result = engine->funcs->setProperty(engine, "pitch", buffer, bufSize);
}
return result;
@@ -625,7 +662,7 @@ static int
android_tts_SynthProxy_synthesizeToFile(JNIEnv *env, jobject thiz, jint jniData,
jstring textJavaString, jstring filenameJavaString)
{
- int result = TTS_FAILURE;
+ int result = ANDROID_TTS_FAILURE;
if (jniData == 0) {
LOGE("android_tts_SynthProxy_synthesizeToFile(): invalid JNI data");
@@ -633,7 +670,7 @@ android_tts_SynthProxy_synthesizeToFile(JNIEnv *env, jobject thiz, jint jniData,
}
SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData;
- if (!pSynthData->mNativeSynthInterface) {
+ if (!pSynthData->mEngine) {
LOGE("android_tts_SynthProxy_synthesizeToFile(): invalid engine handle");
return result;
}
@@ -643,12 +680,22 @@ android_tts_SynthProxy_synthesizeToFile(JNIEnv *env, jobject thiz, jint jniData,
Mutex::Autolock l(engineMutex);
// Retrieve audio parameters before writing the file header
- AudioSystem::audio_format encoding = DEFAULT_TTS_FORMAT;
+ AudioSystem::audio_format encoding;
uint32_t rate = DEFAULT_TTS_RATE;
int channels = DEFAULT_TTS_NB_CHANNELS;
- pSynthData->mNativeSynthInterface->setAudioFormat(encoding, rate, channels);
-
- if ((encoding != AudioSystem::PCM_16_BIT) && (encoding != AudioSystem::PCM_8_BIT)) {
+ android_tts_engine_t *engine = pSynthData->mEngine;
+ android_tts_audio_format_t format = ANDROID_TTS_AUDIO_FORMAT_DEFAULT;
+
+ engine->funcs->setAudioFormat(engine, &format, &rate, &channels);
+
+ switch (format) {
+ case ANDROID_TTS_AUDIO_FORMAT_PCM_16_BIT:
+ encoding = AudioSystem::PCM_16_BIT;
+ break;
+ case ANDROID_TTS_AUDIO_FORMAT_PCM_8_BIT:
+ encoding = AudioSystem::PCM_8_BIT;
+ break;
+ default:
LOGE("android_tts_SynthProxy_synthesizeToFile(): engine uses invalid format");
return result;
}
@@ -677,7 +724,8 @@ android_tts_SynthProxy_synthesizeToFile(JNIEnv *env, jobject thiz, jint jniData,
unsigned int unique_identifier;
memset(pSynthData->mBuffer, 0, pSynthData->mBufferSize);
- result = pSynthData->mNativeSynthInterface->synthesizeText(textNativeString,
+
+ result = engine->funcs->synthesizeText(engine, textNativeString,
pSynthData->mBuffer, pSynthData->mBufferSize, (void *)pForAfter);
long filelen = ftell(pForAfter->outputFile);
@@ -737,7 +785,7 @@ static int
android_tts_SynthProxy_speak(JNIEnv *env, jobject thiz, jint jniData,
jstring textJavaString, jint javaStreamType)
{
- int result = TTS_FAILURE;
+ int result = ANDROID_TTS_FAILURE;
if (jniData == 0) {
LOGE("android_tts_SynthProxy_speak(): invalid JNI data");
@@ -759,10 +807,12 @@ android_tts_SynthProxy_speak(JNIEnv *env, jobject thiz, jint jniData,
pForAfter->usageMode = USAGEMODE_PLAY_IMMEDIATELY;
pForAfter->streamType = (AudioSystem::stream_type) javaStreamType;
- if (pSynthData->mNativeSynthInterface) {
+ if (pSynthData->mEngine) {
const char *textNativeString = env->GetStringUTFChars(textJavaString, 0);
memset(pSynthData->mBuffer, 0, pSynthData->mBufferSize);
- result = pSynthData->mNativeSynthInterface->synthesizeText(textNativeString,
+ android_tts_engine_t *engine = pSynthData->mEngine;
+
+ result = engine->funcs->synthesizeText(engine, textNativeString,
pSynthData->mBuffer, pSynthData->mBufferSize, (void *)pForAfter);
env->ReleaseStringUTFChars(textJavaString, textNativeString);
}
@@ -774,7 +824,7 @@ android_tts_SynthProxy_speak(JNIEnv *env, jobject thiz, jint jniData,
static int
android_tts_SynthProxy_stop(JNIEnv *env, jobject thiz, jint jniData)
{
- int result = TTS_FAILURE;
+ int result = ANDROID_TTS_FAILURE;
if (jniData == 0) {
LOGE("android_tts_SynthProxy_stop(): invalid JNI data");
@@ -790,8 +840,9 @@ android_tts_SynthProxy_stop(JNIEnv *env, jobject thiz, jint jniData)
}
pSynthData->mPlayLock.unlock();
- if (pSynthData->mNativeSynthInterface) {
- result = pSynthData->mNativeSynthInterface->stop();
+ android_tts_engine_t *engine = pSynthData->mEngine;
+ if (engine) {
+ result = engine->funcs->stop(engine);
}
return result;
@@ -801,7 +852,7 @@ android_tts_SynthProxy_stop(JNIEnv *env, jobject thiz, jint jniData)
static int
android_tts_SynthProxy_stopSync(JNIEnv *env, jobject thiz, jint jniData)
{
- int result = TTS_FAILURE;
+ int result = ANDROID_TTS_FAILURE;
if (jniData == 0) {
LOGE("android_tts_SynthProxy_stop(): invalid JNI data");
@@ -829,7 +880,7 @@ android_tts_SynthProxy_getLanguage(JNIEnv *env, jobject thiz, jint jniData)
SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData;
- if (pSynthData->mNativeSynthInterface) {
+ if (pSynthData->mEngine) {
size_t bufSize = 100;
char lang[bufSize];
char country[bufSize];
@@ -839,7 +890,9 @@ android_tts_SynthProxy_getLanguage(JNIEnv *env, jobject thiz, jint jniData)
memset(variant, 0, bufSize);
jobjectArray retLocale = (jobjectArray)env->NewObjectArray(3,
env->FindClass("java/lang/String"), env->NewStringUTF(""));
- pSynthData->mNativeSynthInterface->getLanguage(lang, country, variant);
+
+ android_tts_engine_t *engine = pSynthData->mEngine;
+ engine->funcs->getLanguage(engine, lang, country, variant);
env->SetObjectArrayElement(retLocale, 0, env->NewStringUTF(lang));
env->SetObjectArrayElement(retLocale, 1, env->NewStringUTF(country));
env->SetObjectArrayElement(retLocale, 2, env->NewStringUTF(variant));
@@ -864,8 +917,9 @@ android_tts_SynthProxy_getRate(JNIEnv *env, jobject thiz, jint jniData)
char buf[bufSize];
memset(buf, 0, bufSize);
// TODO check return codes
- if (pSynthData->mNativeSynthInterface) {
- pSynthData->mNativeSynthInterface->getProperty("rate", buf, &bufSize);
+ android_tts_engine_t *engine = pSynthData->mEngine;
+ if (engine) {
+ engine->funcs->getProperty(engine,"rate", buf, &bufSize);
}
return atoi(buf);
}