26

Web Audio API 有一个分析器节点,它允许您获取正在使用的音频的 FFT 数据,并具有获取数据的字节和浮点方式。字节版本有点意义,返回看起来像归一化(取决于最小和最大分贝值)的强度谱,其中 0 不是特定频率仓的音频分量,而 255 是最大值。

但是我想要比 8 位更多的细节,但是使用浮动版本会产生奇怪的结果。

freqData = new Float32Array(analyser.frequencyBinCount);
analyser.getFloatFrequencyData(freqData);

这给了我介于 -891.048828125 和 0 之间的值。-891 显示对应于静音,所以它在某种程度上是最小值,而我猜测 0 等于最大值。

这是怎么回事?为什么 -891.048828125 很重要?为什么一个大的负数是沉默而零是最大值?我使用了错误的 FloatArray 还是配置错误?Float64 给出 0 值。

4

3 回答 3

34

由于关于数据实际代表什么的文档似乎为零,我查看了 webkit 的相关源代码:RealtimeAnalyser.cpp

简短的回答:从 Float32Array 的每个值中减去 analyser.minDecibels 以获得正数并乘以 (analyzer.maxDecibels - analyser.minDecibels) 以获得与 getByteFrequencyData 类似的表示,只是分辨率更高。

长答案

getByteFrequencyData 和 getFloatFrequencyData 都以分贝为单位提供量级。它只是缩放不同,对于 getByteFrequencyData 减去 minDecibels 常数:

webkit中getByteFrequencyData的相关代码:

const double rangeScaleFactor = m_maxDecibels == m_minDecibels ? 1 : 1 / (m_maxDecibels - m_minDecibels);
float linearValue = source[i];
double dbMag = !linearValue ? minDecibels : AudioUtilities::linearToDecibels(linearValue);

// The range m_minDecibels to m_maxDecibels will be scaled to byte values from 0 to UCHAR_MAX.
double scaledValue = UCHAR_MAX * (dbMag - minDecibels) * rangeScaleFactor;

webkit中getFloatFrequencyData的相关代码:

float linearValue = source[i];
double dbMag = !linearValue ? minDecibels : AudioUtilities::linearToDecibels(linearValue);
destination[i] = float(dbMag);

因此,要获得正值,您可以简单地自己减去 minDecibels,它在分析器节点中公开:

 //The minimum power value in the scaling range for the FFT analysis data for conversion to unsigned byte values.
 attribute double minDecibels;

另一个细节是,默认情况下,分析器节点会进行时间平滑,可以通过将 SmoothingTimeConstant 设置为零来禁用它。

webkit 中的默认值是:

const double RealtimeAnalyser::DefaultSmoothingTimeConstant  = 0.8;
const double RealtimeAnalyser::DefaultMinDecibels = -100;
const double RealtimeAnalyser::DefaultMaxDecibels = -30;

可悲的是,即使分析器节点计算了一个复杂的 fft,它也不能访问复杂的表示,只是它的大小。

于 2013-02-26T17:35:14.760 回答
2

您使用 Float32Array 是正确的。我发现了一个关于使用音频数据 API 的有趣教程,虽然它与 Web 音频 API 不同,但它给了我一些有用的见解,让我了解你在这里尝试做什么。我快速查看了为什么这些数字是负数,并没有注意到任何明显的问题,但我想知道这些数字是否可能以分贝dB为单位,通常以负数给出,而零是峰值。该理论的唯一问题是 -891 对于 dB 来说似乎是一个非常小的数字。

于 2013-01-05T07:23:34.847 回答
2

纠正上一个答案和评论中的两点 - 数字以分贝为单位,所以 0 是最大值,-infinity 是最小值(绝对静音)。-891.0 ... 我相信,只是一个浮点转换奇怪。

于 2013-01-05T20:52:24.207 回答