我对整个音频处理领域都很陌生,我想知道如何从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);
}
返回:
这是对的吗?如何将这些数据更有用?
答案 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。 您应该补偿这种影响(可能在平均频率之前)以获得“更好”的显示效果。