mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-10 04:57:26 +01:00
audio: Split locks
This commit is contained in:
parent
e7478b794a
commit
873b3905df
@ -313,7 +313,8 @@ type Player struct {
|
|||||||
pos int64
|
pos int64
|
||||||
volume float64
|
volume float64
|
||||||
|
|
||||||
sync.RWMutex
|
srcM sync.Mutex
|
||||||
|
m sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPlayer creates a new player with the given stream.
|
// NewPlayer creates a new player with the given stream.
|
||||||
@ -375,45 +376,47 @@ func NewPlayerFromBytes(context *Context, src []byte) (*Player, error) {
|
|||||||
func (p *Player) Close() error {
|
func (p *Player) Close() error {
|
||||||
p.players.removePlayer(p)
|
p.players.removePlayer(p)
|
||||||
runtime.SetFinalizer(p, nil)
|
runtime.SetFinalizer(p, nil)
|
||||||
p.Lock()
|
p.srcM.Lock()
|
||||||
err := p.src.Close()
|
err := p.src.Close()
|
||||||
p.Unlock()
|
p.srcM.Unlock()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Player) readToBuffer(length int) error {
|
func (p *Player) readToBuffer(length int) error {
|
||||||
p.Lock()
|
p.srcM.Lock()
|
||||||
|
p.m.Lock()
|
||||||
bb := make([]byte, length)
|
bb := make([]byte, length)
|
||||||
n, err := p.src.Read(bb)
|
n, err := p.src.Read(bb)
|
||||||
if 0 < n {
|
if 0 < n {
|
||||||
p.buf = append(p.buf, bb[:n]...)
|
p.buf = append(p.buf, bb[:n]...)
|
||||||
}
|
}
|
||||||
p.Unlock()
|
p.m.Unlock()
|
||||||
|
p.srcM.Unlock()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Player) bufferToInt16(lengthInBytes int) []int16 {
|
func (p *Player) bufferToInt16(lengthInBytes int) []int16 {
|
||||||
p.RLock()
|
p.m.RLock()
|
||||||
r := make([]int16, lengthInBytes/2)
|
r := make([]int16, lengthInBytes/2)
|
||||||
for i := 0; i < lengthInBytes/2; i++ {
|
for i := 0; i < lengthInBytes/2; i++ {
|
||||||
r[i] = int16(p.buf[2*i]) | (int16(p.buf[2*i+1]) << 8)
|
r[i] = int16(p.buf[2*i]) | (int16(p.buf[2*i+1]) << 8)
|
||||||
r[i] = int16(float64(r[i]) * p.volume)
|
r[i] = int16(float64(r[i]) * p.volume)
|
||||||
}
|
}
|
||||||
p.RUnlock()
|
p.m.RUnlock()
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Player) proceed(length int) {
|
func (p *Player) proceed(length int) {
|
||||||
p.Lock()
|
p.m.Lock()
|
||||||
p.buf = p.buf[length:]
|
p.buf = p.buf[length:]
|
||||||
p.pos += int64(length)
|
p.pos += int64(length)
|
||||||
p.Unlock()
|
p.m.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Player) bufferLength() int {
|
func (p *Player) bufferLength() int {
|
||||||
p.RLock()
|
p.m.RLock()
|
||||||
l := len(p.buf)
|
l := len(p.buf)
|
||||||
p.RUnlock()
|
p.m.RUnlock()
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -453,14 +456,16 @@ func (p *Player) Seek(offset time.Duration) error {
|
|||||||
defer p.players.removeSeeking(p)
|
defer p.players.removeSeeking(p)
|
||||||
o := int64(offset) * bytesPerSample * channelNum * int64(p.sampleRate) / int64(time.Second)
|
o := int64(offset) * bytesPerSample * channelNum * int64(p.sampleRate) / int64(time.Second)
|
||||||
o &= mask
|
o &= mask
|
||||||
p.Lock()
|
p.srcM.Lock()
|
||||||
defer p.Unlock()
|
|
||||||
p.buf = []byte{}
|
|
||||||
pos, err := p.src.Seek(o, io.SeekStart)
|
pos, err := p.src.Seek(o, io.SeekStart)
|
||||||
|
p.srcM.Unlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
p.m.Lock()
|
||||||
|
p.buf = []byte{}
|
||||||
p.pos = pos
|
p.pos = pos
|
||||||
|
p.m.Unlock()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -478,19 +483,21 @@ func (p *Player) Pause() error {
|
|||||||
//
|
//
|
||||||
// Current is concurrent safe.
|
// Current is concurrent safe.
|
||||||
func (p *Player) Current() time.Duration {
|
func (p *Player) Current() time.Duration {
|
||||||
p.RLock()
|
p.m.RLock()
|
||||||
defer p.RUnlock()
|
|
||||||
sample := p.pos / bytesPerSample / channelNum
|
sample := p.pos / bytesPerSample / channelNum
|
||||||
return time.Duration(sample) * time.Second / time.Duration(p.sampleRate)
|
t := time.Duration(sample) * time.Second / time.Duration(p.sampleRate)
|
||||||
|
p.m.RUnlock()
|
||||||
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
// Volume returns the current volume of this player [0-1].
|
// Volume returns the current volume of this player [0-1].
|
||||||
//
|
//
|
||||||
// Volume is concurrent safe.
|
// Volume is concurrent safe.
|
||||||
func (p *Player) Volume() float64 {
|
func (p *Player) Volume() float64 {
|
||||||
p.RLock()
|
p.m.RLock()
|
||||||
defer p.RUnlock()
|
v := p.volume
|
||||||
return p.volume
|
p.m.RUnlock()
|
||||||
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetVolume sets the volume of this player.
|
// SetVolume sets the volume of this player.
|
||||||
@ -498,8 +505,8 @@ func (p *Player) Volume() float64 {
|
|||||||
//
|
//
|
||||||
// SetVolume is concurrent safe.
|
// SetVolume is concurrent safe.
|
||||||
func (p *Player) SetVolume(volume float64) {
|
func (p *Player) SetVolume(volume float64) {
|
||||||
p.Lock()
|
p.m.Lock()
|
||||||
defer p.Unlock()
|
defer p.m.Unlock()
|
||||||
// The condition must be true when volume is NaN.
|
// The condition must be true when volume is NaN.
|
||||||
if !(0 <= volume && volume <= 1) {
|
if !(0 <= volume && volume <= 1) {
|
||||||
panic("audio: volume must be in between 0 and 1")
|
panic("audio: volume must be in between 0 and 1")
|
||||||
|
Loading…
Reference in New Issue
Block a user