618b08fa9a01 — Chris Cannam 2 years ago
Tests & fixes for seeking in PairConcatenatingStatefulStreamFn (and hence PaddedStatefulStreamFn)
2 files changed, 154 insertions(+), 3 deletions(-)

M duration-adapting-fn.sml
M test.sml
M duration-adapting-fn.sml +8 -3
@@ 38,7 38,8 @@ functor PairConcatenatingStatefulStreamF
         let fun performCutover n =
                 case (! status) of
                     IN_1 => (status := IN_2;
-                             cutover := SOME (FRAME (frameOf (! position) + n))
+                             cutover := SOME (FRAME (frameOf (! position) + n));
+                             SampleStreamLog.info (fn () => ["cutover = %1", SampleStreamLog.I (frameOf (! position) + n)])
                             )
                   | _ => raise Fail "Internal error: performCutover called when already cutover"
             val result = 

          
@@ 97,19 98,23 @@ functor PairConcatenatingStatefulStreamF
             case (! cutover) of
                 SOME (FRAME c) =>
                 if (fr >= c) then
-                    if S2.seek (s2, m, RealTime.fromFrame
-                                           (FRAME (fr - c), S2.rate s2))
+                    if S2.seek (s2, m, RealTime.fromFrame (FRAME (fr - c), rate))
                     then (status := IN_2;
+                          position := FRAME fr;
                           true)
                     else false
                 else
                     if S1.seek (s1, m, t)
                     then (status := IN_1;
+                          S2.seek (s2, SampleStreamTypes.SEEK_COMPLETE,
+                                   RealTime.zeroTime);
+                          position := FRAME fr;
                           true)
                     else false
               | NONE =>
                 if S1.seek (s1, m, t)
                 then (status := IN_1;
+                      position := FRAME fr;
                       true)
                 else let val c = findCutover (! position, s1)
                      in

          
M test.sml +146 -0
@@ 96,6 96,151 @@ structure TestSyntheticStreams : TESTS =
                          
 end
 
