restructure files into directories by year and "Misc" to ease testing with current...
[fw/tmflights] / Misc / filter.5c
diff --git a/Misc/filter.5c b/Misc/filter.5c
new file mode 100644 (file)
index 0000000..34609ee
--- /dev/null
@@ -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.β)
+    };
+}
+
+