From d6408797755878783623690eeed2a6c1da909d73 Mon Sep 17 00:00:00 2001
From: faiface <faiface@ksp.sk>
Date: Wed, 5 Jul 2017 18:14:18 +0200
Subject: [PATCH] add Take decorator function

---
 audio/compositors.go      | 23 +++++++++++++++++++++++
 audio/compositors_test.go | 16 ++++++++++++++++
 2 files changed, 39 insertions(+)

diff --git a/audio/compositors.go b/audio/compositors.go
index bb4740f..ceed138 100644
--- a/audio/compositors.go
+++ b/audio/compositors.go
@@ -1,5 +1,28 @@
 package audio
 
+import (
+	"math"
+	"time"
+)
+
+// Take returns a Streamer which streams s for at most d duration.
+func Take(d time.Duration, s Streamer) Streamer {
+	currSample := 0
+	numSamples := int(math.Ceil(d.Seconds() * SampleRate))
+	return StreamerFunc(func(samples [][2]float64) (n int, ok bool) {
+		if currSample >= numSamples {
+			return 0, false
+		}
+		toStream := numSamples - currSample
+		if len(samples) < toStream {
+			toStream = len(samples)
+		}
+		sn, sok := s.Stream(samples[:toStream])
+		currSample += sn
+		return sn, sok
+	})
+}
+
 // Seq takes zero or more Streamers and returns a Streamer which streams them one by one without pauses.
 func Seq(s ...Streamer) Streamer {
 	i := 0
diff --git a/audio/compositors_test.go b/audio/compositors_test.go
index 4114b92..450430b 100644
--- a/audio/compositors_test.go
+++ b/audio/compositors_test.go
@@ -44,6 +44,22 @@ func collect(s audio.Streamer) [][2]float64 {
 	}
 }
 
+func TestTake(t *testing.T) {
+	for i := 0; i < 7; i++ {
+		total := time.Nanosecond * time.Duration(1e8+rand.Intn(1e9))
+		s, data := randomDataStreamer(total)
+		d := time.Nanosecond * time.Duration(rand.Int63n(total.Nanoseconds()))
+		numSamples := int(math.Ceil(d.Seconds() * audio.SampleRate))
+
+		want := data[:numSamples]
+		got := collect(audio.Take(d, s))
+
+		if !reflect.DeepEqual(want, got) {
+			t.Error("Take not working correctly")
+		}
+	}
+}
+
 func TestSeq(t *testing.T) {
 	var (
 		s    = make([]audio.Streamer, 7)
-- 
GitLab