Mercurial > hg > may
changeset 265:c7efd12c27c5
Window fixes and tests
author | Chris Cannam |
---|---|
date | Thu, 23 May 2013 13:21:05 +0100 |
parents | 046a2e323716 |
children | 46d2923a04ab |
files | yetilab/signal/test/test_window.yeti yetilab/signal/window.yeti yetilab/test/all.yeti yetilab/vector/test/test_vector.yeti yetilab/vector/vector.yeti |
diffstat | 5 files changed, 156 insertions(+), 15 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/yetilab/signal/test/test_window.yeti Thu May 23 13:21:05 2013 +0100 @@ -0,0 +1,107 @@ + +module yetilab.signal.test.test_window; + +win = load yetilab.signal.window; +vec = load yetilab.vector.vector; + +{ compare, compareUsing } = load yetilab.test.test; + +functions = [ + Hann () : win.hann, + Hamming () : win.hamming, + Blackman () : win.blackman, + Nuttall () : win.nuttall, + BlackmanNuttall () : win.blackmanNuttall, + BlackmanHarris () : win.blackmanHarris, + Boxcar () : win.boxcar, + Bartlett () : win.bartlett, +]; + +close aa bb = all id (map2 do a b: (abs (a - b) < 0.00001) done aa bb); + +isSymmetric a = + (len = (vec.length a); + b = if len % 2 == 0 then + half = vec.slice a 0 (len/2); + vec.concat [half, vec.reversed half]; + else + half = vec.slice a 0 (int (len/2)); + mid = vec.slice a (int (len/2)) (int (len/2) + 1); + vec.concat [half, mid, vec.reversed half]; + fi; + compareUsing close (vec.list a) (vec.list b)); + +[ + +"windowFunction": \( + all id (map do type: + f = functions[type]; + a = f 10; + b = win.windowFunction type [ Symmetric false ] 10; + compareUsing close (vec.list a) (vec.list b) + or (eprintln "** failed window type: \(type)"; false) + done (keys functions)); +), + +"symmetric-even": \( + len = 10; + all id (map do type: + f = win.windowFunction type [ Symmetric true ]; + v = f len; + (compare (vec.length v) len and isSymmetric v) or + (eprintln "** failed window type: \(type)"; false); + done (keys functions)); +), + +"symmetric-odd": \( + len = 11; + all id (map do type: + f = win.windowFunction type [ Symmetric true ]; + v = f len; + (compare (vec.length v) len and isSymmetric v) or + (eprintln "** failed window type: \(type)"; false); + done (keys functions)); +), + +"periodic-even": \( + // We can't actually test whether a function is periodic, given + // only one cycle of it! But we can make sure that all but the + // first sample is symmetric, which is what a symmetric window + // becomes when generated in periodic mode + len = 10; + all id (map do type: + f = win.windowFunction type [ Symmetric false ]; + v = f len; + (compare (vec.length v) len and isSymmetric (vec.slice v 1 len)) or + (eprintln "** failed window type: \(type)"; false); + done (keys functions)); +), + +"periodic-odd": \( + len = 11; + all id (map do type: + f = win.windowFunction type [ Symmetric false ]; + v = f len; + (compare (vec.length v) len and isSymmetric (vec.slice v 1 len)) or + (eprintln "** failed window type: \(type)"; false); + done (keys functions)); +), + +"bartlett-periodic": \( + compare (vec.list (win.bartlett 1)) [1] and + compare (vec.list (win.bartlett 2)) [0,1] and + compare (vec.list (win.bartlett 3)) [0,2/3,2/3] and + compare (vec.list (win.bartlett 4)) [0,1/2,1,1/2] +), + +"bartlett-symmetric": \( + b = win.windowFunction (Bartlett ()) [ Symmetric true ]; + compare (vec.list (b 1)) [1] and + compare (vec.list (b 2)) [0,0] and + compare (vec.list (b 3)) [0,1,0] and + compare (vec.list (b 4)) [0,2/3,2/3,0] and + compare (vec.list (b 5)) [0,1/2,1,1/2,0] +), + +] is hash<string, () -> boolean>; +
--- a/yetilab/signal/window.yeti Thu May 23 11:21:30 2013 +0100 +++ b/yetilab/signal/window.yeti Thu May 23 13:21:05 2013 +0100 @@ -29,6 +29,34 @@ Periodic (): cosineWindowPeriodic; esac a0 a1 a2 a3 n; +bartlettSymmetric n = + if n < 2 then vec.ones n + else + vec.fromList + (n1 = n - 1; + h = int (n1 / 2); + concat [ + map do i: + 2 * i / n1 + done [0..h], + map do i: + 2 - (2 * i / n1) + done [h+1..n1] + ]); + fi; + +bartlettPeriodic n = + if n < 2 then vec.ones n + else + vec.slice (bartlettSymmetric (n+1)) 0 n; + fi; + +bartlett sampling = + case sampling of + Symmetric (): bartlettSymmetric; + Periodic (): bartlettPeriodic; + esac; + hann = cosineWindow 0.5 0.5 0.0 0.0; hamming = cosineWindow 0.54 0.46 0.0 0.0; blackman = cosineWindow 0.42 0.50 0.08 0.0; @@ -38,19 +66,7 @@ boxcar = vec.consts 0.5; -bartlett n = - vec.fromList - (m = n/2; - concat [ - map do i: - i / m - done [0..m-1], - map do i: - 1.0 - (i / m) - done [0..m-1] - ]); - -windowFunction type options n = +windowFunction type options = (var sampling = Periodic (); for options \case of Symmetric s: if s then sampling := Symmetric () fi @@ -63,7 +79,7 @@ BlackmanNuttall (): blackmanNuttall sampling; BlackmanHarris (): blackmanHarris sampling; Boxcar (): boxcar; - Bartlett (): bartlett; + Bartlett (): bartlett sampling; esac); windowed windowFunc frames = @@ -82,7 +98,8 @@ nuttall = nuttall (Periodic ()), blackmanNuttall = blackmanNuttall (Periodic ()), blackmanHarris = blackmanHarris (Periodic ()), -boxcar, bartlett, +boxcar, +bartlett = bartlett (Periodic ()), windowFunction, windowed };
--- a/yetilab/test/all.yeti Thu May 23 11:21:30 2013 +0100 +++ b/yetilab/test/all.yeti Thu May 23 13:21:05 2013 +0100 @@ -18,6 +18,7 @@ "matrix" : load yetilab.matrix.test.test_matrix, "plot" : load yetilab.plot.test.test_plot, "signal" : load yetilab.signal.test.test_signal, +"window" : load yetilab.signal.test.test_window, ]; bad = sum (mapHash do name testHash: runTests name testHash done tests);
--- a/yetilab/vector/test/test_vector.yeti Thu May 23 11:21:30 2013 +0100 +++ b/yetilab/vector/test/test_vector.yeti Thu May 23 13:21:05 2013 +0100 @@ -90,6 +90,12 @@ vec.equal (vec.resizedTo 2 (vec.fromList [1,2,3])) (vec.fromList [1,2]); ), +"reversed": \( + vec.equal (vec.reversed (vec.fromList [])) (vec.fromList []) and + vec.equal (vec.reversed (vec.fromList [1,2,3])) (vec.fromList [3,2,1]) and + vec.equal (vec.reversed (vec.fromList [1,2])) (vec.fromList [2,1]) +), + "concat2": \( v = vec.fromList [1,2,3]; w = vec.fromList [4,5,6];
--- a/yetilab/vector/vector.yeti Thu May 23 11:21:30 2013 +0100 +++ b/yetilab/vector/vector.yeti Thu May 23 13:21:05 2013 +0100 @@ -77,6 +77,14 @@ resizedTo n v is number -> ~double[] -> ~double[] = Arrays#copyOf(v, n); +reversed v is ~double[] -> ~double[] = + (len = length (list v); + a = new double[len]; + for [0..len-1] do i: + a[len-i-1] := v[i]; + done; + a); + concat vv is list?<~double[]> -> ~double[] = (len = sum (map length' vv); vout = zeros len; @@ -106,6 +114,7 @@ equalUnder, slice, resizedTo, + reversed, concat, } as { zeros is number -> vector, @@ -125,6 +134,7 @@ equalUnder is (number -> number -> boolean) -> vector -> vector -> boolean, slice is vector -> number -> number -> vector, resizedTo is number -> vector -> vector, + reversed is vector -> vector, concat is list?<vector> -> vector, }