⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rateconv.c

📁 AAC音频解码算法程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/**********************************************************************
audio sample rate converter

$Id: rateconv.c,v 1.1 2000/01/17 21:53:04 menno Exp $

Source file: rateconv.c

Authors:
NM    Nikolaus Meine, Uni Hannover (c/o Heiko Purnhagen)
HP    Heiko Purnhagen, Uni Hannover <purnhage@tnt.uni-hannover.de>

Changes:
xx-jun-98   NM      resamp.c
18-sep-98   HP      converted into module
03-aug-99   NM      now even faster ...
04-nov-99   NM/HP   double ratio, htaps1 /= 2
11-nov-99   HP      improved RateConvInit() debuglevel
**********************************************************************/

/*
 * Sample-rate converter
 *
 * Realized in three steps:
 *
 * 1. Upsampling by factor two while doing appropriate lowpass-filtering.
 *    This is done by using an FFT-based convolution algorithm with a multi-tap
 *    Kaiser-windowed lowpass filter.
 *    If the cotoff-frequency is less than 0.5, only lowpass-filtering without
 *    the upsampling is done.
 * 2. Upsampling by factor 128 using a 15 tap Kaiser-windowed lowpass filter
 *    (alpha=12.5) and conventional convolution algorithm.
 *    Two values (the next neighbours) are computed for every sample needed.
 * 3. Linear interpolation between the two bounding values.
 *
 * Stereo and mono data is supported.
 * Up- and downsampling of any ratio is possible.
 * Input and output file format is Sun-audio.
 *
 * Written by N.Meine, 1998
 *
 */

/* Multi channel data is interleaved: l0 r0 l1 r1 ... */
/* Total number of samples (over all channels) is used. */


#include <stdio.h>
#include <stdlib.h>
#include <math.h>


#include "aacenc.h"
#include "rateconv.h"

/* ---------- declarations ---------- */

#ifndef min
#define min(a,b) ((a) < (b) ? (a) : (b))
#endif
#ifndef min
#define max(a,b) ((a) > (b) ? (a) : (b))
#endif

/* ---------- declarations (structures) ---------- */

#define real	double	/* float seems to be precise enough, but it	*/
			/* doesn't run much faster than double		*/

typedef struct {
	real	re,im;
} complex;


struct RCBufStruct		/* buffer handle */
{
  int numChannel;		/* number of channels */
  long currentSampleIn;		/* number of input samples */
  long currentSampleOut;	/* number of output samples */

  real *wtab;
  complex *x;
  real *tp1;
  real *tp2;
  complex *ibuf;

  long nfn;
  long adv;
  long istart;
  long numode;
  long fm;
  double p1;
  double d1;

  long outSize;
  float *out;
};


/* ---------- variables ---------- */

static int RCdebugLevel = 0;	/* debug level */


#define deftaps1	485

#define ov2exp	7		/* Oversampling exponent in the second step */
#define ov2fac	(1<<ov2exp)	/* Oversampling factor in the second step */
#define htaps2	7		/* Num. taps of the 2nd filter: 2*htaps2+1 */
#define alpha2	12.5		/* Kaiser-parameter for the second filter */
#define cutoff2	0.97		/* cutoff-frequency for the second filter */

#define cexp	(CACHE1-(sizeof(real)==4 ? 3 : 4 ))
#define cache	(1<<cexp)

#define pi	3.1415926535897932
#define zpi	6.2831853071795965


/* ---------- local functions ---------- */


static void mkeiwutab(real *st,long fn)
{
	register int	i,k;
	register double	phi;

	for (k=fn; k; k>>=1)
	{
		phi = zpi/((double) k);
		for (i=0; i<k; i++) st[i]=(real) sin(phi*((double) i));
		st+=k;
	}
}

