防止播放Java 7/8采样声音时单击(适用于6)

防止播放Java 7/8采样声音时单击(适用于6),java,audio,java-8,java-7,javax.sound.sampled,Java,Audio,Java 8,Java 7,Javax.sound.sampled,在OSX上以Java 6运行时,以下代码与预期的一样工作(它不会发出声音-它会多次播放静音示例),但在Java 7和8中运行时,在每次播放示例的末尾,会出现一个单击。不明白为什么;在6和7之间看不到任何明显的API更改。(这是莫尔斯电码培训计划的一部分,该计划还播放dits和dahs。在每个静音间隔或示例的末尾单击显然是不可接受的) 提前感谢您的建议 import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioS

在OSX上以Java 6运行时,以下代码与预期的一样工作(它不会发出声音-它会多次播放静音示例),但在Java 7和8中运行时,在每次播放示例的末尾,会出现一个单击。不明白为什么;在6和7之间看不到任何明显的API更改。(这是莫尔斯电码培训计划的一部分,该计划还播放dits和dahs。在每个静音间隔或示例的末尾单击显然是不可接受的)

提前感谢您的建议

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineEvent.Type;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineUnavailableException;

// Demonstration of the 'clicking sound' fault in Java 7 & 8
// Repeatedly play a short sample of silence (happens on other samples too).
public class PlaySilence {
    private static int SAMPLE_RATE = 48000;
    private static final AudioFormat FORMAT = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 
            (float) SAMPLE_RATE, 8, 1, 1, SAMPLE_RATE, false);

    public static void main(String[] args) throws LineUnavailableException, InterruptedException {
        AudioListener listener = new AudioListener();
        Clip clip = oneSecondSilentClip();
        System.out.println("Clip is a " + clip);
        clip.addLineListener(listener);

        System.out.println("Starting");
        for (int i = 0; i < 10; i++) {
            listener.reset();

            System.out.println("Playing..." + System.currentTimeMillis());
            clip.setFramePosition(0);
            clip.start(); 
            clip.drain(); // just to make sure we've finished the clip; the listener is more reliable?

            // On OSX Java 1.6.0_65, you just hear silence here as expected.
            // On OSX Java 1.8.0_25 and 1.7.0_75, at the end of each playback of the clip, there's a
            // very noticeable click.

            listener.waitUntilDone();
        }
        System.out.println("Done");
        clip.removeLineListener(listener);
        clip.close();
    }

    private static Clip oneSecondSilentClip() throws LineUnavailableException {
        int samples = (int) (SAMPLE_RATE * (double) 1);
        byte[] out = new byte[samples];
        Clip clip = AudioSystem.getClip();
        clip.open(FORMAT, out, 0, out.length);
        clip.setFramePosition(0);
        return clip;
    }

    // Adapted from http://stackoverflow.com/questions/577724/trouble-playing-wav-in-java/577926#577926
    // Thanks, McDowell.
    static class AudioListener implements LineListener {
        private boolean done = false;

        public synchronized void reset() {
            done = false;
        }

        public synchronized void update(LineEvent event) {
            Type eventType = event.getType();
            System.out.println("event " + eventType);
            if (eventType == Type.STOP || eventType == Type.CLOSE) {
                done = true;
                notifyAll();
            }
        }

        public synchronized void waitUntilDone() throws InterruptedException {
            while (!done) {
                wait();
            }
        }
    }

}
导入javax.sound.sampled.AudioFormat;
导入javax.sound.sampled.AudioSystem;
导入javax.sound.sampled.Clip;
导入javax.sound.sampled.LineEvent;
导入javax.sound.sampled.LineEvent.Type;
导入javax.sound.sampled.LineListener;
导入javax.sound.sampled.LineUnavailableException;
//Java 7和8中“咔哒声”故障的演示
//重复播放简短的沉默示例(其他示例也会出现)。
公共课游戏沉默{
私有静态整数抽样率=48000;
专用静态最终音频格式=新音频格式(AudioFormat.Encoding.PCM_签名,
(浮动)采样率,8,1,1,采样率,假);
公共静态void main(字符串[]args)引发LineUnavailableException、InterruptedException{
AudioListener=新的AudioListener();
Clip Clip=oneSecondSilentClip();
System.out.println(“Clip是一个”+Clip);
clip.addLineListener(listener);
System.out.println(“启动”);
对于(int i=0;i<10;i++){
reset();
System.out.println(“播放…”+System.currentTimeMillis());
clip.setFramePosition(0);
clip.start();
clip.drain();//只是为了确保我们已经完成了剪辑;侦听器更可靠吗?
//在OSX Java 1.6.0_65上,您只需像预期的那样听到这里的沉默。
//在OSX Java 1.8.0_25和1.7.0_75上,在每次播放片段的末尾,都有一个
//非常明显的咔嗒声。
listener.waitUntilDone();
}
系统输出打印项次(“完成”);
clip.removeLineListener(监听器);
clip.close();
}
私有静态剪辑oneSecondSilentClip()引发LineUnavailableException{
int样本=(int)(样本率*(双)1);
字节[]输出=新字节[样本];
Clip Clip=AudioSystem.getClip();
clip.open(格式,out,0,out.length);
clip.setFramePosition(0);
回程夹;
}
//改编自http://stackoverflow.com/questions/577724/trouble-playing-wav-in-java/577926#577926
//谢谢,麦克道尔。
静态类AudioListener实现LineListener{
私有布尔完成=假;
公共同步无效重置(){
完成=错误;
}
公共同步作废更新(LineEvent事件){
类型eventType=event.getType();
System.out.println(“事件”+事件类型);
if(eventType==Type.STOP | | eventType==Type.CLOSE){
完成=正确;
notifyAll();
}
}
public synchronized void waitUntilDone()引发InterruptedException{
而(!完成){
等待();
}
}
}
}

它不喜欢音频格式中的帧大小为1,任何大于1的都可以:

private static int FRAME_SIZE = 2;

private static final AudioFormat FORMAT = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
      SAMPLE_RATE, 8, 1, FRAME_SIZE, SAMPLE_RATE, false);

谢谢你发现了这个,greg-449!它工作正常(在Java 8上进行了测试),并且完全解决了这个问题。Greg,你能解释一下为什么它可以工作吗?正如AudioFormat文档中所说的那样,我明白了:“对于像PCM这样的编码,帧由给定时间点上所有通道的样本集组成,因此帧的大小(以字节为单位)总是等于样本的大小(以字节为单位)乘以通道数。“。。。我使用单声道(单声道)和字节。。因此,帧大小为1字节*1通道=1(这会导致单击)。。。向你问好,马特对不起,我真的不知道。一个相框大小似乎不寻常,所以我尝试了其他东西!