2017-03-15 78 views
1

我有一个(来自CsCore),这是我FFT的结果。来自fft结果c的功率谱密度#

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建议简单地广场幅度。那是对的吗?

+0

根据[CsCore'Complex'代码](https://github.com/filoe/cscore/blob/master/CSCore/Utils/Complex.cs),它具有'float real'和'float imaginary' ,不是'double' ... – JHBonarius

回答

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]范围(而不是Math.Atan()只涵盖[-pi/2,pi/2])。

+0

我不太确定如何使用窗口。我理解hann('0.50f *(1 - (float)Math.Cos((2 * Math.PI * n)/ N-1))''的公式,但我必须在fft之前使用窗口我的浪潮? –

+1

如果您只是使用['Complex.Phase'属性](https://msdn.microsoft.com/en-us/library/system.numerics.complex.phase(v = vs.110).aspx)它已经使用'Math.Atan2(b,a)'作为复数'a + bi'。 – JHBonarius

+0

@GertKommer是的,如果你有一大堆N样本来自你的wave,你可以用窗口函数乘以元素,然后对结果进行FFT。 – SleuthEye

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

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

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

因此,似乎在幅度特性和ABS方法使用平方根内部,这需要大量的周期来处理的。但是对于你不需要的PSD。

+0

我没有使用标准的Complex类,而是CsCore的Complex类。可悲的是,一个没有规模和阶段。至于你的答案的其余部分,我不确定如何处理它。 –

+0

有时它值得将一种类型转换为另一种类型以便能够使用更多的函数;)但是我想说的是:首先确定绝对/幅度(我知道:在CsCore中它被称为“Complex.Value”) - 它有一个平方根,然后平方的结果是非常低效的。 – JHBonarius

+0

嗯,我很惭愧,我没有看到'Complex.Value'。 对于PSD我必须在幅度上平方,然后'Complex.Value'或我自己的写函数比Sys数字更快? –