| /* |
| * 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. |
| */ |
| package android.tts; |
| |
| import android.app.Service; |
| import android.content.ContentResolver; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.content.SharedPreferences; |
| import android.content.pm.PackageManager; |
| import android.content.pm.PackageManager.NameNotFoundException; |
| import android.media.MediaPlayer; |
| import android.media.MediaPlayer.OnCompletionListener; |
| import android.net.Uri; |
| import android.os.IBinder; |
| import android.os.RemoteCallbackList; |
| import android.os.RemoteException; |
| import android.preference.PreferenceManager; |
| import android.speech.tts.ITts.Stub; |
| import android.speech.tts.ITtsCallback; |
| import android.speech.tts.TextToSpeech; |
| import android.util.Log; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.HashMap; |
| import java.util.concurrent.locks.ReentrantLock; |
| |
| /** |
| * @hide Synthesizes speech from text. This is implemented as a service so that |
| * other applications can call the TTS without needing to bundle the TTS |
| * in the build. |
| * |
| */ |
| public class TtsService extends Service implements OnCompletionListener { |
| |
| private static class SpeechItem { |
| public static final int TEXT = 0; |
| public static final int IPA = 1; |
| public static final int EARCON = 2; |
| public static final int SILENCE = 3; |
| public String mText = null; |
| public ArrayList<String> mParams = null; |
| public int mType = TEXT; |
| public long mDuration = 0; |
| |
| public SpeechItem(String text, ArrayList<String> params, int itemType) { |
| mText = text; |
| mParams = params; |
| mType = itemType; |
| } |
| |
| public SpeechItem(long silenceTime) { |
| mDuration = silenceTime; |
| } |
| } |
| |
| /** |
| * Contains the information needed to access a sound resource; the name of |
| * the package that contains the resource and the resID of the resource |
| * within that package. |
| */ |
| private static class SoundResource { |
| public String mSourcePackageName = null; |
| public int mResId = -1; |
| public String mFilename = null; |
| |
| public SoundResource(String packageName, int id) { |
| mSourcePackageName = packageName; |
| mResId = id; |
| mFilename = null; |
| } |
| |
| public SoundResource(String file) { |
| mSourcePackageName = null; |
| mResId = -1; |
| mFilename = file; |
| } |
| } |
| |
| private static final int MAX_SPEECH_ITEM_CHAR_LENGTH = 4000; |
| private static final int MAX_FILENAME_LENGTH = 250; |
| |
| private static final String ACTION = "android.intent.action.USE_TTS"; |
| private static final String CATEGORY = "android.intent.category.TTS"; |
| private static final String PKGNAME = "android.tts"; |
| |
| final RemoteCallbackList<android.speech.tts.ITtsCallback> mCallbacks = new RemoteCallbackList<ITtsCallback>(); |
| |
| private Boolean mIsSpeaking; |
| private ArrayList<SpeechItem> mSpeechQueue; |
| private HashMap<String, SoundResource> mEarcons; |
| private HashMap<String, SoundResource> mUtterances; |
| private MediaPlayer mPlayer; |
| private TtsService mSelf; |
| |
| private ContentResolver mResolver; |
| |
| private final ReentrantLock speechQueueLock = new ReentrantLock(); |
| private final ReentrantLock synthesizerLock = new ReentrantLock(); |
| |
| private SynthProxy nativeSynth; |
| @Override |
| public void onCreate() { |
| super.onCreate(); |
| Log.i("TTS", "TTS starting"); |
| |
| mResolver = getContentResolver(); |
| |
| String soLibPath = "/system/lib/libttspico.so"; |
| nativeSynth = new SynthProxy(soLibPath); |
| |
| mSelf = this; |
| mIsSpeaking = false; |
| |
| mEarcons = new HashMap<String, SoundResource>(); |
| mUtterances = new HashMap<String, SoundResource>(); |
| |
| mSpeechQueue = new ArrayList<SpeechItem>(); |
| mPlayer = null; |
| |
| setDefaultSettings(); |
| } |
| |
| @Override |
| public void onDestroy() { |
| super.onDestroy(); |
| // Don't hog the media player |
| cleanUpPlayer(); |
| |
| nativeSynth.shutdown(); |
| |
| // Unregister all callbacks. |
| mCallbacks.kill(); |
| } |
| |
| |
| private void setDefaultSettings() { |
| setLanguage(this.getDefaultLanguage(), getDefaultCountry(), getDefaultLocVariant()); |
| |
| // speech rate |
| setSpeechRate(getDefaultRate()); |
| } |
| |
| |
| private boolean isDefaultEnforced() { |
| return (android.provider.Settings.Secure.getInt(mResolver, |
| android.provider.Settings.Secure.TTS_USE_DEFAULTS, |
| TextToSpeech.Engine.FALLBACK_TTS_USE_DEFAULTS) |
| == 1 ); |
| } |
| |
| |
| private int getDefaultRate() { |
| return android.provider.Settings.Secure.getInt(mResolver, |
| android.provider.Settings.Secure.TTS_DEFAULT_RATE, |
| TextToSpeech.Engine.FALLBACK_TTS_DEFAULT_RATE); |
| } |
| |
| |
| private String getDefaultLanguage() { |
| String defaultLang = android.provider.Settings.Secure.getString(mResolver, |
| android.provider.Settings.Secure.TTS_DEFAULT_LANG); |
| if (defaultLang == null) { |
| return TextToSpeech.Engine.FALLBACK_TTS_DEFAULT_LANG; |
| } else { |
| return defaultLang; |
| } |
| } |
| |
| |
| private String getDefaultCountry() { |
| String defaultCountry = android.provider.Settings.Secure.getString(mResolver, |
| android.provider.Settings.Secure.TTS_DEFAULT_COUNTRY); |
| if (defaultCountry == null) { |
| return TextToSpeech.Engine.FALLBACK_TTS_DEFAULT_COUNTRY; |
| } else { |
| return defaultCountry; |
| } |
| } |
| |
| |
| private String getDefaultLocVariant() { |
| String defaultVar = android.provider.Settings.Secure.getString(mResolver, |
| android.provider.Settings.Secure.TTS_DEFAULT_VARIANT); |
| if (defaultVar == null) { |
| return TextToSpeech.Engine.FALLBACK_TTS_DEFAULT_VARIANT; |
| } else { |
| return defaultVar; |
| } |
| } |
| |
| |
| private void setSpeechRate(int rate) { |
| if (isDefaultEnforced()) { |
| nativeSynth.setSpeechRate(getDefaultRate()); |
| } else { |
| nativeSynth.setSpeechRate(rate); |
| } |
| } |
| |
| |
| private void setPitch(int pitch) { |
| nativeSynth.setPitch(pitch); |
| } |
| |
| |
| private int isLanguageAvailable(String lang, String country, String variant) { |
| Log.v("TTS", "TtsService.isLanguageAvailable(" + lang + ", " + country + ", " +variant+")"); |
| return nativeSynth.isLanguageAvailable(lang, country, variant); |
| } |
| |
| |
| private String[] getLanguage() { |
| return nativeSynth.getLanguage(); |
| } |
| |
| |
| private void setLanguage(String lang, String country, String variant) { |
| Log.v("TTS", "TtsService.setLanguage(" + lang + ", " + country + ", " + variant + ")"); |
| if (isDefaultEnforced()) { |
| nativeSynth.setLanguage(getDefaultLanguage(), getDefaultCountry(), |
| getDefaultLocVariant()); |
| } else { |
| nativeSynth.setLanguage(lang, country, variant); |
| } |
| } |
| |
| |
| /** |
| * Adds a sound resource to the TTS. |
| * |
| * @param text |
| * The text that should be associated with the sound resource |
| * @param packageName |
| * The name of the package which has the sound resource |
| * @param resId |
| * The resource ID of the sound within its package |
| */ |
| private void addSpeech(String text, String packageName, int resId) { |
| mUtterances.put(text, new SoundResource(packageName, resId)); |
| } |
| |
| /** |
| * Adds a sound resource to the TTS. |
| * |
| * @param text |
| * The text that should be associated with the sound resource |
| * @param filename |
| * The filename of the sound resource. This must be a complete |
| * path like: (/sdcard/mysounds/mysoundbite.mp3). |
| */ |
| private void addSpeech(String text, String filename) { |
| mUtterances.put(text, new SoundResource(filename)); |
| } |
| |
| /** |
| * Adds a sound resource to the TTS as an earcon. |
| * |
| * @param earcon |
| * The text that should be associated with the sound resource |
| * @param packageName |
| * The name of the package which has the sound resource |
| * @param resId |
| * The resource ID of the sound within its package |
| */ |
| private void addEarcon(String earcon, String packageName, int resId) { |
| mEarcons.put(earcon, new SoundResource(packageName, resId)); |
| } |
| |
| /** |
| * Adds a sound resource to the TTS as an earcon. |
| * |
| * @param earcon |
| * The text that should be associated with the sound resource |
| * @param filename |
| * The filename of the sound resource. This must be a complete |
| * path like: (/sdcard/mysounds/mysoundbite.mp3). |
| */ |
| private void addEarcon(String earcon, String filename) { |
| mEarcons.put(earcon, new SoundResource(filename)); |
| } |
| |
| /** |
| * Speaks the given text using the specified queueing mode and parameters. |
| * |
| * @param text |
| * The text that should be spoken |
| * @param queueMode |
| * 0 for no queue (interrupts all previous utterances), 1 for |
| * queued |
| * @param params |
| * An ArrayList of parameters. This is not implemented for all |
| * engines. |
| */ |
| private void speak(String text, int queueMode, ArrayList<String> params) { |
| if (queueMode == 0) { |
| stop(); |
| } |
| mSpeechQueue.add(new SpeechItem(text, params, SpeechItem.TEXT)); |
| if (!mIsSpeaking) { |
| processSpeechQueue(); |
| } |
| } |
| |
| /** |
| * Speaks the given IPA text using the specified queueing mode and parameters. |
| * |
| * @param ipaText |
| * The IPA text that should be spoken |
| * @param queueMode |
| * 0 for no queue (interrupts all previous utterances), 1 for |
| * queued |
| * @param params |
| * An ArrayList of parameters. This is not implemented for all |
| * engines. |
| */ |
| private void speakIpa(String ipaText, int queueMode, ArrayList<String> params) { |
| if (queueMode == 0) { |
| stop(); |
| } |
| mSpeechQueue.add(new SpeechItem(ipaText, params, SpeechItem.IPA)); |
| if (!mIsSpeaking) { |
| processSpeechQueue(); |
| } |
| } |
| |
| /** |
| * Plays the earcon using the specified queueing mode and parameters. |
| * |
| * @param earcon |
| * The earcon that should be played |
| * @param queueMode |
| * 0 for no queue (interrupts all previous utterances), 1 for |
| * queued |
| * @param params |
| * An ArrayList of parameters. This is not implemented for all |
| * engines. |
| */ |
| private void playEarcon(String earcon, int queueMode, |
| ArrayList<String> params) { |
| if (queueMode == 0) { |
| stop(); |
| } |
| mSpeechQueue.add(new SpeechItem(earcon, params, SpeechItem.EARCON)); |
| if (!mIsSpeaking) { |
| processSpeechQueue(); |
| } |
| } |
| |
| /** |
| * Stops all speech output and removes any utterances still in the queue. |
| */ |
| private void stop() { |
| Log.i("TTS", "Stopping"); |
| mSpeechQueue.clear(); |
| |
| nativeSynth.stop(); |
| mIsSpeaking = false; |
| if (mPlayer != null) { |
| try { |
| mPlayer.stop(); |
| } catch (IllegalStateException e) { |
| // Do nothing, the player is already stopped. |
| } |
| } |
| Log.i("TTS", "Stopped"); |
| } |
| |
| public void onCompletion(MediaPlayer arg0) { |
| processSpeechQueue(); |
| } |
| |
| private void playSilence(long duration, int queueMode, |
| ArrayList<String> params) { |
| if (queueMode == 0) { |
| stop(); |
| } |
| mSpeechQueue.add(new SpeechItem(duration)); |
| if (!mIsSpeaking) { |
| processSpeechQueue(); |
| } |
| } |
| |
| private void silence(final long duration) { |
| class SilenceThread implements Runnable { |
| public void run() { |
| try { |
| Thread.sleep(duration); |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } finally { |
| processSpeechQueue(); |
| } |
| } |
| } |
| Thread slnc = (new Thread(new SilenceThread())); |
| slnc.setPriority(Thread.MIN_PRIORITY); |
| slnc.start(); |
| } |
| |
| private void speakInternalOnly(final String text, |
| final ArrayList<String> params) { |
| class SynthThread implements Runnable { |
| public void run() { |
| boolean synthAvailable = false; |
| try { |
| synthAvailable = synthesizerLock.tryLock(); |
| if (!synthAvailable) { |
| Thread.sleep(100); |
| Thread synth = (new Thread(new SynthThread())); |
| synth.setPriority(Thread.MIN_PRIORITY); |
| synth.start(); |
| return; |
| } |
| 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.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); |
| } else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_COUNTRY)){ |
| country = params.get(i+1); |
| } else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_VARIANT)){ |
| variant = params.get(i+1); |
| } |
| } |
| if (language.length() > 0){ |
| setLanguage(language, country, variant); |
| } |
| } |
| nativeSynth.speak(text); |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } finally { |
| // This check is needed because finally will always run; |
| // even if the |
| // method returns somewhere in the try block. |
| if (synthAvailable) { |
| synthesizerLock.unlock(); |
| } |
| processSpeechQueue(); |
| } |
| } |
| } |
| Thread synth = (new Thread(new SynthThread())); |
| synth.setPriority(Thread.MIN_PRIORITY); |
| synth.start(); |
| } |
| |
| private SoundResource getSoundResource(SpeechItem speechItem) { |
| SoundResource sr = null; |
| String text = speechItem.mText; |
| if (speechItem.mType == SpeechItem.SILENCE) { |
| // Do nothing if this is just silence |
| } else if (speechItem.mType == SpeechItem.EARCON) { |
| sr = mEarcons.get(text); |
| } else { |
| sr = mUtterances.get(text); |
| } |
| return sr; |
| } |
| |
| private void broadcastTtsQueueProcessingCompleted(){ |
| Intent i = new Intent(Intent.ACTION_TTS_QUEUE_PROCESSING_COMPLETED); |
| sendBroadcast(i); |
| } |
| |
| private void dispatchSpeechCompletedCallbacks(String mark) { |
| Log.i("TTS callback", "dispatch started"); |
| // Broadcast to all clients the new value. |
| final int N = mCallbacks.beginBroadcast(); |
| for (int i = 0; i < N; i++) { |
| try { |
| mCallbacks.getBroadcastItem(i).markReached(mark); |
| } catch (RemoteException e) { |
| // The RemoteCallbackList will take care of removing |
| // the dead object for us. |
| } |
| } |
| mCallbacks.finishBroadcast(); |
| Log.i("TTS callback", "dispatch completed to " + N); |
| } |
| |
| private SpeechItem splitCurrentTextIfNeeded(SpeechItem currentSpeechItem){ |
| if (currentSpeechItem.mText.length() < MAX_SPEECH_ITEM_CHAR_LENGTH){ |
| return currentSpeechItem; |
| } else { |
| ArrayList<SpeechItem> splitItems = new ArrayList<SpeechItem>(); |
| int start = 0; |
| int end = start + MAX_SPEECH_ITEM_CHAR_LENGTH - 1; |
| String splitText; |
| SpeechItem splitItem; |
| while (end < currentSpeechItem.mText.length()){ |
| splitText = currentSpeechItem.mText.substring(start, end); |
| splitItem = new SpeechItem(splitText, null, SpeechItem.TEXT); |
| splitItems.add(splitItem); |
| start = end; |
| end = start + MAX_SPEECH_ITEM_CHAR_LENGTH - 1; |
| } |
| splitText = currentSpeechItem.mText.substring(start); |
| splitItem = new SpeechItem(splitText, null, SpeechItem.TEXT); |
| splitItems.add(splitItem); |
| mSpeechQueue.remove(0); |
| for (int i = splitItems.size() - 1; i >= 0; i--){ |
| mSpeechQueue.add(0, splitItems.get(i)); |
| } |
| return mSpeechQueue.get(0); |
| } |
| } |
| |
| private void processSpeechQueue() { |
| boolean speechQueueAvailable = false; |
| try { |
| speechQueueAvailable = speechQueueLock.tryLock(); |
| if (!speechQueueAvailable) { |
| return; |
| } |
| if (mSpeechQueue.size() < 1) { |
| mIsSpeaking = false; |
| broadcastTtsQueueProcessingCompleted(); |
| return; |
| } |
| |
| SpeechItem currentSpeechItem = mSpeechQueue.get(0); |
| mIsSpeaking = true; |
| SoundResource sr = getSoundResource(currentSpeechItem); |
| // Synth speech as needed - synthesizer should call |
| // processSpeechQueue to continue running the queue |
| Log.i("TTS processing: ", currentSpeechItem.mText); |
| if (sr == null) { |
| if (currentSpeechItem.mType == SpeechItem.TEXT) { |
| currentSpeechItem = splitCurrentTextIfNeeded(currentSpeechItem); |
| speakInternalOnly(currentSpeechItem.mText, |
| currentSpeechItem.mParams); |
| } else if (currentSpeechItem.mType == SpeechItem.IPA) { |
| // TODO Implement IPA support |
| } else { |
| // This is either silence or an earcon that was missing |
| silence(currentSpeechItem.mDuration); |
| } |
| } else { |
| cleanUpPlayer(); |
| if (sr.mSourcePackageName == PKGNAME) { |
| // Utterance is part of the TTS library |
| mPlayer = MediaPlayer.create(this, sr.mResId); |
| } else if (sr.mSourcePackageName != null) { |
| // Utterance is part of the app calling the library |
| Context ctx; |
| try { |
| ctx = this.createPackageContext(sr.mSourcePackageName, |
| 0); |
| } catch (NameNotFoundException e) { |
| e.printStackTrace(); |
| mSpeechQueue.remove(0); // Remove it from the queue and |
| // move on |
| mIsSpeaking = false; |
| return; |
| } |
| mPlayer = MediaPlayer.create(ctx, sr.mResId); |
| } else { |
| // Utterance is coming from a file |
| mPlayer = MediaPlayer.create(this, Uri.parse(sr.mFilename)); |
| } |
| |
| // Check if Media Server is dead; if it is, clear the queue and |
| // give up for now - hopefully, it will recover itself. |
| if (mPlayer == null) { |
| mSpeechQueue.clear(); |
| mIsSpeaking = false; |
| return; |
| } |
| mPlayer.setOnCompletionListener(this); |
| try { |
| mPlayer.start(); |
| } catch (IllegalStateException e) { |
| mSpeechQueue.clear(); |
| mIsSpeaking = false; |
| cleanUpPlayer(); |
| return; |
| } |
| } |
| if (mSpeechQueue.size() > 0) { |
| mSpeechQueue.remove(0); |
| } |
| } finally { |
| // This check is needed because finally will always run; even if the |
| // method returns somewhere in the try block. |
| if (speechQueueAvailable) { |
| speechQueueLock.unlock(); |
| } |
| } |
| } |
| |
| private void cleanUpPlayer() { |
| if (mPlayer != null) { |
| mPlayer.release(); |
| mPlayer = null; |
| } |
| } |
| |
| /** |
| * Synthesizes the given text to a file using the specified parameters. |
| * |
| * @param text |
| * The String of text that should be synthesized |
| * @param params |
| * An ArrayList of parameters. The first element of this array |
| * controls the type of voice to use. |
| * @param filename |
| * The string that gives the full output filename; it should be |
| * something like "/sdcard/myappsounds/mysound.wav". |
| * @return A boolean that indicates if the synthesis succeeded |
| */ |
| private boolean synthesizeToFile(String text, ArrayList<String> params, |
| String filename, boolean calledFromApi) { |
| // Only stop everything if this is a call made by an outside app trying |
| // to |
| // use the API. Do NOT stop if this is a call from within the service as |
| // clearing the speech queue here would be a mistake. |
| if (calledFromApi) { |
| stop(); |
| } |
| Log.i("TTS", "Synthesizing to " + filename); |
| boolean synthAvailable = false; |
| try { |
| synthAvailable = synthesizerLock.tryLock(); |
| if (!synthAvailable) { |
| return false; |
| } |
| // Don't allow a filename that is too long |
| if (filename.length() > MAX_FILENAME_LENGTH) { |
| return false; |
| } |
| nativeSynth.synthesizeToFile(text, filename); |
| } finally { |
| // This check is needed because finally will always run; even if the |
| // method returns somewhere in the try block. |
| if (synthAvailable) { |
| synthesizerLock.unlock(); |
| } |
| } |
| Log.i("TTS", "Completed synthesis for " + filename); |
| return true; |
| } |
| |
| /** |
| * Synthesizes the given IPA text to a file using the specified parameters. |
| * |
| * @param ipaText |
| * The String of IPA text that should be synthesized |
| * @param params |
| * An ArrayList of parameters. The first element of this array |
| * controls the type of voice to use. |
| * @param filename |
| * The string that gives the full output filename; it should be |
| * something like "/sdcard/myappsounds/mysound.wav". |
| * @return A boolean that indicates if the synthesis succeeded |
| */ |
| private boolean synthesizeIpaToFile(String ipaText, ArrayList<String> params, |
| String filename, boolean calledFromApi) { |
| // Only stop everything if this is a call made by an outside app trying |
| // to |
| // use the API. Do NOT stop if this is a call from within the service as |
| // clearing the speech queue here would be a mistake. |
| if (calledFromApi) { |
| stop(); |
| } |
| Log.i("TTS", "Synthesizing IPA to " + filename); |
| boolean synthAvailable = false; |
| try { |
| synthAvailable = synthesizerLock.tryLock(); |
| if (!synthAvailable) { |
| return false; |
| } |
| // Don't allow a filename that is too long |
| if (filename.length() > MAX_FILENAME_LENGTH) { |
| return false; |
| } |
| // TODO: Add nativeSynth.synthesizeIpaToFile(text, filename); |
| } finally { |
| // This check is needed because finally will always run; even if the |
| // method returns somewhere in the try block. |
| if (synthAvailable) { |
| synthesizerLock.unlock(); |
| } |
| } |
| Log.i("TTS", "Completed synthesis for " + filename); |
| return true; |
| } |
| |
| @Override |
| public IBinder onBind(Intent intent) { |
| if (ACTION.equals(intent.getAction())) { |
| for (String category : intent.getCategories()) { |
| if (category.equals(CATEGORY)) { |
| return mBinder; |
| } |
| } |
| } |
| return null; |
| } |
| |
| private final android.speech.tts.ITts.Stub mBinder = new Stub() { |
| |
| public void registerCallback(ITtsCallback cb) { |
| if (cb != null) |
| mCallbacks.register(cb); |
| } |
| |
| public void unregisterCallback(ITtsCallback cb) { |
| if (cb != null) |
| mCallbacks.unregister(cb); |
| } |
| |
| /** |
| * Speaks the given text using the specified queueing mode and |
| * parameters. |
| * |
| * @param text |
| * The text that should be spoken |
| * @param queueMode |
| * 0 for no queue (interrupts all previous utterances), 1 for |
| * queued |
| * @param params |
| * An ArrayList of parameters. The first element of this |
| * array controls the type of voice to use. |
| */ |
| public void speak(String text, int queueMode, String[] params) { |
| ArrayList<String> speakingParams = new ArrayList<String>(); |
| if (params != null) { |
| speakingParams = new ArrayList<String>(Arrays.asList(params)); |
| } |
| mSelf.speak(text, queueMode, speakingParams); |
| } |
| |
| /** |
| * Speaks the given IPA text using the specified queueing mode and |
| * parameters. |
| * |
| * @param ipaText |
| * The IPA text that should be spoken |
| * @param queueMode |
| * 0 for no queue (interrupts all previous utterances), 1 for |
| * queued |
| * @param params |
| * An ArrayList of parameters. The first element of this |
| * array controls the type of voice to use. |
| */ |
| public void speakIpa(String ipaText, int queueMode, String[] params) { |
| ArrayList<String> speakingParams = new ArrayList<String>(); |
| if (params != null) { |
| speakingParams = new ArrayList<String>(Arrays.asList(params)); |
| } |
| mSelf.speakIpa(ipaText, queueMode, speakingParams); |
| } |
| |
| /** |
| * Plays the earcon using the specified queueing mode and parameters. |
| * |
| * @param earcon |
| * The earcon that should be played |
| * @param queueMode |
| * 0 for no queue (interrupts all previous utterances), 1 for |
| * queued |
| * @param params |
| * An ArrayList of parameters. |
| */ |
| public void playEarcon(String earcon, int queueMode, String[] params) { |
| ArrayList<String> speakingParams = new ArrayList<String>(); |
| if (params != null) { |
| speakingParams = new ArrayList<String>(Arrays.asList(params)); |
| } |
| mSelf.playEarcon(earcon, queueMode, speakingParams); |
| } |
| |
| /** |
| * Plays the silence using the specified queueing mode and parameters. |
| * |
| * @param duration |
| * The duration of the silence that should be played |
| * @param queueMode |
| * 0 for no queue (interrupts all previous utterances), 1 for |
| * queued |
| * @param params |
| * An ArrayList of parameters. |
| */ |
| public void playSilence(long duration, int queueMode, String[] params) { |
| ArrayList<String> speakingParams = new ArrayList<String>(); |
| if (params != null) { |
| speakingParams = new ArrayList<String>(Arrays.asList(params)); |
| } |
| mSelf.playSilence(duration, queueMode, speakingParams); |
| } |
| |
| /** |
| * Stops all speech output and removes any utterances still in the |
| * queue. |
| */ |
| public void stop() { |
| mSelf.stop(); |
| } |
| |
| /** |
| * Returns whether or not the TTS is speaking. |
| * |
| * @return Boolean to indicate whether or not the TTS is speaking |
| */ |
| public boolean isSpeaking() { |
| return (mSelf.mIsSpeaking && (mSpeechQueue.size() < 1)); |
| } |
| |
| /** |
| * Adds a sound resource to the TTS. |
| * |
| * @param text |
| * The text that should be associated with the sound resource |
| * @param packageName |
| * The name of the package which has the sound resource |
| * @param resId |
| * The resource ID of the sound within its package |
| */ |
| public void addSpeech(String text, String packageName, int resId) { |
| mSelf.addSpeech(text, packageName, resId); |
| } |
| |
| /** |
| * Adds a sound resource to the TTS. |
| * |
| * @param text |
| * The text that should be associated with the sound resource |
| * @param filename |
| * The filename of the sound resource. This must be a |
| * complete path like: (/sdcard/mysounds/mysoundbite.mp3). |
| */ |
| public void addSpeechFile(String text, String filename) { |
| mSelf.addSpeech(text, filename); |
| } |
| |
| /** |
| * Adds a sound resource to the TTS as an earcon. |
| * |
| * @param earcon |
| * The text that should be associated with the sound resource |
| * @param packageName |
| * The name of the package which has the sound resource |
| * @param resId |
| * The resource ID of the sound within its package |
| */ |
| public void addEarcon(String earcon, String packageName, int resId) { |
| mSelf.addEarcon(earcon, packageName, resId); |
| } |
| |
| /** |
| * Adds a sound resource to the TTS as an earcon. |
| * |
| * @param earcon |
| * The text that should be associated with the sound resource |
| * @param filename |
| * The filename of the sound resource. This must be a |
| * complete path like: (/sdcard/mysounds/mysoundbite.mp3). |
| */ |
| public void addEarconFile(String earcon, String filename) { |
| mSelf.addEarcon(earcon, filename); |
| } |
| |
| /** |
| * Sets the speech rate for the TTS. Note that this will only have an |
| * effect on synthesized speech; it will not affect pre-recorded speech. |
| * |
| * @param speechRate |
| * The speech rate that should be used |
| */ |
| public void setSpeechRate(int speechRate) { |
| mSelf.setSpeechRate(speechRate); |
| } |
| |
| /** |
| * Sets the pitch for the TTS. Note that this will only have an |
| * effect on synthesized speech; it will not affect pre-recorded speech. |
| * |
| * @param pitch |
| * The pitch that should be used for the synthesized voice |
| */ |
| public void setPitch(int pitch) { |
| mSelf.setPitch(pitch); |
| } |
| |
| /** |
| * Returns the level of support for the specified language. |
| * |
| * @param lang the three letter ISO language code. |
| * @param country the three letter ISO country code. |
| * @param variant the variant code associated with the country and language pair. |
| * @return one of TTS_LANG_NOT_SUPPORTED, TTS_LANG_MISSING_DATA, TTS_LANG_AVAILABLE, |
| * TTS_LANG_COUNTRY_AVAILABLE, TTS_LANG_COUNTRY_VAR_AVAILABLE as defined in |
| * android.speech.tts.TextToSpeech. |
| */ |
| public int isLanguageAvailable(String lang, String country, String variant) { |
| return mSelf.isLanguageAvailable(lang, country, variant); |
| } |
| |
| /** |
| * Returns the currently set language / country / variant strings representing the |
| * language used by the TTS engine. |
| * @return null is no language is set, or an array of 3 string containing respectively |
| * the language, country and variant. |
| */ |
| public String[] getLanguage() { |
| return mSelf.getLanguage(); |
| } |
| |
| /** |
| * Sets the speech rate for the TTS, which affects the synthesized voice. |
| * |
| * @param lang the three letter ISO language code. |
| * @param country the three letter ISO country code. |
| * @param variant the variant code associated with the country and language pair. |
| */ |
| public void setLanguage(String lang, String country, String variant) { |
| mSelf.setLanguage(lang, country, variant); |
| } |
| |
| /** |
| * Synthesizes the given text to a file using the specified |
| * parameters. |
| * |
| * @param text |
| * The String of text that should be synthesized |
| * @param params |
| * An ArrayList of parameters. The first element of this |
| * array controls the type of voice to use. |
| * @param filename |
| * The string that gives the full output filename; it should |
| * be something like "/sdcard/myappsounds/mysound.wav". |
| * @return A boolean that indicates if the synthesis succeeded |
| */ |
| public boolean synthesizeToFile(String text, String[] params, |
| String filename) { |
| ArrayList<String> speakingParams = new ArrayList<String>(); |
| if (params != null) { |
| speakingParams = new ArrayList<String>(Arrays.asList(params)); |
| } |
| return mSelf.synthesizeToFile(text, speakingParams, filename, true); |
| } |
| |
| /** |
| * Synthesizes the given IPA text to a file using the specified |
| * parameters. |
| * |
| * @param ipaText |
| * The String of IPA text that should be synthesized |
| * @param params |
| * An ArrayList of parameters. The first element of this |
| * array controls the type of voice to use. |
| * @param filename |
| * The string that gives the full output filename; it should |
| * be something like "/sdcard/myappsounds/mysound.wav". |
| * @return A boolean that indicates if the synthesis succeeded |
| */ |
| public boolean synthesizeIpaToFile(String ipaText, String[] params, |
| String filename) { |
| ArrayList<String> speakingParams = new ArrayList<String>(); |
| if (params != null) { |
| speakingParams = new ArrayList<String>(Arrays.asList(params)); |
| } |
| return mSelf.synthesizeIpaToFile(ipaText, speakingParams, filename, true); |
| } |
| }; |
| |
| } |