sam*_*rad 4 javascript merge arraybuffer audiobuffer web-audio-api
我需要分层循环.wav轨道,最终我将需要能够打开和关闭并保持同步。
首先,我加载了曲目,并停止BufferLoader了将加载的内容arraybuffer变成的AudioBuffer(因此false)
function loadTracks(data) {
for (var i = 0; i < data.length; i++) {
trackUrls.push(data[i]['url']);
};
bufferLoader = new BufferLoader(context, trackUrls, finishedLoading);
bufferLoader.load(false);
return loaderDefered.promise;
}
Run Code Online (Sandbox Code Playgroud)
当您单击屏幕上的按钮时,它将调用startStop()。
function startStop(index, name, isPlaying) {
if(!activeBuffer) {
activeBuffer = bufferList[index];
}else{
activeBuffer = appendBuffer(activeBuffer, bufferList[index]);
}
context.decodeAudioData(activeBuffer, function(buffer){
audioBuffer = buffer;
play();
})
function play() {
var scheduledTime = 0.015;
try {
audioSource.stop(scheduledTime);
} catch (e) {}
audioSource = context.createBufferSource();
audioSource.buffer = audioBuffer;
audioSource.loop = true;
audioSource.connect(context.destination);
var currentTime = context.currentTime + 0.010 || 0;
audioSource.start(scheduledTime - 0.005, currentTime, audioBuffer.duration - currentTime);
audioSource.playbackRate.value = 1;
}
Run Code Online (Sandbox Code Playgroud)
我在这个github上找到的大多数代码。在演示中,您可以听到他正在对AudioBuffers进行分层。
我已经在主机上尝试过相同的方法。
不管这些argularJS东西,Web Audio东西都发生service.js在:
/js/angular/service.js
Run Code Online (Sandbox Code Playgroud)
如果您打开控制台并单击按钮,您会看到activeBuffer.byteLength(类型ArrayBuffer)正在增加,但是即使在通过该context.decodeAudioData方法解码之后,它仍只会播放您单击的第一个声音,而不是合并的声音AudioBuffer
我不确定我是否完全了解您的情况-您不希望它们同时播放吗?(即,低音在鼓的顶部分层)。
每当您点击该文件的按钮时,您当前的代码就会尝试连接一个其他音频文件。您不能只连接音频文件(以ENCODED格式),然后通过解码运行它-解码音频数据方法将解码数组缓冲区中的第一个完整声音,然后停止(因为它已经完成了声音解码)。
您应该做的是更改逻辑,以将生成的AudioBuffers中的缓冲区数据连接起来(请参见下文)。即使这种逻辑也不完全是您应该做的-这仍然会缓存编码的音频文件,并在您每次按下按钮时进行解码。相反,您应该缓存解码后的音频缓冲区,然后将其串联起来。
function startStop(index, name, isPlaying) {
// Note we're decoding just the new sound
context.decodeAudioData( bufferList[index], function(buffer){
// We have a decoded buffer - now we need to concatenate it
audioBuffer = buffer;
if(!audioBuffer) {
audioBuffer = buffer;
}else{
audioBuffer = concatenateAudioBuffers(audioBuffer, buffer);
}
play();
})
}
function concatenateAudioBuffers(buffer1, buffer2) {
if (!buffer1 || !buffer2) {
console.log("no buffers!");
return null;
}
if (buffer1.numberOfChannels != buffer2.numberOfChannels) {
console.log("number of channels is not the same!");
return null;
}
if (buffer1.sampleRate != buffer2.sampleRate) {
console.log("sample rates don't match!");
return null;
}
var tmp = context.createBuffer(buffer1.numberOfChannels, buffer1.length + buffer2.length, buffer1.sampleRate);
for (var i=0; i<tmp.numberOfChannels; i++) {
var data = tmp.getChannelData(i);
data.set(buffer1.getChannelData(i));
data.set(buffer2.getChannelData(i),buffer1.length);
}
return tmp;
};
Run Code Online (Sandbox Code Playgroud)