/* * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */package com.sun.media.sound;import java.io.IOException;import java.io.InputStream;import java.io.BufferedInputStream;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.applet.AudioClip;import java.lang.InterruptedException;import javax.sound.sampled.AudioSystem;import javax.sound.sampled.Mixer;import javax.sound.sampled.Clip;import javax.sound.sampled.Control;import javax.sound.sampled.AudioInputStream;import javax.sound.sampled.AudioFormat;import javax.sound.sampled.DataLine;import javax.sound.sampled.SourceDataLine;import javax.sound.sampled.LineEvent;import javax.sound.sampled.LineListener;import javax.sound.sampled.LineUnavailableException;import javax.sound.sampled.UnsupportedAudioFileException;import javax.sound.midi.MidiSystem;import javax.sound.midi.MidiFileFormat;import javax.sound.midi.MetaMessage;import javax.sound.midi.Sequence;import javax.sound.midi.Sequencer;import javax.sound.midi.InvalidMidiDataException;import javax.sound.midi.MidiUnavailableException;import javax.sound.midi.MetaEventListener;/** * Java Sound audio clip; * * @author Arthur van Hoff, Kara Kytle, Jan Borgersen * @author Florian Bomers */public class JavaSoundAudioClip implements AudioClip, MetaEventListener, LineListener { private static final boolean DEBUG = false; private static final int BUFFER_SIZE = 16384; // number of bytes written each time to the source data line private long lastPlayCall = 0; private static final int MINIMUM_PLAY_DELAY = 30; private byte loadedAudio[] = null; private int loadedAudioByteLength = 0; private AudioFormat loadedAudioFormat = null; private AutoClosingClip clip = null; private boolean clipLooping = false; private DataPusher datapusher = null; private Sequencer sequencer = null; private Sequence sequence = null; private boolean sequencerloop = false; /** * used for determining how many samples is the * threshhold between playing as a Clip and streaming * from the file. * * $$jb: 11.07.99: the engine has a limit of 1M * samples to play as a Clip, so compare this number * with the number of samples in the stream. * */ private final static long CLIP_THRESHOLD = 1048576; //private final static long CLIP_THRESHOLD = 1; private final static int STREAM_BUFFER_SIZE = 1024; public JavaSoundAudioClip(InputStream in) throws IOException { if (DEBUG || Printer.debug)Printer.debug("JavaSoundAudioClip.<init>"); BufferedInputStream bis = new BufferedInputStream(in, STREAM_BUFFER_SIZE); bis.mark(STREAM_BUFFER_SIZE); boolean success = false; try { AudioInputStream as = AudioSystem.getAudioInputStream(bis); // load the stream data into memory success = loadAudioData(as); if (success) { success = false; if (loadedAudioByteLength < CLIP_THRESHOLD) { success = createClip(); } if (!success) { success = createSourceDataLine(); } } } catch (UnsupportedAudioFileException e) { // not an audio file try { MidiFileFormat mff = MidiSystem.getMidiFileFormat(bis); success = createSequencer(bis); } catch (InvalidMidiDataException e1) { success = false; } } if (!success) { throw new IOException("Unable to create AudioClip from input stream"); } } public synchronized void play() { startImpl(false); } public synchronized void loop() { startImpl(true); } private synchronized void startImpl(boolean loop) { // hack for some applets that call the start method very rapidly... long currentTime = System.currentTimeMillis(); long diff = currentTime - lastPlayCall; if (diff < MINIMUM_PLAY_DELAY) { if (DEBUG || Printer.debug) Printer.debug("JavaSoundAudioClip.startImpl(loop="+loop+"): abort - too rapdly"); return; } lastPlayCall = currentTime; if (DEBUG || Printer.debug) Printer.debug("JavaSoundAudioClip.startImpl(loop="+loop+")"); try { if (clip != null) { if (!clip.isOpen()) { if (DEBUG || Printer.trace)Printer.trace("JavaSoundAudioClip: clip.open()"); clip.open(loadedAudioFormat, loadedAudio, 0, loadedAudioByteLength); } else { if (DEBUG || Printer.trace)Printer.trace("JavaSoundAudioClip: clip.flush()"); clip.flush(); if (loop != clipLooping) { // need to stop in case the looped status changed if (DEBUG || Printer.trace)Printer.trace("JavaSoundAudioClip: clip.stop()"); clip.stop(); } } clip.setFramePosition(0); if (loop) { if (DEBUG || Printer.trace)Printer.trace("JavaSoundAudioClip: clip.loop()"); clip.loop(Clip.LOOP_CONTINUOUSLY); } else { if (DEBUG || Printer.trace)Printer.trace("JavaSoundAudioClip: clip.start()"); clip.start(); } clipLooping = loop; if (DEBUG || Printer.debug)Printer.debug("Clip should be playing/looping"); } else if (datapusher != null ) { datapusher.start(loop); if (DEBUG || Printer.debug)Printer.debug("Stream should be playing/looping"); } else if (sequencer != null) { sequencerloop = loop; if (sequencer.isRunning()) { sequencer.setMicrosecondPosition(0); } if (!sequencer.isOpen()) { try { sequencer.open(); sequencer.setSequence(sequence); } catch (InvalidMidiDataException e1) { if (DEBUG || Printer.err)e1.printStackTrace(); } catch (MidiUnavailableException e2) { if (DEBUG || Printer.err)e2.printStackTrace(); } } sequencer.addMetaEventListener(this); try { sequencer.start(); } catch (Exception e) { if (DEBUG || Printer.err) e.printStackTrace(); } if (DEBUG || Printer.debug)Printer.debug("Sequencer should be playing/looping"); } } catch (Exception e) { if (DEBUG || Printer.err)e.printStackTrace(); } } public synchronized void stop() { if (DEBUG || Printer.debug)Printer.debug("JavaSoundAudioClip->stop()"); lastPlayCall = 0; if (clip != null) { try { if (DEBUG || Printer.trace)Printer.trace("JavaSoundAudioClip: clip.flush()"); clip.flush(); } catch (Exception e1) { if (Printer.err) e1.printStackTrace(); } try { if (DEBUG || Printer.trace)Printer.trace("JavaSoundAudioClip: clip.stop()"); clip.stop(); } catch (Exception e2) { if (Printer.err) e2.printStackTrace(); } if (DEBUG || Printer.debug)Printer.debug("Clip should be stopped"); } else if (datapusher != null) { datapusher.stop(); if (DEBUG || Printer.debug)Printer.debug("Stream should be stopped"); } else if (sequencer != null) { try { sequencerloop = false; sequencer.addMetaEventListener(this); sequencer.stop(); } catch (Exception e3) { if (Printer.err) e3.printStackTrace(); } try { sequencer.close(); } catch (Exception e4) { if (Printer.err) e4.printStackTrace(); } if (DEBUG || Printer.debug)Printer.debug("Sequencer should be stopped"); } } // Event handlers (for debugging) public synchronized void update(LineEvent event) { if (DEBUG || Printer.debug) Printer.debug("line event received: "+event); } // handle MIDI track end meta events for looping public synchronized void meta( MetaMessage message ) { if (DEBUG || Printer.debug)Printer.debug("META EVENT RECEIVED!!!!! "); if( message.getType() == 47 ) { if (sequencerloop){ //notifyAll(); sequencer.setMicrosecondPosition(0); loop(); } else { stop(); } } } public String toString() { return getClass().toString(); } protected void finalize() { if (clip != null) { if (DEBUG || Printer.trace)Printer.trace("JavaSoundAudioClip.finalize: clip.close()"); clip.close(); } //$$fb 2001-09-26: may improve situation related to bug #4302884 if (datapusher != null) { datapusher.close(); } if (sequencer != null) { sequencer.close(); } } // FILE LOADING METHODS private boolean loadAudioData(AudioInputStream as) throws IOException, UnsupportedAudioFileException { if (DEBUG || Printer.debug)Printer.debug("JavaSoundAudioClip->openAsClip()"); // first possibly convert this stream to PCM as = Toolkit.getPCMConvertedAudioInputStream(as); if (as == null) { return false; } loadedAudioFormat = as.getFormat(); long frameLen = as.getFrameLength(); int frameSize = loadedAudioFormat.getFrameSize(); long byteLen = AudioSystem.NOT_SPECIFIED; if (frameLen != AudioSystem.NOT_SPECIFIED && frameLen > 0 && frameSize != AudioSystem.NOT_SPECIFIED && frameSize > 0) { byteLen = frameLen * frameSize; } if (byteLen != AudioSystem.NOT_SPECIFIED) { // if the stream length is known, it can be efficiently loaded into memory readStream(as, byteLen); } else { // otherwise we use a ByteArrayOutputStream to load it into memory readStream(as); } // if everything went fine, we have now the audio data in // loadedAudio, and the byte length in loadedAudioByteLength return true; } private void readStream(AudioInputStream as, long byteLen) throws IOException { // arrays "only" max. 2GB int intLen; if (byteLen > 2147483647) { intLen = 2147483647; } else { intLen = (int) byteLen; } loadedAudio = new byte[intLen]; loadedAudioByteLength = 0; // this loop may throw an IOException while (true) { int bytesRead = as.read(loadedAudio, loadedAudioByteLength, intLen - loadedAudioByteLength); if (bytesRead <= 0) { as.close(); break; } loadedAudioByteLength += bytesRead; } } private void readStream(AudioInputStream as) throws IOException { DirectBAOS baos = new DirectBAOS(); byte buffer[] = new byte[16384]; int bytesRead = 0; int totalBytesRead = 0; // this loop may throw an IOException while( true ) { bytesRead = as.read(buffer, 0, buffer.length); if (bytesRead <= 0) { as.close(); break; } totalBytesRead += bytesRead; baos.write(buffer, 0, bytesRead); } loadedAudio = baos.getInternalBuffer(); loadedAudioByteLength = totalBytesRead; } // METHODS FOR CREATING THE DEVICE private boolean createClip() { if (DEBUG || Printer.debug)Printer.debug("JavaSoundAudioClip.createClip()"); try { DataLine.Info info = new DataLine.Info(Clip.class, loadedAudioFormat); if (!(AudioSystem.isLineSupported(info)) ) { if (DEBUG || Printer.err)Printer.err("Clip not supported: "+loadedAudioFormat); // fail silently return false; } Object line = AudioSystem.getLine(info); if (!(line instanceof AutoClosingClip)) { if (DEBUG || Printer.err)Printer.err("Clip is not auto closing!"+clip); // fail -> will try with SourceDataLine return false; } clip = (AutoClosingClip) line; clip.setAutoClosing(true); if (DEBUG || Printer.debug) clip.addLineListener(this); } catch (Exception e) { if (DEBUG || Printer.err)e.printStackTrace(); // fail silently return false; } if (clip==null) { // fail silently return false; } if (DEBUG || Printer.debug)Printer.debug("Loaded clip."); return true; } private boolean createSourceDataLine() { if (DEBUG || Printer.debug)Printer.debug("JavaSoundAudioClip.createSourceDataLine()"); try { DataLine.Info info = new DataLine.Info(SourceDataLine.class, loadedAudioFormat); if (!(AudioSystem.isLineSupported(info)) ) { if (DEBUG || Printer.err)Printer.err("Line not supported: "+loadedAudioFormat); // fail silently return false; } SourceDataLine source = (SourceDataLine) AudioSystem.getLine(info); datapusher = new DataPusher(source, loadedAudioFormat, loadedAudio, loadedAudioByteLength); } catch (Exception e) { if (DEBUG || Printer.err)e.printStackTrace(); // fail silently return false; } if (datapusher==null) { // fail silently return false; } if (DEBUG || Printer.debug)Printer.debug("Created SourceDataLine."); return true; } private boolean createSequencer(BufferedInputStream in) throws IOException { if (DEBUG || Printer.debug)Printer.debug("JavaSoundAudioClip.createSequencer()"); // get the sequencer try { sequencer = MidiSystem.getSequencer( ); } catch(MidiUnavailableException me) { if (DEBUG || Printer.err)me.printStackTrace(); return false; } if (sequencer==null) { return false; } try { sequence = MidiSystem.getSequence(in); if (sequence == null) { return false; } } catch (InvalidMidiDataException e) { if (DEBUG || Printer.err)e.printStackTrace(); return false; } if (DEBUG || Printer.debug)Printer.debug("Created Sequencer."); return true; } /* * private inner class representing a ByteArrayOutputStream * which allows retrieval of the internal array */ private static class DirectBAOS extends ByteArrayOutputStream { public DirectBAOS() { super(); } public byte[] getInternalBuffer() { return buf; } } // class DirectBAOS}
/*
* Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.media.sound;
import java.io.IOException;
import java.io.InputStream;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.applet.AudioClip;
import java.lang.InterruptedException;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.Clip;
import javax.sound.sampled.Control;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiFileFormat;
import javax.sound.midi.MetaMessage;
import javax.sound.midi.Sequence;
import javax.sound.midi.Sequencer;
import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.MetaEventListener;
/**
* Java Sound audio clip;
*
* @author Arthur van Hoff, Kara Kytle, Jan Borgersen
* @author Florian Bomers
*/
public class JavaSoundAudioClip implements AudioClip, MetaEventListener, LineListener {
private static final boolean DEBUG = false;
private static final int BUFFER_SIZE = 16384; // number of bytes written each time to the source data line
private long lastPlayCall = 0;
private static final int MINIMUM_PLAY_DELAY = 30;
private byte loadedAudio[] = null;
private int loadedAudioByteLength = 0;
private AudioFormat loadedAudioFormat = null;
private AutoClosingClip clip = null;
private boolean clipLooping = false;
private DataPusher datapusher = null;
private Sequencer sequencer = null;
private Sequence sequence = null;
private boolean sequencerloop = false;
/**
* used for determining how many samples is the
* threshhold between playing as a Clip and streaming
* from the file.
*
* $$jb: 11.07.99: the engine has a limit of 1M
* samples to play as a Clip, so compare this number
* with the number of samples in the stream.
*
*/
private final static long CLIP_THRESHOLD = 1048576;
//private final static long CLIP_THRESHOLD = 1;
private final static int STREAM_BUFFER_SIZE = 1024;
public JavaSoundAudioClip(InputStream in) throws IOException {
if (DEBUG || Printer.debug)Printer.debug("JavaSoundAudioClip.<init>");
BufferedInputStream bis = new BufferedInputStream(in, STREAM_BUFFER_SIZE);
bis.mark(STREAM_BUFFER_SIZE);
boolean success = false;
try {
AudioInputStream as = AudioSystem.getAudioInputStream(bis);
// load the stream data into memory
success = loadAudioData(as);
if (success) {
success = false;
if (loadedAudioByteLength < CLIP_THRESHOLD) {
success = createClip();
}
if (!success) {
success = createSourceDataLine();
}
}
} catch (UnsupportedAudioFileException e) {
// not an audio file
try {
MidiFileFormat mff = MidiSystem.getMidiFileFormat(bis);
success = createSequencer(bis);
} catch (InvalidMidiDataException e1) {
success = false;
}
}
if (!success) {
throw new IOException("Unable to create AudioClip from input stream");
}
}
public synchronized void play() {
startImpl(false);
}
public synchronized void loop() {
startImpl(true);
}
private synchronized void startImpl(boolean loop) {
// hack for some applets that call the start method very rapidly...
long currentTime = System.currentTimeMillis();
long diff = currentTime - lastPlayCall;
if (diff < MINIMUM_PLAY_DELAY) {
if (DEBUG || Printer.debug) Printer.debug("JavaSoundAudioClip.startImpl(loop="+loop+"): abort - too rapdly");
return;
}
lastPlayCall = currentTime;
if (DEBUG || Printer.debug) Printer.debug("JavaSoundAudioClip.startImpl(loop="+loop+")");
try {
if (clip != null) {
if (!clip.isOpen()) {
if (DEBUG || Printer.trace)Printer.trace("JavaSoundAudioClip: clip.open()");
clip.open(loadedAudioFormat, loadedAudio, 0, loadedAudioByteLength);
} else {
if (DEBUG || Printer.trace)Printer.trace("JavaSoundAudioClip: clip.flush()");
clip.flush();
if (loop != clipLooping) {
// need to stop in case the looped status changed
if (DEBUG || Printer.trace)Printer.trace("JavaSoundAudioClip: clip.stop()");
clip.stop();
}
}
clip.setFramePosition(0);
if (loop) {
if (DEBUG || Printer.trace)Printer.trace("JavaSoundAudioClip: clip.loop()");
clip.loop(Clip.LOOP_CONTINUOUSLY);
} else {
if (DEBUG || Printer.trace)Printer.trace("JavaSoundAudioClip: clip.start()");
clip.start();
}
clipLooping = loop;
if (DEBUG || Printer.debug)Printer.debug("Clip should be playing/looping");
} else if (datapusher != null ) {
datapusher.start(loop);
if (DEBUG || Printer.debug)Printer.debug("Stream should be playing/looping");
} else if (sequencer != null) {
sequencerloop = loop;
if (sequencer.isRunning()) {
sequencer.setMicrosecondPosition(0);
}
if (!sequencer.isOpen()) {
try {
sequencer.open();
sequencer.setSequence(sequence);
} catch (InvalidMidiDataException e1) {
if (DEBUG || Printer.err)e1.printStackTrace();
} catch (MidiUnavailableException e2) {
if (DEBUG || Printer.err)e2.printStackTrace();
}
}
sequencer.addMetaEventListener(this);
try {
sequencer.start();
} catch (Exception e) {
if (DEBUG || Printer.err) e.printStackTrace();
}
if (DEBUG || Printer.debug)Printer.debug("Sequencer should be playing/looping");
}
} catch (Exception e) {
if (DEBUG || Printer.err)e.printStackTrace();
}
}
public synchronized void stop() {
if (DEBUG || Printer.debug)Printer.debug("JavaSoundAudioClip->stop()");
lastPlayCall = 0;
if (clip != null) {
try {
if (DEBUG || Printer.trace)Printer.trace("JavaSoundAudioClip: clip.flush()");
clip.flush();
} catch (Exception e1) {
if (Printer.err) e1.printStackTrace();
}
try {
if (DEBUG || Printer.trace)Printer.trace("JavaSoundAudioClip: clip.stop()");
clip.stop();
} catch (Exception e2) {
if (Printer.err) e2.printStackTrace();
}
if (DEBUG || Printer.debug)Printer.debug("Clip should be stopped");
} else if (datapusher != null) {
datapusher.stop();
if (DEBUG || Printer.debug)Printer.debug("Stream should be stopped");
} else if (sequencer != null) {
try {
sequencerloop = false;
sequencer.addMetaEventListener(this);
sequencer.stop();
} catch (Exception e3) {
if (Printer.err) e3.printStackTrace();
}
try {
sequencer.close();
} catch (Exception e4) {
if (Printer.err) e4.printStackTrace();
}
if (DEBUG || Printer.debug)Printer.debug("Sequencer should be stopped");
}
}
// Event handlers (for debugging)
public synchronized void update(LineEvent event) {
if (DEBUG || Printer.debug) Printer.debug("line event received: "+event);
}
// handle MIDI track end meta events for looping
public synchronized void meta( MetaMessage message ) {
if (DEBUG || Printer.debug)Printer.debug("META EVENT RECEIVED!!!!! ");
if( message.getType() == 47 ) {
if (sequencerloop){
//notifyAll();
sequencer.setMicrosecondPosition(0);
loop();
} else {
stop();
}
}
}
public String toString() {
return getClass().toString();
}
protected void finalize() {
if (clip != null) {
if (DEBUG || Printer.trace)Printer.trace("JavaSoundAudioClip.finalize: clip.close()");
clip.close();
}
//$$fb 2001-09-26: may improve situation related to bug #4302884
if (datapusher != null) {
datapusher.close();
}
if (sequencer != null) {
sequencer.close();
}
}
// FILE LOADING METHODS
private boolean loadAudioData(AudioInputStream as) throws IOException, UnsupportedAudioFileException {
if (DEBUG || Printer.debug)Printer.debug("JavaSoundAudioClip->openAsClip()");
// first possibly convert this stream to PCM
as = Toolkit.getPCMConvertedAudioInputStream(as);
if (as == null) {
return false;
}
loadedAudioFormat = as.getFormat();
long frameLen = as.getFrameLength();
int frameSize = loadedAudioFormat.getFrameSize();
long byteLen = AudioSystem.NOT_SPECIFIED;
if (frameLen != AudioSystem.NOT_SPECIFIED
&& frameLen > 0
&& frameSize != AudioSystem.NOT_SPECIFIED
&& frameSize > 0) {
byteLen = frameLen * frameSize;
}
if (byteLen != AudioSystem.NOT_SPECIFIED) {
// if the stream length is known, it can be efficiently loaded into memory
readStream(as, byteLen);
} else {
// otherwise we use a ByteArrayOutputStream to load it into memory
readStream(as);
}
// if everything went fine, we have now the audio data in
// loadedAudio, and the byte length in loadedAudioByteLength
return true;
}
private void readStream(AudioInputStream as, long byteLen) throws IOException {
// arrays "only" max. 2GB
int intLen;
if (byteLen > 2147483647) {
intLen = 2147483647;
} else {
intLen = (int) byteLen;
}
loadedAudio = new byte[intLen];
loadedAudioByteLength = 0;
// this loop may throw an IOException
while (true) {
int bytesRead = as.read(loadedAudio, loadedAudioByteLength, intLen - loadedAudioByteLength);
if (bytesRead <= 0) {
as.close();
break;
}
loadedAudioByteLength += bytesRead;
}
}
private void readStream(AudioInputStream as) throws IOException {
DirectBAOS baos = new DirectBAOS();
byte buffer[] = new byte[16384];
int bytesRead = 0;
int totalBytesRead = 0;
// this loop may throw an IOException
while( true ) {
bytesRead = as.read(buffer, 0, buffer.length);
if (bytesRead <= 0) {
as.close();
break;
}
totalBytesRead += bytesRead;
baos.write(buffer, 0, bytesRead);
}
loadedAudio = baos.getInternalBuffer();
loadedAudioByteLength = totalBytesRead;
}
// METHODS FOR CREATING THE DEVICE
private boolean createClip() {
if (DEBUG || Printer.debug)Printer.debug("JavaSoundAudioClip.createClip()");
try {
DataLine.Info info = new DataLine.Info(Clip.class, loadedAudioFormat);
if (!(AudioSystem.isLineSupported(info)) ) {
if (DEBUG || Printer.err)Printer.err("Clip not supported: "+loadedAudioFormat);
// fail silently
return false;
}
Object line = AudioSystem.getLine(info);
if (!(line instanceof AutoClosingClip)) {
if (DEBUG || Printer.err)Printer.err("Clip is not auto closing!"+clip);
// fail -> will try with SourceDataLine
return false;
}
clip = (AutoClosingClip) line;
clip.setAutoClosing(true);
if (DEBUG || Printer.debug) clip.addLineListener(this);
} catch (Exception e) {
if (DEBUG || Printer.err)e.printStackTrace();
// fail silently
return false;
}
if (clip==null) {
// fail silently
return false;
}
if (DEBUG || Printer.debug)Printer.debug("Loaded clip.");
return true;
}
private boolean createSourceDataLine() {
if (DEBUG || Printer.debug)Printer.debug("JavaSoundAudioClip.createSourceDataLine()");
try {
DataLine.Info info = new DataLine.Info(SourceDataLine.class, loadedAudioFormat);
if (!(AudioSystem.isLineSupported(info)) ) {
if (DEBUG || Printer.err)Printer.err("Line not supported: "+loadedAudioFormat);
// fail silently
return false;
}
SourceDataLine source = (SourceDataLine) AudioSystem.getLine(info);
datapusher = new DataPusher(source, loadedAudioFormat, loadedAudio, loadedAudioByteLength);
} catch (Exception e) {
if (DEBUG || Printer.err)e.printStackTrace();
// fail silently
return false;
}
if (datapusher==null) {
// fail silently
return false;
}
if (DEBUG || Printer.debug)Printer.debug("Created SourceDataLine.");
return true;
}
private boolean createSequencer(BufferedInputStream in) throws IOException {
if (DEBUG || Printer.debug)Printer.debug("JavaSoundAudioClip.createSequencer()");
// get the sequencer
try {
sequencer = MidiSystem.getSequencer( );
} catch(MidiUnavailableException me) {
if (DEBUG || Printer.err)me.printStackTrace();
return false;
}
if (sequencer==null) {
return false;
}
try {
sequence = MidiSystem.getSequence(in);
if (sequence == null) {
return false;
}
} catch (InvalidMidiDataException e) {
if (DEBUG || Printer.err)e.printStackTrace();
return false;
}
if (DEBUG || Printer.debug)Printer.debug("Created Sequencer.");
return true;
}
/*
* private inner class representing a ByteArrayOutputStream
* which allows retrieval of the internal array
*/
private static class DirectBAOS extends ByteArrayOutputStream {
public DirectBAOS() {
super();
}
public byte[] getInternalBuffer() {
return buf;
}
} // class DirectBAOS
}