audioContext.suspend()未能按预期停止音乐

时间:2019-04-14 19:31:38

标签: javascript web-audio

我正在尝试使一些生成音乐理想地暂停,但我决定停止使用Wen Audio Javascript API。我的问题是audioContext.suspend()似乎没有做任何事情。所有文档和示例均建议使用以下方法,但我无法解决问题。但是,我是javascript新手,所以怀疑我在做一些愚蠢的事情。

所有控制台日志均证明该功能在第二次单击时触发。我也尝试过停止,但也没有用。我正在使用Chrome来测试我的作品,已经在Safari上进行了尝试,但是效果还不及播放曲目。

// for cross browser
const AudioContext = window.AudioContext || window.webkitAudioContext;
const audioContext = new AudioContext();

function startLoop(audioBuffer, pan=0, rate=1) {
    let sourceNode = audioContext.createBufferSource();
    let pannerNode = audioContext.createStereoPanner();

    sourceNode.buffer = audioBuffer;
    sourceNode.loop = true;
    sourceNode.loopStart = 11.35;
    sourceNode.loopEnd = 12.1;
    sourceNode.playbackRate.value = rate;
    sourceNode.connect(audioContext.destination);

    pannerNode.pan.value = pan;

    sourceNode.connect(pannerNode);
    pannerNode.connect(audioContext.destination);

    sourceNode.start(0, 0);
}

function playAudio() {
console.log("playAudio")
fetch('Ambition.mp3')
  .then(response => response.arrayBuffer())
  .then(arrayBuffer => audioContext.decodeAudioData(arrayBuffer))
  .then(audioBuffer => {
    startLoop(audioBuffer,-1);
    startLoop(audioBuffer,1,1.002);
  })
  .catch(e => console.error(e));
}

var playing = "False"

function playOrStop() {
console.log("Playing is set to " + playing)
if (playing === "False") 
    {
    console.log("Play");
    playAudio();
    playing="True";
     }
else {
console.log("Suspend");

//这是不起作用的功能

audioContext.suspend().then(function() {
      playing="Suspend";
      console.log("Suspend happened")
        })
     }
}

var b1=document.getElementById("playButton1");
b1.onclick = playOrStop;

第二次单击按钮-在日志上显示“发生了暂停”,但音频没有暂停。 第一次点击可以正常工作。

1 个答案:

答案 0 :(得分:0)

我执行了您的代码(使用其他MP3),并且在Firefox和Chrome中按预期方式工作。我按下按钮,等待声音开始。几秒钟后,我再次按下按钮,声音停止了。

但是我认为您在Chrome中遇到了一个微妙的错误/功能。在Chrome中实施自动播放策略后,该策略应尽可能向后兼容。这就是为什么在start()上调用AudioScheduledSourceNode还能恢复暂停的上下文的原因。

如果您两次按下按钮而第一个承诺尚未解决,则您的代码会先调用audioContext.suspend(),然后再调用sourceNode.start()。即使对suspend()的调用有效,随后在start()上对AudioScheduledSourceNode的任何调用也会将上下文的状态重新设置为运行。

Firefox的处理方式有所不同,共识是Firefox在这种情况下是正确的。规范已经更改以反映(https://github.com/WebAudio/web-audio-api/pull/1823),并且很可能会在将来的Chrome版本中得到修复。但是,提交一个错误当然不会造成伤害。 https://new.crbug.com

如果要阻止sourceNode恢复AudioContext,可以在调用state之前检查上下文的start()

if (audioContext.state === 'running') {
    sourceNode.start(0, 0);
}

您的示例在Safari中不起作用,因为它不支持StereoPannerNode。我确实建议使用标准化音频上下文(https://github.com/chrisguttandin/standardized-audio-context),以获得更好的跨浏览器兼容性,因为我是该库的作者。 :-)它还带有StereoPannerNode实现,可在Safari中使用。