简体   繁体   中英

power spectral density from fft result c#

I have a Complex[] (from CsCore) which is the result of my FFT.

Complex has a float real and a float imaginary .

From this I calculated the following

  • Frequency: (double)index * sampleRate / FftSize;
  • Amplitude / Magnitude: Math.Sqrt(Math.Pow(real, 2) + Math.Pow(imaginary, 2));
  • Phase: Math.Atan(imaginary / real);

If these are wrong please correct me.

From what I understand, this is the frequency domain information and it allows me to see which frequencies are most common in my sample. Now I want to see the power density over time. Matlab documentation shows examples, But I don't understand it because I don't know Matlab. Could someone explain the Matlab documentation on this subject or help me with a C# implementation?

EDIT:
This answer suggest to simply square the amplitude. Is that correct?

Indeed, as I stated in this other answer you could obtain a power spectrum density (PSD) estimate by squaring the amplitudes of the FFT results. This is essentially what the following line from the Matlab documentation you quoted states (up to a scaling factor, which is not significant for most applications requiring only to compare the relative strength of the different frequency components):

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

As I also mentioned in my other answer, and is also described in Matlab documentation, you could get a better PSD estimate by multiplying your signal by a window function before taking the FFT, and averaging the squared-magnitude of multiple FFT results.

Note: for the phase you would be better served with Math.Atan2(imaginary, real) (see Math.Atan2 on MSDN ) which covers the enter [-pi,pi] range (instead of Math.Atan() which only covers [-pi/2,pi/2] ).

Firstly Math.Sqrt(Math.Pow(real, 2) + Math.Pow(imaginary, 2)); is already implemented as the Complex.Magnitude property . Or you can use the Complex.Abs method .

In addition to what SleuthEye said, I did some measurements on function implementation.

Because I did not trust the Math.Pow(x,2) function I implemented:

private static double Square(double value)
{
    return value * value;
}

However, it turns out that C# already optimized Math.Pow(x,2) , so it's fast enough. But anyhow: next I compared three implementations

  1. Square(testData[idx].Real) + Square(testData[idx].Imaginary);
  2. Square(testData[idx].Magnitude);
  3. Square(Complex.Abs(testData[idx]));

My (average) results were (for 10,000,000 complex elements):

  1. 45 ms
  2. 220 ms
  3. 211 ms

So it seems the Magnitude property and Abs method use a square root internally, which takes a lot of cycles to process. But for the PSD you don't need that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM