example/piano: Speed up

This commit is contained in:
Hajime Hoshi 2015-02-16 10:33:27 +09:00
parent 8c2301e542
commit 9ec7b13f27
4 changed files with 59 additions and 54 deletions

View File

@ -103,6 +103,36 @@ func updateInput() {
} }
} }
var pianoImage *ebiten.Image
func init() {
var err error
pianoImage, err = ebiten.NewImage(screenWidth, screenHeight, ebiten.FilterNearest)
if err != nil {
panic(err)
}
whiteKeys := []string{"A", "S", "D", "F", "G", "H", "J", "K", "L"}
width := 24
y := 48
for i, k := range whiteKeys {
x := i*width + 36
height := 112
pianoImage.DrawFilledRect(x, y, width-1, height, color.White)
common.ArcadeFont.DrawText(pianoImage, k, x+8, y+height-16, 1, color.Black)
}
blackKeys := []string{"Q", "W", "", "R", "T", "", "U", "I", "O"}
for i, k := range blackKeys {
if k == "" {
continue
}
x := i*width + 24
height := 64
pianoImage.DrawFilledRect(x, y, width-1, height, color.Black)
common.ArcadeFont.DrawText(pianoImage, k, x+8, y+height-16, 1, color.White)
}
}
func update(screen *ebiten.Image) error { func update(screen *ebiten.Image) error {
updateInput() updateInput()
for i, key := range keys { for i, key := range keys {
@ -113,27 +143,7 @@ func update(screen *ebiten.Image) error {
} }
screen.Fill(color.RGBA{0x80, 0x80, 0xc0, 0xff}) screen.Fill(color.RGBA{0x80, 0x80, 0xc0, 0xff})
screen.DrawImage(pianoImage, nil)
whiteKeys := []string{"A", "S", "D", "F", "G", "H", "J", "K", "L"}
width := 24
y := 48
for i, k := range whiteKeys {
x := i*width + 36
height := 112
screen.DrawFilledRect(x, y, width-1, height, color.White)
common.ArcadeFont.DrawText(screen, k, x+8, y+height-16, 1, color.Black)
}
blackKeys := []string{"Q", "W", "", "R", "T", "", "U", "I", "O"}
for i, k := range blackKeys {
if k == "" {
continue
}
x := i*width + 24
height := 64
screen.DrawFilledRect(x, y, width-1, height, color.Black)
common.ArcadeFont.DrawText(screen, k, x+8, y+height-16, 1, color.White)
}
ebitenutil.DebugPrint(screen, fmt.Sprintf("FPS: %0.2f", ebiten.CurrentFPS())) ebitenutil.DebugPrint(screen, fmt.Sprintf("FPS: %0.2f", ebiten.CurrentFPS()))
return nil return nil

View File

@ -18,8 +18,6 @@ var audioEnabled = false
const SampleRate = 44100 const SampleRate = 44100
var currentPosition = 0
type channel struct { type channel struct {
l []int16 l []int16
r []int16 r []int16
@ -143,10 +141,8 @@ func loadChannelBuffer(channel int, bufferSize int) (l, r []int16) {
ch := channels[channel] ch := channels[channel]
length := min(len(ch.l), bufferSize) length := min(len(ch.l), bufferSize)
inputL := make([]int16, length) inputL := ch.l[:length]
inputR := make([]int16, length) inputR := ch.r[:length]
copy(inputL, ch.l[:length])
copy(inputR, ch.r[:length])
ch.l = ch.l[length:] ch.l = ch.l[length:]
ch.r = ch.r[length:] ch.r = ch.r[length:]
ch.nextInsertionPosition -= min(bufferSize, ch.nextInsertionPosition) ch.nextInsertionPosition -= min(bufferSize, ch.nextInsertionPosition)

View File

@ -33,28 +33,21 @@ var (
const bufferSize = 1024 const bufferSize = 1024
func audioProcess(channel int) func(e js.Object) { type audioProcessor struct {
return func(e js.Object) { channel int
// Can't use 'go' here. Probably it may cause race conditions. }
defer func() {
currentPosition += bufferSize
}()
b := e.Get("outputBuffer") func (a *audioProcessor) Process(e js.Object) {
l := b.Call("getChannelData", 0) // Can't use 'go' here. Probably it may cause race conditions.
r := b.Call("getChannelData", 1) b := e.Get("outputBuffer")
inputL, inputR := loadChannelBuffer(channel, bufferSize) l := b.Call("getChannelData", 0)
const max = 1 << 15 r := b.Call("getChannelData", 1)
for i := 0; i < bufferSize; i++ { inputL, inputR := loadChannelBuffer(a.channel, bufferSize)
// TODO: Use copyToChannel? const max = 1 << 15
if len(inputL) <= i { for i := 0; i < len(inputL); i++ {
l.SetIndex(i, 0) // TODO: Use copyToChannel?
r.SetIndex(i, 0) l.SetIndex(i, float64(inputL[i])/max)
continue r.SetIndex(i, float64(inputR[i])/max)
}
l.SetIndex(i, float64(inputL[i])/max)
r.SetIndex(i, float64(inputR[i])/max)
}
} }
} }
@ -69,7 +62,8 @@ func initialize() {
// https://developer.mozilla.org/ja/docs/Web/API/ScriptProcessorNode // https://developer.mozilla.org/ja/docs/Web/API/ScriptProcessorNode
for i := 0; i < MaxChannel; i++ { for i := 0; i < MaxChannel; i++ {
node := context.Call("createScriptProcessor", bufferSize, 0, 2) node := context.Call("createScriptProcessor", bufferSize, 0, 2)
node.Call("addEventListener", "audioprocess", audioProcess(i)) processor := &audioProcessor{i}
node.Call("addEventListener", "audioprocess", processor.Process)
nodes = append(nodes, node) nodes = append(nodes, node)
dummy := context.Call("createBufferSource") dummy := context.Call("createBufferSource")

View File

@ -53,10 +53,11 @@ func orthoProjectionMatrix(left, right, bottom, top int) *[4][4]float64 {
} }
type Framebuffer struct { type Framebuffer struct {
native opengl.Framebuffer native opengl.Framebuffer
width int width int
height int height int
flipY bool flipY bool
proMatrix *[4][4]float64
} }
func NewZeroFramebuffer(c *opengl.Context, width, height int) (*Framebuffer, error) { func NewZeroFramebuffer(c *opengl.Context, width, height int) (*Framebuffer, error) {
@ -100,6 +101,9 @@ func (f *Framebuffer) setAsViewport(c *opengl.Context) error {
} }
func (f *Framebuffer) projectionMatrix() *[4][4]float64 { func (f *Framebuffer) projectionMatrix() *[4][4]float64 {
if f.proMatrix != nil {
return f.proMatrix
}
width := NextPowerOf2Int(f.width) width := NextPowerOf2Int(f.width)
height := NextPowerOf2Int(f.height) height := NextPowerOf2Int(f.height)
m := orthoProjectionMatrix(0, width, 0, height) m := orthoProjectionMatrix(0, width, 0, height)
@ -107,7 +111,8 @@ func (f *Framebuffer) projectionMatrix() *[4][4]float64 {
m[1][1] *= -1 m[1][1] *= -1
m[1][3] += float64(f.height) / float64(NextPowerOf2Int(f.height)) * 2 m[1][3] += float64(f.height) / float64(NextPowerOf2Int(f.height)) * 2
} }
return m f.proMatrix = m
return f.proMatrix
} }
func (f *Framebuffer) Fill(c *opengl.Context, clr color.Color) error { func (f *Framebuffer) Fill(c *opengl.Context, clr color.Color) error {