简体   繁体   中英

Correct way to implement windowing

I'm trying to implement windowing in a program, for that I've wrote a sin function with 2048 samples. I'm reading the values and try to calculate the PSD using the "rect" window, when my window is 2048 wide, the result is accurate. Otherwise the result doesn't make any sense to me.

Here is the code that I'm using,

#include <fftw3.h>
#include <math.h>
#include <stdio.h>
#include <complex.h>


int main (){
  FILE* inputFile = NULL;
  FILE* outputFile= NULL;
  double* inputData=NULL; 
  double* outputData=NULL;
  double* windowData=NULL;
  unsigned int windowSize = 512;
  int overlaping =128;
  int index1 =0,index2=0, i=0;
  double powVal= 0.0;
  fftw_plan plan_r2hc;

// mememory allocation
  inputData = (double*) fftw_malloc(sizeof(double)*windowSize);
  outputData= (double*) fftw_malloc(sizeof(double)*windowSize);
  windowData= (double*) fftw_malloc(sizeof(double)*windowSize);
  plan_r2hc = fftw_plan_r2r_1d(windowSize, inputData, windowData, FFTW_R2HC, FFTW_PATIENT);
  // Opning files 
  inputFile = fopen("sinusD","rb");
  outputFile= fopen("windowingResult","wb+");
  if(inputFile==NULL ){
    printf("Couldn't open either the input or the output file \n");
    return -1;
  }

  while((i=fread(inputData,sizeof(double),windowSize,inputFile))==windowSize){   
      fftw_execute_r2r(plan_r2hc, inputData, windowData);
    for( index1 =0; index1 < windowSize;index1++){
      outputData[index1]+=windowData[index1];
      printf("index %d \t %lf\n",index1,inputData[index1]);
    }
     if(overlaping!=0)
      fseek(inputFile,(-overlaping)*sizeof(double),SEEK_CUR);
  }
  if( i!=0){
     i = -i;
    fseek(inputFile ,i*sizeof(double),SEEK_END);
    fread(inputData,sizeof(double),-i,inputFile);


  fftw_execute_r2r(plan_r2hc, inputData, windowData);
  for( index1=0;index1< windowSize; index1++){
    outputData[index1]+=windowData[index1];
  }

  }

  powVal = outputData[0]*outputData[0];
  powVal /= (windowSize*windowSize)/2;
  index1 = 0;
  fprintf(outputFile,"%lf ",powVal);
  printf(" PSD \t %lf\n",powVal);
  for (index1 =1; index1<=windowSize/2;index1++){
            powVal = outputData[index1]*outputData[index1]+outputData[windowSize-index1]*outputData[windowSize- index1];
            powVal/=(windowSize*windowSize)/2;
          //  powVal = 20*log10(fabs(powVal));
            fprintf(outputFile,"%lf ",powVal);
            printf(" PsD %d \t %10.5lf\n",index1,powVal);
    }


  fftw_free(inputData);
  fftw_free(outputData);
  fftw_free(windowData);
  fclose(inputFile);
  fclose(outputFile);
}

You need to premultiply the signal with a window function . This can be precomputed if you are calculating multiple FFTs.

For example, a Hanning window is calculated as follows:

#define WINDOW_SIZE 2048
int i;
double w[WINDOW_SIZE];
for (i=0; i<WINDOW_SIZE; i++) {
  w[i] = (1.0 - cos(2.0 * M_PI * i/(WINDOW_SIZE-1))) * 0.5;
}

Before computing the Fourier transform, multiply your input data by this window as follows:

for (i=0; i<WINDOW_SIZE; i++) inputData[i] *= w[i];

Explanation

When you calculate the Fourier transform of a finite set of samples, what you actually get is the frequency spectrum of the infinite signal that you would get by repeating these samples forever. Unless you're sampling a signal whose frequency is an exact multiple of the sampling frame rate, you will get large discontinuities where the end of one sample frame runs into the start of the next. A window function flattens out the samples at the edges of the sample frame to eliminate these discontinuities.

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