在Chrome或Firefox中使用exponentialRampToValueAtTime的音频淡出并不可靠

问题描述 投票:0回答:1

以下代码遵循 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 中进行适当的淡出?

javascript audio html5-audio web-audio-api fadeout
1个回答
0
投票

在调用这些方法时,您(显然)需要在

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>

© www.soinside.com 2019 - 2024. All rights reserved.