Package com.sun.speech.freetts.en.us

Source Code of com.sun.speech.freetts.en.us.NumberExpander

/**
* Portions Copyright 2001-2003 Sun Microsystems, Inc.
* Portions Copyright 1999-2001 Language Technologies Institute,
* Carnegie Mellon University.
* All Rights Reserved.  Use is subject to license terms.
*
* See the file "license.terms" for information on usage and
* redistribution of this file, and for a DISCLAIMER OF ALL
* WARRANTIES.
*/
package com.sun.speech.freetts.en.us;

import com.sun.speech.freetts.FeatureSet;
import com.sun.speech.freetts.Item;
import com.sun.speech.freetts.util.Utilities;

/**
* Expands Strings containing digits characters into
* a list of words representing those digits.
*
* It translates the following code from flite:
* <code>lang/usEnglish/us_expand.c</code>
*/
public class NumberExpander {
   
    private static final String[] digit2num = {
  "zero",
  "one",
  "two",
  "three",
  "four",
  "five",
  "six",
  "seven",
  "eight",
  "nine" };
   
    private static final String[] digit2teen = {
  "ten"/* shouldn't get called */
  "eleven",
  "twelve",
  "thirteen",
  "fourteen",
  "fifteen",
  "sixteen",
  "seventeen",
  "eighteen",
  "nineteen" };
   
    private static final String[] digit2enty = {
  "zero"/* shouldn't get called */
  "ten",
  "twenty",
  "thirty",
  "forty",
  "fifty",
  "sixty",
  "seventy",
  "eighty",
  "ninety" };
   
    private static final String[] ord2num = {
  "zeroth",
  "first",
  "second",
  "third",
  "fourth",
  "fifth",
  "sixth",
  "seventh",
  "eighth",
  "ninth" };
   
    private static final String[] ord2teen = {
  "tenth"/* shouldn't get called */
  "eleventh",
  "twelfth",
  "thirteenth",
  "fourteenth",
  "fifteenth",
  "sixteenth",
  "seventeenth",
  "eighteenth",
  "nineteenth" };
   
    private static final String[] ord2enty = {
  "zeroth"/* shouldn't get called */
  "tenth",
  "twentieth",
  "thirtieth",
  "fortieth",
  "fiftieth",
  "sixtieth",
  "seventieth",
  "eightieth",
  "ninetieth" };


    /**
     * Unconstructable
     */
    private NumberExpander() {
    }


    /**
     * Expands a digit string into a list of English words of those digits.
     * For example, "1234" expands to "one two three four"
     *
     * @param  numberString  the digit string to expand.
     * @param  wordRelation  words are added to this Relation
     */
    public static void expandNumber(String numberString,
            WordRelation wordRelation) {
  int numDigits = numberString.length();
 
  if (numDigits == 0) {
      // wordRelation = null;
  } else if (numDigits == 1) {
      expandDigits(numberString, wordRelation);
  } else if (numDigits == 2) {
      expand2DigitNumber(numberString, wordRelation);
  } else if (numDigits == 3) {
      expand3DigitNumber(numberString, wordRelation);
  } else if (numDigits < 7) {
      expandBelow7DigitNumber(numberString, wordRelation);
  } else if (numDigits < 10) {
      expandBelow10DigitNumber(numberString, wordRelation);
  } else if (numDigits < 13) {
      expandBelow13DigitNumber(numberString, wordRelation);
  } else {
      expandDigits(numberString, wordRelation);
  }
    }


    /**
     * Expands a two-digit string into a list of English words.
     *
     * @param numberString the string which is the number to expand
     * @param  wordRelation  words are added to this Relation
     */
    private static void expand2DigitNumber(String numberString,
             WordRelation wordRelation) {
  if (numberString.charAt(0) == '0') {
      // numberString is "0X"
      if (numberString.charAt(1) == '0') {
    // numberString is "00", do nothing
      } else {
    // numberString is "01", "02" ...
    String number = digit2num[numberString.charAt(1)-'0'];
    wordRelation.addWord(number);
      }
  } else if (numberString.charAt(1) == '0') {
      // numberString is "10", "20", ...
      String number = digit2enty[numberString.charAt(0)-'0'];
      wordRelation.addWord(number);
  } else if (numberString.charAt(0) == '1') {
      // numberString is "11", "12", ..., "19"
      String number = digit2teen[numberString.charAt(1)-'0'];
      wordRelation.addWord(number);
  } else {
      // numberString is "2X", "3X", ...
      String enty = digit2enty[numberString.charAt(0)-'0'];
      wordRelation.addWord(enty);
      expandDigits(numberString.substring(1,numberString.length()),
       wordRelation);
  }
    }

   
    /**
     * Expands a three-digit string into a list of English words.
     *
     * @param numberString the string which is the number to expand
     * @param  wordRelation  words are added to this Relation
     */
    private static void expand3DigitNumber(String numberString,
             WordRelation wordRelation) {
  if (numberString.charAt(0) == '0') {
      expandNumberAt(numberString, 1, wordRelation);
  } else {
      String hundredDigit = digit2num[numberString.charAt(0)-'0'];
      wordRelation.addWord(hundredDigit);
      wordRelation.addWord("hundred");
      expandNumberAt(numberString, 1, wordRelation);
  }
    }


