Search code examples
javaeclipseswingaudioembedded-resource

Audio file plays in Eclipse IDE; but NOT as JAR file


The audio file that I am using is found here: http://www.orangefreesounds.com/loud-alarm-clock-sound/

This is what my file structure looks like in my Eclipse IDE: What my file structure looks like

The audio file plays perfectly fine when I run it in my IDE, but not when I export it as a JAR file. I have already checked and found that the audio file is inside the JAR file.

I am using the terminal command java -jar Sandbox.jar & to run the JAR file. The program seems to be able to find the file (since it is not throwing an IOException), but does not seem to be able to perform playback.

Why is this problem happening and how can I fix it?

Weird Update

Okay, so actually, the JAR file is able to play the audio file when run in cmd or PowerShell on Windows 8.1, but not in the terminal of Ubuntu 14.04 for some reason. This whole time, I have been trying to run the JAR file in Ubuntu 14.04.

Weird Update #2

I have confirmed the issue of the JAR files only working on a Windows 8.1 system. Both of the code snippets in this question DO NOT WORK, while both of MadProgrammer's solutions work.

Minimal, Complete, and Verifiable example (does NOT work on Windows or Ubuntu)

import java.io.IOException;
import java.net.URL;
import javax.sound.sampled.*;

public class Sandbox
{

    public static void main(String[] args) throws UnsupportedAudioFileException, IOException, LineUnavailableException
    {
        URL url = Sandbox.class.getResource("/sound-effects/alarmSoundClip.wav");
        AudioInputStream ais = AudioSystem.getAudioInputStream(url);
        AudioFormat af = ais.getFormat();
        DataLine.Info info = new DataLine.Info(Clip.class, af);

        Clip clip = (Clip) AudioSystem.getLine(info);
        clip.open(ais);
        clip.start();
    }

}

Attempted Solution #1 (does NOT work on Windows or Ubuntu)

One attempted solution (as suggested by Andrew Thompson) was to write this.getClass().getResource( ... ) instead of Sandbox.class.getResource( ... ):

import java.io.IOException;
import java.net.URL;

import javax.sound.sampled.*;

public class Sandbox
{

    public static void main(String[] args) throws UnsupportedAudioFileException, IOException, LineUnavailableException
    {
        new Sandbox();
    }

    public Sandbox() throws UnsupportedAudioFileException, IOException, LineUnavailableException
    {
        URL url = this.getClass().getResource("/sound-effects/alarmSoundClip.wav");
        AudioInputStream ais = AudioSystem.getAudioInputStream(url);
        AudioFormat af = ais.getFormat();
        DataLine.Info info = new DataLine.Info(Clip.class, af);

        Clip clip = (Clip) AudioSystem.getLine(info);
        clip.open(ais);
        clip.start();
    }
}

Solution

  • Adding clip.drain() after clip.start() seems to have worked okay for me (IDE and command line both with and without &)

    import java.io.IOException;
    import java.net.URL;
    import javax.sound.sampled.AudioFormat;
    import javax.sound.sampled.AudioInputStream;
    import javax.sound.sampled.AudioSystem;
    import javax.sound.sampled.Clip;
    import javax.sound.sampled.DataLine;
    import javax.sound.sampled.LineUnavailableException;
    import javax.sound.sampled.UnsupportedAudioFileException;
    
    public class Sandbox {
    
        public static void main(String[] args)  {
            try {
                URL url = Sandbox.class.getResource("/sound-effects/Loud-alarm-clock-sound.wav");
                AudioInputStream ais = AudioSystem.getAudioInputStream(url);
                AudioFormat af = ais.getFormat();
                DataLine.Info info = new DataLine.Info(Clip.class, af);
    
                Clip clip = (Clip) AudioSystem.getLine(info);
                clip.open(ais);
                clip.start();
                System.out.println("Drain...");
                clip.drain();
                System.out.println("...Drained");
            } catch (UnsupportedAudioFileException | IOException | LineUnavailableException exp) {
                exp.printStackTrace();
            }
        }
    
    }
    

    Now, having said that, I have found drain a little unreliable in the past, especially when there are multiple sounds playing in which case I tend to use a LineListener

    For example...

    import java.io.IOException;
    import java.net.URL;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import javax.sound.sampled.AudioFormat;
    import javax.sound.sampled.AudioInputStream;
    import javax.sound.sampled.AudioSystem;
    import javax.sound.sampled.Clip;
    import javax.sound.sampled.DataLine;
    import javax.sound.sampled.LineEvent;
    import javax.sound.sampled.LineListener;
    import javax.sound.sampled.LineUnavailableException;
    import javax.sound.sampled.UnsupportedAudioFileException;
    
    public class Sandbox {
    
        protected static final Object LOCK = new Object();
    
        public static void main(String[] args) {
            try {
                URL url = Sandbox.class.getResource("/sound-effects/Loud-alarm-clock-sound.wav");
                AudioInputStream ais = AudioSystem.getAudioInputStream(url);
                AudioFormat af = ais.getFormat();
                DataLine.Info info = new DataLine.Info(Clip.class, af);
    
                Clip clip = (Clip) AudioSystem.getLine(info);
                clip.open(ais);
    
                clip.addLineListener(new LineListener() {
                    @Override
                    public void update(LineEvent event) {
                        System.out.println(event.getType());
                        if (event.getType() == LineEvent.Type.STOP) {
                            synchronized (LOCK) {
                                LOCK.notify();
                            }
                        }
                    }
                });
                clip.start();
    
                synchronized (LOCK) {
                    LOCK.wait();
                }
            } catch (UnsupportedAudioFileException | IOException | LineUnavailableException | InterruptedException exp) {
                exp.printStackTrace();
            }
        }
    
    }