mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-02-04 23:14:28 +01:00
audio: Refactoring
This commit is contained in:
parent
1e4f486174
commit
1fec0d8203
@ -19,8 +19,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Player struct {
|
type Player struct {
|
||||||
src io.ReadSeeker
|
*player
|
||||||
sampleRate int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPlayer creates a new player with the given data to the given channel.
|
// 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.
|
// TODO: Pass sample rate and num of channels.
|
||||||
func NewPlayer(src io.ReadSeeker, sampleRate int) *Player {
|
func NewPlayer(src io.ReadSeeker, sampleRate int) *Player {
|
||||||
return &Player{
|
return newPlayer(src, sampleRate)
|
||||||
src: src,
|
|
||||||
sampleRate: sampleRate,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Player) Play() error {
|
func (p *Player) Play() error {
|
||||||
return play(p.src, p.sampleRate)
|
return p.play()
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
package audio
|
package audio
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
|
||||||
@ -26,12 +25,27 @@ import (
|
|||||||
|
|
||||||
var context *js.Object
|
var context *js.Object
|
||||||
|
|
||||||
type audioProcessor struct {
|
type player struct {
|
||||||
src io.ReadSeeker
|
src io.ReadSeeker
|
||||||
sampleRate int
|
sampleRate int
|
||||||
position float64
|
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) {
|
func toLR(data []byte) ([]int16, []int16) {
|
||||||
l := make([]int16, len(data)/4)
|
l := make([]int16, len(data)/4)
|
||||||
r := make([]int16, len(data)/4)
|
r := make([]int16, len(data)/4)
|
||||||
@ -42,9 +56,9 @@ func toLR(data []byte) ([]int16, []int16) {
|
|||||||
return l, r
|
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.
|
// 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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -53,7 +67,7 @@ func (a *audioProcessor) play() error {
|
|||||||
}
|
}
|
||||||
const channelNum = 2
|
const channelNum = 2
|
||||||
const bytesPerSample = channelNum * 16 / 8
|
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)
|
l := b.Call("getChannelData", 0)
|
||||||
r := b.Call("getChannelData", 1)
|
r := b.Call("getChannelData", 1)
|
||||||
il, ir := toLR(buf)
|
il, ir := toLR(buf)
|
||||||
@ -65,25 +79,11 @@ func (a *audioProcessor) play() error {
|
|||||||
s := context.Call("createBufferSource")
|
s := context.Call("createBufferSource")
|
||||||
s.Set("buffer", b)
|
s.Set("buffer", b)
|
||||||
s.Call("connect", context.Get("destination"))
|
s.Call("connect", context.Get("destination"))
|
||||||
s.Call("start", a.position)
|
s.Call("start", p.position)
|
||||||
a.position += b.Get("duration").Float()
|
p.position += b.Get("duration").Float()
|
||||||
return nil
|
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 {
|
func initialize() bool {
|
||||||
// Do nothing in node.js.
|
// Do nothing in node.js.
|
||||||
if js.Global.Get("require") != js.Undefined {
|
if js.Global.Get("require") != js.Undefined {
|
||||||
|
@ -30,13 +30,23 @@ func (r *readSeekCloser) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func play(src io.ReadSeeker, sampleRate int) error {
|
type player struct {
|
||||||
// TODO: audio.NewPlayer interprets WAV header, which we don't want.
|
*audio.Player
|
||||||
// Use OpenAL or native API instead.
|
}
|
||||||
|
|
||||||
|
func newPlayer(src io.ReadSeeker, sampleRate int) *Player {
|
||||||
p, err := audio.NewPlayer(&readSeekCloser{src}, audio.Stereo16, int64(sampleRate))
|
p, err := audio.NewPlayer(&readSeekCloser{src}, audio.Stereo16, int64(sampleRate))
|
||||||
if err != nil {
|
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()
|
return p.Play()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user