static void r4fftstep(register real *x0,register long n,register real *t)
{
	register long		n4 = n/4;
	register real		*x1 = x0+2*n4;
	register real		*x2 = x1+2*n4;
	register real		*x3 = x2+2*n4;
	register real		*y;
	register real		wr,wi,ar,ai,br,bi,cr,ci,dr,di,hr,hi;
	register long		i;


	if ( n>16 )
	{
		y=t+6*n4;
		r4fftstep(x0,n4,y);
		r4fftstep(x1,n4,y);
		r4fftstep(x2,n4,y);
		r4fftstep(x3,n4,y);
	}
	else
	{
		if ( n==8 )
		{
			for (y=x0; y<x0+16; y+=4)
			{
				ar=y[0]; ai=y[1];
				br=y[2]; bi=y[3];
				y[0]=ar+br;
				y[1]=ai+bi;
				y[2]=ar-br;
				y[3]=ai-bi;
			}
		}
		else
		{
			for (y=x0; y<x0+32; y+=8)
			{
				ar=y[0]; ai=y[1];
				br=y[2]; bi=y[3];
				cr=y[4]; ci=y[5];
				dr=y[6]; di=y[7];
				hr=ar+cr; wr=ar-cr; hi=ai+ci; wi=ai-ci;
				ar=br+dr; cr=br-dr; ai=bi+di; ci=bi-di;
				y[0]=hr+ar; y[1]=hi+ai;
				y[2]=wr+ci; y[3]=wi-cr;
				y[4]=hr-ar; y[5]=hi-ai;
				y[6]=wr-ci; y[7]=wi+cr;
			}
		}
	}

	y=t+n4;
	for (i=0; i<n4; i++)
	{
		ar=x0[0]; ai=x0[1];
		wr=y[  i]; wi=t[  i]; hr=x1[0]; hi=x1[1]; br=wr*hr+wi*hi; bi=wr*hi-wi*hr;
		wr=y[2*i]; wi=t[2*i]; hr=x2[0]; hi=x2[1]; cr=wr*hr+wi*hi; ci=wr*hi-wi*hr;
		wr=y[3*i]; wi=t[3*i]; hr=x3[0]; hi=x3[1]; dr=wr*hr+wi*hi; di=wr*hi-wi*hr;
		hr=ar+cr; wr=ar-cr; hi=ai+ci; wi=ai-ci;
		ar=br+dr; cr=br-dr; ai=bi+di; ci=bi-di;
		x0[0]=hr+ar; x0[1]=hi+ai;
		x1[0]=wr+ci; x1[1]=wi-cr;
		x2[0]=hr-ar; x2[1]=hi-ai;
		x3[0]=wr-ci; x3[1]=wi+cr;
		x0+=2; x1+=2; x2+=2; x3+=2;
	}
}


static void r4ifftstep(register real *x0,register long n,register real *t)
{
	register long		n4 = n/4;
	register real		*x1 = x0+2*n4;
	register real		*x2 = x1+2*n4;
	register real		*x3 = x2+2*n4;
	register real		*y;
	register real		wr,wi,ar,ai,br,bi,cr,ci,dr,di,hr,hi;
	register long		i;

	if ( n>16 )
	{
		y=t+6*n4;
		r4ifftstep(x0,n4,y);
		r4ifftstep(x1,n4,y);
		r4ifftstep(x2,n4,y);
		r4ifftstep(x3,n4,y);
	}
	else
	{
		if ( n==8 )
		{
			for (y=x0; y<x0+16; y+=4)
			{
				ar=y[0]; ai=y[1];
				br=y[2]; bi=y[3];
				y[0]=ar+br;
				y[1]=ai+bi;
				y[2]=ar-br;
				y[3]=ai-bi;
			}
		}
		else
		{
			for (y=x0; y<x0+32; y+=8)
			{
				ar=y[0]; ai=y[1];
				br=y[2]; bi=y[3];
				cr=y[4]; ci=y[5];
				dr=y[6]; di=y[7];
				hr=ar+cr; wr=ar-cr; hi=ai+ci; wi=ai-ci;
				ar=br+dr; cr=br-dr; ai=bi+di; ci=bi-di;
				y[0]=hr+ar; y[1]=hi+ai;
				y[2]=wr-ci; y[3]=wi+cr;
				y[4]=hr-ar; y[5]=hi-ai;
				y[6]=wr+ci; y[7]=wi-cr;
			}
		}
	}

	y=t+n4;
	for (i=0; i<n4; i++)
	{
		ar=x0[0]; ai=x0[1];
		wr=y[  i]; wi=t[  i]; hr=x1[0]; hi=x1[1]; br=wr*hr-wi*hi; bi=wr*hi+wi*hr;
		wr=y[2*i]; wi=t[2*i]; hr=x2[0]; hi=x2[1]; cr=wr*hr-wi*hi; ci=wr*hi+wi*hr;
		wr=y[3*i]; wi=t[3*i]; hr=x3[0]; hi=x3[1]; dr=wr*hr-wi*hi; di=wr*hi+wi*hr;
		hr=ar+cr; wr=ar-cr; hi=ai+ci; wi=ai-ci;
		ar=br+dr; cr=br-dr; ai=bi+di; ci=bi-di;
		x0[0]=hr+ar; x0[1]=hi+ai;
		x1[0]=wr-ci; x1[1]=wi+cr;
		x2[0]=hr-ar; x2[1]=hi-ai;
		x3[0]=wr+ci; x3[1]=wi-cr;
		x0+=2; x1+=2; x2+=2; x3+=2;
	}
}


