From 624d2853e7161fdf13cbc497ea941b8638896271 Mon Sep 17 00:00:00 2001 From: Mark Kremer Date: Thu, 9 Nov 2023 17:09:34 +0100 Subject: [PATCH 1/2] Fix speaker buffer size The buffer size was previously set on the speaker but during the upgrade of the Oto version, was in error moved to the context. These aren't the same and this change moves setting the buffer size back to the player. Commit introducing the bug: https://github.com/gopxl/beep/commit/5fefa491fdb0ba5eba5854f06fbd3cce91f4f9f2 --- speaker/speaker.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/speaker/speaker.go b/speaker/speaker.go index fc83208..94d58e9 100644 --- a/speaker/speaker.go +++ b/speaker/speaker.go @@ -39,7 +39,7 @@ func Init(sampleRate beep.SampleRate, bufferSize int) error { SampleRate: int(sampleRate), ChannelCount: channelCount, Format: otoFormat, - BufferSize: sampleRate.D(bufferSize), + BufferSize: 0, // use the default }) if err != nil { return errors.Wrap(err, "failed to initialize speaker") @@ -47,6 +47,7 @@ func Init(sampleRate beep.SampleRate, bufferSize int) error { <-readyChan player = context.NewPlayer(newReaderFromStreamer(&mixer)) + player.SetBufferSize(bufferSize * bytesPerSample) player.Play() return nil From 3de56070d98331de89158578657f554972ad4d26 Mon Sep 17 00:00:00 2001 From: Mark Kremer Date: Thu, 9 Nov 2023 18:03:06 +0100 Subject: [PATCH 2/2] Tweak the speaker's context & player's buffer sizes --- speaker/speaker.go | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/speaker/speaker.go b/speaker/speaker.go index 94d58e9..9c5b080 100644 --- a/speaker/speaker.go +++ b/speaker/speaker.go @@ -2,11 +2,13 @@ package speaker import ( - "github.com/ebitengine/oto/v3" - "github.com/gopxl/beep" - "github.com/pkg/errors" "io" "sync" + + "github.com/ebitengine/oto/v3" + "github.com/pkg/errors" + + "github.com/gopxl/beep" ) const channelCount = 2 @@ -33,13 +35,21 @@ func Init(sampleRate beep.SampleRate, bufferSize int) error { mixer = beep.Mixer{} + // We split the total amount of buffer size between the driver and the player. + // This seems to be a decent ratio on my machine, but it may have different + // results on other OS's because of different underlying implementations. + // Both buffers try to keep themselves filled, so the total buffered + // number of samples should be some number less than bufferSize. + driverBufferSize := bufferSize / 2 + playerBufferSize := bufferSize / 2 + var err error var readyChan chan struct{} context, readyChan, err := oto.NewContext(&oto.NewContextOptions{ SampleRate: int(sampleRate), ChannelCount: channelCount, Format: otoFormat, - BufferSize: 0, // use the default + BufferSize: sampleRate.D(driverBufferSize), }) if err != nil { return errors.Wrap(err, "failed to initialize speaker") @@ -47,7 +57,7 @@ func Init(sampleRate beep.SampleRate, bufferSize int) error { <-readyChan player = context.NewPlayer(newReaderFromStreamer(&mixer)) - player.SetBufferSize(bufferSize * bytesPerSample) + player.SetBufferSize(playerBufferSize * bytesPerSample) player.Play() return nil