From 661c5e6d860f381fd6295366af1c8d56a030534f Mon Sep 17 00:00:00 2001 From: Mark Kremer Date: Sat, 21 Sep 2024 15:13:18 +0200 Subject: [PATCH 1/3] Downgrade Go version --- .github/workflows/go.yml | 3 +-- go.mod | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 41af4a1..cfd7404 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -16,8 +16,7 @@ jobs: strategy: matrix: go: - - '1.21' # minimum supported version - - 'stable' + - '1.20' # Go version of Ikemen GO name: "build with Go ${{ matrix.go }}" steps: - uses: actions/checkout@v4 diff --git a/go.mod b/go.mod index e4148b0..1d8f208 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/gopxl/beep/v2 -go 1.21 +go 1.20 require ( github.com/ebitengine/oto/v3 v3.3.2 From 607210eef81b32ef0a953624e7ce76f10f3f41d7 Mon Sep 17 00:00:00 2001 From: Mark Kremer Date: Sat, 21 Sep 2024 15:19:35 +0200 Subject: [PATCH 2/3] Make Clamp Go 1.20 compatible --- buffer.go | 4 ++-- internal/util/math.go | 12 ++++++++---- internal/util/math_test.go | 6 +++--- speaker/speaker.go | 2 +- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/buffer.go b/buffer.go index 485e842..3c9ba65 100644 --- a/buffer.go +++ b/buffer.go @@ -65,11 +65,11 @@ func (f Format) DecodeUnsigned(p []byte) (sample [2]float64, n int) { func (f Format) encode(signed bool, p []byte, sample [2]float64) (n int) { switch { case f.NumChannels == 1: - x := util.Clamp((sample[0]+sample[1])/2, -1, 1) + x := util.ClampFloat64((sample[0]+sample[1])/2, -1, 1) p = p[encodeFloat(signed, f.Precision, p, x):] case f.NumChannels >= 2: for c := range sample { - x := util.Clamp(sample[c], -1, 1) + x := util.ClampFloat64(sample[c], -1, 1) p = p[encodeFloat(signed, f.Precision, p, x):] } for c := len(sample); c < f.NumChannels; c++ { diff --git a/internal/util/math.go b/internal/util/math.go index e335edb..b988d02 100644 --- a/internal/util/math.go +++ b/internal/util/math.go @@ -1,7 +1,11 @@ package util -import "cmp" - -func Clamp[T cmp.Ordered](x, minV, maxV T) T { - return max(min(x, maxV), minV) +func ClampFloat64(x, minV, maxV float64) float64 { + if x <= minV { + return minV + } + if x >= maxV { + return maxV + } + return x } diff --git a/internal/util/math_test.go b/internal/util/math_test.go index aa669f3..b3255ec 100644 --- a/internal/util/math_test.go +++ b/internal/util/math_test.go @@ -7,7 +7,7 @@ import ( ) func TestClamp(t *testing.T) { - assert.Equal(t, 0, Clamp(-5, 0, 1)) - assert.Equal(t, 1, Clamp(5, 0, 1)) - assert.Equal(t, 0.5, Clamp(0.5, 0, 1)) + assert.Equal(t, 0.0, ClampFloat64(-5, 0, 1)) + assert.Equal(t, 1.0, ClampFloat64(5, 0, 1)) + assert.Equal(t, 0.5, ClampFloat64(0.5, 0, 1)) } diff --git a/speaker/speaker.go b/speaker/speaker.go index 4e81900..6246083 100644 --- a/speaker/speaker.go +++ b/speaker/speaker.go @@ -187,7 +187,7 @@ func (s *sampleReader) Read(buf []byte) (n int, err error) { for i := range s.buf[:ns] { for c := range s.buf[i] { val := s.buf[i][c] - val = util.Clamp(val, -1, 1) + val = util.ClampFloat64(val, -1, 1) valInt16 := int16(val * (1<<15 - 1)) low := byte(valInt16) high := byte(valInt16 >> 8) From ac234dc0f45d1eb1efce17a8bb5f43dfa3729e3e Mon Sep 17 00:00:00 2001 From: Mark Kremer Date: Sat, 21 Sep 2024 15:37:31 +0200 Subject: [PATCH 3/3] Replace usages of min, max and clear --- compositors.go | 16 +++++++++++++--- compositors_test.go | 5 ++++- ctrl.go | 5 ++++- effects/transition.go | 5 ++++- examples/speedy-player/main.go | 20 ++++++++++++++++---- flac/decode.go | 6 +++++- generators/silence.go | 10 ++++++++-- internal/testtools/asserts.go | 6 +++++- internal/testtools/streamers.go | 6 +++++- midi/decode.go | 6 +++++- mixer.go | 11 +++++++++-- resample.go | 10 ++++++++-- streamers.go | 5 ++++- wav/decode.go | 6 +++++- 14 files changed, 95 insertions(+), 22 deletions(-) diff --git a/compositors.go b/compositors.go index 174992e..34c5471 100644 --- a/compositors.go +++ b/compositors.go @@ -26,7 +26,11 @@ func (t *take) Stream(samples [][2]float64) (n int, ok bool) { if t.remains <= 0 { return 0, false } - toStream := min(t.remains, len(samples)) + //toStream := min(t.remains, len(samples)) + toStream := t.remains + if len(samples) < toStream { + toStream = len(samples) + } n, ok = t.s.Stream(samples[:toStream]) t.remains -= n return n, ok @@ -157,7 +161,10 @@ func Loop2(s StreamSeeker, opts ...LoopOption) (Streamer, error) { if l.start >= l.end { return nil, errors.New(fmt.Sprintf("invalid argument to Loop2; start position %d must be smaller than the end position %d", l.start, l.end)) } - l.end = min(l.end, n) + //l.end = min(l.end, n) + if n < l.end { + l.end = n + } return l, nil } @@ -190,7 +197,10 @@ func (l *loop2) Stream(samples [][2]float64) (n int, ok bool) { continue } // Stream only up to the end of the loop. - toStream = min(samplesUntilEnd, toStream) + //toStream = min(samplesUntilEnd, toStream) + if samplesUntilEnd < toStream { + toStream = samplesUntilEnd + } } sn, sok := l.s.Stream(samples[:toStream]) diff --git a/compositors_test.go b/compositors_test.go index e1879e7..87f3d29 100644 --- a/compositors_test.go +++ b/compositors_test.go @@ -196,7 +196,10 @@ func TestMix(t *testing.T) { maxLen := 0 for _, d := range data { - maxLen = max(maxLen, len(d)) + //maxLen = max(maxLen, len(d)) + if len(d) > maxLen { + maxLen = len(d) + } } want := make([][2]float64, maxLen) diff --git a/ctrl.go b/ctrl.go index 8ca1601..bda50e9 100644 --- a/ctrl.go +++ b/ctrl.go @@ -35,7 +35,10 @@ func (c *Ctrl) Stream(samples [][2]float64) (n int, ok bool) { return 0, false } if c.Paused { - clear(samples) + //clear(samples) + for i := range samples { + samples[i] = [2]float64{} + } return len(samples), true } return c.Streamer.Stream(samples) diff --git a/effects/transition.go b/effects/transition.go index d9ff5e6..dffe295 100644 --- a/effects/transition.go +++ b/effects/transition.go @@ -57,7 +57,10 @@ func (t *TransitionStreamer) Stream(samples [][2]float64) (n int, ok bool) { for i := 0; i < n; i++ { pos := t.pos + i progress := float64(pos) / float64(t.len) - progress = min(progress, 1.0) + //progress = min(progress, 1.0) + if progress > 1 { + progress = 1 + } value := t.transitionFunc(progress) gain := t.startGain + (t.endGain-t.startGain)*value diff --git a/examples/speedy-player/main.go b/examples/speedy-player/main.go index f05e490..c95b976 100644 --- a/examples/speedy-player/main.go +++ b/examples/speedy-player/main.go @@ -109,8 +109,14 @@ func (ap *audioPanel) handle(event tcell.Event) (changed, quit bool) { newPos += ap.sampleRate.N(time.Second) } // Clamp the position to be within the stream - newPos = max(newPos, 0) - newPos = min(newPos, ap.streamer.Len()-1) + //newPos = max(newPos, 0) + if newPos < 0 { + newPos = 0 + } + //newPos = min(newPos, ap.streamer.Len()-1) + if newPos >= ap.streamer.Len() { + newPos = ap.streamer.Len() - 1 + } if err := ap.streamer.Seek(newPos); err != nil { report(err) @@ -133,7 +139,10 @@ func (ap *audioPanel) handle(event tcell.Event) (changed, quit bool) { case 'z': speaker.Lock() newRatio := ap.resampler.Ratio() * 15 / 16 - newRatio = max(newRatio, 0.001) // Limit to a reasonable ratio + //newRatio = max(newRatio, 0.001) // Limit to a reasonable ratio + if newRatio < 0.001 { + newRatio = 0.001 + } ap.resampler.SetRatio(newRatio) speaker.Unlock() return true, false @@ -141,7 +150,10 @@ func (ap *audioPanel) handle(event tcell.Event) (changed, quit bool) { case 'x': speaker.Lock() newRatio := ap.resampler.Ratio() * 16 / 15 - newRatio = min(newRatio, 100) // Limit to a reasonable ratio + //newRatio = min(newRatio, 100) // Limit to a reasonable ratio + if newRatio > 100 { + newRatio = 100 + } ap.resampler.SetRatio(newRatio) speaker.Unlock() return true, false diff --git a/flac/decode.go b/flac/decode.go index 8e86433..af32d2b 100644 --- a/flac/decode.go +++ b/flac/decode.go @@ -85,7 +85,11 @@ func (d *decoder) Stream(samples [][2]float64) (n int, ok bool) { continue } - toFill := min(samplesLeft, len(samples)) + //toFill := min(samplesLeft, len(samples)) + toFill := samplesLeft + if toFill > len(samples) { + toFill = len(samples) + } d.decodeFrameRangeInto(d.frame, d.posInFrame, toFill, samples) d.posInFrame += toFill n += toFill diff --git a/generators/silence.go b/generators/silence.go index 19f64d5..9f8819f 100644 --- a/generators/silence.go +++ b/generators/silence.go @@ -7,7 +7,10 @@ import "github.com/gopxl/beep/v2" func Silence(num int) beep.Streamer { if num < 0 { return beep.StreamerFunc(func(samples [][2]float64) (m int, ok bool) { - clear(samples) + //clear(samples) + for i := range samples { + samples[i] = [2]float64{} + } return len(samples), true }) } @@ -19,7 +22,10 @@ func Silence(num int) beep.Streamer { if num < len(samples) { samples = samples[:num] } - clear(samples) + //clear(samples) + for i := range samples { + samples[i] = [2]float64{} + } num -= len(samples) return len(samples), true diff --git a/internal/testtools/asserts.go b/internal/testtools/asserts.go index 60b77de..3935ccf 100644 --- a/internal/testtools/asserts.go +++ b/internal/testtools/asserts.go @@ -22,7 +22,11 @@ func AssertStreamerHasCorrectReturnBehaviour(t *testing.T, s beep.Streamer, expe buf := make([][2]float64, 512) samplesLeft := expectedSamples - leaveUnreadInFirstCase for samplesLeft > 0 { - toRead := min(samplesLeft, len(buf)) + //toRead := min(samplesLeft, len(buf)) + toRead := len(buf) + if toRead > samplesLeft { + toRead = samplesLeft + } n, ok := s.Stream(buf[:toRead]) if !ok { t.Fatalf("streamer returned !ok before it was expected to be drained") diff --git a/internal/testtools/streamers.go b/internal/testtools/streamers.go index 48e02be..1ec2846 100644 --- a/internal/testtools/streamers.go +++ b/internal/testtools/streamers.go @@ -96,7 +96,11 @@ func (e *ErrorStreamer) Stream(samples [][2]float64) (n int, ok bool) { return 0, false } - toStream := min(e.samplesLeft, len(samples)) + //toStream := min(e.samplesLeft, len(samples)) + toStream := e.samplesLeft + if toStream > len(samples) { + toStream = len(samples) + } n, ok = e.s.Stream(samples[:toStream]) e.samplesLeft -= n diff --git a/midi/decode.go b/midi/decode.go index 8b8b686..f7b999f 100644 --- a/midi/decode.go +++ b/midi/decode.go @@ -100,7 +100,11 @@ func (d *decoder) Stream(samples [][2]float64) (n int, ok bool) { } for len(samples) > 0 { - cn := min(len(d.bufLeft), len(samples)) + //cn := min(len(d.bufLeft), len(samples)) + cn := len(d.bufLeft) + if cn > len(samples) { + cn = len(samples) + } d.seq.Render(d.bufLeft[:cn], d.bufRight[:cn]) for i := 0; i < cn; i++ { diff --git a/mixer.go b/mixer.go index 8954bcf..d249b29 100644 --- a/mixer.go +++ b/mixer.go @@ -43,10 +43,17 @@ func (m *Mixer) Stream(samples [][2]float64) (n int, ok bool) { var tmp [512][2]float64 for len(samples) > 0 { - toStream := min(len(tmp), len(samples)) + //toStream := min(len(tmp), len(samples)) + toStream := len(tmp) + if toStream > len(samples) { + toStream = len(samples) + } // Clear the samples - clear(samples[:toStream]) + //clear(samples[:toStream]) + for i := range samples[:toStream] { + samples[i] = [2]float64{} + } snMax := 0 for si := 0; si < len(m.streamers); si++ { diff --git a/resample.go b/resample.go index 75fd709..5bda09c 100644 --- a/resample.go +++ b/resample.go @@ -115,8 +115,14 @@ func (r *Resampler) Stream(samples [][2]float64) (n int, ok bool) { } // Adjust the window to be within the available buffers. - windowStart = max(windowStart, 0) - windowEnd = min(windowEnd, r.end) + //windowStart = max(windowStart, 0) + if windowStart < 0 { + windowStart = 0 + } + //windowEnd = min(windowEnd, r.end) + if windowEnd > r.end { + windowEnd = r.end + } // For each channel... for c := range samples[0] { diff --git a/streamers.go b/streamers.go index 888fdf4..5cb5e86 100644 --- a/streamers.go +++ b/streamers.go @@ -12,7 +12,10 @@ func Silence(num int) Streamer { if 0 < num && num < len(samples) { samples = samples[:num] } - clear(samples) + //clear(samples) + for i := range samples { + samples[i] = [2]float64{} + } if num > 0 { num -= len(samples) } diff --git a/wav/decode.go b/wav/decode.go index f26c5e7..b6e8201 100644 --- a/wav/decode.go +++ b/wav/decode.go @@ -210,7 +210,11 @@ func (d *decoder) Stream(samples [][2]float64) (n int, ok bool) { bytesPerFrame := int(d.h.BytesPerFrame) wantBytes := len(samples) * bytesPerFrame availableBytes := int(d.h.DataSize - d.pos) - numBytes := min(wantBytes, availableBytes) + //numBytes := min(wantBytes, availableBytes) + numBytes := wantBytes + if numBytes > availableBytes { + numBytes = availableBytes + } p := make([]byte, numBytes) n, err := d.r.Read(p) if err != nil && err != io.EOF {