Java音频噼啪声

时间:2016-01-03 18:20:06

标签: java javasound

当我在我的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();
        }
    }
}

3 个答案:

答案 0 :(得分:1)

好奇的东西。鉴于你找到了解决方案,也许我不应该加两分钱。但是有些事情看起来令人费解,并且与我所知道的音频世界并不完全匹配。

通常爆裂和失真是PCM数据点超出其界限的结果。例如,如果您的数据范围为-32768到32767(通过签名短路表示的16位编码)的wav文件,并且值超出该范围,则可能发生各种排序的失真。

如果一次播放多个wav文件,并且wavs已经处于非常高的音量,则可能会出现这种情况。当它们的数据相加在一起以便同时回放时,可能会超出16位范围。

如果暂停的增加具有阻止wavs同时播放的主要作用,那么这也可以减少失真量。

在某些情况下,音频线程需要一点时间才能完成并响应状态更改。但我无法想到任何可能导致噼啪声或模糊的地方。 (但这并不意味着没有这种情况。)

简单地绕过一些样本,通过skip(),应该(理论上)只有在原始wav文件中出现相同的噼啪声和模糊时才会有帮助,并且你跳过了扭曲的部分。但是,如果从已经可听到的音量​​级别开始,则应该导致单击。

顺便说一句,你可能最好将文件作为SourceDataLines而不是Clips运行。剪辑仅适用于您要多次重放声音并且能够将数据保存在内存中的情况。编码时,每次播放声音时,首先将整个声音加载到内存中,然后播放。在将所有数据加载到内存之前,Clip不会播放。使用SourceDataLine,播放代码在播放时读取数据,消耗更少的内存。

如果你能负担得起内存,只需将Clip加载一次到它自己的变量中。在播放Clip之后,可以将光标设置回Clip的开头,然后重放数据而无需从文件中重新加载(正如您一直在做的那样)。

答案 1 :(得分:-1)

没关系,我想通了,while循环运行得很快,所以我添加了一个睡眠功能

答案 2 :(得分:-2)

噼里啪啦总是在开始?如果是这样,我发现一些代码跳过了第一个字节以避免这种情况:

// Skip some bytes at the beginning to prevent crackling noise.
audio.skip(30);

来源:http://veritas.eecs.berkeley.edu/apcsa-ret/program/projects/lesson13/Sound/SampleRateConverter.java