网络音频 "Click" 即使在使用 exponentialRampToValueAtTime 时也会发出声音

Web audio "Click" sound even when using exponentialRampToValueAtTime

我试图避免在停止振荡器时发出丑陋的 "click" 声音,所以我决定尝试使用 exponentialRampToValueAtTime 进行一些淡出。像这样:

var playButton = document.getElementById('play');
var stopButton = document.getElementById('stop');

var context = new AudioContext();
var gainNode = context.createGain();
var oscillator =  context.createOscillator();

gainNode.connect(context.destination);
oscillator.connect(gainNode);
gainNode.gain.setValueAtTime(1, context.currentTime);
oscillator.start();
gainNode.gain.exponentialRampToValueAtTime(0.0001, context.currentTime + 1);

这很好用,没有 "click" 声音,而且下降很平稳。然而,一旦我使用按钮和事件侦听器执行此操作,丑陋的点击就会回来,不知何故,斜坡下降更加粗暴

顺便说一句,请在按下 "stop" 后等待 1 秒,然后再按下 "play" 或丑陋的事情发生:)

var playButton = document.getElementById('play');
var stopButton = document.getElementById('stop');

var context = new AudioContext();
var gainNode = context.createGain();
var oscillator;

gainNode.connect(context.destination);


playButton.addEventListener('click', function() {
  oscillator = context.createOscillator();
  oscillator.connect(gainNode);
  gainNode.gain.setValueAtTime(1, context.currentTime);
  oscillator.start();
}, false);

stopButton.addEventListener('click', function() {
  gainNode.gain.exponentialRampToValueAtTime(0.0001, context.currentTime + 1);
  setTimeout(function(){
   oscillator.stop();
  }, 1000)
}, false);
<button id="play">play</button>
<button id="stop">stop</button>

我显然在这里遗漏了一些理论。除了侦听器之外,代码非常相似,并且两个片段的结果在质量上有很大不同。你能解释一下这种差异来自哪里吗?

有没有办法在使用 buttons/listeners 时达到第一个片段的质量?

谢谢!

问题是斜坡是从之前预定的值开始的,在本例中是当您按下播放按钮时。如果您在安排渐变之前再次设置该值,您将再次获得平滑过渡!

var playButton = document.getElementById('play');
var stopButton = document.getElementById('stop');

var context = new AudioContext();
var gainNode = context.createGain();
var oscillator;

gainNode.connect(context.destination);


playButton.addEventListener('click', function() {
  oscillator = context.createOscillator();
  oscillator.connect(gainNode);
  gainNode.gain.setValueAtTime(1, context.currentTime);
  oscillator.start();
}, false);

stopButton.addEventListener('click', function() {
  gainNode.gain.setValueAtTime(gainNode.gain.value, context.currentTime);
  gainNode.gain.exponentialRampToValueAtTime(0.0001, context.currentTime + 1);
  setTimeout(function(){
   oscillator.stop();
  }, 1000)
}, false);
<button id="play">play</button>
<button id="stop">stop</button>

我还建议对 playButton 事件使用斜坡。这样的话,开始播放时也不会出现“咔嚓”的效果。

var playButton = document.getElementById('play');
var stopButton = document.getElementById('stop');

var context = new AudioContext();
var gainNode = context.createGain();
var oscillator;
var rampDuration = 0.3;

gainNode.connect(context.destination);


playButton.addEventListener('click', function() {
  oscillator = context.createOscillator();
  oscillator.connect(gainNode);
  gainNode.gain.setValueAtTime(0.0001, context.currentTime);
  gainNode.gain.exponentialRampToValueAtTime(1, context.currentTime + rampDuration);
  oscillator.start();
}, false);

stopButton.addEventListener('click', function() {
  gainNode.gain.setValueAtTime(gainNode.gain.value, context.currentTime);
  gainNode.gain.exponentialRampToValueAtTime(0.0001, context.currentTime + rampDuration);
  setTimeout(function(){
    oscillator.stop();
  }, rampDuration*1000)
}, false);
<button id="play">play</button>
<button id="stop">stop</button>