+structure TestPadded : TESTS = struct
+
+    type test = string * (unit -> bool)
+
+    val name = "padded"
+
+    structure P = PaddedStatefulStreamFn
+                      (StatefulSampleStreamFromStatelessFn
+                           (StatelessSyntheticStream))
+
+    structure RM = RealMatrix
+    structure RT = RealTime
+
+    open TestSupport
+    open SignalTypes
+    open SampleStreamTestSupport
+
+    fun checkReadMono s expected =
+        let val t = P.time s
+            val v = RealVector.fromList expected
+            val n = RealVector.length v
+            val mopt = P.read (s, n)
+        in
+            checkSome mopt andalso
+            let val m = Option.valOf mopt in
+                intsEqual (RM.rows m, 1) andalso
+                realVectorsEqual (RM.row (m, 0), v) andalso
+                realTimesEqual (P.time s, RT.+ (t, RT.fromFrame
+                                                       (FRAME n, P.rate s)))
+            end
+        end
+
+    val mode = SampleStreamTypes.SEEK_COMPLETE
+            
+    fun tests () = [
+        ("no-padding",
+         fn () =>
+            let val p = P.new ({ padding = 0 },
+                               { rate = RATE 80.0,
+                                 sort = StatelessSyntheticStream.GENERATED
+                                            (fn i => SOME (real i))
+                               }
+                              )
+            in
+                equal (rateOf (P.rate p), 80.0) andalso
+                realTimesEqual (P.time p, RT.zeroTime) andalso
+                checkReadMono p [ 0.0, 1.0, 2.0, 3.0 ]
+            end
+        ),
+        ("no-padding-seek",
+         fn () =>
+            let val p = P.new ({ padding = 0 },
+                               { rate = RATE 80.0,
+                                 sort = StatelessSyntheticStream.GENERATED
+                                            (fn i => SOME (real i))
+                               }
+                              )
+            in
+                (case P.seekable p of
+                     SampleStreamTypes.SEEKABLE { startTime, endTime = NONE } =>
+                     true
+                   | _ => false) andalso
+                realTimesEqual (P.time p, RT.zeroTime) andalso
+                verify (P.seek (p, mode, RT.fromFrame (FRAME 5, P.rate p))) andalso
+                checkReadMono p [ 5.0, 6.0, 7.0, 8.0 ] andalso
+                verify (P.seek (p, mode, RT.fromFrame (FRAME 1, P.rate p))) andalso
+                checkReadMono p [ 1.0, 2.0, 3.0, 4.0 ]
+            end
+        ),
+        ("padding",
+         fn () =>
+            let val p = P.new ({ padding = 4 },
+                               { rate = RATE 80.0,
+                                 sort = StatelessSyntheticStream.GENERATED
+                                            (fn i => SOME (real i))
+                               }
+                              )
+            in
+                equal (rateOf (P.rate p), 80.0) andalso
+                realTimesEqual (P.time p, RT.zeroTime) andalso
+                checkReadMono p [ 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 2.0, 3.0 ]
+            end
+        ),
+        ("padding-seek", (* Seeking to beyond cutover before reading at all *)
+         fn () =>
+            let val p = P.new ({ padding = 4 },
+                               { rate = RATE 80.0,
+                                 sort = StatelessSyntheticStream.GENERATED
+                                            (fn i => SOME (real i))
+                               }
+                              )
+            in
+                (case P.seekable p of
+                     SampleStreamTypes.SEEKABLE { startTime, endTime = NONE } =>
+                     true
+                   | _ => false) andalso
+                realTimesEqual (P.time p, RT.zeroTime) andalso
+                verify (P.seek (p, mode, RT.fromFrame (FRAME 5, P.rate p))) andalso
+                checkReadMono p [ 1.0, 2.0, 3.0, 4.0 ] andalso
+                verify (P.seek (p, mode, RT.fromFrame (FRAME 1, P.rate p))) andalso
+                checkReadMono p [ 0.0, 0.0, 0.0, 0.0, 1.0, 2.0, 3.0 ] andalso
+                verify (P.seek (p, mode, RT.fromFrame (FRAME 4, P.rate p))) andalso
+                checkReadMono p [ 0.0, 1.0, 2.0, 3.0 ]
+            end
+        ),
+        ("padding-seek-2", (* Reading to precisely cutover before seeking at all *)
+         fn () =>
+            let val p = P.new ({ padding = 4 },
+                               { rate = RATE 80.0,
+                                 sort = StatelessSyntheticStream.GENERATED
+                                            (fn i => SOME (real i))
+                               }
+                              )
+            in
+                checkReadMono p [ 0.0, 0.0, 0.0, 0.0 ] andalso
+                verify (P.seek (p, mode, RT.fromFrame (FRAME 5, P.rate p))) andalso
+                checkReadMono p [ 1.0, 2.0, 3.0, 4.0 ] andalso
+                verify (P.seek (p, mode, RT.fromFrame (FRAME 1, P.rate p))) andalso
+                checkReadMono p [ 0.0, 0.0, 0.0, 0.0, 1.0, 2.0, 3.0 ] andalso
+                verify (P.seek (p, mode, RT.fromFrame (FRAME 4, P.rate p))) andalso
+                checkReadMono p [ 0.0, 1.0, 2.0, 3.0 ]
+            end
+        ),
+        ("padding-seek-3", (* Reading to beyond cutover before seeking at all *)
+         fn () =>
+            let val p = P.new ({ padding = 4 },
+                               { rate = RATE 80.0,
+                                 sort = StatelessSyntheticStream.GENERATED
+                                            (fn i => SOME (real i))
+                               }
+                              )
+            in
+                checkReadMono p [ 0.0, 0.0, 0.0, 0.0, 0.0 ] andalso
+                verify (P.seek (p, mode, RT.fromFrame (FRAME 5, P.rate p))) andalso
+                checkReadMono p [ 1.0, 2.0, 3.0, 4.0 ] andalso
+                verify (P.seek (p, mode, RT.fromFrame (FRAME 1, P.rate p))) andalso
+                checkReadMono p [ 0.0, 0.0, 0.0, 0.0, 1.0, 2.0, 3.0 ] andalso
+                verify (P.seek (p, mode, RT.fromFrame (FRAME 4, P.rate p))) andalso
+                checkReadMono p [ 0.0, 1.0, 2.0, 3.0 ]
+            end
+        )
+    ]
+
+end
+                                             
 structure TestFraming : TESTS = struct
 
     type test = string * (unit -> bool)

          
@@ 1266,6 1411,7 @@ end
                                         
 val samplestreams_tests = [
     (TestSyntheticStreams.name, TestSyntheticStreams.tests ()),
+    (TestPadded.name, TestPadded.tests ()),
     (TestFraming.name, TestFraming.tests ()),
     (TestFrequencyDomain.name, TestFrequencyDomain.tests ()),
     (TestSummarising.name, TestSummarising.tests ()),