Links

  • 1. Sogeti
  • 2. JBoss
  • 3. IBM
  • 4. Oracle
  • 5. SpringSource
  • 6. NL-JUG
  • 7. Java

Archives

Syndication  RSS 2.0

RSS 1.0
RSS 2.0

Bookmark this site

Add 'JCN Blog' site to delicious  Add 'JCN Blog' site to technorati  Add 'JCN Blog' site to digg  Add 'JCN Blog' site to dzone

Posted by Martijn van de Rijdt at 18:18 on Saturday 14 August    Add 'Java sound' site to delicious  Add 'Java sound' site to technorati  Add 'Java sound' site to digg  Add 'Java sound' site to dzone

Recently I’ve been working on an application which, when a certain event occurs, should give off a warning to its end user. A warning in this case literally means displaying a bright red warning screen and blaring an audio clip. Displaying a red screen wasn’t too hard, but I don’t deal with playing audio from Java applications every day, so that took me a little effort.

java.applet.AudioClip

My first solution was using the java.applet.AudioClip class. As part of the application’s initialisation the audio clip is read from the file system and store it in a local variable:

File file = new File("src/test/resources/warning.wav");
URL url = file.toURI().toURL();
this.warningClip = Applet.newAudioClip(url);

(Plus some exception handling.)

Handling of the “warning” event could simply be implemented as follows:

this.warningClip.play();

I liked this solution, for several reasons. First of all, java.applet.AudioClip is part of the JRE, so there’s no need to use any additional Java libraries. Secondly, it’s nice and simple. On top of that, it supports multiple different types of audio transparently. The Applet.newAudioClip() method supports multiple audio file formats, and there’s no need for me to specify which is used. This was a nice feature, because when I wrote this all I had was a placeholder .wav file; we would still need to choose (or record!) an audio clip to be used, and it would be nice if we could just plug the new audio clip in without needing to convert it or change the code.

However, of course I ran into a problem. As it turns out, our warning event doesn’t occur very often, but when it does, it does so every second for a brief period of time. This means AudioClip.play() will be called every second as well. Whenever the play method is called, it checks whether the clip is already playing, and if so, the clip is stopped and restarted from the beginning. This isn’t the behaviour we wanted – if the clip is already playing when a new warning event occurs, it should just continue playing.

The obvious solution would be to check whether the clip is already playing before calling AudioClip.play(). However, as it turns out, this is not possible. AudioClip only offers a few methods: play(), stop() and loop(), and nothing else. If you want to do anything more complicated than that with an audio clip, Sun recommends using the Java Sound API, which is part of the JDK.

Java Sound API

Very well then! I took a look at its documentation, which was pretty daunting. I figured playback of an audio clip would be one of the first and most basic things people would want to do with the Java Sound API, but a quick Google search didn’t turn up any straightforward examples. I did find some useful code samples at Java Sound Resources.

Eventually I pieced together the following, from the Progammer’s guide, the Java Sound Resources examples and some experimentation of my own. For the initialisation I changed the type of the warningClip variable to javax.sound.sampled.Clip, and changed the implementation to the following:

File file = new File("src/test/resources/warning.wav");
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(file);
Line.Info info = new Line.Info(Clip.class);
Line line = AudioSystem.getLine(info);
this.warningClip = (Clip)line;
this.warningClip.open(audioInputStream);

(Quite a bit more exception handling omitted.)

As you can see, I needed a lot more boilerplate code, including a typecast that seems like it shouldn’t be necessary. Oh well.

Forturnately, the handling of the “warning” event looks much better:

if (!this.warningClip.isRunning())
{
    // rewind the clip
    this.warningClip.setFramePosition(0);
    // play
    this.warningClip.start();
}

This worked perfectly with the few .wav files I used to test this code, but when we started testing with different clips, we discovered that it couldn’t play several .mp3s and .wav files. I ended up using a separate program to convert an .mp3 to a .wav format that this implementation could handle.

Java Media Framework

As a third alternative, it may be that the Java Media Framework offers an easier API for dealing with audio clips, and better support for multiple audio file formats. However, since the above solution worked well enough for our purposes, so far I haven’t bothered to investigate further.


© 2020 Java Competence Network. All Rights Reserved.