import java.util.Random; import com.sun.speech.freetts.*; /** * Class OutputVocal. Deals with all TTS outputs to the user. * * @author Adrien Martel * */ public class OutputVocal extends Thread { private static final String MAIN_VOICE_TYPE = "mbrola_us3"; private static final String STATS_VOICE_TYPE = "mbrola_us1"; public static final int STANDARD_VOICE = -1; public static final int EXCITED_VOICE = 1; public static final int SLIGHTLY_EXCITED_VOICE = 2; public static final int BEFORE_MATCH_VOICE = 0; public static final int GOAL_VOICE = 3; private Voice mainVoice; private Voice statsVoice; private Random rng; private String nextComment = ""; private int nextCommentParam = -2; private boolean stats = false; //true when the next voice to use is stats private boolean voiceDeAlloc = true; //used for testing purposes /** * * Constructor for OutputVocal. Instantiates the relevant speech engines and * constructs the 2 voices for commentating and stats. * */ public OutputVocal(){ VoiceManager voiceManagerMain = VoiceManager.getInstance(); VoiceManager voiceManagerStats = VoiceManager.getInstance(); mainVoice = voiceManagerMain.getVoice(MAIN_VOICE_TYPE); statsVoice = voiceManagerStats.getVoice(STATS_VOICE_TYPE); rng = new Random(); mainVoice.setPitch(110); } /** * * Run method. This method will always run throughout the commentating phase. * It blocks until a message has been placed in nextComment and notified by Output. * Once this has occured the speech output procedure is called. * */ public synchronized void run(){ while(true){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } if(nextComment != null){ prepareSpeak(); } nextComment = ""; } } /** * Method to pass a comment to the currently running * thread for the tts to eventually service when it next * becomes available. Stats * */ public boolean serviceCommentator(String speech,boolean stats){ nextComment = speech; this.stats = true; return true; } /** * Method to pass a comment to the currently running * thread for the tts to eventually service when it next * becomes available. * */ public boolean serviceCommentator(String speech, int param){ nextComment = speech; nextCommentParam = param; this.stats = false; return true; } /** * * Method speak. Identifies the voice to be used and passes the next comment * to be spoken to the speech engine. * */ private void speak() { Voice voice = mainVoice; if(stats){ voice = statsVoice; } voice.allocate(); voice.speak(nextComment); } /** * * Method perpareSpeak. Alters the parameters of the voice according to the param * set by the gameplay analysers. This includes pitch changes, volume changes and * word per minute rate changes. * */ public void prepareSpeak(){ //if this is 0 then we are not changing the voice excitation level int oldCommentParam = nextCommentParam; if(nextCommentParam != -2){ if(nextCommentParam != STANDARD_VOICE) allocateVoiceParam(nextCommentParam); //give it a random pitch shift } this.speak(); //return to normal speaking voice if it was excited if(oldCommentParam != STANDARD_VOICE && voiceDeAlloc) deallocateVoiceParam(); nextCommentParam = -2; } /** * * Method allocateVoiceParam. Sets the relevant fields to alter the excitement * level of the next comment to be spoken. * * @param - the voice param as set by the gameplay analysers. * */ private void allocateVoiceParam(int voiceParam){ int rate = 0; int pitch = 0; switch(voiceParam){ case EXCITED_VOICE: pitch = 115; rate = 165; break; case SLIGHTLY_EXCITED_VOICE: pitch = 110; rate = 155; break; case BEFORE_MATCH_VOICE: pitch = 105; rate = 150; break; case GOAL_VOICE: pitch = 120; rate = 175; mainVoice.setVolume(1.3f); break; } mainVoice.setRate(rate); mainVoice.setPitch(pitch); } /** * * Method deallocateVoiceParam. Method to reset the parameters of the voice to default. * This is typically carried out after each utterance. * */ private void deallocateVoiceParam(){ mainVoice.setRate(150); mainVoice.setPitch(110); mainVoice.setVolume(1.0f); mainVoice.setPitchShift(1.0f); } /** * All methods below are for testing purposes. * */ //returns the mainVoice that is used for vocal output public Voice getMainVoice() { return mainVoice; } //returns the nextComment to be spoken public String getNextComment() { return nextComment; } //returns the next parameter that will be applied for the next comment public int getNextCommentParam() { return nextCommentParam; } //true if the next utterance will be stats based public boolean isStats() { return stats; } //returns the voice used for stats utterences public Voice getStatsVoice() { return statsVoice; } //sets the main commentary voice public void setMainVoice(Voice mainVoice) { this.mainVoice = mainVoice; } //sets the next comment to be spoken public void setNextComment(String nextComment) { this.nextComment = nextComment; } //disables the deallocation of voices public void disableDeallocationVoice(){ voiceDeAlloc = false; } }