I'd like to load a sound file, store the sound as an object, and then
play it back at some later time. What are the classes appropriate
for that scheme? I have a lot of experience programming Java, aside
from audio, so really all I need is a pointer to the right approach,
and I think I can figure out the rest.
I just did this. You don't need the SPI packages...those are for
implementing audio services ("service provider interface"), not needed for
using them. You do need the javax.sound.sampled package.
The basic unit you need is the Clip class. You get one from the
AudioSystem class, and initialize it with an AudioInputStream, also
obtainable from the AudioSystem class using an existing InputStream (e.g..
created from a file, or from a resource in your .jar file).
Here's some sample code from my effort, followed by some notes regarding
"gotchas" I ran into:
// some variable used to store the reference to the
// Clip...put it wherever is appropriate for your needs
Clip clip;
// A stream that will read your data. In my case, I get this using
// Class.getResourceAsStream, but you can just as easily open a file
Stream streamSource;
// Then, where you want to initialize the Clip:
InputStream stream = new BufferedInputStream(streamSource);
AudioInputStream ais = AudioSystem.getAudioInputStream(stream);
clip = AudioSystem.getClip();
clip.open(ais);
ais.close();
clip.addLineListener(new LineListener()
{
public void update(LineEvent event)
{
if (event.getType() == LineEvent.Type.STOP)
{
clip.stop();
clip.setFramePosition(0);
}
}
});
// Finally, wherever you want to play the Clip:
if (clip != null && !clip.isActive())
{
clip.start();
}
Now, for the gotchas:
1) On at least one Java implementation (Mac OS), you must stop the
clip before you can start it again, even if the audio has actually reached
the end
2) On at least one Java implementation (Windows), you must also reset
the clip's position back to the beginning before playing it again (on the
Mac, the clip resets automatically if you stop it when it's reached the
end)
3) You need to use a BufferedInputStream to read the data, at least
when reading it as a resource. Without buffering, something goes wrong
and the clip can't be correctly initialized (an exception is thrown,
though I don't recall off the top of my head what exception it was).
I don't know Java well enough to know for sure whether closing the
AudioInputStream is sufficient for also closing the wrapped
BufferedInputStream and the original Stream (from the resource in my
case). I'm assuming it is, but someone might correct me on that point.
As you can see, the basic idea is actually very simple and not hard to
implement at all. Good luck and have fun!
Pete