Java剪辑不起作用
有人可以帮我理解为什么下面这段代码不起作用?
我通过调用方法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(); } }
UPDATE
我发现了问题! 问题是因为音频文件。 我使用了不同的音频文件,我可以用上面的代码听到声音。
编译的代码没有任何错误或警告真的很烦人。 我通过获取音频格式检测到问题,然后将其传递给类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位
所以,我替换了音频文件,它工作了!
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) {
你应该设置一些你设置为false
并帮助终止循环的volitle
标志.. 。
例如…
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(); } }
更新
上面的例子(恕我直言)有一些问题,可以用简单的对象监视器修复。
因此,我们可以使用Clip#loop
function而不是volatile
标志和while
循环,而只需使用Object#wait
和Object#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(); } }