audio: Consider the state of the player's starting and seeking

Before this change, if a player's buffer was not enough for
reading, 0 value were used and this caused noises. The reading
size should be aligned with all the players.

Just after a player just starts playing or seeking, the buffer is
empty but other players should not wait for the player read since
decoding might take some time.

To summerize, this change aligns the read buffer sizes but use
zero values only when the player just starts or seeks.
This commit is contained in:
Hajime Hoshi 2018-06-09 19:00:47 +09:00
parent 91958d24ef
commit 2fee7a6fe5

View File

@ -74,6 +74,18 @@ func (p *players) Read(b []byte) (int, error) {
l := len(b)
l &= mask
for player := range p.players {
if player.isJustAfterStartedOrSeeked() {
println("oh")
continue
}
s := player.bufferSizeInBytes()
if l > s {
l = s
l &= mask
}
}
b16s := [][]int16{}
for player := range p.players {
buf, err := player.bufferToInt16(l)
@ -82,6 +94,7 @@ func (p *players) Read(b []byte) (int, error) {
}
b16s = append(b16s, buf)
}
for i := 0; i < l/2; i++ {
x := 0
for _, b16 := range b16s {
@ -349,7 +362,7 @@ func NewPlayer(context *Context, src io.ReadCloser) (*Player, error) {
players: context.players,
src: src,
sampleRate: context.sampleRate,
buf: []byte{},
buf: nil,
volume: 1,
closeCh: make(chan struct{}),
closedCh: make(chan struct{}),
@ -526,13 +539,15 @@ func (p *Player) readLoop() {
return
}
lengthInBytes := len(buf) * 2
l := lengthInBytes
if len(p.buf) < lengthInBytes && !p.srcEOF {
if p.isJustAfterStartedOrSeekedImpl() {
// Return zero values.
p.proceededCh <- proceededValues{buf, nil}
break
}
lengthInBytes := len(buf) * 2
l := lengthInBytes
if l > len(p.buf) {
l = len(p.buf)
}
@ -543,7 +558,7 @@ func (p *Player) readLoop() {
p.pos += int64(l)
p.buf = p.buf[l:]
p.proceededCh <- proceededValues{buf, nil}
p.proceededCh <- proceededValues{buf[:l/2], nil}
case f := <-p.syncCh:
f()
@ -566,6 +581,28 @@ func (p *Player) sync(f func()) bool {
}
}
func (p *Player) isJustAfterStartedOrSeeked() bool {
r := false
p.sync(func() {
r = p.isJustAfterStartedOrSeekedImpl()
})
return r
}
func (p *Player) isJustAfterStartedOrSeekedImpl() bool {
// When p.buf is nil, the player just starts playing or seeking.
// Note that this is different from len(p.buf) == 0 && p.buf != nil.
return p.buf == nil
}
func (p *Player) bufferSizeInBytes() int {
s := 0
p.sync(func() {
s = len(p.buf)
})
return s
}
func (p *Player) eof() bool {
r := false
p.sync(func() {