【问题标题】:Web Audio API: gap between playback when using context.currentTimeWeb Audio API:使用 context.currentTime 时播放之间的间隙
【发布时间】: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();
}

Actual waveform

Expected waveform

https://github.com/JeffreyLangston/WebAudioApiTest

【问题讨论】:

    标签: javascript web-audio-api


    【解决方案1】:

    您可以使用.setValueCurveAtTime() 方法而不是.linearRampToValueAtTime() 实现等功率交叉淡入淡出。您可以使用以下这些方法来创建所需的曲线并根据需要进行调整:

    const curve = new Float32Array(64);
    
    function makeEqualPowerCurveIn(startVolume, endVolume) {
        var range = endVolume - startVolume;
        curve[0] = startVolume;
        for (var i = 1; i < curve.length; i++)
            curve[i] = startVolume + range * Math.cos((1 - i / (curve.length-1)) * 0.5*Math.PI);
        return curve;
    }
    
    function makeEqualPowerCurveOut(startVolume, endVolume) {
        var range = startVolume - endVolume;
        for (var i = 0; i < curve.length; i++)
            curve[i] = endVolume + range * Math.cos(i / (curve.length-1) * 0.5*Math.PI);
        curve[curve.length - 1] = endVolume;
        return curve;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-06-23
      • 2021-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多