javasound Java音频爆裂声
当我在Java桌面应用程序上播放音频时,声音开始噼啪作响。我不知道为什么,有什么建议吗?我正在制作一款口袋妖怪粉丝游戏
static AudioInputStream audio = null;
public static boolean change = false;
static Clip clip = null;
public static void music() {
try {
change = false;
if(!Main.choosegame) {
if(!Main.startup) {
if(Movement.POKEMONBATTLE) {
audio = AudioSystem.getAudioInputStream(new File("Res/music/pokemon battle.wav"));
} else {
audio = AudioSystem.getAudioInputStream(new File("Res/music/route.wav"));
}
} else {
audio = AudioSystem.getAudioInputStream(new File("Res/music/Oak's Speech.wav"));
}
} else {
audio = AudioSystem.getAudioInputStream(new File("Res/music/Title Screen.wav"));
}
clip = AudioSystem.getClip();
clip.open(audio);
clip.start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
while(clip.isActive() && Main.Running && !change){
}
clip.stop();
audio.close();
Thread.sleep(100);
} catch(UnsupportedAudioFileException uae) {
System.out.println(uae);
} catch(IOException ioe) {
System.out.println(ioe);
} catch(LineUnavailableException lua) {
System.out.println(lua);
} catch (InterruptedException e) {
e.printStackTrace();
} catch(OutOfMemoryError e12) {
clip.stop();
change = true;
try {
audio.close();
} catch (IOException e1) {
e1.printStackTrace();
}
System.out.println("OUT OF MEMORY IN MUSIC");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
public void run() {
while(Main.Running) {
music();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
# 1 楼答案
裂纹总是在开始时发出吗?如果是这样,我发现一些代码跳过了第一个字节以避免:
资料来源:http://veritas.eecs.berkeley.edu/apcsa-ret/program/projects/lesson13/Sound/SampleRateConverter.java
# 2 楼答案
奇怪的东西。既然你已经找到了解决办法,也许我不应该再加上我的两分钱。但有一些事情似乎令人困惑,与我所知的音频世界不太匹配
通常裂纹和失真是PCM数据点超出其界限的结果。例如,如果wav文件的数据范围为-32768到32767(通过带符号的短字符表示的16位编码),并且值超出该范围,则可能会发生各种失真
在您的情况下,如果一次播放多个wav文件,并且wav的音量已经非常大,则可能会发生这种情况。当他们的数据被汇总在一起进行同步播放时,可能会超出16位的范围
如果增加暂停的主要作用是防止WAV同时播放,那么这也可以减少失真量
在某些情况下,音频线程需要一些时间才能完成并响应状态更改。但我想不出会在哪里产生裂纹或绒毛。(但这并不意味着不存在这种情况。)
如果原始wav文件上存在相同的裂纹和模糊,并且跳过了扭曲的部分,那么通过skip()简单地绕过大量样本(理论上)应该只会有所帮助。但是,如果从已经可以听到的音量水平开始,则会导致咔哒声
顺便说一下,您可能会更好地将文件作为SourceDataLines运行,而不是作为片段运行。剪辑仅适用于需要多次重放声音并且能够将数据保存在内存中的情况。按照编码,每次播放声音时,首先将整个声音加载到内存中,然后播放。只有将所有数据加载到内存中,才能播放剪辑。使用SourceDataLine,播放代码在播放时读取数据,占用的内存要少得多
如果您有足够的内存,只需将片段加载一次到它自己的变量中。播放剪辑后,可以将其光标设置回剪辑的开头,然后在不必从文件重新加载的情况下重播数据(就像您一直在做的那样)