001/**
002 * Copyright 2002 DFKI GmbH.
003 * Portions Copyright 2002 Sun Microsystems, Inc.
004 * All Rights Reserved.  Use is subject to license terms.
005 *
006 * See the file "license.terms" for information on usage and
007 * redistribution of this file, and for a DISCLAIMER OF ALL
008 * WARRANTIES.
009 */
010
011package de.dfki.lt.freetts.en.us;
012
013import java.io.File;
014import java.io.IOException;
015import java.net.URL;
016import java.util.Locale;
017
018import com.sun.speech.freetts.Age;
019import com.sun.speech.freetts.Gender;
020import com.sun.speech.freetts.UtteranceProcessor;
021import com.sun.speech.freetts.en.us.CMULexicon;
022import com.sun.speech.freetts.en.us.CMUVoice;
023import com.sun.speech.freetts.util.Utilities;
024
025import de.dfki.lt.freetts.mbrola.MbrolaAudioOutput;
026import de.dfki.lt.freetts.mbrola.MbrolaCaller;
027import de.dfki.lt.freetts.mbrola.ParametersToMbrolaConverter;
028
029/**
030 * Defines an unlimited-domain diphone synthesis based voice using
031 * the MBROLA synthesis.
032 */
033public class MbrolaVoice extends CMUVoice {
034
035    private String databaseDirectory; // where the voice database is
036    private String database;          // name of the voice database
037
038    private static final String MRPA_TO_SAMPA_RENAME_LIST =
039        "V ah i iy I ih U uh { ae @ ax r= er A aa O ao u uw E eh EI ey AI ay OI oy aU aw @U ow j y h hh N ng S sh T th Z zh D dh tS ch dZ jh _ pau";
040    
041    /**
042     * Creates an MbrolaVoice.
043     *
044     * @param databaseDirectory the directory within the MBROLA directory
045     *    where the voice database of this voice is located
046     * @param database the name of the voice database of this voice
047     * @param rate the rate of the voice
048     * @param pitch the pitch of the voice
049     * @param range the range of the voice
050     * @param name the name of the voice
051     * @param gender the gender of the voice
052     * @param age the age of the voice
053     * @param description a human-readable string providing a
054     * description that can be displayed for the users.
055     * @param locale the locale of the voice
056     * @param domain the domain of this voice.  For example,
057     * @param organization the organization which created the voice
058     * @param lexicon the lexicon to use
059     */
060    public MbrolaVoice(String databaseDirectory, 
061                       String database, float rate, float pitch, float range,
062                       String name, Gender gender, Age age,
063                       String description, Locale locale, String domain,
064                       String organization, CMULexicon lexicon) {
065        super(name, gender, age, description, locale,
066              domain, organization, lexicon);
067        setRate(rate);
068        setPitch(pitch);
069        setPitchRange(range);
070        this.databaseDirectory = databaseDirectory;
071        this.database = database;
072    }
073
074    //[[Providing the Mbrola classes via getUnitSelector() and
075    // getUnitConcatenator() is just a hack allowing us to use
076    // the current CMUVoice.java framework. It only means that
077    // after the Durator and the ContourGenerator, the classes
078    // process the utterance (Selector before Concatenator).]]
079    /**
080     * Returns the unit selector to be used by this voice.
081     * Derived voices typically override this to customize behaviors.
082     * 
083     * @return the unit selector
084     * 
085     * @throws IOException if an IO error occurs while getting
086     *     processor
087     */
088    protected UtteranceProcessor getUnitSelector() throws IOException {
089        return new ParametersToMbrolaConverter();
090    }
091
092    /**
093     * Returns the command line that invokes the MBROLA executable.
094     * The command will be in the form of:
095     *
096     * <pre> {mbrolaExecutable} -e -R {mbrolaRenameList} {mbrolaVoiceDB} 
097     * - -.raw </pre>
098     */
099    protected String[] getMbrolaCommand() {
100
101        // Construct the mbrola command in such a way that
102        // mbrola reads from stdin and writes raw, headerless audio data
103        // to stdout; translates CMU us radio to sampa phonetic symbols;
104        // and only complains, but does not abort, when encountering an
105        // unknown diphone:
106        String[] cmd = 
107             {getMbrolaBinary(), "-e", "-R",  getRenameList(), 
108             getDatabase(), "-", "-.raw"};
109
110         if (false) {
111             for (int i = 0; i < cmd.length; i++) {
112                 System.out.println(cmd[i]);
113             }
114         }
115
116        return cmd;
117    }
118
119    /**
120     * Returns the absolute name of the MBROLA directory.
121     *
122     * @return the absolute name of the MBROLA directory
123     */
124    public String getMbrolaBase() {
125        return Utilities.getProperty("mbrola.base", ".");
126    }
127
128    /**
129     * Returns the absolute file name of the MBROLA binary.
130     *
131     * @return the absolute file name of the MBROLA binary
132     */
133    public String getMbrolaBinary() {
134        // In windows environments, executables typically end with exe, so
135        // we add this suffix if we are running under windows.
136        StringBuffer executable = new StringBuffer();
137        executable.append("mbrola");
138        String os = System.getProperty("os.name");
139        if (os.indexOf("Windows") >= 0) {
140            executable.append(".exe");
141        }
142        return getMbrolaBase() + File.separator + executable.toString();
143    }
144
145    /**
146     * Returns the absolute file name of the MBROLA phonetic symbols
147     * rename table.
148     *
149     * @return the absolute file name of the rename table
150     */
151    public String getRenameList() {
152        return MRPA_TO_SAMPA_RENAME_LIST;
153    }
154
155    /**
156     * Returns the absolute file name of the Voice database
157     * this MbrolaVoice uses.
158     *
159     * @return the absolute file name of the Voice database
160     */
161    public String getDatabase() {
162        return getMbrolaBase() + File.separator + 
163            databaseDirectory + File.separator + database;
164    }
165
166//    /**
167//     * Returns the unit concatenator to be used by this voice.
168//     * Derived voices typically override this to customize behaviors.
169//     * 
170//     * @return the unit conatenator
171//     * 
172//     * @throws IOException if an IO error occurs while getting
173//     *     processor
174//     */
175//    protected UtteranceProcessor getUnitConcatenator() throws IOException {
176//        return null;
177//    }
178
179    //[[Providing the Mbrola classes via getUnitSelector() and
180    // getUnitConcatenator() is just a hack allowing us to use
181    // the current CMUVoice.java framework. It only means that
182    // after the Durator and the ContourGenerator, the classes
183    // process the utterance (Selector before Concatenator).]]
184    /**
185     * Returns the unit concatenator to be used by this voice.
186     * This method constructs the command line with which the
187     * MBROLA binary will be called, and initialises the
188     * MbrolaCaller accordingly.
189     *
190     * @return the unit conatenator
191     *
192     * @throws IOException if an IO error occurs while getting
193     *     processor
194     */
195    protected UtteranceProcessor getUnitConcatenator() throws IOException {
196        return new MbrolaCaller(getMbrolaCommand());
197    }
198
199    /**
200     * Returns the audio output used by this voice.
201     *
202     * @return the audio output used by this voice
203     *
204     * @throws IOException if an I/O error occurs
205     */
206    protected UtteranceProcessor getAudioOutput() throws IOException {
207        return new MbrolaAudioOutput();
208    }
209
210    /**
211     * Get a resource for this voice.  Resources for this voice are located in
212     * the package <code>com.sun.speech.freetts.en.us</code>.
213     */
214    protected URL getResource(String resource) {
215        return com.sun.speech.freetts.en.us.CMUVoice.class.
216            getResource(resource);
217    }
218
219    /**
220     * Converts this object to a string
221     * 
222     * @return a string representation of this object
223     */
224    public String toString() {
225        return "MbrolaVoice";
226    }
227}
228