summaryrefslogtreecommitdiffstats
path: root/core/java/android/speech
diff options
context:
space:
mode:
authorNiels Egberts <nielse@google.com>2014-07-10 11:45:23 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2014-07-09 19:47:58 +0000
commit931a0e27e114aee8e8297f4d6499d4e1891f0591 (patch)
treee687e2c27790c55281ca73cef51cd7c0d1fb751f /core/java/android/speech
parenteeba0257a7d9bd10bf0d97d38828d52c035d2628 (diff)
parent34d4ac88f70c37cbe143ab01b40f343bcf02035f (diff)
downloadframeworks_base-931a0e27e114aee8e8297f4d6499d4e1891f0591.zip
frameworks_base-931a0e27e114aee8e8297f4d6499d4e1891f0591.tar.gz
frameworks_base-931a0e27e114aee8e8297f4d6499d4e1891f0591.tar.bz2
Merge "Remove Markup and Utterance classes."
Diffstat (limited to 'core/java/android/speech')
-rw-r--r--core/java/android/speech/tts/Markup.java537
-rw-r--r--core/java/android/speech/tts/Utterance.java595
2 files changed, 0 insertions, 1132 deletions
diff --git a/core/java/android/speech/tts/Markup.java b/core/java/android/speech/tts/Markup.java
deleted file mode 100644
index c886e5d..0000000
--- a/core/java/android/speech/tts/Markup.java
+++ /dev/null
@@ -1,537 +0,0 @@
-package android.speech.tts;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.SortedMap;
-import java.util.TreeMap;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * A class that provides markup to a synthesis request to control aspects of speech.
- * <p>
- * Markup itself is a feature agnostic data format; the {@link Utterance} class defines the currently
- * available set of features and should be used to construct instances of the Markup class.
- * </p>
- * <p>
- * A marked up sentence is a tree. Each node has a type, an optional plain text, a set of
- * parameters, and a list of children.
- * The <b>type</b> defines what it contains, e.g. "text", "date", "measure", etc. A Markup node
- * can be either a part of sentence (often a leaf node), or node altering some property of its
- * children (node with children). The top level node has to be of type "utterance" and its children
- * are synthesized in order.
- * The <b>plain text</b> is optional except for the top level node. If the synthesis engine does not
- * support Markup at all, it should use the plain text of the top level node. If an engine does not
- * recognize or support a node type, it will try to use the plain text of that node if provided. If
- * the plain text is null, it will synthesize its children in order.
- * <b>Parameters</b> are key-value pairs specific to each node type. In case of a date node the
- * parameters may be for example "month: 7" and "day: 10".
- * The <b>nested markups</b> are children and can for example be used to nest semiotic classes (a
- * measure may have a node of type "decimal" as its child) or to modify some property of its
- * children. See "plain text" on how they are processed if the parent of the children is unknown to
- * the engine.
- * <p>
- */
-public final class Markup implements Parcelable {
-
- private String mType;
- private String mPlainText;
-
- private Bundle mParameters = new Bundle();
- private List<Markup> mNestedMarkups = new ArrayList<Markup>();
-
- private static final String TYPE = "type";
- private static final String PLAIN_TEXT = "plain_text";
- private static final String MARKUP = "markup";
-
- private static final String IDENTIFIER_REGEX = "([0-9a-z_]+)";
- private static final Pattern legalIdentifierPattern = Pattern.compile(IDENTIFIER_REGEX);
-
- /**
- * Constructs an empty markup.
- */
- public Markup() {}
-
- /**
- * Constructs a markup of the given type.
- */
- public Markup(String type) {
- setType(type);
- }
-
- /**
- * Returns the type of this node; can be null.
- */
- public String getType() {
- return mType;
- }
-
- /**
- * Sets the type of this node. can be null. May only contain [0-9a-z_].
- */
- public void setType(String type) {
- if (type != null) {
- Matcher matcher = legalIdentifierPattern.matcher(type);
- if (!matcher.matches()) {
- throw new IllegalArgumentException("Type cannot be empty and may only contain " +
- "0-9, a-z and underscores.");
- }
- }
- mType = type;
- }
-
- /**
- * Returns this node's plain text; can be null.
- */
- public String getPlainText() {
- return mPlainText;
- }
-
- /**
- * Sets this nodes's plain text; can be null.
- */
- public void setPlainText(String plainText) {
- mPlainText = plainText;
- }
-
- /**
- * Adds or modifies a parameter.
- * @param key The key; may only contain [0-9a-z_] and cannot be "type" or "plain_text".
- * @param value The value.
- * @throws An {@link IllegalArgumentException} if the key is null or empty.
- * @return this
- */
- public Markup setParameter(String key, String value) {
- if (key == null || key.isEmpty()) {
- throw new IllegalArgumentException("Key cannot be null or empty.");
- }
- if (key.equals("type")) {
- throw new IllegalArgumentException("Key cannot be \"type\".");
- }
- if (key.equals("plain_text")) {
- throw new IllegalArgumentException("Key cannot be \"plain_text\".");
- }
- Matcher matcher = legalIdentifierPattern.matcher(key);
- if (!matcher.matches()) {
- throw new IllegalArgumentException("Key may only contain 0-9, a-z and underscores.");
- }
-
- if (value != null) {
- mParameters.putString(key, value);
- } else {
- removeParameter(key);
- }
- return this;
- }
-
- /**
- * Removes the parameter with the given key
- */
- public void removeParameter(String key) {
- mParameters.remove(key);
- }
-
- /**
- * Returns the value of the parameter.
- * @param key The parameter key.
- * @return The value of the parameter or null if the parameter is not set.
- */
- public String getParameter(String key) {
- return mParameters.getString(key);
- }
-
- /**
- * Returns the number of parameters that have been set.
- */
- public int parametersSize() {
- return mParameters.size();
- }
-
- /**
- * Appends a child to the list of children
- * @param markup The child.
- * @return This instance.
- * @throws {@link IllegalArgumentException} if markup is null.
- */
- public Markup addNestedMarkup(Markup markup) {
- if (markup == null) {
- throw new IllegalArgumentException("Nested markup cannot be null");
- }
- mNestedMarkups.add(markup);
- return this;
- }
-
- /**
- * Removes the given node from its children.
- * @param markup The child to remove.
- * @return True if this instance was modified by this operation, false otherwise.
- */
- public boolean removeNestedMarkup(Markup markup) {
- return mNestedMarkups.remove(markup);
- }
-
- /**
- * Returns the index'th child.
- * @param i The index of the child.
- * @return The child.
- * @throws {@link IndexOutOfBoundsException} if i < 0 or i >= nestedMarkupSize()
- */
- public Markup getNestedMarkup(int i) {
- return mNestedMarkups.get(i);
- }
-
-
- /**
- * Returns the number of children.
- */
- public int nestedMarkupSize() {
- return mNestedMarkups.size();
- }
-
- /**
- * Returns a string representation of this Markup instance. Can be deserialized back to a Markup
- * instance with markupFromString().
- */
- public String toString() {
- StringBuilder out = new StringBuilder();
- if (mType != null) {
- out.append(TYPE + ": \"" + mType + "\"");
- }
- if (mPlainText != null) {
- out.append(out.length() > 0 ? " " : "");
- out.append(PLAIN_TEXT + ": \"" + escapeQuotedString(mPlainText) + "\"");
- }
- // Sort the parameters alphabetically by key so we have a stable output.
- SortedMap<String, String> sortedMap = new TreeMap<String, String>();
- for (String key : mParameters.keySet()) {
- sortedMap.put(key, mParameters.getString(key));
- }
- for (Map.Entry<String, String> entry : sortedMap.entrySet()) {
- out.append(out.length() > 0 ? " " : "");
- out.append(entry.getKey() + ": \"" + escapeQuotedString(entry.getValue()) + "\"");
- }
- for (Markup m : mNestedMarkups) {
- out.append(out.length() > 0 ? " " : "");
- String nestedStr = m.toString();
- if (nestedStr.isEmpty()) {
- out.append(MARKUP + " {}");
- } else {
- out.append(MARKUP + " { " + m.toString() + " }");
- }
- }
- return out.toString();
- }
-
- /**
- * Escapes backslashes and double quotes in the plain text and parameter values before this
- * instance is written to a string.
- * @param str The string to escape.
- * @return The escaped string.
- */
- private static String escapeQuotedString(String str) {
- StringBuilder out = new StringBuilder();
- for (int i = 0; i < str.length(); i++) {
- char c = str.charAt(i);
- if (c == '"') {
- out.append("\\\"");
- } else if (str.charAt(i) == '\\') {
- out.append("\\\\");
- } else {
- out.append(c);
- }
- }
- return out.toString();
- }
-
- /**
- * The reverse of the escape method, returning plain text and parameter values to their original
- * form.
- * @param str An escaped string.
- * @return The unescaped string.
- */
- private static String unescapeQuotedString(String str) {
- StringBuilder out = new StringBuilder();
- for (int i = 0; i < str.length(); i++) {
- char c = str.charAt(i);
- if (c == '\\') {
- i++;
- if (i >= str.length()) {
- throw new IllegalArgumentException("Unterminated escape sequence in string: " +
- str);
- }
- c = str.charAt(i);
- if (c == '\\') {
- out.append("\\");
- } else if (c == '"') {
- out.append("\"");
- } else {
- throw new IllegalArgumentException("Unsupported escape sequence: \\" + c +
- " in string " + str);
- }
- } else {
- out.append(c);
- }
- }
- return out.toString();
- }
-
- /**
- * Returns true if the given string consists only of whitespace.
- * @param str The string to check.
- * @return True if the given string consists only of whitespace.
- */
- private static boolean isWhitespace(String str) {
- return Pattern.matches("\\s*", str);
- }
-
- /**
- * Parses the given string, and overrides the values of this instance with those contained
- * in the given string.
- * @param str The string to parse; can have superfluous whitespace.
- * @return An empty string on success, else the remainder of the string that could not be
- * parsed.
- */
- private String fromReadableString(String str) {
- while (!isWhitespace(str)) {
- String newStr = matchValue(str);
- if (newStr == null) {
- newStr = matchMarkup(str);
-
- if (newStr == null) {
- return str;
- }
- }
- str = newStr;
- }
- return "";
- }
-
- // Matches: key : "value"
- // where key is an identifier and value can contain escaped quotes
- // there may be superflouous whitespace
- // The value string may contain quotes and backslashes.
- private static final String OPTIONAL_WHITESPACE = "\\s*";
- private static final String VALUE_REGEX = "((\\\\.|[^\\\"])*)";
- private static final String KEY_VALUE_REGEX =
- "\\A" + OPTIONAL_WHITESPACE + // start of string
- IDENTIFIER_REGEX + OPTIONAL_WHITESPACE + ":" + OPTIONAL_WHITESPACE + // key:
- "\"" + VALUE_REGEX + "\""; // "value"
- private static final Pattern KEY_VALUE_PATTERN = Pattern.compile(KEY_VALUE_REGEX);
-
- /**
- * Tries to match a key-value pair at the start of the string. If found, add that as a parameter
- * of this instance.
- * @param str The string to parse.
- * @return The remainder of the string without the parsed key-value pair on success, else null.
- */
- private String matchValue(String str) {
- // Matches: key: "value"
- Matcher matcher = KEY_VALUE_PATTERN.matcher(str);
- if (!matcher.find()) {
- return null;
- }
- String key = matcher.group(1);
- String value = matcher.group(2);
-
- if (key == null || value == null) {
- return null;
- }
- String unescapedValue = unescapeQuotedString(value);
- if (key.equals(TYPE)) {
- this.mType = unescapedValue;
- } else if (key.equals(PLAIN_TEXT)) {
- this.mPlainText = unescapedValue;
- } else {
- setParameter(key, unescapedValue);
- }
-
- return str.substring(matcher.group(0).length());
- }
-
- // matches 'markup {'
- private static final Pattern OPEN_MARKUP_PATTERN =
- Pattern.compile("\\A" + OPTIONAL_WHITESPACE + MARKUP + OPTIONAL_WHITESPACE + "\\{");
- // matches '}'
- private static final Pattern CLOSE_MARKUP_PATTERN =
- Pattern.compile("\\A" + OPTIONAL_WHITESPACE + "\\}");
-
- /**
- * Tries to parse a Markup specification from the start of the string. If so, add that markup to
- * the list of nested Markup's of this instance.
- * @param str The string to parse.
- * @return The remainder of the string without the parsed Markup on success, else null.
- */
- private String matchMarkup(String str) {
- // find and strip "markup {"
- Matcher matcher = OPEN_MARKUP_PATTERN.matcher(str);
-
- if (!matcher.find()) {
- return null;
- }
- String strRemainder = str.substring(matcher.group(0).length());
- // parse and strip markup contents
- Markup nestedMarkup = new Markup();
- strRemainder = nestedMarkup.fromReadableString(strRemainder);
-
- // find and strip "}"
- Matcher matcherClose = CLOSE_MARKUP_PATTERN.matcher(strRemainder);
- if (!matcherClose.find()) {
- return null;
- }
- strRemainder = strRemainder.substring(matcherClose.group(0).length());
-
- // Everything parsed, add markup
- this.addNestedMarkup(nestedMarkup);
-
- // Return remainder
- return strRemainder;
- }
-
- /**
- * Returns a Markup instance from the string representation generated by toString().
- * @param string The string representation generated by toString().
- * @return The new Markup instance.
- * @throws {@link IllegalArgumentException} if the input cannot be correctly parsed.
- */
- public static Markup markupFromString(String string) throws IllegalArgumentException {
- Markup m = new Markup();
- if (m.fromReadableString(string).isEmpty()) {
- return m;
- } else {
- throw new IllegalArgumentException("Cannot parse input to Markup");
- }
- }
-
- /**
- * Compares the specified object with this Markup for equality.
- * @return True if the given object is a Markup instance with the same type, plain text,
- * parameters and the nested markups are also equal to each other and in the same order.
- */
- @Override
- public boolean equals(Object o) {
- if ( this == o ) return true;
- if ( !(o instanceof Markup) ) return false;
- Markup m = (Markup) o;
-
- if (nestedMarkupSize() != this.nestedMarkupSize()) {
- return false;
- }
-
- if (!(mType == null ? m.mType == null : mType.equals(m.mType))) {
- return false;
- }
- if (!(mPlainText == null ? m.mPlainText == null : mPlainText.equals(m.mPlainText))) {
- return false;
- }
- if (!equalBundles(mParameters, m.mParameters)) {
- return false;
- }
-
- for (int i = 0; i < this.nestedMarkupSize(); i++) {
- if (!mNestedMarkups.get(i).equals(m.mNestedMarkups.get(i))) {
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * Checks if two bundles are equal to each other. Used by equals(o).
- */
- private boolean equalBundles(Bundle one, Bundle two) {
- if (one == null || two == null) {
- return false;
- }
-
- if(one.size() != two.size()) {
- return false;
- }
-
- Set<String> valuesOne = one.keySet();
- for(String key : valuesOne) {
- Object valueOne = one.get(key);
- Object valueTwo = two.get(key);
- if (valueOne instanceof Bundle && valueTwo instanceof Bundle &&
- !equalBundles((Bundle) valueOne, (Bundle) valueTwo)) {
- return false;
- } else if (valueOne == null) {
- if (valueTwo != null || !two.containsKey(key)) {
- return false;
- }
- } else if(!valueOne.equals(valueTwo)) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Returns an unmodifiable list of the children.
- * @return An unmodifiable list of children that throws an {@link UnsupportedOperationException}
- * if an attempt is made to modify it
- */
- public List<Markup> getNestedMarkups() {
- return Collections.unmodifiableList(mNestedMarkups);
- }
-
- /**
- * @hide
- */
- public Markup(Parcel in) {
- mType = in.readString();
- mPlainText = in.readString();
- mParameters = in.readBundle();
- in.readList(mNestedMarkups, Markup.class.getClassLoader());
- }
-
- /**
- * Creates a deep copy of the given markup.
- */
- public Markup(Markup markup) {
- mType = markup.mType;
- mPlainText = markup.mPlainText;
- mParameters = markup.mParameters;
- for (Markup nested : markup.getNestedMarkups()) {
- addNestedMarkup(new Markup(nested));
- }
- }
-
- /**
- * @hide
- */
- public int describeContents() {
- return 0;
- }
-
- /**
- * @hide
- */
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(mType);
- dest.writeString(mPlainText);
- dest.writeBundle(mParameters);
- dest.writeList(mNestedMarkups);
- }
-
- /**
- * @hide
- */
- public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
- public Markup createFromParcel(Parcel in) {
- return new Markup(in);
- }
-
- public Markup[] newArray(int size) {
- return new Markup[size];
- }
- };
-}
-
diff --git a/core/java/android/speech/tts/Utterance.java b/core/java/android/speech/tts/Utterance.java
deleted file mode 100644
index 0a29283..0000000
--- a/core/java/android/speech/tts/Utterance.java
+++ /dev/null
@@ -1,595 +0,0 @@
-package android.speech.tts;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * This class acts as a builder for {@link Markup} instances.
- * <p>
- * Each Utterance consists of a list of the semiotic classes ({@link Utterance.TtsCardinal} and
- * {@link Utterance.TtsText}).
- * <p>Each semiotic class can be supplied with morphosyntactic features
- * (gender, animacy, multiplicity and case), it is up to the synthesis engine to use this
- * information during synthesis.
- * Examples where morphosyntactic features matter:
- * <ul>
- * <li>In French, the number one is verbalized differently based on the gender of the noun
- * it modifies. "un homme" (one man) versus "une femme" (one woman).
- * <li>In German the grammatical case (accusative, locative, etc) needs to be included to be
- * verbalize correctly. In German you'd have the sentence "Sie haben 1 kilometer vor Ihnen" (You
- * have 1 kilometer ahead of you), "1" in this case needs to become inflected to the accusative
- * form ("einen") instead of the nominative form "ein".
- * </p>
- * <p>
- * Utterance usage example:
- * Markup m1 = new Utterance().append("The Eiffel Tower is")
- * .append(new TtsCardinal(324))
- * .append("meters tall.");
- * Markup m2 = new Utterance().append("Sie haben")
- * .append(new TtsCardinal(1).setGender(Utterance.GENDER_MALE)
- * .append("Tag frei.");
- * </p>
- */
-public class Utterance {
-
- /***
- * Toplevel type of markup representation.
- */
- public static final String TYPE_UTTERANCE = "utterance";
- /***
- * The no_warning_on_fallback parameter can be set to "false" or "true", true indicating that
- * no warning will be given when the synthesizer does not support Markup. This is used when
- * the user only provides a string to the API instead of a markup.
- */
- public static final String KEY_NO_WARNING_ON_FALLBACK = "no_warning_on_fallback";
-
- // Gender.
- public final static int GENDER_UNKNOWN = 0;
- public final static int GENDER_NEUTRAL = 1;
- public final static int GENDER_MALE = 2;
- public final static int GENDER_FEMALE = 3;
-
- // Animacy.
- public final static int ANIMACY_UNKNOWN = 0;
- public final static int ANIMACY_ANIMATE = 1;
- public final static int ANIMACY_INANIMATE = 2;
-
- // Multiplicity.
- public final static int MULTIPLICITY_UNKNOWN = 0;
- public final static int MULTIPLICITY_SINGLE = 1;
- public final static int MULTIPLICITY_DUAL = 2;
- public final static int MULTIPLICITY_PLURAL = 3;
-
- // Case.
- public final static int CASE_UNKNOWN = 0;
- public final static int CASE_NOMINATIVE = 1;
- public final static int CASE_ACCUSATIVE = 2;
- public final static int CASE_DATIVE = 3;
- public final static int CASE_ABLATIVE = 4;
- public final static int CASE_GENITIVE = 5;
- public final static int CASE_VOCATIVE = 6;
- public final static int CASE_LOCATIVE = 7;
- public final static int CASE_INSTRUMENTAL = 8;
-
- private List<AbstractTts<? extends AbstractTts<?>>> says =
- new ArrayList<AbstractTts<? extends AbstractTts<?>>>();
- Boolean mNoWarningOnFallback = null;
-
- /**
- * Objects deriving from this class can be appended to a Utterance. This class uses generics
- * so method from this class can return instances of its child classes, resulting in a better
- * API (CRTP pattern).
- */
- public static abstract class AbstractTts<C extends AbstractTts<C>> {
-
- protected Markup mMarkup = new Markup();
-
- /**
- * Empty constructor.
- */
- protected AbstractTts() {
- }
-
- /**
- * Construct with Markup.
- * @param markup
- */
- protected AbstractTts(Markup markup) {
- mMarkup = markup;
- }
-
- /**
- * Returns the type of this class, e.g. "cardinal" or "measure".
- * @return The type.
- */
- public String getType() {
- return mMarkup.getType();
- }
-
- /**
- * A fallback plain text can be provided, in case the engine does not support this class
- * type, or even Markup altogether.
- * @param plainText A string with the plain text.
- * @return This instance.
- */
- @SuppressWarnings("unchecked")
- public C setPlainText(String plainText) {
- mMarkup.setPlainText(plainText);
- return (C) this;
- }
-
- /**
- * Returns the plain text (fallback) string.
- * @return Plain text string or null if not set.
- */
- public String getPlainText() {
- return mMarkup.getPlainText();
- }
-
- /**
- * Populates the plainText if not set and builds a Markup instance.
- * @return The Markup object describing this instance.
- */
- public Markup getMarkup() {
- return new Markup(mMarkup);
- }
-
- @SuppressWarnings("unchecked")
- protected C setParameter(String key, String value) {
- mMarkup.setParameter(key, value);
- return (C) this;
- }
-
- protected String getParameter(String key) {
- return mMarkup.getParameter(key);
- }
-
- @SuppressWarnings("unchecked")
- protected C removeParameter(String key) {
- mMarkup.removeParameter(key);
- return (C) this;
- }
-
- /**
- * Returns a string representation of this instance, can be deserialized to an equal
- * Utterance instance.
- */
- public String toString() {
- return mMarkup.toString();
- }
-
- /**
- * Returns a generated plain text alternative for this instance if this instance isn't
- * better representated by the list of it's children.
- * @return Best effort plain text representation of this instance, can be null.
- */
- public String generatePlainText() {
- return null;
- }
- }
-
- public static abstract class AbstractTtsSemioticClass<C extends AbstractTtsSemioticClass<C>>
- extends AbstractTts<C> {
- // Keys.
- private static final String KEY_GENDER = "gender";
- private static final String KEY_ANIMACY = "animacy";
- private static final String KEY_MULTIPLICITY = "multiplicity";
- private static final String KEY_CASE = "case";
-
- protected AbstractTtsSemioticClass() {
- super();
- }
-
- protected AbstractTtsSemioticClass(Markup markup) {
- super(markup);
- }
-
- @SuppressWarnings("unchecked")
- public C setGender(int gender) {
- if (gender < 0 || gender > 3) {
- throw new IllegalArgumentException("Only four types of gender can be set: " +
- "unknown, neutral, maculine and female.");
- }
- if (gender != GENDER_UNKNOWN) {
- setParameter(KEY_GENDER, String.valueOf(gender));
- } else {
- setParameter(KEY_GENDER, null);
- }
- return (C) this;
- }
-
- public int getGender() {
- String gender = mMarkup.getParameter(KEY_GENDER);
- return gender != null ? Integer.valueOf(gender) : GENDER_UNKNOWN;
- }
-
- @SuppressWarnings("unchecked")
- public C setAnimacy(int animacy) {
- if (animacy < 0 || animacy > 2) {
- throw new IllegalArgumentException(
- "Only two types of animacy can be set: unknown, animate and inanimate");
- }
- if (animacy != ANIMACY_UNKNOWN) {
- setParameter(KEY_ANIMACY, String.valueOf(animacy));
- } else {
- setParameter(KEY_ANIMACY, null);
- }
- return (C) this;
- }
-
- public int getAnimacy() {
- String animacy = getParameter(KEY_ANIMACY);
- return animacy != null ? Integer.valueOf(animacy) : ANIMACY_UNKNOWN;
- }
-
- @SuppressWarnings("unchecked")
- public C setMultiplicity(int multiplicity) {
- if (multiplicity < 0 || multiplicity > 3) {
- throw new IllegalArgumentException(
- "Only four types of multiplicity can be set: unknown, single, dual and " +
- "plural.");
- }
- if (multiplicity != MULTIPLICITY_UNKNOWN) {
- setParameter(KEY_MULTIPLICITY, String.valueOf(multiplicity));
- } else {
- setParameter(KEY_MULTIPLICITY, null);
- }
- return (C) this;
- }
-
- public int getMultiplicity() {
- String multiplicity = mMarkup.getParameter(KEY_MULTIPLICITY);
- return multiplicity != null ? Integer.valueOf(multiplicity) : MULTIPLICITY_UNKNOWN;
- }
-
- @SuppressWarnings("unchecked")
- public C setCase(int grammaticalCase) {
- if (grammaticalCase < 0 || grammaticalCase > 8) {
- throw new IllegalArgumentException(
- "Only nine types of grammatical case can be set.");
- }
- if (grammaticalCase != CASE_UNKNOWN) {
- setParameter(KEY_CASE, String.valueOf(grammaticalCase));
- } else {
- setParameter(KEY_CASE, null);
- }
- return (C) this;
- }
-
- public int getCase() {
- String grammaticalCase = mMarkup.getParameter(KEY_CASE);
- return grammaticalCase != null ? Integer.valueOf(grammaticalCase) : CASE_UNKNOWN;
- }
- }
-
- /**
- * Class that contains regular text, synthesis engine pronounces it using its regular pipeline.
- * Parameters:
- * <ul>
- * <li>Text: the text to synthesize</li>
- * </ul>
- */
- public static class TtsText extends AbstractTtsSemioticClass<TtsText> {
-
- // The type of this node.
- protected static final String TYPE_TEXT = "text";
- // The text parameter stores the text to be synthesized.
- private static final String KEY_TEXT = "text";
-
- /**
- * Default constructor.
- */
- public TtsText() {
- mMarkup.setType(TYPE_TEXT);
- }
-
- /**
- * Constructor that sets the text to be synthesized.
- * @param text The text to be synthesized.
- */
- public TtsText(String text) {
- this();
- setText(text);
- }
-
- /**
- * Constructs a TtsText with the values of the Markup, does not check if the given Markup is
- * of the right type.
- */
- private TtsText(Markup markup) {
- super(markup);
- }
-
- /**
- * Sets the text to be synthesized.
- * @return This instance.
- */
- public TtsText setText(String text) {
- setParameter(KEY_TEXT, text);
- return this;
- }
-
- /**
- * Returns the text to be synthesized.
- * @return This instance.
- */
- public String getText() {
- return getParameter(KEY_TEXT);
- }
-
- /**
- * Generates a best effort plain text, in this case simply the text.
- */
- @Override
- public String generatePlainText() {
- return getText();
- }
- }
-
- /**
- * Contains a cardinal.
- * Parameters:
- * <ul>
- * <li>integer: the integer to synthesize</li>
- * </ul>
- */
- public static class TtsCardinal extends AbstractTtsSemioticClass<TtsCardinal> {
-
- // The type of this node.
- protected static final String TYPE_CARDINAL = "cardinal";
- // The parameter integer stores the integer to synthesize.
- private static final String KEY_INTEGER = "integer";
-
- /**
- * Default constructor.
- */
- public TtsCardinal() {
- mMarkup.setType(TYPE_CARDINAL);
- }
-
- /**
- * Constructor that sets the integer to be synthesized.
- */
- public TtsCardinal(int integer) {
- this();
- setInteger(integer);
- }
-
- /**
- * Constructor that sets the integer to be synthesized.
- */
- public TtsCardinal(String integer) {
- this();
- setInteger(integer);
- }
-
- /**
- * Constructs a TtsText with the values of the Markup.
- * Does not check if the given Markup is of the right type.
- */
- private TtsCardinal(Markup markup) {
- super(markup);
- }
-
- /**
- * Sets the integer.
- * @return This instance.
- */
- public TtsCardinal setInteger(int integer) {
- return setInteger(String.valueOf(integer));
- }
-
- /**
- * Sets the integer.
- * @param integer A non-empty string of digits with an optional '-' in front.
- * @return This instance.
- */
- public TtsCardinal setInteger(String integer) {
- if (!integer.matches("-?\\d+")) {
- throw new IllegalArgumentException("Expected a cardinal: \"" + integer + "\"");
- }
- setParameter(KEY_INTEGER, integer);
- return this;
- }
-
- /**
- * Returns the integer parameter.
- */
- public String getInteger() {
- return getParameter(KEY_INTEGER);
- }
-
- /**
- * Generates a best effort plain text, in this case simply the integer.
- */
- @Override
- public String generatePlainText() {
- return getInteger();
- }
- }
-
- /**
- * Default constructor.
- */
- public Utterance() {}
-
- /**
- * Returns the plain text of a given Markup if it was set; if it's not set, recursively call the
- * this same method on its children.
- */
- private String constructPlainText(Markup m) {
- StringBuilder plainText = new StringBuilder();
- if (m.getPlainText() != null) {
- plainText.append(m.getPlainText());
- } else {
- for (Markup nestedMarkup : m.getNestedMarkups()) {
- String nestedPlainText = constructPlainText(nestedMarkup);
- if (!nestedPlainText.isEmpty()) {
- if (plainText.length() != 0) {
- plainText.append(" ");
- }
- plainText.append(nestedPlainText);
- }
- }
- }
- return plainText.toString();
- }
-
- /**
- * Creates a Markup instance with auto generated plain texts for the relevant nodes, in case the
- * user has not provided one already.
- * @return A Markup instance representing this utterance.
- */
- public Markup createMarkup() {
- Markup markup = new Markup(TYPE_UTTERANCE);
- StringBuilder plainText = new StringBuilder();
- for (AbstractTts<? extends AbstractTts<?>> say : says) {
- // Get a copy of this markup, and generate a plaintext for it if is not set.
- Markup sayMarkup = say.getMarkup();
- if (sayMarkup.getPlainText() == null) {
- sayMarkup.setPlainText(say.generatePlainText());
- }
- if (plainText.length() != 0) {
- plainText.append(" ");
- }
- plainText.append(constructPlainText(sayMarkup));
- markup.addNestedMarkup(sayMarkup);
- }
- if (mNoWarningOnFallback != null) {
- markup.setParameter(KEY_NO_WARNING_ON_FALLBACK,
- mNoWarningOnFallback ? "true" : "false");
- }
- markup.setPlainText(plainText.toString());
- return markup;
- }
-
- /**
- * Appends an element to this Utterance instance.
- * @return this instance
- */
- public Utterance append(AbstractTts<? extends AbstractTts<?>> say) {
- says.add(say);
- return this;
- }
-
- private Utterance append(Markup markup) {
- if (markup.getType().equals(TtsText.TYPE_TEXT)) {
- append(new TtsText(markup));
- } else if (markup.getType().equals(TtsCardinal.TYPE_CARDINAL)) {
- append(new TtsCardinal(markup));
- } else {
- // Unknown node, a class we don't know about.
- if (markup.getPlainText() != null) {
- append(new TtsText(markup.getPlainText()));
- } else {
- // No plainText specified; add its children
- // seperately. In case of a new prosody node,
- // we would still verbalize it correctly.
- for (Markup nested : markup.getNestedMarkups()) {
- append(nested);
- }
- }
- }
- return this;
- }
-
- /**
- * Returns a string representation of this Utterance instance. Can be deserialized back to an
- * Utterance instance with utteranceFromString(). Can be used to store utterances to be used
- * at a later time.
- */
- public String toString() {
- String out = "type: \"" + TYPE_UTTERANCE + "\"";
- if (mNoWarningOnFallback != null) {
- out += " no_warning_on_fallback: \"" + (mNoWarningOnFallback ? "true" : "false") + "\"";
- }
- for (AbstractTts<? extends AbstractTts<?>> say : says) {
- out += " markup { " + say.getMarkup().toString() + " }";
- }
- return out;
- }
-
- /**
- * Returns an Utterance instance from the string representation generated by toString().
- * @param string The string representation generated by toString().
- * @return The new Utterance instance.
- * @throws {@link IllegalArgumentException} if the input cannot be correctly parsed.
- */
- static public Utterance utteranceFromString(String string) throws IllegalArgumentException {
- Utterance utterance = new Utterance();
- Markup markup = Markup.markupFromString(string);
- if (!markup.getType().equals(TYPE_UTTERANCE)) {
- throw new IllegalArgumentException("Top level markup should be of type \"" +
- TYPE_UTTERANCE + "\", but was of type \"" +
- markup.getType() + "\".") ;
- }
- for (Markup nestedMarkup : markup.getNestedMarkups()) {
- utterance.append(nestedMarkup);
- }
- return utterance;
- }
-
- /**
- * Appends a new TtsText with the given text.
- * @param text The text to synthesize.
- * @return This instance.
- */
- public Utterance append(String text) {
- return append(new TtsText(text));
- }
-
- /**
- * Appends a TtsCardinal representing the given number.
- * @param integer The integer to synthesize.
- * @return this
- */
- public Utterance append(int integer) {
- return append(new TtsCardinal(integer));
- }
-
- /**
- * Returns the n'th element in this Utterance.
- * @param i The index.
- * @return The n'th element in this Utterance.
- * @throws {@link IndexOutOfBoundsException} - if i < 0 || i >= size()
- */
- public AbstractTts<? extends AbstractTts<?>> get(int i) {
- return says.get(i);
- }
-
- /**
- * Returns the number of elements in this Utterance.
- * @return The number of elements in this Utterance.
- */
- public int size() {
- return says.size();
- }
-
- @Override
- public boolean equals(Object o) {
- if ( this == o ) return true;
- if ( !(o instanceof Utterance) ) return false;
- Utterance utt = (Utterance) o;
-
- if (says.size() != utt.says.size()) {
- return false;
- }
-
- for (int i = 0; i < says.size(); i++) {
- if (!says.get(i).getMarkup().equals(utt.says.get(i).getMarkup())) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Can be set to true or false, true indicating that the user provided only a string to the API,
- * at which the system will not issue a warning if the synthesizer falls back onto the plain
- * text when the synthesizer does not support Markup.
- */
- public Utterance setNoWarningOnFallback(boolean noWarning) {
- mNoWarningOnFallback = noWarning;
- return this;
- }
-}