2017-03-15 140 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數字更快? –