Java剪辑不起作用

时间:2014-06-10 01:43:37

标签: java audio javasound clip

有人可以帮助我理解为什么以下代码不起作用?

我通过调用方法start()来启动剪辑。此方法为剪辑创建新线程以运行。但是,不,它似乎没有发挥任何作用。

编译代码没有任何错误......

public class Audio
{
    private Clip clip;

    private Thread thread; 

    public Audio (String audioFile)
    {
        AudioInputStream audioStream = null;

        URL audioURL = this.getClass().getClassLoader().getResource(audioFile);

        // Obtain audio input stream from the audio file and load the information
        // into main memory using the URL path retrieved from above.
        try { audioStream = AudioSystem.getAudioInputStream(audioURL); }
        catch (Exception e)
        {
            e.printStackTrace();
            System.exit(1);
        }

        try
        {
            // Retrieve the object of class Clip from the Data Line.
            this.clip = AudioSystem.getClip();

            // Load the audio input stream into memory for future play-back.
            this.clip.open(audioStream);
        }
        catch (LineUnavailableException e)
        {
            e.printStackTrace();
            System.exit(1);
        }
        catch (IOException e)
        {
            e.printStackTrace();
            System.exit(1);
        }
    }

    public void start()
    {
        Runnable r = new Runnable() {
            public void run()
            {
                loop();
            }
        };
        thread = new Thread(r);
        thread.start();
    }

    public void loop ()
    {       
        // Rewind the media to the beginning of the clip.
        this.clip.setFramePosition(0);

        // Continuously play the clip.
        this.clip.loop(Clip.LOOP_CONTINUOUSLY);

        try
        {
            Thread.sleep(5000);
        } catch (InterruptedException e)
        {
            e.printStackTrace();
        }
    }

更新

我发现了问题!问题是因为音频文件。我使用了不同的音频文件,我可以用上面的代码听到声音。

编译的代码没有任何错误或警告真的很烦人。我通过获取音频格式检测到问题,然后将其传递给类DataLine.Info的对象。然后,从数据线中检索剪辑。

所以,基本上不是通过以下方式获取剪辑:

this.clip = AudioSystem.getClip();

我会得到剪辑:

AudioFormat format = audioStream.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, format);
this.clip = (Clip) AudioSystem.getLine(info);

当我用这个编译时,Java抛出了以下错误:

  

没有行匹配接口Clip支持格式PCM_SIGNED 48000.0 Hz,24 bit

所以,我更换了音频文件,它有效!

1 个答案:

答案 0 :(得分:1)

clip.loop是非阻止通话。也就是说,一旦你调用它(并且它完成了它的工作),它将返回,这意味着你的线程将退出,除非有另一个非守护程序线程在运行,否则JVM将退出。

我原本以为你可以使用Clip#drain来阻止它直到剪辑完成,但从技术上讲,剪辑将无法完成......正常意义上。

相反,我建立了自己的循环......

public void start() {
    Runnable r = new Runnable() {
    public void run() {
        while (true) {
            clip.setFramePosition(0);
            clip.start();
            clip.drain();
        }
    }
    };
    thread = new Thread(r);
    thread.start();
}

现在,这可能是一个问题,因为Thread是一个非守护程序线程,永远不会结束......而不是while (true) {你应该设置一些volitle标志您设置为false并帮助终止循环...

例如......

import java.io.IOException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;

public class Audio {

    private Clip clip;

    private Thread thread;
    private volatile boolean keepPlaying = true;

    public static void main(String[] args) {
        Audio audio = new Audio("Kalimba.wav");
        audio.start();

        try {
            Thread.sleep(5000);
        } catch (InterruptedException ex) {
        }
        audio.stop();
    }

    public Audio(String audioFile) {
        AudioInputStream audioStream = null;

        URL audioURL = this.getClass().getClassLoader().getResource(audioFile);

        // Obtain audio input stream from the audio file and load the information
        // into main memory using the URL path retrieved from above.
        try {
            audioStream = AudioSystem.getAudioInputStream(audioURL);
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }

        try {
            // Retrieve the object of class Clip from the Data Line.
            this.clip = AudioSystem.getClip();

            // Load the audio input stream into memory for future play-back.
            this.clip.open(audioStream);
        } catch (LineUnavailableException e) {
            e.printStackTrace();
            System.exit(1);
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(1);
        }
    }

    public void stop() {
        if (thread != null) {

            keepPlaying = false;
            clip.stop();
            thread.interrupt();

        }
    }

    public void start() {
        Runnable r = new Runnable() {
            public void run() {
                while (keepPlaying) {
                    clip.setFramePosition(0);
                    clip.start();
                    clip.drain();
                }
            }
        };
        thread = new Thread(r);
        thread.start();
    }
}

<强>更新

上面的例子(恕我直言)有一些问题,可以用简单的对象监视器修复。

因此,我们可以使用volatile功能代替while标记和Clip#loop循环,而只需使用Object#waitObject#notify代替示例

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.LineUnavailableException;

public class Audio {

    private Clip clip;

    private Thread thread;
    private final Object loopLock = new Object();

    public static void main(String[] args) {
        Audio audio = new Audio("Music.wav");
        audio.start();

        try {
            Thread.sleep(5000);
        } catch (InterruptedException ex) {
        }
        audio.stop();
    }

    public Audio(String audioFile) {
        AudioInputStream audioStream = null;

        URL audioURL = this.getClass().getClassLoader().getResource(audioFile);

        // Obtain audio input stream from the audio file and load the information
        // into main memory using the URL path retrieved from above.
        try {
            audioStream = AudioSystem.getAudioInputStream(audioURL);
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }

        try {
            // Retrieve the object of class Clip from the Data Line.
            this.clip = AudioSystem.getClip();

            // Load the audio input stream into memory for future play-back.
            this.clip.open(audioStream);
        } catch (LineUnavailableException e) {
            e.printStackTrace();
            System.exit(1);
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(1);
        }
    }

    public void stop() {
        synchronized (loopLock) {
            loopLock.notifyAll();
        }
    }

    public void start() {
        Runnable r = new Runnable() {
            public void run() {
                clip.setFramePosition(0);
                clip.loop(Clip.LOOP_CONTINUOUSLY);
                synchronized (loopLock) {
                    try {
                        loopLock.wait();
                    } catch (InterruptedException ex) {
                    }
                }
                clip.stop();
            }
        };
        thread = new Thread(r);
        thread.start();
    }
}