001/**
002 * Portions Copyright 2003 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 java.io.IOException;
014import java.util.List;
015import java.util.Locale;
016
017import com.sun.speech.freetts.Age;
018import com.sun.speech.freetts.FeatureSet;
019import com.sun.speech.freetts.Gender;
020import com.sun.speech.freetts.PartOfSpeech;
021import com.sun.speech.freetts.PartOfSpeechImpl;
022import com.sun.speech.freetts.PhoneDurations;
023import com.sun.speech.freetts.PhoneDurationsImpl;
024import com.sun.speech.freetts.PhoneSet;
025import com.sun.speech.freetts.PhoneSetImpl;
026import com.sun.speech.freetts.Segmenter;
027import com.sun.speech.freetts.Tokenizer;
028import com.sun.speech.freetts.UtteranceProcessor;
029import com.sun.speech.freetts.Voice;
030import com.sun.speech.freetts.cart.CARTImpl;
031import com.sun.speech.freetts.cart.Durator;
032import com.sun.speech.freetts.cart.Intonator;
033import com.sun.speech.freetts.cart.Phraser;
034import com.sun.speech.freetts.en.ContourGenerator;
035import com.sun.speech.freetts.en.PartOfSpeechTagger;
036import com.sun.speech.freetts.en.PauseGenerator;
037import com.sun.speech.freetts.relp.AudioOutput;
038import com.sun.speech.freetts.util.BulkTimer;
039
040/**
041 * Provides generic support for a CMU Voice
042 */
043public abstract class CMUVoice extends Voice {
044    private PhoneSet phoneSet;
045
046    /**
047     * Creates a simple voice
048     *
049     * @param name the name of the voice
050     * @param gender the gender of the voice
051     * @param age the age of the voice
052     * @param description a human-readable string providing a
053     * description that can be displayed for the users.
054     * @param locale the locale of the voice
055     * @param domain the domain of this voice.  For example,
056     * @param organization the organization which created the voice
057     * "general", "time", or
058     * "weather".
059     * @param lexicon the lexicon to load
060     */
061    public CMUVoice(String name, Gender gender,
062            Age age, String description, Locale locale, String domain,
063            String organization, CMULexicon lexicon) {
064        super(name, gender, age, description, locale, domain,
065                organization);
066        setLexicon(lexicon);
067    }
068
069    // overrides Voice.loader
070
071    /**
072     * Called by <code> Voice </code>  during loading, derived voices
073     * should override this to provide customized loading.
074     */
075    protected void loader() throws IOException {
076        setupFeatureSet();
077        setupUtteranceProcessors();
078        setupFeatureProcessors();
079    }
080
081    /**
082     * Sets up the FeatureSet for this Voice.
083     *
084     * @throws IOException if an I/O error occurs
085     */
086    protected void setupFeatureSet() throws IOException {
087        BulkTimer.LOAD.start("FeatureSet");
088        FeatureSet features = getFeatures();
089        features.setString(FEATURE_SILENCE, "pau");
090        features.setString("join_type", "simple_join");
091        BulkTimer.LOAD.stop("FeatureSet");
092    }
093
094
095    /**
096     * Sets up the utterance processors for this voice. Subclasses
097     * should define this method to setup the utterance processors for
098     * the voice.
099     *
100     * @throws IOException throws an IOException if an error occurs
101     */
102    protected void setupUtteranceProcessors() throws IOException {
103        List<UtteranceProcessor> processors = getUtteranceProcessors();
104
105        BulkTimer.LOAD.start("CartLoading");
106        CARTImpl numbersCart = new CARTImpl(getResource("nums_cart.txt"));
107        CARTImpl phrasingCart = new CARTImpl(getResource("phrasing_cart.txt"));
108        CARTImpl accentCart = new CARTImpl(getResource("int_accent_cart.txt"));
109        CARTImpl toneCart = new CARTImpl(getResource("int_tone_cart.txt"));
110        CARTImpl durzCart = new CARTImpl(getResource("durz_cart.txt"));
111        BulkTimer.LOAD.stop("CartLoading");
112
113        BulkTimer.LOAD.start("UtteranceProcessors");
114        PhoneDurations phoneDurations = new PhoneDurationsImpl(
115            getResource("dur_stat.txt"));
116        PronounceableFSM prefixFSM = new PrefixFSM
117            (getResource("prefix_fsm.txt"));
118        PronounceableFSM suffixFSM = new SuffixFSM
119            (getResource("suffix_fsm.txt"));
120        
121        processors.add(new TokenToWords(numbersCart, prefixFSM, suffixFSM));
122        processors.add(new PartOfSpeechTagger());
123        processors.add(new Phraser(phrasingCart));
124        processors.add(new Segmenter());
125        processors.add(new PauseGenerator());
126        processors.add(new Intonator(accentCart, toneCart));
127        processors.add(getPostLexicalAnalyzer());
128        processors.add(new Durator(durzCart, phoneDurations));
129        processors.add(new ContourGenerator
130           (getResource("f0_lr_terms.txt"), 170.0f, 34.0f));
131
132
133        processors.add(getUnitSelector());
134        processors.add(getPitchmarkGenerator());
135        processors.add(getUnitConcatenator());
136        BulkTimer.LOAD.stop("UtteranceProcessors");
137    }
138
139    // [[[TODO: currently a CMUVoice only allows customization of
140    // the postlex, unit selector and wave synthesizer. This may 
141    // grow as time goes on ]]]
142    /**
143     * Returns the post lexical processor to be used by this voice.
144     * Derived voices typically override this to customize behaviors.
145     * 
146     * @return the post lexical analyzer in use by this voice
147     * 
148     * @throws IOException if an IO error occurs while getting
149     *     processor
150     */
151    protected UtteranceProcessor getPostLexicalAnalyzer() throws IOException {
152        return new com.sun.speech.freetts.en.PostLexicalAnalyzer();
153    }
154
155    /**
156     * Returns the unit selector to be used by this voice
157     * Derived voices typically override this to customize behaviors.
158     * 
159     * @return the unit selector in use by this voice
160     * 
161     * @throws IOException if an IO error occurs while getting
162     *     processor
163     */
164    protected UtteranceProcessor getUnitSelector() throws IOException {
165        return null;
166    }
167
168    /**
169     * Returns the pitch mark generator to be used by this voice
170     * Derived voices typically override this to customize behaviors.
171     * 
172     * @return the pitch mark generator to be used by this voice
173     * 
174     * @throws IOException if an IO error occurs while getting
175     *     processor
176     */
177    protected UtteranceProcessor getPitchmarkGenerator() throws IOException {
178        return null;
179    }
180
181    /**
182     * Returns the unit concatenator to be used by this voice
183     * Derived voices typically override this to customize behaviors.
184     * 
185     * @return the Unit concatenator
186     * 
187     * @throws IOException if an IO error occurs while getting
188     *     processor
189     */
190    protected UtteranceProcessor getUnitConcatenator() throws IOException {
191        return null;
192    }
193
194    
195    /**
196     * Sets up the FeatureProcessors for this Voice.
197     *
198     * @throws IOException if an I/O error occurs
199     */
200    protected void setupFeatureProcessors() throws IOException {
201        BulkTimer.LOAD.start("FeatureProcessing");
202        PartOfSpeech pos = new PartOfSpeechImpl( 
203            getResource("part_of_speech.txt"),
204            "content");
205
206        phoneSet  = new PhoneSetImpl(getResource("phoneset.txt"));
207
208        addFeatureProcessor("word_break", new FeatureProcessors.WordBreak());
209        addFeatureProcessor("word_punc", new FeatureProcessors.WordPunc());
210        addFeatureProcessor("gpos", new FeatureProcessors.Gpos(pos));
211        addFeatureProcessor("word_numsyls",new FeatureProcessors.WordNumSyls());
212        addFeatureProcessor("ssyl_in", new FeatureProcessors.StressedSylIn());
213        addFeatureProcessor("syl_in", new FeatureProcessors.SylIn());
214        addFeatureProcessor("syl_out", new FeatureProcessors.SylOut());
215        addFeatureProcessor("ssyl_out", new
216                FeatureProcessors.StressedSylOut());
217        addFeatureProcessor("syl_break", new FeatureProcessors.SylBreak());
218        addFeatureProcessor("old_syl_break", new FeatureProcessors.SylBreak());
219        addFeatureProcessor("num_digits", new FeatureProcessors.NumDigits());
220        addFeatureProcessor("month_range", new FeatureProcessors.MonthRange());
221        addFeatureProcessor("token_pos_guess", 
222                new FeatureProcessors.TokenPosGuess());
223        addFeatureProcessor("segment_duration", 
224                new FeatureProcessors.SegmentDuration());
225        addFeatureProcessor("sub_phrases", new FeatureProcessors.SubPhrases());
226        addFeatureProcessor("asyl_in", new FeatureProcessors.AccentedSylIn());
227        addFeatureProcessor("last_accent", new FeatureProcessors.LastAccent());
228        addFeatureProcessor("pos_in_syl", new FeatureProcessors.PosInSyl());
229        addFeatureProcessor("position_type", new
230                FeatureProcessors.PositionType());
231
232        addFeatureProcessor("ph_cplace", new FeatureProcessors.PH_CPlace());
233        addFeatureProcessor("ph_ctype", new FeatureProcessors.PH_CType());
234        addFeatureProcessor("ph_cvox", new FeatureProcessors.PH_CVox());
235        addFeatureProcessor("ph_vc", new FeatureProcessors.PH_VC());
236        addFeatureProcessor("ph_vfront", new FeatureProcessors.PH_VFront());
237        addFeatureProcessor("ph_vheight", new FeatureProcessors.PH_VHeight());
238        addFeatureProcessor("ph_vlng", new FeatureProcessors.PH_VLength());
239        addFeatureProcessor("ph_vrnd", new FeatureProcessors.PH_VRnd());
240
241        addFeatureProcessor("seg_coda_fric", new
242                FeatureProcessors.SegCodaFric());
243        addFeatureProcessor("seg_onset_fric", new
244                FeatureProcessors.SegOnsetFric());
245
246        addFeatureProcessor("seg_coda_stop", new
247                FeatureProcessors.SegCodaStop());
248        addFeatureProcessor("seg_onset_stop", new
249                FeatureProcessors.SegOnsetStop());
250
251        addFeatureProcessor("seg_coda_nasal", new
252                FeatureProcessors.SegCodaNasal());
253        addFeatureProcessor("seg_onset_nasal", new
254                FeatureProcessors.SegOnsetNasal());
255
256        addFeatureProcessor("seg_coda_glide", new
257                FeatureProcessors.SegCodaGlide());
258        addFeatureProcessor("seg_onset_glide", new
259                FeatureProcessors.SegOnsetGlide());
260
261        addFeatureProcessor("seg_onsetcoda", new
262                FeatureProcessors.SegOnsetCoda());
263        addFeatureProcessor("syl_codasize", new
264                FeatureProcessors.SylCodaSize());
265        addFeatureProcessor("syl_onsetsize", new
266                FeatureProcessors.SylOnsetSize());
267        addFeatureProcessor("accented", new FeatureProcessors.Accented());
268        BulkTimer.LOAD.stop("FeatureProcessing");
269    }
270    
271    /**
272     * Given a phoneme and a feature name, return the feature
273     *
274     * @param phone the phoneme of interest
275     * @param featureName the name of the feature of interest
276     *
277     * @return the feature with the given name
278     */
279    public String getPhoneFeature(String phone, String featureName) {
280        return phoneSet.getPhoneFeature(phone, featureName);
281    }
282
283    /**
284     * Returns the AudioOutput processor to be used by this voice
285     * Derived voices typically override this to customize behaviors.
286     * 
287     * @return the audio output processor
288     * 
289     * @throws IOException if an IO error occurs while getting
290     *     processor
291     */
292    protected UtteranceProcessor getAudioOutput() throws IOException {
293        return new AudioOutput();
294    }
295
296    /**
297     * Gets a tokenizer for this voice
298     *
299     * @return the tokenizer
300     */
301    public Tokenizer getTokenizer() {
302        Tokenizer tokenizer = new com.sun.speech.freetts.en.TokenizerImpl();
303        tokenizer.setWhitespaceSymbols(USEnglish.WHITESPACE_SYMBOLS);
304        tokenizer.setSingleCharSymbols(USEnglish.SINGLE_CHAR_SYMBOLS);
305        tokenizer.setPrepunctuationSymbols(USEnglish.PREPUNCTUATION_SYMBOLS);
306        tokenizer.setPostpunctuationSymbols(USEnglish.PUNCTUATION_SYMBOLS);
307        return tokenizer;
308    }
309
310    /**
311     * Converts this object to its String representation
312     *
313     * @return the string representation of this object
314     */
315    public String toString() {
316        return "CMUVoice";
317    }
318}
319