2 * Copyright © 2009 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23 static inline double sqr (double x) { return x * x; }
26 * Kaiser Window digital filter
30 /* not used in this program */
31 static double highpass (double n, double m, double wc)
38 return (M_PI/2 - wc) / M_PI;
39 return -sin(dist * (M_PI/2-wc)) / (M_PI * dist);
43 static double lowpass (double n, double m, double wc)
50 return sin (wc * dist) / (M_PI * dist);
53 static double kaiser (double n, double m, double beta)
56 return i0 (beta * sqrt (1 - sqr((n - alpha) / alpha))) / i0(beta);
59 static double beta (double A)
62 return 0.1102 * (A - 8.7);
64 return 0.5842 * pow((A - 21), 0.4) + 0.07886 * (A - 21);
69 static int M (double A, double delta_omega)
72 return ceil ((A - 7.95) / (2.285 * delta_omega));
74 return ceil(5.79 / delta_omega);
85 static struct filter_param
86 filter (double omega_pass, double omega_stop, double error)
88 struct filter_param p;
89 p.omega_pass = omega_pass;
90 p.delta_omega = omega_stop - omega_pass;
91 p.A = -20 * log10 (error);
93 p.M = M (p.A, p.delta_omega);
100 make_low_pass_filter(double omega_pass, double omega_stop, double error, int *length_p)
102 struct filter_param p = filter(omega_pass, omega_stop, error);
108 lpf = calloc (length, sizeof(double));
109 for (n = 0; n < length; n++)
110 lpf[n] = lowpass(n, p.M, omega_pass) * kaiser(n, p.M, p.beta);
116 convolve(double *d, int d_len, double *e, int e_len)
118 int w = (e_len - 1) / 2;
120 double *con = calloc (d_len, sizeof (double));
122 for (n = 0; n < d_len; n++) {
125 for (o = -w; o <= w; o++) {
127 double sample = p < 0 ? d[0] : p >= d_len ? d[d_len-1] : d[p];
128 v += sample * e[o + w];
136 cc_low_pass(double *data, int data_len, double omega_pass, double omega_stop, double error)
139 double *fir = make_low_pass_filter(omega_pass, omega_stop, error, &fir_len);
142 result = convolve(data, data_len, fir, fir_len);