changeset 398:3b44bfd23352 resample

Separate out Kaiser window parameter calculation
author Chris Cannam
date Thu, 26 Sep 2013 14:47:27 +0100
parents aa08b26d4a83
children ac828725aeae
files src/may/signal/test/test_window.yeti src/may/signal/window.yeti
diffstat 2 files changed, 50 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/src/may/signal/test/test_window.yeti	Thu Sep 26 14:46:36 2013 +0100
+++ b/src/may/signal/test/test_window.yeti	Thu Sep 26 14:47:27 2013 +0100
@@ -165,11 +165,11 @@
 ),
 
 "kaiser": \(
-    compareUsing close (vec.list (win.kaiser 4 10)) [
+    compareUsing close (vec.list (win.kaiser { beta = 4, length = 10 })) [
         0.0885, 0.2943, 0.5644, 0.8216, 0.9789,
         0.9789, 0.8216, 0.5644, 0.2943, 0.0885
     ] and
-    compareUsing close (vec.list (win.kaiser 2.5 11)) [
+    compareUsing close (vec.list (win.kaiser { beta = 2.5, length = 11 })) [
         0.3040, 0.5005, 0.6929, 0.8546, 0.9622,
         1.0000, 0.9622, 0.8546, 0.6929, 0.5005, 0.3040
     ]
--- a/src/may/signal/window.yeti	Thu Sep 26 14:46:36 2013 +0100
+++ b/src/may/signal/window.yeti	Thu Sep 26 14:47:27 2013 +0100
@@ -97,7 +97,8 @@
         vec.fromList ((take n0 (reverse half)) ++ (take n1 half));
     fi;
 
-kaiser beta n =
+//!!! if kaiser is going to take a structure, so I guess should sinc and cosineWindow
+kaiser { length, beta } =
    (bes0 x = 
        (fact x = fold do x y: x*y done 1 [1..x];   // x!
         ipow a b = fold do x _: x*a done 1 [1..b]; // a^b where b∈ℕ
@@ -109,40 +110,66 @@
             esac;
         sum (map (term x) [0..20]));
     denominator = bes0 beta;
-    vec.fromList
+    kw = vec.fromList
        (map do i:
-            k = 2*i / (n-1) - 1;
+            k = 2*i / (length-1) - 1;
             bes0 (beta * sqrt (1 - k*k)) / denominator;
-            done [0..n-1]));
+            done [0..length-1]);
+    println "kaiser: peak is \(bf.max kw) at index \(bf.maxindex kw) of \(vec.length kw)";
+    kw);
+
+/**
+ * Calculate beta and length for a Kaiser window with the given
+ * sidelobe attentuation and either transition width (in samples) or
+ * samplerate plus transition bandwidth (in Hz).
+ */
+kaiserParameters options =
+    case options of
+    ByTransitionWidth { attenuation, transition }:
+       (m = if attenuation > 21 
+            then Math#ceil((attenuation - 7.95) / (2.285 * transition))
+            else Math#ceil(5.79 / transition)
+            fi;
+        beta =
+            if attenuation > 50 then 0.1102 * (attenuation - 8.7)
+            elif attenuation > 21 then
+                0.5842 * Math#pow(attenuation - 21, 0.4) +
+                0.07886 * (attenuation - 21)
+            else 0
+            fi;
+        { length = m + 1, beta });
+    ByFrequency { attenuation, bandwidth, samplerate }:
+        kaiserParameters
+           (ByTransitionWidth
+            { attenuation, transition = ((bandwidth * 2 * pi) / samplerate) }
+            );
+    esac;
 
 /** 
   Kaiser window with sidelobe attenuation of alpha dB and window length n
 */
 kaiserForAttenuation alpha n =
-   (beta =
-        if alpha > 50 then 0.1102 * (alpha - 8.7)
-        elif alpha > 21 then 0.5842 * Math#pow(alpha - 21, 0.4) + 0.07886 * (alpha - 21)
-        else 0
-        fi;
-    kaiser beta n);
+   (pp = kaiserParameters
+       (ByTransitionWidth { attenuation = alpha, transition = 1 });
+    kaiser (pp with { length = n }));
 
 /**
   Kaiser window with sidelobe attenuation of alpha dB and transition 
-  bandwidth of (tw * samplerate) / (2 * pi)
+  bandwidth of (tw * samplerate) / (2 * pi).
 */
-kaiserForTransitionLength alpha tw =
-   (m = if alpha > 21 
-        then Math#ceil((alpha - 7.95) / (2.285 * tw))
-        else Math#ceil(5.79 / tw)
-        fi;
-    kaiserForAttenuation alpha (m+1));
+kaiserForTransitionWidth alpha tw =
+    kaiser
+       (kaiserParameters
+           (ByTransitionWidth { attenuation = alpha, transition = tw }));
 
 /**
   Kaiser window with sidelobe attenuation of alpha dB and transition
   bandwidth of tbw Hz at the given sampleRate
 */
 kaiserForBandwidth alpha tbw samplerate =
-    kaiserForTransitionLength alpha ((tbw * 2 * pi) / samplerate);
+    kaiser
+       (kaiserParameters
+           (ByFrequency { attenuation = alpha, bandwidth = tbw, samplerate }));
 
 windowFunction type options =
    (var sampling = Periodic ();
@@ -160,7 +187,7 @@
     BlackmanHarris (): blackmanHarris sampling;
     Boxcar (): boxcar;
     Bartlett (): bartlett sampling;
-    Kaiser (): kaiser beta;
+    Kaiser (): do length: kaiser { beta, length } done;
     esac);
 
 //!!! should use vector. but does anyone use this function anyway? would we use it in framer if it used vector?
@@ -184,7 +211,8 @@
 bartlett = bartlett (Periodic ()), 
 dirac,
 sinc,
-kaiser, kaiserForAttenuation, kaiserForTransitionLength, kaiserForBandwidth,
+kaiser, kaiserParameters,
+kaiserForAttenuation, kaiserForTransitionWidth, kaiserForBandwidth,
 windowFunction,
 windowed
 };