Java Reference
In-Depth Information
An
AudioInputStream
is an
InputStream
and works just like other
InputStream
objects, so we can just
read the content to an
AudioInputStream
like we would any other
InputStream
. In this case, we read the
content from
decodedInputStream
and write the data to the
ByteArrayOutputStream
object's
baos
. The
variable
baos
is a temporary variable whose content is dumped into the variable
decodedAudio
. This is
our end goal—to have the entire song decoded and stored in memory. This not only allows us to play the
music but also give us the ability to stop and start playing the song form any point.
Working with the Audio Data
The last thing that the method
init
does is use the
AudioSubsystem
class again to create a
DataLine
. A
DataLine
object allows us to actually make sound come out of the speakers; the class
SoundRunnable
, as
shown in Listing 9-3, does this in a separate thread.
Listing 9-3.
SoundRunnable
private class SoundRunnable implements Runnable {
public void run() {
try {
byte[] data = new byte[bytesPerChunk];
byte[] dataToAudio = new byte[bytesPerChunk];
int nBytesRead;
while (true) {
if (isPlaying) {
while (isPlaying && (nBytesRead = decodedAudio.read(data, 0,
data.length)) != -1) {
for (int i = 0; i < nBytesRead; i++) {
dataToAudio[i] = (byte) (data[i] * volume);
}
line.write(dataToAudio, 0, nBytesRead);
audioConsumer.writeAudioData(data);
currentChunk++;
}
}
Thread.sleep(10);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
In Listing 9-3 we can see that the class
SoundRunnable
implements
Runnable
, which requires the
method
run
to be implemented. In the
run
method there are two
while
loops. The outer loop is used to
toggle whether sound should be playing or not. The inner loop does the real work; it reads a chunk of