audio: Change API to accept raw PCM data

This commit is contained in:
Hajime Hoshi 2015-06-08 00:04:21 +09:00
parent 23cef1b715
commit de59c93219
3 changed files with 72 additions and 16 deletions

View File

@ -15,12 +15,15 @@
package main
import (
"bytes"
"encoding/binary"
"fmt"
"log"
"math"
"github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/ebitenutil"
"github.com/hajimehoshi/ebiten/exp/audio"
"log"
"math"
)
const (
@ -69,6 +72,19 @@ func square(out []int16, volume float64, freq float64, sequence float64) {
}
}
func toBytes(l, r []int16) []byte {
if len(l) != len(r) {
panic("len(l) must equal to len(r)")
}
b := &bytes.Buffer{}
for i := 0; i < len(l); i++ {
if err := binary.Write(b, binary.LittleEndian, []int16{l[i], r[i]}); err != nil {
panic(err)
}
}
return b.Bytes()
}
func addNote() {
size := audio.SampleRate() / 60
notes := []float64{freqC, freqD, freqE, freqF, freqG, freqA * 2, freqB * 2}
@ -97,7 +113,7 @@ func addNote() {
vol := 1.0 / 16.0
square(l, vol, freq, 0.25)
square(r, vol, freq, 0.25)
audio.Play(0, l, r)
audio.Play(0, toBytes(l, r))
}
func update(screen *ebiten.Image) error {

View File

@ -15,14 +15,17 @@
package main
import (
"bytes"
"encoding/binary"
"fmt"
"image/color"
"log"
"math"
"github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/ebitenutil"
"github.com/hajimehoshi/ebiten/example/common"
"github.com/hajimehoshi/ebiten/exp/audio"
"image/color"
"log"
"math"
)
const (
@ -50,15 +53,26 @@ func init() {
}
var (
noteLCache = map[int][]int16{}
noteRCache = map[int][]int16{}
noteCache = map[int][]byte{}
)
func toBytes(l, r []int16) []byte {
if len(l) != len(r) {
panic("len(l) must equal to len(r)")
}
b := &bytes.Buffer{}
for i := 0; i < len(l); i++ {
if err := binary.Write(b, binary.LittleEndian, []int16{l[i], r[i]}); err != nil {
panic(err)
}
}
return b.Bytes()
}
func addNote(freq float64, vol float64) {
f := int(freq)
if l, ok := noteLCache[f]; ok {
r := noteRCache[f]
audio.Play(-1, l, r)
if n, ok := noteCache[f]; ok {
audio.Play(-1, n)
return
}
length := len(pcm) * baseFreq / f
@ -73,9 +87,9 @@ func addNote(freq float64, vol float64) {
jj += f
j = jj / baseFreq
}
noteLCache[f] = l
noteRCache[f] = r
audio.Play(-1, l, r)
n := toBytes(l, r)
noteCache[f] = n
audio.Play(-1, n)
}
var keys = []ebiten.Key{

View File

@ -15,6 +15,9 @@
package audio
import (
"bytes"
"encoding/binary"
"github.com/hajimehoshi/ebiten/exp/audio/internal"
)
@ -26,13 +29,32 @@ func SampleRate() int {
// MaxChannel is a max number of channels.
var MaxChannel = internal.MaxChannel
func toLR(data []byte) ([]int16, []int16) {
buf := bytes.NewReader(data)
b := make([]int16, len(data)/2)
if err := binary.Read(buf, binary.LittleEndian, b); err != nil {
panic(err)
}
l := make([]int16, len(data)/4)
r := make([]int16, len(data)/4)
for i := 0; i < len(data)/4; i++ {
l[i] = b[2*i]
r[i] = b[2*i+1]
}
return l, r
}
// Play appends the given data to the given channel.
//
// channel must be -1 or a channel index. If channel is -1, an empty channel is automatically selected.
// If the channel is not empty, this function does nothing and returns false. This returns true otherwise.
//
// data's format must be linear PCM (44100Hz, stereo, 16bit little endian).
//
// This function is useful to play SE or a note of PCM synthesis immediately.
func Play(channel int, l []int16, r []int16) bool {
func Play(channel int, data []byte) bool {
l, r := toLR(data)
// TODO: Pass data directly.
return internal.Play(channel, l, r)
}
@ -41,8 +63,12 @@ func Play(channel int, l []int16, r []int16) bool {
//
// channel must be a channel index. You can't give -1 to channel.
//
// data's format must be linear PCM (44100Hz, stereo, 16bit little endian).
//
// This function is useful to play streaming data.
func Queue(channel int, l []int16, r []int16) {
func Queue(channel int, data []byte) {
l, r := toLR(data)
// TODO: Pass data directly.
internal.Queue(channel, l, r)
}