From eca9f5ff73f8accec92fcfd4c6e79a3a95209504 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Thu, 7 Nov 2019 01:09:40 +0900 Subject: [PATCH] audio: Bug fix: Fill empty data even when audio is suspended When writing is stopped on Oto's players, unexpected delaying happens. The ideal solution is to have APIs to suspend and resume Oto's player, but this is not easy. For a temporary solution, write zero values on the players when audio is suspended. Fixes #975 --- audio/audio.go | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/audio/audio.go b/audio/audio.go index f5b32060e..f7c1c3598 100644 --- a/audio/audio.go +++ b/audio/audio.go @@ -63,11 +63,11 @@ type Context struct { sampleRate int err error ready bool + suspended bool players map[*playerImpl]struct{} - m sync.Mutex - semaphore chan struct{} + m sync.Mutex } var ( @@ -75,6 +75,8 @@ var ( theContextLock sync.Mutex ) +var emptyBytes = make([]byte, 256) + // NewContext creates a new audio context with the given sample rate. // // The sample rate is also used for decoding MP3 with audio/mp3 package @@ -99,16 +101,19 @@ func NewContext(sampleRate int) (*Context, error) { c: newContext(sampleRate), players: map[*playerImpl]struct{}{}, inited: make(chan struct{}), - semaphore: make(chan struct{}, 1), } theContext = c h := getHook() h.OnSuspendAudio(func() { - c.semaphore <- struct{}{} + c.m.Lock() + c.suspended = true + c.m.Unlock() }) h.OnResumeAudio(func() { - <-c.semaphore + c.m.Lock() + c.suspended = false + c.m.Unlock() }) h.AppendHookOnBeforeUpdate(func() error { @@ -455,10 +460,14 @@ func (p *playerImpl) read() ([]byte, bool) { const bufSize = 2048 - p.context.semaphore <- struct{}{} - defer func() { - <-p.context.semaphore - }() + // If audio is suspended, fill zero values not to cause delay (#975). + // TODO: Oto's players should be able to be suspended and resumed. + p.context.m.Lock() + s := p.context.suspended + p.context.m.Unlock() + if s { + return emptyBytes, true + } newBuf := make([]byte, bufSize-len(p.buf)) n, err := p.src.Read(newBuf)