使用javax.sound.sampled.Clip在游戏中播放、循环和停止多个声音。意外错误。

7
我正在尝试在游戏中同时播放两个wav声音(背景音乐和效果音)。我最初使用Java中的另一个音频处理程序构建了这段代码,该程序将处理声音的播放、停止和循环。这个结构会播放背景音乐或效果音,但一次只能播放一个。我在互联网上搜索后得知可以使用javax.sound.sampled.Clip来处理声音,于是重用了相同的结构(播放、停止、循环),但切换到了使用javax.sound.sampled.Clip。现在我完全迷失了方向。从我到目前为止所读到的内容来看,我已经做得没错,在eclipse编辑器中也没有错误,但是当我运行它时,会出现以下两种错误之一。在Linux上运行的eclipse中,抛出LineUnavailableException异常。在Windows 7上运行的eclipse中,我在此代码的loop()部分中得到了java.lang.NullPointerException。如果您能告诉我我做错了什么,或者指点我一些相关的文档,我将不胜感激。我认为这可能与我的异常处理代码有关,但我不确定。如果您发现任何其他可怕的代码错误,请让我知道,我正在努力成为最好的程序员,并真的感谢建设性的批评。谢谢您的时间。
    import java.io.File;
    import java.io.IOException;
    import java.net.MalformedURLException;
    import javax.sound.sampled.AudioInputStream;
    import javax.sound.sampled.AudioSystem;
    import javax.sound.sampled.Clip;
    import javax.sound.sampled.LineUnavailableException;
    import javax.sound.sampled.UnsupportedAudioFileException;

    /**
     * Handles play, pause, and looping of sounds for the game.
     * @author Tyler Thomas
     *
     */
    public class Sound {
        private Clip myClip;
        public Sound(String fileName) {
                try {
                    File file = new File(fileName);
                    if (file.exists()) {
                        Clip myClip = AudioSystem.getClip();
                        AudioInputStream ais = AudioSystem.getAudioInputStream(file.toURI().toURL());
                        myClip.open(ais);
                    }
                    else {
                        throw new RuntimeException("Sound: file not found: " + fileName);
                    }
                }
                catch (MalformedURLException e) {
                    throw new RuntimeException("Sound: Malformed URL: " + e);
                }
                catch (UnsupportedAudioFileException e) {
                    throw new RuntimeException("Sound: Unsupported Audio File: " + e);
                }
                catch (IOException e) {
                    throw new RuntimeException("Sound: Input/Output Error: " + e);
                }
                catch (LineUnavailableException e) {
                    throw new RuntimeException("Sound: Line Unavailable: " + e);
                }
        }
        public void play(){
            myClip.setFramePosition(0);  // Must always rewind!
            myClip.loop(0);
            myClip.start();
        }
        public void loop(){
            myClip.loop(Clip.LOOP_CONTINUOUSLY);
        }
        public void stop(){
            myClip.stop();
        }
    }
2个回答

17

我已经成功让这段代码运行了,并且现在对Clips有了更好的理解。帮助我最多的页面是http://www3.ntu.edu.sg/home/ehchua/programming/java/J8c_PlayingSound.html,它把所有内容都分解了,帮助我看到了我的错误。以下是我最终的工作代码。如果您看到任何可怕的错误或逻辑上的疏漏或风格方面的问题,请让我知道。

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;

/**
 * Handles playing, stoping, and looping of sounds for the game.
 * @author Tyler Thomas
 *
 */
public class Sound {
    private Clip clip;
    public Sound(String fileName) {
        // specify the sound to play
        // (assuming the sound can be played by the audio system)
        // from a wave File
        try {
            File file = new File(fileName);
            if (file.exists()) {
                AudioInputStream sound = AudioSystem.getAudioInputStream(file);
             // load the sound into memory (a Clip)
                clip = AudioSystem.getClip();
                clip.open(sound);
            }
            else {
                throw new RuntimeException("Sound: file not found: " + fileName);
            }
        }
        catch (MalformedURLException e) {
            e.printStackTrace();
            throw new RuntimeException("Sound: Malformed URL: " + e);
        }
        catch (UnsupportedAudioFileException e) {
            e.printStackTrace();
            throw new RuntimeException("Sound: Unsupported Audio File: " + e);
        }
        catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("Sound: Input/Output Error: " + e);
        }
        catch (LineUnavailableException e) {
            e.printStackTrace();
            throw new RuntimeException("Sound: Line Unavailable Exception Error: " + e);
        }

