upstream version 1.2.2
[debian/freetts] / demo / freetts / ClientServer / Server.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
9 import com.sun.speech.freetts.Voice;
10 import com.sun.speech.freetts.VoiceManager;
11
12 import com.sun.speech.freetts.util.Utilities;
13
14 import java.io.BufferedReader;
15 import java.io.DataOutputStream;
16 import java.io.InputStreamReader;
17 import java.io.IOException;
18 import java.io.PrintWriter;
19 import java.net.ServerSocket;
20 import java.net.Socket;
21
22
23 /**
24  * Implements a text-to-speech server for the Client/Server demo.
25  * It creates two Voices when it starts up, one 8k and one 16k,
26  * and then waits for socket connections.
27  * After it receives a connection, it waits for TTS requests from the client,
28  * does speech synthesis, and then sends the synthesized wave bytes back to
29  * the client. For a complete specification of the protocol, please refer
30  * to the document <code>Protocol.txt</code>.
31  */
32 public class Server extends TTSServer {
33
34     // 8k Voice
35     private Voice voice8k;
36     private String voice8kName = Utilities.getProperty
37         ("voice8kName", "kevin");
38
39     // 16k Voice
40     private Voice voice16k;
41     private String voice16kName = Utilities.getProperty
42         ("voice16kName", "kevin16");
43
44
45     /**
46      * Constructs a default Server, which loads an 8k Voice and a 16k Voice
47      * by default.
48      */
49     public Server() {
50         port = Utilities.getInteger("port", 5555).intValue();
51         try {
52             VoiceManager voiceManager = VoiceManager.getInstance();
53             voice8k = voiceManager.getVoice(voice8kName);
54             voice16k = voiceManager.getVoice(voice16kName);
55             voice8k.allocate();
56             voice16k.allocate();
57         } catch (Exception e) {
58             e.printStackTrace();
59             System.exit(1);
60         }
61     }
62
63     /**
64      * Returns the 8k diphone voice.
65      *
66      * @return 8k diphone voice
67      */
68     public Voice get8kVoice() {
69         return voice8k;
70     }
71
72
73     /**
74      * Returns the 16k diphone voice.
75      *
76      * @return 16k diphone voice
77      */
78     public Voice get16kVoice() {
79         return voice16k;
80     }
81
82
83     /**
84      * Spawns a ProtocolHandler depending on the current protocol.
85      *
86      * @param socket the socket that the spawned protocol handler will use
87      */
88     protected void spawnProtocolHandler(Socket socket) {
89         try {
90             SocketTTSHandler handler = new SocketTTSHandler(socket, this);
91             (new Thread(handler)).start();
92         } catch (Exception e) {
93             e.printStackTrace();
94         }
95     }
96
97
98     /**
99      * Starts this TTS Server.
100      */
101     public static void main(String[] args) {
102         Server server = new Server();
103         (new Thread(server)).start();
104     }
105 }
106
107
108 /**
109  * A simple socket TTS request handler.
110  */
111 class SocketTTSHandler implements Runnable {
112
113     // the Voice to use to speak
114     private Voice voice;
115
116     // the Server to obtain Voices from
117     private Server server;
118
119     // the Socket to communicate with
120     private Socket socket;
121
122     // an AudioPlayer that writes bytes to the socket
123     private SocketAudioPlayer socketAudioPlayer;
124
125     private BufferedReader reader;
126     private PrintWriter writer;
127
128     private static final int INVALID_SAMPLE_RATE = 1;
129
130     // metrics variables
131     private boolean metrics = Utilities.getBoolean("metrics");
132     private long requestReceivedTime;
133     private long requestSpeakTime;
134
135
136     /**
137      * Constructs a SocketTTSHandler with the given <code>Socket</code>
138      * and <code>Server</code>.
139      *
140      * @param socket the Socket to read from and write to
141      * @param server the Server to obtain Voices from
142      */
143     public SocketTTSHandler(Socket socket, Server server) {
144         setSocket(socket);
145         this.server = server;
146         this.socketAudioPlayer = new SocketAudioPlayer(socket);
147     }
148
149
150     /**
151      * Sets the Socket to be used by this ProtocolHandler.
152      *
153      * @param socket the Socket to be used
154      */
155     private void setSocket(Socket socket) {
156         this.socket = socket;
157         if (socket != null) {
158             try {
159                 reader = new BufferedReader
160                     (new InputStreamReader(socket.getInputStream()));
161                 writer = new PrintWriter(socket.getOutputStream(), true);
162             } catch (IOException ioe) {
163                 ioe.printStackTrace();
164                 println("Socket reader/writer not instantiated");
165                 throw new Error();
166             }
167         }
168     }
169
170
171     /**
172      * Sends the given line of text over the Socket.
173      *
174      * @param line the line of text to send
175      */
176     private void sendLine(String line) {
177         writer.print(line);
178         writer.print('\n');
179         writer.flush();
180     }
181
182
183     /**
184      * Implements the run() method of Runnable
185      */
186     public void run() {
187         try {
188             sendLine("READY");
189
190             String command = null;
191             int status;
192             
193             while ((command = reader.readLine()) != null &&
194                    command.equals("TTS")) {
195
196                 requestReceivedTime = System.currentTimeMillis();
197                 
198                 status = handleSynthesisRequest();
199
200                 if (status == INVALID_SAMPLE_RATE) {
201                     println("Invalid sample rate\nexit.");
202                     return;
203                 } else if (metrics) {
204                     System.out.println
205                         ("Time To Sending First Byte: " + 
206                          (socketAudioPlayer.getFirstByteSentTime() -
207                           requestReceivedTime) + " ms");
208                 }
209             }
210             if (command != null) {
211                 if (command.equals("DONE")) {
212                     socket.close();
213                     println("... closed socket connection");
214                 } else {
215                     println("invalid command: " + command);
216                 }
217             }
218         } catch (IOException ioe) {
219             ioe.printStackTrace();
220         }
221     }
222
223
224     /**
225      * Handles a single speech synthesis request.
226      */
227     private int handleSynthesisRequest() {
228         try {
229             String sampleRateLine = reader.readLine();
230             int sampleRate = Integer.parseInt(sampleRateLine);
231
232             if (sampleRate == 8000) {
233                 voice = server.get8kVoice();
234             } else if (sampleRate == 16000) {
235                 voice = server.get16kVoice();
236             } else {
237                 // invalid sample rate
238                 sendLine("-2");
239                 return INVALID_SAMPLE_RATE;
240             }
241
242             String text = reader.readLine();
243
244             voice.setAudioPlayer(socketAudioPlayer);
245             voice.speak(text);
246
247             // tell the client that there is no more data for this request
248             sendLine("-1");
249             
250         } catch (IOException ioe) {
251             ioe.printStackTrace();
252         }
253         return 0;
254     }
255
256
257     /**
258      * A central point to write out all message.
259      *
260      * @param message the message
261      */
262     private void println(String message) {
263         System.out.println(message);
264     }
265 }