Java Sound API
To play sampled sound in your Java game, you use the Java Sound API, in the package, javax.sound.sampled. Java Sound can play sound formats with 8- or 16-bit samples with sample rates from 8000Hz to 48,000Hz. Also, it can play either mono or stereo sound. What sound format you use for your game depends on what you want. For these examples, we use 16-bit, mono, 44,100Hz sound. If you are feeling brave, you could generate all these samples yourself in code, but typically you'll want to get sound samples from a sound file. Java Sound provides support for reading three sampled sound file formats: AIFF, AU, and WAV. All formats are very flexible, and it doesn't make much of a difference which one you use. We use the WAV format in our examples. Some sound programs that you can use to create, record, and edit sounds are Pro Tools FREE (www.digidesign.com/ptfree), Cool Edit (www.syntrillium.com/cooledit), GoldWave (www.goldwave.com), and Audacity (audacity.sf.net). Be sure to check out , "Creating Game Art and Sounds," to get some ideas on creating sounds.
Opening a Sound File
You can load a sound file with Java Sound using the AudioSystem class. The AudioSystem class contains several static functions, most of which you won't use. But it provides several getAudioInputStream() methods to open an audio file from the file system or other source, such as the Internet. These methods return an AudioInputStream object. With an AudioInputStream object, you can read the samples of a sound without having to mess with the sound file header or other extra information in the file. Also, you can query the format of the sound by calling the getFormat() method:
File file = new File("sound.wav"); AudioInputStream stream = AudioSystem.getAudioInputStream(file); AudioFormat format = stream.getFormat();
The AudioFormat class provides a way to get information about the format of the sound, such as the sample rate and number of channels. Also, it provides a way to get the frame size, which is the number of bytes required for every sample for every channel. For 16-bit stereo sound, the frame size is four, or 2 bytes for each sample (left and right). This can be useful if you want to find out how many bytes it takes to store a sound in memory. For example, a three-second-long sound with an audio format of 16-bit samples, stereo, 44,100Hz would be 44,100x3x4 bytes, or about 517KB. Using mono instead of stereo would cut the size in half.
Using a Line
Okay, now that you have a way to get the sound samples and the format they are in, what do you do with them? The answer is to feed them through a Line. A Line is an interface to send or receive audio from the sound system. You can use Lines to send sound samples to the sound system to play or to receive sound from, say, a microphone. The Line interface has several subinterfaces. The main Line subinterface used here is a SourceDataLine, which enables you to write audio data to the sound system. Lines are created by using AudioSystem's getLine() method. You pass this method a Line.Info object, which specifies the type of Line you want to create. Line.Info has a DataLine.Info subclass, which you'll use to create your Lines because it contains information on the line's audio format. Besides SourceDataLine, we'll touch on another Line called a Clip. A Clip does a lot of work for you, loading samples into memory from an AudioInputStream and feeding them to the audio system automatically. Here is how you would extend the AudioInputStream to play it using a Clip:
// specify what kind of line we want to create DataLine.Info info = new DataLine.Info(Clip.class, format); // create the line Clip clip = (Clip)AudioSystem.getLine(info); // load the samples from the stream clip.open(stream); // begin playback of the sound clip clip.start();
Clips are convenient and easy to use, and are similar to AudioClips introduced in Java SDK 1.0. But Clips have some drawbacks. Java Sound has a limit to the number of Lines you can have open at the same time, which is usually a maximum of 32 Lines. Because Clips are Lines, this means you can open only a limited number of sounds, even before you play any one of them. Also, although several Clips can play simultaneously, each Clip can play only one sound at a time. For example, if you want two or three explosions to play simultaneously, you'll need a Clip for each one. Because of these drawbacks, in the next section you'll create a solution that will enable you to load any number of sounds and play several copies of each sound simultaneously.