Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 有没有一种方法可以使用Web音频API比实时更快地采样音频?_Javascript_Html_Webkit_Web Audio Api - Fatal编程技术网

Javascript 有没有一种方法可以使用Web音频API比实时更快地采样音频?

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

我正在使用Web音频API&试图找到一种方法来导入mp3(因此这只在Chrome中),并在画布上生成它的波形。我可以实时完成这项工作,但我的目标是比实时更快地完成这项工作

我所能找到的所有例子都涉及到从分析仪对象读取频率数据,在连接到onaudioprocess事件的函数中:

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()