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 + -
显示快捷键?