diff --git a/audio/audio.go b/audio/audio.go index 4fa705a26..85e1a39b1 100644 --- a/audio/audio.go +++ b/audio/audio.go @@ -170,13 +170,14 @@ func (p *players) hasSource(src ReadSeekCloser) bool { // You can also call Update independently from the game loop as 'async mode'. // In this case, audio goes on even when the game stops e.g. by diactivating the screen. type Context struct { - players *players - playerWriteCh chan []uint8 - playerErrCh chan error - playerCloseCh chan struct{} - sampleRate int - frames int64 - writtenBytes int64 + players *players + playerWriteCh chan []uint8 + playerErrCh chan error + playerCloseCh chan struct{} + sampleRate int + frames int64 + writtenBytes int64 + unwrittenCount int } var ( @@ -223,8 +224,7 @@ func (c *Context) Update() error { // e.g. a variable for JVM on Android might not be set. if c.playerWriteCh == nil { init := make(chan error) - // 4 is (buffer size) / (bytes for 1 frame). - c.playerWriteCh = make(chan []uint8, 4) + c.playerWriteCh = make(chan []uint8) c.playerErrCh = make(chan error, 1) c.playerCloseCh = make(chan struct{}) go func() { @@ -269,10 +269,18 @@ func (c *Context) Update() error { close(c.playerCloseCh) return err } + // Discard when the buffer queue seems full. + if c.unwrittenCount > 0 { + c.unwrittenCount-- + return nil + } select { case c.playerWriteCh <- buf: // Writing can block. Don't wait for the result here. default: + // The current buffer size is 1/15 [sec] = 4 [frames]. + // Wait for 5 [frames] which is more than 4. + c.unwrittenCount = 5 } return nil }