我有一个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建议简单地调整幅度。这是对的吗?
答案 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)
,所以它足够快。但无论如何:接下来我比较了三个实现
Square(testData[idx].Real) + Square(testData[idx].Imaginary);
Square(testData[idx].Magnitude);
Square(Complex.Abs(testData[idx]));
我的(平均)结果是(对于10,000,000个复杂元素):
所以似乎Magnitude属性和Abs方法在内部使用平方根,这需要很多周期来处理。但是对于PSD你不需要那样。