static void perm4(real *x,long p)
{
	register real	a,b,c,d;
	register long	i,j,k,l;

	l=1<<(p-1);
	for (i=j=0; i<(2<<p); i+=2)
	{
		if ( j>i )
		{
			a=x[i]; b=x[i+1]; c=x[j]; d=x[j+1]; x[j]=a; x[j+1]=b; x[i]=c; x[i+1]=d;	
		}
		j+=l;
		for (k=l<<2; j&k; k>>=2) j=(j^=k)+(k>>4);
	}
}

static void perm42(real *x,long p)
{
	register real	*y,*z;
	register long	i,n;

	n=1<<p;
	perm4(x  ,p-1);
	perm4(x+n,p-1);

	y=x+2*n;
	z=x+n;
	for (i=0; i<n; i+=2)
	{
		y[2*i  ]=x[i  ];
		y[2*i+1]=x[i+1];
		y[2*i+2]=z[i  ];
		y[2*i+3]=z[i+1];
		x[i  ]=y[i  ];
		x[i+1]=y[i+1];
	}
	for (; i<2*n; i+=2)
	{
		x[i  ]=y[i  ];
		x[i+1]=y[i+1];
	}
}

static void r4fft(real *t,real *x,long p)
{
	register long	n  = 1<<p;

	if ( p&1 ) perm42(x,p); else perm4(x,p);
	r4fftstep(x,n,t);
}

static void r4ifft(real *t,real *x,long p)
{
	register long	n  = 1<<p;

	if ( p&1 ) perm42(x,p); else perm4(x,p);
	r4ifftstep(x,n,t);
}


static double bessel(double x)
{
  register double	p,s,ds,k;

  x*=0.5;
  k=0.0;
  p=s=1.0;
  do
    {
      k+=1.0;
      p*=x/k;
      ds=p*p;
      s+=ds;
    }
  while ( ds>1.0e-17*s ); 

  return s;
}

static void mktp1(complex *y,double fg,double a,long fn,long htaps1)
{
  register long	i;
  register double	f,g,x,px;

  y[0].re=fg;
  y[0].im=0.0;

  f=1.0/bessel(a);
  g=1.0/(htaps1+0.5);
  g*=g;

  for (i=1; i<=htaps1; i++)
    {
      x=(double) i;
      px=pi*x;
      y[i].re=(real) f*bessel(a*sqrt(1.0-g*x*x))*sin(fg*px)/px;
      y[i].im=(real) 0.0;
      y[fn-i]=y[i];
    }
  for (; i<fn-htaps1; i++) y[i].re=y[i].im=0.0;
}

static void mktp2(real *y,double fg,double a)
{
  register long	i;
  register double	f,g,x,px;

  y[0]=fg;

  f=1.0/bessel(a);
  g=1.0/(((double) ((htaps2+1)*ov2fac))-0.5);
  g*=g;

  for (i=1; i<(htaps2+1)*ov2fac; i++)
    {
      x=(double) i;
      px=(pi/ov2fac)*x;
      y[i]=(real) f*bessel(a*sqrt(1.0-g*x*x))*sin(fg*px)/px;
    }
  for (; i<(htaps2+2)*ov2fac; i++) y[i]=0.0;
}

static void ctp2_m(real *x,double p,real *k,float **out)
{
  register long	n,i,j;
  register double	h,l,r;
  register real	*ka,*kb;
  register real	*xa,*xb;

  h=ov2fac*p;
  i=(long) h;
  h-=(double) i;

  j=i&(ov2fac-1); i>>=ov2exp;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -