有人可以帮助我理解为什么以下代码不起作用?
我通过调用方法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
所以,我更换了音频文件,它有效!
答案 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#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();
}
}