Add MP3 capabilities to Java Sound with SPI

The Service Provider Interface adds functionality to Java Sound without recoding

1 2 Page 2
Page 2 of 2

Since in this article we intend to describe and implement a Java service provider, I will gloss over the nuances of MP3 decoding and refer you instead to the source code. For this article, we use a free, 100 percent Java, open source MP3 decoder from the JavaLayer Project (see Resources). The JavaLayer Project was publicly developed by a programmer nicknamed JavaZOOM with contributors Mat MacGowan and Matthias Pfisterer. Download the small module and add the JavaLayer JAR file (for example jl008.jar) to your Java classpath.

Now let's take a break and take a deep breath. We've gone over in detail the classes and methods necessary to provide a new service to Java Sound: reading and decoding MP3 audio files. If that seems daunting, realize that other sound decoders will use an identical framework to enhance Java Sound. It is now time to bundle up and test our creation.

Packaging and testing

At this point, we have created several class files to implement the Java Sound SPI to read and play MP3 files. In this section we package all our work and test it, using an ordinary Java audio player program.

First, you must create a jar file that contains all the classes. That is done using the command:

   jar -cvf MP3.jar *.class

That command creates the MP3.jar file and places all the class files in it. Additionally, we must provide the META/services directory discussed earlier in this article. To accomplish that, create two files javax.sound.sampled.spi.AudioFileReader and javax.sound.sampled.spi.FormatConversionProvider and place the name of the service provider classes in them. Take care when editing or checking those files in and out of a source-code control system: if you treat them as ASCII, your editor might introduce extraneous spaces or line-feed characters. Both files should be UTF-8 encoded bytes. Here are the full contents of the first file:

# Providers for audio file reading
BasicMP3FileReader

Add these files to the jar file using the command:

   jar -uvf MP3.jar META-INF/services

Now add the MP3.jar file to your Java runtime environment classpath. Recall that Java Sound uses the provider name list in the services directory to find mixers, file reader and writers, format converter, and other sound-related functions. Java Sound is written to load and instantiate each provider class name and ask whether it can handle certain types of sounds.

To test our extension to Java Sound, let's test it with an ordinary audio program written for Java Sound. One example program is Play.java, provided with this article. Play.java, a simple audio player, will now handle MP3 files as well as the standard sampled file formats (AU, WAV, and AIFF). If you are not familiar with playing sampled audio files in Java 2 version 1.3, you should review the code in the play example or check out the Java Sound examples on Matthias Pfisterer's sound page (see Resources)

Due to Java audio's limitations, your favorite Java audio program may not work with MP3 files, so don't blame it on the service provider! For instance, the Java Sound demo provided with the SDK has a nice Swing-based jukebox applet called Juke that uses the Clip interface to load sound files. Unfortunately, the Clip interface requires that the entire file be decoded and loaded into memory, causing it to fail with an OutOfMemory error if you attempt to load large MP3 songs. Don't blame the service provider, however; it also will fail if you try to load large WAV songs! Unfortunately, the Clip interface is used with the Applet AudioClip class, and thus many older Java audio programs will also run out of memory if you attempt to load large songs. To write a good jukebox, it's best to use the Java DataLine interfaces, which allow audio files to be streamed, reducing memory requirements.

Conclusion

In this article, we've examined the details of the Java Service Provider Interface. Rather than just an academic example, we've looked at a useful example, a full-fledged MP3 decoder that allows any Java program to play MP3 audio files. Because the Java Service Provider extends the JVM, all that is done without rewriting or recompiling the original Java sound program.

Why is that useful? It opens the door for all sorts of audio formats, such as the exciting new Dolby labs Advanced Audio Codec (AAC) or any future audio format, to be added to Java Sound without forcing existing Java programs to be rewritten.

Learn more about this topic

1 2 Page 2
Page 2 of 2