2 * Portions Copyright 2001 Sun Microsystems, Inc.
3 * Portions Copyright 1999-2001 Language Technologies Institute,
4 * Carnegie Mellon University.
5 * All Rights Reserved. Use is subject to license terms.
7 * See the file "license.terms" for information on usage and
8 * redistribution of this file, and for a DISCLAIMER OF ALL
11 package com.sun.speech.freetts.en.us;
13 import java.util.HashSet;
15 import java.util.regex.Pattern;
17 import com.sun.speech.freetts.FeatureProcessor;
18 import com.sun.speech.freetts.Item;
19 import com.sun.speech.freetts.PartOfSpeech;
20 import com.sun.speech.freetts.PathExtractor;
21 import com.sun.speech.freetts.PathExtractorImpl;
22 import com.sun.speech.freetts.ProcessException;
23 import com.sun.speech.freetts.Relation;
24 import com.sun.speech.freetts.Voice;
29 * Provides the set of feature processors that are used by this
30 * language as part of the CART processing.
32 public class FeatureProcessors {
34 private final static PathExtractor FIRST_SYLLABLE_PATH =
35 new PathExtractorImpl(
36 "R:SylStructure.parent.R:Phrase.parent.daughter.R:SylStructure.daughter",
39 private final static PathExtractor LAST_SYLLABLE_PATH =
40 new PathExtractorImpl(
41 "R:SylStructure.parent.R:Phrase.parent.daughtern.R:SylStructure.daughter",
44 private final static PathExtractor LAST_LAST_SYLLABLE_PATH =
45 new PathExtractorImpl(
46 "R:SylStructure.parent.R:Phrase.parent.daughtern.R:SylStructure.daughtern",
49 private final static PathExtractor SUB_PHRASE_PATH =
50 new PathExtractorImpl("R:SylStructure.parent.R:Phrase.parent.p", false);
52 private final static Pattern DOUBLE_PATTERN
53 = Pattern.compile(USEnglish.RX_DOUBLE);
55 private final static Pattern DIGITS_PATTERN
56 = Pattern.compile(USEnglish.RX_DIGITS);
58 private static Set months;
59 private static Set days;
61 // the set of month names
63 months = new HashSet();
65 months.add("january");
67 months.add("february");
80 months.add("september");
82 months.add("october");
84 months.add("november");
86 months.add("december");
89 // the set of week neames
99 days.add("wednesday");
101 days.add("thursday");
105 days.add("saturday");
109 private FeatureProcessors() {}
112 * Returns a guess of the part-of-speech.
114 * This is a feature processor. A feature processor takes an item,
115 * performs some sort of processing on the item and returns an object.
117 public static class Gpos implements FeatureProcessor {
120 * Creates a GPOS with the given part-of-speech table
122 * @param pos part of speech determiner
124 public Gpos(PartOfSpeech pos) {
129 * Performs some processing on the given item.
131 * @param item the item to process
133 * @return a guess at the part-of-speech for the item
135 * @throws ProcessException if an exception occurred during the
138 public String process(Item item) throws ProcessException {
139 return pos.getPartOfSpeech(item.toString());
145 * Returns as an Integer the number of syllables in the given
146 * word. This is a feature processor. A feature processor takes an item,
147 * performs some sort of processing on the item and returns an object.
149 public static class WordNumSyls implements FeatureProcessor {
152 * Performs some processing on the given item.
154 * @param item the item to process
156 * @return the number of syllables in the given word
158 * @throws ProcessException if an exception occurred during the
161 public String process(Item item) throws ProcessException {
163 Item daughter = item.getItemAs(
164 Relation.SYLLABLE_STRUCTURE).getDaughter();
165 while (daughter != null) {
167 daughter = daughter.getNext();
169 return Integer.toString(rail(count));
174 * Counts the number of accented syllables since the last major break.
175 * This is a feature processor. A feature processor takes an item,
176 * performs some sort of processing on the item and returns an object.
178 public static class AccentedSylIn implements FeatureProcessor {
181 * Performs some processing on the given item.
183 * @param item the item to process
185 * @return the number of accented syllables since the last
188 * @throws ProcessException if an exception occurred during the
191 public String process(Item item) throws ProcessException {
193 Item ss = item.getItemAs(Relation.SYLLABLE);
194 Item firstSyllable = FIRST_SYLLABLE_PATH.findItem(item);
196 for (Item p = ss; p != null; p = p.getPrevious() ) {
200 if (p.equalsShared(firstSyllable)) {
204 return Integer.toString(rail(count));
210 * Counts the number of stressed syllables since the last major break.
211 * This is a feature processor. A feature processor takes an item,
212 * performs some sort of processing on the item and returns an object.
214 public static class StressedSylIn implements FeatureProcessor {
217 * Performs some processing on the given item.
219 * @param item the item to process
221 * @return the number of stresses syllables since the last
224 * @throws ProcessException if an exception occurred during the
227 public String process(Item item) throws ProcessException {
229 Item ss = item.getItemAs(Relation.SYLLABLE);
230 Item firstSyllable = FIRST_SYLLABLE_PATH.findItem(item);
232 // this should include the first syllable, but
233 // flite 1.1 and festival don't.
235 for (Item p = ss.getPrevious();
236 p != null && !p.equalsShared(firstSyllable);
237 p = p.getPrevious() ) {
238 if ("1".equals(p.getFeatures().getString("stress"))) {
242 return Integer.toString(rail(count));
247 * Counts the number of stressed syllables until the next major break.
248 * This is a feature processor. A feature processor takes an item,
249 * performs some sort of processing on the item and returns an object.
251 public static class StressedSylOut implements FeatureProcessor {
254 * Performs some processing on the given item.
256 * @param item the item to process
258 * @return the number of stressed syllables until the next major break
260 * @throws ProcessException if an exception occurred during the
263 public String process(Item item) throws ProcessException {
265 Item ss = item.getItemAs(Relation.SYLLABLE);
266 Item lastSyllable = LAST_SYLLABLE_PATH.findItem(item);
268 for (Item p = ss.getNext(); p != null; p = p.getNext() ) {
269 if ("1".equals(p.getFeatures().getString("stress"))) {
272 if (p.equalsShared(lastSyllable)) {
276 return Integer.toString(rail(count));
281 * Returns the length of the string. (generally this is a digit
283 * This is a feature processor. A feature processor takes an item,
284 * performs some sort of processing on the item and returns an object.
286 public static class NumDigits implements FeatureProcessor {
289 * Performs some processing on the given item.
291 * @param item the item to process
293 * @return the length of the string
295 * @throws ProcessException if an exception occurred during the
298 public String process(Item item) throws ProcessException {
299 String name = item.getFeatures().getString("name");
300 return Integer.toString(rail(name.length()));
305 * Returns true ("1") if the given item is a number between 0 and
306 * 32 exclusive, otherwise, returns "0".
308 * This is a feature processor. A feature processor takes an item,
309 * performs some sort of processing on the item and returns an object.
311 public static class MonthRange implements FeatureProcessor {
314 * Performs some processing on the given item.
316 * @param item the item to process
318 * @return returns "1" if the given item is a number between 0
319 * and 32 (exclusive) otherwise returns "0"
321 * @throws ProcessException if an exception occurred during the
324 public String process(Item item) throws ProcessException {
325 int v = Integer.parseInt(item.getFeatures().getString("name"));
326 if ((v > 0) && (v < 32)) {
335 * Attempts to guess the part of speech.
336 * This is a feature processor. A feature processor takes an item,
337 * performs some sort of processing on the item and returns an object.
339 public static class TokenPosGuess implements FeatureProcessor {
341 * Performs some processing on the given item.
343 * @param item the item to process
345 * @return a guess at the part of speech
347 * @throws ProcessException if an exception occurred during the
350 public String process(Item item) throws ProcessException {
351 String name = item.getFeatures().getString("name");
352 String dc = name.toLowerCase();
353 if (DIGITS_PATTERN.matcher(dc).matches()) {
355 } else if (DOUBLE_PATTERN.matcher(dc).matches()) {
357 } else if (months.contains(dc)) {
359 } else if (days.contains(dc)) {
361 } else if (dc.equals("a")) {
363 } else if (dc.equals("flight")) {
365 } else if (dc.equals("to")) {
374 * Checks to see if the given syllable is accented.
375 * This is a feature processor. A feature processor takes an item,
376 * performs some sort of processing on the item and returns an object.
378 public static class Accented implements FeatureProcessor {
381 * Performs some processing on the given item.
382 * @param item the item to process
384 * @return "1" if the syllable is accented; otherwise "0"
386 * @throws ProcessException if an exception occurred during the
389 public String process(Item item) throws ProcessException {
390 if (isAccented(item)) {
399 * Find the last accented syllable
400 * This is a feature processor. A feature processor takes an item,
401 * performs some sort of processing on the item and returns an object.
403 public static class LastAccent implements FeatureProcessor {
406 * Performs some processing on the given item.
408 * @param item the item to process
410 * @return the count of the last accented syllable
412 * @throws ProcessException if an exception occurred during the
415 public String process(Item item) throws ProcessException {
418 for (Item p = item.getItemAs(Relation.SYLLABLE);
419 p != null; p = p.getPrevious(), count++) {
424 return Integer.toString(rail(count));
429 * Finds the position of the phoneme in the syllable
430 * This is a feature processor. A feature processor takes an item,
431 * performs some sort of processing on the item and returns an object.
433 public static class PosInSyl implements FeatureProcessor {
436 * Performs some processing on the given item.
438 * @param item the item to process
440 * @return the position of the phoneme in the syllable
442 * @throws ProcessException if an exception occurred during the
445 public String process(Item item) throws ProcessException {
448 for (Item p = item.getItemAs(Relation.SYLLABLE_STRUCTURE);
449 p != null; p = p.getPrevious() ) {
452 return Integer.toString(rail(count));
457 * Classifies the the syllable as single, initial, mid or final.
458 * This is a feature processor. A feature processor takes an item,
459 * performs some sort of processing on the item and returns an object.
461 public static class PositionType implements FeatureProcessor {
464 * Performs some processing on the given item.
466 * @param item the item to process
468 * @return classifies the syllable as "single", "final",
471 * @throws ProcessException if an exception occurred during the
474 public String process(Item item) throws ProcessException {
477 Item s = item.getItemAs(Relation.SYLLABLE_STRUCTURE);
480 } else if (s.getNext() == null) {
481 if (s.getPrevious() == null) {
486 } else if (s.getPrevious() == null) {
497 * Counts the number of stressed syllables since the last major break.
498 * This is a feature processor. A feature processor takes an item,
499 * performs some sort of processing on the item and returns an object.
501 public static class SylIn implements FeatureProcessor {
504 * Performs some processing on the given item.
506 * @param item the item to process
508 * @return the number of stressed syllables since the last
511 * @throws ProcessException if an exception occurred during the
514 public String process(Item item) throws ProcessException {
516 Item ss = item.getItemAs(Relation.SYLLABLE);
517 Item firstSyllable = FIRST_SYLLABLE_PATH.findItem(item);
519 for (Item p = ss; p != null; p = p.getPrevious(), count++ ) {
520 if (p.equalsShared(firstSyllable)) {
524 return Integer.toString(rail(count));
529 * Counts the number of stressed syllables since the last major break.
530 * This is a feature processor. A feature processor takes an item,
531 * performs some sort of processing on the item and returns an object.
533 public static class SylOut implements FeatureProcessor {
536 * Performs some processing on the given item.
538 * @param item the item to process
540 * @return the number of stressed syllables since the last
543 * @throws ProcessException if an exception occurred during the
546 public String process(Item item) throws ProcessException {
548 Item ss = item.getItemAs(Relation.SYLLABLE);
549 Item firstSyllable = LAST_LAST_SYLLABLE_PATH.findItem(item);
551 for (Item p = ss; p != null; p = p.getNext() ) {
552 if (p.equalsShared(firstSyllable)) {
557 return Integer.toString(rail(count));
563 * Determines the break level after this syllable
564 * This is a feature processor. A feature processor takes an item,
565 * performs some sort of processing on the item and returns an object.
567 public static class SylBreak implements FeatureProcessor {
570 * Performs some processing on the given item.
572 * @param syl the item to process
574 * @return the break level after this syllable
576 * @throws ProcessException if an exception occurred during the
579 public String process(Item syl) throws ProcessException {
580 Item ss = syl.getItemAs(Relation.SYLLABLE_STRUCTURE);
583 } else if (ss.getNext() != null) {
585 } else if (ss.getParent() == null) {
588 return wordBreak(ss.getParent());
596 * Determines the word break.
597 * This is a feature processor. A feature processor takes an item,
598 * performs some sort of processing on the item and returns an object.
600 public static class WordBreak implements FeatureProcessor {
603 * Performs some processing on the given item.
605 * @param word the item to process
607 * @return the break level for this word
609 * @throws ProcessException if an exception occurred during the
612 public String process(Item word) throws ProcessException {
613 return wordBreak(word);
618 * Determines the word punctuation.
619 * This is a feature processor. A feature processor takes an item,
620 * performs some sort of processing on the item and returns an object.
622 public static class WordPunc implements FeatureProcessor {
625 * Performs some processing on the given item.
627 * @param word the item to process
629 * @return the punctuation for this word
631 * @throws ProcessException if an exception occurred during the
634 public String process(Item word) throws ProcessException {
635 return wordPunc(word);
640 * Return consonant cplace
641 * l-labial a-alveolar p-palatal b-labio_dental d-dental v-velar
643 * This is a feature processor. A feature processor takes an item,
644 * performs some sort of processing on the item and returns an object.
646 public static class PH_CPlace implements FeatureProcessor {
649 * Performs some processing on the given item.
651 * @param item the item to process
653 * @return consonant cplace
655 * @throws ProcessException if an exception occurred during the
658 public String process(Item item) throws ProcessException {
659 return getPhoneFeature(item, "cplace");
664 * Return consonant type
665 * s-stop f-fricative a-affricative n-nasal * l-liquid
667 * This is a feature processor. A feature processor takes an item,
668 * performs some sort of processing on the item and returns an object.
670 public static class PH_CType implements FeatureProcessor {
673 * Performs some processing on the given item.
675 * @param item the item to process
677 * @return consonant type
679 * @throws ProcessException if an exception occurred during the
682 public String process(Item item) throws ProcessException {
683 return getPhoneFeature(item, "ctype");
688 * Return consonant voicing
691 * This is a feature processor. A feature processor takes an item,
692 * performs some sort of processing on the item and returns an object.
694 public static class PH_CVox implements FeatureProcessor {
697 * Performs some processing on the given item.
699 * @param item the item to process
701 * @return consonant voicing
703 * @throws ProcessException if an exception occurred during the
706 public String process(Item item) throws ProcessException {
707 return getPhoneFeature(item, "cvox");
712 * Return vowel or consonant
715 * This is a feature processor. A feature processor takes an item,
716 * performs some sort of processing on the item and returns an object.
718 public static class PH_VC implements FeatureProcessor {
721 * Performs some processing on the given item.
723 * @param item the item to process
725 * @return vowel or consonant
727 * @throws ProcessException if an exception occurred during the
730 public String process(Item item) throws ProcessException {
731 return getPhoneFeature(item, "vc");
736 * Return vowel frontness
737 * 1-front 2-mid 3-back
739 * This is a feature processor. A feature processor takes an item,
740 * performs some sort of processing on the item and returns an object.
742 public static class PH_VFront implements FeatureProcessor {
745 * Performs some processing on the given item.
747 * @param item the item to process
749 * @return vowel frontness
751 * @throws ProcessException if an exception occurred during the
754 public String process(Item item) throws ProcessException {
755 return getPhoneFeature(item, "vfront");
760 * Return vowel height
763 * This is a feature processor. A feature processor takes an item,
764 * performs some sort of processing on the item and returns an object.
766 public static class PH_VHeight implements FeatureProcessor {
769 * Performs some processing on the given item.
771 * @param item the item to process
773 * @return vowel height
775 * @throws ProcessException if an exception occurred during the
778 public String process(Item item) throws ProcessException {
779 return getPhoneFeature(item, "vheight");
785 * Return vowel length
786 * s-short l-long d-dipthong a-schwa
788 * This is a feature processor. A feature processor takes an item,
789 * performs some sort of processing on the item and returns an object.
791 public static class PH_VLength implements FeatureProcessor {
794 * Performs some processing on the given item.
796 * @param item the item to process
798 * @return vowel length
800 * @throws ProcessException if an exception occurred during the
803 public String process(Item item) throws ProcessException {
804 return getPhoneFeature(item, "vlng");
812 * Return vowel rnd (lip rounding)
813 * lip rounding +=on -=off
815 * This is a feature processor. A feature processor takes an item,
816 * performs some sort of processing on the item and returns an object.
818 public static class PH_VRnd implements FeatureProcessor {
821 * Performs some processing on the given item.
823 * @param item the item to process
827 * @throws ProcessException if an exception occurred during the
830 public String process(Item item) throws ProcessException {
831 return getPhoneFeature(item, "vrnd");
836 * Determines the onset size of this syllable
837 * This is a feature processor. A feature processor takes an item,
838 * performs some sort of processing on the item and returns an object.
840 public static class SylOnsetSize implements FeatureProcessor {
843 * Performs some processing on the given item.
845 * @param syl the item to process
847 * @return onset size of this syllable
849 * @throws ProcessException if an exception occurred during the
852 public String process(Item syl) throws ProcessException {
854 Item daughter = syl.getItemAs(
855 Relation.SYLLABLE_STRUCTURE).getDaughter();
856 while (daughter != null) {
857 if ("+".equals(getPhoneFeature(daughter, "vc"))) {
861 daughter = daughter.getNext();
863 return Integer.toString(rail(count));
869 * Determines the coda size
870 * This is a feature processor. A feature processor takes an item,
871 * performs some sort of processing on the item and returns an object.
873 public static class SylCodaSize implements FeatureProcessor {
876 * Performs some processing on the given item.
878 * @param syl the item to process
882 * @throws ProcessException if an exception occurred during the
885 public String process(Item syl) throws ProcessException {
887 Item daughter = syl.getItemAs(
888 Relation.SYLLABLE_STRUCTURE).getLastDaughter();
890 while (daughter != null) {
891 if ("+".equals(getPhoneFeature(daughter, "vc"))) {
895 daughter = daughter.getPrevious();
898 return Integer.toString(rail(count));
904 * Checks for fricative
905 * This is a feature processor. A feature processor takes an item,
906 * performs some sort of processing on the item and returns an object.
908 public static class SegCodaFric implements FeatureProcessor {
911 * Performs some processing on the given item.
913 * @param seg the item to process
915 * @return "1" if fricative; else "0"
917 * @throws ProcessException if an exception occurred during the
920 public String process(Item seg) throws ProcessException {
921 return segCodaCtype(seg, "f");
926 * Checks for fricative
927 * This is a feature processor. A feature processor takes an item,
928 * performs some sort of processing on the item and returns an object.
930 public static class SegOnsetFric implements FeatureProcessor {
933 * Performs some processing on the given item.
935 * @param seg the item to process
937 * @return "1" if fricative; else "0"
939 * @throws ProcessException if an exception occurred during the
942 public String process(Item seg) throws ProcessException {
943 return segOnsetCtype(seg, "f");
950 * Checks for coda stop
951 * This is a feature processor. A feature processor takes an item,
952 * performs some sort of processing on the item and returns an object.
954 public static class SegCodaStop implements FeatureProcessor {
957 * Performs some processing on the given item.
959 * @param seg the item to process
961 * @return if coda stop "1"; otherwise "0"
963 * @throws ProcessException if an exception occurred during the
966 public String process(Item seg) throws ProcessException {
967 return segCodaCtype(seg, "s");
972 * Checks for onset stop
973 * This is a feature processor. A feature processor takes an item,
974 * performs some sort of processing on the item and returns an object.
976 public static class SegOnsetStop implements FeatureProcessor {
979 * Performs some processing on the given item.
981 * @param seg the item to process
983 * @return if Onset Stop "1"; otherwise "0"
985 * @throws ProcessException if an exception occurred during the
988 public String process(Item seg) throws ProcessException {
989 return segOnsetCtype(seg, "s");
994 * Checks for coda nasal
995 * This is a feature processor. A feature processor takes an item,
996 * performs some sort of processing on the item and returns an object.
998 public static class SegCodaNasal implements FeatureProcessor {
1001 * Performs some processing on the given item.
1003 * @param seg the item to process
1005 * @return if coda stop "1"; otherwise "0"
1007 * @throws ProcessException if an exception occurred during the
1010 public String process(Item seg) throws ProcessException {
1011 return segCodaCtype(seg, "n");
1016 * Checks for onset nasal
1017 * This is a feature processor. A feature processor takes an item,
1018 * performs some sort of processing on the item and returns an object.
1020 public static class SegOnsetNasal implements FeatureProcessor {
1023 * Performs some processing on the given item.
1025 * @param seg the item to process
1027 * @return if Onset Stop "1"; otherwise "0"
1029 * @throws ProcessException if an exception occurred during the
1032 public String process(Item seg) throws ProcessException {
1033 return segOnsetCtype(seg, "n");
1038 * Checks for coda glide
1039 * This is a feature processor. A feature processor takes an item,
1040 * performs some sort of processing on the item and returns an object.
1042 public static class SegCodaGlide implements FeatureProcessor {
1045 * Performs some processing on the given item.
1047 * @param seg the item to process
1049 * @return if coda stop "1"; otherwise "0"
1051 * @throws ProcessException if an exception occurred during the
1054 public String process(Item seg) throws ProcessException {
1055 if (segCodaCtype(seg, "r").equals("0")) {
1056 return segCodaCtype(seg, "l");
1063 * Checks for onset glide
1064 * This is a feature processor. A feature processor takes an item,
1065 * performs some sort of processing on the item and returns an object.
1067 public static class SegOnsetGlide implements FeatureProcessor {
1070 * Performs some processing on the given item.
1072 * @param seg the item to process
1074 * @return if coda stop "1"; otherwise "0"
1076 * @throws ProcessException if an exception occurred during the
1079 public String process(Item seg) throws ProcessException {
1080 if (segOnsetCtype(seg, "r").equals("0")) {
1081 return segOnsetCtype(seg, "l");
1089 * Checks for onset coda
1090 * This is a feature processor. A feature processor takes an item,
1091 * performs some sort of processing on the item and returns an object.
1093 public static class SegOnsetCoda implements FeatureProcessor {
1096 * Performs some processing on the given item.
1098 * @param seg the item to process
1100 * @return if onset coda "1"; otherwise "0"
1102 * @throws ProcessException if an exception occurred during the
1105 public String process(Item seg) throws ProcessException {
1106 Item s = seg.getItemAs(Relation.SYLLABLE_STRUCTURE);
1113 if ("+".equals(getPhoneFeature(s, "vc"))) {
1125 * Counts the number of phrases before this one.
1126 * This is a feature processor. A feature processor takes an item,
1127 * performs some sort of processing on the item and returns an object.
1129 public static class SubPhrases implements FeatureProcessor {
1132 * Performs some processing on the given item.
1134 * @param item the item to process
1136 * @return the number of phrases before this one
1138 * @throws ProcessException if an exception occurred during the
1141 public String process(Item item) throws ProcessException {
1143 Item inPhrase = SUB_PHRASE_PATH.findItem(item);
1145 for (Item p = inPhrase; p != null; p = p.getPrevious() ) {
1148 return Integer.toString(rail(count));
1153 * Returns the duration of the given segment
1154 * This is a feature processor. A feature processor takes an item,
1155 * performs some sort of processing on the item and returns an object.
1157 public static class SegmentDuration implements FeatureProcessor {
1160 * Performs some processing on the given item.
1162 * @param seg the item to process
1164 * @return the duration of the segment as a string.
1166 * @throws ProcessException if an exception occurred during the
1169 public String process(Item seg) throws ProcessException {
1172 } else if (seg.getPrevious() == null) {
1173 return seg.getFeatures().getObject("end").toString();
1175 return Float.toString(
1176 seg.getFeatures().getFloat("end") -
1177 seg.getPrevious().getFeatures().getFloat("end")
1184 * Gets the phoneset feature with the given name
1186 * @param item item the phoneme of interest
1187 * @param featureName the feature of interest
1189 * @return the phone feature for the item
1193 public static String getPhoneFeature(Item item, String featureName) {
1194 Voice voice = item.getUtterance().getVoice();
1195 String feature = voice.getPhoneFeature(item.toString(), featureName);
1200 * Classifies the type of word break
1202 * @param item the item to process
1204 * @return "4" for a big break, "3" for a break; otherwise "1"
1206 * @throws ProcessException if an exception occurred during the
1209 public static String wordBreak(Item item) throws ProcessException {
1210 Item ww = item.getItemAs(Relation.PHRASE);
1211 if (ww == null || ww.getNext() != null) {
1214 String pname = ww.getParent().toString();
1215 if (pname.equals("BB")) {
1217 } else if (pname.equals("B")) {
1226 * Gets the punctuation associated with the word
1228 * @param item the word to process
1230 * @return the punctuation associated with the word
1232 * @throws ProcessException if an exception occurred during the
1235 public static String wordPunc(Item item) throws ProcessException {
1236 Item ww = item.getItemAs(Relation.TOKEN);
1237 if (ww != null && ww.getNext() != null) {
1240 if (ww != null && ww.getParent() != null) {
1241 return ww.getParent().getFeatures().getString("punc");
1249 * Tests the coda ctype of the given segment.
1251 * @param seg the segment to test
1252 * @param ctype the ctype to check for
1254 * @return "1" on match "0" on no match
1256 private static String segCodaCtype(Item seg, String ctype) {
1259 Relation.SYLLABLE_STRUCTURE).getParent().getLastDaughter();
1261 while (daughter != null) {
1262 if ("+".equals(getPhoneFeature(daughter, "vc"))) {
1265 if (ctype.equals(getPhoneFeature(daughter, "ctype"))) {
1269 daughter = daughter.getPrevious();
1275 * Tests the onset ctype of the given segment.
1277 * @param seg the segment to test to process
1278 * @param ctype the ctype to check for
1280 * @return if Onset Stop "1"; otherwise "0"
1283 private static String segOnsetCtype(Item seg, String ctype) {
1284 Item daughter = seg.getItemAs(
1285 Relation.SYLLABLE_STRUCTURE).getParent().getDaughter();
1287 while (daughter != null) {
1288 if ("+".equals(getPhoneFeature(daughter, "vc"))) {
1291 if (ctype.equals(getPhoneFeature(daughter, "ctype"))) {
1295 daughter = daughter.getNext();
1301 * Determines if the given item is accented
1303 * @param item the item of interest
1305 * @return <code>true</code> if the item is accented, otherwise
1306 * <code>false</code>
1308 private static boolean isAccented(Item item) {
1309 return (item.getFeatures().isPresent("accent") ||
1310 item.getFeatures().isPresent("endtone"));
1314 * Rails an int. flite never returns an int more than 19 from
1315 * a feature processor, we duplicate that behavior
1316 * here so that our tests will match.
1318 * @param val the value to rail
1320 * @return val clipped to be betweein 0 and 19
1322 private static int rail(int val) {
1323 return val > 19 ? 19 : val;