PSD using FFTW Halfcomplex transformation

社会主义新天地 提交于 2019-12-02 07:19:10

问题


I've asked a similar question,which was answered but when I try to do it my way I get "strange" values. I want to get the PSD of a sin wave use the half complex transformation like :

    #include <stdio.h>
#include <fftw3.h>
#include <complex.h>
#include <stdlib.h>
#include <math.h>
#define PI 3.141592653589793
int main (){

        double* inputValues;
        double* outputValues;
        double  realVal;
        double  imagVal;
        double  powVal=0.0;
        double  absVal;
        double timer;
        fftw_plan plan;
        double timeIntervall= 1.0; // 1sec 
        int numberOfSamples  =512;
        double timeSteps = timeIntervall/numberOfSamples;
        float frequency=10.0;
        float dcValue = 0.2;
        float value=0.0;
        int index=0;
        // allocating the memory for the fftw arrays 
        inputValues = (double*) fftw_malloc(sizeof(double)* numberOfSamples);
        outputValues = (double *) fftw_malloc(sizeof(double)*(numberOfSamples/*2*/));
        plan = fftw_plan_r2r_1d(numberOfSamples,inputValues,outputValues,FFTW_R2HC,FFTW_ESTIMATE);


    for (timer = 0; timer<=timeIntervall; timer += timeSteps){
        value =  sin(2*M_PI*frequency*timer) +dcValue;
        inputValues[index++] = value;

    }


        fftw_execute(plan);

        for (index=0;index<=numberOfSamples/*2*/;index++){
            powVal = outputValues[index]*outputValues[index]+outputValues[numberOfSamples-index]*outputValues[numberOfSamples- index];
            if(index==0)
                powVal/=2;
            powVal/=numberOfSamples;
            fprintf(stdout," index %d \t PSD value %lf \n",index,powVal);
        }

    return 0;
}

the value that I get are :

index 0          PSD value 12.24  // expecting 0.2
................
.....................
index 10         PSD value 129.99999  // expecting 0.5
........
.......
index 502       PSD value 127.9999  // expecting 0.5
......................
......................
index 512       PSD value 12.24   // expecting 0.2

otherwise the PSD value is zero, the position of the peak is correct but their value isn't any idea why ?

thanks in advance !

UPDATE

I solve it but I don't get why it works , so I won't put it as an answer : here is what I've changed in the code :

.......................................
      fftw_execute_r2r(plan_r2hc, in, out);
  powVal = outputValues[0]*outputValues[0];
  powVal /= (numberOfSamples*numberOfSamples)/2;  ///WHY ??????
  index = 0;
fprintf(stdout," index %d \t PSD value %lf \t \t %lf \n",index,powVal,outputValues[index]);
  for (index =1; index<numberOfSamples/2;index++){
  powVal = outputValues[index]*outputValues[index]+outputValues[numberOfSamples-index]*outputValues[numberOfSamples- index];

            powVal/=(numberOfSamples*numberOfSamples)/2;  //WHY?????
            fprintf(stdout," index %d \t PSD value %lf \t \t %lf \n",index,powVal,outputValues[index]);
        }

the result is accurate , I hope getting any explanation about why I should divide on the square of the windowsSize and the on 2 ? thanks again for your help !


回答1:


As described in Numerical Recipes, the normalization of the power-spectrum density (PSD) may vary depending on your exact definition of PSD. One possible definition which makes the sum of spectrum estimates correspond to the mean squared amplitude of the time domain function:

where P(k) is related to the FFT outputs X(k) through:


for some scaling factor S.

This seems to be the definition you are using based on your expected results.

Applying Parseval's theorem:


to the definition yields:


Or S=1/N2.

This of course assumes that you work with the entire spectrum. FFTW's Half-complex format on the other hand, as the name implies, gives you only half the spectrum (the other half being symmetric for real-valued inputs). You get the total power of a frequency component by adding in the equal-valued squared-magnitude of that symmetric spectrum value. This is where you get the factor of 2 from. Note that there are no corresponding symmetric outputs for real-valued index 0 and numberOfSamples/2, so you should not multiply by 2 in these cases.

So, your PSD should be computed as:

powVal = outputValues[0]*outputValues[0];
powVal /= (numberOfSamples*numberOfSamples);
for (index =1; index<numberOfSamples/2;index++){
  powVal = outputValues[index]*outputValues[index]+outputValues[numberOfSamples-index]*outputValues[numberOfSamples-index];
  powVal /= (numberOfSamples*numberOfSamples)/2;
}
powVal = outputValues[numberOfSamples/2]*outputValues[numberOfSamples/2];
powVal /= (numberOfSamples*numberOfSamples);

Note: the mean squared amplitude of your DC component should be 0.2*0.2 = 0.04 (not 0.2 which you indicated as your expected value for index 0).



来源:https://stackoverflow.com/questions/24946383/psd-using-fftw-halfcomplex-transformation

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!