upstream version 1.2.2
[debian/freetts] / com / sun / speech / freetts / audio / MultiFile8BitAudioPlayer.java
1 /**
2  * Copyright 2001 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 package com.sun.speech.freetts.audio;
9
10 import java.io.ByteArrayInputStream;
11 import java.io.File;
12 import java.io.IOException;
13
14 import javax.sound.sampled.AudioFileFormat;
15 import javax.sound.sampled.AudioFormat;
16 import javax.sound.sampled.AudioInputStream;
17 import javax.sound.sampled.AudioSystem;
18
19 import com.sun.speech.freetts.util.Utilities;
20
21 /**
22  * Streams audio to multiple files as 8-bit samples, one per utterance. 
23  * Currently, FreeTTS always outputs 16-bit samples, and this
24  * MultiFile8BitAudioPlayer will convert them to 8-bit before outputting
25  * them.
26  */
27 public class MultiFile8BitAudioPlayer implements AudioPlayer {
28     // 8-bit unsigned little-endian mono audio
29     private AudioFormat currentFormat = new AudioFormat
30     (8000, 8, 1, false, false);
31
32     private int fileCount = 0;
33     private String baseName;
34     private byte[] outputData;
35     private int curIndex = 0;
36     private AudioFileFormat.Type outputType;
37
38
39     /**
40      * Creates a default audio player for an AudioFileFormat of type
41      * WAVE.  Reads the "com.sun.speech.freetts.AudioPlayer.baseName"
42      * property for the base filename to use, and will produce files
43      * of the form <baseName>1.wav.  The default value for the
44      * base name is "freetts".
45      */
46     public MultiFile8BitAudioPlayer() {
47         this(Utilities.getProperty(
48                  "com.sun.speech.freetts.AudioPlayer.baseName", "freetts"),
49              AudioFileFormat.Type.WAVE);
50     }
51     
52     /**
53      * Constructs a MultiFile8BitAudioPlayer 
54      *
55      * @param baseName the base name of the audio file
56      * @param type the type of audio output
57      *
58      */
59     public MultiFile8BitAudioPlayer(String baseName, 
60                                     AudioFileFormat.Type type) {
61         this.baseName = baseName;
62         this.outputType = type;
63     }
64
65
66     /**
67      * Sets the audio format for this player
68      *
69      * @param format the audio format
70      *
71      * @throws UnsupportedOperationException if the line cannot be opened with
72      *     the given format
73      */
74     public synchronized void setAudioFormat(AudioFormat format) {
75     }
76
77
78     /**
79      * Gets the audio format for this player
80      *
81      * @return format the audio format
82      */
83     public AudioFormat getAudioFormat() {
84         return currentFormat;
85     }
86
87
88     /**
89      * Pauses audio output
90      */
91     public void pause() {
92     }
93
94     /**
95      * Resumes audio output
96      */
97     public synchronized void resume() {
98     }
99         
100     /**
101      * Starts the first sample timer
102      */
103     public void startFirstSampleTimer() {
104     }
105
106
107     /**
108      * Cancels currently playing audio
109      */
110     public synchronized void cancel() {
111     }
112
113     /**
114      * Prepares for another batch of output. Larger groups of output
115      * (such as all output associated with a single FreeTTSSpeakable)
116      * should be grouped between a reset/drain pair.
117      */
118     public synchronized void reset() {
119     }
120
121     /**
122      * Closes this audio player
123      */
124     public synchronized void close() {
125     }
126
127     /**
128      * Returns the current volume.
129      *
130      * @return the current volume (between 0 and 1)
131      */
132     public float getVolume() {
133         return 1.0f;
134     }         
135
136     /**
137      * Sets the current volume.
138      *
139      * @param volume  the current volume (between 0 and 1)
140      */
141     public void setVolume(float volume) {
142     }         
143
144
145     /**
146      *  Starts the output of a set of data. Audio data for a single
147      *  utterance should be grouped between begin/end pairs.
148      *
149      * @param size the size of data between now and the end
150      */
151     public void begin(int size) {
152         outputData = new byte[size/2];
153         curIndex = 0;
154     }
155
156     /**
157      *  Marks the end of a set of data. Audio data for a single 
158      *  utterance should be groupd between begin/end pairs.
159      *
160      *  @return true if the audio was output properly, false if the
161      *      output was cancelled or interrupted.
162      *
163      */
164     public boolean end()  {
165         ByteArrayInputStream bais = new ByteArrayInputStream(outputData);
166         AudioInputStream ais = new AudioInputStream
167             (bais, currentFormat, 
168              outputData.length/currentFormat.getFrameSize());
169         String name = baseName;
170         name = name + fileCount;
171         name = name + "." + outputType.getExtension();
172         File file = new File(name);
173         try {
174             AudioSystem.write(ais, outputType, file);
175             System.out.println("Wrote synthesized speech to " + name);
176         } catch (IOException ioe) {
177             System.err.println("Can't write audio to " + file);
178             return false;
179         } catch (IllegalArgumentException iae) {
180             System.err.println("Can't write audio type " + outputType);
181             return false;
182         }
183         fileCount++;
184         return true;
185     }
186
187
188     /**
189      * Waits for all queued audio to be played
190      *
191      * @return true if the audio played to completion, false if
192      *   the audio was stopped
193      */
194     public boolean drain()  {
195         return true;
196     }
197
198     /**
199      * Gets the amount of played since the last mark
200      *
201      * @return the amount of audio in milliseconds
202      */
203     public synchronized long getTime()  {
204         return -1L;
205     }
206
207
208     /**
209      * Resets the audio clock
210      */
211     public synchronized void resetTime() {
212     }
213     
214
215     
216     /**
217      * Writes the given bytes to the audio stream
218      *
219      * @param audioData audio data to write to the device
220      *
221      * @return <code>true</code> of the write completed successfully, 
222      *          <code> false </code>if the write was cancelled.
223      */
224     public boolean write(byte[] audioData) {
225         return write(audioData, 0, audioData.length);
226     }
227
228     
229     /**
230      * Writes the given bytes to the audio stream
231      *
232      * @param bytes audio data to write to the device
233      * @param offset the offset into the buffer
234      * @param size the size into the buffer
235      *
236      * @return <code>true</code> of the write completed successfully, 
237      *          <code> false </code>if the write was cancelled.
238      */
239     public boolean write(byte[] bytes, int offset, int size) {
240         bytes = convert16To8Bits(bytes);
241         size /= 2;
242         System.arraycopy(bytes, offset, outputData, curIndex, size);
243         curIndex += size;
244         return true;
245     }
246
247
248     /**
249      * Converts an array of signed 16-bit audio data to unsigned 8-bit
250      * audio data.
251      *
252      * @param samples16Bit the signed 16-bit audio data to convert
253      *
254      * @return unsigned 8-bit audio data
255      */
256     private static byte[] convert16To8Bits(byte[] samples16Bit) {
257         byte[] samples8Bit = new byte[samples16Bit.length/2];
258         for (int i = 0, j = 0; i < samples16Bit.length; i += 2, j++) {
259             int sample = (0x000000FF & samples16Bit[i]);
260             samples8Bit[j] = (byte) (sample + 128);
261         }
262         return samples8Bit;
263     }
264
265
266     /**
267      * Returns the name of this audioplayer
268      *
269      * @return the name of the audio player
270      */
271     public String toString() {
272         return "MultiFile8BitAudioPlayer";
273     }
274
275     /**
276      * Shows metrics for this audio player
277      */
278     public void showMetrics() {
279     }
280 }