ftp.nice.ch/pub/next/unix/audio/cmusic.bs.N.tar.gz#/src/convert/window.c

This is window.c in view mode; [Download] [Up]

#include <math.h>
#include <stdio.h>
/*
#include <malloc.h>
*/

/*-----------------------------------------------------------------------
			WINDOW Subroutines

These are essentially C versions of the classical window subroutines in
	the IEEE Programs for Digital Signal Processing.  In order that
	the code be more easily portable to PC's, complicated arithmetic
	expressions have been broken into parts, dynamic array allocation
	has replaced static declaration, and error checking has been
	improved.

-----------------------------------------------------------------------*/

/*-----------------------------------------------------------------------
subroutine:  triang

triangular window
-----------------------------------------------------------------------*/

triang(nf,w,n,ieo)
	int nf, n, ieo;
	float *w;
{

/*
    nf = filter length in samples
    w = window coefficients for half the window
    n = half window length=(nf+1)/2
    ieo = even - odd indication--ieo=0 for nf even
*/

	float	fn, xi;

	int	i;

	fn = n;
	for (i = 0; i < n; i++){
		xi = i;
		if (ieo == 0)
			xi += 0.5;
		w[i] = 1. - xi / fn;
	}
	return;
}



/*-----------------------------------------------------------------------
subroutine:  hammin

generalized hamming window routine
window is w(n) = alpha + beta * cos( twopi*(n-1) / (nf-1) )
-----------------------------------------------------------------------*/

hammin(nf,w,n,ieo,alpha,beta)
	int nf, n, ieo;
	float *w, alpha, beta;
{

/*
    nf = filter length in samples
     w = window array of size n
     n = half length of filter=(nf+1)/2
   ieo = even odd indicator--ieo=0 if nf even
 alpha = constant of window
  beta = constant of window--generally beta=1-alpha
*/

	float	pi2, fn, fi;

	int	i;

	pi2 = 8.0 * atan(1.0);
	fn = nf - 1;
	for (i = 0; i < n; i++) {
		fi = i;
		if (ieo == 0)
			fi += 0.5;
		w[i] = cos((pi2 * fi) / fn);
		w[i] = alpha + beta * w[i];
	}
	return;
}



/*-----------------------------------------------------------------------
subroutine:  kaiser

kaiser window
-----------------------------------------------------------------------*/

kaiser(nf,w,n,ieo,beta)
	int nf, n, ieo;
	float *w, beta;
{

/*
   nf = filter length in samples
    w = window array of size n
    n = filter half length=(nf+1)/2
  ieo = even odd indicator--ieo=0 if nf even
 beta = parameter of kaiser window
*/

	extern	float	ino();

	float	bes, xind, xi;

	int	i;

	bes = ino(beta);
	xind = (float)(nf-1)*(nf-1);

	for (i = 0; i < n; i++) {
		xi = i;
		if (ieo == 0)
			xi += 0.5;
		xi = 4. * xi * xi;
		xi = sqrt(1. - xi / xind);
		w[i] = ino(beta * xi);
		w[i] /= bes;
	}
	return;
}



/*-----------------------------------------------------------------------
function:  ino
bessel function for kaiser window
-----------------------------------------------------------------------*/

float ino(x)
	float x;
{

	float	y, t, e, de, sde, xi;

	int i;

	y = x / 2.;
	t = 1.e-08;
	e = 1.;
	de = 1.;
	for (i = 1; i <= 25; i++) {
		xi = i;
		de = de * y / xi;
		sde = de * de;
		e += sde;
		if (e * t > sde)
			break;
	}
	return(e);
}



/*-----------------------------------------------------------------------
subroutine:  chebc

subroutine to generate chebyshev window parameters when
one of the three parameters nf,dp and df is unspecified

note:  parameters must be passed as addresses so they can be changed
-----------------------------------------------------------------------*/

