Audio 我如何避免这种情况';单击';当我停止播放某个声音时,会发出声音吗?

Audio 我如何避免这种情况';单击';当我停止播放某个声音时,会发出声音吗?,audio,html5-audio,Audio,Html5 Audio,我真的希望这个问题仍然是一个编程问题,而不是一个声音力学问题。。。这是 我正在做一些实验,以弄清楚Web音频API是如何工作的。我想做的是在一个循环中播放一个简单的“挂断电话”的声音。问题是,当声音结束时,你会听到一种非常恼人的“咔哒”声。我无法更好地解释它,但如果您测试代码,您可以听到它 有什么办法可以避免这种情况吗?我可以用什么过滤器 var audioContext=new(audioContext | | webkitadiocontext)(); var频率偏移=0 函数boop()

我真的希望这个问题仍然是一个编程问题,而不是一个声音力学问题。。。这是

我正在做一些实验,以弄清楚Web音频API是如何工作的。我想做的是在一个循环中播放一个简单的“挂断电话”的声音。问题是,当声音结束时,你会听到一种非常恼人的“咔哒”声。我无法更好地解释它,但如果您测试代码,您可以听到它

有什么办法可以避免这种情况吗?我可以用什么过滤器

var audioContext=new(audioContext | | webkitadiocontext)();
var频率偏移=0
函数boop(){
//我们的声源是一个简单的三角形振荡器
var振荡器=audioContext.CreateSocator();//创建声源
振荡器类型='三角形';
//添加一个增益节点只是为了降低音量并使
//无声刺耳
var gain=audioContext.createGain();
振荡器。连接(增益);
增益.连接(audioContext.目的地);
增益.增益.值=0.1;
//只是为了好玩,让频率在每一天增加
振荡器.frequency.value=200+频率偏移;
振荡器。启动(0);
//声音应持续250毫秒
setTimeout(函数(){
振荡器。断开();
振荡器。停止();
增益。断开连接();
}, 250);
频率偏移+=1;
}

设置间隔(boop,500)这是音频问题,不是编程问题。当一个波形在波的中间停止/切断而不是01:00交叉时,就会发生点击声。 音频模式的最佳简单解决方案是非常快地淡出,而不仅仅是停止播放


一个稍微复杂一点的解决方案是找到下一个过零点并在该点停止播放

看起来Web Audio API为开发人员提供了一种简单的方法,可以在不突然停止波形的情况下停止播放声源,并避免任何噪音和声音瑕疵

  • 创建您的声源(在我的示例中为振荡器)
  • 创建增益节点并将其与声源连接
  • 启动声源并将增益值设置为0。这样,即使从技术上讲,你也不会听到声音
  • 当希望震源播放时,将增益值设置为1;当震源不应播放时,将增益值设置为0。增益节点将处理其余部分,不会听到咔嗒声
  • var audioContext=new(audioContext | | webkitadiocontext)();
    var频率偏移=0
    //我们的声源是一个简单的三角形振荡器
    var振荡器=audioContext.CreateSocator();//创建声源
    振荡器类型='三角形';
    //添加一个增益节点只是为了降低音量并使
    //声音少刺耳。它还允许我们静音和重播
    //我们的随需应变服务
    var gainNode=audioContext.createGain();
    振荡器。连接(增益节点);
    连接(audioContext.destination);
    gainNode.gain.value=0;
    振荡器.frequency.value=200;
    振荡器。启动(0);
    函数boop(){
    gainNode.gain.value=0.1;
    //声音应持续250毫秒
    setTimeout(函数(){
    gainNode.gain.value=0;
    }, 250);
    振荡器.频率.值++;
    }
    
    设置间隔(boop,500)这里有一个简单的解释,说明我们为什么会听到咔哒声(这是人耳的声音),以及如何使用Web audio API绕过这个问题的好例子:

    本文的主要结论是,指数方法可以更好地消除点击指数RAMPTOVALUETIME设置目标时间

    使用SETTARGETATIME删除单击按钮

    var context = new AudioContext();
    var oscillator = context.createOscillator();
    var gainNode = context.createGain();
    
    oscillator.connect(gainNode);
    gainNode.connect(context.destination)
    oscillator.start();
    
    stopButton.addEventListener('click', function() {
        gainNode.gain.setTargetAtTime(0, context.currentTime, 0.015);
    });
    
    var context = new AudioContext();
    var oscillator = context.createOscillator();
    var gainNode = context.createGain();
    
    oscillator.connect(gainNode);
    gainNode.connect(context.destination)
    
    oscillator.start();
    
    stopButton.addEventListener('click', function() {
        // Important! Setting a scheduled parameter value
        gainNode.gain.setValueAtTime(gainNode.gain.value, context.currentTime); 
    
        gainNode.gain.exponentialRampToValueAtTime(0.0001, context.currentTime + 0.03);
    });
    
    使用指数RamptoValueTime删除单击

    var context = new AudioContext();
    var oscillator = context.createOscillator();
    var gainNode = context.createGain();
    
    oscillator.connect(gainNode);
    gainNode.connect(context.destination)
    oscillator.start();
    
    stopButton.addEventListener('click', function() {
        gainNode.gain.setTargetAtTime(0, context.currentTime, 0.015);
    });
    
    var context = new AudioContext();
    var oscillator = context.createOscillator();
    var gainNode = context.createGain();
    
    oscillator.connect(gainNode);
    gainNode.connect(context.destination)
    
    oscillator.start();
    
    stopButton.addEventListener('click', function() {
        // Important! Setting a scheduled parameter value
        gainNode.gain.setValueAtTime(gainNode.gain.value, context.currentTime); 
    
        gainNode.gain.exponentialRampToValueAtTime(0.0001, context.currentTime + 0.03);
    });
    

    在我的用例中,这两种方法对我都有效,指数RAMPTOVALUEATTIME的效果稍好一些。使用setTargetAtTime

    我仍然可以听到微弱的点击声,这正是我在我的应用程序中所做的,但即使在你的代码片段中,也仍然有这种点击声。我甚至尝试了gain.exponentialRampToValueAtTime()和gain.linearRampToValueAtTime(),但它也不起作用。好吧,在Chrome中,它可以正常工作,但在Firefox中不行。(win7,ff 41.0.1)Mozilla知道这个bug吗?@LajosMeszaros——这不是bug,而是音频处理和合成中一个基本的、众所周知的问题。web音频API实现可能提供一个简单的现成解决方案,但这不是一个优先考虑的问题。@JohnWeisz-让我重新表述一下这个问题。Mozilla是否意识到这种实现与Chrome不一致?顺便说一句,答案是肯定的,但他们正在等待解决方案,直到WebAudio API提供了一个关于如何处理这种情况的适当解决方案。添加指向WebAudioAPI讨论的链接,该讨论针对这个主题:现在,您可以使用增益节点,并使用指数RamptoValueTime降低其值。如果你感兴趣的话,我在这里写了更多的内容:@margg
    exponentialRampToValueAtTime
    method或
    setTargetAtTime
    method目前在Firefox(Windows 7,54.0.1版(32位))振荡器中不起作用。stop()丢失了这是我在Chrome上唯一起作用的方法。谢谢