package me.Warrior;
import java.net.URL;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.FloatControl;
public class SoundPlayer {
static URL path=null;
static AudioInputStream inputStream;
public static Clip clip;
public static synchronized void Play(final String url,float Volume) {
new Thread(new Runnable() {
public void run() {
try {
clip = AudioSystem.getClip();
URL resource = getClass().getClassLoader().getResource(url);
path=resource;
inputStream = AudioSystem.getAudioInputStream(path);
clip.open(inputStream);
setVolume(Volume,clip);
clip.start();
} catch (Exception e) {
}
}
}).start();
}
public static void setVolume(float Volume,Clip clip) {
FloatControl gainControl =
(FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
float dB=(float)(Math.log(Volume)/Math.log(10)*20);
gainControl.setValue(dB);
}
}
**所以我在游戏中播放很多音频,但我认为这是一个问题,但是如果我在相同的六十分之一秒内播放两个音频,则会弹出错误并冻结游戏半秒钟
我可以以某种方式确定剪辑何时开始播放,以便可以停止下一个剪辑 (我想查看剪辑何时开始播放,而不是何时播放) (但这对我来说也很有趣)
是否有比此更好的播放音频的方式
答案 0 :(得分:0)
剪辑没有设计成可以同时打开和启动。在从磁盘加载整个文件之前,它们甚至都不会开始播放。我猜如果您尝试同时使用显示的代码同时播放两个,则文件加载滞后问题将会加剧。
您可以(并且应该)做的是事先初始化Clips,包括将其打开并将其保存在内存中,以备使用。是时候播放它们了,您应该只执行以下操作:
public void playMyAudioFX() {
myAudioFX.setFramePosition(0);
myAudioFX.start();
}
通过将帧位置设置为开始,您可以重复使用Clip
,而不必一遍又一遍地加载它。
但是,如果您不想耗尽存储音频的内存,请使用SourceDataLine
进行播放。在SourceDataLine
开始播放之前,仅从磁盘加载了一个缓冲区的数据(而不是等待整个文件加载)。
这两种文件类型都不适合同时播放(一次播放两次或多次),但是如果正确执行上述操作,声音应该会很好。如果仍然存在问题,或者您对MASTER_GAIN行的笨拙不满意,可以尝试使用几个简单的库。一个称为TinySound,另一个称为AudioCue。我偏爱后者(因为我写了它),它确实处理并发回放,并且比Clip
具有更细粒度的实时音量控制。
这是一个非常普遍的问题,很多原因是关于音频的Java教程很难阅读,因此人们会错过这些重要的细节。我猜想许多其他志愿教程的作者在强调最佳实践方面做得不好,只满足于播放声音而已。
编辑:重新阅读您的问题-有一个名为LineListener
的类可以接收有关Clip
何时开始或停止的通知,如果您想进一步追求这一方面。
此外,如果您收到实际的错误消息,请发布它们!这将有助于确定原因和解决方案。