audio: Move drivers to internal/driver

This commit is contained in:
Hajime Hoshi 2016-04-09 00:54:18 +09:00
parent 5c73357ef8
commit 2840bafd0a
5 changed files with 40 additions and 33 deletions

View File

@ -21,6 +21,7 @@ import (
"time"
"github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/exp/audio/internal/driver"
)
type mixingStream struct {
@ -44,7 +45,6 @@ func min(a, b int) int {
const (
channelNum = 2
bytesPerSample = 2
bitsPerSample = bytesPerSample * 8
// TODO: This assumes that channelNum is a power of 2.
mask = ^(channelNum*bytesPerSample - 1)
@ -197,15 +197,15 @@ func NewContext(sampleRate int) (*Context, error) {
players: map[*Player]struct{}{},
}
// TODO: Rename this other than player
p, err := newPlayer(c.stream, sampleRate)
p, err := driver.NewPlayer(c.stream, sampleRate, channelNum, bytesPerSample)
if err != nil {
return nil, err
}
go func() {
// TODO: Is it OK to close asap?
defer p.close()
defer p.Close()
for {
err := p.proceed()
err := p.Proceed()
if err == io.EOF {
break
}

View File

@ -14,25 +14,26 @@
// +build js
package audio
package driver
import (
"errors"
"io"
"github.com/gopherjs/gopherjs/js"
"github.com/hajimehoshi/ebiten"
)
type player struct {
type Player struct {
src io.Reader
sampleRate int
channelNum int
bytesPerSample int
positionInSamples int64
context *js.Object
bufferSource *js.Object
}
func newPlayer(src io.Reader, sampleRate int) (*player, error) {
func NewPlayer(src io.Reader, sampleRate, channelNum, bytesPerSample int) (*Player, error) {
class := js.Global.Get("AudioContext")
if class == js.Undefined {
class = js.Global.Get("webkitAudioContext")
@ -40,11 +41,13 @@ func newPlayer(src io.Reader, sampleRate int) (*player, error) {
if class == js.Undefined {
return nil, errors.New("audio: audio couldn't be initialized")
}
p := &player{
src: src,
sampleRate: sampleRate,
bufferSource: nil,
context: class.New(),
p := &Player{
src: src,
sampleRate: sampleRate,
channelNum: channelNum,
bytesPerSample: bytesPerSample,
bufferSource: nil,
context: class.New(),
}
p.positionInSamples = int64(p.context.Get("currentTime").Float() * float64(p.sampleRate))
return p, nil
@ -67,8 +70,12 @@ func max64(a, b int64) int64 {
return b
}
func (p *player) proceed() error {
bufferSize := p.sampleRate * bytesPerSample * channelNum / ebiten.FPS
const (
// 1024 seems not enough (some noise remains after the tab is deactivated).
bufferSize = 2048
)
func (p *Player) Proceed() error {
c := int64(p.context.Get("currentTime").Float() * float64(p.sampleRate))
if p.positionInSamples < c {
p.positionInSamples = c
@ -76,7 +83,7 @@ func (p *player) proceed() error {
b := make([]byte, bufferSize)
n, err := p.src.Read(b)
if 0 < n {
buf := p.context.Call("createBuffer", channelNum, n/bytesPerSample/channelNum, p.sampleRate)
buf := p.context.Call("createBuffer", p.channelNum, n/p.bytesPerSample/p.channelNum, p.sampleRate)
l := buf.Call("getChannelData", 0)
r := buf.Call("getChannelData", 1)
il, ir := toLR(b[:n])
@ -96,7 +103,7 @@ func (p *player) proceed() error {
return err
}
func (p *player) close() error {
func (p *Player) Close() error {
if p.bufferSource == nil {
return nil
}

View File

@ -14,7 +14,7 @@
// +build !js,!windows
package audio
package driver
import (
"fmt"
@ -28,7 +28,7 @@ const (
maxBufferNum = 8
)
type player struct {
type Player struct {
alSource al.Source
alBuffers []al.Buffer
source io.Reader
@ -36,7 +36,7 @@ type player struct {
isClosed bool
}
func newPlayer(src io.Reader, sampleRate int) (*player, error) {
func NewPlayer(src io.Reader, sampleRate, channelNum, bytesPerSample int) (*Player, error) {
if e := al.OpenDevice(); e != nil {
return nil, fmt.Errorf("audio: OpenAL initialization failed: %v", e)
}
@ -44,13 +44,13 @@ func newPlayer(src io.Reader, sampleRate int) (*player, error) {
if err := al.Error(); err != 0 {
return nil, fmt.Errorf("audio: al.GenSources error: %d", err)
}
p := &player{
p := &Player{
alSource: s[0],
alBuffers: []al.Buffer{},
source: src,
sampleRate: sampleRate,
}
runtime.SetFinalizer(p, (*player).close)
runtime.SetFinalizer(p, (*Player).Close)
bs := al.GenBuffers(maxBufferNum)
emptyBytes := make([]byte, bufferSize)
@ -72,7 +72,7 @@ var (
tmpAlBuffers = make([]al.Buffer, maxBufferNum)
)
func (p *player) proceed() error {
func (p *Player) Proceed() error {
if err := al.Error(); err != 0 {
return fmt.Errorf("audio: before proceed: %d", err)
}
@ -113,7 +113,7 @@ func (p *player) proceed() error {
return nil
}
func (p *player) close() error {
func (p *Player) Close() error {
if err := al.Error(); err != 0 {
return fmt.Errorf("audio: error before closing: %d", err)
}

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package audio
package driver
// #cgo LDFLAGS: -lwinmm
//
@ -75,7 +75,7 @@ func releaseSemaphore() {
<-sem
}
type player struct {
type Player struct {
src io.Reader
out C.HWAVEOUT
buffer []byte
@ -84,21 +84,21 @@ type player struct {
const bufferSize = 1024
func newPlayer(src io.Reader, sampleRate int) (*player, error) {
const numBlockAlign = channelNum * bitsPerSample / 8
func NewPlayer(src io.Reader, sampleRate, channelNum, bytesPerSample int) (*Player, error) {
const numBlockAlign = channelNum * bytesPerSample
f := C.WAVEFORMATEX{
wFormatTag: C.WAVE_FORMAT_PCM,
nChannels: channelNum,
nSamplesPerSec: C.DWORD(sampleRate),
nAvgBytesPerSec: C.DWORD(sampleRate) * numBlockAlign,
wBitsPerSample: bitsPerSample,
wBitsPerSample: bytesPerSample * 8,
nBlockAlign: numBlockAlign,
}
var w C.HWAVEOUT
if err := C.waveOutOpen2(&w, &f); err != C.MMSYSERR_NOERROR {
return nil, fmt.Errorf("audio: waveOutOpen error: %d", err)
}
p := &player{
p := &Player{
src: src,
out: w,
buffer: []byte{},
@ -114,7 +114,7 @@ func newPlayer(src io.Reader, sampleRate int) (*player, error) {
return p, nil
}
func (p *player) proceed() error {
func (p *Player) Proceed() error {
if len(p.buffer) < bufferSize {
b := make([]byte, bufferSize)
n, err := p.src.Read(b)
@ -130,7 +130,7 @@ func (p *player) proceed() error {
headerToWrite := (*header)(nil)
for _, h := range p.headers {
// TODO: Need to check WHDR_DONE?
if h.waveHdr.dwFlags & C.WHDR_INQUEUE == 0 {
if h.waveHdr.dwFlags&C.WHDR_INQUEUE == 0 {
headerToWrite = h
break
}
@ -146,6 +146,6 @@ func (p *player) proceed() error {
return nil
}
func (p *player) close() {
func (p *Player) Close() {
// TODO: Implement this
}