2

Background: I have a simple test application which plays a sound using Java's javax.sound.sampled package. Presently, the application plays the sound for either 10 seconds, or however many times I've told it to loop (whichever comes first). When either of these conditions are reached, the program orders the audio clip to stop playing, and the program should, at that point, completely shut down.

The problem: Oddly, while testing the application on my Raspberry PI, when the end of the program is reached, the audio does not cease; it continues playing for a seemingly arbitrary amount of time afterwards, from a few seconds, up to a minute (perhaps more, I haven't explicitly timed it).

However, the application behaves perfectly fine locally. I'm developing on a Mac, and packaging up a runnable jar which I deployed on the Pi.

Here is a condensed version of the test application code:

public class AudioTest {

    public static void main(String[] args) throws UnsupportedAudioFileException, IOException, LineUnavailableException, InterruptedException {
        URL audioFileURL = AudioTest.class.getResource("/smokealarm.wav");

        if(audioFileURL != null){
            System.out.println("Got the file!");

            AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(audioFileURL);
            Line.Info lineInfo = new Line.Info(Clip.class);
            Line line = AudioSystem.getLine(lineInfo);

            Clip clip = (Clip)line;
            clip.open(audioInputStream);
            clip.loop(Clip.LOOP_CONTINUOUSLY);
            clip.start();

            long startTime = System.currentTimeMillis();
            int repeatDuration = 10; // repeat for 10 seconds
            String previousDuration = null;
            do{
                Thread.sleep(50); // keeps the application alive
                System.out.println("Still waiting...");
            }while(clip.isRunning() && ((System.currentTimeMillis() - startTime) < (repeatDuration * 1000)));

            System.out.println("Stopping audio");
            clip.stop();

            // These two lines don't seem to have any effect.
            // Adding them here to show that I've attempted them.
            clip.flush();
            clip.close();
        }else{
            System.err.println("COULD NOT FIND THE FILE!");
        }
    }
}

Note: You can obtain the smoke alarm sound file here, or just substitute your own if you prefer

In either case, I know the program has reached the end because I see the "Stopping audio" line in the console.

I cannot think of any reason for this behaviour, other than a bug in the JVM. Has anyone encountered something like this?

P.S: I used this as a guide for writing the above, in case anyone is wondering. Also, I'm using Oracle Java 1.7.

2 Answers 2

2

I don't know the java-language, but I can think of a solution, not a correct fix i guess: Mute the line.
That will probably work direct. Stop the audio also but let it play through its buffer in silence...

From the Oracle docs:

The Java Sound API specifies the following abstract subclasses of Control:

BooleanControl— represents a binary-state (true or false) control. For example, mute, solo, and on/off switches would be good candidates for BooleanControls. 
[...]
Each subclass of Control above has methods appropriate for its underlying data type. 
Most of the classes include methods that set and get the control's current value(s), get the control's label(s), and so on.\

Of course, each class has methods that are particular to it and the data model represented by the class. 
For example, EnumControl has a method that lets you get the set of its possible values, and FloatControl permits you to get its minimum and maximum values, as well as the precision (increment or step size) of the control.

Each subclass of Control has a corresponding Control.Type subclass, which includes static instances that identify specific controls.

The following table shows each Control subclass, its corresponding Control.Type subclass, and the static instances that indicate specific kinds of controls:

Control         Control.Type         Control.Type instances
BooleanControl  BooleanControl.Type  MUTE – Mute status of line
[...]
1
  • Ah ok, interesting idea. I will give that a try shortly. That will definitely solve the "blaring sound" issue at the very least. Commented Mar 12, 2014 at 21:36
1

Just to close off this question, I've been able to solve the problem by using the Clip#loop() method instead of the DataLine#stop() I was using previously. This, I believe, is the correct way to halt a looping audio clip because of this explanation from the loop method's documentation:

A count value of 0 indicates that any current looping should cease and playback should continue to the end of the clip.

In addition, taking ExploWare's suggestion, I'm also muting the line when I want to stop the sound so that it at least appears to behave as I desire.

Unfortunately, I still have no explanation for why I observe this odd non-ceasing sound issue ONLY on the Raspberry Pi. Should anyone in the future who has this knowledge see this, please by all means post an answer (or comment).

So, in short, here is my final code implementing the solutions described above:

// ... other code
System.out.println("Stopping audio");

// Mute the clip
BooleanControl muteControl = (BooleanControl) clip.getControl(BooleanControl.Type.MUTE);
if(muteControl != null){
    muteControl.setValue(true); // True to mute the line, false to unmute
}

clip.loop(0); // Stops the sound after it runs through its buffer
clip.flush();
1
  • 1
    Thanks for this answer. I encountered the same problem on my Pi. Absolutely annoying!
    – rolve
    Commented May 13, 2016 at 7:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.