AnalyserNode.getFloatFrequencyData始终返回-Infinity

时间:2018-10-28 09:47:55

标签: javascript web-audio web-audio-api

好的,所以我试图确定用户浏览器记录的音频文件样本的强度(以dB为单位)。

我已经能够记录下来并通过HTML元素播放它。 但是,当我尝试将此元素用作源并将其连接到AnalyserNode时,AnalyserNode.getFloatFrequencyData总是返回一个充满-Infinity的数组,getByteFrequencyData总是返回零,getByteTimeDomainData则充满128。

这是我的代码:

var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var source;

var analyser = audioCtx.createAnalyser();

var bufferLength = analyser.frequencyBinCount;
var data = new Float32Array(bufferLength);

mediaRecorder.onstop = function(e) {
  var blob = new Blob(chunks, { 'type' : 'audio/ogg; codecs=opus' });

  chunks = [];
  var audioURL = window.URL.createObjectURL(blob);
  // audio is an HTML audio element
  audio.src = audioURL;

  audio.addEventListener("canplaythrough", function() {
      source = audioCtx.createMediaElementSource(audio);

      source.connect(analyser);
      analyser.connect(audioCtx.destination);

      analyser.getFloatFrequencyData(data);
      console.log(data);
  });
}

有人知道为什么AnalyserNode表现得像源是空/静音吗?我还尝试在录制时将流作为源,结果相同。

3 个答案:

答案 0 :(得分:0)

源文件是否来自其他域?那将在createMediaElementSource中失败。

答案 1 :(得分:0)

您需要获取音频文件并解码音频缓冲区。 音频源的URL也必须位于相同的域上,或者也具有正确的CORS标头(如Anthony所述)。

注意:在下面的示例中,将<FILE-URI>替换为文件的路径。

var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var source;
var analyser = audioCtx.createAnalyser();
var button = document.querySelector('button');
var freqs;
var times;


button.addEventListener('click', (e) => {
  fetch("<FILE-URI>", {
    headers: new Headers({
      "Content-Type" : "audio/mpeg"
    })
  }).then(function(response){
    return response.arrayBuffer()
  }).then((ab) => {
    audioCtx.decodeAudioData(ab, (buffer) => {
      source = audioCtx.createBufferSource();
      source.connect(audioCtx.destination)
      source.connect(analyser);
      source.buffer = buffer;
      source.start(0);
      viewBufferData();
    });
  });
});

// Watch the changes in the audio buffer
function viewBufferData() {
  setInterval(function(){
    freqs = new Uint8Array(analyser.frequencyBinCount);
    times = new Uint8Array(analyser.frequencyBinCount);
    analyser.smoothingTimeConstant = 0.8;
    analyser.fftSize = 2048;
    analyser.getByteFrequencyData(freqs);
    analyser.getByteTimeDomainData(times);
    console.log(freqs)
    console.log(times)
  }, 1000)
}

答案 2 :(得分:0)

由于您的一些代码片段,我遇到了同样的问题,使它可以正常工作(下面的代码是打字稿,撰写本文时在浏览器中不起作用):

audioCtx.decodeAudioData(this.result as ArrayBuffer).then(function (buffer: AudioBuffer) { 
      soundSource = audioCtx.createBufferSource();
      soundSource.buffer = buffer;
      //soundSource.connect(audioCtx.destination); //I do not need to play the sound
      soundSource.connect(analyser);
      soundSource.start(0);

      setInterval(() => {
         calc(); //In here, I will get the analyzed data with analyser.getFloatFrequencyData 
      }, 300); //This can be changed to 0.
      // The interval helps with making sure the buffer has the data

一些解释(关于Web Audio API,我仍然是一个初学者,所以我的解释可能是错误的或不完整的): 分析人员需要能够分析声音文件的特定部分。在这种情况下,我创建一个AudioBufferSoundNode,其中包含从解码音频数据中获得的缓冲区。我将缓冲区提供给源,最终可以将其复制到分析器中。但是,如果没有时间间隔回调,缓冲区似乎永远不会准备好,并且分析的数据在数组的每个索引处都包含-Inifinity(我认为是没有任何声音,因为没有声音可读取)。这就是为什么存在间隔的原因。每300毫秒分析一次数据。

希望这对某人有帮助!