Initial primitive sound manager that provides facilities for >gasp<

playing sounds.


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@1611 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Walter Korman
2002-07-24 21:28:10 +00:00
parent 4e55c7dc0e
commit f930d53cdd
2 changed files with 231 additions and 0 deletions
@@ -0,0 +1,191 @@
//
// $Id: SoundManager.java,v 1.1 2002/07/24 21:28:09 shaper Exp $
package com.threerings.media;
import java.io.IOException;
import java.io.InputStream;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine.Info;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.Line;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.Mixer;
import com.samskivert.util.Queue;
import com.threerings.resource.ResourceManager;
import com.threerings.media.Log;
/**
* Manages the playing of audio files.
*/
public class SoundManager
implements LineListener
{
/**
* Constructs a sound manager.
*/
public SoundManager (ResourceManager rmgr)
{
// save things off
_rmgr = rmgr;
// obtain the mixer
_mixer = AudioSystem.getMixer(null);
if (_mixer == null) {
Log.warning("Can't get default mixer, aborting audio " +
"initialization.");
return;
}
// create a thread to manage the sound queue
_player = new Thread() {
public void run () {
while (true) {
// wait for a sound
_clips.waitForItem();
// play the sound
playSound((String)_clips.get());
}
}
};
_player.setDaemon(true);
_player.start();
}
/**
* Queues up the sound file with the given pathname to be played when
* the sound manager deems the time appropriate.
*/
public void play (String path)
{
Log.debug("Queueing sound [path=" + path + "].");
_clips.append(path);
}
/**
* Plays the sound file with the given pathname.
*/
protected void playSound (String path)
{
Log.debug("Playing sound [path=" + path + "].");
// get the resource input stream
InputStream in = null;
try {
in = _rmgr.getResource(path);
} catch (IOException ioe) {
Log.warning("Failed to obtain resource input stream " +
"[path=" + path + ", ioe=" + ioe + "].");
return;
}
try {
// get the audio input stream and format
AudioInputStream ais = AudioSystem.getAudioInputStream(in);
// ais = getPCMAudioStream(ais);
AudioFormat format = ais.getFormat();
Log.debug("Obtained stream [format=" + format + "].");
// get the audio output line
Clip clip = (Clip)getLine(Clip.class, ais);
if (clip != null) {
// listen to our audio antics
clip.addLineListener(this);
// and start the clip playing
clip.open(ais);
clip.start();
}
} catch (Exception e) {
Log.warning("Failed to play sound [path=" + path +
", e=" + e + "].");
Log.logStackTrace(e);
}
}
// documentation inherited
public void update (LineEvent event)
{
// Log.info("LineListener update [event=" + event + "].");
Clip clip = (Clip)event.getLine();
if (event.getType() == LineEvent.Type.STOP) {
// shut the clip down
// clip.stop();
// clip.close();
Log.debug("Finished playing sound [clip=" + clip + "].");
}
}
/**
* Returns an audio stream from the given audio stream with the sound
* data converted to a <code>PCM_SIGNED</code> format playable in JDK
* 1.4-beta3.
*/
protected AudioInputStream getPCMAudioStream (AudioInputStream ais)
{
AudioFormat format = ais.getFormat();
AudioFormat pcmFormat = new AudioFormat(
AudioFormat.Encoding.PCM_SIGNED,
format.getSampleRate(),
format.getSampleSizeInBits() * 2,
format.getChannels(),
format.getFrameSize() * 2,
format.getFrameRate(),
true);
return AudioSystem.getAudioInputStream(pcmFormat, ais);
}
/**
* Returns a line suitable for playing the audio in the given stream,
* or <code>null</code> if an error occurred.
*/
protected Line getLine (Class clazz, AudioInputStream ais)
{
AudioFormat format = ais.getFormat();
int bufferSize = (int)(ais.getFrameLength() * format.getFrameSize());
DataLine.Info info = new DataLine.Info(clazz, format, bufferSize);
if (!AudioSystem.isLineSupported(info)) {
Log.warning("Audio line for clip playback not supported " +
"[format=" + format + "].");
return null;
}
// Log.info("Checking available lines " +
// "[num=" + _mixer.getMaxLines(info) + "].");
// obtain a reference to the line
Line line;
try {
line = AudioSystem.getLine(info);
// line.open(format);
} catch (LineUnavailableException lue) {
Log.warning("Failed to open audio line [lue=" + lue + "].");
return null;
}
return line;
}
/** The resource manager from which we obtain audio files. */
protected ResourceManager _rmgr;
/** The thread that plays sounds. */
protected Thread _player;
/** The queue of sound clips to be played. */
protected Queue _clips = new Queue();
/** The default mixer. */
protected Mixer _mixer;
}
@@ -0,0 +1,40 @@
//
// $Id: SoundTestApp.java,v 1.1 2002/07/24 21:28:10 shaper Exp $
package com.threerings.media;
import com.samskivert.util.StringUtil;
import com.threerings.resource.ResourceManager;
import com.threerings.media.Log;
public class SoundTestApp
{
public SoundTestApp (String[] args)
{
if (args.length == 0) {
Log.info("Usage: runjava com.threerings.media.SoundTestApp " +
"<file1> [<file2> <file3> ...]");
System.exit(0);
}
ResourceManager rmgr = new ResourceManager("rsrc");
_soundmgr = new SoundManager(rmgr);
_files = args;
}
public void run ()
{
for (int ii = 0; ii < _files.length; ii++) {
_soundmgr.play(_files[ii]);
}
}
public static void main (String[] args)
{
SoundTestApp app = new SoundTestApp(args);
app.run();
}
protected String[] _files;
protected SoundManager _soundmgr;
}