Web Audio API有一个分析器节点,它允许您获取正在使用的音频的FFT数据,并具有获取数据的字节和浮点数。字节版本有点意义,返回看起来像标准化(取决于最小和最大分贝值)的强度频谱,其中0不是特定频率仓的音频分量而255是最大值。
但是我想要比8位更多的细节,但使用float版本会产生奇怪的结果。
freqData = new Float32Array(analyser.frequencyBinCount);
analyser.getFloatFrequencyData(freqData);
这给了我介于-891.048828125和0. -891之间的值对应于静音,因此它在某种程度上是最小值,而我猜0是等于最大值。
发生了什么事?为什么-891.048828125显着?为什么一个大的负面是沉默,零是最大的?我使用错误的FloatArray还是存在配置错误? Float64给出0值。
答案 0 :(得分:31)
由于似乎没有关于数据实际代表的文档,我查看了webkit的相关源代码:RealtimeAnalyser.cpp
简短回答:从Float32Array的每个值中减去analyser.minDecibels得到正数并乘以(analyser.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,这在analyzer node中公开:
//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,它也无法访问复杂的表示,只能访问它的大小。
答案 1 :(得分:2)
使用Float32Array是正确的。我找到了一个关于使用音频数据API的有趣教程,虽然它与Web音频API不同,但我给了我一些有用的见解,告诉我你要做什么here。我快速查看了为什么数字是负数,并没有注意到任何明显的数字,但我想知道这些数字是否可能是分贝dB,通常以负数给出,零是峰值。该理论唯一的问题是-891对于dB来说似乎是一个非常小的数字。
答案 2 :(得分:2)
纠正上一个答案和评论中的两个点 - 数字以分贝为单位,因此0表示最大值,-infinity表示最小值(绝对静音)。 -891.0 ...我相信,只是一个浮点转换奇怪。