【问题标题】:Recovering RMS and/or Peak from Spectrum Power Levels (FFT output)从频谱功率电平恢复 RMS 和/或峰值(FFT 输出)
【发布时间】:2013-11-13 16:21:45
【问题描述】:

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

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

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

【问题讨论】:

    标签: javascript math audio fft web-audio-api


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      是的,可以从 FFT 中找到 RMS 值,您需要确保 AnalyserNote 不会在信号上应用任何窗口(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
      

      【讨论】:

      猜你喜欢
      • 2019-02-14
      • 2014-04-24
      • 1970-01-01
      • 2017-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多