upstream version 1.2.2
[debian/freetts] / com / sun / speech / freetts / FreeTTSTime.java
1 /**
2  * Portions Copyright 2001 Sun Microsystems, Inc.
3  * Portions Copyright 1999-2001 Language Technologies Institute, 
4  * Carnegie Mellon University.
5  * All Rights Reserved.  Use is subject to license terms.
6  * 
7  * See the file "license.terms" for information on usage and
8  * redistribution of this file, and for a DISCLAIMER OF ALL 
9  * WARRANTIES.
10  */
11 package com.sun.speech.freetts;
12
13 import java.io.BufferedReader;
14 import java.io.IOException;
15 import java.io.InputStreamReader;
16 import java.util.Calendar;
17 import java.util.GregorianCalendar;
18 import java.util.logging.ConsoleHandler;
19 import java.util.logging.Handler;
20 import java.util.logging.Level;
21 import java.util.logging.Logger;
22 import java.util.regex.Pattern;
23
24 /**
25  * Standalone utility that tells the time.
26  *
27  * Defaults to "alan" voice.
28  * 
29  */
30 public class FreeTTSTime extends FreeTTS {
31
32     private final static String VERSION = 
33             "FreeTTSTime Version 1.1, August  1, 2003";
34
35     /**
36      * Class constructor.
37      */
38     public FreeTTSTime() {
39         super(VoiceManager.getInstance().getVoice("alan"));
40     }
41
42     /**
43      * Class constructor.
44      *
45      * @param voice Voice to say time with
46      */
47     public FreeTTSTime(Voice voice) {
48         super(voice);
49     }
50
51
52     /**
53      * Prints the usage message for FreeTTSTime.
54      */
55     public static void usage() {
56         System.out.println(VERSION);
57         System.out.println("Usage:");
58         System.out.println("    -dumpASCII file : dump the final wave to file");
59         System.out.println("    -dumpAudio file : dump audio to file ");
60         System.out.println("    -help           : shows usage information");
61         System.out.println("    -detailedMetrics: turn on detailed metrics");
62         System.out.println("    -dumpRelations  : dump the relations ");
63         System.out.println("    -dumpUtterance  : dump the final utterance");
64         System.out.println("    -metrics        : turn on metrics");
65         System.out.println("    -run  name      : sets the name of the run");
66         System.out.println("    -silent         : don't say anything");
67         System.out.println("    -verbose        : verbose output");
68         System.out.println("    -version        : shows version number");
69         System.out.println("    -timeTest       : runs a lengthy time test");
70         System.out.println("    -iter count     : run for count iterations");
71         System.out.println("    -time XX:XX     : speak the given time");
72         System.out.println("    -time now       : speak the current time");
73         System.out.println("    -period secs    : period of iter");
74         System.out.println("    -clockMode      : tells time every 5 mins");
75         System.out.println("    -voice VOICE    : " +
76                 VoiceManager.getInstance().toString());
77         System.exit(0);
78     }
79
80     /**
81      * Starts interactive mode on the given FreeTTSTime. Reads text
82      * from the console and gives it to FreeTTSTime to speak.
83      * terminates on end of file.
84      *
85      * @param freetts the engine that speaks
86      */
87     private static void interactiveMode(FreeTTSTime freetts) {
88         try {
89             while (true) {
90                 String time;
91                 BufferedReader reader;
92                 reader = new BufferedReader(
93                     new InputStreamReader(System.in));
94                 System.out.print("Enter time: ");
95                 System.out.flush();
96                 time = reader.readLine();
97                 if ((time == null) || (time.length() == 0)
98                         || time.equals("quit") ) {
99                     freetts.shutdown();
100                     System.exit(0);
101                 } else {
102                     freetts.getVoice().startBatch();
103                     freetts.safeTimeToSpeech(time);
104                     freetts.getVoice().endBatch();
105                 }
106             }
107         } catch (IOException e) {
108         }
109     }
110
111     /**
112      * Returns a phrase that conveys the exactness
113      * of the time.
114      *
115      * @param hour the hour of the time
116      * @param min the minute of the time
117      *
118      * @return a string phrase
119      */
120     private static String timeApprox(int hour, int min) {
121         int mm;
122
123         mm = min % 5;
124
125         if ((mm == 0) || (mm == 4)) {
126             return "exactly";
127         } else if (mm == 1) {
128             return "just after";
129         } else if (mm == 2) {
130             return "a little after";
131         } else {
132             return "almost";
133         }
134     }
135
136     /**
137      * Returns a phrase that conveys the minutes in relation
138      * to the hour.
139      *
140      * @param hour the hour of the time
141      * @param min the minute of the time
142      *
143      * @return a string phrase.
144      */
145     private static String timeMin(int hour, int min) {
146         int mm;
147
148         mm = min / 5;
149         if ((min % 5) > 2) {
150             mm += 1;
151         }
152         mm = mm * 5;
153         if (mm > 55) {
154             mm = 0;
155         }
156
157         if (mm == 0) {
158             return "";
159         } else if (mm == 5) {
160             return "five past";
161         } else if (mm == 10) {
162             return "ten past";
163         } else if (mm == 15) {
164             return "quarter past";
165         } else if (mm == 20) {
166             return "twenty past";
167         } else if (mm == 25) {
168             return "twenty-five past";
169         } else if (mm == 30) {
170             return "half past";
171         } else if (mm == 35) {
172             return "twenty-five to";
173         } else if (mm == 40) {
174             return "twenty to";
175         } else if (mm == 45) {
176             return "quarter to";
177         } else if (mm == 50) {
178             return "ten to";
179         } else if (mm == 55) {
180             return "five to";
181         } else {
182             return "five to";
183         }
184     }
185
186     /**
187      * Returns a phrase that conveys the hour in relation
188      * to the hour.
189      *
190      * @param hour the hour of the time
191      * @param min the minute of the time
192      *
193      * @return a string phrase.
194      */
195     private static String timeHour(int hour, int min) {
196         int hh;
197
198         hh = hour;
199         if (min > 32)  { // PBL: fixed from flite_time
200             hh += 1;
201         }
202         if (hh == 24) {
203             hh = 0;
204         }
205         if (hh > 12) {
206             hh -= 12;
207         }
208
209         if (hh == 0) {
210             return "midnight";
211         } else if (hh == 1) {
212             return "one";
213         } else if (hh == 2) {
214             return "two";
215         } else if (hh == 3) {
216             return "three";
217         } else if (hh == 4) {
218             return "four";
219         } else if (hh == 5) {
220             return "five";
221         } else if (hh == 6) {
222             return "six";
223         } else if (hh == 7) {
224             return "seven";
225         } else if (hh == 8) {
226             return "eight";
227         } else if (hh == 9) {
228             return "nine";
229         } else if (hh == 10) {
230             return "ten";
231         } else if (hh == 11) {
232             return "eleven";
233         } else if (hh == 12) {
234             return "twelve";
235         } else {
236             return "twelve";
237         }
238     }
239
240     /**
241      * Returns a phrase that conveys the time of day.
242      *
243      * @param hour the hour of the time
244      * @param min the minute of the time
245      *
246      * @return a string phrase
247      */
248     private static String timeOfDay(int hour, int min) {
249         int hh = hour;
250
251         if (min > 58)
252             hh++;
253
254         if (hh == 24) {
255             return "";
256         } else if (hh > 17) {
257             return "in the evening";
258         } else if (hh > 11) {
259             return "in the afternoon";
260         } else {
261             return "in the morning";
262         }
263     }
264
265     /**
266      * Returns a string that corresponds to the given time.
267      *
268      * @param time the time in the form HH:MM
269      *
270      * @return the time in string, null if the given time is not in the
271      *   form HH:MM 
272      */
273     public static String timeToString(String time) {
274         String theTime = null;
275         if (Pattern.matches("[012][0-9]:[0-5][0-9]", time)) {
276             int hour = Integer.parseInt(time.substring(0, 2));
277             int min = Integer.parseInt(time.substring(3));
278
279             theTime = timeToString(hour, min);
280         }
281         return theTime;
282     }
283
284     /**
285      * Returns a string that corresponds to the given time.
286      *
287      * @param hour the hour
288      * @param min the minutes
289      *
290      * @return the time in string, null if the given time out of range
291      */
292     public static String timeToString(int hour, int min) {
293         String theTime = "The time is now, " +
294             timeApprox(hour, min) + " " +
295             timeMin(hour, min) + " " +
296             timeHour(hour, min) + ", " +
297             timeOfDay(hour, min) + "." ;
298         return theTime;
299     }
300
301     
302     /**
303      * Speaks the given time. Time should be in the exact form
304      * HH:MM where HH is the hour 00 to 23, and MM is the minute 00 to
305      * 59.
306      *
307      * @param time the time in the form HH:MM
308      *
309      * @throws IllegalArgumentException if time is not in the form
310      *   HH:MM
311      */
312     public void timeToSpeech(String time) {
313         String theTime = timeToString(time);
314         if (theTime != null) {
315             textToSpeech(theTime);
316         } else {
317             throw new IllegalArgumentException("Bad time format");
318         }
319     }
320     
321     /**
322      * Speaks the time given the hour and minute.
323      *
324      * @param hour the hour of the day (0 to 23)
325      * @param min the minute of the hour (0 to 59)
326      */
327     public void timeToSpeech(int hour, int min) {
328         if (hour < 0 || hour > 23) {
329             throw new IllegalArgumentException("Bad time format: hour");
330         }
331
332         if (min < 0 || min > 59) {
333             throw new IllegalArgumentException("Bad time format: min");
334         }
335         String theTime = timeToString(hour, min);
336         textToSpeech(theTime);
337     }
338
339
340     /**
341      * Speaks the given time.  Prints an error message if the time
342      * is ill-formed.
343      *
344      * @param time the time in the form HH:MM
345      */
346     public void safeTimeToSpeech(String time) {
347         try {
348             if (time.equals("now")) {
349                 speakNow();
350             } else {
351                 timeToSpeech(time);
352             }
353         } catch (IllegalArgumentException iae) {
354             System.err.println("Bad time format");
355         }
356     }
357
358     /**
359      * Tells the current time.
360      */
361     public void speakNow() {
362         Calendar cal = new GregorianCalendar();
363         int hour = cal.get(Calendar.HOUR_OF_DAY);
364         int min = cal.get(Calendar.MINUTE);
365         timeToSpeech(hour, min);
366     }
367
368     /**
369      * The main entry point for FreeTTSTime.
370      */
371     public static void main(String[] args) {
372
373         String time = null; // default is interactive mode
374         int iterations = 1;
375         int delay = 0;
376
377         boolean setMetrics = false;
378         boolean setDetailedMetrics = false;
379         boolean setVerbose = false;
380         boolean setDumpUtterance = false;
381         boolean setDumpRelations = false;
382         String waveDumpFile = null;
383         String runTitle = null;
384
385         boolean setSilentMode = false;
386         String audioFile = null;
387         boolean setInputMode = false;
388
389         String voiceName = null;
390
391         for (int i = 0; i < args.length; i++) {
392             if (args[i].equals("-metrics")) {
393                 setMetrics = true;
394             } else if (args[i].equals("-detailedMetrics")) {
395                 setDetailedMetrics = true;
396             } else if (args[i].equals("-silent")) {
397                 setSilentMode = true;
398             } else if (args[i].equals("-period")) {
399                 if (++i < args.length) {
400                     try {
401                       delay  = Integer.parseInt(args[i]);
402                     } catch (NumberFormatException nfe) {
403                         System.out.println("Bad clock period");
404                         usage();
405                     }
406                 }
407             } else if (args[i].equals("-verbose")) {
408                 setVerbose = true;
409             } else if (args[i].equals("-dumpUtterance")) {
410                 setDumpUtterance = true;
411             } else if (args[i].equals("-dumpRelations")) {
412                 setDumpRelations = true;
413             } else if (args[i].equals("-clockMode")) {
414                 iterations = Integer.MAX_VALUE;
415                 delay = 300;
416             } else if (args[i].equals("-timeTest")) {
417                 iterations = 100;
418             } else if (args[i].equals("-dumpAudio")) {
419                 if (++i < args.length) {
420                     audioFile = args[i];
421                 } else {
422                     usage();
423                 }
424             } else if (args[i].equals("-iter")) {
425                 if (++i < args.length) {
426                     try {
427                       iterations = Integer.parseInt(args[i]);
428                     } catch (NumberFormatException nfe) {
429                         System.out.println("Bad iteration format");
430                         usage();
431                     }
432                 } else {
433                     usage();
434                 }
435             } else if (args[i].equals("-dumpASCII")) {
436                 if (++i < args.length) {
437                     waveDumpFile = args[i];
438                 } else {
439                     usage();
440                 }
441             } else if (args[i].equals("-version")) {
442                 System.out.println(VERSION);
443             } else if (args[i].equals("-help")) {
444                 usage();
445             } else if (args[i].equals("-time")) {
446                 setInputMode = true;
447                 if (++i < args.length) {
448                     time = args[i];
449                 } else {
450                     usage();
451                 }
452             } else if (args[i].equals("-run")) {
453                 if (++i < args.length) {
454                     runTitle = args[i];
455                 } else {
456                     usage();
457                 }
458             } else if (args[i].equals("-voice")) {
459                 if (++i < args.length) {
460                     voiceName = args[i];
461                 } else {
462                     usage();
463                 }
464             } else {
465                 System.out.println("Unknown option:" + args[i]);
466             }
467         }
468
469         if (voiceName == null) {
470             voiceName = "alan";
471         }
472
473         FreeTTSTime freetts = new
474             FreeTTSTime(VoiceManager.getInstance().getVoice(voiceName));
475         Voice voice = freetts.getVoice();
476
477         if (setMetrics) {
478             voice.setMetrics(true);
479         }
480
481         if (setDetailedMetrics) {
482             voice.setDetailedMetrics(true);
483         }
484
485         if (setVerbose) {
486             Handler handler = new ConsoleHandler();
487             handler.setLevel(Level.ALL);
488             Logger.getLogger("com.sun").addHandler(handler);
489             Logger.getLogger("com.sun").setLevel(Level.ALL);
490         }
491
492         if (setDumpUtterance) {
493             voice.setDumpUtterance(true);
494         }
495
496         if (setDumpRelations) {
497             voice.setDumpRelations(true);
498         }
499
500         if (waveDumpFile != null) {
501             voice.setWaveDumpFile(waveDumpFile);
502         }
503
504         if (runTitle != null) {
505             voice.setRunTitle(runTitle);
506         }
507
508         if (setSilentMode) {
509             freetts.setSilentMode(true);
510         }
511
512         if (audioFile != null) {
513             freetts.setAudioFile(audioFile);
514         }
515
516         if (setInputMode) {
517             freetts.setInputMode(InputMode.TEXT);
518         }
519     
520
521         freetts.startup();
522
523         if (time != null) {
524             freetts.getVoice().startBatch();
525             for (int i = 0; i < iterations; i++) {
526                 freetts.safeTimeToSpeech(time);
527                 try {
528                     Thread.sleep(delay * 1000L);
529                 } catch (InterruptedException ie) {
530                     break;
531                 }
532             }
533             freetts.getVoice().endBatch();
534         } else {
535             interactiveMode(freetts);
536         }
537         freetts.shutdown();
538         System.exit(0);
539     }
540 }
541
542