mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-12 22:17:26 +01:00
audio: Refactoring
This commit is contained in:
parent
e04e709a10
commit
a6b3f32f3a
@ -48,6 +48,10 @@ const (
|
|||||||
bytesPerSample = 2 * channelNum
|
bytesPerSample = 2 * channelNum
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type newPlayerImpler interface {
|
||||||
|
newPlayerImpl(context *Context, src io.Reader) (playerImpl, error)
|
||||||
|
}
|
||||||
|
|
||||||
// A Context represents a current state of audio.
|
// A Context represents a current state of audio.
|
||||||
//
|
//
|
||||||
// At most one Context object can exist in one process.
|
// At most one Context object can exist in one process.
|
||||||
@ -55,7 +59,7 @@ const (
|
|||||||
//
|
//
|
||||||
// For a typical usage example, see examples/wav/main.go.
|
// For a typical usage example, see examples/wav/main.go.
|
||||||
type Context struct {
|
type Context struct {
|
||||||
wc writerContext
|
np newPlayerImpler
|
||||||
|
|
||||||
// inited represents whether the audio device is initialized and available or not.
|
// inited represents whether the audio device is initialized and available or not.
|
||||||
// On Android, audio loop cannot be started unless JVM is accessible. After updating one frame, JVM should exist.
|
// On Android, audio loop cannot be started unless JVM is accessible. After updating one frame, JVM should exist.
|
||||||
@ -97,7 +101,7 @@ func NewContext(sampleRate int) *Context {
|
|||||||
|
|
||||||
c := &Context{
|
c := &Context{
|
||||||
sampleRate: sampleRate,
|
sampleRate: sampleRate,
|
||||||
wc: newWriterContext(sampleRate),
|
np: newWriterContext(sampleRate),
|
||||||
players: map[playerImpl]struct{}{},
|
players: map[playerImpl]struct{}{},
|
||||||
inited: make(chan struct{}),
|
inited: make(chan struct{}),
|
||||||
semaphore: make(chan struct{}, 1),
|
semaphore: make(chan struct{}, 1),
|
||||||
@ -268,7 +272,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, context.wc, src)
|
pi, err := context.np.newPlayerImpl(context, src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -19,15 +19,15 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
dummyContext struct{}
|
dummyDriver struct{}
|
||||||
dummyPlayer struct{}
|
dummyPlayer struct{}
|
||||||
)
|
)
|
||||||
|
|
||||||
func (d *dummyContext) NewPlayer() io.WriteCloser {
|
func (d *dummyDriver) NewPlayer() io.WriteCloser {
|
||||||
return &dummyPlayer{}
|
return &dummyPlayer{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *dummyContext) Close() error {
|
func (d *dummyDriver) Close() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ func (p *dummyPlayer) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
writerContextForTesting = &dummyContext{}
|
writerDriverForTesting = &dummyDriver{}
|
||||||
}
|
}
|
||||||
|
|
||||||
type dummyHook struct {
|
type dummyHook struct {
|
||||||
|
@ -21,14 +21,14 @@ import (
|
|||||||
"github.com/hajimehoshi/oto"
|
"github.com/hajimehoshi/oto"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newOtoContext(sampleRate int, initCh chan struct{}) *otoContext {
|
func newOtoDriver(sampleRate int, initCh chan struct{}) *otoDriver {
|
||||||
return &otoContext{
|
return &otoDriver{
|
||||||
sampleRate: sampleRate,
|
sampleRate: sampleRate,
|
||||||
initCh: initCh,
|
initCh: initCh,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type otoContext struct {
|
type otoDriver struct {
|
||||||
sampleRate int
|
sampleRate int
|
||||||
initCh <-chan struct{}
|
initCh <-chan struct{}
|
||||||
|
|
||||||
@ -36,18 +36,18 @@ type otoContext struct {
|
|||||||
once sync.Once
|
once sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *otoContext) NewPlayer() io.WriteCloser {
|
func (c *otoDriver) NewPlayer() io.WriteCloser {
|
||||||
return &otoPlayer{c: c}
|
return &otoPlayer{c: c}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *otoContext) Close() error {
|
func (c *otoDriver) Close() error {
|
||||||
if c.c == nil {
|
if c.c == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return c.c.Close()
|
return c.c.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *otoContext) ensureContext() error {
|
func (c *otoDriver) ensureContext() error {
|
||||||
var err error
|
var err error
|
||||||
c.once.Do(func() {
|
c.once.Do(func() {
|
||||||
<-c.initCh
|
<-c.initCh
|
||||||
@ -57,7 +57,7 @@ func (c *otoContext) ensureContext() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type otoPlayer struct {
|
type otoPlayer struct {
|
||||||
c *otoContext
|
c *otoDriver
|
||||||
p *oto.Player
|
p *oto.Player
|
||||||
once sync.Once
|
once sync.Once
|
||||||
}
|
}
|
@ -23,18 +23,18 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/v2/internal/hooks"
|
"github.com/hajimehoshi/ebiten/v2/internal/hooks"
|
||||||
)
|
)
|
||||||
|
|
||||||
// writerContext represents a context represented as io.WriteClosers.
|
// writerDriver represents a driver using io.WriteClosers.
|
||||||
// The actual implementation is oto.Context.
|
// The actual implementation is otoDriver.
|
||||||
type writerContext interface {
|
type writerDriver interface {
|
||||||
NewPlayer() io.WriteCloser
|
NewPlayer() io.WriteCloser
|
||||||
io.Closer
|
io.Closer
|
||||||
}
|
}
|
||||||
|
|
||||||
var writerContextForTesting writerContext
|
var writerDriverForTesting writerDriver
|
||||||
|
|
||||||
func newWriterContext(sampleRate int) writerContext {
|
func newWriterDriver(sampleRate int) writerDriver {
|
||||||
if writerContextForTesting != nil {
|
if writerDriverForTesting != nil {
|
||||||
return writerContextForTesting
|
return writerDriverForTesting
|
||||||
}
|
}
|
||||||
|
|
||||||
ch := make(chan struct{})
|
ch := make(chan struct{})
|
||||||
@ -45,12 +45,22 @@ func newWriterContext(sampleRate int) writerContext {
|
|||||||
})
|
})
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
return newOtoContext(sampleRate, ch)
|
return newOtoDriver(sampleRate, ch)
|
||||||
|
}
|
||||||
|
|
||||||
|
type writerContext struct {
|
||||||
|
driver writerDriver
|
||||||
|
}
|
||||||
|
|
||||||
|
func newWriterContext(sampleRate int) *writerContext {
|
||||||
|
return &writerContext{
|
||||||
|
driver: newWriterDriver(sampleRate),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type writerContextPlayerImpl struct {
|
type writerContextPlayerImpl struct {
|
||||||
context *Context
|
context *Context
|
||||||
writerContext writerContext
|
driver writerDriver
|
||||||
src io.Reader
|
src io.Reader
|
||||||
playing bool
|
playing bool
|
||||||
closedExplicitly bool
|
closedExplicitly bool
|
||||||
@ -64,12 +74,12 @@ type writerContextPlayerImpl struct {
|
|||||||
m sync.Mutex
|
m sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func newWriterContextPlayerImpl(context *Context, writerContext writerContext, src io.Reader) (*writerContextPlayerImpl, error) {
|
func (c *writerContext) newPlayerImpl(context *Context, src io.Reader) (playerImpl, error) {
|
||||||
p := &writerContextPlayerImpl{
|
p := &writerContextPlayerImpl{
|
||||||
context: context,
|
context: context,
|
||||||
writerContext: writerContext,
|
driver: c.driver,
|
||||||
src: src,
|
src: src,
|
||||||
volume: 1,
|
volume: 1,
|
||||||
}
|
}
|
||||||
if seeker, ok := p.src.(io.Seeker); ok {
|
if seeker, ok := p.src.(io.Seeker); ok {
|
||||||
// Get the current position of the source.
|
// Get the current position of the source.
|
||||||
@ -119,7 +129,7 @@ func (p *writerContextPlayerImpl) Play() {
|
|||||||
func (p *writerContextPlayerImpl) loop() {
|
func (p *writerContextPlayerImpl) loop() {
|
||||||
p.context.waitUntilInited()
|
p.context.waitUntilInited()
|
||||||
|
|
||||||
w := p.writerContext.NewPlayer()
|
w := p.driver.NewPlayer()
|
||||||
wclosed := make(chan struct{})
|
wclosed := make(chan struct{})
|
||||||
defer func() {
|
defer func() {
|
||||||
<-wclosed
|
<-wclosed
|
||||||
|
Loading…
Reference in New Issue
Block a user