Calculating the Power spectral density

前端 未结 3 1721
一向
一向 2021-01-20 03:59

I am trying to get the PSD of a real data set by making use of fftw3 library To test I wrote a small program as shown below ,that generates the a signal whic

3条回答
  •  无人及你
    2021-01-20 04:25

    Some remarks to your expected output function.

    • Your input is a function with pure real values. The result of a DFT has complex values. So you have to declare the variable out not as double but as fftw_complex *out.

    • In general the number of dft input values is the same as the number of output values. However, the output spectrum of a dft contains the complex amplitudes for positive frequencies as well as for negative frequencies.

    • In the special case for pure real input, the amplitudes of the positive frequencies are conjugated complex values of the amplitudes of the negative frequencies. For that, only the frequencies of the positive spectrum are calculated, which means that the number of the complex output values is the half of the number of real input values.

    • If your input is a simple sinewave, the spectrum contains only a single frequency component. This is true for 10, 100, 1000 or even more input samples. All other values are zero. So it doesn't make any sense to work with a huge number of input values.

    • If the input data set contains a single period, the complex output value is contained in out[1].

    • If the If the input data set contains M complete periods, in your case 5, so the result is stored in out[5]

    • I did some modifications on your code. To make some facts more clear.


    #include 
    #include 
    #include 
    #include 
    #include "fftw3.h"
    
    int performDFT(int nbrOfInputSamples, char *fileName)
    {
        int nbrOfOutputSamples;
        double *in;
        fftw_complex *out;
        fftw_plan p;
    
        // In the case of pure real input data,
        // the output values of the positive frequencies and the negative frequencies
        // are conjugated complex values.
        // This means, that there no need for calculating both.
        // If you have the complex values for the positive frequencies,
        // you can calculate the values of the negative frequencies just by
        // changing the sign of the value's imaginary part
        // So the number of complex output values ( amplitudes of frequency components)
        // are the half of the number of the real input values ( amplitutes in time domain):
        nbrOfOutputSamples = ceil(nbrOfInputSamples/2.0);
    
        // Create a plan for a 1D DFT with real input and complex output
        in = (double*) fftw_malloc(sizeof(double) * nbrOfInputSamples);
        out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * nbrOfOutputSamples);
        p = fftw_plan_dft_r2c_1d(nbrOfInputSamples, in, out, FFTW_ESTIMATE);
    
        // Read data from input file to input array
        FILE* inputFile = NULL;
        inputFile = fopen(fileName,"r");
        if(inputFile==NULL){
            fprintf(stdout,"couldn't open the file %s\n", fileName);
            return -1;
        }
        double value;
        int     idx = 0;
        while(!feof(inputFile)){
            fscanf(inputFile, "%lf", &value);
            in[idx++] = value;       
        }
        fclose(inputFile);
    
        // Perform the dft
        fftw_execute(p);
    
        // Print output results
        char outputFileName[] = "dftvalues.txt";
        FILE* outputFile = NULL;
       outputFile = fopen(outputFileName,"w+");
        if(outputFile==NULL){
            fprintf(stdout,"couldn't open the file %s\n", outputFileName);
            return -1;
        }
        double  realVal;
        double  imagVal;
        double  powVal;
        double  absVal;
    
        fprintf(stdout, "     Frequency  Real       Imag        Abs       Power\n");
        for (idx=0; idx
    • If the input of a dft is pure real, the output is complex in any case. So you have to use the plan r2c (RealToComplex).
    • If the signal is sin(2*pi*f*t), starting at t=0, the spectrum contains a single frequency line at f, which is pure imaginary.
    • If the sign has an offset in phase, like sin(2*pi*f*t+phi) the single line's value is complex.
    • If your sampling frequency is fs, the range of the output spectrum is -fs/2 ... +fs/2.
    • The real parts of the positive and negative frequencies are the same.
    • The imaginary parts of the positive and negative frequencies have opposite signs. This is called conjugated complex.
    • If you have the complex values of the positive spectrum you can calculate the values of the negative spectrum by changing the sign of the imaginary parts. For this reason there is no need to compute both, the positive and the negative sprectrum.
    • One sideband holds all information. Therefore the number of output samples in the plan r2c is the half+1 of the number of input samples.
    • To get the power of a frequency, you have to consider the positive frequency as well as the negative frequency. However, the plan r2c delivers only the right positive half of the spectrum. So you have to double the power of the positive side to get the total power.

      By the way, the documentation of the fftw3 package describes the usage of plans quite well. You should invest the time to go over the manual.

提交回复
热议问题