From aced228318f29967171bc57a1a28b043120311ef Mon Sep 17 00:00:00 2001 From: Mark Kremer Date: Sun, 7 Jan 2024 16:48:06 +0100 Subject: [PATCH] Add speaker.PlayAndWait --- speaker/speaker.go | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/speaker/speaker.go b/speaker/speaker.go index 9c5b080..d2fe2e8 100644 --- a/speaker/speaker.go +++ b/speaker/speaker.go @@ -4,6 +4,7 @@ package speaker import ( "io" "sync" + "time" "github.com/ebitengine/oto/v3" "github.com/pkg/errors" @@ -21,6 +22,8 @@ var ( mixer beep.Mixer context *oto.Context player *oto.Player + + bufferDuration time.Duration ) // Init initializes audio playback through speaker. Must be called before using this package. @@ -45,7 +48,7 @@ func Init(sampleRate beep.SampleRate, bufferSize int) error { var err error var readyChan chan struct{} - context, readyChan, err := oto.NewContext(&oto.NewContextOptions{ + context, readyChan, err = oto.NewContext(&oto.NewContextOptions{ SampleRate: int(sampleRate), ChannelCount: channelCount, Format: otoFormat, @@ -60,6 +63,8 @@ func Init(sampleRate beep.SampleRate, bufferSize int) error { player.SetBufferSize(playerBufferSize * bytesPerSample) player.Play() + bufferDuration = sampleRate.D(bufferSize) + return nil } @@ -95,6 +100,25 @@ func Play(s ...beep.Streamer) { mu.Unlock() } +// PlayAndWait plays all provided Streamers through the speaker and waits until they have all finished playing. +func PlayAndWait(s ...beep.Streamer) { + mu.Lock() + var wg sync.WaitGroup + wg.Add(len(s)) + for _, e := range s { + mixer.Add(beep.Seq(e, beep.Callback(func() { + wg.Done() + }))) + } + mu.Unlock() + + // Wait for the streamers to drain. + wg.Wait() + + // Wait the expected time it takes for the samples to reach the driver. + time.Sleep(bufferDuration) +} + // Clear removes all currently playing Streamers from the speaker. // Previously buffered samples may still be played. func Clear() {