/* * Kaiser Window digital filter * * Copyright © 2001, Keith Packard * All Rights Reserved. See the file COPYING in this directory * for licensing information. */ real i0(real x) { real ds, d, s; ds = 1; d = 0; s = 0; do { d = d + 2; ds = ds * x**2 / d**2; s = s + ds; # printf ("ds %g s %g dist %g\n", ds, s, # ds - 0.2e-8 * s); } while (ds - 0.2e-8 * s > 0); return s; } real highpass (real n, real m, real wc) { real alpha = m/2; real dist; dist = n - alpha; if (dist == 0) return (pi/2 - wc) / pi; return -sin(dist * (pi/2-wc)) / (pi * dist); } real lowpass (real n, real m, real wc) { real alpha = m/2; real dist; dist = n - alpha; if (dist == 0) return wc / pi; return sin (wc * dist) / (pi * dist); } real kaiser (real n, real m, real beta) { real alpha = m / 2; return i0 (beta * sqrt (1 - ((n - alpha) / alpha)**2)) / i0(beta); } void write_high (string filename, real m, real wc, real beta, real step) { real n; file f; f = File::open (filename, "w"); for (n = 0; n <= m; n += step) File::fprintf (f, "%g,\n", highpass (n, m, wc) * kaiser (n, m, beta)); File::close (f); } void write_low (string filename, real m, real wc, real beta, real step) { real n; file f; f = File::open (filename, "w"); for (n = 0; n <= m; n += step) File::fprintf (f, "%g,\n", lowpass (n, m, wc) * kaiser (n, m, beta)); File::close (f); } real β (real A) { if (A > 50) return 0.1102 * (A - 8.7); else if (A >= 21) return 0.5842 * (A - 21) ** 0.4 + 0.07886 * (A - 21); else return 0.0; } int M (real A, real Δω) { if (A > 21) return ceil ((A - 7.95) / (2.285 * Δω)); else return ceil(5.79 / Δω); } typedef struct { real ωpass; real Δω; real A; real β; int M; } filter_param_t; filter_param_t filter (real ωpass, real ωstop, real error) { filter_param_t p; p.ωpass = ωpass; p.Δω = ωstop - ωpass; p.A = -20 * log10 (error); p.β = β (p.A); p.M = M (p.A, p.Δω); if ((p.M & 1) == 1) p.M++; return p; } real[] low_pass_filter(real ωpass, real ωstop, real error) { filter_param_t p = filter(ωpass, ωstop, error); return (real[p.M + 1]) { [n] = lowpass(n, p.M, ωpass) * kaiser(n, p.M, p.β) }; }