From ee258c1d13ac99529de74268ff0ff03e82b09192 Mon Sep 17 00:00:00 2001 From: faiface Date: Fri, 7 Jul 2017 16:11:48 +0200 Subject: [PATCH] audio: add Mix compositor --- audio/compositors.go | 47 +++++++++++++++++++++++++++++++++++++++ audio/compositors_test.go | 25 +++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/audio/compositors.go b/audio/compositors.go index ceed138..5fe7c36 100644 --- a/audio/compositors.go +++ b/audio/compositors.go @@ -38,3 +38,50 @@ func Seq(s ...Streamer) Streamer { return n, ok }) } + +// Mix takes zero or more Streamers and returns a Streamer which streames them mixed together. +func Mix(s ...Streamer) Streamer { + return StreamerFunc(func(samples [][2]float64) (n int, ok bool) { + var tmp, mix [512][2]float64 + + for len(samples) > 0 { + toStream := len(mix) + if toStream > len(samples) { + toStream = len(samples) + } + + // clear the mix buffer + for i := range mix[:toStream] { + mix[i] = [2]float64{} + } + + snMax := 0 // max number of streamed samples in this iteration + for _, st := range s { + // mix the stream + sn, sok := st.Stream(tmp[:toStream]) + if sn > snMax { + snMax = sn + } + ok = ok || sok + + for i := range tmp[:sn] { + mix[i][0] += tmp[i][0] + mix[i][1] += tmp[i][1] + } + } + + // copy mix buffer into samples + for i := range mix[:snMax] { + samples[i] = mix[i] + } + + n += snMax + if snMax < len(mix) { + break + } + samples = samples[snMax:] + } + + return n, ok + }) +} diff --git a/audio/compositors_test.go b/audio/compositors_test.go index 450430b..6842d89 100644 --- a/audio/compositors_test.go +++ b/audio/compositors_test.go @@ -77,3 +77,28 @@ func TestSeq(t *testing.T) { t.Error("Seq not working correctly") } } + +func TestMix(t *testing.T) { + var ( + s = make([]audio.Streamer, 7) + want [][2]float64 + ) + for i := range s { + var data [][2]float64 + s[i], data = randomDataStreamer(time.Nanosecond * time.Duration(1e8+rand.Intn(1e9))) + for j := range data { + if j >= len(want) { + want = append(want, data[j]) + continue + } + want[j][0] += data[j][0] + want[j][1] += data[j][1] + } + } + + got := collect(audio.Mix(s...)) + + if !reflect.DeepEqual(want, got) { + t.Error("Mix not working correctly") + } +}