admin管理员组文章数量:1335371
So i have a bunch of loaded audio samples that I am calling the schedule function with in the code below:
let audio;
function playChannel() {
let audioStart = context.currentTime;
let next = 0;
for(let i = 0; i < 8; i++) {
scheduler(audioStart, next);
next++;
}
}
Here is the audio scheduler function:
function scheduler(audioStart, index) {
audio = context.createBufferSource();
audio.buffer = audioSamples[index]; //array with all the loaded audio
audio.connect(context.destination);
audio.start(audioStart + (audio.buffer.duration * index));
}
And it's working fine and plays the scheduled sounds as it should.
How am I supposed to stop/cancel all the scheduled sounds from playing?
Because right now when I try to call the stop()
method it will only stop the last scheduled sound from playing.
So i have a bunch of loaded audio samples that I am calling the schedule function with in the code below:
let audio;
function playChannel() {
let audioStart = context.currentTime;
let next = 0;
for(let i = 0; i < 8; i++) {
scheduler(audioStart, next);
next++;
}
}
Here is the audio scheduler function:
function scheduler(audioStart, index) {
audio = context.createBufferSource();
audio.buffer = audioSamples[index]; //array with all the loaded audio
audio.connect(context.destination);
audio.start(audioStart + (audio.buffer.duration * index));
}
And it's working fine and plays the scheduled sounds as it should.
How am I supposed to stop/cancel all the scheduled sounds from playing?
Because right now when I try to call the stop()
method it will only stop the last scheduled sound from playing.
2 Answers
Reset to default 6You'll need to keep track of the BufferSource nodes you're creating inside scheduler, referenced by index, and then run through all of them. E.g.:
var sources = [];
function scheduler(audioStart, index) {
audio = context.createBufferSource();
sources[index] = audio;
audio.buffer = audioSamples[index]; //array with all the loaded audio
audio.connect(context.destination);
audio.start(audioStart + (audio.buffer.duration * index));
}
function stopAll() {
for(let i = 0; i < 8; i++)
if (sources[i])
sources[i].stop(0);
}
While the accepted answer is correct, the sources
array will keep growing indefinitely.
To fix that, you should listen to the source node's onended
and remove them from sources
once they are done playing (or stopped).
Here's a class that encapsulates the logic to load a sound from a URL and play/stop it as many times as you want, keeping track of all currently playing sources and cleaning them up as needed:
window.AudioContext = window.AudioContext || window.webkitAudioContext;
const context = new AudioContext();
export class Sound {
url = '';
buffer = null;
sources = [];
constructor(url) {
this.url = url;
}
load() {
if (!this.url) return Promise.reject(new Error('Missing or invalid URL: ', this.url));
if (this.buffer) return Promise.resolve(this.buffer);
return new Promise((resolve, reject) => {
const request = new XMLHttpRequest();
request.open('GET', this.url, true);
request.responseType = 'arraybuffer';
// Decode asynchronously:
request.onload = () => {
context.decodeAudioData(request.response, (buffer) => {
if (!buffer) {
console.log(`Sound decoding error: ${ this.url }`);
reject(new Error(`Sound decoding error: ${ this.url }`));
return;
}
this.buffer = buffer;
resolve(buffer);
});
};
request.onerror = (err) => {
console.log('Sound XMLHttpRequest error:', err);
reject(err);
};
request.send();
});
}
play(volume = 1, time = 0) {
if (!this.buffer) return;
// Create a new sound source and assign it the loaded sound's buffer:
const source = context.createBufferSource();
source.buffer = this.buffer;
// Keep track of all sources created, and stop tracking them once they finish playing:
const insertedAt = this.sources.push(source) - 1;
source.onended = () => {
source.stop(0);
this.sources.splice(insertedAt, 1);
};
// Create a gain node with the desired volume:
const gainNode = context.createGain();
gainNode.gain.value = volume;
// Connect nodes:
source.connect(gainNode).connect(context.destination);
// Start playing at the desired time:
source.start(time);
}
stop() {
// Stop any sources still playing:
this.sources.forEach((source) => {
source.stop(0);
});
this.sources = [];
}
}
You can then do something like this:
const soundOne = new Sound('./sounds/sound-one.mp3')
const soundTwo = new Sound('./sounds/sound-two.mp3')
Promises.all([
soundOne.load(),
soundTwo.load(),
]).then(() => {
buttonOne.onclick = () => soundOne.play();
buttonTwo.onclick = () => soundOne.play();
})
本文标签: javascriptWeb Audio API Stop all scheduled sounds from playingStack Overflow
版权声明:本文标题:javascript - Web Audio API: Stop all scheduled sounds from playing - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742343635a2457085.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论