我知道AudioBufferSourceNode上有一个选项loop=true
。但是我只想重复几次wav。例如,如何重复两次?
var url = 'main.wav';
var context = new AudioContext();
var source = context.createBufferSource();
source.connect(context.destination);
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
request.onload = function() {
context.decodeAudioData(request.response, function(response) {
source.buffer = response;
source.start(0);
source.start(source.buffer.duration); // doesn't work "cannot call start more than once."
//source.loop = true; // this is infinite amount of times, not good
}, function () { console.error('The request failed.'); } );
}
request.send();
我也尝试创建第二个缓冲区:
var source2 = context.createBufferSource();
// inside callback
source2.buffer = response; // same response so I don't need to load this separately
source2.start(source.buffer.duration); // doesn't work
但是那也不起作用。有什么想法吗?
您可以将AudioBufferSource的source
设置为true并调用
const url = 'main.wav';
const context = new AudioContext();
const source = context.createBufferSource();
// Tracks the number to playback cycles remaining
let playbackCount = 5;
source.connect(context.destination);
const request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
request.onload = () => {
context.decodeAudioData(request.response, (response) => {
source.buffer = response;
source.start(0);
// Enable loop behavior
source.loop = true;
// Add event listener that fires after full playthrough
source.addEventListener("ended", () => {
// Decrement playback count
playbackCount --;
if(playbackCount <= 0) {
// Stop playback source if count reaches zero
source.stop();
}
});
}, () => {
console.error('The request failed.');
});
}
request.send();
loop
source.stop( ctx.currentTime + audioBuffer.duration * repeatTime )
您使用第二个缓冲区的方法是正确的,您只需要通过将音频上下文时间和声音持续时间相加来使用绝对开始时间:
(async () => {
const url = 'https://dl.dropboxusercontent.com/s/1cdwpm3gca9mlo0/kick.mp3';
const buf = await fetch( url ).then( (r) => r.arrayBuffer() );
const ctx = new AudioContext();
const audioBuffer = await ctx.decodeAudioData( buf );
btn.onclick = (e) => {
const source = ctx.createBufferSource();
source.buffer = audioBuffer;
source.loop = true;
source.connect( ctx.destination );
source.start( 0 );
source.stop( ctx.currentTime + audioBuffer.duration * inp.valueAsNumber );
};
btn.disabled = false;
})().catch( console.error );
此方法可提供无缝播放(如果文件无间隙)。
您可以将其包装为一个简单的函数:
<label> repeat<input id="inp" type="number" min="1" max="20" value="5"></label>
<button id="btn" disabled>start</button>