diff options
| author | Android (Google) Code Review <android-gerrit@google.com> | 2009-07-13 13:36:37 -0700 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2009-07-13 13:36:37 -0700 |
| commit | 334b861e3339bc7189372f790d0c0e2043d160a3 (patch) | |
| tree | f9d2cdd1e183f12f9cfa584fe9b8a00406fdf033 /packages/TtsService | |
| parent | aa4593706e4586fb4dfa6bd00d49c6f6159cbe0f (diff) | |
| parent | 9440bce8553a82e420e06ded3fcccc6971d1ff79 (diff) | |
| download | frameworks_base-334b861e3339bc7189372f790d0c0e2043d160a3.zip frameworks_base-334b861e3339bc7189372f790d0c0e2043d160a3.tar.gz frameworks_base-334b861e3339bc7189372f790d0c0e2043d160a3.tar.bz2 | |
Merge change 6925 into donut
* changes:
Propagate optional audio stream type to the creation of the audio resources to enable the playback of TTS content on various stream types.
Diffstat (limited to 'packages/TtsService')
| -rw-r--r-- | packages/TtsService/jni/android_tts_SynthProxy.cpp | 42 | ||||
| -rwxr-xr-x | packages/TtsService/src/android/tts/SynthProxy.java | 13 | ||||
| -rwxr-xr-x | packages/TtsService/src/android/tts/TtsService.java | 38 |
3 files changed, 67 insertions, 26 deletions
diff --git a/packages/TtsService/jni/android_tts_SynthProxy.cpp b/packages/TtsService/jni/android_tts_SynthProxy.cpp index 1958ba9..4247483 100644 --- a/packages/TtsService/jni/android_tts_SynthProxy.cpp +++ b/packages/TtsService/jni/android_tts_SynthProxy.cpp @@ -33,6 +33,8 @@ #define DEFAULT_TTS_FORMAT AudioSystem::PCM_16_BIT #define DEFAULT_TTS_NB_CHANNELS 1 #define DEFAULT_TTS_BUFFERSIZE 1024 +// TODO use the TTS stream type when available +#define DEFAULT_TTS_STREAM_TYPE AudioSystem::MUSIC #define USAGEMODE_PLAY_IMMEDIATELY 0 #define USAGEMODE_WRITE_TO_FILE 1 @@ -46,10 +48,12 @@ struct fields_t { jmethodID synthProxyMethodPost; }; +// structure to hold the data that is used each time the TTS engine has synthesized more data struct afterSynthData_t { jint jniStorage; int usageMode; FILE* outputFile; + AudioSystem::stream_type streamType; }; // ---------------------------------------------------------------------------- @@ -62,6 +66,7 @@ class SynthProxyJniStorage { jobject tts_ref; TtsEngine* mNativeSynthInterface; AudioTrack* mAudioOut; + AudioSystem::stream_type mStreamType; uint32_t mSampleRate; AudioSystem::audio_format mAudFormat; int mNbChannels; @@ -73,6 +78,7 @@ class SynthProxyJniStorage { tts_ref = NULL; mNativeSynthInterface = NULL; mAudioOut = NULL; + mStreamType = DEFAULT_TTS_STREAM_TYPE; mSampleRate = DEFAULT_TTS_RATE; mAudFormat = DEFAULT_TTS_FORMAT; mNbChannels = DEFAULT_TTS_NB_CHANNELS; @@ -97,34 +103,33 @@ class SynthProxyJniStorage { } } - void createAudioOut(uint32_t rate, AudioSystem::audio_format format, - int channel) { + void createAudioOut(AudioSystem::stream_type streamType, uint32_t rate, + AudioSystem::audio_format format, int channel) { mSampleRate = rate; mAudFormat = format; mNbChannels = channel; - // TODO use the TTS stream type - int streamType = AudioSystem::MUSIC; + mStreamType = streamType; // retrieve system properties to ensure successful creation of the // AudioTrack object for playback int afSampleRate; - if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) { + if (AudioSystem::getOutputSamplingRate(&afSampleRate, mStreamType) != NO_ERROR) { afSampleRate = 44100; } int afFrameCount; - if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) { + if (AudioSystem::getOutputFrameCount(&afFrameCount, mStreamType) != NO_ERROR) { afFrameCount = 2048; } uint32_t afLatency; - if (AudioSystem::getOutputLatency(&afLatency, streamType) != NO_ERROR) { + if (AudioSystem::getOutputLatency(&afLatency, mStreamType) != NO_ERROR) { afLatency = 500; } uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate); if (minBufCount < 2) minBufCount = 2; int minFrameCount = (afFrameCount * rate * minBufCount)/afSampleRate; - mAudioOut = new AudioTrack(streamType, rate, format, channel, + mAudioOut = new AudioTrack(mStreamType, rate, format, channel, minFrameCount > 4096 ? minFrameCount : 4096, 0, 0, 0, 0); // not using an AudioTrack callback @@ -142,21 +147,21 @@ class SynthProxyJniStorage { // ---------------------------------------------------------------------------- -void prepAudioTrack(SynthProxyJniStorage* pJniData, - uint32_t rate, AudioSystem::audio_format format, int channel) -{ +void prepAudioTrack(SynthProxyJniStorage* pJniData, AudioSystem::stream_type streamType, + uint32_t rate, AudioSystem::audio_format format, int channel) { // Don't bother creating a new audiotrack object if the current - // object is already set. + // object is already initialized with the same audio parameters. if ( pJniData->mAudioOut && (rate == pJniData->mSampleRate) && (format == pJniData->mAudFormat) && - (channel == pJniData->mNbChannels) ){ + (channel == pJniData->mNbChannels) && + (streamType == pJniData->mStreamType) ){ return; } if (pJniData->mAudioOut){ pJniData->killAudio(); } - pJniData->createAudioOut(rate, format, channel); + pJniData->createAudioOut(streamType, rate, format, channel); } @@ -186,7 +191,7 @@ static tts_callback_status ttsSynthDoneCB(void *& userdata, uint32_t rate, } if (bufferSize > 0) { - prepAudioTrack(pJniData, rate, format, channel); + prepAudioTrack(pJniData, pForAfter->streamType, rate, format, channel); if (pJniData->mAudioOut) { pJniData->mAudioOut->write(wav, bufferSize); //LOGV("AudioTrack wrote: %d bytes", bufferSize); @@ -241,7 +246,7 @@ android_tts_SynthProxy_native_setup(JNIEnv *env, jobject thiz, SynthProxyJniStorage* pJniStorage = new SynthProxyJniStorage(); prepAudioTrack(pJniStorage, - DEFAULT_TTS_RATE, DEFAULT_TTS_FORMAT, DEFAULT_TTS_NB_CHANNELS); + DEFAULT_TTS_STREAM_TYPE, DEFAULT_TTS_RATE, DEFAULT_TTS_FORMAT, DEFAULT_TTS_NB_CHANNELS); const char *nativeSoLibNativeString = env->GetStringUTFChars(nativeSoLib, 0); @@ -526,7 +531,7 @@ android_tts_SynthProxy_synthesizeToFile(JNIEnv *env, jobject thiz, jint jniData, static int android_tts_SynthProxy_speak(JNIEnv *env, jobject thiz, jint jniData, - jstring textJavaString) + jstring textJavaString, jint javaStreamType) { int result = TTS_FAILURE; @@ -545,6 +550,7 @@ android_tts_SynthProxy_speak(JNIEnv *env, jobject thiz, jint jniData, afterSynthData_t* pForAfter = new (afterSynthData_t); pForAfter->jniStorage = jniData; pForAfter->usageMode = USAGEMODE_PLAY_IMMEDIATELY; + pForAfter->streamType = (AudioSystem::stream_type) javaStreamType; if (pSynthData->mNativeSynthInterface) { const char *textNativeString = env->GetStringUTFChars(textJavaString, 0); @@ -672,7 +678,7 @@ static JNINativeMethod gMethods[] = { (void*)android_tts_SynthProxy_stop }, { "native_speak", - "(ILjava/lang/String;)I", + "(ILjava/lang/String;I)I", (void*)android_tts_SynthProxy_speak }, { "native_synthesizeToFile", diff --git a/packages/TtsService/src/android/tts/SynthProxy.java b/packages/TtsService/src/android/tts/SynthProxy.java index bb16b14..41ff92a 100755 --- a/packages/TtsService/src/android/tts/SynthProxy.java +++ b/packages/TtsService/src/android/tts/SynthProxy.java @@ -15,6 +15,8 @@ */ package android.tts; +import android.media.AudioManager; +import android.media.AudioSystem; import android.util.Log; import java.lang.ref.WeakReference; @@ -52,8 +54,13 @@ public class SynthProxy { /** * Synthesize speech and speak it directly using AudioTrack. */ - public int speak(String text) { - return native_speak(mJniData, text); + public int speak(String text, int streamType) { + if ((streamType > -1) && (streamType < AudioSystem.getNumStreamTypes())) { + return native_speak(mJniData, text, streamType); + } else { + Log.e("SynthProxy", "Trying to speak with invalid stream type " + streamType); + return native_speak(mJniData, text, AudioManager.STREAM_MUSIC); + } } /** @@ -156,7 +163,7 @@ public class SynthProxy { private native final int native_stop(int jniData); - private native final int native_speak(int jniData, String text); + private native final int native_speak(int jniData, String text, int streamType); private native final int native_synthesizeToFile(int jniData, String text, String filename); diff --git a/packages/TtsService/src/android/tts/TtsService.java b/packages/TtsService/src/android/tts/TtsService.java index 60c30b2..949dfae 100755 --- a/packages/TtsService/src/android/tts/TtsService.java +++ b/packages/TtsService/src/android/tts/TtsService.java @@ -22,6 +22,7 @@ import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; +import android.media.AudioManager; import android.media.MediaPlayer; import android.media.MediaPlayer.OnCompletionListener; import android.net.Uri; @@ -109,6 +110,8 @@ public class TtsService extends Service implements OnCompletionListener { private static final int MAX_SPEECH_ITEM_CHAR_LENGTH = 4000; private static final int MAX_FILENAME_LENGTH = 250; + // TODO use the TTS stream type when available + private static final int DEFAULT_STREAM_TYPE = AudioManager.STREAM_MUSIC; private static final String ACTION = "android.intent.action.START_TTS_SERVICE"; private static final String CATEGORY = "android.intent.category.TTS"; @@ -450,14 +453,15 @@ public class TtsService extends Service implements OnCompletionListener { synth.start(); return; } + int streamType = DEFAULT_STREAM_TYPE; if (params != null){ String language = ""; String country = ""; String variant = ""; for (int i = 0; i < params.size() - 1; i = i + 2){ String param = params.get(i); - if (param != null){ - if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_RATE)){ + if (param != null) { + if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_RATE)) { setSpeechRate("", Integer.parseInt(params.get(i+1))); } else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_LANGUAGE)){ language = params.get(i+1); @@ -465,6 +469,12 @@ public class TtsService extends Service implements OnCompletionListener { country = params.get(i+1); } else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_VARIANT)){ variant = params.get(i+1); + } else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_STREAM)) { + try { + streamType = Integer.parseInt(params.get(i + 1)); + } catch (NumberFormatException e) { + streamType = DEFAULT_STREAM_TYPE; + } } } } @@ -472,7 +482,7 @@ public class TtsService extends Service implements OnCompletionListener { setLanguage("", language, country, variant); } } - nativeSynth.speak(text); + nativeSynth.speak(text, streamType); } catch (InterruptedException e) { Log.e("TTS speakInternalOnly", "tryLock interrupted"); e.printStackTrace(); @@ -651,8 +661,7 @@ public class TtsService extends Service implements OnCompletionListener { // Utterance is part of the app calling the library Context ctx; try { - ctx = this.createPackageContext(sr.mSourcePackageName, - 0); + ctx = this.createPackageContext(sr.mSourcePackageName, 0); } catch (NameNotFoundException e) { e.printStackTrace(); mSpeechQueue.remove(0); // Remove it from the queue and @@ -675,6 +684,7 @@ public class TtsService extends Service implements OnCompletionListener { } mPlayer.setOnCompletionListener(this); try { + mPlayer.setAudioStreamType(getStreamTypeFromParams(currentSpeechItem.mParams)); mPlayer.start(); } catch (IllegalStateException e) { mSpeechQueue.clear(); @@ -695,6 +705,24 @@ public class TtsService extends Service implements OnCompletionListener { } } + private int getStreamTypeFromParams(ArrayList<String> paramList) { + int streamType = DEFAULT_STREAM_TYPE; + if (paramList == null) { + return streamType; + } + for (int i = 0; i < paramList.size() - 1; i = i + 2) { + String param = paramList.get(i); + if ((param != null) && (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_STREAM))) { + try { + streamType = Integer.parseInt(paramList.get(i + 1)); + } catch (NumberFormatException e) { + streamType = DEFAULT_STREAM_TYPE; + } + } + } + return streamType; + } + private void cleanUpPlayer() { if (mPlayer != null) { mPlayer.release(); |
