upstream version 1.2.2
[debian/freetts] / demo / JSAPI / MixedVoices / MixedVoices.java
1 /**
2  * Copyright 2003 Sun Microsystems, Inc.
3  * 
4  * See the file "license.terms" for information on usage and
5  * redistribution of this file, and for a DISCLAIMER OF ALL 
6  * WARRANTIES.
7  */
8 import java.io.File;
9 import java.util.Locale;
10 import java.beans.PropertyChangeEvent;
11 import java.beans.PropertyChangeListener;
12
13 import javax.speech.Central;
14 import javax.speech.Engine;
15 import javax.speech.EngineException;
16 import javax.speech.synthesis.Synthesizer;
17 import javax.speech.synthesis.SynthesizerModeDesc;
18 import javax.speech.synthesis.SynthesizerProperties;
19 import javax.speech.synthesis.Voice;
20 import javax.speech.synthesis.Speakable;
21 import javax.speech.synthesis.SpeakableAdapter;
22 import javax.speech.synthesis.SpeakableEvent;
23
24 /**
25  * Sample program that demonstrates how multiple voices
26  * and synthesizers can be used.
27  */
28 public class MixedVoices {
29     
30     private final static void usage() {
31         System.out.println("MixedVoices [-showEvents] [-showPropertyChanges]");
32     }
33
34     /**
35      * Returns a "no synthesizer" message, and asks 
36      * the user to check if the "speech.properties" file is
37      * at <code>user.home</code> or <code>java.home/lib</code>.
38      *
39      * @return a no synthesizer message
40      */
41     static private String noSynthesizerMessage(String synthesizer) {
42         String message =
43             "Cannot find " + synthesizer + ".\n" +
44             "This may be the result of any number of problems.  It's\n" +
45             "typically due to a missing \"speech.properties\" file that\n" +
46             "should be at either of these locations: \n\n";
47         message += "user.home    : " + System.getProperty("user.home") + "\n";
48         message += "java.home/lib: " + System.getProperty("java.home") +
49             File.separator + "lib\n\n" +
50             "Another cause of this problem might be corrupt or missing\n" +
51             "voice jar files in the freetts lib directory.  This problem\n" +
52             "also sometimes arises when the freetts.jar file is corrupt\n" +
53             "or missing.  Sorry about that.  Please check for these\n" +
54             "various conditions and then try again.\n";
55         return message;
56     }
57
58     public static void main(String[] argv) {
59         boolean showEvents = false;
60         boolean showPropertyChanges = false;
61
62         for (int i = 0; i < argv.length; i++) {
63             if (argv[i].equals("-showEvents")) {
64                 showEvents = true;
65             } else if (argv[i].equals("-showPropertyChanges")) {
66                 showPropertyChanges = true;
67             } else {
68                 usage();
69                 System.exit(0);
70             }
71         }
72
73         System.out.println(" ** Mixed Voices - JSAPI Demonstration program **");
74         /* alan is a limited-domain voice that only knows how talk
75          * about the time of day.
76          */
77         Voice alan = new Voice("alan", 
78                 Voice.GENDER_DONT_CARE, Voice.AGE_DONT_CARE, null);
79
80         /* kevin in an 8khz general domain diphone voice
81          */
82         Voice kevin = new Voice("kevin", 
83                 Voice.GENDER_DONT_CARE, Voice.AGE_DONT_CARE, null);
84
85         /* kevin16 in a 16khz general domain diphone voice
86          */
87         Voice kevinHQ = new Voice("kevin16", 
88                 Voice.GENDER_DONT_CARE, Voice.AGE_DONT_CARE, null);
89
90         try {
91             /* Find a synthesizer that has the general domain voice
92              * we are looking for.  NOTE:  this uses the Central class
93              * of JSAPI to find a Synthesizer.  The Central class
94              * expects to find a speech.properties file in user.home
95              * or java.home/lib.
96              *
97              * If your situation doesn't allow you to set up a
98              * speech.properties file, you can circumvent the Central
99              * class and do a very non-JSAPI thing by talking to
100              * FreeTTSEngineCentral directly.  See the WebStartClock
101              * demo for an example of how to do this.
102              */
103             SynthesizerModeDesc generalDesc = new SynthesizerModeDesc(
104                 null,          // engine name
105                 "general",     // mode name
106                 Locale.US,     // locale
107                 null,          // running
108                 null);         // voice
109             
110             final Synthesizer synthesizer1 =
111                 Central.createSynthesizer(generalDesc);
112
113             if (synthesizer1 == null) {
114                 System.err.println(
115                     noSynthesizerMessage("general domain synthesizer"));
116                 System.exit(1);
117             }
118
119             /* Find a synthesizer that has the time domain voice.
120              */
121             SynthesizerModeDesc limitedDesc = new SynthesizerModeDesc(
122                 null,          // engine name
123                 "time",        // mode name
124                 Locale.US,     // locale
125                 null,          // running
126                 null);         // voice
127
128             final Synthesizer synthesizer2 =
129                 Central.createSynthesizer(limitedDesc);
130
131             if (synthesizer2 == null) {
132                 System.err.println(
133                     noSynthesizerMessage("time domain synthesizer"));
134                 System.exit(1);
135             }
136
137             System.out.print("  Allocating synthesizers...");
138             synthesizer1.allocate();
139             synthesizer2.allocate();
140
141             /* get general domain synthesizer ready to speak
142              */
143             System.out.print("Loading voices...");
144             synthesizer1.getSynthesizerProperties().setVoice(kevinHQ);
145             synthesizer1.getSynthesizerProperties().setVoice(kevin);
146
147             if (showPropertyChanges) {
148                 synthesizer1.getSynthesizerProperties().addPropertyChangeListener(
149                     new PropertyChangeListener() {
150                         public void propertyChange(
151                             PropertyChangeEvent pce) {
152                             if (pce.getNewValue() instanceof Voice) {
153                                 String newVoice = 
154                                     ((Voice) pce.getNewValue()).getName();
155                                 System.out.println(
156                                     "  PCE Voice changed to " + newVoice);
157                             } else {
158                                 System.out.println(
159                                     "  PCE " + pce.getPropertyName()
160                                     + " changed from " 
161                                     + pce.getOldValue() + " to " +
162                                     pce.getNewValue() + ".");
163                             }
164                         }
165                     });
166             }
167             
168             if (showEvents) {
169                 synthesizer1.addSpeakableListener(
170                     new SpeakableAdapter() {
171                         public void markerReached(SpeakableEvent e) {
172                             dumpEvent(e);
173                         }
174                         public void speakableCancelled(SpeakableEvent e) {
175                             dumpEvent(e);
176                         }
177                         public void speakableEnded(SpeakableEvent e) {
178                             dumpEvent(e);
179                         }
180                         public void speakablePaused(SpeakableEvent e) {
181                             dumpEvent(e);
182                         }
183                         public void speakableResumed(SpeakableEvent e) {
184                             dumpEvent(e);
185                         }
186                         public void speakableStarted(SpeakableEvent e) {
187                             dumpEvent(e);
188                         }
189                         public void topOfQueue(SpeakableEvent e) {
190                             dumpEvent(e);
191                         }
192                         public void wordStarted(SpeakableEvent e) {
193                             dumpEvent(e);
194                         }
195                         private void dumpEvent(SpeakableEvent e) {
196                             System.out.println(" EVT: " + e.paramString() 
197                                                + " source: " + e.getSource());
198                         }
199                     });
200             }
201             
202             System.out.println("And here we go!");
203             synthesizer1.resume();
204             synthesizer2.resume();
205             
206             // speak the "Hello world" string
207             synthesizer1.speakPlainText("Hello! My name is Kevin.", null);
208             synthesizer1.speakPlainText("I am a die phone synthesizer", null);
209             synthesizer1.speakPlainText("I have a friend named Alan.", null);
210             synthesizer1.speakPlainText("Listen to him count!", null);
211
212             // get synth2 ready to speak
213             synthesizer2.waitEngineState(Synthesizer.ALLOCATED);
214             synthesizer2.resume();
215
216             synthesizer1.waitEngineState(Synthesizer.QUEUE_EMPTY);
217             synthesizer2.speakPlainText("1 2 3 4 5 6 7 8 9 ten", null);
218
219             synthesizer2.waitEngineState(Synthesizer.QUEUE_EMPTY);
220
221             synthesizer1.speakPlainText("Now listen to me count!", null);
222             synthesizer1.speakPlainText("1 2 3 4 5 6 7 8 9 10.", null);
223
224             synthesizer1.speakPlainText(
225                     "Now, let's try that a little bit faster.", null);
226             synthesizer1.waitEngineState(Synthesizer.QUEUE_EMPTY);
227
228             synthesizer1.getSynthesizerProperties().setSpeakingRate(240.0f);
229             synthesizer1.speakPlainText("1 2 3 4 5 6 7 8 9 10.", null);
230             synthesizer1.speakPlainText("That's pretty fast.", null);
231             synthesizer1.speakPlainText("Now lets go very slow.", null);
232             synthesizer1.waitEngineState(Synthesizer.QUEUE_EMPTY);
233
234             synthesizer1.getSynthesizerProperties().setSpeakingRate(80.0f);
235             synthesizer1.speakPlainText("1 2 3 4 5 6 7 8 9 10.", null);
236             synthesizer1.speakPlainText("That is pretty slow.", null);
237             synthesizer1.waitEngineState(Synthesizer.QUEUE_EMPTY);
238
239             synthesizer1.getSynthesizerProperties().setSpeakingRate(150.0f);
240             synthesizer1.speakPlainText("Now back to normal", null);
241             synthesizer1.waitEngineState(Synthesizer.QUEUE_EMPTY);
242
243             synthesizer1.getSynthesizerProperties().setPitch(200);
244             synthesizer1.speakPlainText("I can talk very high.", null);
245             synthesizer1.waitEngineState(Synthesizer.QUEUE_EMPTY);
246
247             synthesizer1.getSynthesizerProperties().setPitch(50);
248             synthesizer1.speakPlainText("and I can talk very low.", null);
249             synthesizer1.waitEngineState(Synthesizer.QUEUE_EMPTY);
250
251             synthesizer1.getSynthesizerProperties().setPitch(100);
252             synthesizer1.getSynthesizerProperties().setVolume(.8f);
253             synthesizer1.speakPlainText("and I can talk very softly.", null);
254             synthesizer1.waitEngineState(Synthesizer.QUEUE_EMPTY);
255
256             synthesizer1.getSynthesizerProperties().setVolume(1.0f);
257             synthesizer1.speakPlainText(
258                 "I can talk with a higher quality voice", null);
259             synthesizer1.speakPlainText(
260                     "Here is a low quality tongue twister. "
261                     + "She sells seashells by the seashore.", null);
262             synthesizer1.waitEngineState(Synthesizer.QUEUE_EMPTY);
263
264             synthesizer1.getSynthesizerProperties().setVoice(kevinHQ);
265             synthesizer1.speakPlainText("And this is high quality. "
266                     + "She sells seashells by the seashore.", null);
267             synthesizer1.speakPlainText(
268                     "The funny thing is, I do not have a tongue.", null);
269             synthesizer1.speakPlainText(
270                 "Hey Alan, what time is it where you are right now?", null);
271             synthesizer1.waitEngineState(Synthesizer.QUEUE_EMPTY);
272
273             synthesizer2.speakPlainText(
274                     "the time is now twenty past six.", null);
275             synthesizer2.waitEngineState(Synthesizer.QUEUE_EMPTY);
276
277             synthesizer1.speakPlainText("Is that the exact time?", null);
278             synthesizer1.waitEngineState(Synthesizer.QUEUE_EMPTY);
279
280             synthesizer2.speakPlainText("Almost", null);
281             synthesizer2.waitEngineState(Synthesizer.QUEUE_EMPTY);
282
283             synthesizer1.speakPlainText(
284                 "Is it twenty past six In the morning or the evening?", null);
285             synthesizer1.waitEngineState(Synthesizer.QUEUE_EMPTY);
286
287             synthesizer2.speakPlainText("in the morning.", null);
288             synthesizer2.waitEngineState(Synthesizer.QUEUE_EMPTY);
289
290             synthesizer1.speakPlainText(
291                     "Alan and I can talk at the same time", null);
292             synthesizer1.waitEngineState(Synthesizer.QUEUE_EMPTY);
293
294             synthesizer1.speakPlainText("1 2 3 4 5 6 7 8 9 11 12", null);
295             synthesizer2.speakPlainText("1 2 3 4 5 6 7 8 9", null);
296             synthesizer1.waitEngineState(Synthesizer.QUEUE_EMPTY);
297             synthesizer2.waitEngineState(Synthesizer.QUEUE_EMPTY);
298
299             synthesizer1.speakPlainText( "That is a bit confusing.", null);
300             synthesizer1.speakPlainText( "Well, thanks. This was fun.", null);
301             synthesizer1.speakPlainText("Goodbye everyone.", null);
302             synthesizer1.waitEngineState(Synthesizer.QUEUE_EMPTY);
303             
304             // clean up
305             synthesizer1.deallocate();
306             synthesizer2.deallocate();
307         }
308         catch (Exception e) {
309             e.printStackTrace();
310         }
311
312         System.exit(0);
313     }
314 }
315