简体   繁体   English

AnalyserNode.getFloatFrequencyData() 返回负值

[英]AnalyserNode.getFloatFrequencyData() returns negative values

I'm trying to get the volume of a microphone input using the Web Audio API using AnalyserNode.getFloatFrequencyData() .我正在尝试使用 Web Audio API 使用 AnalyserNode.getFloatFrequencyData AnalyserNode.getFloatFrequencyData()获取麦克风输入的音量。

The spec states that "each item in the array represents the decibel value for a specific frequency" but it returns only negative values although they do look like they are reacting to the level of sound - a whistle will return a value of around -23 and silence around -80 (the values in the dataArray are also all negative, so I don't think it's to do with how I've added them together).规范声明“数组中的每个项目代表特定频率的分贝值”,但它只返回负值,尽管它们看起来确实对声音水平做出反应 - 哨子将返回大约 -23 和在 -80 左右静音(dataArray 中的值也都是负数,所以我认为这与我将它们加在一起的方式无关)。 The same code gives the values I'd expect (positive) with AnalyserNode.getByeFrequencyData() but the decibel values returned have been normalised between 0-255 so are more difficult to add together to determine the overall volume.相同的代码使用AnalyserNode.getByeFrequencyData()给出了我期望的值(正),但返回的分贝值已在 0-255 之间标准化,因此更难将它们加在一起以确定整体音量。

Why am I not getting the values I expect?为什么我没有得到我期望的值? And/or is this perhaps not a good way of getting the volume of the microphone input in the first place?和/或这可能不是首先获得麦克风输入音量的好方法吗?

function getVolume(analyser) {
  analyser.fftSize = 32; 
  let bufferLength = analyser.frequencyBinCount;
  let dataArray = new Float32Array(bufferLength);
  analyser.getFloatFrequencyData(dataArray);
  let totalAntilogAmplitude = 0;
  for (let i = 0; i < bufferLength; i++) {
    let thisAmp = dataArray[i]; // amplitude of current bin
      let thisAmpAntilog = Math.pow(10, (thisAmp / 10)) // antilog amplitude for adding
      totalAntilogAmplitude = totalAntilogAmplitude + thisAmpAntilog; 
  }
  let amplitude = 10 * Math.log10(totalAntilogAmplitude);
  return amplitude;
}

Your code looks correct.您的代码看起来正确。 But without an example, it's hard to tell if it's producing the values you expect.但是如果没有示例,很难判断它是否产生了您期望的值。 Also, since you're just computing (basically), the sum of all the values of the transform coefficients, you've just done aa more expensive version of summing the squares of the time domain signal.此外,由于您只是(基本上)计算变换系数的所有值的总和,因此您刚刚完成了对时域信号的平方求和的更昂贵的版本。

Another alternative would square the signal, filter it a bit to smooth out variations, and get the output value at various times.另一种选择是对信号进行平方,对其进行过滤以消除变化,并在不同时间获得 output 值。 Something like the following, where s is the node that has the signal you're interested in.如下所示,其中s是具有您感兴趣的信号的节点。

let g = new GainNode(context, {gain: 0});
s.connect(g);
s.connect(g.gain);
// Output of g is now the square of s

let f = new BiquadFilterNode(context, {frequency: 10});
// May want to adjust the frequency some to other value for your needs.
// I arbitrarily chose 10 Hz.
g.connect(f).connect(analyser)

// Now get the time-domain value from the analyser and just take the first 
// value from the signal.  This is the energy of the signal and represents 
// the volume.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM