/**
* Portions Copyright 2004 DFKI GmbH.
* Portions Copyright 2001 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 de.dfki.lt.freetts;
import java.io.IOException;
import java.net.URL;
import java.util.Locale;
import com.sun.speech.freetts.Age;
import com.sun.speech.freetts.Gender;
import com.sun.speech.freetts.PartOfSpeech;
import com.sun.speech.freetts.PartOfSpeechImpl;
import com.sun.speech.freetts.PhoneSet;
import com.sun.speech.freetts.PhoneSetImpl;
import com.sun.speech.freetts.Tokenizer;
import com.sun.speech.freetts.UtteranceProcessor;
import com.sun.speech.freetts.Voice;
import com.sun.speech.freetts.diphone.DiphonePitchmarkGenerator;
import com.sun.speech.freetts.diphone.DiphoneUnitSelector;
import com.sun.speech.freetts.en.us.CMULexicon;
import com.sun.speech.freetts.en.us.FeatureProcessors;
import com.sun.speech.freetts.lexicon.Lexicon;
import com.sun.speech.freetts.relp.AudioOutput;
import com.sun.speech.freetts.relp.SampleInfo;
import com.sun.speech.freetts.relp.UnitConcatenator;
/**
* A simple dummy voice as a starting point for non-US-English
* cluster unit voices. All NLP stuff would need to be implemented
* in order for this to become a full TTS voice.
*/
public class DiphoneVoice extends Voice implements ConcatenativeVoice {
private PhoneSet phoneSet;
protected URL database;
protected URL phonesetURL;
protected URL partOfSpeechURL;
protected DiphoneUnitSelector unitSelector;
public DiphoneVoice(String name, Gender gender, Age age,
String description, Locale locale, String domain,
String organization, Lexicon lexicon, URL database) {
this(name, gender, age, description, locale, domain,
organization, lexicon, database, null, null);
}
/**
* Creates a ClusterUnitVoice
*
* @param database the database of the voice
* @param unitNamer specifies the name of the Units (if null, an
* ldom naming scheme will be used: 'ae_afternoon')
* @param phonesetURL leads to the phoneset, which will be used
* for the FeatureProcessors (can be null)
* @param partOfSpeechURL leads to the pos-textfile which will be used
* for the FeatureProcessors (can be null)
*/
public DiphoneVoice(String name, Gender gender, Age age,
String description, Locale locale, String domain,
String organization, Lexicon lexicon, URL database,
URL phonesetURL, URL partOfSpeechURL) {
//TODO: do something useful with the lexicon
super(name, gender, age, description, locale,
domain, organization);
// Set default prosody values:
setRate(150f);
setPitch(100F);
setPitchRange(12F);
if (lexicon != null) {
setLexicon(lexicon);
} else {
// Use a small dummy lexicon
setLexicon(new CMULexicon("cmutimelex"));
}
this.database = database;
this.phonesetURL = phonesetURL;
this.partOfSpeechURL = partOfSpeechURL;
try {
this.unitSelector = new DiphoneUnitSelector(getDatabase());
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
public Tokenizer getTokenizer() {
return null;
}
protected void loader() throws IOException {
setupFeatureProcessors();
}
/**
* Get the sample info for the underlying database.
* @return the sample info object
*/
public SampleInfo getSampleInfo() {
return unitSelector.getSampleInfo();
}
protected UtteranceProcessor getAudioOutput() throws IOException {
return new AudioOutput();
}
/**
* Gets the url to the database that defines the unit data for this
* voice.
*
* @return a url to the database
*/
public URL getDatabase() {
return database;
}
/**
* Returns the unit selector to be used by this voice.
* Derived voices typically override this to customize behaviors.
* This voice uses a diphone selector as the unit selector.
*
* @return the post lexical processor
*
* @throws IOException if an IO error occurs while getting
* processor
*/
public UtteranceProcessor getUnitSelector() throws IOException {
return unitSelector;
}
/**
* Returns the pitch mark generator to be used by this voice.
* Derived voices typically override this to customize behaviors.
* There is no default unit selector
*
* @return the post lexical processor
*
* @throws IOException if an IO error occurs while getting
* processor
*/
public UtteranceProcessor getPitchmarkGenerator() throws IOException {
return new DiphonePitchmarkGenerator();
}
/**
* Returns the unit concatenator to be used by this voice.
* Derived voices typically override this to customize behaviors.
* There is no default unit selector
*
* @return the post lexical processor
*
* @throws IOException if an IO error occurs while getting
* processor
*/
public UtteranceProcessor getUnitConcatenator() throws IOException {
return new UnitConcatenator();
}
protected void setupFeatureProcessors() throws IOException {
if (phonesetURL != null) {
phoneSet = new PhoneSetImpl(phonesetURL);
}
if (partOfSpeechURL != null) {
PartOfSpeech pos = new PartOfSpeechImpl(partOfSpeechURL, "content");
addFeatureProcessor("gpos", new FeatureProcessors.Gpos(pos));
}
addFeatureProcessor("word_break", new FeatureProcessors.WordBreak());
addFeatureProcessor("word_punc", new FeatureProcessors.WordPunc());
addFeatureProcessor("word_numsyls",new FeatureProcessors.WordNumSyls());
addFeatureProcessor("ssyl_in", new FeatureProcessors.StressedSylIn());
addFeatureProcessor("syl_in", new FeatureProcessors.SylIn());
addFeatureProcessor("syl_out", new FeatureProcessors.SylOut());
addFeatureProcessor("ssyl_out", new
FeatureProcessors.StressedSylOut());
addFeatureProcessor("syl_break", new FeatureProcessors.SylBreak());
addFeatureProcessor("old_syl_break", new FeatureProcessors.SylBreak());
addFeatureProcessor("num_digits", new FeatureProcessors.NumDigits());
addFeatureProcessor("month_range", new FeatureProcessors.MonthRange());
addFeatureProcessor("token_pos_guess",
new FeatureProcessors.TokenPosGuess());
addFeatureProcessor("segment_duration",
new FeatureProcessors.SegmentDuration());
addFeatureProcessor("sub_phrases", new FeatureProcessors.SubPhrases());
addFeatureProcessor("asyl_in", new FeatureProcessors.AccentedSylIn());
addFeatureProcessor("last_accent", new FeatureProcessors.LastAccent());
addFeatureProcessor("pos_in_syl", new FeatureProcessors.PosInSyl());
addFeatureProcessor("position_type", new
FeatureProcessors.PositionType());
addFeatureProcessor("ph_cplace", new FeatureProcessors.PH_CPlace());
addFeatureProcessor("ph_ctype", new FeatureProcessors.PH_CType());
addFeatureProcessor("ph_cvox", new FeatureProcessors.PH_CVox());
addFeatureProcessor("ph_vc", new FeatureProcessors.PH_VC());
addFeatureProcessor("ph_vfront", new FeatureProcessors.PH_VFront());
addFeatureProcessor("ph_vheight", new FeatureProcessors.PH_VHeight());
addFeatureProcessor("ph_vlng", new FeatureProcessors.PH_VLength());
addFeatureProcessor("ph_vrnd", new FeatureProcessors.PH_VRnd());
addFeatureProcessor("seg_coda_fric", new
FeatureProcessors.SegCodaFric());
addFeatureProcessor("seg_onset_fric", new
FeatureProcessors.SegOnsetFric());
addFeatureProcessor("seg_coda_stop", new
FeatureProcessors.SegCodaStop());
addFeatureProcessor("seg_onset_stop", new
FeatureProcessors.SegOnsetStop());
addFeatureProcessor("seg_coda_nasal", new
FeatureProcessors.SegCodaNasal());
addFeatureProcessor("seg_onset_nasal", new
FeatureProcessors.SegOnsetNasal());
addFeatureProcessor("seg_coda_glide", new
FeatureProcessors.SegCodaGlide());
addFeatureProcessor("seg_onset_glide", new
FeatureProcessors.SegOnsetGlide());
addFeatureProcessor("seg_onsetcoda", new
FeatureProcessors.SegOnsetCoda());
addFeatureProcessor("syl_codasize", new
FeatureProcessors.SylCodaSize());
addFeatureProcessor("syl_onsetsize", new
FeatureProcessors.SylOnsetSize());
addFeatureProcessor("accented", new FeatureProcessors.Accented());
}
/**
* Given a phoneme and a feature name, return the feature
*
* @param phone the phoneme of interest
* @param featureName the name of the feature of interest
*
* @return the feature with the given name
*/
public String getPhoneFeature(String phone, String featureName) {
if (phoneSet != null)
return phoneSet.getPhoneFeature(phone, featureName);
else
return null;
}
}