changeset 203:ee3fbcc779d9

Implement and test mixed
author Chris Cannam
date Mon, 06 May 2013 18:33:30 +0100
parents 9bc6070c041c
children 0c81455270dc
files yetilab/stream/filter.yeti yetilab/stream/test/test_filter.yeti
diffstat 2 files changed, 121 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/yetilab/stream/filter.yeti	Mon May 06 18:22:41 2013 +0100
+++ b/yetilab/stream/filter.yeti	Mon May 06 18:33:30 2013 +0100
@@ -72,11 +72,53 @@
         close = s.close
     });
 
+//!!! what should happen if we mix or multiplex a finite-length and an
+//infinite-length stream? or even two streams with differing finite
+//lengths? write tests for this. At the moment the resulting stream
+//has duration equal to the shortest source stream and finishes as
+//soon as any one of them finishes
+
+mixed streams =
+   (mix m1 m2 =
+       (sz = { rows = max m1.size.rows m2.size.rows,
+               columns = min m1.size.columns m2.size.columns };
+        if sz.columns == 0 then
+            mat.zeroSizeMatrix ()
+        else
+            mat.sum (mat.resizedTo sz m1) (mat.resizedTo sz m2);
+        fi);
+    {
+        get position () = head (sort (map (.position) streams)),
+        get channels () = head (sortBy (>) (map (.channels) streams)),
+        get sampleRate () = (head streams).sampleRate, //!!! document this
+        get available () =
+            fold do dur s: minDurationOf dur s.available done (Infinite ()) streams,
+        get finished? () = any id (map (.finished?) streams),
+        read count =
+           (readTo acc ss count =
+               case ss of
+               first::rest:
+                   part = first.read count;
+                   case acc of 
+                   Some m:
+                       readTo (Some (mix m part)) rest count;
+                   None ():
+                       readTo (Some part) rest count;
+                   esac;
+                _: acc;
+               esac;
+            case readTo (None ()) streams count of
+            None (): mat.zeroSizeMatrix ();
+            Some m: m;
+            esac),
+        close () = for streams do s: s.close() done,
+    });
+
 multiplexed streams = 
     {
         get position () = head (sort (map (.position) streams)), // can differ after EOS
         get channels () = sum (map (.channels) streams),
-        get sampleRate () = (head streams).sampleRate,
+        get sampleRate () = (head streams).sampleRate, //!!! document this
         get available () = 
             fold do dur s: minDurationOf dur s.available done (Infinite ()) streams,
         get finished? () = any id (map (.finished?) streams),
@@ -151,6 +193,7 @@
 {
     withDuration is number -> stream -> stream,
     delayedBy is number -> stream -> stream,
+    mixed is list<stream> -> stream,
     multiplexed is list<stream> -> stream,
     repeated is stream -> stream,
 }
--- a/yetilab/stream/test/test_filter.yeti	Mon May 06 18:22:41 2013 +0100
+++ b/yetilab/stream/test/test_filter.yeti	Mon May 06 18:33:30 2013 +0100
@@ -182,6 +182,83 @@
         ( str.close (); true )
 ),
 
+"mixed-inf-inf-\(name)": \(
+    str = filt.mixed [syn.generated 2 (2*), syn.generated 2 (0-)];
+    compare str.position 0 and
+        compare str.channels 1 and
+        compare str.sampleRate 2 and
+        compare str.available (Infinite ()) and
+        compare str.finished? false and
+        compare (map bl.list (mat.asRows (str.read 4))) [[0,1,2,3]] and
+        compare str.available (Infinite ()) and
+        compare str.position 4 and
+        ( str.close (); true )
+),
+
+"mixed-inf-trunc-\(name)": \(
+    str = filt.mixed [syn.generated 2 (2*), withDuration 3 (syn.generated 2 (0-))];
+    compare str.position 0 and
+        compare str.channels 1 and
+        compare str.sampleRate 2 and
+        compare str.available (maybeKnown 3) and
+        compare str.finished? false and
+        compare (map bl.list (mat.asRows (str.read 4))) [[0,1,2]] and
+        compare str.available (Known 0) and
+        compare str.finished? true and
+        compare str.position 3 and
+        ( str.close (); true )
+),
+
+"mixed-precalc-trunc-\(name)": \(
+    str = filt.mixed
+       [syn.precalculated 2 (bl.fromList [1,2]),
+        withDuration 3 (syn.generated 2 (0-))];
+    compare str.position 0 and
+        compare str.channels 1 and
+        compare str.sampleRate 2 and
+        compare str.available (maybeKnown 2) and
+        compare str.finished? false and
+        compare (map bl.list (mat.asRows (str.read 4))) [[1,1]] and
+        compare str.available (Known 0) and
+        compare str.finished? true and
+        compare str.position 2 and
+        ( str.close (); true )
+),
+
+"mixed-2-1-\(name)": \(
+    str = filt.mixed
+       [syn.precalculated 2 (bl.fromList [1,2]),
+        filt.multiplexed [syn.precalculated 2 (bl.fromList [3,4]),
+                          withDuration 3 (syn.generated 2 (0-))]];
+    compare str.position 0 and
+        compare str.channels 2 and
+        compare str.sampleRate 2 and
+        compare str.available (maybeKnown 2) and
+        compare str.finished? false and
+        compare (map bl.list (mat.asRows (str.read 4))) [[4,6], [0,-1]] and
+        compare str.available (Known 0) and
+        compare str.finished? true and
+        compare str.position 2 and
+        ( str.close (); true )
+),
+
+"mixed-3-\(name)": \(
+    str = filt.mixed
+       [syn.precalculated 2 (bl.fromList [1,2]),
+        syn.precalculated 2 (bl.fromList [3,4]),
+        withDuration 3 (syn.generated 2 (0-))];
+    compare str.position 0 and
+        compare str.channels 1 and
+        compare str.sampleRate 2 and
+        compare str.available (maybeKnown 2) and
+        compare str.finished? false and
+        compare (map bl.list (mat.asRows (str.read 4))) [[4,5]] and
+        compare str.available (Known 0) and
+        compare str.finished? true and
+        compare str.position 2 and
+        ( str.close (); true )
+),
+
 "multiplexed-inf-inf-\(name)": \(
     str = filt.multiplexed [syn.generated 2 id, syn.generated 2 (0-)];
     compare str.position 0 and