resample.c

来自「基于sip协议的网络电话源码」· C语言 代码 · 共 705 行 · 第 1/2 页

C
705
字号
/* $Id: resample.c 974 2007-02-19 01:13:53Z bennylp $ *//*  * Copyright (C) 2003-2007 Benny Prijono <benny@prijono.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  *//* * Based on: * resample-1.8.tar.gz from the  * Digital Audio Resampling Home Page located at * http://www-ccrma.stanford.edu/~jos/resample/. * * SOFTWARE FOR SAMPLING-RATE CONVERSION AND FIR DIGITAL FILTER DESIGN * * Snippet from the resample.1 man page: *  * HISTORY * * The first version of this software was written by Julius O. Smith III * <jos@ccrma.stanford.edu> at CCRMA <http://www-ccrma.stanford.edu> in * 1981.  It was called SRCONV and was written in SAIL for PDP-10 * compatible machines.  The algorithm was first published in *  * Smith, Julius O. and Phil Gossett. ``A Flexible Sampling-Rate * Conversion Method,'' Proceedings (2): 19.4.1-19.4.4, IEEE Conference * on Acoustics, Speech, and Signal Processing, San Diego, March 1984. *  * An expanded tutorial based on this paper is available at the Digital * Audio Resampling Home Page given above. *  * Circa 1988, the SRCONV program was translated from SAIL to C by * Christopher Lee Fraley working with Roger Dannenberg at CMU. *  * Since then, the C version has been maintained by jos. *  * Sndlib support was added 6/99 by John Gibson <jgg9c@virginia.edu>. *  * The resample program is free software distributed in accordance * with the Lesser GNU Public License (LGPL).  There is NO warranty; not * even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *//* PJMEDIA modification: *  - remove resample(), just use SrcUp, SrcUD, and SrcLinear directly. *  - move FilterUp() and FilterUD() from filterkit.c *  - move stddefs.h and resample.h to this file. *  - const correctness. */#include <pjmedia/resample.h>#include <pjmedia/errno.h>#include <pj/assert.h>#include <pj/log.h>#include <pj/pool.h>#define THIS_FILE   "resample.c"/* * Taken from stddefs.h */#ifndef PI#define PI (3.14159265358979232846)#endif#ifndef PI2#define PI2 (6.28318530717958465692)#endif#define D2R (0.01745329348)          /* (2*pi)/360 */#define R2D (57.29577951)            /* 360/(2*pi) */#ifndef MAX#define MAX(x,y) ((x)>(y) ?(x):(y))#endif#ifndef MIN#define MIN(x,y) ((x)<(y) ?(x):(y))#endif#ifndef ABS#define ABS(x)   ((x)<0   ?(-(x)):(x))#endif#ifndef SGN#define SGN(x)   ((x)<0   ?(-1):((x)==0?(0):(1)))#endiftypedef char           RES_BOOL;typedef short          RES_HWORD;typedef int            RES_WORD;typedef unsigned short RES_UHWORD;typedef unsigned int   RES_UWORD;#define MAX_HWORD (32767)#define MIN_HWORD (-32768)#ifdef DEBUG#define INLINE#else#define INLINE inline#endif/* * Taken from resample.h * * The configuration constants below govern * the number of bits in the input sample and filter coefficients, the  * number of bits to the right of the binary-point for fixed-point math, etc. * *//* Conversion constants */#define Nhc       8#define Na        7#define Np       (Nhc+Na)#define Npc      (1<<Nhc)#define Amask    ((1<<Na)-1)#define Pmask    ((1<<Np)-1)#define Nh       16#define Nb       16#define Nhxn     14#define Nhg      (Nh-Nhxn)#define NLpScl   13/* Description of constants: * * Npc - is the number of look-up values available for the lowpass filter *    between the beginning of its impulse response and the "cutoff time" *    of the filter.  The cutoff time is defined as the reciprocal of the *    lowpass-filter cut off frequence in Hz.  For example, if the *    lowpass filter were a sinc function, Npc would be the index of the *    impulse-response lookup-table corresponding to the first zero- *    crossing of the sinc function.  (The inverse first zero-crossing *    time of a sinc function equals its nominal cutoff frequency in Hz.) *    Npc must be a power of 2 due to the details of the current *    implementation. The default value of 512 is sufficiently high that *    using linear interpolation to fill in between the table entries *    gives approximately 16-bit accuracy in filter coefficients. * * Nhc - is log base 2 of Npc. * * Na - is the number of bits devoted to linear interpolation of the *    filter coefficients. * * Np - is Na + Nhc, the number of bits to the right of the binary point *    in the integer "time" variable. To the left of the point, it indexes *    the input array (X), and to the right, it is interpreted as a number *    between 0 and 1 sample of the input X.  Np must be less than 16 in *    this implementation. * * Nh - is the number of bits in the filter coefficients. The sum of Nh and *    the number of bits in the input data (typically 16) cannot exceed 32. *    Thus Nh should be 16.  The largest filter coefficient should nearly *    fill 16 bits (32767). * * Nb - is the number of bits in the input data. The sum of Nb and Nh cannot *    exceed 32. * * Nhxn - is the number of bits to right shift after multiplying each input *    sample times a filter coefficient. It can be as great as Nh and as *    small as 0. Nhxn = Nh-2 gives 2 guard bits in the multiply-add *    accumulation.  If Nhxn=0, the accumulation will soon overflow 32 bits. * * Nhg - is the number of guard bits in mpy-add accumulation (equal to Nh-Nhxn) * * NLpScl - is the number of bits allocated to the unity-gain normalization *    factor.  The output of the lowpass filter is multiplied by LpScl and *    then right-shifted NLpScl bits. To avoid overflow, we must have  *    Nb+Nhg+NLpScl < 32. */#ifdef _MSC_VER#   pragma warning(push, 3)//#   pragma warning(disable: 4245)   // Conversion from uint to ushort#   pragma warning(disable: 4244)   // Conversion from double to uint#   pragma warning(disable: 4146)   // unary minus operator applied to unsigned type, result still unsigned#   pragma warning(disable: 4761)   // integral size mismatch in argument; conversion supplied#endif#if defined(PJMEDIA_HAS_SMALL_FILTER) && PJMEDIA_HAS_SMALL_FILTER!=0#   include "smallfilter.h"#else#   define SMALL_FILTER_NMULT	0#   define SMALL_FILTER_SCALE	0#   define SMALL_FILTER_NWING	0#   define SMALL_FILTER_IMP	NULL#   define SMALL_FILTER_IMPD	NULL#endif#if defined(PJMEDIA_HAS_LARGE_FILTER) && PJMEDIA_HAS_LARGE_FILTER!=0#   include "largefilter.h"#else#   define LARGE_FILTER_NMULT	0#   define LARGE_FILTER_SCALE	0#   define LARGE_FILTER_NWING	0#   define LARGE_FILTER_IMP	NULL#   define LARGE_FILTER_IMPD	NULL#endif#undef INLINE#define INLINE#define HAVE_FILTER 0    #ifndef NULL#   define NULL	0#endifstatic INLINE RES_HWORD WordToHword(RES_WORD v, int scl){    RES_HWORD out;    RES_WORD llsb = (1<<(scl-1));    v += llsb;		/* round */    v >>= scl;    if (v>MAX_HWORD) {	v = MAX_HWORD;    } else if (v < MIN_HWORD) {	v = MIN_HWORD;    }	    out = (RES_HWORD) v;    return out;}/* Sampling rate conversion using linear interpolation for maximum speed. */static int   SrcLinear(const RES_HWORD X[], RES_HWORD Y[], double pFactor, RES_UHWORD nx){    RES_HWORD iconst;    RES_UWORD time = 0;    const RES_HWORD *xp;    RES_HWORD *Ystart, *Yend;    RES_WORD v,x1,x2;        double dt;                  /* Step through input signal */     RES_UWORD dtb;                  /* Fixed-point version of Dt */    RES_UWORD endTime;              /* When time reaches EndTime, return to user */        dt = 1.0/pFactor;            /* Output sampling period */    dtb = dt*(1<<Np) + 0.5;     /* Fixed-point representation */        Ystart = Y;    Yend = Ystart + (unsigned)(nx * pFactor);    endTime = time + (1<<Np)*(RES_WORD)nx;    while (time < endTime)    {	iconst = (time) & Pmask;	xp = &X[(time)>>Np];      /* Ptr to current input sample */	x1 = *xp++;	x2 = *xp;	x1 *= ((1<<Np)-iconst);	x2 *= iconst;	v = x1 + x2;	*Y++ = WordToHword(v,Np);   /* Deposit output */	time += dtb;		    /* Move to next sample by time increment */    }    return (Y - Ystart);            /* Return number of output samples */}static RES_WORD FilterUp(const RES_HWORD Imp[], const RES_HWORD ImpD[], 		     RES_UHWORD Nwing, RES_BOOL Interp,		     const RES_HWORD *Xp, RES_HWORD Ph, RES_HWORD Inc){    const RES_HWORD *Hp;    const RES_HWORD *Hdp = NULL;    const RES_HWORD *End;    RES_HWORD a = 0;    RES_WORD v, t;        v=0;    Hp = &Imp[Ph>>Na];    End = &Imp[Nwing];    if (Interp) {	Hdp = &ImpD[Ph>>Na];	a = Ph & Amask;    }    if (Inc == 1)		/* If doing right wing...              */    {				/* ...drop extra coeff, so when Ph is  */	End--;			/*    0.5, we don't do too many mult's */	if (Ph == 0)		/* If the phase is zero...           */	{			/* ...then we've already skipped the */	    Hp += Npc;		/*    first sample, so we must also  */	    Hdp += Npc;		/*    skip ahead in Imp[] and ImpD[] */	}    }    if (Interp)      while (Hp < End) {	  t = *Hp;		/* Get filter coeff */	  t += (((RES_WORD)*Hdp)*a)>>Na; /* t is now interp'd filter coeff */	  Hdp += Npc;		/* Filter coeff differences step */	  t *= *Xp;		/* Mult coeff by input sample */	  if (t & (1<<(Nhxn-1)))  /* Round, if needed */	    t += (1<<(Nhxn-1));	  t >>= Nhxn;		/* Leave some guard bits, but come back some */	  v += t;			/* The filter output */	  Hp += Npc;		/* Filter coeff step */	  Xp += Inc;		/* Input signal step. NO CHECK ON BOUNDS */      }     else       while (Hp < End) {	  t = *Hp;		/* Get filter coeff */	  t *= *Xp;		/* Mult coeff by input sample */	  if (t & (1<<(Nhxn-1)))  /* Round, if needed */	    t += (1<<(Nhxn-1));	  t >>= Nhxn;		/* Leave some guard bits, but come back some */	  v += t;			/* The filter output */	  Hp += Npc;		/* Filter coeff step */	  Xp += Inc;		/* Input signal step. NO CHECK ON BOUNDS */      }    return(v);}static RES_WORD FilterUD(const RES_HWORD Imp[], const RES_HWORD ImpD[],		     RES_UHWORD Nwing, RES_BOOL Interp,		     const RES_HWORD *Xp, RES_HWORD Ph, RES_HWORD Inc, RES_UHWORD dhb){    RES_HWORD a;    const RES_HWORD *Hp, *Hdp, *End;    RES_WORD v, t;    RES_UWORD Ho;        v=0;    Ho = (Ph*(RES_UWORD)dhb)>>Np;    End = &Imp[Nwing];    if (Inc == 1)		/* If doing right wing...              */    {				/* ...drop extra coeff, so when Ph is  */	End--;			/*    0.5, we don't do too many mult's */	if (Ph == 0)		/* If the phase is zero...           */	  Ho += dhb;		/* ...then we've already skipped the */    }				/*    first sample, so we must also  */				/*    skip ahead in Imp[] and ImpD[] */    if (Interp)      while ((Hp = &Imp[Ho>>Na]) < End) {	  t = *Hp;		/* Get IR sample */	  Hdp = &ImpD[Ho>>Na];  /* get interp (lower Na) bits from diff table*/	  a = Ho & Amask;	/* a is logically between 0 and 1 */

⌨️ 快捷键说明

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