【发布时间】:2019-02-08 04:13:28
【问题描述】:
环境: Windows 10 和 MacOS 高塞拉 Chrome 和 Safari
用例: 我们想一次播放 N 个音频文件。无缝循环给定音频文件,直到用户通过 UI 交互切换另一个轨道。目前我们在轨道之间使用线性淡入淡出。因为用户可以更改轨道将在什么点循环,我们需要能够通过循环市场检测轨道位置并在轨道之间进行动态转换。我们安排淡出当前增益节点,并在循环结束后立即淡入同一轨道的新增益节点。
预期结果: 使用 110hz 余弦信号音频文件,我们循环播放源之间的无限衰落。给定相同频率的两个余弦波形之间完美对齐的过渡,我们预计在轨道之间的过渡过程中幅度没有变化。在这种情况下,两个具有相同持续时间和起始时间的线性斜坡应该会完美地相互抵消。
观察结果: 即使我们将第二个源的开始时间设置为与第一个源的淡出开始时间相同,我们最终还是会在播放中出现随机幅度下降。偶尔播放会对齐,我们会看到对齐波形的预期结果。
什么可能导致这种行为? context.currentTime 是否不可靠来调度事件?
此代码是一个混蛋版本,但复制了该问题:
function Crossfade() {
console.log('crossfade function');
var request = new XMLHttpRequest();
request.open('GET', 'http://localhost:8080/cosine_110hz.wav', true);
request.responseType = 'arraybuffer';
request.onload = function() {
context.decodeAudioData(request.response, function(buffer) {
console.log("track received.");
let trackStart = context.currentTime + .1;
let fadeDuration = .25;
let fadeOutStart = trackStart;
var gainNode2 = context.createGain();
var source2 = context.createBufferSource();
source2.buffer = buffer;
source2.connect(gainNode2);
gainNode2.connect(context.destination);
gainNode.gain.setValueAtTime(1, trackStart);
gainNode.gain.linearRampToValueAtTime(0, trackStart + fadeDuration);
source.stop(trackStart + fadeDuration);
gainNode2.gain.setValueAtTime(0, trackStart);
gainNode2.gain.linearRampToValueAtTime(1, trackStart + fadeDuration);
source2.start(trackStart, 0);
gainNode = gainNode2;
source = source2;
setTimeout(Crossfade, 1000);
})
}
request.send();
}
【问题讨论】: