从频谱功率电平恢复RMS和/或峰值(FFT输出)

时间:2013-11-02 16:34:24

标签: javascript math audio fft web-audio

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

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

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

2 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:1)

是的,有可能从FFT中找到RMS值,你需要确保AnalyserNote不对信号应用任何Window(hanning,blackman,kaiser等)!

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

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