以下代码遵循 MDN 文档,但会导致突然静音,而不是 2 秒长的淡出:
const audioContext = new window.AudioContext();
let oscillator;
let gainNode;
document.getElementById("playSweep").addEventListener("click", () => {
oscillator = audioContext.createOscillator();
oscillator.type = "sine"; // Sine wave
oscillator.frequency = 200;
gainNode = audioContext.createGain();
gainNode.gain.setValueAtTime(1, audioContext.currentTime);
oscillator.connect(gainNode);
gainNode.connect(audioContext.destination);
oscillator.start();
});
document.getElementById("fadeOut").addEventListener("click", () => {
gainNode.gain.exponentialRampToValueAtTime(0.001, audioContext.currentTime + 2);
});
document.getElementById("fadeOut2").addEventListener("click", () => {
gainNode.gain.linearRampToValueAtTime(0.001, audioContext.currentTime + 2);
});
<button id="playSweep">Play Frequency Sweep</button>
<button id="fadeOut">Exp Fade Out</button>
<button id="fadeOut2">Lin Fade Out</button>
即使使用线性版本,我们也可以听到咔哒声,这不是干净的淡出。
如何在 JS Web Audio API 中进行适当的淡出?
在调用这些方法时,您(显然)需要在
AudioParam
上有一个活动事件,以便它们能够优雅地转换。您可以通过在调用任一方法之前调用 setValueAtTime()
来实现此目的。exponentialRampToValueAtTime()
,它足够接近 setTargetAtTime(target, startTime, timeConstant)
并允许变为零。
const audioContext = new window.AudioContext();
let oscillator;
let gainNode;
document.getElementById("playSweep").addEventListener("click", () => {
oscillator = audioContext.createOscillator();
oscillator.type = "sine"; // Sine wave
oscillator.frequency = 200;
gainNode = audioContext.createGain();
oscillator.connect(gainNode);
gainNode.connect(audioContext.destination);
oscillator.start();
});
document.getElementById("fadeOut").addEventListener("click", () => {
gainNode.gain.setValueAtTime(1, audioContext.currentTime);
gainNode.gain.exponentialRampToValueAtTime(0.001, audioContext.currentTime + 2);
oscillator.stop(audioContext.currentTime + 2);
});
document.getElementById("fadeOut2").addEventListener("click", () => {
gainNode.gain.setValueAtTime(1, audioContext.currentTime);
gainNode.gain.linearRampToValueAtTime(0, audioContext.currentTime + 2);
oscillator?.stop(audioContext.currentTime + 2);
});
document.getElementById("fadeOut3").addEventListener("click", () => {
gainNode.gain.setTargetAtTime(0, audioContext.currentTime, 0.5);
oscillator?.stop(audioContext.currentTime + 3);
});
<button id="playSweep">Play Frequency Sweep</button>
<button id="fadeOut">Exp Fade Out</button>
<button id="fadeOut2">Lin Fade Out</button>
<button id="fadeOut3">Time constant Fade Out</button>