audio: Add player methods

This commit is contained in:
Hajime Hoshi 2016-03-06 18:55:20 +09:00
parent 38e36dedc1
commit 5ba5a1fb90

View File

@ -18,6 +18,7 @@ import (
"fmt" "fmt"
"io" "io"
"sync" "sync"
"time"
) )
// TODO: In JavaScript, mixing should be done by WebAudio for performance. // TODO: In JavaScript, mixing should be done by WebAudio for performance.
@ -80,6 +81,7 @@ func (s *mixedPlayersStream) Read(b []byte) (int, error) {
} }
for p := range s.context.players { for p := range s.context.players {
p.buf = p.buf[ll:] p.buf = p.buf[ll:]
p.pos += int64(ll)
} }
for _, p := range closed { for _, p := range closed {
delete(s.context.players, p) delete(s.context.players, p)
@ -113,6 +115,7 @@ type Player struct {
context *Context context *Context
src io.ReadSeeker src io.ReadSeeker
buf []byte buf []byte
pos int64
} }
// NewPlayer creates a new player with the given data to the given channel. // NewPlayer creates a new player with the given data to the given channel.
@ -121,17 +124,20 @@ type Player struct {
// //
// src's format must be linear PCM (16bits, 2 channel stereo, little endian) // src's format must be linear PCM (16bits, 2 channel stereo, little endian)
// without a header (e.g. RIFF header). // without a header (e.g. RIFF header).
//
// TODO: Pass sample rate and num of channels.
func (c *Context) NewPlayer(src io.ReadSeeker) (*Player, error) { func (c *Context) NewPlayer(src io.ReadSeeker) (*Player, error) {
c.Lock() c.Lock()
defer c.Unlock() defer c.Unlock()
p := &Player{ p := &Player{
context: c, context: c,
src: src, src: src,
buf: []byte{}, buf: []byte{},
} }
// Get the current position of the source.
pos, err := p.src.Seek(0, 1)
if err != nil {
return nil, err
}
p.pos = pos
return p, nil return p, nil
} }
@ -143,9 +149,25 @@ func (p *Player) Play() error {
return nil return nil
} }
// TODO: IsPlaying func (p *Player) IsPlaying() bool {
// TODO: Stop _, ok := p.context.players[p]
// TODO: Seek return ok
}
func (p *Player) Rewind() error {
return p.Seek(0)
}
func (p *Player) Seek(offset time.Duration) error {
p.buf = []byte{}
o := int64(offset) * int64(p.context.sampleRate) / int64(time.Second)
pos, err := p.src.Seek(o, 0)
if err != nil {
return err
}
p.pos = pos
return nil
}
func (p *Player) Pause() error { func (p *Player) Pause() error {
p.context.Lock() p.context.Lock()
@ -154,3 +176,10 @@ func (p *Player) Pause() error {
delete(p.context.players, p) delete(p.context.players, p)
return nil return nil
} }
func (p *Player) Current() time.Duration {
return time.Duration(p.pos) * time.Second / time.Duration(p.context.sampleRate)
}
// TODO: Volume / SetVolume?
// TODO: Panning