001/** 002 * Copyright 2001 Sun Microsystems, Inc. 003 * 004 * See the file "license.terms" for information on usage and 005 * redistribution of this file, and for a DISCLAIMER OF ALL 006 * WARRANTIES. 007 */ 008package com.sun.speech.freetts.audio; 009 010import java.io.ByteArrayInputStream; 011import java.io.File; 012import java.io.IOException; 013 014import javax.sound.sampled.AudioFileFormat; 015import javax.sound.sampled.AudioFormat; 016import javax.sound.sampled.AudioInputStream; 017import javax.sound.sampled.AudioSystem; 018 019import com.sun.speech.freetts.util.Utilities; 020 021/** 022 * Streams audio to multiple files, one per utterance. 023 * 024 * 025 */ 026public class MultiFileAudioPlayer implements AudioPlayer { 027 private AudioFormat currentFormat = null; 028 private int fileCount = 0; 029 private String baseName; 030 private byte[] outputData; 031 private int curIndex = 0; 032 private AudioFileFormat.Type outputType; 033 034 /** 035 * Creates a default audio player for an AudioFileFormat of type 036 * WAVE. Reads the "com.sun.speech.freetts.AudioPlayer.baseName" 037 * property for the base filename to use, and will produce files 038 * of the form <baseName>1.wav. The default value for the 039 * base name is "freetts". 040 */ 041 public MultiFileAudioPlayer() { 042 this(Utilities.getProperty( 043 "com.sun.speech.freetts.AudioPlayer.baseName", "freetts"), 044 AudioFileFormat.Type.WAVE); 045 } 046 047 /** 048 * Constructs a MultiFileAudioPlayer 049 * 050 * @param baseName the base name of the audio file 051 * @param type the type of audio output 052 * 053 */ 054 public MultiFileAudioPlayer(String baseName, AudioFileFormat.Type type) { 055 this.baseName = baseName; 056 this.outputType = type; 057 } 058 059 /** 060 * Sets the audio format for this player 061 * 062 * @param format the audio format 063 * 064 * @throws UnsupportedOperationException if the line cannot be opened with 065 * the given format 066 */ 067 public synchronized void setAudioFormat(AudioFormat format) { 068 currentFormat = format; 069 } 070 071 072 /** 073 * Gets the audio format for this player 074 * 075 * @return format the audio format 076 */ 077 public AudioFormat getAudioFormat() { 078 return currentFormat; 079 } 080 081 082 /** 083 * Pauses audio output 084 */ 085 public void pause() { 086 } 087 088 /** 089 * Resumes audio output 090 */ 091 public synchronized void resume() { 092 } 093 094 /** 095 * Starts the first sample timer 096 */ 097 public void startFirstSampleTimer() { 098 } 099 100 101 /** 102 * Cancels currently playing audio 103 */ 104 public synchronized void cancel() { 105 } 106 107 /** 108 * Prepares for another batch of output. Larger groups of output 109 * (such as all output associated with a single FreeTTSSpeakable) 110 * should be grouped between a reset/drain pair. 111 */ 112 public synchronized void reset() { 113 } 114 115 /** 116 * Closes this audio player 117 */ 118 public synchronized void close() { 119 } 120 121 /** 122 * Returns the current volume. 123 * 124 * @return the current volume (between 0 and 1) 125 */ 126 public float getVolume() { 127 return 1.0f; 128 } 129 130 /** 131 * Sets the current volume. 132 * 133 * @param volume the current volume (between 0 and 1) 134 */ 135 public void setVolume(float volume) { 136 } 137 138 139 140 141 /** 142 * Starts the output of a set of data. Audio data for a single 143 * utterance should be grouped between begin/end pairs. 144 * 145 * @param size the size of data between now and the end 146 */ 147 public void begin(int size) { 148 outputData = new byte[size]; 149 curIndex = 0; 150 } 151 152 /** 153 * {@inheritDoc} 154 */ 155 public boolean end() throws IOException { 156 ByteArrayInputStream bais = new ByteArrayInputStream(outputData); 157 AudioInputStream ais = new AudioInputStream(bais, 158 currentFormat, outputData.length/currentFormat.getFrameSize()); 159 String name = baseName; 160 name = name + fileCount; 161 name = name + "." + outputType.getExtension(); 162 File file = new File(name); 163 try { 164 AudioSystem.write(ais, outputType, file); 165 System.out.println("Wrote synthesized speech to " + name); 166 } catch (IllegalArgumentException iae) { 167 throw new IOException("Can't write audio type " + outputType, iae); 168 } 169 fileCount++; 170 return true; 171 } 172 173 /** 174 * Waits for all queued audio to be played 175 * 176 * @return true if the audio played to completion, false if 177 * the audio was stopped 178 */ 179 public boolean drain() { 180 return true; 181 } 182 183 /** 184 * Gets the amount of played since the last mark 185 * 186 * @return the amount of audio in milliseconds 187 */ 188 public synchronized long getTime() { 189 return -1L; 190 } 191 192 193 /** 194 * Resets the audio clock 195 */ 196 public synchronized void resetTime() { 197 } 198 199 200 201 /** 202 * Writes the given bytes to the audio stream 203 * 204 * @param audioData audio data to write to the device 205 * 206 * @return <code>true</code> of the write completed successfully, 207 * <code> false </code>if the write was cancelled. 208 */ 209 public boolean write(byte[] audioData) { 210 return write(audioData, 0, audioData.length); 211 } 212 213 /** 214 * Writes the given bytes to the audio stream 215 * 216 * @param bytes audio data to write to the device 217 * @param offset the offset into the buffer 218 * @param size the size into the buffer 219 * 220 * @return <code>true</code> of the write completed successfully, 221 * <code> false </code>if the write was cancelled. 222 */ 223 public boolean write(byte[] bytes, int offset, int size) { 224 System.arraycopy(bytes, offset, outputData, curIndex, size); 225 curIndex += size; 226 return true; 227 } 228 229 /** 230 * Returns the name of this audioplayer 231 * 232 * @return the name of the audio player 233 */ 234 public String toString() { 235 return "FileAudioPlayer"; 236 } 237 238 239 /** 240 * Shows metrics for this audio player 241 */ 242 public void showMetrics() { 243 } 244}