我一直在玩Web Audio API,我正在尝试加载一首歌曲的多个部分,并将其附加到一个新的ArrayBuffer,然后使用该ArrayBuffer播放所有的部分作为一首歌曲.在下面的例子中,我使用相同的歌曲数据(这是一个小循环),而不是一首歌曲的不同部分.
问题是它仍然播放一次而不是两次,我不知道为什么.
function init() { /** * Appends two ArrayBuffers into a new one. * * @param {ArrayBuffer} buffer1 The first buffer. * @param {ArrayBuffer} buffer2 The second buffer. */ function appendBuffer(buffer1,buffer2) { var tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength); tmp.set( new Uint8Array(buffer1),0); tmp.set( new Uint8Array(buffer2),buffer1.byteLength); return tmp; } /** * Loads a song * * @param {String} url The url of the song. */ function loadSongWebAudioAPI(url) { var request = new XMLHttpRequest(); var context = new webkitAudioContext(); request.open('GET',url,true); request.responseType = 'arraybuffer'; /** * Appends two ArrayBuffers into a new one. * * @param {ArrayBuffer} data The ArrayBuffer that was loaded. */ function play(data) { // Concatenate the two buffers into one. var a = appendBuffer(data,data); var buffer = a.buffer; var audioSource = context.createBufferSource(); audioSource.connect(context.destination); //decode the loaded data context.decodeAudioData(buffer,function(buf) { console.log('The buffer',buf); audioSource.buffer = buf; audioSource.noteOn(0); audioSource.playbackRate.value = 1; }); }; // When the song is loaded asynchronously try to play it. request.onload = function() { play(request.response); } request.send(); } loadSongWebAudioAPI('http://localhost:8282/loop.mp3'); } window.addEventListener('load',init,false);
解决方法
您的代码中的问题是您正在将MP3文件的另一个副本复制并附加到本身的末尾.该副本被解码器有效地忽略 – 它不是原始缓冲区数据,它只是文件流中的随机虚假垃圾,完全完整的MP3文件.
您需要做的是首先将音频数据解码为AudioBuffer,然后将音频缓冲区附加到一个新的AudioBuffer中.这需要对您的代码进行一些重组.
你想做的是这样的:
var context = new webkitAudioContext(); function init() { /** * Appends two ArrayBuffers into a new one. * * @param {ArrayBuffer} buffer1 The first buffer. * @param {ArrayBuffer} buffer2 The second buffer. */ function appendBuffer(buffer1,buffer2) { var numberOfChannels = Math.min( buffer1.numberOfChannels,buffer2.numberOfChannels ); var tmp = context.createBuffer( numberOfChannels,(buffer1.length + buffer2.length),buffer1.sampleRate ); for (var i=0; i<numberOfChannels; i++) { var channel = tmp.getChannelData(i); channel.set( buffer1.getChannelData(i),0); channel.set( buffer2.getChannelData(i),buffer1.length); } return tmp; } /** * Loads a song * * @param {String} url The url of the song. */ function loadSongWebAudioAPI(url) { var request = new XMLHttpRequest(); request.open('GET',true); request.responseType = 'arraybuffer'; /** * Appends two ArrayBuffers into a new one. * * @param {ArrayBuffer} data The ArrayBuffer that was loaded. */ function play(data) { //decode the loaded data context.decodeAudioData(data,function(buf) { var audioSource = context.createBufferSource(); audioSource.connect(context.destination); // Concatenate the two buffers into one. audioSource.buffer = appendBuffer(buf,buf); audioSource.noteOn(0); audioSource.playbackRate.value = 1; }); }; // When the song is loaded asynchronously try to play it. request.onload = function() { play(request.response); } request.send(); } loadSongWebAudioAPI('loop.mp3'); } window.addEventListener('load',false);
有一个轻微的播放差距 – 这是因为您的声音样本开始时有近50ms的沉默,而不是由于循环的问题.
希望这可以帮助!