2 * Copyright (C) 2009 Google Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations under
16 package android.speech.tts;
18 import android.speech.tts.ITts;
19 import android.speech.tts.ITtsCallback;
21 import android.annotation.SdkConstant;
22 import android.annotation.SdkConstant.SdkConstantType;
23 import android.content.ComponentName;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.ServiceConnection;
27 import android.media.AudioManager;
28 import android.os.IBinder;
29 import android.os.RemoteException;
30 import android.util.Log;
32 import java.util.HashMap;
33 import java.util.Locale;
37 * Synthesizes speech from text for immediate playback or to create a sound file.
38 * <p>A TextToSpeech instance can only be used to synthesize text once it has completed its
39 * initialization. Implement the {@link TextToSpeech.OnInitListener} to be
40 * notified of the completion of the initialization.<br>
41 * When you are done using the TextToSpeech instance, call the {@link #shutdown()} method
42 * to release the native resources used by the TextToSpeech engine.
45 public class TextToSpeech {
48 * Denotes a successful operation.
50 public static final int SUCCESS = 0;
52 * Denotes a generic operation failure.
54 public static final int ERROR = -1;
57 * Queue mode where all entries in the playback queue (media to be played
58 * and text to be synthesized) are dropped and replaced by the new entry.
60 public static final int QUEUE_FLUSH = 0;
62 * Queue mode where the new entry is added at the end of the playback queue.
64 public static final int QUEUE_ADD = 1;
68 * Denotes the language is available exactly as specified by the locale.
70 public static final int LANG_COUNTRY_VAR_AVAILABLE = 2;
74 * Denotes the language is available for the language and country specified
75 * by the locale, but not the variant.
77 public static final int LANG_COUNTRY_AVAILABLE = 1;
81 * Denotes the language is available for the language by the locale,
82 * but not the country and variant.
84 public static final int LANG_AVAILABLE = 0;
87 * Denotes the language data is missing.
89 public static final int LANG_MISSING_DATA = -1;
92 * Denotes the language is not supported.
94 public static final int LANG_NOT_SUPPORTED = -2;
98 * Broadcast Action: The TextToSpeech synthesizer has completed processing
99 * of all the text in the speech queue.
101 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
102 public static final String ACTION_TTS_QUEUE_PROCESSING_COMPLETED =
103 "android.speech.tts.TTS_QUEUE_PROCESSING_COMPLETED";
107 * Interface definition of a callback to be invoked indicating the completion of the
108 * TextToSpeech engine initialization.
110 public interface OnInitListener {
112 * Called to signal the completion of the TextToSpeech engine initialization.
113 * @param status {@link TextToSpeech#SUCCESS} or {@link TextToSpeech#ERROR}.
115 public void onInit(int status);
119 * Interface definition of a callback to be invoked indicating the TextToSpeech engine has
120 * completed synthesizing an utterance with an utterance ID set.
123 public interface OnUtteranceCompletedListener {
125 * Called to signal the completion of the synthesis of the utterance that was identified
126 * with the string parameter. This identifier is the one originally passed in the
127 * parameter hashmap of the synthesis request in
128 * {@link TextToSpeech#speak(String, int, HashMap)} or
129 * {@link TextToSpeech#synthesizeToFile(String, HashMap, String)} with the
130 * {@link TextToSpeech.Engine#KEY_PARAM_UTTERANCE_ID} key.
131 * @param utteranceId the identifier of the utterance.
133 public void onUtteranceCompleted(String utteranceId);
138 * Internal constants for the TextToSpeech functionality
141 public class Engine {
142 // default values for a TTS engine when settings are not found in the provider
146 public static final int DEFAULT_RATE = 100; // 1x
150 public static final int DEFAULT_PITCH = 100;// 1x
154 public static final int USE_DEFAULTS = 0; // false
158 public static final String DEFAULT_SYNTH = "com.svox.pico";
160 // default values for rendering
162 * Default audio stream used when playing synthesized speech.
164 public static final int DEFAULT_STREAM = AudioManager.STREAM_MUSIC;
166 // return codes for a TTS engine's check data activity
168 * Indicates success when checking the installation status of the resources used by the
169 * TextToSpeech engine with the {@link #ACTION_CHECK_TTS_DATA} intent.
171 public static final int CHECK_VOICE_DATA_PASS = 1;
173 * Indicates failure when checking the installation status of the resources used by the
174 * TextToSpeech engine with the {@link #ACTION_CHECK_TTS_DATA} intent.
176 public static final int CHECK_VOICE_DATA_FAIL = 0;
178 * Indicates erroneous data when checking the installation status of the resources used by
179 * the TextToSpeech engine with the {@link #ACTION_CHECK_TTS_DATA} intent.
181 public static final int CHECK_VOICE_DATA_BAD_DATA = -1;
183 * Indicates missing resources when checking the installation status of the resources used
184 * by the TextToSpeech engine with the {@link #ACTION_CHECK_TTS_DATA} intent.
186 public static final int CHECK_VOICE_DATA_MISSING_DATA = -2;
188 * Indicates missing storage volume when checking the installation status of the resources
189 * used by the TextToSpeech engine with the {@link #ACTION_CHECK_TTS_DATA} intent.
191 public static final int CHECK_VOICE_DATA_MISSING_VOLUME = -3;
193 // intents to ask engine to install data or check its data
195 * Activity Action: Triggers the platform TextToSpeech engine to
196 * start the activity that installs the resource files on the device
197 * that are required for TTS to be operational. Since the installation
198 * of the data can be interrupted or declined by the user, the application
199 * shouldn't expect successful installation upon return from that intent,
200 * and if need be, should check installation status with
201 * {@link #ACTION_CHECK_TTS_DATA}.
203 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
204 public static final String ACTION_INSTALL_TTS_DATA =
205 "android.speech.tts.engine.INSTALL_TTS_DATA";
208 * Broadcast Action: broadcast to signal the completion of the installation of
209 * the data files used by the synthesis engine. Success or failure is indicated in the
210 * {@link #EXTRA_TTS_DATA_INSTALLED} extra.
212 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
213 public static final String ACTION_TTS_DATA_INSTALLED =
214 "android.speech.tts.engine.TTS_DATA_INSTALLED";
216 * Activity Action: Starts the activity from the platform TextToSpeech
217 * engine to verify the proper installation and availability of the
218 * resource files on the system. Upon completion, the activity will
219 * return one of the following codes:
220 * {@link #CHECK_VOICE_DATA_PASS},
221 * {@link #CHECK_VOICE_DATA_FAIL},
222 * {@link #CHECK_VOICE_DATA_BAD_DATA},
223 * {@link #CHECK_VOICE_DATA_MISSING_DATA}, or
224 * {@link #CHECK_VOICE_DATA_MISSING_VOLUME}.
225 * <p> Moreover, the data received in the activity result will contain the following
228 * <li>{@link #EXTRA_VOICE_DATA_ROOT_DIRECTORY} which
229 * indicates the path to the location of the resource files,</li>
230 * <li>{@link #EXTRA_VOICE_DATA_FILES} which contains
231 * the list of all the resource files,</li>
232 * <li>and {@link #EXTRA_VOICE_DATA_FILES_INFO} which
233 * contains, for each resource file, the description of the language covered by
234 * the file in the xxx-YYY format, where xxx is the 3-letter ISO language code,
235 * and YYY is the 3-letter ISO country code.</li>
238 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
239 public static final String ACTION_CHECK_TTS_DATA =
240 "android.speech.tts.engine.CHECK_TTS_DATA";
242 // extras for a TTS engine's check data activity
244 * Extra information received with the {@link #ACTION_CHECK_TTS_DATA} intent where
245 * the TextToSpeech engine specifies the path to its resources.
247 public static final String EXTRA_VOICE_DATA_ROOT_DIRECTORY = "dataRoot";
249 * Extra information received with the {@link #ACTION_CHECK_TTS_DATA} intent where
250 * the TextToSpeech engine specifies the file names of its resources under the
253 public static final String EXTRA_VOICE_DATA_FILES = "dataFiles";
255 * Extra information received with the {@link #ACTION_CHECK_TTS_DATA} intent where
256 * the TextToSpeech engine specifies the locale associated with each resource file.
258 public static final String EXTRA_VOICE_DATA_FILES_INFO = "dataFilesInfo";
260 * Extra information received with the {@link #ACTION_CHECK_TTS_DATA} intent where
261 * the TextToSpeech engine returns an ArrayList<String> of all the available voices.
262 * The format of each voice is: lang-COUNTRY-variant where COUNTRY and variant are
263 * optional (ie, "eng" or "eng-USA" or "eng-USA-FEMALE").
265 public static final String EXTRA_AVAILABLE_VOICES = "availableVoices";
267 * Extra information received with the {@link #ACTION_CHECK_TTS_DATA} intent where
268 * the TextToSpeech engine returns an ArrayList<String> of all the unavailable voices.
269 * The format of each voice is: lang-COUNTRY-variant where COUNTRY and variant are
270 * optional (ie, "eng" or "eng-USA" or "eng-USA-FEMALE").
272 public static final String EXTRA_UNAVAILABLE_VOICES = "unavailableVoices";
274 * Extra information sent with the {@link #ACTION_CHECK_TTS_DATA} intent where the
275 * caller indicates to the TextToSpeech engine which specific sets of voice data to
276 * check for by sending an ArrayList<String> of the voices that are of interest.
277 * The format of each voice is: lang-COUNTRY-variant where COUNTRY and variant are
278 * optional (ie, "eng" or "eng-USA" or "eng-USA-FEMALE").
280 public static final String EXTRA_CHECK_VOICE_DATA_FOR = "checkVoiceDataFor";
282 // extras for a TTS engine's data installation
284 * Extra information received with the {@link #ACTION_TTS_DATA_INSTALLED} intent.
285 * It indicates whether the data files for the synthesis engine were successfully
286 * installed. The installation was initiated with the {@link #ACTION_INSTALL_TTS_DATA}
287 * intent. The possible values for this extra are
288 * {@link TextToSpeech#SUCCESS} and {@link TextToSpeech#ERROR}.
290 public static final String EXTRA_TTS_DATA_INSTALLED = "dataInstalled";
292 // keys for the parameters passed with speak commands. Hidden keys are used internally
293 // to maintain engine state for each TextToSpeech instance.
297 public static final String KEY_PARAM_RATE = "rate";
301 public static final String KEY_PARAM_LANGUAGE = "language";
305 public static final String KEY_PARAM_COUNTRY = "country";
309 public static final String KEY_PARAM_VARIANT = "variant";
313 public static final String KEY_PARAM_ENGINE = "engine";
317 public static final String KEY_PARAM_PITCH = "pitch";
319 * Parameter key to specify the audio stream type to be used when speaking text
320 * or playing back a file.
321 * @see TextToSpeech#speak(String, int, HashMap)
322 * @see TextToSpeech#playEarcon(String, int, HashMap)
324 public static final String KEY_PARAM_STREAM = "streamType";
326 * Parameter key to identify an utterance in the
327 * {@link TextToSpeech.OnUtteranceCompletedListener} after text has been
328 * spoken, a file has been played back or a silence duration has elapsed.
329 * @see TextToSpeech#speak(String, int, HashMap)
330 * @see TextToSpeech#playEarcon(String, int, HashMap)
331 * @see TextToSpeech#synthesizeToFile(String, HashMap, String)
333 public static final String KEY_PARAM_UTTERANCE_ID = "utteranceId";
335 // key positions in the array of cached parameters
339 protected static final int PARAM_POSITION_RATE = 0;
343 protected static final int PARAM_POSITION_LANGUAGE = 2;
347 protected static final int PARAM_POSITION_COUNTRY = 4;
351 protected static final int PARAM_POSITION_VARIANT = 6;
355 protected static final int PARAM_POSITION_STREAM = 8;
359 protected static final int PARAM_POSITION_UTTERANCE_ID = 10;
364 protected static final int PARAM_POSITION_ENGINE = 12;
369 protected static final int PARAM_POSITION_PITCH = 14;
374 protected static final int NB_CACHED_PARAMS = 8;
378 * Connection needed for the TTS.
380 private ServiceConnection mServiceConnection;
382 private ITts mITts = null;
383 private ITtsCallback mITtscallback = null;
384 private Context mContext = null;
385 private String mPackageName = "";
386 private OnInitListener mInitListener = null;
387 private boolean mStarted = false;
388 private final Object mStartLock = new Object();
390 * Used to store the cached parameters sent along with each synthesis request to the
393 private String[] mCachedParams;
396 * The constructor for the TextToSpeech class.
397 * This will also initialize the associated TextToSpeech engine if it isn't already running.
400 * The context this instance is running in.
402 * The {@link TextToSpeech.OnInitListener} that will be called when the
403 * TextToSpeech engine has initialized.
405 public TextToSpeech(Context context, OnInitListener listener) {
407 mPackageName = mContext.getPackageName();
408 mInitListener = listener;
410 mCachedParams = new String[2*Engine.NB_CACHED_PARAMS]; // store key and value
411 mCachedParams[Engine.PARAM_POSITION_RATE] = Engine.KEY_PARAM_RATE;
412 mCachedParams[Engine.PARAM_POSITION_LANGUAGE] = Engine.KEY_PARAM_LANGUAGE;
413 mCachedParams[Engine.PARAM_POSITION_COUNTRY] = Engine.KEY_PARAM_COUNTRY;
414 mCachedParams[Engine.PARAM_POSITION_VARIANT] = Engine.KEY_PARAM_VARIANT;
415 mCachedParams[Engine.PARAM_POSITION_STREAM] = Engine.KEY_PARAM_STREAM;
416 mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID] = Engine.KEY_PARAM_UTTERANCE_ID;
417 mCachedParams[Engine.PARAM_POSITION_ENGINE] = Engine.KEY_PARAM_ENGINE;
418 mCachedParams[Engine.PARAM_POSITION_PITCH] = Engine.KEY_PARAM_PITCH;
420 // Leave all defaults that are shown in Settings uninitialized/at the default
421 // so that the values set in Settings will take effect if the application does
422 // not try to change these settings itself.
423 mCachedParams[Engine.PARAM_POSITION_RATE + 1] = "";
424 mCachedParams[Engine.PARAM_POSITION_LANGUAGE + 1] = "";
425 mCachedParams[Engine.PARAM_POSITION_COUNTRY + 1] = "";
426 mCachedParams[Engine.PARAM_POSITION_VARIANT + 1] = "";
427 mCachedParams[Engine.PARAM_POSITION_STREAM + 1] =
428 String.valueOf(Engine.DEFAULT_STREAM);
429 mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID + 1] = "";
430 mCachedParams[Engine.PARAM_POSITION_ENGINE + 1] = "";
431 mCachedParams[Engine.PARAM_POSITION_PITCH + 1] = "100";
437 private void initTts() {
440 // Initialize the TTS, run the callback after the binding is successful
441 mServiceConnection = new ServiceConnection() {
442 public void onServiceConnected(ComponentName name, IBinder service) {
443 synchronized(mStartLock) {
444 mITts = ITts.Stub.asInterface(service);
446 // Cache the default engine and current language
447 setEngineByPackageName(getDefaultEngine());
448 setLanguage(getLanguage());
449 if (mInitListener != null) {
450 // TODO manage failures and missing resources
451 mInitListener.onInit(SUCCESS);
456 public void onServiceDisconnected(ComponentName name) {
457 synchronized(mStartLock) {
459 mInitListener = null;
465 Intent intent = new Intent("android.intent.action.START_TTS_SERVICE");
466 intent.addCategory("android.intent.category.TTS");
467 boolean bound = mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
469 Log.e("TextToSpeech.java", "initTts() failed to bind to service");
470 if (mInitListener != null) {
471 mInitListener.onInit(ERROR);
474 // initialization listener will be called inside ServiceConnection
475 Log.i("TextToSpeech.java", "initTts() successfully bound to service");
477 // TODO handle plugin failures
482 * Releases the resources used by the TextToSpeech engine.
483 * It is good practice for instance to call this method in the onDestroy() method of an Activity
484 * so the TextToSpeech engine can be cleanly stopped.
486 public void shutdown() {
488 mContext.unbindService(mServiceConnection);
489 } catch (IllegalArgumentException e) {
490 // Do nothing and fail silently since an error here indicates that
491 // binding never succeeded in the first place.
497 * Adds a mapping between a string of text and a sound resource in a
498 * package. After a call to this method, subsequent calls to
499 * {@link #speak(String, int, HashMap)} will play the specified sound resource
500 * if it is available, or synthesize the text it is missing.
503 * The string of text. Example: <code>"south_south_east"</code>
506 * Pass the packagename of the application that contains the
507 * resource. If the resource is in your own application (this is
508 * the most common case), then put the packagename of your
509 * application here.<br/>
510 * Example: <b>"com.google.marvin.compass"</b><br/>
511 * The packagename can be found in the AndroidManifest.xml of
514 * <code><manifest xmlns:android="..."
515 * package="<b>com.google.marvin.compass</b>"></code>
519 * Example: <code>R.raw.south_south_east</code>
521 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
523 public int addSpeech(String text, String packagename, int resourceId) {
524 synchronized(mStartLock) {
529 mITts.addSpeech(mPackageName, text, packagename, resourceId);
531 } catch (RemoteException e) {
532 // TTS died; restart it.
533 Log.e("TextToSpeech.java - addSpeech", "RemoteException");
537 } catch (NullPointerException e) {
538 // TTS died; restart it.
539 Log.e("TextToSpeech.java - addSpeech", "NullPointerException");
543 } catch (IllegalStateException e) {
544 // TTS died; restart it.
545 Log.e("TextToSpeech.java - addSpeech", "IllegalStateException");
556 * Adds a mapping between a string of text and a sound file. Using this, it
557 * is possible to add custom pronounciations for a string of text.
558 * After a call to this method, subsequent calls to {@link #speak(String, int, HashMap)}
559 * will play the specified sound resource if it is available, or synthesize the text it is
563 * The string of text. Example: <code>"south_south_east"</code>
565 * The full path to the sound file (for example:
566 * "/sdcard/mysounds/hello.wav")
568 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
570 public int addSpeech(String text, String filename) {
571 synchronized (mStartLock) {
576 mITts.addSpeechFile(mPackageName, text, filename);
578 } catch (RemoteException e) {
579 // TTS died; restart it.
580 Log.e("TextToSpeech.java - addSpeech", "RemoteException");
584 } catch (NullPointerException e) {
585 // TTS died; restart it.
586 Log.e("TextToSpeech.java - addSpeech", "NullPointerException");
590 } catch (IllegalStateException e) {
591 // TTS died; restart it.
592 Log.e("TextToSpeech.java - addSpeech", "IllegalStateException");
603 * Adds a mapping between a string of text and a sound resource in a
604 * package. Use this to add custom earcons.
606 * @see #playEarcon(String, int, HashMap)
608 * @param earcon The name of the earcon.
609 * Example: <code>"[tick]"</code><br/>
612 * the package name of the application that contains the
613 * resource. This can for instance be the package name of your own application.
614 * Example: <b>"com.google.marvin.compass"</b><br/>
615 * The package name can be found in the AndroidManifest.xml of
616 * the application containing the resource.
618 * <code><manifest xmlns:android="..."
619 * package="<b>com.google.marvin.compass</b>"></code>
623 * Example: <code>R.raw.tick_snd</code>
625 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
627 public int addEarcon(String earcon, String packagename, int resourceId) {
628 synchronized(mStartLock) {
633 mITts.addEarcon(mPackageName, earcon, packagename, resourceId);
635 } catch (RemoteException e) {
636 // TTS died; restart it.
637 Log.e("TextToSpeech.java - addEarcon", "RemoteException");
641 } catch (NullPointerException e) {
642 // TTS died; restart it.
643 Log.e("TextToSpeech.java - addEarcon", "NullPointerException");
647 } catch (IllegalStateException e) {
648 // TTS died; restart it.
649 Log.e("TextToSpeech.java - addEarcon", "IllegalStateException");
660 * Adds a mapping between a string of text and a sound file.
661 * Use this to add custom earcons.
663 * @see #playEarcon(String, int, HashMap)
666 * The name of the earcon.
667 * Example: <code>"[tick]"</code>
669 * The full path to the sound file (for example:
670 * "/sdcard/mysounds/tick.wav")
672 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
674 public int addEarcon(String earcon, String filename) {
675 synchronized (mStartLock) {
680 mITts.addEarconFile(mPackageName, earcon, filename);
682 } catch (RemoteException e) {
683 // TTS died; restart it.
684 Log.e("TextToSpeech.java - addEarcon", "RemoteException");
688 } catch (NullPointerException e) {
689 // TTS died; restart it.
690 Log.e("TextToSpeech.java - addEarcon", "NullPointerException");
694 } catch (IllegalStateException e) {
695 // TTS died; restart it.
696 Log.e("TextToSpeech.java - addEarcon", "IllegalStateException");
707 * Speaks the string using the specified queuing strategy and speech
711 * The string of text to be spoken.
713 * The queuing strategy to use.
714 * {@link #QUEUE_ADD} or {@link #QUEUE_FLUSH}.
716 * The list of parameters to be used. Can be null if no parameters are given.
717 * They are specified using a (key, value) pair, where the key can be
718 * {@link Engine#KEY_PARAM_STREAM} or
719 * {@link Engine#KEY_PARAM_UTTERANCE_ID}.
721 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
723 public int speak(String text, int queueMode, HashMap<String,String> params)
725 synchronized (mStartLock) {
727 Log.i("TextToSpeech.java - speak", "speak text of length " + text.length());
729 Log.e("TextToSpeech.java - speak", "service isn't started");
733 if ((params != null) && (!params.isEmpty())) {
734 String extra = params.get(Engine.KEY_PARAM_STREAM);
736 mCachedParams[Engine.PARAM_POSITION_STREAM + 1] = extra;
738 extra = params.get(Engine.KEY_PARAM_UTTERANCE_ID);
740 mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID + 1] = extra;
742 extra = params.get(Engine.KEY_PARAM_ENGINE);
744 mCachedParams[Engine.PARAM_POSITION_ENGINE + 1] = extra;
747 result = mITts.speak(mPackageName, text, queueMode, mCachedParams);
748 } catch (RemoteException e) {
749 // TTS died; restart it.
750 Log.e("TextToSpeech.java - speak", "RemoteException");
754 } catch (NullPointerException e) {
755 // TTS died; restart it.
756 Log.e("TextToSpeech.java - speak", "NullPointerException");
760 } catch (IllegalStateException e) {
761 // TTS died; restart it.
762 Log.e("TextToSpeech.java - speak", "IllegalStateException");
775 * Plays the earcon using the specified queueing mode and parameters.
778 * The earcon that should be played
780 * {@link #QUEUE_ADD} or {@link #QUEUE_FLUSH}.
782 * The list of parameters to be used. Can be null if no parameters are given.
783 * They are specified using a (key, value) pair, where the key can be
784 * {@link Engine#KEY_PARAM_STREAM} or
785 * {@link Engine#KEY_PARAM_UTTERANCE_ID}.
787 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
789 public int playEarcon(String earcon, int queueMode,
790 HashMap<String,String> params) {
791 synchronized (mStartLock) {
797 if ((params != null) && (!params.isEmpty())) {
798 String extra = params.get(Engine.KEY_PARAM_STREAM);
800 mCachedParams[Engine.PARAM_POSITION_STREAM + 1] = extra;
802 extra = params.get(Engine.KEY_PARAM_UTTERANCE_ID);
804 mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID + 1] = extra;
807 result = mITts.playEarcon(mPackageName, earcon, queueMode, null);
808 } catch (RemoteException e) {
809 // TTS died; restart it.
810 Log.e("TextToSpeech.java - playEarcon", "RemoteException");
814 } catch (NullPointerException e) {
815 // TTS died; restart it.
816 Log.e("TextToSpeech.java - playEarcon", "NullPointerException");
820 } catch (IllegalStateException e) {
821 // TTS died; restart it.
822 Log.e("TextToSpeech.java - playEarcon", "IllegalStateException");
834 * Plays silence for the specified amount of time using the specified
837 * @param durationInMs
838 * A long that indicates how long the silence should last.
840 * {@link #QUEUE_ADD} or {@link #QUEUE_FLUSH}.
842 * The list of parameters to be used. Can be null if no parameters are given.
843 * They are specified using a (key, value) pair, where the key can be
844 * {@link Engine#KEY_PARAM_UTTERANCE_ID}.
846 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
848 public int playSilence(long durationInMs, int queueMode, HashMap<String,String> params) {
849 synchronized (mStartLock) {
855 if ((params != null) && (!params.isEmpty())) {
856 String extra = params.get(Engine.KEY_PARAM_UTTERANCE_ID);
858 mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID + 1] = extra;
861 result = mITts.playSilence(mPackageName, durationInMs, queueMode, mCachedParams);
862 } catch (RemoteException e) {
863 // TTS died; restart it.
864 Log.e("TextToSpeech.java - playSilence", "RemoteException");
868 } catch (NullPointerException e) {
869 // TTS died; restart it.
870 Log.e("TextToSpeech.java - playSilence", "NullPointerException");
874 } catch (IllegalStateException e) {
875 // TTS died; restart it.
876 Log.e("TextToSpeech.java - playSilence", "IllegalStateException");
888 * Returns whether or not the TextToSpeech engine is busy speaking.
890 * @return Whether or not the TextToSpeech engine is busy speaking.
892 public boolean isSpeaking() {
893 synchronized (mStartLock) {
898 return mITts.isSpeaking();
899 } catch (RemoteException e) {
900 // TTS died; restart it.
901 Log.e("TextToSpeech.java - isSpeaking", "RemoteException");
905 } catch (NullPointerException e) {
906 // TTS died; restart it.
907 Log.e("TextToSpeech.java - isSpeaking", "NullPointerException");
911 } catch (IllegalStateException e) {
912 // TTS died; restart it.
913 Log.e("TextToSpeech.java - isSpeaking", "IllegalStateException");
924 * Interrupts the current utterance (whether played or rendered to file) and discards other
925 * utterances in the queue.
927 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
930 synchronized (mStartLock) {
936 result = mITts.stop(mPackageName);
937 } catch (RemoteException e) {
938 // TTS died; restart it.
939 Log.e("TextToSpeech.java - stop", "RemoteException");
943 } catch (NullPointerException e) {
944 // TTS died; restart it.
945 Log.e("TextToSpeech.java - stop", "NullPointerException");
949 } catch (IllegalStateException e) {
950 // TTS died; restart it.
951 Log.e("TextToSpeech.java - stop", "IllegalStateException");
963 * Sets the speech rate for the TextToSpeech engine.
965 * This has no effect on any pre-recorded speech.
968 * The speech rate for the TextToSpeech engine. 1 is the normal speed,
969 * lower values slow down the speech (0.5 is half the normal speech rate),
970 * greater values accelerate it (2 is twice the normal speech rate).
972 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
974 public int setSpeechRate(float speechRate) {
975 synchronized (mStartLock) {
981 if (speechRate > 0) {
982 int rate = (int)(speechRate*100);
983 mCachedParams[Engine.PARAM_POSITION_RATE + 1] = String.valueOf(rate);
984 // the rate is not set here, instead it is cached so it will be associated
985 // with all upcoming utterances.
986 if (speechRate > 0.0f) {
992 } catch (NullPointerException e) {
993 // TTS died; restart it.
994 Log.e("TextToSpeech.java - setSpeechRate", "NullPointerException");
998 } catch (IllegalStateException e) {
999 // TTS died; restart it.
1000 Log.e("TextToSpeech.java - setSpeechRate", "IllegalStateException");
1001 e.printStackTrace();
1012 * Sets the speech pitch for the TextToSpeech engine.
1014 * This has no effect on any pre-recorded speech.
1017 * The pitch for the TextToSpeech engine. 1 is the normal pitch,
1018 * lower values lower the tone of the synthesized voice,
1019 * greater values increase it.
1021 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
1023 public int setPitch(float pitch) {
1024 synchronized (mStartLock) {
1030 // the pitch is not set here, instead it is cached so it will be associated
1031 // with all upcoming utterances.
1033 int p = (int)(pitch*100);
1034 mCachedParams[Engine.PARAM_POSITION_PITCH + 1] = String.valueOf(p);
1037 } catch (NullPointerException e) {
1038 // TTS died; restart it.
1039 Log.e("TextToSpeech.java - setPitch", "NullPointerException");
1040 e.printStackTrace();
1043 } catch (IllegalStateException e) {
1044 // TTS died; restart it.
1045 Log.e("TextToSpeech.java - setPitch", "IllegalStateException");
1046 e.printStackTrace();
1057 * Sets the language for the TextToSpeech engine.
1058 * The TextToSpeech engine will try to use the closest match to the specified
1059 * language as represented by the Locale, but there is no guarantee that the exact same Locale
1060 * will be used. Use {@link #isLanguageAvailable(Locale)} to check the level of support
1061 * before choosing the language to use for the next utterances.
1064 * The locale describing the language to be used.
1066 * @return code indicating the support status for the locale. See {@link #LANG_AVAILABLE},
1067 * {@link #LANG_COUNTRY_AVAILABLE}, {@link #LANG_COUNTRY_VAR_AVAILABLE},
1068 * {@link #LANG_MISSING_DATA} and {@link #LANG_NOT_SUPPORTED}.
1070 public int setLanguage(Locale loc) {
1071 synchronized (mStartLock) {
1072 int result = LANG_NOT_SUPPORTED;
1080 String language = loc.getISO3Language();
1081 String country = loc.getISO3Country();
1082 String variant = loc.getVariant();
1083 // Check if the language, country, variant are available, and cache
1084 // the available parts.
1085 // Note that the language is not actually set here, instead it is cached so it
1086 // will be associated with all upcoming utterances.
1087 result = mITts.isLanguageAvailable(language, country, variant, mCachedParams);
1088 if (result >= LANG_AVAILABLE){
1089 mCachedParams[Engine.PARAM_POSITION_LANGUAGE + 1] = language;
1090 if (result >= LANG_COUNTRY_AVAILABLE){
1091 mCachedParams[Engine.PARAM_POSITION_COUNTRY + 1] = country;
1093 mCachedParams[Engine.PARAM_POSITION_COUNTRY + 1] = "";
1095 if (result >= LANG_COUNTRY_VAR_AVAILABLE){
1096 mCachedParams[Engine.PARAM_POSITION_VARIANT + 1] = variant;
1098 mCachedParams[Engine.PARAM_POSITION_VARIANT + 1] = "";
1101 } catch (RemoteException e) {
1102 // TTS died; restart it.
1103 Log.e("TextToSpeech.java - setLanguage", "RemoteException");
1104 e.printStackTrace();
1107 } catch (NullPointerException e) {
1108 // TTS died; restart it.
1109 Log.e("TextToSpeech.java - setLanguage", "NullPointerException");
1110 e.printStackTrace();
1113 } catch (IllegalStateException e) {
1114 // TTS died; restart it.
1115 Log.e("TextToSpeech.java - setLanguage", "IllegalStateException");
1116 e.printStackTrace();
1127 * Returns a Locale instance describing the language currently being used by the TextToSpeech
1129 * @return language, country (if any) and variant (if any) used by the engine stored in a Locale
1130 * instance, or null is the TextToSpeech engine has failed.
1132 public Locale getLanguage() {
1133 synchronized (mStartLock) {
1138 // Only do a call to the native synth if there is nothing in the cached params
1139 if (mCachedParams[Engine.PARAM_POSITION_LANGUAGE + 1].length() < 1){
1140 String[] locStrings = mITts.getLanguage();
1141 if ((locStrings != null) && (locStrings.length == 3)) {
1142 return new Locale(locStrings[0], locStrings[1], locStrings[2]);
1147 return new Locale(mCachedParams[Engine.PARAM_POSITION_LANGUAGE + 1],
1148 mCachedParams[Engine.PARAM_POSITION_COUNTRY + 1],
1149 mCachedParams[Engine.PARAM_POSITION_VARIANT + 1]);
1151 } catch (RemoteException e) {
1152 // TTS died; restart it.
1153 Log.e("TextToSpeech.java - getLanguage", "RemoteException");
1154 e.printStackTrace();
1157 } catch (NullPointerException e) {
1158 // TTS died; restart it.
1159 Log.e("TextToSpeech.java - getLanguage", "NullPointerException");
1160 e.printStackTrace();
1163 } catch (IllegalStateException e) {
1164 // TTS died; restart it.
1165 Log.e("TextToSpeech.java - getLanguage", "IllegalStateException");
1166 e.printStackTrace();
1175 * Checks if the specified language as represented by the Locale is available and supported.
1178 * The Locale describing the language to be used.
1180 * @return code indicating the support status for the locale. See {@link #LANG_AVAILABLE},
1181 * {@link #LANG_COUNTRY_AVAILABLE}, {@link #LANG_COUNTRY_VAR_AVAILABLE},
1182 * {@link #LANG_MISSING_DATA} and {@link #LANG_NOT_SUPPORTED}.
1184 public int isLanguageAvailable(Locale loc) {
1185 synchronized (mStartLock) {
1186 int result = LANG_NOT_SUPPORTED;
1191 result = mITts.isLanguageAvailable(loc.getISO3Language(),
1192 loc.getISO3Country(), loc.getVariant(), mCachedParams);
1193 } catch (RemoteException e) {
1194 // TTS died; restart it.
1195 Log.e("TextToSpeech.java - isLanguageAvailable", "RemoteException");
1196 e.printStackTrace();
1199 } catch (NullPointerException e) {
1200 // TTS died; restart it.
1201 Log.e("TextToSpeech.java - isLanguageAvailable", "NullPointerException");
1202 e.printStackTrace();
1205 } catch (IllegalStateException e) {
1206 // TTS died; restart it.
1207 Log.e("TextToSpeech.java - isLanguageAvailable", "IllegalStateException");
1208 e.printStackTrace();
1219 * Synthesizes the given text to a file using the specified parameters.
1222 * The String of text that should be synthesized
1224 * The list of parameters to be used. Can be null if no parameters are given.
1225 * They are specified using a (key, value) pair, where the key can be
1226 * {@link Engine#KEY_PARAM_UTTERANCE_ID}.
1228 * The string that gives the full output filename; it should be
1229 * something like "/sdcard/myappsounds/mysound.wav".
1231 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
1233 public int synthesizeToFile(String text, HashMap<String,String> params,
1235 synchronized (mStartLock) {
1237 Log.i("TextToSpeech.java - synthesizeToFile", "synthesizeToFile text of length "
1240 Log.e("TextToSpeech.java - synthesizeToFile", "service isn't started");
1244 if ((params != null) && (!params.isEmpty())) {
1245 // no need to read the stream type here
1246 String extra = params.get(Engine.KEY_PARAM_UTTERANCE_ID);
1247 if (extra != null) {
1248 mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID + 1] = extra;
1250 extra = params.get(Engine.KEY_PARAM_ENGINE);
1251 if (extra != null) {
1252 mCachedParams[Engine.PARAM_POSITION_ENGINE + 1] = extra;
1255 result = mITts.synthesizeToFile(mPackageName, text, mCachedParams, filename) ?
1257 } catch (RemoteException e) {
1258 // TTS died; restart it.
1259 Log.e("TextToSpeech.java - synthesizeToFile", "RemoteException");
1260 e.printStackTrace();
1263 } catch (NullPointerException e) {
1264 // TTS died; restart it.
1265 Log.e("TextToSpeech.java - synthesizeToFile", "NullPointerException");
1266 e.printStackTrace();
1269 } catch (IllegalStateException e) {
1270 // TTS died; restart it.
1271 Log.e("TextToSpeech.java - synthesizeToFile", "IllegalStateException");
1272 e.printStackTrace();
1276 resetCachedParams();
1284 * Convenience method to reset the cached parameters to the current default values
1285 * if they are not persistent between calls to the service.
1287 private void resetCachedParams() {
1288 mCachedParams[Engine.PARAM_POSITION_STREAM + 1] =
1289 String.valueOf(Engine.DEFAULT_STREAM);
1290 mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID+ 1] = "";
1294 * Sets the OnUtteranceCompletedListener that will fire when an utterance completes.
1297 * The OnUtteranceCompletedListener
1299 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
1301 public int setOnUtteranceCompletedListener(
1302 final OnUtteranceCompletedListener listener) {
1303 synchronized (mStartLock) {
1308 mITtscallback = new ITtsCallback.Stub() {
1309 public void utteranceCompleted(String utteranceId) throws RemoteException {
1310 if (listener != null) {
1311 listener.onUtteranceCompleted(utteranceId);
1316 result = mITts.registerCallback(mPackageName, mITtscallback);
1317 } catch (RemoteException e) {
1318 // TTS died; restart it.
1319 Log.e("TextToSpeech.java - registerCallback", "RemoteException");
1320 e.printStackTrace();
1323 } catch (NullPointerException e) {
1324 // TTS died; restart it.
1325 Log.e("TextToSpeech.java - registerCallback", "NullPointerException");
1326 e.printStackTrace();
1329 } catch (IllegalStateException e) {
1330 // TTS died; restart it.
1331 Log.e("TextToSpeech.java - registerCallback", "IllegalStateException");
1332 e.printStackTrace();
1342 * Sets the speech synthesis engine to be used by its packagename.
1344 * @param enginePackageName
1345 * The packagename for the synthesis engine (ie, "com.svox.pico")
1347 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
1349 public int setEngineByPackageName(String enginePackageName) {
1350 synchronized (mStartLock) {
1351 int result = TextToSpeech.ERROR;
1356 result = mITts.setEngineByPackageName(enginePackageName);
1357 if (result == TextToSpeech.SUCCESS){
1358 mCachedParams[Engine.PARAM_POSITION_ENGINE + 1] = enginePackageName;
1360 } catch (RemoteException e) {
1361 // TTS died; restart it.
1362 Log.e("TextToSpeech.java - setEngineByPackageName", "RemoteException");
1363 e.printStackTrace();
1366 } catch (NullPointerException e) {
1367 // TTS died; restart it.
1368 Log.e("TextToSpeech.java - setEngineByPackageName", "NullPointerException");
1369 e.printStackTrace();
1372 } catch (IllegalStateException e) {
1373 // TTS died; restart it.
1374 Log.e("TextToSpeech.java - setEngineByPackageName", "IllegalStateException");
1375 e.printStackTrace();
1386 * Gets the packagename of the default speech synthesis engine.
1388 * @return Packagename of the TTS engine that the user has chosen as their default.
1390 public String getDefaultEngine() {
1391 synchronized (mStartLock) {
1392 String engineName = "";
1397 engineName = mITts.getDefaultEngine();
1398 } catch (RemoteException e) {
1399 // TTS died; restart it.
1400 Log.e("TextToSpeech.java - setEngineByPackageName", "RemoteException");
1401 e.printStackTrace();
1404 } catch (NullPointerException e) {
1405 // TTS died; restart it.
1406 Log.e("TextToSpeech.java - setEngineByPackageName", "NullPointerException");
1407 e.printStackTrace();
1410 } catch (IllegalStateException e) {
1411 // TTS died; restart it.
1412 Log.e("TextToSpeech.java - setEngineByPackageName", "IllegalStateException");
1413 e.printStackTrace();
1424 * Returns whether or not the user is forcing their defaults to override the
1425 * Text-To-Speech settings set by applications.
1427 * @return Whether or not defaults are enforced.
1429 public boolean areDefaultsEnforced() {
1430 synchronized (mStartLock) {
1431 boolean defaultsEnforced = false;
1433 return defaultsEnforced;
1436 defaultsEnforced = mITts.areDefaultsEnforced();
1437 } catch (RemoteException e) {
1438 // TTS died; restart it.
1439 Log.e("TextToSpeech.java - areDefaultsEnforced", "RemoteException");
1440 e.printStackTrace();
1443 } catch (NullPointerException e) {
1444 // TTS died; restart it.
1445 Log.e("TextToSpeech.java - areDefaultsEnforced", "NullPointerException");
1446 e.printStackTrace();
1449 } catch (IllegalStateException e) {
1450 // TTS died; restart it.
1451 Log.e("TextToSpeech.java - areDefaultsEnforced", "IllegalStateException");
1452 e.printStackTrace();
1456 return defaultsEnforced;