NAudio频段强度

Mar*_*mić 7 c# algorithm fft naudio

我有一个使用NAudio的音频播放器,我想为每个频段显示实时强度.

我为每个1024个样本块触发了一个事件:

public void Update(Complex[] fftResults)
{
   // ??
}
Run Code Online (Sandbox Code Playgroud)

我想要的是一组数字,表示每个频段的强度.让我们说我想将窗口划分为16个波段.

例如,当有更多低音频率时,它可能如下所示:

????????????????
????????????????
????????????????
????????????????
????????????????
????????????????
Run Code Online (Sandbox Code Playgroud)

如果可以使用该数据,我应该将什么放入该事件处理程序?

来自(Complex [])的数据已经通过FFT进行了转换.这是一个立体声流.

第一次尝试:

    double[] bandIntensity = new double[16] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

    public void Update(Complex[] fftResults)
    {
        // using half fftResults because the others are just mirrored
        int band = 0;
        for (int n = 0; n < fftResults.Length/2; n++)
        {
            band = (int)((double)n / (fftResults.Length / 2) * bandIntensity.Length);
            bandIntensity[band] += Math.Sqrt(fftResults[n].X * fftResults[n].X + fftResults[n].Y * fftResults[n].Y);
            bandIntensity[band] /= 2;
        }
    }
Run Code Online (Sandbox Code Playgroud)

以上是做了一些事情,但我认为前两个乐队太多了,我正在演奏没有那么多低音的夏奇拉.

谢谢!

Pau*_*l R 8

您可能希望在此处解决两个不同的问题:

(1)窗口功能

您需要在FFT之前对数据应用窗口函数,否则会出现频谱泄漏,从而导致光谱非常模糊.频谱泄漏的一个令人不快的副作用是,如果您有任何类型的重要DC(0 Hz)分量,那么这将导致您在条形图上看到的那种1/f形状.

(2)记录幅度/频率轴

人类听力在强度和频率轴上基本上都是对数的.不仅如此,语音和音乐往往在频谱的低频部分拥有更多的能量.为了获得更加令人愉悦和有意义的强度与频率的显示,我们通常使幅度轴和频率轴都成对数.在幅度轴的情况下,通常通过绘制dB re full scale来表示,即

magnitude_dB = 10 * log10(magnitude);
Run Code Online (Sandbox Code Playgroud)

在频率轴的情况下,您可能希望将频段分组为频段,每个频段可能是一个八度音程(2:1频率范围),或者更常见的是更高分辨率,第三个八度音阶.所以,如果您只想要10个"条形",那么您可以使用以下八度音阶:

   25 -    50 Hz
   50 -   100 Hz
  100 -   200 Hz
  200 -   400 Hz
  400 -   800 Hz
  800 -  1600 Hz
 1600 -  3200 Hz
 3200 -  6400 Hz
 6400 - 12800 Hz
12800 - 20000 Hz
Run Code Online (Sandbox Code Playgroud)

(假设您的采样率为44.1 kHz,音频输入硬件的上限为20 kHz).

请注意,虽然对于这种应用来说,具有幅度(dB)强度标度几乎是必需的,但是对数频率轴不那么重要,因此您现在可以尝试使用现有的线性分级,并看看您从应用中获得的效果时域中的窗口函数(假设您还没有)并将幅度比例转换为dB.