    /**
     * Expands a string that is a 4 to 6 digits number into a list
     * of English words. For example, "333000" into "three hundred
     * and thirty-three thousand".
     *
     * @param numberString the string which is the number to expand
     * @param  wordRelation  words are added to this Relation
     */
    private static void expandBelow7DigitNumber(String numberString,
            WordRelation wordRelation) {
  expandLargeNumber(numberString, "thousand", 3, wordRelation);
    }
   

    /**
     * Expands a string that is a 7 to 9 digits number into a list
     * of English words. For example, "19000000" into nineteen million.
     *
     * @param numberString the string which is the number to expand
     * @param  wordRelation  words are added to this Relation
     */
    private static void expandBelow10DigitNumber(String numberString,
             WordRelation wordRelation) {
  expandLargeNumber(numberString, "million", 6, wordRelation);
    }


    /**
     * Expands a string that is a 10 to 12 digits number into a list
     * of English words. For example, "27000000000" into twenty-seven
     * billion.
     *
     * @param numberString the string which is the number to expand
     * @param  wordRelation  words are added to this Relation
     */
    private static void expandBelow13DigitNumber(String numberString,
             WordRelation wordRelation) {
  expandLargeNumber(numberString, "billion", 9, wordRelation);
    }


    /**
     * Expands a string that is a number longer than 3 digits into a list
     * of English words. For example, "1000" into one thousand.
     *
     * @param numberString the string which is the number to expand
     * @param order either "thousand", "million", or "billion"
     * @param numberZeroes the number of zeroes, depending on the order, so
     *        its either 3, 6, or 9
     * @param  wordRelation  words are added to this Relation
     */
    private static void expandLargeNumber(String numberString,
            String order,
            int numberZeroes,
            WordRelation wordRelation) {
  int numberDigits = numberString.length();
 
  // parse out the prefix, e.g., "113" in "113,000"
  int i = numberDigits - numberZeroes;
  String part = numberString.substring(0, i);
   
  // get how many thousands/millions/billions
  Item oldTail = wordRelation.getTail();
 
  expandNumber(part, wordRelation);

  if (wordRelation.getTail() == oldTail) {
      expandNumberAt(numberString, i, wordRelation);
  } else {
      wordRelation.addWord(order);
      expandNumberAt(numberString, i, wordRelation);
  }
    }


    /**
     * Returns the number string list of the given string starting at
     * the given index. E.g., expandNumberAt("1100", 1) gives "one hundred"
     *
     * @param numberString the string which is the number to expand
     * @param startIndex the starting position
     * @param  wordRelation  words are added to this Relation
     */
    private static void expandNumberAt(String numberString,
               int startIndex,
               WordRelation wordRelation) {
  expandNumber(numberString.substring(startIndex,numberString.length()),
         wordRelation);
    }
   

    /**
     * Expands given token to list of words pronouncing it as digits
     *
     * @param numberString the string which is the number to expand
     * @param  wordRelation  words are added to this Relation
     */
    public static void expandDigits(String numberString,
            WordRelation wordRelation) {
  int numberDigits = numberString.length();
  for (int i = 0; i < numberDigits; i++) {
      char digit = numberString.charAt(i);
      if (isDigit(digit)) {
    wordRelation.addWord(digit2num[numberString.charAt(i)-'0']);
      } else {
    wordRelation.addWord("umpty");
      }
  }
    }
   

    /**
     * Expands the digit string of an ordinal number.
     *
     * @param rawNumberString the string which is the number to expand
     * @param  wordRelation  words are added to this Relation
     */
    public static void expandOrdinal(String rawNumberString,
             WordRelation wordRelation) {
  // remove all ','s from the raw number string
  String numberString = Utilities.deleteChar(rawNumberString, ',');
 
  expandNumber(numberString, wordRelation);

  // get the last in the list of number strings
  Item lastItem = wordRelation.getTail();

  if (lastItem != null) {

      FeatureSet featureSet = lastItem.getFeatures();
      String lastNumber = featureSet.getString("name");
      String ordinal = findMatchInArray(lastNumber, digit2num, ord2num);

      if (ordinal == null) {
    ordinal = findMatchInArray(lastNumber, digit2teen, ord2teen);
      }
      if (ordinal == null) {
    ordinal = findMatchInArray(lastNumber, digit2enty, ord2enty);
      }

      if (lastNumber.equals("hundred")) {
    ordinal = "hundredth";
      } else if (lastNumber.equals("thousand")) {
    ordinal = "thousandth";
      } else if (lastNumber.equals("billion")) {
    ordinal = "billionth";
      }

      // if there was an ordinal, set the last element of the list
      // to that ordinal; otherwise, don't do anything
      if (ordinal != null) {
    wordRelation.setLastWord(ordinal);
      }
  }
    }


    /**
     * Finds a match of the given string in the given array,
     * and returns the element at the same index in the returnInArray
     *
     * @param strToMatch the string to match
     * @param matchInArray the source array
     * @param returnInArray the return array
     *
     * @return an element in returnInArray, or <code>null</code>
     *   if a match is not found
     */
    private static String findMatchInArray(String strToMatch,
             String[] matchInArray,
             String[] returnInArray) {
  for (int i = 0; i < matchInArray.length; i++) {
      if (strToMatch.equals(matchInArray[i])) {
    if (i < returnInArray.length) {
        return returnInArray[i];
    } else {
        return null;
    }
      }
  }
  return null;
    }
   

    /**
     * Expands the given number string as pairs as in years or IDs
     *
     * @param numberString the string which is the number to expand
     * @param  wordRelation  words are added to this Relation
     */
    public static void expandID(String numberString, WordRelation wordRelation) {
 
  int numberDigits = numberString.length();
 
        if ((numberDigits == 4) &&
                    (numberString.charAt(2) == '0') &&
                    (numberString.charAt(3) == '0')) {
            if (numberString.charAt(1) == '0') {          // e.g. 2000, 3000
                expandNumber(numberString, wordRelation);
            } else {
                expandNumber(numberString.substring(0,2), wordRelation);
                wordRelation.addWord("hundred");
            }
  } else if ((numberDigits == 2) && (numberString.charAt(0) == '0')) {
      wordRelation.addWord("oh");
      expandDigits(numberString.substring(1,2), wordRelation);
  } else if ((numberDigits == 4 &&
        numberString.charAt(1) == '0') ||
       numberDigits < 3) {
      expandNumber(numberString, wordRelation);
  } else if (numberDigits % 2 == 1) {
      String firstDigit = digit2num[numberString.charAt(0)-'0'];
      wordRelation.addWord(firstDigit);
      expandID(numberString.substring(1,numberDigits), wordRelation);
  } else {
      expandNumber(numberString.substring(0,2), wordRelation);
      expandID(numberString.substring(2,numberDigits), wordRelation);
  }
    }


    /**
     * Expands the given number string as a real number.
     *
     * @param numberString the string which is the real number to expand
     * @param wordRelation words are added to this Relation
     */
    public static void expandReal(String numberString, WordRelation wordRelation) {

  int stringLength = numberString.length();
  int position;

  if (numberString.charAt(0) == '-') {
      // negative real numbers
      wordRelation.addWord("minus");
      expandReal(numberString.substring(1, stringLength), wordRelation);
  } else if (numberString.charAt(0) == '+') {
      // prefixed with a '+'
      wordRelation.addWord("plus");
      expandReal(numberString.substring(1, stringLength), wordRelation);
  } else if ((position = numberString.indexOf('e')) != -1 ||
       (position = numberString.indexOf('E')) != -1) {
      // numbers with 'E' or 'e'
      expandReal(numberString.substring(0, position), wordRelation);
      wordRelation.addWord("e");
      expandReal(numberString.substring(position + 1), wordRelation);
  } else if ((position = numberString.indexOf('.')) != -1) {
      // numbers with '.'
      String beforeDot = numberString.substring(0, position);
      if (beforeDot.length() > 0) {
    expandReal(beforeDot, wordRelation);
      }
      wordRelation.addWord("point");
      String afterDot = numberString.substring(position + 1);
      if (afterDot.length() > 0) {
    expandDigits(afterDot, wordRelation);
      }
  } else {
      // everything else
      expandNumber(numberString, wordRelation);
  }
    }
   

    /**
     * Expands the given string of letters as a list of single char symbols.
     *
     * @param letters the string of letters to expand
     * @param wordRelation words are added to this Relation
     */
    public static void expandLetters(String letters,
             WordRelation wordRelation) {
  letters = letters.toLowerCase();
  char c;
     
  for (int i = 0; i < letters.length(); i++) {
      // if this is a number
      c = letters.charAt(i);

      if (isDigit(c)) {
    wordRelation.addWord(digit2num[c-'0']);
      } else if (letters.equals("a")) {
    wordRelation.addWord("_a");
      } else {
    wordRelation.addWord(String.valueOf(c));
      }
  }
    }
   
   
    /**
     * Returns the integer value of the given string of Roman numerals.
     *
     * @param roman the string of Roman numbers
     *
     * @return the integer value
     */
    public static int expandRoman(String roman) {
  int value = 0;

  for (int p = 0; p < roman.length(); p++) {
      char c = roman.charAt(p);
      if (c == 'X') {
    value += 10;
      } else if (c == 'V') {
    value += 5;
      } else if (c == 'I') {
    if (p+1 < roman.length()) {
        char p1 = roman.charAt(p+1);
        if (p1 == 'V') {
      value += 4;
      p++;
        } else if (p1 == 'X') {
      value += 9;
      p++;
        } else {
      value += 1;
        }
    } else {
        value += 1;
    }
      }
  }
  return value;
    }


    /**
     * Returns true if the given character is a digit (0-9 only).
     *
     * @param ch the character to test
     *
     * @return true or false
     */
    public static boolean isDigit(char ch) {
  return ('0' <= ch && ch <= '9');
    }
}
TOP

Related Classes of com.sun.speech.freetts.en.us.NumberExpander

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.