Javascript 使用chrome的OfflineAudioContext FFT分析
我正在尝试构建一个波形生成器,它可以获取音频文件的振幅值,并以javascript的形式尽可能快(比实时速度快)地将它们显示在画布上。因此,我使用OfflineAudioContext/webkitOfflineAudioContext,加载文件并开始分析。 波形是用来填充一个宽画布的 我分析处理器中的缓冲区。onaudioprocess函数。(我想这就是它的工作方式?) 它在firefox中运行良好,但我在chrome中遇到了一个问题:它似乎“跳过”了很多分析,以尽快完成它的工作,并且只返回几个坐标(比如16) 以下是JSFIDLE:Javascript 使用chrome的OfflineAudioContext FFT分析,javascript,html,google-chrome,chromium,web-audio-api,Javascript,Html,Google Chrome,Chromium,Web Audio Api,我正在尝试构建一个波形生成器,它可以获取音频文件的振幅值,并以javascript的形式尽可能快(比实时速度快)地将它们显示在画布上。因此,我使用OfflineAudioContext/webkitOfflineAudioContext,加载文件并开始分析。 波形是用来填充一个宽画布的 我分析处理器中的缓冲区。onaudioprocess函数。(我想这就是它的工作方式?) 它在firefox中运行良好,但我在chrome中遇到了一个问题:它似乎“跳过”了很多分析,以尽快完成它的工作,并且只返回几
//创建音频上下文
如果(!window.OfflineAudioContext){
如果(!window.webkitOfflineAudioContext){
$(“#输出”).append('failed:no audiocontext found,change browser');
}
window.OfflineAudioContext=window.webkitOfflineAudioContext;
}
//var context=新的AudioContext();
变量长度=15241583;
var-samplerate=44100;
var fftSamples=2048;
var波宽=1920;
变量上下文=新的OfflineAudioContext(1,长度,samplerate);
var源;
无功功率分配器;
var分析仪;
var处理器;
var i=0;
var平均值;
var-max;
var coord;
processor=context.createScriptProcessor(fftSamples,1,1);
processor.connect(context.destination);
Analyzer=context.createAnalyzer();
Analyzer.smoothingTimeConstant=0;
Analyzer.fftSize=fftSamples;
source=context.createBufferSource();
splitter=context.createChannelSplitter();
源。连接(拆分器);
分离器连接(分析仪,0,0);
分析仪。连接(处理器);
context.oncomplete=函数(){
$(“#输出”)。追加(“
完成”);
}
var request=new XMLHttpRequest();
request.open('GET',”http://www.mindthepressure.org/bounce.ogg“,对);
request.responseType='arraybuffer';
request.onload=函数(){
$(“#输出”).append('loaded!');
上下文.解码音频数据(请求.响应,函数(缓冲区){
$(“#输出”).append('starting analysis
');
processor.onaudioprocess=函数(e){
var数据=新UINT8阵列(分析仪频率BINCOUNT);
分析仪。GetByTefFrequencyData(数据);
average=getAverageVolume(数据);
max=Math.max.apply(数学,数据);
坐标=数学最小值(平均值*2255);
坐标=数学圆((最大+坐标)/2);
ctx.fillStyle=渐变;
ctx.fillRect(i,255 coord,1255);
console.log(i+'->'+coord);
i++;
}
source.buffer=缓冲区;
source.start(0);
startRendering();
},onError);
}
request.send();
函数onError(e){
$('#output').append('错误,检查控制台');
控制台日志(e);
}
函数getAverageVolume(数组){
var值=0;
var平均值;
var length=array.length;
对于(var k=0;k
(这里是另一个版本,它强制波形适应1920像素宽,并为感兴趣的人生成波形数据:)
我真的不明白,chrome怎么不处理音频文件的每个部分
谢谢你的帮助 Chrome在脱机模式下的脚本处理器中有一个bug。也可以用Canary 34确认这一点。如果当前呼叫无法在给定的时间内完成,这似乎是一种暴力行为,但这只是一种猜测。。如果您实时运行它(正常上下文),它的行为如何?(将渐变填充样式移动到全局范围会产生更好的结果)它在实时上下文中工作良好。谢谢你的小把戏!我在safari中也遇到同样的问题,我想这是一个webkit/blink问题。这似乎得到了和的证实:主音频线程不会等待处理器计算其任务,然后再继续下一个样本帧块。。。很遗憾,我还没有找到一份确认的bug报告。谢谢你的回答。你有没有找到关于这个的错误报告?在ChromeV36中渲染振荡器时仍然存在问题。在最新的firefox v30中工作得非常完美。Chromium中的Bug报告,我真的需要它工作,我想知道它什么时候会被解决:janesconference:我怀疑这会得到解决,因为目标是用音频工作程序取代脚本处理器(默认情况下可以脱机工作)@cwilso:音频工作程序会非常酷,正如您在这里指出的那样,它们将消除令人讨厌的缓冲区延迟操作系统脚本处理器:但这将阻止许多可能的应用程序,直到它们实现为止,可能以年而不是月为单位。考虑到Firefox的实现是有效的,这是不方便的。根本不想批评,只是(有点痛苦的)考虑。
// create the audio context
if (! window.OfflineAudioContext) {
if (! window.webkitOfflineAudioContext) {
$('#output').append('failed : no audiocontext found, change browser');
}
window.OfflineAudioContext = window.webkitOfflineAudioContext;
}
//var context = new AudioContext();
var length = 15241583;
var samplerate = 44100;
var fftSamples = 2048;
var waveformWidth = 1920;
var context = new OfflineAudioContext(1,length,samplerate);
var source;
var splitter;
var analyser;
var processor;
var i=0;
var average;
var max;
var coord;
processor = context.createScriptProcessor(fftSamples, 1, 1);
processor.connect(context.destination);
analyser = context.createAnalyser();
analyser.smoothingTimeConstant = 0;
analyser.fftSize = fftSamples;
source = context.createBufferSource();
splitter = context.createChannelSplitter();
source.connect(splitter);
splitter.connect(analyser,0,0);
analyser.connect(processor);
context.oncomplete = function(){
$('#output').append('<br />complete');
}
var request = new XMLHttpRequest();
request.open('GET', "http://www.mindthepressure.org/bounce.ogg", true);
request.responseType = 'arraybuffer';
request.onload = function(){
$('#output').append('loaded ! ');
context.decodeAudioData(request.response, function(buffer) {
$('#output').append('starting analysis<br />');
processor.onaudioprocess = function(e){
var data = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(data);
average = getAverageVolume(data);
max = Math.max.apply(Math, data);
coord = Math.min(average*2,255);
coord = Math.round((max+coord)/2);
ctx.fillStyle=gradient;
ctx.fillRect(i,255-coord,1,255);
console.log(i+' -> '+coord);
i++;
}
source.buffer = buffer;
source.start(0);
context.startRendering();
}, onError);
}
request.send();
function onError(e) {
$('#output').append('error, check the console');
console.log(e);
}
function getAverageVolume(array) {
var values = 0;
var average;
var length = array.length;
for (var k = 0; k < length; k++) {
values += array[k];
}
average = values / length;
return average;
}