2

我有一个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文档显示了示例,但我不明白,因为我不了解Matlab。有人可以解释有关此主题的 Matlab 文档或帮助我实现 C# 吗?

编辑:
这个答案建议简单地平方幅度。那是对的吗?

4

2 回答 2

2

实际上,正如我在另一个答案中所述,您可以通过对 FFT 结果的幅度进行平方来获得功率谱密度 (PSD) 估计值。这本质上是您引用的Matlab 文档中的以下行(最多为比例因子,这对于大多数只需要比较不同频率分量的相对强度的应用来说并不重要):

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

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

注意:对于涵盖输入范围(而不是仅涵盖)的阶段,您会得到更好的服务Math.Atan2(imaginary, real)(参见Math.Atan2MSDN)。[-pi,pi]Math.Atan()[-pi/2,pi/2]

于 2017-03-15T11:59:15.083 回答
1

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

除了 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]));

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

  1. 45 毫秒
  2. 220 毫秒
  3. 211 毫秒

所以看起来 Magnitude 属性和 Abs 方法在内部使用平方根,这需要很多周期来处理。但是对于 PSD,你不需要那个。

于 2017-03-15T15:32:25.220 回答