简体   繁体   中英

What is the correct way to play a sound file using java.sound.sampled.Clip

I have read many SoF threads and other sites on this topic, but none of them works for me, so I am asking again, hoping to receive tailored answer.

I have a.WAV file inside my jar what I want to play, but I am getting NullPointerException. I have tried many ways, even playing file outside the jar via absolute path, but I got the same result. This is the function for playing the sound

public void gimli(){
        try {
            Clip clip;
             AudioInputStream  stream = AudioSystem.getAudioInputStream(this.getClass().getResource(Utils.class.getResourceAsStream("gimlilaught.wav").toString()));
   AudioFormat format = stream.getFormat();
    DataLine.Info info = new DataLine.Info(Clip.class, format);
  clip = (Clip)AudioSystem.getLine(info);
    clip.open(stream);
    clip.start();
}catch(Exception ex){
ex.printStackTrace(System.out);
}

Thank you for your trying.

I was trying this last night and what seems to work for me is:

try {
            File filePath = new File(audioLocation);

            if (filePath.exists()) {
                AudioInputStream audioInput = AudioSystem.getAudioInputStream(filePath);
                Clip clip = AudioSystem.getClip();
                clip.open(audioInput);
                FloatControl gainControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
                gainControl.setValue(getVolume());
                clip.loop(Clip.LOOP_CONTINUOUSLY);
                clip.start();
            } else {
                System.out.println("Incorrect audio file path!");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

Although I think I should have clip.open() in there somewhere and I've had issues stopping and starting the audio from another class, this does get the sound to play.

An AudioInputStream is needed as an argument for opening a Clip . Looking at the API, you will see that either AudioSystem.getAudioInputStream(InputStream) or AudioSystem.getAudioInputStream(URL) can be used to get an AudioInputStream .

There are two methods of Class that serve: getResource(String) or getResourceAsStream(String) . The getResource method will return a URL . The getResourceAsStream method will return an InputStream .

I prefer using the URL form, as it is more forgiving. When using AudioSystem.getAudioInputStream(InputStream) , an IOException will be returned if the file does not support marking and resetting . The method AudioSystem.getAudioInputStream(URL) circumvents this requirement.

Also, you should be aware that a URL , unlike a File , can be used to identify a file that is within jar.

You also have to be careful about setting the relative address. I generally like to have a /res file or /audio file that holds the.wav to be loaded. For example, you can use " ../res/myAudio.wav " if /res is a parallel folder or " res/myAudio.wav " if /res is subfolder, relative to the location of the class being used in the getResource method.

Here is a simple working example, where the audio file is in a subfolder, /res :

private static void loadAndPlayClip() throws UnsupportedAudioFileException, 
        IOException, LineUnavailableException, InterruptedException
{
    String filename = "a3.wav";
    URL url = BasicClipExample.class.getResource("res/" + filename);
    AudioInputStream ais = AudioSystem.getAudioInputStream(url);
    DataLine.Info info = new DataLine.Info(Clip.class, ais.getFormat());
    Clip clip = (Clip) AudioSystem.getLine(info);
    clip.open(ais);

    clip.start();
    Thread.sleep(7000); // Duration should match length of audio file.
    clip.close();
}

While this example should work, it shouldn't be used as is in production, for two reasons.

  1. The Thread.sleep() command halts the main thread, which is usually neither desirable nor needed. The thread that the system creates for Clip playback is adaemon thread. Daemon threads will not prevent a program from completing and shutting down. In this simple "fire and forget" example the main thread is quickly done, so the program will immediately shut down if we don't stave off completion with a sleep interval.

  2. The initial loading of a Clip and the playing of a Clip are usually done in two separate methods. A Clip was designed for audio that can be conveniently held in memory, allowing it to be replayed without requiring reloading. If you reload the Clip with each play command, you would be both redoing work that is not needed and adding latency, as the clip will not begin playing until it has been entirely loaded. If the audio file is inconvenient to hold in memory (eg, large file due to long duration), the preferred method is to play it with a SourceDataLine .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM