最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Web audio "Click" sound even when using exponentialRampToValueAtTime - Stack Overflow

programmeradmin0浏览0评论

I am trying to avoid having the ugly "click" sound when stopping an oscillator, so I decided to try some fade-outs with exponentialRampToValueAtTime. Like this:

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);

I am trying to avoid having the ugly "click" sound when stopping an oscillator, so I decided to try some fade-outs with exponentialRampToValueAtTime. Like this:

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);

This works well, there's no "click" sound and the ramp down is smooth. However, as soon as I do this using buttons and event listeners, the ugly click es back and somehow the ramp down is more brute

btw, please wait 1 second after pressing "stop" and before re-pressing "play" or ugly things happen :)

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>

I'm clearly missing some theory here. The code is very similar except for the listeners and the oute of both snippets is very different in quality. Can you please explain where that difference es from?

Is there a way to achieve the first snippet quality while using buttons/listeners?

Thanks!

Share Improve this question asked Dec 26, 2015 at 23:18 alemanguialemangui 3,65525 silver badges33 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 11

The problem is that the ramp is done from the previously scheduled value, which in this case is when you pressed the play button. If you set the value once more before scheduling the ramp you'll get a smooth transition again!

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>

I would also remend using a ramp for the playButton event. In this case, there will also be no "click" effect when starting playback.

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>

发布评论

评论列表(0)

  1. 暂无评论