如何从FFT获得Bass,Mid,Treble数据

时间:2015-01-28 02:10:23

标签: c# fft naudio

我对整个音频处理领域都很陌生,我想知道如何从FFT输出中提取低音,中音和高音。我目前正在使用它获取数据:https://stackoverflow.com/a/20414331/2714577,它使用的是Naudio。

但是我使用了1024的强度(要求速度)。我试图以0-255这样的格式获取这3个部分用于颜色目的。

我目前有这个:

    double[] data = new double[512];

    void FftCalculated(object sender, FftEventArgs e)
    {

        for (int j = 0; j < e.Result.Length / 2; j++)
        {
            double magnitude = Math.Sqrt(e.Result[j].X * e.Result[j].X + e.Result[j].Y * e.Result[j].Y);
            double dbValue = 20 * Math.Log10(magnitude);

            data[j] = dbValue;
        }

        double d = 0;

        for (int i = 20; i < 89; i++)
        {

            d += data[i];
        }

        double m = 0;

        for (int i = 150; i < 255; i++)
        {

            m += data[i];
        }

        double t = 0;

        for (int i = 300; i < 512; i++)
        {

            t += data[i];
        }

        Debug.Message(""+d+" |||| "+m+" |||| "+t);
    }

返回:

enter image description here

这是对的吗?如何将这些数据更有用?

2 个答案:

答案 0 :(得分:2)

你从傅立叶变换中得到的系数可以是正数或负数 - 你感兴趣的是数量级(即每个频率的数量),所以你需要取你的绝对值总和。

另外,我建议规范化 - 在总结结束时这样做:

double total = data.Sum(x => Math.Abs(x));
d /= total;
m /= total;
t /= total;

这样,您的号码将被限制在[0-1]范围内,如果声音更安静,您将获得相同的信息(除非您不想这样)。实际上,范围将略小于此范围,因为每个总和涵盖较小的个别范围。所以你可能希望用最大的一个来扩展它们:

double largest = Math.Max(d, m, t);
d /= largest;
m /= largest;
t /= largest;

现在每个的范围应该在0和1之间。然后可以乘以255或256,并根据需要截断小数。

最后一步的缺点是如果值全部为零(因为输入全部为零),那么您将除以零。哎呀!此时你需要确切地决定你想要什么..如果你没有做这个缩放,那么一个完全高音的声音(根据你上面的细分)将有(0,0,1)for(d ,公吨)。但是对于(d,m,t),三者的均匀混合的声音将是(0.3333,0.3333,0.3333)。并且完全安静的声音将是(0,0,0)。如果这不是你想要的,那么你需要在我能够帮助你之前准确定义你想要的东西。

答案 1 :(得分:2)

您的dbValue已经是一个非常好的数字,相对于1.0而言,以分贝为单位测量,变为0.0 dB

你应该平均而不是个人(各种各样的dB值)。

然后将约-80db .. 0.0dB的dB范围映射到您的颜色范围。

另请注意:演讲和音乐往往具有平均粉红噪声频谱。这意味着低频往往比高频具有更高的dB。 您应该补偿这种影响(可能在平均频率之前)以获得“更好”的显示效果。