Skip to content

Commit

Permalink
Merge pull request #198 from gopxl/clear-mixer-during-callback
Browse files Browse the repository at this point in the history
Fix panic when clearing Mixer during mixing
  • Loading branch information
MarkKremer authored Jan 5, 2025
2 parents 2db4462 + 74097d1 commit e2b0015
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 8 deletions.
20 changes: 12 additions & 8 deletions mixer.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ func (m *Mixer) Stream(samples [][2]float64) (n int, ok bool) {
for len(samples) > 0 {
toStream := min(len(tmp), len(samples))

// clear the samples
// Clear the samples
clear(samples[:toStream])

snMax := 0
for si := 0; si < len(m.streamers); si++ {
// mix the stream
// Mix the stream
sn, sok := m.streamers[si].Stream(tmp[:toStream])
for i := range tmp[:sn] {
samples[i][0] += tmp[i][0]
Expand All @@ -61,12 +61,16 @@ func (m *Mixer) Stream(samples [][2]float64) (n int, ok bool) {
}

if sn < toStream || !sok {
// remove drained streamer
last := len(m.streamers) - 1
m.streamers[si] = m.streamers[last]
m.streamers[last] = nil
m.streamers = m.streamers[:last]
si--
// Remove drained streamer.
// Check the length of m.streamers again in case the call to Stream()
// had a callback which clears the Mixer.
if len(m.streamers) > 0 {
last := len(m.streamers) - 1
m.streamers[si] = m.streamers[last]
m.streamers[last] = nil
m.streamers = m.streamers[:last]
si--
}

if m.stopWhenEmpty && len(m.streamers) == 0 {
return n + snMax, true
Expand Down
11 changes: 11 additions & 0 deletions mixer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,17 @@ func TestMixer_PlaysSilenceWhenNoStreamersProduceSamples(t *testing.T) {
assert.Equal(t, make([][2]float64, 10), samples)
}

// Bug: https://github.com/gopxl/beep/issues/197#issuecomment-2468951277
func TestMixer_CanClearDuringCallback(t *testing.T) {
m := beep.Mixer{}

m.Add(beep.Callback(func() {
m.Clear()
}))

testtools.CollectNum(10, &m)
}

func BenchmarkMixer_MultipleStreams(b *testing.B) {
s1, _ := testtools.RandomDataStreamer(b.N)
s2, _ := testtools.RandomDataStreamer(b.N)
Expand Down

0 comments on commit e2b0015

Please sign in to comment.