view WindowFunctions.cpp @ 1:6422640a802f

first upload
author Wen X <xue.wen@elec.qmul.ac.uk>
date Tue, 05 Oct 2010 10:45:57 +0100
parents
children
line wrap: on
line source
//---------------------------------------------------------------------------
#include <math.h>
#include <mem.h>
#include "WindowFunctions.h"
#include "align8.h"
//---------------------------------------------------------------------------

/*
  function I0: Bessel function of order zero

  Returns the Bessel function of x.
*/
double I0(double x)
{
  const double eps=1e-9;

  int n=1;
  double S=1, D=1, T;

  while (D>eps*S)
  {
    T=x/(2*n++);
    D*=T*T;
    S+=D;
  }
  return S;
}//I0

/*
  function FillWindow: fills a buffer $Result with a window function.

  In: wt:window type
      Count: window size
      ips & ups: extra window specificatin parameters
  Out: newwindow[Count+1]: the window function.

  No return value. This function is designed assuming Count being even, and Count/2 is the symmetry
  centre of newwindow. newwindow has physical size Count+1 for compatibility purpose. For all vanishing
  windows (e.g. Hann) newwindow[0]=newwindow[Count]=0.
*/
void FillWindow(double* Result, WindowType wt, int Count, int* ips, double* dps)
{
	switch(wt)
  {
    case wtRectangle:
      for (int i=0; i<=Count; i++)
        Result[i]=1;
      break;
    case wtTriangular:
      for (int i=0; i<=Count; i++)
				Result[i]=1-2*fabs(i-Count/2.0)/Count;
      break;
    case wtHamming:
      for (int i=0; i<=Count; i++)
        Result[i]=(0.54-0.46*cos(2*M_PI*i/Count));
      break;
    case wtBlackman:
      for (int i=0; i<=Count; i++)
        Result[i]=0.42-0.5*cos(2*M_PI*i/Count)+0.08*cos(4*M_PI*i/Count);
      break;
    case wtGaussian:
    {
      double num=*dps*M_PI*M_PI/2/Count/Count;
      for (int i=0; i<=Count; i++)
        Result[i]=exp(-(i-Count/2.0)*(i-Count/2.0)*num);
      break;
    }
    case wtKaiser:
    {
      double ldps=*dps*M_PI*M_PI/2/Count;
      double den=I0(0.5*Count*ldps);
      for (int i=0; i<=Count; i++)
        Result[i]=I0(ldps*sqrt(0.25*Count*Count-(i-Count*0.5)*(i-Count*0.5)))/den;
      break;
    }
    case wtHalfCosine:
    {
      for (int i=0; i<=Count; i++)
				Result[i]=sin(M_PI*i/Count);
      break;
    }
    case wtHann:
    {
      for (int i=0; i<=Count; i++)
        Result[i]=(0.5-cos(M_PI*2*i/Count)/2);
      break;
    }
    case wtHannSqr:
    {
      for (int i=0; i<=Count; i++)
        Result[i]=(3-4*cos(M_PI*2*i/Count)+cos(M_PI*4*i/Count))/8;
      break;
		}
		case wtHann3sqrt:
		{
			for (int i=0; i<=Count; i++)
			{
				double tmp=sin(M_PI*i/Count);
				Result[i]=tmp*tmp*tmp;
			}
			break;
		}
	}
}//FillWindow

/*
  function NewWindow: creates a window function.

  In: wt: window type
      Count: window size
      ips & ups: extra window specificatin parameters
  Out: newwindow[Count+1]: the window function.

  Returns pointer to newwindow. newwindow is created anew if newwindow=0 is specified on start.
*/
double* NewWindow(WindowType wt, int Count, int* ips, double* dps, double* newwindow)
{
	double* Result=newwindow; if (!Result) Result=new double[Count+1];
	FillWindow(Result, wt, Count, ips, dps);
	return Result;
}//NewWindow

/*
  function NewWindow8: 8-byte aligned version of NewWindow.

  In: wt: window type
      Count: window size
      ips & ups: extra window specificatin parameters
  Out: newwindow[Count+1]: the window function.

  Returns pointer to newwindow. newwindow is created anew and 8-byte aligned if newwindow=0 is
  specified on start. However, if newwindow is not 8-byte aligned on start, the unaligned buffer is
  returned.
*/
double* NewWindow8(WindowType wt, int Count, int* ips, double* dps, double* newwindow)
{
	double* Result=newwindow; if (!Result) Result=(double*)malloc8(sizeof(double)*(Count+1));
	FillWindow(Result, wt, Count, ips, dps);
	return Result;
}//NewWindow8

