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
This commit is contained in:
Hajime Hoshi 2019-11-07 01:09:40 +09:00
parent ddba7f0ee0
commit 529dddda53

View File

@ -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)