2 * Copyright 2003 Sun Microsystems, Inc.
4 * See the file "license.terms" for information on usage and
5 * redistribution of this file, and for a DISCLAIMER OF ALL
9 import com.sun.speech.freetts.Voice;
10 import com.sun.speech.freetts.VoiceManager;
12 import com.sun.speech.freetts.util.Utilities;
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;
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>.
32 public class Server extends TTSServer {
35 private Voice voice8k;
36 private String voice8kName = Utilities.getProperty
37 ("voice8kName", "kevin");
40 private Voice voice16k;
41 private String voice16kName = Utilities.getProperty
42 ("voice16kName", "kevin16");
46 * Constructs a default Server, which loads an 8k Voice and a 16k Voice
50 port = Utilities.getInteger("port", 5555).intValue();
52 VoiceManager voiceManager = VoiceManager.getInstance();
53 voice8k = voiceManager.getVoice(voice8kName);
54 voice16k = voiceManager.getVoice(voice16kName);
57 } catch (Exception e) {
64 * Returns the 8k diphone voice.
66 * @return 8k diphone voice
68 public Voice get8kVoice() {
74 * Returns the 16k diphone voice.
76 * @return 16k diphone voice
78 public Voice get16kVoice() {
84 * Spawns a ProtocolHandler depending on the current protocol.
86 * @param socket the socket that the spawned protocol handler will use
88 protected void spawnProtocolHandler(Socket socket) {
90 SocketTTSHandler handler = new SocketTTSHandler(socket, this);
91 (new Thread(handler)).start();
92 } catch (Exception e) {
99 * Starts this TTS Server.
101 public static void main(String[] args) {
102 Server server = new Server();
103 (new Thread(server)).start();
109 * A simple socket TTS request handler.
111 class SocketTTSHandler implements Runnable {
113 // the Voice to use to speak
116 // the Server to obtain Voices from
117 private Server server;
119 // the Socket to communicate with
120 private Socket socket;
122 // an AudioPlayer that writes bytes to the socket
123 private SocketAudioPlayer socketAudioPlayer;
125 private BufferedReader reader;
126 private PrintWriter writer;
128 private static final int INVALID_SAMPLE_RATE = 1;
131 private boolean metrics = Utilities.getBoolean("metrics");
132 private long requestReceivedTime;
133 private long requestSpeakTime;
137 * Constructs a SocketTTSHandler with the given <code>Socket</code>
138 * and <code>Server</code>.
140 * @param socket the Socket to read from and write to
141 * @param server the Server to obtain Voices from
143 public SocketTTSHandler(Socket socket, Server server) {
145 this.server = server;
146 this.socketAudioPlayer = new SocketAudioPlayer(socket);
151 * Sets the Socket to be used by this ProtocolHandler.
153 * @param socket the Socket to be used
155 private void setSocket(Socket socket) {
156 this.socket = socket;
157 if (socket != null) {
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");
172 * Sends the given line of text over the Socket.
174 * @param line the line of text to send
176 private void sendLine(String line) {
184 * Implements the run() method of Runnable
190 String command = null;
193 while ((command = reader.readLine()) != null &&
194 command.equals("TTS")) {
196 requestReceivedTime = System.currentTimeMillis();
198 status = handleSynthesisRequest();
200 if (status == INVALID_SAMPLE_RATE) {
201 println("Invalid sample rate\nexit.");
203 } else if (metrics) {
205 ("Time To Sending First Byte: " +
206 (socketAudioPlayer.getFirstByteSentTime() -
207 requestReceivedTime) + " ms");
210 if (command != null) {
211 if (command.equals("DONE")) {
213 println("... closed socket connection");
215 println("invalid command: " + command);
218 } catch (IOException ioe) {
219 ioe.printStackTrace();
225 * Handles a single speech synthesis request.
227 private int handleSynthesisRequest() {
229 String sampleRateLine = reader.readLine();
230 int sampleRate = Integer.parseInt(sampleRateLine);
232 if (sampleRate == 8000) {
233 voice = server.get8kVoice();
234 } else if (sampleRate == 16000) {
235 voice = server.get16kVoice();
237 // invalid sample rate
239 return INVALID_SAMPLE_RATE;
242 String text = reader.readLine();
244 voice.setAudioPlayer(socketAudioPlayer);
247 // tell the client that there is no more data for this request
250 } catch (IOException ioe) {
251 ioe.printStackTrace();
258 * A central point to write out all message.
260 * @param message the message
262 private void println(String message) {
263 System.out.println(message);