C 基于FFTW半复变换的PSD

C 基于FFTW半复变换的PSD,c,fftw,C,Fftw,我问了一个问题,得到了回答,但当我试图用我的方式去做时,我得到了“奇怪”的值。 我想用半复变换得到正弦波的PSD,如: #include <stdio.h> #include <fftw3.h> #include <complex.h> #include <stdlib.h> #include <math.h> #define PI 3.141592653589793 int main (){ double*

我问了一个问题,得到了回答,但当我试图用我的方式去做时,我得到了“奇怪”的值。 我想用半复变换得到正弦波的PSD,如:

    #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;
}
否则PSD值为零,峰值位置正确,但其值不知道为什么

提前谢谢

更新

我解决了它,但我不明白它为什么有效,所以我不会把它作为一个答案: 以下是我在代码中更改的内容:

.......................................
      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]);
        }
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
fftw_execute_r2r(计划、输入、输出);
powVal=outputValues[0]*outputValues[0];
powVal/=(numberOfSamples*numberOfSamples)/2///为什么?
指数=0;
fprintf(标准输出,“索引%d\t PSD值%lf\t\t%lf\n”,索引,功率值,输出值[索引];
对于(index=1;index,如中所述,功率谱密度(PSD)的标准化可能因PSD的确切定义而异。
一种可能的定义,使谱估计的总和对应于时域函数的均方振幅:

其中p(k)与FFT输出X(k)至:

对于某些比例因子
S

这似乎是您根据预期结果使用的定义

申请:

根据定义产生:

或S=1/N2

当然,这假设您使用整个频谱。 另一方面,顾名思义,它只提供了光谱的一半 (另一半对于实值输入是对称的)。 通过将对称频谱值的等值平方幅值相加,可以得到频率分量的总功率。 这就是得到因子2的原因。 请注意,实值索引0和
numberOfSamples/2
没有相应的对称输出,因此在这些情况下不应乘以2

因此,您的PSD应计算为:

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);
powVal=outputValues[0]*outputValues[0];
powVal/=(numberOfSamples*numberOfSamples);

对于(index=1;index谢谢你的答案,这个和另一个,需要一点时间来理解它
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);