mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 18:58:54 +01:00
parent
9009b293e5
commit
18113f259a
@ -132,7 +132,7 @@ func (p *players) hasPlayer(player *Player) bool {
|
|||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *players) hasSource(src ReadSeekCloser) bool {
|
func (p *players) hasSource(src io.ReadCloser) bool {
|
||||||
p.RLock()
|
p.RLock()
|
||||||
defer p.RUnlock()
|
defer p.RUnlock()
|
||||||
for player := range p.players {
|
for player := range p.players {
|
||||||
@ -328,7 +328,7 @@ func BytesReadSeekCloser(b []byte) ReadSeekCloser {
|
|||||||
// Player is an audio player which has one stream.
|
// Player is an audio player which has one stream.
|
||||||
type Player struct {
|
type Player struct {
|
||||||
players *players
|
players *players
|
||||||
src ReadSeekCloser
|
src io.ReadCloser
|
||||||
srcEOF bool
|
srcEOF bool
|
||||||
sampleRate int
|
sampleRate int
|
||||||
|
|
||||||
@ -362,11 +362,14 @@ type proceededValues struct {
|
|||||||
// without a header (e.g. RIFF header).
|
// without a header (e.g. RIFF header).
|
||||||
// The sample rate must be same as that of the audio context.
|
// The sample rate must be same as that of the audio context.
|
||||||
//
|
//
|
||||||
|
// The player is seekable when src is io.Seeker.
|
||||||
|
// Attempt to seek the player that is not io.Seeker causes panic.
|
||||||
|
//
|
||||||
// Note that the given src can't be shared with other Player objects.
|
// Note that the given src can't be shared with other Player objects.
|
||||||
//
|
//
|
||||||
// NewPlayer tries to call Seek of src to get the current position.
|
// NewPlayer tries to call Seek of src to get the current position.
|
||||||
// NewPlayer returns error when the Seek returns error.
|
// NewPlayer returns error when the Seek returns error.
|
||||||
func NewPlayer(context *Context, src ReadSeekCloser) (*Player, error) {
|
func NewPlayer(context *Context, src io.ReadCloser) (*Player, error) {
|
||||||
if context.players.hasSource(src) {
|
if context.players.hasSource(src) {
|
||||||
return nil, errors.New("audio: src cannot be shared with another Player")
|
return nil, errors.New("audio: src cannot be shared with another Player")
|
||||||
}
|
}
|
||||||
@ -385,12 +388,14 @@ func NewPlayer(context *Context, src ReadSeekCloser) (*Player, error) {
|
|||||||
proceededCh: make(chan proceededValues),
|
proceededCh: make(chan proceededValues),
|
||||||
syncCh: make(chan func()),
|
syncCh: make(chan func()),
|
||||||
}
|
}
|
||||||
// Get the current position of the source.
|
if seeker, ok := p.src.(io.Seeker); ok {
|
||||||
pos, err := p.src.Seek(0, io.SeekCurrent)
|
// Get the current position of the source.
|
||||||
if err != nil {
|
pos, err := seeker.Seek(0, io.SeekCurrent)
|
||||||
return nil, err
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
p.pos = pos
|
||||||
}
|
}
|
||||||
p.pos = pos
|
|
||||||
runtime.SetFinalizer(p, (*Player).Close)
|
runtime.SetFinalizer(p, (*Player).Close)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
@ -473,7 +478,11 @@ func (p *Player) readLoop() {
|
|||||||
return
|
return
|
||||||
|
|
||||||
case s := <-p.seekCh:
|
case s := <-p.seekCh:
|
||||||
pos, err := p.src.Seek(s.offset, s.whence)
|
seeker, ok := p.src.(io.Seeker)
|
||||||
|
if !ok {
|
||||||
|
panic("not reached")
|
||||||
|
}
|
||||||
|
pos, err := seeker.Seek(s.offset, s.whence)
|
||||||
p.buf = nil
|
p.buf = nil
|
||||||
p.pos = pos
|
p.pos = pos
|
||||||
p.srcEOF = false
|
p.srcEOF = false
|
||||||
@ -600,15 +609,25 @@ func (p *Player) IsPlaying() bool {
|
|||||||
|
|
||||||
// Rewind rewinds the current position to the start.
|
// Rewind rewinds the current position to the start.
|
||||||
//
|
//
|
||||||
|
// The passed source to NewPlayer must be io.Seeker, or Rewind panics.
|
||||||
|
//
|
||||||
// Rewind returns error when seeking the source stream returns error.
|
// Rewind returns error when seeking the source stream returns error.
|
||||||
func (p *Player) Rewind() error {
|
func (p *Player) Rewind() error {
|
||||||
|
if _, ok := p.src.(io.Seeker); !ok {
|
||||||
|
panic("audio: player to be rewinded must be io.Seeker")
|
||||||
|
}
|
||||||
return p.Seek(0)
|
return p.Seek(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Seek seeks the position with the given offset.
|
// Seek seeks the position with the given offset.
|
||||||
//
|
//
|
||||||
|
// The passed source to NewPlayer must be io.Seeker, or Seek panics.
|
||||||
|
//
|
||||||
// Seek returns error when seeking the source stream returns error.
|
// Seek returns error when seeking the source stream returns error.
|
||||||
func (p *Player) Seek(offset time.Duration) error {
|
func (p *Player) Seek(offset time.Duration) error {
|
||||||
|
if _, ok := p.src.(io.Seeker); !ok {
|
||||||
|
panic("audio: player to be sought must be io.Seeker")
|
||||||
|
}
|
||||||
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
|
||||||
select {
|
select {
|
||||||
|
@ -19,7 +19,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"log"
|
"log"
|
||||||
"math"
|
"math"
|
||||||
|
|
||||||
@ -73,23 +72,6 @@ func (s *stream) Read(data []byte) (int, error) {
|
|||||||
return len(data), nil
|
return len(data), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Seek is io.Seeker's Seek.
|
|
||||||
//
|
|
||||||
// whence must be io.SeekStart or io.SeekCurrent.
|
|
||||||
func (s *stream) Seek(offset int64, whence int) (int64, error) {
|
|
||||||
const length = sampleRate / frequency
|
|
||||||
switch whence {
|
|
||||||
case io.SeekStart:
|
|
||||||
s.position = offset
|
|
||||||
case io.SeekCurrent:
|
|
||||||
s.position += offset
|
|
||||||
default:
|
|
||||||
return 0, errors.New("whence must be io.SeekStart or io.SeekCurrent")
|
|
||||||
}
|
|
||||||
s.position %= length * 4
|
|
||||||
return s.position, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close is io.Closer's Close.
|
// Close is io.Closer's Close.
|
||||||
func (s *stream) Close() error {
|
func (s *stream) Close() error {
|
||||||
return nil
|
return nil
|
||||||
|
Loading…
Reference in New Issue
Block a user