2017-03-15 1 views
1

J'ai un (de CsCore) qui est le résultat de ma FFT.densité spectrale de puissance du résultat fft C#

Complex a un float real et un float imaginary.

De cela, je calculé comme suit

  • Fréquence: (double)index * sampleRate/FftSize;
  • Amplitude/Magnitude: Math.Sqrt(Math.Pow(real, 2) + Math.Pow(imaginary, 2));
  • Phase: Si ceux-ci sont mal Math.Atan(imaginary/real);

s'il vous plaît me corriger. D'après ce que je comprends, c'est l'information de domaine de fréquence et elle me permet de voir quelles fréquences sont les plus communes dans mon échantillon. Maintenant, je veux voir la densité de puissance au fil du temps. Matlab documentation montre des exemples, mais je ne comprends pas parce que je ne connais pas Matlab. Quelqu'un pourrait-il expliquer la documentation Matlab sur ce sujet ou m'aider avec une implémentation C#?

EDIT:
This answer suggèrent à la case simplement l'amplitude. Est-ce exact?

+0

Selon [le code CsCore 'Complex'] (https://github.com/filoe/cscore/blob/master/CSCore/Utils/Complex.cs), il a' float real' et 'float imaginary' , pas 'double '... – JHBonarius

Répondre

2

En effet, comme je l'ai dit dans this other answer, vous pouvez obtenir une estimation de la densité spectrale de puissance (PSD) en quadraquant les amplitudes des résultats de la FFT. Ceci est essentiellement ce que la ligne suivante de la Matlab documentation vous avez cité les Etats (jusqu'à un facteur d'échelle, ce qui est important pour la plupart des applications ne nécessitant que de comparer la force relative des différentes composantes de fréquence):

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

Comme je l'ai également mentionné dans mon autre réponse, et est également décrit dans la documentation Matlab, vous pourriez obtenir une meilleure estimation PSD en multipliant votre signal par un window function avant de prendre la FFT, et en faisant la moyenne de l'amplitude au carré de plusieurs résultats FFT.

Note: pour la phase vous seriez mieux servis avec Math.Atan2(imaginary, real) (voir Math.Atan2 on MSDN) qui couvre la plage [-pi,pi] entrer (au lieu de Math.Atan() qui ne couvre [-pi/2,pi/2]).

+0

Je ne suis pas vraiment sûr de savoir comment utiliser le fenêtrage. Je comprends la formule du hann ('0.50f * (1 - (float) Math.Cos ((2 * Math.PI * n)/N - 1))') mais je dois utiliser la fenêtre avant le fft sur ma vague? –

+1

Si vous utilisez simplement la propriété ['Complex.Phase'] (https://msdn.microsoft.com/en-us/library/system.numerics.complex.phase (v = vs.110) .aspx) déjà utilise 'Math.Atan2 (b, a)' pour un nombre complexe 'a + bi'. – JHBonarius

+0

@GertKommer oui, si vous avez un morceau de N échantillons de votre vague, vous devez multiplier élément par la fonction de la fenêtre, puis prenez la FFT du résultat. – SleuthEye

1

Tout d'abord, Math.Sqrt(Math.Pow(real, 2) + Math.Pow(imaginary, 2)); est déjà implémenté en tant que Complex.Magnitude property. Ou vous pouvez utiliser le Complex.Abs method.

En plus de ce que dit SleuthEye, j'ai fait quelques mesures sur l'implémentation de la fonction.

Parce que je ne faisais pas confiance la fonction Math.Pow(x,2) I mis en œuvre:

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

Cependant, il se trouve que C# déjà optimisé Math.Pow(x,2), il est donc assez vite.Mais de toute façon: prochaine je comparais trois implémentations

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

Mes résultats (moyenne) ont été (pour 10.000.000 éléments complexes):

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

Il semble donc que la propriété Magnitude et méthode Abs utiliser une racine carrée à l'intérieur, ce qui prend beaucoup de cycles à traiter. Mais pour le PSD, vous n'avez pas besoin de ça.

+0

Je n'utilise pas la classe Complex standard, mais la classe Complex de CsCore. Malheureusement, on n'a pas la magnitude et la phase. Pour le reste de votre réponse, je ne sais pas vraiment quoi en faire. –

+0

Parfois ça vaut le coup de convertir un type en un autre pour pouvoir utiliser plus de fonctions;) Mais ce que j'essaie de dire: d'abord déterminer l'Absolu/Magnitude (je vois: dans CsCore on l'appelle 'Complex.Value') - qui a une racine carrée et ensuite le quadrature du résultat est très inefficace. – JHBonarius

+0

Eh bien j'ai honte, je n'ai pas vu le 'Complex.Value'. Pour le PSD, je dois faire un carré sur l'amplitude, puis le 'Complex.Value' ou ma propre fonction writen est plus rapide que les nombres Sys? –