/* SoX Resampler Library Copyright (c) 2013 robs@users.sourceforge.net * Licence for this file: LGPL v2.1 See LICENCE for details. */ /* Generate the filter coefficients for variable-rate resampling. */ #include #include #include #define PI 3.14159265358979323846 /* Since M_PI can't be relied on */ static void print(double * h, int m, double l, char const * name) { /* Print out a filter: */ int i, N = l? (int)(l*m)-(l>1) : m, R=(N+1)/2; int a = !l||l>1? 0:N-R, b = l>1? R:N; printf("static float const %s[] = {\n", name); if (l>1) printf(" 0.f,"); else if (!l) l=1; for (i=a; h && i 0 && x E[i] >= x E[i z 1]) #define PEAK do {if (k0)-(E[i]<0);} while (0) typedef struct {double x, beta, gamma;} coef_t; static double amp_response(coef_t * coef, int R, double f, int i) { double n = 0, d = 0, x = cos(PI*f), t; for (; i < R; d += t = coef[i].beta / t, n += coef[i].gamma * t, ++i) if (fabs(t = x - coef[i].x) < 1e-9) return coef[i].gamma; return n/d; } static void fir(int m, double l, double Fp0, double Fs0, double weight0, int density, char const * name) { double Fp=Fp0/l, Fs=Fs0/l, weight=1/weight0, inc[2], Ws=1-Fs; int N = (int)(l*m)-(l>1), R=(N+1)/2, NP=R+1, grid_size=1+density*R+1, pass=0; int n1 = Ws>=(2*R-1)*Fp? 1:(int)(R*Fp/(Fp+Ws)+.5), n2=NP-n1, _1, i, j, k; int * peak = calloc(sizeof(*peak), (size_t)(NP+1)), * P=peak, end[2]; coef_t * coef = calloc(sizeof(*coef), (size_t)(NP)); float * E = calloc(sizeof(*E ), (size_t)(grid_size)); double d, n, e, f, mult, delta, sum, hi, lo, * A = (double*)E, *h=0; if (!P || !coef || !E) goto END; end[0] = n1 * density, end[1] = grid_size-1; /* Create prototype peaks: */ inc[0] = Fp/end[0], inc[1] = n2==1? 0 : Ws / ((n2-1)*density); for (i=0; iE[i+1]) || (EE(-,-) && E[i] 1) goto END; /* Too many/few? */ P = peak + k * (fabs(E[peak[0]]) < fabs(E[peak[NP]])); /* rm 1st? */ for (lo = hi = fabs(E[P[0]]), i=1; ihi? e:hi; } while ((hi-lo)/hi > .001 && ++pass < 20); /* Create impulse response from final amp. resp. coefs: */ if (!(h = malloc(sizeof(*h)*(size_t)N))) goto END; for (i = 0; i < R; f = 2.*i/N, A[i++] = amp_response(coef,R,f,0)*even_adj(f)); for (i = 0; i < R; h[N-1-i] = h[i] = sum/N, ++i) for (sum=*A, j=1; j