1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 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 6 * the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 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 14 * the License. 15 */ 16 17 package android.speech.tts; 18 19 import android.os.Parcel; 20 import android.os.Parcelable; 21 22 import java.util.ArrayList; 23 import java.util.Collections; 24 import java.util.HashSet; 25 import java.util.Locale; 26 import java.util.Set; 27 28 /** 29 * Characteristics and features of a Text-To-Speech Voice. Each TTS Engine can expose 30 * multiple voices for each locale, with different set of features. 31 */ 32 public class Voice implements Parcelable { 33 /** Very low, but still intelligible quality of speech synthesis */ 34 public static final int QUALITY_VERY_LOW = 100; 35 36 /** Low, not human-like quality of speech synthesis */ 37 public static final int QUALITY_LOW = 200; 38 39 /** Normal quality of speech synthesis */ 40 public static final int QUALITY_NORMAL = 300; 41 42 /** High, human-like quality of speech synthesis */ 43 public static final int QUALITY_HIGH = 400; 44 45 /** Very high, almost human-indistinguishable quality of speech synthesis */ 46 public static final int QUALITY_VERY_HIGH = 500; 47 48 /** Very low expected synthesizer latency (< 20ms) */ 49 public static final int LATENCY_VERY_LOW = 100; 50 51 /** Low expected synthesizer latency (~20ms) */ 52 public static final int LATENCY_LOW = 200; 53 54 /** Normal expected synthesizer latency (~50ms) */ 55 public static final int LATENCY_NORMAL = 300; 56 57 /** Network based expected synthesizer latency (~200ms) */ 58 public static final int LATENCY_HIGH = 400; 59 60 /** Very slow network based expected synthesizer latency (> 200ms) */ 61 public static final int LATENCY_VERY_HIGH = 500; 62 63 private final String mName; 64 private final Locale mLocale; 65 private final int mQuality; 66 private final int mLatency; 67 private final boolean mRequiresNetworkConnection; 68 private final Set<String> mFeatures; 69 Voice(String name, Locale locale, int quality, int latency, boolean requiresNetworkConnection, Set<String> features)70 public Voice(String name, 71 Locale locale, 72 int quality, 73 int latency, 74 boolean requiresNetworkConnection, 75 Set<String> features) { 76 this.mName = name; 77 this.mLocale = locale; 78 this.mQuality = quality; 79 this.mLatency = latency; 80 this.mRequiresNetworkConnection = requiresNetworkConnection; 81 this.mFeatures = features; 82 } 83 Voice(Parcel in)84 private Voice(Parcel in) { 85 this.mName = in.readString(); 86 this.mLocale = (Locale)in.readSerializable(); 87 this.mQuality = in.readInt(); 88 this.mLatency = in.readInt(); 89 this.mRequiresNetworkConnection = (in.readByte() == 1); 90 this.mFeatures = new HashSet<String>(); 91 Collections.addAll(this.mFeatures, in.readStringArray()); 92 } 93 94 @Override writeToParcel(Parcel dest, int flags)95 public void writeToParcel(Parcel dest, int flags) { 96 dest.writeString(mName); 97 dest.writeSerializable(mLocale); 98 dest.writeInt(mQuality); 99 dest.writeInt(mLatency); 100 dest.writeByte((byte) (mRequiresNetworkConnection ? 1 : 0)); 101 dest.writeStringList(new ArrayList<String>(mFeatures)); 102 } 103 104 @Override describeContents()105 public int describeContents() { 106 return 0; 107 } 108 109 public static final @android.annotation.NonNull Parcelable.Creator<Voice> CREATOR = new Parcelable.Creator<Voice>() { 110 @Override 111 public Voice createFromParcel(Parcel in) { 112 return new Voice(in); 113 } 114 115 @Override 116 public Voice[] newArray(int size) { 117 return new Voice[size]; 118 } 119 }; 120 121 122 /** 123 * @return The voice's locale 124 */ getLocale()125 public Locale getLocale() { 126 return mLocale; 127 } 128 129 /** 130 * @return The voice's quality (higher is better) 131 * @see #QUALITY_VERY_HIGH 132 * @see #QUALITY_HIGH 133 * @see #QUALITY_NORMAL 134 * @see #QUALITY_LOW 135 * @see #QUALITY_VERY_LOW 136 */ getQuality()137 public int getQuality() { 138 return mQuality; 139 } 140 141 /** 142 * @return The voice's latency (lower is better) 143 * @see #LATENCY_VERY_LOW 144 * @see #LATENCY_LOW 145 * @see #LATENCY_NORMAL 146 * @see #LATENCY_HIGH 147 * @see #LATENCY_VERY_HIGH 148 */ getLatency()149 public int getLatency() { 150 return mLatency; 151 } 152 153 /** 154 * @return Does the Voice require a network connection to work. 155 */ isNetworkConnectionRequired()156 public boolean isNetworkConnectionRequired() { 157 return mRequiresNetworkConnection; 158 } 159 160 /** 161 * @return Unique voice name. 162 */ getName()163 public String getName() { 164 return mName; 165 } 166 167 /** 168 * Returns the set of features it supports for a given voice. 169 * Features can either be framework defined, e.g. 170 * {@link TextToSpeech.Engine#KEY_FEATURE_NETWORK_TIMEOUT_MS} or engine specific. 171 * Engine specific keys must be prefixed by the name of the engine they 172 * are intended for. These keys can be used as parameters to 173 * {@link TextToSpeech#speak(String, int, java.util.HashMap)} and 174 * {@link TextToSpeech#synthesizeToFile(String, java.util.HashMap, String)}. 175 * 176 * Features values are strings and their values must met restrictions described in their 177 * documentation. 178 * 179 * @return Set instance. May return {@code null} on error. 180 */ getFeatures()181 public Set<String> getFeatures() { 182 return mFeatures; 183 } 184 185 @Override toString()186 public String toString() { 187 StringBuilder builder = new StringBuilder(64); 188 return builder.append("Voice[Name: ").append(mName) 189 .append(", locale: ").append(mLocale) 190 .append(", quality: ").append(mQuality) 191 .append(", latency: ").append(mLatency) 192 .append(", requiresNetwork: ").append(mRequiresNetworkConnection) 193 .append(", features: ").append(mFeatures.toString()) 194 .append("]").toString(); 195 } 196 197 @Override hashCode()198 public int hashCode() { 199 final int prime = 31; 200 int result = 1; 201 result = prime * result + ((mFeatures == null) ? 0 : mFeatures.hashCode()); 202 result = prime * result + mLatency; 203 result = prime * result + ((mLocale == null) ? 0 : mLocale.hashCode()); 204 result = prime * result + ((mName == null) ? 0 : mName.hashCode()); 205 result = prime * result + mQuality; 206 result = prime * result + (mRequiresNetworkConnection ? 1231 : 1237); 207 return result; 208 } 209 210 @Override equals(Object obj)211 public boolean equals(Object obj) { 212 if (this == obj) { 213 return true; 214 } 215 if (obj == null) { 216 return false; 217 } 218 if (getClass() != obj.getClass()) { 219 return false; 220 } 221 Voice other = (Voice) obj; 222 if (mFeatures == null) { 223 if (other.mFeatures != null) { 224 return false; 225 } 226 } else if (!mFeatures.equals(other.mFeatures)) { 227 return false; 228 } 229 if (mLatency != other.mLatency) { 230 return false; 231 } 232 if (mLocale == null) { 233 if (other.mLocale != null) { 234 return false; 235 } 236 } else if (!mLocale.equals(other.mLocale)) { 237 return false; 238 } 239 if (mName == null) { 240 if (other.mName != null) { 241 return false; 242 } 243 } else if (!mName.equals(other.mName)) { 244 return false; 245 } 246 if (mQuality != other.mQuality) { 247 return false; 248 } 249 if (mRequiresNetworkConnection != other.mRequiresNetworkConnection) { 250 return false; 251 } 252 return true; 253 } 254 } 255