resample.c
来自「linux下录音程序」· C语言 代码 · 共 681 行 · 第 1/2 页
C
681 行
/* * July 5, 1991 * Copyright 1991 Lance Norskog And Sundry Contributors * This source code is freely redistributable and may be used for * any purpose. This copyright notice must be maintained. * Lance Norskog And Sundry Contributors are not responsible for * the consequences of using this software. *//* * Sound Tools rate change effect file. * Spiffy rate changer using Smith & Wesson Bandwidth-Limited Interpolation. * The algorithm is described in "Bandlimited Interpolation - * Introduction and Algorithm" by Julian O. Smith III. * Available on ccrma-ftp.stanford.edu as * pub/BandlimitedInterpolation.eps.Z or similar. * * The latest stand alone version of this algorithm can be found * at ftp://ccrma-ftp.stanford.edu/pub/NeXT/ * under the name of resample-version.number.tar.Z * * NOTE: This source badly needs to be updated to reflect the latest * version of the above software! Someone please perform this and * send patches to cbagwell@sprynet.com. */#include <math.h>#include <stdlib.h>#include "st.h"/* resample includes */#include "resdefs.h"#include "resampl.h"#define IBUFFSIZE 1024 /* Input buffer size */#define OBUFFSIZE (IBUFFSIZE*MAXFACTOR+2) /* Calc'd out buffer size *//* Private data for Lerp via LCM file */typedef struct resamplestuff { double Factor; /* Factor = Fout/Fin sample rates */ double rolloff; /* roll-off frequency */ double beta; /* passband/stopband tuning magic */ short InterpFilt; /* TRUE means interpolate filter coeffs */ UHWORD Oskip; /* number of bogus output samples at start */ UHWORD LpScl, Nmult, Nwing; HWORD *Imp; /* impulse [MAXNWING] Filter coefficients */ HWORD *ImpD; /* [MAXNWING] ImpD[n] = Imp[n+1]-Imp[n] */ /* for resample main loop */ UWORD Time; /* Current time/pos in input sample */ UHWORD Xp, Xoff, Xread; HWORD *X, *Y; /* I/O buffers */} *resample_t;int makeFilter(P6(HWORD Imp[], HWORD ImpD[], UHWORD *LpScl, UHWORD Nwing, double Froll, double Beta));HWORD SrcUp(P10(HWORD X[], HWORD Y[], double Factor, UWORD *Time, UHWORD Nx, UHWORD Nwing, UHWORD LpScl, HWORD Imp[], HWORD ImpD[], BOOL Interp));HWORD SrcUD(P10(HWORD X[], HWORD Y[], double Factor, UWORD *Time, UHWORD Nx, UHWORD Nwing, UHWORD LpScl, HWORD Imp[], HWORD ImpD[], BOOL Interp));IWORD FilterUp(P7(HWORD Imp[], HWORD ImpD[], UHWORD Nwing, BOOL Interp, HWORD *Xp, HWORD Ph, HWORD Inc));IWORD FilterUD(P8(HWORD Imp[], HWORD ImpD[], UHWORD Nwing, BOOL Interp, HWORD *Xp, HWORD Ph, HWORD Inc, UHWORD dhb));/* * Process options */void resample_getopts(effp, n, argv) eff_t effp;int n;char **argv;{ resample_t resample = (resample_t) effp->priv; resample->rolloff = 0.85; resample->beta = 2.120; /* I don't know why this fails! */ if ((n >= 1) && !sscanf(argv[0], "%lf", &resample->rolloff)) fail("Usage: resample [ rolloff [ beta ] ]"); else if ((resample->rolloff < 0.01) || (resample->rolloff > 1.0)) fail("resample: rolloff factor (%f) no good, should be 0.01<x<1.0", resample->rolloff); if ((n >= 2) && !sscanf(argv[1], "%lf", &resample->beta)) fail("Usage: resample [ rolloff [ beta ] ]"); else if (resample->beta < 1.0) fail("resample: beta factor (%f) no good, should be >= 1.0", resample->beta); /* fprintf(stderr, "resample opts: %f, %f\n", resample->rolloff, resample->beta); */}/* * Prepare processing. */void resample_start(effp)eff_t effp;{ resample_t resample = (resample_t) effp->priv; int i; if ((LONG)effp->ininfo.rate > (LONG)effp->outinfo.rate) resample->rolloff = ((double)effp->outinfo.rate / (double)effp->ininfo.rate) * 0.97; /* empirical */ else resample->rolloff = 0.85; resample->InterpFilt = 1; /* interpolate filter: slower */ resample->Factor = (double)effp->outinfo.rate / (double)effp->ininfo.rate; /* Check for illegal constants */ if (Np >= 16) fail("Error: Np>=16"); if (Nb+Nhg+NLpScl >= 32) fail("Error: Nb+Nhg+NLpScl>=32"); if (Nh+Nb > 32) fail("Error: Nh+Nb>32"); resample->Imp = (HWORD *) malloc(sizeof(HWORD) * MAXNWING); resample->ImpD = (HWORD *) malloc(sizeof(HWORD) * MAXNWING); resample->X = (HWORD *) malloc(sizeof(HWORD) * IBUFFSIZE); resample->Y = (HWORD *) malloc(sizeof(HWORD) * OBUFFSIZE); /* upsampling requires smaller Nmults */ for(resample->Nmult = 37; resample->Nmult > 1; resample->Nmult -= 2) { /* # of filter coeffs in right wing */ resample->Nwing = Npc*(resample->Nmult+1)/2; /* This prevents just missing last coeff */ /* for integer conversion factors */ resample->Nwing += Npc/2 + 1; /* returns error # or 0 for success */ if (makeFilter(resample->Imp, resample->ImpD, &resample->LpScl, resample->Nwing, resample->rolloff, resample->beta)) continue; else break; } if(resample->Nmult == 1) fail("resample: Unable to make filter\n"); if (resample->Factor < 1) resample->LpScl = resample->LpScl*resample->Factor + 0.5; /* Calc reach of LP filter wing & give some creeping room */ resample->Xoff = ((resample->Nmult+1)/2.0) * MAX(1.0,1.0/resample->Factor) + 10; if (IBUFFSIZE < 2*resample->Xoff) /* Check input buffer size */ fail("IBUFFSIZE (or Factor) is too small"); /* Current "now"-sample pointer for input */ resample->Xp = resample->Xoff; /* Position in input array to read into */ resample->Xread = resample->Xoff; /* Current-time pointer for converter */ resample->Time = (resample->Xoff<<Np); /* Set sample drop at beginning */ resample->Oskip = resample->Xread * resample->Factor; /* Need Xoff zeros at begining of sample */ for (i=0; i<resample->Xoff; i++) resample->X[i] = 0;}/* * Processed signed long samples from ibuf to obuf. * Return number of samples processed. */void resample_flow(effp, ibuf, obuf, isamp, osamp)eff_t effp;LONG *ibuf, *obuf;LONG *isamp, *osamp;{ resample_t resample = (resample_t) effp->priv; LONG i, last, creep, Nout, Nx; UHWORD Nproc; /* constrain amount we actually process */ Nproc = IBUFFSIZE - resample->Xp; if (Nproc * resample->Factor >= OBUFFSIZE) Nproc = OBUFFSIZE / resample->Factor; if (Nproc * resample->Factor >= *osamp) Nproc = *osamp / resample->Factor; Nx = Nproc - resample->Xread; if (Nx <= 0) fail("Nx negative: %d", Nx); if (Nx > *isamp) { Nx = *isamp; } for(i = resample->Xread; i < Nx + resample->Xread ; i++) resample->X[i] = RIGHT(*ibuf++ + 0x8000, 16); last = i; Nproc = last - (resample->Xoff * 2); for(; i < last + resample->Xoff ; i++) resample->X[i] = 0; /* If we're draining out a buffer tail, * just do it next time or in drain. */ if ((Nx == *isamp) && (Nx <= resample->Xoff)) { /* fill in starting here next time */ resample->Xread = last; /* leave *isamp alone, we consumed it */ *osamp = 0; return; } /* SrcUp() is faster if we can use it */ if (resample->Factor > 1) /* Resample stuff in input buffer */ Nout = SrcUp(resample->X, resample->Y, resample->Factor, &resample->Time, Nproc, resample->Nwing, resample->LpScl, resample->Imp, resample->ImpD, resample->InterpFilt); else Nout = SrcUD(resample->X, resample->Y, resample->Factor, &resample->Time, Nproc, resample->Nwing, resample->LpScl, resample->Imp, resample->ImpD, resample->InterpFilt); /* Move converter Nproc samples back in time */ resample->Time -= (Nproc<<Np); /* Advance by number of samples processed */ resample->Xp += Nproc; /* Calc time accumulation in Time */ creep = (resample->Time>>Np) - resample->Xoff; if (creep) { resample->Time -= (creep<<Np); /* Remove time accumulation */ resample->Xp += creep; /* and add it to read pointer */ } /* Copy back portion of input signal that must be re-used */ for (i=0; i<last - resample->Xp + resample->Xoff; i++) resample->X[i] = resample->X[i + resample->Xp - resample->Xoff]; /* Pos in input buff to read new data into */ resample->Xread = i; resample->Xp = resample->Xoff; /* copy to output buffer, zero-filling beginning */ /* zero-fill to preserve length and loop points */ for(i = 0; i < resample->Oskip; i++) { *obuf++ = 0; } for(i = resample->Oskip; i < Nout + resample->Oskip; i++) { *obuf++ = LEFT(resample->Y[i], 16); } *isamp = Nx; *osamp = Nout; resample->Oskip = 0;}/* * Process tail of input samples. */void resample_drain(effp, obuf, osamp)eff_t effp;ULONG *obuf;ULONG *osamp;{ resample_t resample = (resample_t) effp->priv; LONG i, Nout; UHWORD Nx; Nx = resample->Xread - resample->Xoff; if (Nx <= resample->Xoff * 2) { /* zero-fill end */ for(i = 0; i < resample->Xoff; i++) *obuf++ = 0; *osamp = resample->Xoff; return; } if (Nx * resample->Factor >= *osamp) fail("resample_drain: Overran output buffer!\n"); /* fill out end with zeros */ for(i = 0; i < resample->Xoff; i++) resample->X[i + resample->Xread] = 0; /* SrcUp() is faster if we can use it */ if (resample->Factor >= 1) /* Resample stuff in input buffer */ Nout = SrcUp(resample->X, resample->Y, resample->Factor, &resample->Time, Nx, resample->Nwing, resample->LpScl, resample->Imp, resample->ImpD, resample->InterpFilt); else Nout = SrcUD(resample->X, resample->Y, resample->Factor, &resample->Time, Nx, resample->Nwing, resample->LpScl, resample->Imp, resample->ImpD, resample->InterpFilt); for(i = resample->Oskip; i < Nout; i++) { *obuf++ = LEFT(resample->Y[i], 16);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?