fft结果的功率谱密度c#

时间:2017-03-15 10:22:38

标签: c# matlab signal-processing fft spectral-density

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

Complex有一个float real和一个float imaginary

由此我计算了以下

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

如果这些是错误的,请纠正我。

根据我的理解,这是频域信息,它允许我查看哪些频率在我的样本中最常见。现在我希望看到功率密度随着时间的推移。 Matlab documentation显示了示例,但我不理解它,因为我不了解Matlab。有人可以解释关于这个主题的Matlab文档或帮助我实现C#实现吗?

修改
This answer建议简单地调整幅度。这是对的吗?

2 个答案:

答案 0 :(得分:2)

实际上,正如我在this other answer中所说,你可以通过平方FFT结果的幅度来获得功率谱密度(PSD)估计。这基本上是您引用的Matlab documentation状态的下一行(直到缩放因子,对于大多数仅需要比较不同频率分量的相对强度的应用而言,这并不重要):

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

正如我在其他答案中所提到的,并且也在Matlab文档中进行了描述,您可以通过在采用FFT之前将信号乘以window function来获得更好的PSD估计,并平均得到平均幅度。多个FFT结果。

注意:对于阶段,您可以更好地使用Math.Atan2(imaginary, real)(请参阅Math.Atan2 on MSDN),其中包含输入[-pi,pi]范围(而不是{{3} }}仅涵盖[-pi/2,pi/2])。

答案 1 :(得分:1)

首先Math.Sqrt(Math.Pow(real, 2) + Math.Pow(imaginary, 2));已经实现为Complex.Magnitude property。或者您可以使用Complex.Abs method

除了SleuthEye所说的,我还对功能实现做了一些测量。

因为我不相信我实施的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]));
  4. 我的(平均)结果是(对于10,000,000个复杂元素):

    1. 45 ms
    2. 220 ms
    3. 211 ms
    4. 所以似乎Magnitude属性和Abs方法在内部使用平方根,这需要很多周期来处理。但是对于PSD你不需要那样。