001/** 002 * Portions Copyright 2001 Sun Microsystems, Inc. 003 * Portions Copyright 1999-2001 Language Technologies Institute, 004 * Carnegie Mellon University. 005 * All Rights Reserved. Use is subject to license terms. 006 * 007 * See the file "license.terms" for information on usage and 008 * redistribution of this file, and for a DISCLAIMER OF ALL 009 * WARRANTIES. 010 */ 011package com.sun.speech.freetts.en.us; 012 013import com.sun.speech.freetts.diphone.DiphonePitchmarkGenerator; 014import com.sun.speech.freetts.diphone.DiphoneUnitSelector; 015import com.sun.speech.freetts.Item; 016import com.sun.speech.freetts.ProcessException; 017import com.sun.speech.freetts.Relation; 018import com.sun.speech.freetts.relp.UnitConcatenator; 019import com.sun.speech.freetts.Utterance; 020import com.sun.speech.freetts.UtteranceProcessor; 021import com.sun.speech.freetts.Voice; 022 023import com.sun.speech.freetts.Gender; 024import com.sun.speech.freetts.Age; 025 026import de.dfki.lt.freetts.ConcatenativeVoice; 027 028import java.util.Locale; 029 030import java.io.IOException; 031 032import java.net.URL; 033 034 035/** 036 * Defines an unlimited-domain diphone synthesis based voice 037 */ 038public class CMUDiphoneVoice extends CMUVoice implements ConcatenativeVoice { 039 040 protected URL database; 041 042 /** 043 * Creates a simple voice. This is merely for backwards 044 * compatibility with versions of FreeTTS earlier than v1.2 045 * (i.e., before the voice manager was introduced). 046 */ 047 public CMUDiphoneVoice() { 048 this(null, null, null, null, null, null, null, null, null); 049 } 050 051 /** 052 * Creates a simple voice 053 * 054 * @param name the name of the voice 055 * @param gender the gender of the voice 056 * @param age the age of the voice 057 * @param description a human-readable string providing a 058 * description that can be displayed for the users. 059 * @param locale the locale of the voice 060 * @param domain the domain of this voice. For example, 061 * @param organization the organization which created the voice 062 * "general", "time", or 063 * "weather". 064 * @param lexicon the lexicon to load 065 * @param database a url to the unit database file for this voice 066 */ 067 public CMUDiphoneVoice(String name, Gender gender, 068 Age age, String description, Locale locale, String domain, 069 String organization, CMULexicon lexicon, URL database) { 070 super(name, gender, age, description, locale, 071 domain, organization, lexicon); 072 setRate(150f); 073 setPitch(100F); 074 setPitchRange(11F); 075 this.database = database; 076 } 077 078 /** 079 * Gets the url to the database that defines the unit data for this 080 * voice. 081 * 082 * @return a url to the database 083 */ 084 public URL getDatabase() { 085 if (database == null) { 086 /* This is merely for backwards compatibility with 087 * versions of FreeTTS earlier than v1.2 (i.e., 088 * before the voice manager was introduced). 089 */ 090 String name = getFeatures().getString(Voice.DATABASE_NAME); 091 database = this.getClass().getResource(name); 092 } 093 return database; 094 } 095 096 /** 097 * Sets the FeatureSet for this Voice. 098 * 099 * @throws IOException if an I/O error occurs 100 */ 101 protected void setupFeatureSet() throws IOException { 102 super.setupFeatureSet(); 103 } 104 105 /** 106 * Returns the post lexical processor to be used by this voice. 107 * Derived voices typically override this to customize behaviors. 108 * 109 * @return the Unit selector 110 * 111 * @throws IOException if an IO error occurs while getting 112 * processor 113 */ 114 protected UtteranceProcessor getPostLexicalAnalyzer() throws IOException { 115 return new CMUDiphoneVoicePostLexicalAnalyzer(); 116 } 117 118 /** 119 * Returns the pitch mark generator to be used by this voice. 120 * Derived voices typically override this to customize behaviors. 121 * This voice uses a DiphonePitchMark generator to generate 122 * pitchmarks. 123 * 124 * @return the pitchmark processor 125 * 126 * @throws IOException if an IO error occurs while getting 127 * processor 128 */ 129 public UtteranceProcessor getPitchmarkGenerator() throws IOException { 130 return new DiphonePitchmarkGenerator(); 131 } 132 133 /** 134 * Returns the unit concatenator to be used by this voice. 135 * Derived voices typically override this to customize behaviors. 136 * This voice uses a relp.UnitConcatenator to concatenate units. 137 * 138 * @return the unit concatenator processor 139 * 140 * @throws IOException if an IO error occurs while getting 141 * processor 142 */ 143 public UtteranceProcessor getUnitConcatenator() throws IOException { 144 return new UnitConcatenator(); 145 } 146 147 148 /** 149 * Returns the unit selector to be used by this voice. 150 * Derived voices typically override this to customize behaviors. 151 * This voice uses the DiphoneUnitSelector to select units. The 152 * unit selector requires the name of a diphone database. If no 153 * diphone database has been specified then an Error is thrown. 154 * 155 * @return the unit selector processor 156 * 157 * @throws IOException if an IO error occurs while getting 158 * processor 159 */ 160 public UtteranceProcessor getUnitSelector() throws IOException { 161 return new DiphoneUnitSelector(getDatabase()); 162 } 163 164 165 /** 166 * Converts this object to a string 167 * 168 * @return a string representation of this object 169 */ 170 public String toString() { 171 return "CMUDiphoneVoice"; 172 } 173} 174 175 176/** 177 * Annotates the utterance with post lexical information. Converts AH 178 * phonemes to AA phoneme in addition to the standard english postlex 179 * processing. 180 */ 181class CMUDiphoneVoicePostLexicalAnalyzer implements UtteranceProcessor { 182 UtteranceProcessor englishPostLex = 183 new com.sun.speech.freetts.en.PostLexicalAnalyzer(); 184 185 /** 186 * performs the processing 187 * @param utterance the utterance to process/tokenize 188 * @throws ProcessException if an IOException is thrown during the 189 * processing of the utterance 190 */ 191 public void processUtterance(Utterance utterance) throws ProcessException { 192 fixPhoneme_AH(utterance); 193 englishPostLex.processUtterance(utterance); 194 } 195 196 197 /** 198 * Turns all AH phonemes into AA phonemes. 199 * This should really be done in the index itself 200 * @param utterance the utterance to fix 201 */ 202 private void fixPhoneme_AH(Utterance utterance) { 203 for (Item item = utterance.getRelation(Relation.SEGMENT).getHead(); 204 item != null; 205 item = item.getNext()) { 206 if (item.getFeatures().getString("name").equals("ah")) { 207 item.getFeatures().setString("name", "aa"); 208 } 209 } 210 } 211 212 // inherited from Object 213 public String toString() { 214 return "PostLexicalAnalyzer"; 215 } 216}