AudioBuffer.java |
package audio; import java.io.*; import javax.sound.sampled.*; /********************************************************/ /** * An AudioBuffer is a self-describing fragment of audio in memory. * It can be read and written in a manner similar to * java.io.ByteArrayInputStream and java.io.ByteArrayOutputStream. * It knows how to transcode itself from one audio format to another. * <p> * GRJ - 11/5/02 - This code can probably be simplifed somewhat, but * my initial goal was to break out this functionality. The goal * was to make an interface that works. The implementation can be * cleaned up in the next version. * */ public class AudioBuffer{ private AudioFormat format = null; private byte[] audioByteArray = null; private AudioInputStream inputStream = null; private ByteArrayOutputStream outputStream = null; /********************************************************/ /** * Construct an empty AudioBuffer which will hold data of the * specified format. */ public AudioBuffer(AudioFormat format){ this.format = format; } /********************************************************/ /** * Construct an AudioBuffer containing audio from the supplied * byte array. */ public AudioBuffer(AudioFormat format, byte[] audioByteArray){ this.format = format; this.audioByteArray = audioByteArray; } /********************************************************/ /** * Construct an AudioBuffer containing audio from the supplied * AudioInputStream. */ public AudioBuffer(AudioInputStream ais){ try{ audioByteArray = new byte[ais.available()]; ais.mark(ais.available()); ais.read(audioByteArray, 0, ais.available()); format = ais.getFormat(); ais.reset(); }catch(IOException ioe){ // what should I do here? ioe.printStackTrace(); } } /********************************************************/ /** * Get the AudioFormat.Encoding corresponding to the AudioBuffer's * audio data. */ public AudioFormat.Encoding getEncoding(){ return format.getEncoding(); } /********************************************************/ /** * Get the sample rate (samples per second) of the AudioBuffer's data. */ public float getSampleRate(){ return format.getSampleRate(); } /********************************************************/ /** * Get the frame size (bytes per sample) of the AudioBuffer's data. */ public int getFrameSize(){ return format.getFrameSize(); } /********************************************************/ /** * Get the audio format of the buffer's data as an AudioFormat object. */ public AudioFormat getFormat(){ return format; } /********************************************************/ /** * Obtain a byte array that contains the AudioBuffer's data. */ public byte[] toByteArray(){ return audioByteArray; } /********************************************************/ /** * Obtain an AudioInputStream that contains the AudioBuffer's data. */ public AudioInputStream toAudioInputStream(){ inputStream = new AudioInputStream( new ByteArrayInputStream(audioByteArray), format, audioByteArray.length / format.getFrameSize() ); return inputStream; } /********************************************************/ /** * Convert the encoding of the audio in the buffer to the * specified encoding. * <p> * GRJ - 11/5/02 - This is inefficient code. See disclaimer above. * <p> * Also, there seems to be a bug in the implementation here (or in * the transcoding version of AudioSystem.getAudioInputStream used by * the implementation?). The available() method of AudioInputStream does * not return a different length after the transcode if the number * of bytes per sample changes. I had to do a workaround. */ public void transcode(AudioFormat.Encoding destinationEncoding){ if (destinationEncoding == null){ return; } try{ AudioFormat formats[] = AudioSystem.getTargetFormats(destinationEncoding, format); int inputByteLength = audioByteArray.length; int outputByteLength = inputByteLength * formats[0].getFrameSize() / format.getFrameSize(); AudioInputStream ais = new AudioInputStream( new ByteArrayInputStream(audioByteArray), format, inputByteLength / format.getFrameSize() ); ais = AudioSystem.getAudioInputStream(formats[0], ais); byte[] newByteArray = new byte[outputByteLength]; ais.read(newByteArray, 0, outputByteLength); format = formats[0]; ais.close(); audioByteArray = newByteArray; inputStream = null; }catch(IOException ioe){ // what should I do here? ioe.printStackTrace(); } } /********************************************************/ /** * Retrieve data from the buffer. */ public int read(byte[] b, int off, int len) throws IOException{ if (inputStream == null){ toAudioInputStream(); } return inputStream.read(b, off, len); } /********************************************************/ /** * Add data to the buffer. */ public void write(byte[] b, int off, int len){ if (outputStream == null){ outputStream = new ByteArrayOutputStream(); } outputStream.write(b, off, len); audioByteArray = outputStream.toByteArray(); } }