1

WebAudio API 允许我创建一个 AnalyserNode,它可以让我访问 FFT 计算的一组音频样本的频谱(在无符号字节数组或浮点数组-11)。我希望我可以使用这些值来计算同一组样本的总功率 (RMS)。

我认为这并不像取 32 个窗口值那样简单,将它们相加并除以 32。(0dB 的正弦波只会填满一个窗口,而一些相邻的窗口会略微亮起,而白噪声在0dB 会填满所有窗口。)是否可以从 FFT/DFT 输出中计算出 RMS 值?

我想这样做的原因是我需要构建一个高效的 RMS 仪表。虽然我可以访问原始样本,但处理它们甚至找到每个缓冲区的峰值都是太多的开销。浏览器在本机代码中运行其 FFT,并且比尝试在 JavaScript 中进行所有这些计算要高效得多。如果我可以从 32 个 FFT 窗口计算 RMS,那效率会更高。

4

2 回答 2

3

对于它的价值——我有一个应用程序计算 RMS 在一个requestAnimationFrame循环中从 12 到 20 个轨道的任何地方,它使用getByteTimeDomainData()并且速度非常快。在这些计算和<canvas>每 16.7 毫秒以米为单位绘制结果之间,我在 Chrome 和 Firefox 中始终获得 60fps。

现代 JS 引擎非常擅长快速合理地计算数学。

于 2013-11-04T15:16:03.770 回答
1

是的,可以从 FFT 中找到 RMS 值,您需要确保 AnalyserNote 不对信号应用任何窗口(汉宁、布莱克曼、凯撒等)!

获得相同结果的两种简单方法:

RMS1 = 绝对 FFOutput 平方和除以样本长度

RMS2 = 绝对 FFOutput 之和除以样本长度再除以样本长度

我在这里测试了我在 450 赫兹创建了一个正弦波 db = 50

dbimput = 50;
t  = [ 0 : 1 : 10000];         
f  = 450;                      
Fs = 44100;                    
data =10^(dbimput/20)*sin(2*pi*f/Fs*t)';        


FFTDATA = fft(data);

rms1 = sum(abs(FFTDATA /length(data)).^2)

rms2 = sum(abs(FFTDATA .^2) / length(data)) / (length(data) )

dblevel1 = 20 * log10(sqrt(rms1))

dblevel2 = 20 * log10(sqrt(rms2))

结果是:

rms1 =  4.9976e+04
rms2 =  4.9976e+04
dblevel1 =  46.988
dblevel2 =  46.988
于 2013-11-02T21:47:53.403 回答