FFT结果C#的功率谱密度



我有一个Complex[](来自CSCORE),这是我的FFT的结果。

Complex具有float realfloat imaginary

从此我计算了以下

  • 频率:(double)index * sampleRate / FftSize;
  • 振幅/幅度:Math.Sqrt(Math.Pow(real, 2) + Math.Pow(imaginary, 2));
  • 阶段:Math.Atan(imaginary / real);

如果这些错了,请纠正我。

据我了解,这是频域信息,它使我可以查看哪些频率在样本中最常见。现在,我想看到随着时间的推移功率密度。MATLAB文档显示了示例,但我不明白,因为我不知道Matlab。有人可以解释有关此主题的MATLAB文档或帮助我实施C#吗?

编辑:
这个答案建议简单地平整振幅。这是正确的吗?

的确,正如我在其他答案中所说的那样,您可以通过平方FFT结果的幅度来获得功率谱密度(PSD)估计值。从本质上讲,这是您引用的MATLAB文档中的以下行(最高缩放因素,这对于大多数需要比较不同频率组件的相对强度的应用并不重要):

psdx = (1/(Fs*N)) * abs(xdft).^2;

正如我在其他答案中也提到的,并且在MATLAB文档中也进行了描述,您可以通过在获取FFT之前将信号乘以窗口函数来获得更好的PSD估计,并平均多个FFT结果的平方尺度。

注意:对于阶段,您将更好地使用Math.Atan2(imaginary, real)(请参阅MSDN上的Math.Atan2),该范围涵盖了Enter [-pi,pi]范围(而不是仅覆盖[-pi/2,pi/2]Math.Atan())。

首先已将Math.Sqrt(Math.Pow(real, 2) + Math.Pow(imaginary, 2));实现为Complex.Magnitude属性。或者您可以使用Complex.Abs方法。

除了Sulutheye所说的话外,我还进行了一些有关实施功能的测量。

因为我不信任我实施的Math.Pow(x,2)功能:

private static double Square(double value)
{
    return value * value;
}

但是,事实证明C#已经优化了Math.Pow(x,2),因此足够快。但是无论如何:接下来我比较了三个实现

  1. Square(testData[idx].Real) + Square(testData[idx].Imaginary);
  2. Square(testData[idx].Magnitude);
  3. Square(Complex.Abs(testData[idx]));

我的(平均)结果(对于10,000,000个复杂元素):

  1. 45 MS
  2. 220 ms
  3. 211 MS

因此,似乎幅度属性和ABS方法在内部使用平方根,这需要很多循环进行处理。但是对于PSD,您不需要。