    // play, stop, loop the sound clip
    }
    public void play(){
        clip.setFramePosition(0);  // Must always rewind!
        clip.start();
    }
    public void loop(){
        clip.loop(Clip.LOOP_CONTINUOUSLY);
    }
    public void stop(){
            clip.stop();
        }
    }

1
能否进一步解释一下那个链接,以防它失效? - RamenChef

3
我发现了一种有用的停止声音的技巧。你可以复制下面这两个类并测试一下。然而,clip.stop() 方法更像是一个暂停方法。它确实停止了声音的播放,但并没有清除该声音所在的线路。因此,声音仍在等待播放,没有新的声音能够播放。因此,使用 clip.close() 方法将清除这个排队的数据,并允许播放新的声音或进行其他操作。还请注意,在以下代码中,一个声音文件被放置在项目文件夹中,名为 "predator.wav"。这个声音可以是任何你想使用的声音,但一定要是 .wav 格式,并且声音必须在项目文件夹的最高层。
/*
 * File: KeyMap.java
 * Author: Andrew Peturis Chaselyn Langley; UAB EE Students
 * Assignment:  SoundBox - EE333 Fall 2015
 * Vers: 1.0.0 10/20/2015 agp - initial coding
 *
 * Credits: Dr. Green, UAB EE Engineering Professor
 */

import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;

public class KeyMap {

    private char keyCode;
    private String song;
    private Clip clip;

    // Don't allow default constructor
    private KeyMap() {
    }

    public KeyMap(char keyCode, String song) throws LineUnavailableException {
        this.keyCode = keyCode;
        this.song = song;

        // Create an audiostream from the inputstream
        clip = AudioSystem.getClip();
    }

    public boolean match(char key) {
        return key == keyCode;
    }

    // Play a sound using javax.sound and Clip interface
    public String play() {
        try {
            // Open a sound file stored in the project folder
            clip.open(AudioSystem.getAudioInputStream(new File(song + ".wav")));

            // Play the audio clip with the audioplayer class
            clip.start();

            // Create a sleep time of 2 seconds to prevent any action from occuring for the first
            // 2 seconds of the sound playing
            Thread.sleep(2000);

        } catch (LineUnavailableException | UnsupportedAudioFileException | IOException | InterruptedException e) {
            System.out.println("Things did not go well");
            System.exit(-1);
        }
        return song;
    }

    // Stop a sound from playing and clear out the line to play another sound if need be.
    public void stop() {
        // clip.stop() will only pause the sound and still leave the sound in the line
        // waiting to be continued. It does not actually clear the line so a new action could be performed.
        clip.stop();

        // clip.close(); will clear out the line and allow a new sound to play. clip.flush() was not 
        // used because it can only flush out a line of data already performed.
        clip.close();
    }
}

/*
 * File: SoundBox.java
 * Author: Andrew Peturis, Chaselyn Langley; UAB EE Students
 * Assignment:  GUI SoundBox - EE333 Fall 2015
 * Vers: 1.0.0 09/08/2015 agp - initial coding
 */

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Scanner;
import javax.sound.sampled.LineUnavailableException;

/**
 *
 * @author Andrew Peturis, Chaselyn Langley
 *
 */
public class SoundBox {

    static Scanner scanner = new Scanner(System.in);   //Scanner object to read user input
    InputStream input;

    /**
     * @param args the command line arguments
     * @throws java.io.IOException
     */
    public static void main(String[] args) throws IOException, LineUnavailableException {

        String line;
        Character firstChar;
        String predator = "predator";
        String explosion = "explosion";

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        KeyMap[] keyedSongs = {
            new KeyMap('a', predator),};

        while (true) {
            line = br.readLine();
            firstChar = line.charAt(0);

            for (int i = 0; i < keyedSongs.length; i++) {
                if (keyedSongs[i].match(firstChar)) {

                    // Notice now by running the code, after the first second of sleep time the sound can
                    // and another sound can be played in its place
                    keyedSongs[i].stop();
                    System.out.println("Played the sound: " + keyedSongs[i].play());
                    break;
                }
            }

            if (firstChar == 'q') {
                break;
            }
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接