简体   繁体   中英

Why does attempting to get a Clip throw exception?

I have been following this tutorial for Java 1.7 and I am sure I have the code right. However, Java throws an IllegalArgumentException at runtime.

I've tried to catch it in an existing catch block, using Java's slightly-newer multi-catch. However, it simply throws exceptions.

Here is the beginning of my code.

        Mixer.Info[] mixInfos = AudioSystem.getMixerInfo();
        /*
        for (Mixer.Info info : mixInfos)
        {
            System.out.println(info.getName() + " - " + info.getDescription());
        }
        */
        mixer = AudioSystem.getMixer(mixInfos[0]);

        DataLine.Info dataInfo = new DataLine.Info(Clip.class, null);
        try
        {
            clip = (Clip) mixer.getLine(dataInfo);
        }

I expect that the code will continue running and play the Clip but I get this exception:

Exception in thread "main" java.lang.IllegalArgumentException: Line unsupported: interface Clip
    at java.desktop/com.sun.media.sound.PortMixer.getLine(PortMixer.java:131)
    at main.Driver.main(Driver.java:35)

Note: If this isn't forward compatible, please explain.

I think you should check your imports. AFAIK, the libraries for sound are all in javax.sound.sampled. The PortMixer is in com.sun.media.sound.

The author of the tutorial is going to a lot more trouble than is necessary. Instead of hardcoding a specific Mixer, you can just let the system pick defaults. This is probably the best strategy, as PC's out in the world are going to have diverse hardware configurations.

Following is an example that might be helpful. Notice that we don't even bother to declare a Mixer.

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

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 BasicClipExample {

    public static void main(String[] args) {

        BasicClipExample bc = new BasicClipExample();

        try {
            bc.run();
        } catch (UnsupportedAudioFileException | IOException 
                | LineUnavailableException | InterruptedException e) {
            e.printStackTrace();
        }

    }

    private void run() throws UnsupportedAudioFileException, 
            IOException, LineUnavailableException, InterruptedException
    {
        String filename = "a3.wav";

        URL url = this.getClass().getResource("audio/" + filename);
        System.out.println(url);

        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(6000);
        clip.close();
    }       
}

This example assumes that your audio file is in a subdirectory called "/audio". It also has a sleep command to keep the program running while the Clip is playing. Clips run under their own thread, but the thread is a "daemon" type and will not prevent a Java program from closing. My a3.wav is a recording of a bell that happens to last about 5 seconds.

Last thing, the above code does not use a Clip in the ideal fashion. The concept of a Clip is that it is for re-use. Reloading the clip variable before playing it each time it is played is inefficient. The clip variable should be loaded only once, and then played on demand. If you have clip.open() and clip.start() as contiguous lines of code, you should probably either be using a SourceDataLine instead of a Clip, or you should recode and put the two commands into separate methods.

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