chebc(nf,dp,df,n,x0,xn)
	int *nf, *n;
	float *dp, *df, *x0, *xn;
{

/*
 nf = filter length (in samples)
 dp = filter ripple (absolute scale)
 df = normalized transition width of filter
  n = (nf+1)/2 = filter half length
 x0 = (3-c0)/(1+c0) with c0=cos(pi*df) = chebyshev window constant
 xn = nf-1
*/

	extern	float arccos(), coshin();

	float	pi, c0, c1, c2, x;

	pi = 4. * atan(1.0);
	if (*nf == 0) {			/* dp,df specified, determine nf */
		c1 = coshin((1. + *dp) / *dp);
		c0 = cos(pi * *df);
		x = coshin(1. / c0);
		x = 1. + c1 / x;
		*nf = x + 1.0;
		*n = (*nf + 1) / 2;
		*xn = *nf - 1.;
	}

	else if (*df != 0.0) { 		/* nf,df specified, determine dp */
		*xn = *nf - 1.;
		c0 = cos(pi * *df);
		c1 = *xn * coshin(1. / c0);
		*dp = cosh(c1) - 1.;
		*dp = 1. / *dp;
	}

	else { 				/* nf,dp specified, determine df */
		*xn = *nf - 1.;
		c1 = coshin((1. + *dp) / *dp);
		c2 = cosh(c1 / *xn);
		*df = arccos(1. / c2) / pi;
	}

	*x0 = 3. - cos(2. * pi * *df);
	*x0 /= (1. + cos(2. * pi * *df));

	return;
}



/*-----------------------------------------------------------------------
subroutine:  cheby

dolph chebyshev window design
-----------------------------------------------------------------------*/

cheby(nf,w,n,ieo,dp,df,x0,xn)
	int nf, n, ieo;
	float *w, dp, df, x0, xn;
{

/*
  nf = filter length in samples
   w = window array of size n
   n = half length of filter = (nf+1)/2
 ieo = even-odd indicator--ieo=0 for nf even
  dp = window ripple on an absolute scale
  df = normalized transition width of window
  x0 = window parameter related to transition width
  xn = nf-1
*/

	float	*pr, *pi;

	float	pie, fnf, alpha, beta, twopi, c1, c2, f, x, p, twn, sum,
		xi, xj, t1, t2;

	int	i, j;

	if ((pr = (float *) calloc(1024,sizeof(float))) == NULL){
		fprintf(stderr,"cheby: can't calloc memory\n");
		return;
	}

	if ((pi = (float *) calloc(1024,sizeof(float))) == NULL){
		fprintf(stderr,"cheby: can't calloc memory\n");
		return;
	}

	pie = 4. * atan(1.0);
	xn = nf - 1;
	fnf = nf;
	alpha = (x0 + 1.) / 2.;
	beta = (x0 - 1.) / 2.;
	twopi = 2. * pie;
	c2 = xn / 2.;

	for (i = 0; i < nf; i++) {
		xi = i;
		f = xi / fnf;
		x = cos(twopi * f);
		x = alpha * x + beta;
		if (x < -1.)	/* in case of arithmetic round-off error */
			x = -1.;
		if (x > 1.){
			p = coshin(x);
			p = dp * cosh(c2 * p);
		}
		else {
			p = arccos(x);
			p = dp * cos(c2 * p);
		}
		pi[i] = 0.;
		pr[i] = p;

/*  for even length filters use a one-half sample delay,
    also the frequency response is antisymmetric in frequency */

		if (ieo != 1) {
			pr[i] = p * cos(pie * f);
			pi[i] = -p * sin(pie * f);
			if (i > nf / 2 + 1){
				pr[i] = -pr[i];
				pi[i] = -pi[i];
			}
		}
	}

/*  use dft to give window */

	twn = twopi / fnf;
	for (i = 0; i < n; i++) {
		xi = i;
		sum = 0.;
		for (j = 0; j < nf; j++) {
			xj = j;
			t1 = cos(twn * xj * xi);
			t2 = sin(twn * xj * xi);
			sum += pr[j] * t1 + pi[j] * t2;
		}
		w[i] = sum;
	}
	c1 = w[1];
	for (i = 0; i < n; i++)
		w[i] /= c1;

	free(pi);
	free(pr);

	return;
}



/*-----------------------------------------------------------------------
function:  coshin

function for hyperbolic inverse cosine of x
-----------------------------------------------------------------------*/

float coshin(x)
	float x;
{
	float c;

	c = sqrt(x * x - 1.);
	c = log(x + c);
	return(c);
}



/*-----------------------------------------------------------------------
function:  arccos

function for inverse cosine of x
-----------------------------------------------------------------------*/

float arccos(x)
	float x;
{

	float c, a;

	if (x < 0.) {
		a = sqrt(1. - x * x);
		a /= x;
		c = atan(a);
		c += 4. * atan(1.0);
	}
	else if (x == 0.)
		c = 2. * atan(1.0);
	else {
		a = sqrt(1. - x * x);
		a /= x;
		c = atan(a);
	}

	return(c);
}



/*-----------------------------------------------------------------------
function:  cosh

function for hyperbolic cosine of x
-----------------------------------------------------------------------*/
/*
float cosh(x)
	float x;
{
	float c;

	c = exp(x);
	c += exp(-x);
	c *= .5;
	return(c);
}
*/

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.