首页 > 解决方案 > cancelScheduledValues(x) 后跟 setValueCurveAtTime(x) 抛出错误

问题描述

我正在使用 WebAudio API 在多个源之间交叉淡入淡出。使用setValueCurveAtTime(曲线、时间、持续时间)对渐变进行排队。WebAudio 规范表明不允许任何后续调用具有重叠持续时间的 setValueCurveAtTime。所以我在排队新的淡入淡出之前调用cancelScheduledValues (时间)。然而,Firefox v68 和 Chrome v77 在第二次调用 setValueCurveAtTime 时都会抛出错误。

附加的代码片段包含在任一浏览器中触发错误的最少代码量。单击开始以触发错误。请注意,它不会播放任何音频,因为它不需要引发错误。选择下拉菜单允许控制time两个函数的参数。在 Chrome v77time=0中不会触发错误。

任何关于如何让它在两种浏览器中工作的想法都将不胜感激!

更新:正如Raymond Toy指出的那样,cancelScheduledValues(t) 似乎取消了在或以后开始t的自动化(不仅仅是在 期间有效t)。通过使用cancelScheduledValues(Math.max(t - duration, 0))代码现在似乎可以在 Chrome 中使用。然而,Firefox 仍然失败并出现Operation is not supported错误。

<!DOCTYPE html>
<html>
  <body>
    <button id="start">Start</button>
    <select id="time">
      <option value="0">time=0</option>
      <option value="1">time=currentTime</option>
    </select>
    <pre id="log"></pre>

    <script>
      const select = document.querySelector('#time')
      const log = document.querySelector('#log')
      
      function start() {
        const ctx = new AudioContext()
        ctx.resume()
        const gain = ctx.createGain()
        gain.connect(ctx.destination)

        // Fade in
        gain.gain.setValueCurveAtTime(new Float32Array([0, 1]), 0, 1)

        setTimeout(() => {
          const time = select.options[select.selectedIndex].value === '0' ? 0 : ctx.currentTime

          // Replace fade in with fade out
          // THIS IS THE CALL THAT DOESN'T WORK =====
          // Doesn't work in Firefox nor Chrome:
          // gain.gain.cancelScheduledValues(time)
          // Doesn't work in Firefox:
          gain.gain.cancelScheduledValues(Math.max(time - 1 /* duration of previous fade */, 0))

          try {
            // ERROR IS THROWN HERE =================
            gain.gain.setValueCurveAtTime(new Float32Array([0, 1]), time, 1)
          } catch (error) {
            log.prepend(error.message + '\n')
            throw error
          }
          log.prepend('No error!\n')
        }, 100)
      }

      document.querySelector('#start').addEventListener('click', start)
    </script>
  </body>
</html>

标签: javascriptgoogle-chromefirefoxweb-audio-api

解决方案


我对cancelScheduledValues的阅读表明这是按预期工作的。a 的事件时间setValueCurveAtTime(curve, time, duration)timecancelScheduledValues(t2)删除事件时间大于或等于的所有事件t2。在您的测试用例中,time= 0,并且t2iscurrentTime大于 0。因此,不会从时间线中删除任何内容。第二次调用setValueCurveAtTime插入一个与前一个重叠的新事件。因此,您会收到错误消息。

话虽如此,我认为这有点出乎意料。这可能是 WebAudio 规范中的错误。


推荐阅读