audioContext.suspend() 没有按预期停止音乐
audioContext.suspend() not stopping music as expected
我正在尝试让一些生成音乐理想地暂停,但我愿意停止使用 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;
第二次单击按钮 - 'Suspend happened' 显示在日志中,但音频没有暂停。
第一次点击按预期工作。
我执行了您的代码(使用不同的 MP3),它在 Firefox 和 Chrome 中按预期工作。我按下按钮,等待声音开始。几秒钟后我再次按下按钮,声音停止了。
但我觉得你运行在Chrome中进入了微妙的bug/feature。当在 Chrome 中实施自动播放政策时,它旨在尽可能向后兼容。这就是为什么在 AudioScheduledSourceNode
上调用 start()
也可以恢复挂起的上下文。
如果您按下按钮两次并且第一个承诺尚未解决,那么您的代码会在调用 sourceNode.start()
之前调用 audioContext.suspend()
。即使对 suspend()
的调用有效,在 AudioScheduledSourceNode
上对 start()
的任何后续调用都会将上下文的状态设置回 运行.
Firefox 对此的处理方式不同,大家一致认为 Firefox 在这种情况下是正确的。规范已更改以反映 (https://github.com/WebAudio/web-audio-api/pull/1823) and it will most likely get fixed in a future version of Chrome. But it can of course never hurt to file a bug. https://new.crbug.com
如果您想阻止 sourceNode
恢复 AudioContext,您可以在调用 start()
.
之前检查上下文的 state
if (audioContext.state === 'running') {
sourceNode.start(0, 0);
}
您的示例在 Safari 中不起作用,因为它不支持 StereoPannerNode
。我建议使用 standardized-audio-context (https://github.com/chrisguttandin/standardized-audio-context) 以获得更好的跨浏览器兼容性,因为我是该库的作者。 :-) 它还附带了一个在 Safari 中工作的 StereoPannerNode
实现。
我正在尝试让一些生成音乐理想地暂停,但我愿意停止使用 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;
第二次单击按钮 - 'Suspend happened' 显示在日志中,但音频没有暂停。 第一次点击按预期工作。
我执行了您的代码(使用不同的 MP3),它在 Firefox 和 Chrome 中按预期工作。我按下按钮,等待声音开始。几秒钟后我再次按下按钮,声音停止了。
但我觉得你运行在Chrome中进入了微妙的bug/feature。当在 Chrome 中实施自动播放政策时,它旨在尽可能向后兼容。这就是为什么在 AudioScheduledSourceNode
上调用 start()
也可以恢复挂起的上下文。
如果您按下按钮两次并且第一个承诺尚未解决,那么您的代码会在调用 sourceNode.start()
之前调用 audioContext.suspend()
。即使对 suspend()
的调用有效,在 AudioScheduledSourceNode
上对 start()
的任何后续调用都会将上下文的状态设置回 运行.
Firefox 对此的处理方式不同,大家一致认为 Firefox 在这种情况下是正确的。规范已更改以反映 (https://github.com/WebAudio/web-audio-api/pull/1823) and it will most likely get fixed in a future version of Chrome. But it can of course never hurt to file a bug. https://new.crbug.com
如果您想阻止 sourceNode
恢复 AudioContext,您可以在调用 start()
.
state
if (audioContext.state === 'running') {
sourceNode.start(0, 0);
}
您的示例在 Safari 中不起作用,因为它不支持 StereoPannerNode
。我建议使用 standardized-audio-context (https://github.com/chrisguttandin/standardized-audio-context) 以获得更好的跨浏览器兼容性,因为我是该库的作者。 :-) 它还附带了一个在 Safari 中工作的 StereoPannerNode
实现。