/*
  function NewdWindow: computes the derivative of a window function.

  In: wt: window type
      Count: window size
      ips & ups: extra window specificatin parameters
  Out: newdwindow[Count+1]: the derivative window function.

  Returns pointer to newdwindow. newdwindow is created anew if newdwindow=0 is specified on start.
*/
double* NewdWindow(WindowType wt, int Count, int* ips, double* dps, double* newdwindow)
{
	double* Result=newdwindow; if (!Result) Result=new double[Count+1];
	double piiCount=M_PI/Count;
	switch(wt)
	{
		case wtRectangle:
			memset(Result, 0, sizeof(double)*(Count+1));
			break;
    case wtTriangular:
      throw("Trying to differentiate triangular window.");
      break;
		case wtHamming:
			for (int i=0; i<=Count; i++)
				Result[i]=0.92*piiCount*sin(2*piiCount*i);
			break;
		case wtBlackman:
			for (int i=0; i<=Count; i++)
				Result[i]=piiCount*sin(2*piiCount*i)-0.32*piiCount*sin(4*piiCount*i);
			break;
    case wtGaussian:
      throw("Trying to differentiate Gaussian window.");
      break;
    case wtKaiser:
      throw("Trying to differentiate Kaiser window.");
      break;
    case wtHalfCosine:
		{
			for (int i=0; i<=Count; i++)
				Result[i]=piiCount*cos(piiCount*i);
			break;
		}
		case wtHann:
		{
			for (int i=0; i<=Count; i++)
				Result[i]=piiCount*sin(2*piiCount*i);
			break;
		}
		case wtHannSqr:
		{
			for (int i=0; i<=Count; i++)
				Result[i]=piiCount*sin(2*piiCount*i)-0.5*piiCount*sin(4*piiCount*i);
			break;
		}
		case wtHann3sqrt:
		{
			for (int i=0; i<=Count; i++)
			{
				double s=sin(M_PI*i/Count), c=cos(M_PI*i/Count);
				Result[i]=3*piiCount*s*s*c;
			}
		}
	}
	return Result;
}//NewdWindow

/*
  function NewddWindow: computes the 2nd-order derivative of a window function.

  In: wt: window type
      Count: window size
      ips & ups: extra window specificatin parameters
  Out: newddwindow[Count+1]: the 2nd-order derivative window function.

  Returns pointer to newddwindow. newddwindow is created anew if newddwindow=0 is specified on start.
*/
double* NewddWindow(WindowType wt, int Count, int* ips, double* dps, double* newddwindow)
{
	double* Result=newddwindow; if (!Result) Result=new double[Count+1];
	double piiCount=M_PI/Count;
	double piC2=piiCount*piiCount;
	switch(wt)
	{
		case wtRectangle:
			memset(Result, 0, sizeof(double)*(Count+1));
      break;
    case wtTriangular:
      throw("Trying to double-differentiate triangular window.");
      break;
    case wtHamming:
			for (int i=0; i<=Count; i++)
				Result[i]=1.84*piC2*cos(2*piiCount*i);
			break;
		case wtBlackman:
			for (int i=0; i<=Count; i++)
				Result[i]=2*piC2*cos(2*piiCount*i)-1.28*piC2*cos(4*piiCount*i);
			break;
    case wtGaussian:
      throw("Trying to double-differentiate Gaussian window.");
      break;
    case wtKaiser:
      throw("Trying to double-differentiate Kaiser window.");
      break;
    case wtHalfCosine:
		{
			for (int i=0; i<=Count; i++)
				Result[i]=-piC2*sin(piiCount*i);
			break;
		}
		case wtHann:
		{
			for (int i=0; i<=Count; i++)
				Result[i]=2*piC2*cos(2*piiCount*i);
			break;
		}
		case wtHannSqr:
		{
			for (int i=0; i<=Count; i++)
				Result[i]=2*piC2*cos(2*piiCount*i)-2*piC2*cos(4*piiCount*i);
			break;
		}
		case wtHann3sqrt:
		{
			for (int i=0; i<=Count; i++)
			{
				double s=sin(M_PI*i/Count), c=cos(M_PI*i/Count);
				Result[i]=3*piC2*(2*c*c-s*s)*s;
			}
			break;
		}
	}
	return Result;
}//NewddWindow

/*
  function NewdddWindow: computes the 3rd-order derivative of a window function.
  In: wt: window type
      Count: window size
      ips & ups: extra window specificatin parameters
  Out: newdddwindow[Count+1]: the 3rd-order derivative window function.

  Returns pointer to newdddwindow. newdddwindow is created anew if newdddwindow=0 is specified on start.
*/
double* NewdddWindow(WindowType wt, int Count, int* ips, double* dps, double* newdddwindow)
{
	double* Result=newdddwindow; if (!Result) Result=new double[Count+1];
	double piiCount=M_PI/Count;
	double piC2=piiCount*piiCount;
	double piC3=piiCount*piC2;
	switch(wt)
	{
    case wtRectangle:
      memset(Result, 0, sizeof(double)*(Count+1));
      break;
    case wtTriangular:
      throw("Trying to triple-differentiate triangular window.");
      break;
    case wtHamming:
			for (int i=0; i<=Count; i++)
				Result[i]=-3.68*piC3*sin(2*piiCount*i);
			break;
		case wtBlackman:
			for (int i=0; i<=Count; i++)
				Result[i]=-4*piC3*sin(2*piiCount*i)+5.12*piC3*sin(4*piiCount*i);
			break;
    case wtGaussian:
      throw("Trying to triple-differentiate Gaussian window.");
      break;
    case wtKaiser:
      throw("Trying to triple-differentiate Kaiser window.");
      break;
    case wtHalfCosine:
		{
			for (int i=0; i<=Count; i++)
				Result[i]=-piC3*cos(piiCount*i);
			break;
		}
		case wtHann:
		{
			for (int i=0; i<=Count; i++)
				Result[i]=-4*piC3*sin(2*piiCount*i);
			break;
    }
		case wtHannSqr:
    {
      for (int i=0; i<=Count; i++)
				Result[i]=-4*piC3*sin(2*piiCount*i)+8*piC3*sin(4*piiCount*i);
			break;
    }
    case wtHann3sqrt:
      throw("Trying to triple-differentiate Hann^1.5 window.");
      break;
	}
  return Result;
}//NewdddWindow

//---------------------------------------------------------------------------
/*
  function windowspec: computes a few descriptors of a cosine family window. A window function in the
  cosine window family is the linear combination of a few cosine functions, therefore has a cosine
  decomposition.

  In: wt: window type
      N: window size
  Out: c[M+1], coefficients of cosine decomposition
       iH2: reciprocal of square of L2 norm,
       d[2M+1]: self-convolution of c[], optional

  No return value.
*/
void windowspec(WindowType wt, int N, int* M, double* c, double* iH2, double* d)
{
  switch(wt)
  {
    case wtRectangle:
      M[0]=0, c[0]=1, iH2[0]=1.0/N/N;
      if (d) d[0]=1;
      break;
    case wtHamming:
      M[0]=1, c[0]=0.54, c[1]=0.23, iH2[0]=1.0/(0.3974*N*N);
      if (d) d[0]=0.3974, d[1]=0.2484, d[2]=0.0529;
      break;
    case wtBlackman:
      M[0]=2, c[0]=0.42, c[1]=0.25, c[2]=0.04, iH2[0]=1.0/(0.3046*N*N);
      if (d) d[0]=0.3046, d[1]=0.23, d[2]=0.0961, d[4]=0.02, d[5]=0.0016;
      break;
    case wtHann:
      M[0]=1, c[0]=0.5, c[1]=0.25, iH2[0]=1.0/(0.375*N*N);
      if (d) d[0]=0.375, d[1]=0.25, d[2]=0.0625;
      break;
    default:
      M[0]=1, c[0]=0.5, c[1]=0.25, iH2[0]=1.0/(0.375*N*N);
      if (d) d[0]=0.375, d[1]=0.25, d[2]=0.0625;
      break;
  }
}//windowspec