diff --git a/examples/audio/main.go b/examples/audio/main.go index 41c9f6e2d..a698e0cdf 100644 --- a/examples/audio/main.go +++ b/examples/audio/main.go @@ -78,6 +78,14 @@ func playerBarRect() (x, y, w, h int) { return } +type SEStream struct { + *bytes.Reader +} + +func (s *SEStream) Close() error { + return nil +} + func (p *Player) updateSE() error { if seStream == nil { return nil @@ -99,7 +107,7 @@ func (p *Player) updateSE() error { } seBuffer = b } - sePlayer, err := audioContext.NewPlayer(bytes.NewReader(seBuffer)) + sePlayer, err := audioContext.NewPlayer(&SEStream{bytes.NewReader(seBuffer)}) if err != nil { return err } @@ -168,6 +176,10 @@ func (p *Player) updateBar() error { return p.audioPlayer.Seek(pos) } +func (p *Player) close() error { + return p.audioPlayer.Close() +} + func update(screen *ebiten.Image) error { audioContext.Update() if musicPlayer == nil { @@ -272,4 +284,9 @@ func main() { if err := ebiten.Run(update, screenWidth, screenHeight, 2, "Audio (Ebiten Demo)"); err != nil { log.Fatal(err) } + if musicPlayer != nil { + if err := musicPlayer.close(); err != nil { + log.Fatal(err) + } + } } diff --git a/examples/sinewave/main.go b/examples/sinewave/main.go index 5b07eab33..d7d6217b0 100644 --- a/examples/sinewave/main.go +++ b/examples/sinewave/main.go @@ -76,6 +76,10 @@ func (s *stream) Seek(offset int64, whence int) (int64, error) { return s.position, nil } +func (s *stream) Close() error { + return nil +} + var player *audio.Player func update(screen *ebiten.Image) error { diff --git a/exp/audio/audio.go b/exp/audio/audio.go index fabdba8e7..db6270671 100644 --- a/exp/audio/audio.go +++ b/exp/audio/audio.go @@ -17,6 +17,7 @@ package audio import ( "fmt" "io" + "runtime" "sync" "time" @@ -148,9 +149,14 @@ func (c *Context) SampleRate() int { return c.sampleRate } +type ReadSeekCloser interface { + io.ReadSeeker + io.Closer +} + type Player struct { context *Context - src io.ReadSeeker + src ReadSeekCloser buf []byte pos int64 volume float64 @@ -162,7 +168,7 @@ type Player struct { // // src's format must be linear PCM (16bits, 2 channel stereo, little endian) // without a header (e.g. RIFF header). -func (c *Context) NewPlayer(src io.ReadSeeker) (*Player, error) { +func (c *Context) NewPlayer(src ReadSeekCloser) (*Player, error) { c.Lock() defer c.Unlock() p := &Player{ @@ -177,9 +183,15 @@ func (c *Context) NewPlayer(src io.ReadSeeker) (*Player, error) { return nil, err } p.pos = pos + runtime.SetFinalizer(p, (*Player).Close) return p, nil } +func (p *Player) Close() error { + runtime.SetFinalizer(p, nil) + return p.src.Close() +} + func (p *Player) readToBuffer(length int) (int, error) { bb := make([]byte, length) n, err := p.src.Read(bb) diff --git a/exp/audio/vorbis/stream.go b/exp/audio/vorbis/stream.go index 00c0ff0d3..983bef6b1 100644 --- a/exp/audio/vorbis/stream.go +++ b/exp/audio/vorbis/stream.go @@ -32,6 +32,11 @@ func (s *Stream) Seek(offset int64, whence int) (int64, error) { return s.buf.Seek(offset, whence) } +func (s *Stream) Close() error { + s.buf = nil + return nil +} + func (s *Stream) Len() time.Duration { const bytesPerSample = 4 return time.Duration(s.buf.Len()/bytesPerSample) * time.Second / time.Duration(s.sampleRate) diff --git a/exp/audio/wav/decode.go b/exp/audio/wav/decode.go index 5f4d229f0..3de898ee1 100644 --- a/exp/audio/wav/decode.go +++ b/exp/audio/wav/decode.go @@ -43,6 +43,11 @@ func (s *Stream) Seek(offset int64, whence int) (int64, error) { return s.buf.Seek(offset, whence) } +func (s *Stream) Close() error { + s.buf = nil + return nil +} + func (s *Stream) Len() time.Duration { const bytesPerSample = 4 return time.Duration(s.buf.Len()/bytesPerSample) * time.Second / time.Duration(s.sampleRate)