audio: remove locks from (*Player).Position

This commit is contained in:
Hajime Hoshi 2024-11-06 21:12:05 +09:00
parent 1014e45365
commit 0981355b61

View File

@ -18,6 +18,7 @@ import (
"io" "io"
"runtime" "runtime"
"sync" "sync"
"sync/atomic"
"time" "time"
) )
@ -73,10 +74,10 @@ type playerImpl struct {
initBufferSize int initBufferSize int
bytesPerSample int bytesPerSample int
// adjustedPosition is the player's more accurate position. // adjustedPosition is the player's more accurate position as time.Duration.
// The underlying buffer might not be changed even if the player is playing. // The underlying buffer might not be changed even if the player is playing.
// adjustedPosition is adjusted by the time duration during the player position doesn't change while its playing. // adjustedPosition is adjusted by the time duration during the player position doesn't change while its playing.
adjustedPosition time.Duration adjustedPosition atomic.Int64
// lastSamples is the last value of the number of samples. // lastSamples is the last value of the number of samples.
// When lastSamples is a negative number, this value is not initialized yet. // When lastSamples is a negative number, this value is not initialized yet.
@ -269,9 +270,7 @@ func (p *playerImpl) Close() error {
} }
func (p *playerImpl) Position() time.Duration { func (p *playerImpl) Position() time.Duration {
p.m.Lock() return time.Duration(p.adjustedPosition.Load())
defer p.m.Unlock()
return p.adjustedPosition
} }
func (p *playerImpl) Rewind() error { func (p *playerImpl) Rewind() error {
@ -283,7 +282,7 @@ func (p *playerImpl) SetPosition(offset time.Duration) error {
defer p.m.Unlock() defer p.m.Unlock()
if offset == 0 && p.player == nil { if offset == 0 && p.player == nil {
p.adjustedPosition = 0 p.adjustedPosition.Store(0)
return nil return nil
} }
@ -297,7 +296,7 @@ func (p *playerImpl) SetPosition(offset time.Duration) error {
} }
p.lastSamples = -1 p.lastSamples = -1
// Just after setting a position, the buffer size should be 0 as no data is sent. // Just after setting a position, the buffer size should be 0 as no data is sent.
p.adjustedPosition = p.stream.positionInTimeDuration() p.adjustedPosition.Store(int64(p.stream.positionInTimeDuration()))
p.stopwatch.reset() p.stopwatch.reset()
if p.isPlaying() { if p.isPlaying() {
p.stopwatch.start() p.stopwatch.start()
@ -359,11 +358,11 @@ func (p *playerImpl) updatePosition() {
defer p.m.Unlock() defer p.m.Unlock()
if p.player == nil { if p.player == nil {
p.adjustedPosition = 0 p.adjustedPosition.Store(0)
return return
} }
if !p.context.IsReady() { if !p.context.IsReady() {
p.adjustedPosition = 0 p.adjustedPosition.Store(0)
return return
} }
@ -383,7 +382,7 @@ func (p *playerImpl) updatePosition() {
} }
// Update the adjusted position every tick. This is necessary to keep the position accurate. // Update the adjusted position every tick. This is necessary to keep the position accurate.
p.adjustedPosition = time.Duration(samples)*time.Second/time.Duration(p.factory.sampleRate) + adjustingTime p.adjustedPosition.Store(int64(time.Duration(samples)*time.Second/time.Duration(p.factory.sampleRate) + adjustingTime))
} }
type timeStream struct { type timeStream struct {