我喜欢从任意数学函数 f(x) 生成声音。现在我使用 AudioBufferSource 来实现此目的,并且我为下一个缓冲区创建并播放另一个源,依此类推。问题是缓冲器之间的裂纹。这是我的示例代码:
function init() {
var contextClass = (AudioContext || webkitAudioContext
|| mozAudioContext || oAudioContext || msAudioContext);
if (contextClass) {
// Web Audio API is available.
context = new contextClass();
return true;
} else {
return false;
}
}
// arbitary mathematical function (not just sin)
function mySoundFunction(i, j, k) {
return j*Math.sin(i/10);
}
function createBufferSource(j) {
var length = 8092;
var audioBuffer = context.createBuffer(1, length, 44500);
var data = audioBuffer.getChannelData(0);
for (var i = 0; i < length; i++) {
data[i] = mySoundFunction(i, j, 5);
}
var source = context.createBufferSource();
source.buffer = audioBuffer;
source.connect(context.destination);
source.onended = function ended(obj) {
createBufferSource(j);
}
source.start(0);
}
if (init()) {
console.log("init was successful");
}
createBufferSource(0.1);
由于用户可以在播放声音时更改数学函数,因此缓冲区大小必须保持较小,并且由于延迟,预缓冲并不是一个真正的选择。 ScriptProcessor 可能是一个替代方案,但我猜它的性能太昂贵了。由于函数可以是任何东西,OscillatorNode 也不好。 那么问题来了,如何消除两个缓冲区之间的裂纹呢? 谢谢
我尝试使用 ScriptProcessor 但它仍然有差距
function feed() {
var a = j === 0 ? 5000: 6000;
for (var i = 0; i < 2048; i++) {
audata[i] = Math.sin(a*k);
k++;
}
j = 1-j ;
}
function createProcessor() {
processor = context.createScriptProcessor(2048, 0, 1);
processor.onaudioprocess = function(e) {;
var L = e.outputBuffer.getChannelData(0);
L.set(audata);
feed();
}
processor.connect(context.destination);
running=true;
}
if (init()) {
console.log("init was successful");
}
audata = new Float32Array(2048);
k=0;
j=1;
feed();
createProcessor();
我错过了什么?谢谢
最佳答案
你不想在这里使用onend。这会留下一个间隙,因为它是在音频线程中的音频播放完毕后触发的,因此存在很大的间隙。
您今天可能想使用 ScriptProcessor,将来可能想使用 AudioWorkers。
关于web-audio-api - 使用 Web Audio Api 连续播放小声音缓冲区序列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30597980/