changeset 279:3aacfde637fd

Simplistic convolution implementation and (currently failing) tests
author Chris Cannam
date Mon, 27 May 2013 23:37:57 +0100
parents 704c58ab4598
children 7f000ae124db
files yetilab/stream/filter.yeti yetilab/stream/syntheticstream.yeti yetilab/stream/test/test_filter.yeti
diffstat 3 files changed, 53 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/yetilab/stream/filter.yeti	Sat May 25 18:42:01 2013 +0100
+++ b/yetilab/stream/filter.yeti	Mon May 27 23:37:57 2013 +0100
@@ -3,8 +3,10 @@
 
 mat = load yetilab.matrix;
 ch = load yetilab.stream.channels;
+vec = load yetilab.vector;
 
 load yetilab.stream.type;
+load yetilab.vector.type;
 
 minDurationOf d1 d2 =
     case d1 of 
@@ -257,7 +259,38 @@
             }
             done [1..copies];
     fi;
-                        
+
+convolvedWith ir s = //!!! currently ir is single channel vector only; very slow
+   (var buffer = mat.toRowMajor
+       (mat.zeroMatrix { rows = s.channels, columns = vec.length ir });
+    s with 
+    {
+        get available () = 
+            case s.available of
+            Known n: Known (n + vec.length ir - 1);
+            other: other;
+            esac,
+        read count = 
+           (signal = s.read count;
+            out = array (map \(new double[mat.width signal]) [1..s.channels]);
+            for [0..s.channels - 1] do ch:
+                for [0..mat.width signal - 1] do i:
+                    for [0..vec.length ir - 1] do j:
+                    history = 
+                        if j > i then
+                            mat.at buffer ch (mat.width buffer + i - j)
+                        else
+                            mat.at signal ch (i - j)
+                        fi;
+                        out[ch][i] := out[ch][i] + history * (vec.at ir j);
+                    done;
+                done;
+            done;
+            extended = mat.concat (Horizontal ()) [buffer, signal];
+            w = mat.width extended;
+            buffer := mat.columnSlice extended (w - vec.length ir) w;
+            mat.newMatrix (RowMajor ()) (map vec.vector out)),
+    });
 
 {
     withDuration is number -> stream -> stream,
@@ -267,5 +300,6 @@
     multiplexed is list<stream> -> stream,
     repeated is stream -> stream,
     duplicated is number -> stream -> list<stream>,
+    convolvedWith is vector -> stream -> stream,
 }
 
--- a/yetilab/stream/syntheticstream.yeti	Sat May 25 18:42:01 2013 +0100
+++ b/yetilab/stream/syntheticstream.yeti	Mon May 27 23:37:57 2013 +0100
@@ -35,7 +35,7 @@
 silent rate =
     generated rate \0;
 
-precalculated rate data =
+precalculated rate data = //!!! hang on -- these are returning 1-ch vectors, not matrices like other streams. how is this working?
    (n = vec.length data;
     var position = 0;
     {
--- a/yetilab/stream/test/test_filter.yeti	Sat May 25 18:42:01 2013 +0100
+++ b/yetilab/stream/test/test_filter.yeti	Mon May 27 23:37:57 2013 +0100
@@ -531,6 +531,23 @@
         ( s1.close (); s2.close() ; true )
 ),
 
+"convolvedWith-\(name)": \(
+    ir = vec.fromList [1,2,3];
+    signal = maybeDuration 2 (syn.precalculated 2 (vec.fromList [1,2]));
+    c = filt.convolvedWith ir signal;
+    compare c.position 0 and
+        compare c.channels 1 and
+        compare c.sampleRate 2 and
+        compare c.available (maybeKnown 4) and
+        compare (map vec.list (mat.asRows (c.read 3))) [[1,4,7]] and
+        compare c.available (maybeKnown 1) and
+        compare c.finished? false and
+        compare (map vec.list (mat.asRows (c.read 4))) [[6]] and
+        compare c.available (Known 0) and
+        compare c.finished? true and
+        ( c.close (); true )
+),
+
 //!!! still no tests for filters with multi-channel inputs
 
 ]);