X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=filter.5c;fp=filter.5c;h=34609ee6108621cd34ddfa9ea1a7a00f99e5bd20;hb=afa1f2dcc7affe9973f7940b6573a99ce27eeab5;hp=0000000000000000000000000000000000000000;hpb=fe458dd5fc2eecdc39f9004883c75335fb21a323;p=fw%2Ftmflights diff --git a/filter.5c b/filter.5c new file mode 100644 index 0000000..34609ee --- /dev/null +++ b/filter.5c @@ -0,0 +1,133 @@ +/* + * 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.β) + }; +} + +