Przemyslaw Szczepaniak | 90d15d2 | 2013-06-14 12:02:53 +0100 | [diff] [blame] | 1 | package android.speech.tts; |
| 2 | |
| 3 | import android.os.Bundle; |
| 4 | import android.os.Parcel; |
| 5 | import android.os.Parcelable; |
| 6 | |
| 7 | import java.util.Locale; |
| 8 | |
| 9 | /** |
| 10 | * Characteristics and features of a Text-To-Speech Voice. Each TTS Engine can expose |
| 11 | * multiple voices for multiple locales, with different set of features. |
| 12 | * |
Przemyslaw Szczepaniak | 97cd647 | 2013-10-25 12:04:47 +0100 | [diff] [blame] | 13 | * Each VoiceInfo has an unique name. This name can be obtained using the {@link #getName()} method |
| 14 | * and will persist until the client is asked to re-evaluate the list of available voices in the |
Przemyslaw Szczepaniak | 90d15d2 | 2013-06-14 12:02:53 +0100 | [diff] [blame] | 15 | * {@link TextToSpeechClient.ConnectionCallbacks#onEngineStatusChange(android.speech.tts.TextToSpeechClient.EngineStatus)} |
Przemyslaw Szczepaniak | 97cd647 | 2013-10-25 12:04:47 +0100 | [diff] [blame] | 16 | * callback. The name can be used to reference a VoiceInfo in an instance of {@link RequestConfig}; |
| 17 | * the {@link TextToSpeechClient.Params#FALLBACK_VOICE_NAME} voice parameter is an example of this. |
| 18 | * It is recommended that the voice name never change during the TTS service lifetime. |
Przemyslaw Szczepaniak | 90d15d2 | 2013-06-14 12:02:53 +0100 | [diff] [blame] | 19 | */ |
| 20 | public final class VoiceInfo implements Parcelable { |
| 21 | /** Very low, but still intelligible quality of speech synthesis */ |
| 22 | public static final int QUALITY_VERY_LOW = 100; |
| 23 | |
| 24 | /** Low, not human-like quality of speech synthesis */ |
| 25 | public static final int QUALITY_LOW = 200; |
| 26 | |
| 27 | /** Normal quality of speech synthesis */ |
| 28 | public static final int QUALITY_NORMAL = 300; |
| 29 | |
| 30 | /** High, human-like quality of speech synthesis */ |
| 31 | public static final int QUALITY_HIGH = 400; |
| 32 | |
| 33 | /** Very high, almost human-indistinguishable quality of speech synthesis */ |
| 34 | public static final int QUALITY_VERY_HIGH = 500; |
| 35 | |
| 36 | /** Very low expected synthesizer latency (< 20ms) */ |
| 37 | public static final int LATENCY_VERY_LOW = 100; |
| 38 | |
| 39 | /** Low expected synthesizer latency (~20ms) */ |
| 40 | public static final int LATENCY_LOW = 200; |
| 41 | |
| 42 | /** Normal expected synthesizer latency (~50ms) */ |
| 43 | public static final int LATENCY_NORMAL = 300; |
| 44 | |
| 45 | /** Network based expected synthesizer latency (~200ms) */ |
| 46 | public static final int LATENCY_HIGH = 400; |
| 47 | |
| 48 | /** Very slow network based expected synthesizer latency (> 200ms) */ |
| 49 | public static final int LATENCY_VERY_HIGH = 500; |
| 50 | |
| 51 | /** Additional feature key, with string value, gender of the speaker */ |
| 52 | public static final String FEATURE_SPEAKER_GENDER = "speakerGender"; |
| 53 | |
| 54 | /** Additional feature key, with integer value, speaking speed in words per minute |
| 55 | * when {@link TextToSpeechClient.Params#SPEECH_SPEED} parameter is set to {@code 1.0} */ |
| 56 | public static final String FEATURE_WORDS_PER_MINUTE = "wordsPerMinute"; |
| 57 | |
| 58 | /** |
| 59 | * Additional feature key, with boolean value, that indicates that voice may need to |
| 60 | * download additional data if used for synthesis. |
| 61 | * |
| 62 | * Making a request with a voice that has this feature may result in a |
| 63 | * {@link TextToSpeechClient.Status#ERROR_DOWNLOADING_ADDITIONAL_DATA} error. It's recommended |
Przemyslaw Szczepaniak | 97cd647 | 2013-10-25 12:04:47 +0100 | [diff] [blame] | 64 | * to set the {@link TextToSpeechClient.Params#FALLBACK_VOICE_NAME} voice parameter to reference |
Przemyslaw Szczepaniak | 90d15d2 | 2013-06-14 12:02:53 +0100 | [diff] [blame] | 65 | * a fully installed voice (or network voice) that can serve as replacement. |
| 66 | * |
| 67 | * Note: It's a good practice for a TTS engine to provide a sensible fallback voice as the |
Przemyslaw Szczepaniak | 97cd647 | 2013-10-25 12:04:47 +0100 | [diff] [blame] | 68 | * default value for {@link TextToSpeechClient.Params#FALLBACK_VOICE_NAME} parameter if this |
Przemyslaw Szczepaniak | 90d15d2 | 2013-06-14 12:02:53 +0100 | [diff] [blame] | 69 | * feature is present. |
| 70 | */ |
| 71 | public static final String FEATURE_MAY_AUTOINSTALL = "mayAutoInstall"; |
| 72 | |
Przemyslaw Szczepaniak | 97cd647 | 2013-10-25 12:04:47 +0100 | [diff] [blame] | 73 | private final String mName; |
Przemyslaw Szczepaniak | 90d15d2 | 2013-06-14 12:02:53 +0100 | [diff] [blame] | 74 | private final Locale mLocale; |
| 75 | private final int mQuality; |
| 76 | private final int mLatency; |
| 77 | private final boolean mRequiresNetworkConnection; |
| 78 | private final Bundle mParams; |
| 79 | private final Bundle mAdditionalFeatures; |
| 80 | |
| 81 | private VoiceInfo(Parcel in) { |
Przemyslaw Szczepaniak | 97cd647 | 2013-10-25 12:04:47 +0100 | [diff] [blame] | 82 | this.mName = in.readString(); |
Przemyslaw Szczepaniak | 90d15d2 | 2013-06-14 12:02:53 +0100 | [diff] [blame] | 83 | String[] localesData = new String[3]; |
| 84 | in.readStringArray(localesData); |
| 85 | this.mLocale = new Locale(localesData[0], localesData[1], localesData[2]); |
| 86 | |
| 87 | this.mQuality = in.readInt(); |
| 88 | this.mLatency = in.readInt(); |
| 89 | this.mRequiresNetworkConnection = (in.readByte() == 1); |
| 90 | |
| 91 | this.mParams = in.readBundle(); |
| 92 | this.mAdditionalFeatures = in.readBundle(); |
| 93 | } |
| 94 | |
Przemyslaw Szczepaniak | 97cd647 | 2013-10-25 12:04:47 +0100 | [diff] [blame] | 95 | private VoiceInfo(String name, |
Przemyslaw Szczepaniak | 90d15d2 | 2013-06-14 12:02:53 +0100 | [diff] [blame] | 96 | Locale locale, |
| 97 | int quality, |
| 98 | int latency, |
| 99 | boolean requiresNetworkConnection, |
| 100 | Bundle params, |
| 101 | Bundle additionalFeatures) { |
Przemyslaw Szczepaniak | 97cd647 | 2013-10-25 12:04:47 +0100 | [diff] [blame] | 102 | this.mName = name; |
Przemyslaw Szczepaniak | 90d15d2 | 2013-06-14 12:02:53 +0100 | [diff] [blame] | 103 | this.mLocale = locale; |
| 104 | this.mQuality = quality; |
| 105 | this.mLatency = latency; |
| 106 | this.mRequiresNetworkConnection = requiresNetworkConnection; |
| 107 | this.mParams = params; |
| 108 | this.mAdditionalFeatures = additionalFeatures; |
| 109 | } |
| 110 | |
| 111 | /** Builder, allows TTS engines to create VoiceInfo instances. */ |
| 112 | public static final class Builder { |
Przemyslaw Szczepaniak | 97cd647 | 2013-10-25 12:04:47 +0100 | [diff] [blame] | 113 | private String name; |
Przemyslaw Szczepaniak | 90d15d2 | 2013-06-14 12:02:53 +0100 | [diff] [blame] | 114 | private Locale locale; |
| 115 | private int quality = VoiceInfo.QUALITY_NORMAL; |
| 116 | private int latency = VoiceInfo.LATENCY_NORMAL; |
| 117 | private boolean requiresNetworkConnection; |
| 118 | private Bundle params; |
| 119 | private Bundle additionalFeatures; |
| 120 | |
| 121 | public Builder() { |
| 122 | |
| 123 | } |
| 124 | |
| 125 | /** |
| 126 | * Copy fields from given VoiceInfo instance. |
| 127 | */ |
| 128 | public Builder(VoiceInfo voiceInfo) { |
Przemyslaw Szczepaniak | 97cd647 | 2013-10-25 12:04:47 +0100 | [diff] [blame] | 129 | this.name = voiceInfo.mName; |
Przemyslaw Szczepaniak | 90d15d2 | 2013-06-14 12:02:53 +0100 | [diff] [blame] | 130 | this.locale = voiceInfo.mLocale; |
| 131 | this.quality = voiceInfo.mQuality; |
| 132 | this.latency = voiceInfo.mLatency; |
| 133 | this.requiresNetworkConnection = voiceInfo.mRequiresNetworkConnection; |
| 134 | this.params = (Bundle)voiceInfo.mParams.clone(); |
| 135 | this.additionalFeatures = (Bundle) voiceInfo.mAdditionalFeatures.clone(); |
| 136 | } |
| 137 | |
| 138 | /** |
Przemyslaw Szczepaniak | 97cd647 | 2013-10-25 12:04:47 +0100 | [diff] [blame] | 139 | * Sets the voice's unique name. It will be used by clients to reference the voice used by a |
Przemyslaw Szczepaniak | 90d15d2 | 2013-06-14 12:02:53 +0100 | [diff] [blame] | 140 | * request. |
Przemyslaw Szczepaniak | 97cd647 | 2013-10-25 12:04:47 +0100 | [diff] [blame] | 141 | * |
| 142 | * It's recommended that each voice use the same consistent name during the TTS service |
| 143 | * lifetime. |
Przemyslaw Szczepaniak | 90d15d2 | 2013-06-14 12:02:53 +0100 | [diff] [blame] | 144 | */ |
Przemyslaw Szczepaniak | 97cd647 | 2013-10-25 12:04:47 +0100 | [diff] [blame] | 145 | public Builder setName(String name) { |
| 146 | this.name = name; |
Przemyslaw Szczepaniak | 90d15d2 | 2013-06-14 12:02:53 +0100 | [diff] [blame] | 147 | return this; |
| 148 | } |
| 149 | |
| 150 | /** |
| 151 | * Sets voice locale. This has to be a valid locale, built from ISO 639-1 and ISO 3166-1 |
| 152 | * two letter codes. |
| 153 | */ |
| 154 | public Builder setLocale(Locale locale) { |
| 155 | this.locale = locale; |
| 156 | return this; |
| 157 | } |
| 158 | |
| 159 | /** |
| 160 | * Sets map of all available request parameters with their default values. |
| 161 | * Some common parameter names can be found in {@link TextToSpeechClient.Params} static |
| 162 | * members. |
| 163 | */ |
| 164 | public Builder setParamsWithDefaults(Bundle params) { |
| 165 | this.params = params; |
| 166 | return this; |
| 167 | } |
| 168 | |
| 169 | /** |
| 170 | * Sets map of additional voice features. Some common feature names can be found in |
| 171 | * {@link VoiceInfo} static members. |
| 172 | */ |
| 173 | public Builder setAdditionalFeatures(Bundle additionalFeatures) { |
| 174 | this.additionalFeatures = additionalFeatures; |
| 175 | return this; |
| 176 | } |
| 177 | |
| 178 | /** |
| 179 | * Sets the voice quality (higher is better). |
| 180 | */ |
| 181 | public Builder setQuality(int quality) { |
| 182 | this.quality = quality; |
| 183 | return this; |
| 184 | } |
| 185 | |
| 186 | /** |
| 187 | * Sets the voice latency (lower is better). |
| 188 | */ |
| 189 | public Builder setLatency(int latency) { |
| 190 | this.latency = latency; |
| 191 | return this; |
| 192 | } |
| 193 | |
| 194 | /** |
| 195 | * Sets whether the voice requires network connection to work properly. |
| 196 | */ |
| 197 | public Builder setRequiresNetworkConnection(boolean requiresNetworkConnection) { |
| 198 | this.requiresNetworkConnection = requiresNetworkConnection; |
| 199 | return this; |
| 200 | } |
| 201 | |
| 202 | /** |
Przemyslaw Szczepaniak | 97cd647 | 2013-10-25 12:04:47 +0100 | [diff] [blame] | 203 | * @return The built VoiceInfo instance. |
Przemyslaw Szczepaniak | 90d15d2 | 2013-06-14 12:02:53 +0100 | [diff] [blame] | 204 | */ |
| 205 | public VoiceInfo build() { |
Przemyslaw Szczepaniak | 97cd647 | 2013-10-25 12:04:47 +0100 | [diff] [blame] | 206 | if (name == null || name.isEmpty()) { |
| 207 | throw new IllegalStateException("Name can't be null or empty"); |
| 208 | } |
Przemyslaw Szczepaniak | 90d15d2 | 2013-06-14 12:02:53 +0100 | [diff] [blame] | 209 | if (locale == null) { |
| 210 | throw new IllegalStateException("Locale can't be null"); |
| 211 | } |
| 212 | |
Przemyslaw Szczepaniak | 97cd647 | 2013-10-25 12:04:47 +0100 | [diff] [blame] | 213 | return new VoiceInfo(name, locale, quality, latency, |
Przemyslaw Szczepaniak | 90d15d2 | 2013-06-14 12:02:53 +0100 | [diff] [blame] | 214 | requiresNetworkConnection, |
| 215 | ((params == null) ? new Bundle() : |
| 216 | (Bundle)params.clone()), |
| 217 | ((additionalFeatures == null) ? new Bundle() : |
| 218 | (Bundle)additionalFeatures.clone())); |
| 219 | } |
| 220 | } |
| 221 | |
| 222 | /** |
| 223 | * @hide |
| 224 | */ |
| 225 | @Override |
| 226 | public int describeContents() { |
| 227 | return 0; |
| 228 | } |
| 229 | |
| 230 | /** |
| 231 | * @hide |
| 232 | */ |
| 233 | @Override |
| 234 | public void writeToParcel(Parcel dest, int flags) { |
Przemyslaw Szczepaniak | 97cd647 | 2013-10-25 12:04:47 +0100 | [diff] [blame] | 235 | dest.writeString(mName); |
Przemyslaw Szczepaniak | 90d15d2 | 2013-06-14 12:02:53 +0100 | [diff] [blame] | 236 | String[] localesData = new String[]{mLocale.getLanguage(), mLocale.getCountry(), mLocale.getVariant()}; |
| 237 | dest.writeStringArray(localesData); |
| 238 | dest.writeInt(mQuality); |
| 239 | dest.writeInt(mLatency); |
| 240 | dest.writeByte((byte) (mRequiresNetworkConnection ? 1 : 0)); |
| 241 | dest.writeBundle(mParams); |
| 242 | dest.writeBundle(mAdditionalFeatures); |
| 243 | } |
| 244 | |
| 245 | /** |
| 246 | * @hide |
| 247 | */ |
| 248 | public static final Parcelable.Creator<VoiceInfo> CREATOR = new Parcelable.Creator<VoiceInfo>() { |
| 249 | @Override |
| 250 | public VoiceInfo createFromParcel(Parcel in) { |
| 251 | return new VoiceInfo(in); |
| 252 | } |
| 253 | |
| 254 | @Override |
| 255 | public VoiceInfo[] newArray(int size) { |
| 256 | return new VoiceInfo[size]; |
| 257 | } |
| 258 | }; |
| 259 | |
| 260 | /** |
| 261 | * @return The voice's locale |
| 262 | */ |
| 263 | public Locale getLocale() { |
| 264 | return mLocale; |
| 265 | } |
| 266 | |
| 267 | /** |
| 268 | * @return The voice's quality (higher is better) |
| 269 | */ |
| 270 | public int getQuality() { |
| 271 | return mQuality; |
| 272 | } |
| 273 | |
| 274 | /** |
| 275 | * @return The voice's latency (lower is better) |
| 276 | */ |
| 277 | public int getLatency() { |
| 278 | return mLatency; |
| 279 | } |
| 280 | |
| 281 | /** |
| 282 | * @return Does the Voice require a network connection to work. |
| 283 | */ |
| 284 | public boolean getRequiresNetworkConnection() { |
| 285 | return mRequiresNetworkConnection; |
| 286 | } |
| 287 | |
| 288 | /** |
| 289 | * @return Bundle of all available parameters with their default values. |
| 290 | */ |
| 291 | public Bundle getParamsWithDefaults() { |
| 292 | return mParams; |
| 293 | } |
| 294 | |
| 295 | /** |
Przemyslaw Szczepaniak | 97cd647 | 2013-10-25 12:04:47 +0100 | [diff] [blame] | 296 | * @return Unique voice name. |
Przemyslaw Szczepaniak | 90d15d2 | 2013-06-14 12:02:53 +0100 | [diff] [blame] | 297 | * |
Przemyslaw Szczepaniak | 97cd647 | 2013-10-25 12:04:47 +0100 | [diff] [blame] | 298 | * Each VoiceInfo has an unique name, that persists until client is asked to re-evaluate the |
Przemyslaw Szczepaniak | 90d15d2 | 2013-06-14 12:02:53 +0100 | [diff] [blame] | 299 | * set of the available languages in the {@link TextToSpeechClient.ConnectionCallbacks#onEngineStatusChange(android.speech.tts.TextToSpeechClient.EngineStatus)} |
Przemyslaw Szczepaniak | 97cd647 | 2013-10-25 12:04:47 +0100 | [diff] [blame] | 300 | * callback (Voice may disappear from the set if voice was removed by the user). |
Przemyslaw Szczepaniak | 90d15d2 | 2013-06-14 12:02:53 +0100 | [diff] [blame] | 301 | */ |
Przemyslaw Szczepaniak | 97cd647 | 2013-10-25 12:04:47 +0100 | [diff] [blame] | 302 | public String getName() { |
| 303 | return mName; |
Przemyslaw Szczepaniak | 90d15d2 | 2013-06-14 12:02:53 +0100 | [diff] [blame] | 304 | } |
| 305 | |
| 306 | /** |
| 307 | * @return Additional features of the voice. |
| 308 | */ |
| 309 | public Bundle getAdditionalFeatures() { |
| 310 | return mAdditionalFeatures; |
| 311 | } |
| 312 | |
| 313 | @Override |
| 314 | public String toString() { |
| 315 | StringBuilder builder = new StringBuilder(64); |
Przemyslaw Szczepaniak | 97cd647 | 2013-10-25 12:04:47 +0100 | [diff] [blame] | 316 | return builder.append("VoiceInfo[Name: ").append(mName) |
Przemyslaw Szczepaniak | 90d15d2 | 2013-06-14 12:02:53 +0100 | [diff] [blame] | 317 | .append(" ,locale: ").append(mLocale) |
| 318 | .append(" ,quality: ").append(mQuality) |
| 319 | .append(" ,latency: ").append(mLatency) |
| 320 | .append(" ,requiresNetwork: ").append(mRequiresNetworkConnection) |
| 321 | .append(" ,paramsWithDefaults: ").append(mParams.toString()) |
| 322 | .append(" ,additionalFeatures: ").append(mAdditionalFeatures.toString()) |
| 323 | .append("]").toString(); |
| 324 | } |
| 325 | } |