audio: Refactoring

This commit is contained in:
Hajime Hoshi 2021-01-07 01:30:03 +09:00
parent e77beac235
commit bda285b376
2 changed files with 26 additions and 13 deletions

View File

@ -90,6 +90,7 @@ var (
func NewContext(sampleRate int) *Context { func NewContext(sampleRate int) *Context {
theContextLock.Lock() theContextLock.Lock()
defer theContextLock.Unlock() defer theContextLock.Unlock()
if theContext != nil { if theContext != nil {
panic("audio: context is already created") panic("audio: context is already created")
} }
@ -213,6 +214,18 @@ func (c *Context) SampleRate() int {
return c.sampleRate return c.sampleRate
} }
func (c *Context) acquireSemaphore() {
c.semaphore <- struct{}{}
}
func (c *Context) releaseSemaphore() {
<-c.semaphore
}
func (c *Context) waitUntilInited() {
<-c.inited
}
// Player is an audio player which has one stream. // Player is an audio player which has one stream.
// //
// Even when all references to a Player object is gone, // Even when all references to a Player object is gone,
@ -255,7 +268,7 @@ type playerImpl interface {
// A Player doesn't close src even if src implements io.Closer. // A Player doesn't close src even if src implements io.Closer.
// Closing the source is src owner's responsibility. // Closing the source is src owner's responsibility.
func NewPlayer(context *Context, src io.Reader) (*Player, error) { func NewPlayer(context *Context, src io.Reader) (*Player, error) {
pi, err := newWriterContextPlayerImpl(context, src) pi, err := newWriterContextPlayerImpl(context, context.c, src)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -50,8 +50,8 @@ func newWriterContext(sampleRate int) writerContext {
type writerContextPlayerImpl struct { type writerContextPlayerImpl struct {
context *Context context *Context
writerContext writerContext
src io.Reader src io.Reader
sampleRate int
playing bool playing bool
closedExplicitly bool closedExplicitly bool
isLoopActive bool isLoopActive bool
@ -64,11 +64,11 @@ type writerContextPlayerImpl struct {
m sync.Mutex m sync.Mutex
} }
func newWriterContextPlayerImpl(context *Context, src io.Reader) (*writerContextPlayerImpl, error) { func newWriterContextPlayerImpl(context *Context, writerContext writerContext, src io.Reader) (*writerContextPlayerImpl, error) {
p := &writerContextPlayerImpl{ p := &writerContextPlayerImpl{
context: context, context: context,
writerContext: writerContext,
src: src, src: src,
sampleRate: context.sampleRate,
volume: 1, volume: 1,
} }
if seeker, ok := p.src.(io.Seeker); ok { if seeker, ok := p.src.(io.Seeker); ok {
@ -117,9 +117,9 @@ func (p *writerContextPlayerImpl) Play() {
} }
func (p *writerContextPlayerImpl) loop() { func (p *writerContextPlayerImpl) loop() {
<-p.context.inited p.context.waitUntilInited()
w := p.context.c.NewPlayer() w := p.writerContext.NewPlayer()
wclosed := make(chan struct{}) wclosed := make(chan struct{})
defer func() { defer func() {
<-wclosed <-wclosed
@ -176,9 +176,9 @@ func (p *writerContextPlayerImpl) read() ([]byte, bool) {
const bufSize = 2048 const bufSize = 2048
p.context.semaphore <- struct{}{} p.context.acquireSemaphore()
defer func() { defer func() {
<-p.context.semaphore p.context.releaseSemaphore()
}() }()
if p.readbuf == nil { if p.readbuf == nil {
@ -228,7 +228,7 @@ func (p *writerContextPlayerImpl) Seek(offset time.Duration) error {
p.m.Lock() p.m.Lock()
defer p.m.Unlock() defer p.m.Unlock()
o := int64(offset) * bytesPerSample * int64(p.sampleRate) / int64(time.Second) o := int64(offset) * bytesPerSample * int64(p.context.SampleRate()) / int64(time.Second)
o = o - (o % bytesPerSample) o = o - (o % bytesPerSample)
seeker, ok := p.src.(io.Seeker) seeker, ok := p.src.(io.Seeker)
@ -255,7 +255,7 @@ func (p *writerContextPlayerImpl) Current() time.Duration {
p.m.Lock() p.m.Lock()
sample := p.pos / bytesPerSample sample := p.pos / bytesPerSample
p.m.Unlock() p.m.Unlock()
return time.Duration(sample) * time.Second / time.Duration(p.sampleRate) return time.Duration(sample) * time.Second / time.Duration(p.context.SampleRate())
} }
func (p *writerContextPlayerImpl) Volume() float64 { func (p *writerContextPlayerImpl) Volume() float64 {