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:
@@ -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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user