Skip to content

Commit

Permalink
Merge pull request #169 from gopxl/use-new-go-features
Browse files Browse the repository at this point in the history
Use Go 2.21 built-in functions `min`, `max` and `clear`
  • Loading branch information
MarkKremer authored Aug 1, 2024
2 parents 20e0303 + b5ea095 commit 113489d
Show file tree
Hide file tree
Showing 16 changed files with 52 additions and 87 deletions.
16 changes: 4 additions & 12 deletions buffer.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"fmt"
"math"
"time"

"github.com/gopxl/beep/internal/util"
)

// SampleRate is the number of samples per second.
Expand Down Expand Up @@ -63,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 := norm((sample[0] + sample[1]) / 2)
x := util.Clamp((sample[0]+sample[1])/2, -1, 1)
p = p[encodeFloat(signed, f.Precision, p, x):]
case f.NumChannels >= 2:
for c := range sample {
x := norm(sample[c])
x := util.Clamp(sample[c], -1, 1)
p = p[encodeFloat(signed, f.Precision, p, x):]
}
for c := len(sample); c < f.NumChannels; c++ {
Expand Down Expand Up @@ -150,16 +152,6 @@ func unsignedToFloat(precision int, xUint64 uint64) float64 {
return float64(xUint64)/(math.Exp2(float64(precision)*8))*2 - 1
}

func norm(x float64) float64 {
if x < -1 {
return -1
}
if x > +1 {
return +1
}
return x
}

// Buffer is a storage for audio data. You can think of it as a bytes.Buffer for audio samples.
type Buffer struct {
f Format
Expand Down
14 changes: 3 additions & 11 deletions compositors.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@ func (t *take) Stream(samples [][2]float64) (n int, ok bool) {
if t.remains <= 0 {
return 0, false
}
toStream := t.remains
if len(samples) < toStream {
toStream = len(samples)
}
toStream := min(t.remains, len(samples))
n, ok = t.s.Stream(samples[:toStream])
t.remains -= n
return n, ok
Expand Down Expand Up @@ -102,15 +99,10 @@ func Mix(s ...Streamer) Streamer {
var tmp [512][2]float64

for len(samples) > 0 {
toStream := len(tmp)
if toStream > len(samples) {
toStream = len(samples)
}
toStream := min(len(tmp), len(samples))

// clear the samples
for i := range samples[:toStream] {
samples[i] = [2]float64{}
}
clear(samples[:toStream])

snMax := 0 // max number of streamed samples in this iteration
for _, st := range s {
Expand Down
4 changes: 1 addition & 3 deletions compositors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,7 @@ func TestMix(t *testing.T) {

maxLen := 0
for _, d := range data {
if len(d) > maxLen {
maxLen = len(d)
}
maxLen = max(maxLen, len(d))
}

want := make([][2]float64, maxLen)
Expand Down
4 changes: 1 addition & 3 deletions ctrl.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,7 @@ func (c *Ctrl) Stream(samples [][2]float64) (n int, ok bool) {
return 0, false
}
if c.Paused {
for i := range samples {
samples[i] = [2]float64{}
}
clear(samples)
return len(samples), true
}
return c.Streamer.Stream(samples)
Expand Down
6 changes: 1 addition & 5 deletions effects/transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,7 @@ 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)
if progress < 0 {
progress = 0
} else if progress > 1 {
progress = 1
}
progress = min(progress, 1.0)
value := t.transitionFunc(progress)
gain := t.startGain + (t.endGain-t.startGain)*value

Expand Down
18 changes: 6 additions & 12 deletions examples/speedy-player/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,10 @@ func (ap *audioPanel) handle(event tcell.Event) (changed, quit bool) {
if event.Rune() == 'w' {
newPos += ap.sampleRate.N(time.Second)
}
if newPos < 0 {
newPos = 0
}
if newPos >= ap.streamer.Len() {
newPos = ap.streamer.Len() - 1
}
// Clamp the position to be within the stream
newPos = max(newPos, 0)
newPos = min(newPos, ap.streamer.Len()-1)

if err := ap.streamer.Seek(newPos); err != nil {
report(err)
}
Expand All @@ -130,19 +128,15 @@ func (ap *audioPanel) handle(event tcell.Event) (changed, quit bool) {
case 'z':
speaker.Lock()
newRatio := ap.resampler.Ratio() * 15 / 16
if newRatio < 0.001 {
newRatio = 0.001
}
newRatio = max(newRatio, 0.001) // Limit to a reasonable ratio
ap.resampler.SetRatio(newRatio)
speaker.Unlock()
return true, false

case 'x':
speaker.Lock()
newRatio := ap.resampler.Ratio() * 16 / 15
if newRatio > 100 {
newRatio = 100
}
newRatio = min(newRatio, 100) // Limit to a reasonable ratio
ap.resampler.SetRatio(newRatio)
speaker.Unlock()
return true, false
Expand Down
8 changes: 2 additions & 6 deletions generators/silence.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ import "github.com/gopxl/beep"
func Silence(num int) beep.Streamer {
if num < 0 {
return beep.StreamerFunc(func(samples [][2]float64) (m int, ok bool) {
for i := range samples {
samples[i] = [2]float64{}
}
clear(samples)
return len(samples), true
})
}
Expand All @@ -21,9 +19,7 @@ func Silence(num int) beep.Streamer {
if num < len(samples) {
samples = samples[:num]
}
for i := range samples {
samples[i] = [2]float64{}
}
clear(samples)
num -= len(samples)

return len(samples), true
Expand Down
5 changes: 1 addition & 4 deletions internal/testtools/asserts.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,7 @@ func AssertStreamerHasCorrectReturnBehaviour(t *testing.T, s beep.Streamer, expe
buf := make([][2]float64, 512)
samplesLeft := expectedSamples - leaveUnreadInFirstCase
for samplesLeft > 0 {
toRead := len(buf)
if toRead > samplesLeft {
toRead = samplesLeft
}
toRead := min(samplesLeft, len(buf))
n, ok := s.Stream(buf[:toRead])
if !ok {
t.Fatalf("streamer returned !ok before it was expected to be drained")
Expand Down
7 changes: 7 additions & 0 deletions internal/util/math.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package util

import "cmp"

func Clamp[T cmp.Ordered](x, minV, maxV T) T {
return max(min(x, maxV), minV)
}
13 changes: 13 additions & 0 deletions internal/util/math_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package util

import (
"testing"

"github.com/stretchr/testify/assert"
)

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))
}
5 changes: 1 addition & 4 deletions midi/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,7 @@ func (d *decoder) Stream(samples [][2]float64) (n int, ok bool) {
}

for len(samples) > 0 {
cn := len(d.bufLeft)
if cn > len(samples) {
cn = len(samples)
}
cn := min(len(d.bufLeft), len(samples))

d.seq.Render(d.bufLeft[:cn], d.bufRight[:cn])
for i := 0; i < cn; i++ {
Expand Down
9 changes: 2 additions & 7 deletions mixer.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,10 @@ func (m *Mixer) Stream(samples [][2]float64) (n int, ok bool) {
var tmp [512][2]float64

for len(samples) > 0 {
toStream := len(tmp)
if toStream > len(samples) {
toStream = len(samples)
}
toStream := min(len(tmp), len(samples))

// clear the samples
for i := range samples[:toStream] {
samples[i] = [2]float64{}
}
clear(samples[:toStream])

for si := 0; si < len(m.streamers); si++ {
// mix the stream
Expand Down
8 changes: 2 additions & 6 deletions resample.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,12 +115,8 @@ func (r *Resampler) Stream(samples [][2]float64) (n int, ok bool) {
}

// Adjust the window to be within the available buffers.
if windowStart < 0 {
windowStart = 0
}
if windowEnd > r.end {
windowEnd = r.end
}
windowStart = max(windowStart, 0)
windowEnd = min(windowEnd, r.end)

// For each channel...
for c := range samples[0] {
Expand Down
8 changes: 2 additions & 6 deletions speaker/speaker.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/pkg/errors"

"github.com/gopxl/beep"
"github.com/gopxl/beep/internal/util"
)

const channelCount = 2
Expand Down Expand Up @@ -186,12 +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]
if val < -1 {
val = -1
}
if val > +1 {
val = +1
}
val = util.Clamp(val, -1, 1)
valInt16 := int16(val * (1<<15 - 1))
low := byte(valInt16)
high := byte(valInt16 >> 8)
Expand Down
4 changes: 1 addition & 3 deletions streamers.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ func Silence(num int) Streamer {
if 0 < num && num < len(samples) {
samples = samples[:num]
}
for i := range samples {
samples[i] = [2]float64{}
}
clear(samples)
if num > 0 {
num -= len(samples)
}
Expand Down
10 changes: 5 additions & 5 deletions wav/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import (
"io"
"time"

"github.com/gopxl/beep"
"github.com/pkg/errors"

"github.com/gopxl/beep"
)

// Decode takes a Reader containing audio data in WAVE format and returns a StreamSeekCloser,
Expand Down Expand Up @@ -207,10 +208,9 @@ func (d *decoder) Stream(samples [][2]float64) (n int, ok bool) {
return 0, false
}
bytesPerFrame := int(d.h.BytesPerFrame)
numBytes := int32(len(samples) * bytesPerFrame)
if numBytes > d.h.DataSize-d.pos {
numBytes = d.h.DataSize - d.pos
}
wantBytes := len(samples) * bytesPerFrame
availableBytes := int(d.h.DataSize - d.pos)
numBytes := min(wantBytes, availableBytes)
p := make([]byte, numBytes)
n, err := d.r.Read(p)
if err != nil && err != io.EOF {
Expand Down

0 comments on commit 113489d

Please sign in to comment.