Javascript 有没有一种方法可以使用Web音频API比实时更快地采样音频?
我正在使用Web音频API&试图找到一种方法来导入mp3(因此这只在Chrome中),并在画布上生成它的波形。我可以实时完成这项工作,但我的目标是比实时更快地完成这项工作 我所能找到的所有例子都涉及到从分析仪对象读取频率数据,在连接到onaudioprocess事件的函数中:Javascript 有没有一种方法可以使用Web音频API比实时更快地采样音频?,javascript,html,webkit,web-audio-api,Javascript,Html,Webkit,Web Audio Api,我正在使用Web音频API&试图找到一种方法来导入mp3(因此这只在Chrome中),并在画布上生成它的波形。我可以实时完成这项工作,但我的目标是比实时更快地完成这项工作 我所能找到的所有例子都涉及到从分析仪对象读取频率数据,在连接到onaudioprocess事件的函数中: processor=context.createJavascriptNode(2048,1,1); processor.onaudioprocess=处理音频; ... 函数processAudio{ var FREKBY
processor=context.createJavascriptNode(2048,1,1);
processor.onaudioprocess=处理音频;
...
函数processAudio{
var FREKBYTEDATA=新UINT8阵列(分析仪频率BINCOUNT);
分析仪。获取频率数据(频率数据);
//计算幅值并渲染到画布
}
不过,似乎只有在播放声音时才会填充analyzer.frequencyBinCount
(缓冲区被填满的情况)
我想要的是能够以手动/编程方式尽可能快地遍历文件,以生成画布图像
到目前为止,我得到的是:
$(“#文件”)。关于('change',函数(e){
var FileList=e.target.files,
Reader=newfilereader();
var File=FileList[0];
Reader.onload=(函数(文件){
返回函数(e){
上下文.解码音频数据(如目标.结果,函数(缓冲区){
source.buffer=缓冲区;
源。连接(分析仪);
analyzer.connect(jsNode);
var freqData=newuint8array(buffer.getChannelData(0));
控制台dir(分析仪);
console.dir(jsNode);
jsNode.connect(context.destination);
//来源:注释(0);
});
};
})(文件);
Reader.readAsArrayBuffer(文件);
});
但是getChannelData()总是返回一个空的类型化数组
任何洞察都是值得赞赏的,即使事实证明它无法做到。我想我是互联网上唯一一个不想实时做事情的人
谢谢。Web Audio API有一个非常惊人的功能,它允许您通过音频上下文预处理整个文件,然后对结果进行处理:
var context = new webkitOfflineAudioContext();
var source = context.createBufferSource();
source.buffer = buffer;
source.connect(context.destination);
source.noteOn(0);
context.oncomplete = function(e) {
var audioBuffer = e.renderedBuffer;
};
context.startRendering();
因此,设置看起来与实时处理模式完全相同,只是设置了
oncomplete
回调和调用startRendering()
。您在e.redneredBuffer
中得到的是一个音频缓冲区
我使用以下代码使用OfflineAudioContext实现了这一点。这里的完整示例显示了如何使用它来计算线性啁啾的FFT幅度。一旦您有了将节点连接在一起的概念,就可以脱机使用它做任何事情
function fsin(freq, phase, t) {
return Math.sin(2 * Math.PI * freq * t + phase)
}
function linearChirp(startFreq, endFreq, duration, sampleRate) {
if (duration === undefined) {
duration = 1; // seconds
}
if (sampleRate === undefined) {
sampleRate = 44100; // per second
}
var numSamples = Math.floor(duration * sampleRate);
var chirp = new Array(numSamples);
var df = (endFreq - startFreq) / numSamples;
for (var i = 0; i < numSamples; i++) {
chirp[i] = fsin(startFreq + df * i, 0, i / sampleRate);
}
return chirp;
}
function AnalyzeWithFFT() {
var numChannels = 1; // mono
var duration = 1; // seconds
var sampleRate = 44100; // Any value in [22050, 96000] is allowed
var chirp = linearChirp(10000, 20000, duration, sampleRate);
var numSamples = chirp.length;
// Now we create the offline context to render this with.
var ctx = new OfflineAudioContext(numChannels, numSamples, sampleRate);
// Our example wires up an analyzer node in between source and destination.
// You may or may not want to do that, but if you can follow how things are
// connected, it will at least give you an idea of what is possible.
//
// This is what computes the spectrum (FFT) information for us.
var analyser = ctx.createAnalyser();
// There are abundant examples of how to get audio from a URL or the
// microphone. This one shows you how to create it programmatically (we'll
// use the chirp array above).
var source = ctx.createBufferSource();
var chirpBuffer = ctx.createBuffer(numChannels, numSamples, sampleRate);
var data = chirpBuffer.getChannelData(0); // first and only channel
for (var i = 0; i < numSamples; i++) {
data[i] = 128 + Math.floor(chirp[i] * 127); // quantize to [0,256)
}
source.buffer = chirpBuffer;
// Now we wire things up: source (data) -> analyser -> offline destination.
source.connect(analyser);
analyser.connect(ctx.destination);
// When the audio buffer has been processed, this will be called.
ctx.oncomplete = function(event) {
console.log("audio processed");
// To get the spectrum data (e.g., if you want to plot it), you use this.
var frequencyBins = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(frequencyBins);
console.log(frequencyBins);
// You can also get the result of any filtering or any other stage here:
console.log(event.renderedBuffer);
};
// Everything is now wired up - start the source so that it produces a
// signal, and tell the context to start rendering.
//
// oncomplete above will be called when it is done.
source.start();
ctx.startRendering();
}
功能fsin(频率、相位、t){
返回Math.sin(2*Math.PI*freq*t+相位)
}
函数linearChirp(startFreq、endFreq、duration、sampleRate){
如果(持续时间===未定义){
持续时间=1;//秒
}
if(sampleRate==未定义){
sampleRate=44100;//每秒
}
var numSamples=数学地板(持续时间*采样器);
var chirp=新阵列(numSamples);
var df=(endFreq-startFreq)/numSamples;
对于(var i=0;i分析器->离线目标。
源。连接(分析仪);
分析仪连接(ctx目的地);
//处理完音频缓冲区后,将调用它。
ctx.oncomplete=函数(事件){
控制台日志(“音频处理”);
//要获取光谱数据(例如,如果您想绘制光谱数据),请使用此选项。
var frequencyBins=新UINT8阵列(分析仪频率BinCount);
分析仪.GetByTefFrequencyData(频率箱);
控制台日志(频率箱);
//您还可以在此处获得任何筛选或任何其他阶段的结果:
console.log(event.renderedBuffer);
};
//现在一切都连接好了-启动源,使其产生一个
//发出信号,并告诉上下文开始渲染。
//
//完成后将调用上面的oncomplete。
source.start();
ctx.startRendering();
}
现在已经很晚了,我正在做其他事情,但这个答案听起来很有希望(基本上是因为这是我唯一得到的答案)。我一定会让你知道这是怎么回事。好吧,我已经玩了差不多一个小时了,我迷路了。你的代码和我的代码配合得怎么样?当你设置source.buffer=buffer时,buffer从哪里来?我能看到创建音频缓冲区的唯一地方是作为成功函数的参数定义context.decodeAudioData()