001/** 002 * Portions Copyright 2001 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; 012 013import java.io.BufferedReader; 014import java.io.IOException; 015import java.io.InputStreamReader; 016import java.util.Calendar; 017import java.util.GregorianCalendar; 018import java.util.logging.ConsoleHandler; 019import java.util.logging.Handler; 020import java.util.logging.Level; 021import java.util.logging.Logger; 022import java.util.regex.Pattern; 023 024/** 025 * Standalone utility that tells the time. 026 * 027 * Defaults to "alan" voice. 028 * 029 */ 030public class FreeTTSTime extends FreeTTS { 031 032 private final static String VERSION = 033 "FreeTTSTime Version 1.1, August 1, 2003"; 034 035 /** 036 * Class constructor. 037 */ 038 public FreeTTSTime() { 039 super(VoiceManager.getInstance().getVoice("alan")); 040 } 041 042 /** 043 * Class constructor. 044 * 045 * @param voice Voice to say time with 046 */ 047 public FreeTTSTime(Voice voice) { 048 super(voice); 049 } 050 051 052 /** 053 * Prints the usage message for FreeTTSTime. 054 */ 055 public static void usage() { 056 System.out.println(VERSION); 057 System.out.println("Usage:"); 058 System.out.println(" -dumpASCII file : dump the final wave to file"); 059 System.out.println(" -dumpAudio file : dump audio to file "); 060 System.out.println(" -help : shows usage information"); 061 System.out.println(" -detailedMetrics: turn on detailed metrics"); 062 System.out.println(" -dumpRelations : dump the relations "); 063 System.out.println(" -dumpUtterance : dump the final utterance"); 064 System.out.println(" -metrics : turn on metrics"); 065 System.out.println(" -run name : sets the name of the run"); 066 System.out.println(" -silent : don't say anything"); 067 System.out.println(" -verbose : verbose output"); 068 System.out.println(" -version : shows version number"); 069 System.out.println(" -timeTest : runs a lengthy time test"); 070 System.out.println(" -iter count : run for count iterations"); 071 System.out.println(" -time XX:XX : speak the given time"); 072 System.out.println(" -time now : speak the current time"); 073 System.out.println(" -period secs : period of iter"); 074 System.out.println(" -clockMode : tells time every 5 mins"); 075 System.out.println(" -voice VOICE : " + 076 VoiceManager.getInstance().toString()); 077 System.exit(0); 078 } 079 080 /** 081 * Starts interactive mode on the given FreeTTSTime. Reads text 082 * from the console and gives it to FreeTTSTime to speak. 083 * terminates on end of file. 084 * 085 * @param freetts the engine that speaks 086 */ 087 private static void interactiveMode(FreeTTSTime freetts) { 088 try { 089 while (true) { 090 String time; 091 BufferedReader reader; 092 reader = new BufferedReader( 093 new InputStreamReader(System.in)); 094 System.out.print("Enter time: "); 095 System.out.flush(); 096 time = reader.readLine(); 097 if ((time == null) || (time.length() == 0) 098 || time.equals("quit") ) { 099 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