Skip to content

Commit

Permalink
add the BufferSizeSetter interface and Player.SetBufferSize
Browse files Browse the repository at this point in the history
Player.SetBufferSize adjuts its buffer size so that a real-time PCM
can be implemented easily.

In order to keep backward compatibility, the Player interface cannot
be modified.

Updates hajimehoshi/ebiten#2026
  • Loading branch information
hajimehoshi committed Mar 24, 2022
1 parent 0a05cf3 commit 585752a
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 19 deletions.
14 changes: 12 additions & 2 deletions driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ type Context struct {
//
// You cannot share r by multiple players.
//
// The returned player implements both Player and BufferSizeSetter.
//
// NewPlayer is concurrent-safe.
//
// All the functions of a Player returned by NewPlayer are concurrent-safe.
Expand Down Expand Up @@ -123,6 +125,14 @@ type Player interface {
io.Closer
}

// BufferSizeSetter sets a buffer size.
// A player created by (*Context).NewPlayer implments both Player and BufferSizeSetter.
type BufferSizeSetter interface {
// SetBufferSize sets the buffer size.
// If 0 is specified, the default buffer size is used.
SetBufferSize(bufferSize int)
}

type playerState int

const (
Expand All @@ -133,9 +143,9 @@ const (

// TODO: The term 'buffer' is confusing. Name each buffer with good terms.

// maxBufferSize returns the maximum size of the buffer for the audio source.
// defaultBufferSize returns the default size of the buffer for the audio source.
// This buffer is used when unreading on pausing the player.
func (c *context) maxBufferSize() int {
func (c *context) defaultBufferSize() int {
bytesPerSample := c.channelNum * c.bitDepthInBytes
s := c.sampleRate * bytesPerSample / 2 // 0.5[s]
// Align s in multiples of bytes per sample, or a buffer could have extra bytes.
Expand Down
54 changes: 37 additions & 17 deletions player.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,15 +116,16 @@ type player struct {
}

type playerImpl struct {
context *context
players *players
src io.Reader
volume float64
err atomicError
state playerState
tmpbuf []byte
buf []byte
eof bool
context *context
players *players
src io.Reader
volume float64
err atomicError
state playerState
tmpbuf []byte
buf []byte
eof bool
bufferSize int

m sync.Mutex
}
Expand All @@ -136,10 +137,11 @@ func (c *context) NewPlayer(src io.Reader) Player {
func newPlayer(context *context, players *players, src io.Reader) *player {
p := &player{
p: &playerImpl{
context: context,
players: players,
src: src,
volume: 1,
context: context,
players: players,
src: src,
volume: 1,
bufferSize: context.defaultBufferSize(),
},
}
runtime.SetFinalizer(p, (*player).Close)
Expand Down Expand Up @@ -181,9 +183,27 @@ func (p *playerImpl) Play() {
}
}

func (p *player) SetBufferSize(bufferSize int) {
p.p.setBufferSize(bufferSize)
}

func (p *playerImpl) setBufferSize(bufferSize int) {
p.m.Lock()
defer p.m.Unlock()

orig := p.bufferSize
p.bufferSize = bufferSize
if bufferSize == 0 {
p.bufferSize = p.context.defaultBufferSize()
}
if orig != p.bufferSize {
p.tmpbuf = nil
}
}

func (p *playerImpl) ensureTmpBuf() []byte {
if p.tmpbuf == nil {
p.tmpbuf = make([]byte, p.context.maxBufferSize())
p.tmpbuf = make([]byte, p.bufferSize)
}
return p.tmpbuf
}
Expand All @@ -198,7 +218,7 @@ func (p *playerImpl) playImpl() {

if !p.eof {
buf := p.ensureTmpBuf()
for len(p.buf) < p.context.maxBufferSize() {
for len(p.buf) < p.bufferSize {
n, err := p.src.Read(buf)
if err != nil && err != io.EOF {
p.setErrorImpl(err)
Expand Down Expand Up @@ -365,7 +385,7 @@ func (p *playerImpl) canReadSourceToBuffer() bool {
if p.eof {
return false
}
return len(p.buf) < p.context.maxBufferSize()
return len(p.buf) < p.bufferSize
}

func (p *playerImpl) readSourceToBuffer() {
Expand All @@ -379,7 +399,7 @@ func (p *playerImpl) readSourceToBuffer() {
return
}

if len(p.buf) >= p.context.maxBufferSize() {
if len(p.buf) >= p.bufferSize {
return
}

Expand Down

0 comments on commit 585752a

Please sign in to comment.