audio: Refactoring

This commit is contained in:
Hajime Hoshi 2016-02-11 18:43:11 +09:00
parent 1e4f486174
commit 1fec0d8203
3 changed files with 38 additions and 32 deletions

View File

@ -19,8 +19,7 @@ import (
)
type Player struct {
src io.ReadSeeker
sampleRate int
*player
}
// NewPlayer creates a new player with the given data to the given channel.
@ -32,12 +31,9 @@ type Player struct {
//
// TODO: Pass sample rate and num of channels.
func NewPlayer(src io.ReadSeeker, sampleRate int) *Player {
return &Player{
src: src,
sampleRate: sampleRate,
}
return newPlayer(src, sampleRate)
}
func (p *Player) Play() error {
return play(p.src, p.sampleRate)
return p.play()
}

View File

@ -17,7 +17,6 @@
package audio
import (
"errors"
"io"
"io/ioutil"
@ -26,12 +25,27 @@ import (
var context *js.Object
type audioProcessor struct {
type player struct {
src io.ReadSeeker
sampleRate int
position float64
}
func newPlayer(src io.ReadSeeker, sampleRate int) *Player {
if context == nil {
if !initialize() {
panic("audio couldn't be initialized")
}
}
p := &player{
src: src,
sampleRate: sampleRate,
position: context.Get("currentTime").Float(),
}
return &Player{p}
}
func toLR(data []byte) ([]int16, []int16) {
l := make([]int16, len(data)/4)
r := make([]int16, len(data)/4)
@ -42,9 +56,9 @@ func toLR(data []byte) ([]int16, []int16) {
return l, r
}
func (a *audioProcessor) play() error {
func (p *player) play() error {
// TODO: Reading all data at once is temporary implemntation. Treat this as stream.
buf, err := ioutil.ReadAll(a.src)
buf, err := ioutil.ReadAll(p.src)
if err != nil {
return err
}
@ -53,7 +67,7 @@ func (a *audioProcessor) play() error {
}
const channelNum = 2
const bytesPerSample = channelNum * 16 / 8
b := context.Call("createBuffer", channelNum, len(buf)/bytesPerSample, a.sampleRate)
b := context.Call("createBuffer", channelNum, len(buf)/bytesPerSample, p.sampleRate)
l := b.Call("getChannelData", 0)
r := b.Call("getChannelData", 1)
il, ir := toLR(buf)
@ -65,25 +79,11 @@ func (a *audioProcessor) play() error {
s := context.Call("createBufferSource")
s.Set("buffer", b)
s.Call("connect", context.Get("destination"))
s.Call("start", a.position)
a.position += b.Get("duration").Float()
s.Call("start", p.position)
p.position += b.Get("duration").Float()
return nil
}
func play(src io.ReadSeeker, sampleRate int) error {
if context == nil {
if !initialize() {
return errors.New("audio couldn't be initialized")
}
}
a := &audioProcessor{
src: src,
sampleRate: sampleRate,
position: context.Get("currentTime").Float(),
}
return a.play()
}
func initialize() bool {
// Do nothing in node.js.
if js.Global.Get("require") != js.Undefined {

View File

@ -30,13 +30,23 @@ func (r *readSeekCloser) Close() error {
return nil
}
func play(src io.ReadSeeker, sampleRate int) error {
// TODO: audio.NewPlayer interprets WAV header, which we don't want.
// Use OpenAL or native API instead.
type player struct {
*audio.Player
}
func newPlayer(src io.ReadSeeker, sampleRate int) *Player {
p, err := audio.NewPlayer(&readSeekCloser{src}, audio.Stereo16, int64(sampleRate))
if err != nil {
return err
// TODO: Should we return errors for this method?
panic(err)
}
pp := &player{p}
return &Player{pp}
}
func (p *player) play() error {
// TODO: audio.NewPlayer interprets WAV header, which we don't want.
// Use OpenAL or native API instead.
return p.Play()
}