mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 03:08:54 +01:00
audio: Bug fix: players' buffer can be empty when seeking before proceeding (#366)
This commit is contained in:
parent
989aef8e2b
commit
d8f425962c
@ -287,12 +287,18 @@ func BytesReadSeekCloser(b []uint8) ReadSeekCloser {
|
|||||||
return &bytesReadSeekCloser{reader: bytes.NewReader(b)}
|
return &bytesReadSeekCloser{reader: bytes.NewReader(b)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type readingResult struct {
|
||||||
|
data []uint8
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
// Player is an audio player which has one stream.
|
// Player is an audio player which has one stream.
|
||||||
type Player struct {
|
type Player struct {
|
||||||
players *players
|
players *players
|
||||||
src ReadSeekCloser
|
src ReadSeekCloser
|
||||||
sampleRate int
|
sampleRate int
|
||||||
readingCh chan error
|
readingCh chan readingResult
|
||||||
|
seekCh chan int64
|
||||||
|
|
||||||
buf []uint8
|
buf []uint8
|
||||||
pos int64
|
pos int64
|
||||||
@ -320,6 +326,7 @@ func NewPlayer(context *Context, src ReadSeekCloser) (*Player, error) {
|
|||||||
players: context.players,
|
players: context.players,
|
||||||
src: src,
|
src: src,
|
||||||
sampleRate: context.sampleRate,
|
sampleRate: context.sampleRate,
|
||||||
|
seekCh: make(chan int64, 1),
|
||||||
buf: []uint8{},
|
buf: []uint8{},
|
||||||
volume: 1,
|
volume: 1,
|
||||||
}
|
}
|
||||||
@ -369,28 +376,38 @@ func (p *Player) Close() error {
|
|||||||
|
|
||||||
func (p *Player) readToBuffer(length int) (int, error) {
|
func (p *Player) readToBuffer(length int) (int, error) {
|
||||||
if p.readingCh == nil {
|
if p.readingCh == nil {
|
||||||
p.readingCh = make(chan error)
|
p.readingCh = make(chan readingResult)
|
||||||
go func() {
|
go func() {
|
||||||
defer close(p.readingCh)
|
defer close(p.readingCh)
|
||||||
bb := make([]uint8, length)
|
b := make([]uint8, length)
|
||||||
p.srcM.Lock()
|
p.srcM.Lock()
|
||||||
n, err := p.src.Read(bb)
|
n, err := p.src.Read(b)
|
||||||
p.srcM.Unlock()
|
p.srcM.Unlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.readingCh <- err
|
p.readingCh <- readingResult{
|
||||||
|
err: err,
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if 0 < n {
|
p.readingCh <- readingResult{
|
||||||
p.m.Lock()
|
data: b[:n],
|
||||||
p.buf = append(p.buf, bb[:n]...)
|
|
||||||
p.m.Unlock()
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
select {
|
select {
|
||||||
case err := <-p.readingCh:
|
case pos := <-p.seekCh:
|
||||||
|
p.buf = []uint8{}
|
||||||
|
p.pos = pos
|
||||||
|
return 0, nil
|
||||||
|
case r := <-p.readingCh:
|
||||||
|
if r.err != nil {
|
||||||
|
return 0, r.err
|
||||||
|
}
|
||||||
|
if len(r.data) > 0 {
|
||||||
|
p.buf = append(p.buf, r.data...)
|
||||||
|
}
|
||||||
p.readingCh = nil
|
p.readingCh = nil
|
||||||
return len(p.buf), err
|
return len(p.buf), nil
|
||||||
case <-time.After(15 * time.Millisecond):
|
case <-time.After(15 * time.Millisecond):
|
||||||
return length, nil
|
return length, nil
|
||||||
}
|
}
|
||||||
@ -416,10 +433,8 @@ func (p *Player) proceed(length int) {
|
|||||||
if p.readingCh != nil {
|
if p.readingCh != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
p.m.Lock()
|
|
||||||
p.buf = p.buf[length:]
|
p.buf = p.buf[length:]
|
||||||
p.pos += int64(length)
|
p.pos += int64(length)
|
||||||
p.m.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Play plays the stream.
|
// Play plays the stream.
|
||||||
@ -462,10 +477,7 @@ func (p *Player) Seek(offset time.Duration) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
p.m.Lock()
|
p.seekCh <- pos
|
||||||
p.buf = []uint8{}
|
|
||||||
p.pos = pos
|
|
||||||
p.m.Unlock()
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user