From 8d250c6b25e445c3c658862a2f584230f954646c Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Fri, 23 Jan 2015 10:58:18 +0900 Subject: [PATCH] audio: Add channel.nextInsertion --- example/audio/main.go | 14 ++++++++++---- internal/audio/audio.go | 4 ++++ internal/audio/audio_js.go | 30 +++++++++++++++++++++--------- run.go | 3 +++ 4 files changed, 38 insertions(+), 13 deletions(-) diff --git a/example/audio/main.go b/example/audio/main.go index 75eacb9a1..40ccf11bb 100644 --- a/example/audio/main.go +++ b/example/audio/main.go @@ -48,6 +48,12 @@ const score = `CCGGAAGR FFEEDDCR GGFFEEDR GGFFEEDR CCGGAAGR FFEEDDCR` var scoreIndex = 0 func square(out []float32, volume float64, freq float64, sequence float64) { + if freq == 0 { + for i := 0; i < len(out); i++ { + out[i] = 0 + } + return + } length := int(float64(ebiten.AudioSampleRate()) / freq) if length == 0 { panic("invalid freq") @@ -69,8 +75,8 @@ func addNote() { scoreIndex++ scoreIndex %= len(score) }() - l := make([]float32, size*30*2) - r := make([]float32, size*30*2) + l := make([]float32, size*30) + r := make([]float32, size*30) note := score[scoreIndex] for note == ' ' { scoreIndex++ @@ -80,7 +86,7 @@ func addNote() { freq := 0.0 switch { case note == 'R': - return + freq = 0 case note <= 'B': freq = notes[int(note)+len(notes)-int('C')] default: @@ -89,7 +95,7 @@ func addNote() { vol := 1.0 / 32.0 square(l, vol, freq, 0.5) square(r, vol, freq, 0.5) - ebiten.AppendToAudioBuffer(-1, l, r) + ebiten.AppendToAudioBuffer(0, l, r) } func update(screen *ebiten.Image) error { diff --git a/internal/audio/audio.go b/internal/audio/audio.go index 806cb9b5a..2d6093e24 100644 --- a/internal/audio/audio.go +++ b/internal/audio/audio.go @@ -35,3 +35,7 @@ func CurrentBytes() int { // TODO: Implement return 0 } + +func Update() { + // TODO: Implement +} diff --git a/internal/audio/audio_js.go b/internal/audio/audio_js.go index 90a56c279..6bbc8636f 100644 --- a/internal/audio/audio_js.go +++ b/internal/audio/audio_js.go @@ -28,8 +28,9 @@ const bufferSize = 1024 const SampleRate = 44100 type channel struct { - l []float32 - r []float32 + l []float32 + r []float32 + nextInsertion int } var channels = make([]*channel, 16) @@ -83,6 +84,7 @@ func Init() { usedLen := min(bufferSize, len(ch.l)) ch.l = ch.l[usedLen:] ch.r = ch.r[usedLen:] + ch.nextInsertion -= min(bufferSize, ch.nextInsertion) } for i := 0; i < bufferSize; i++ { // TODO: Use copyFromChannel? @@ -97,6 +99,15 @@ func Init() { }) } +func Update() { + for _, ch := range channels { + if len(ch.l) == 0 { + continue + } + ch.nextInsertion += SampleRate / 60 + } +} + func Start() { // TODO: For iOS, node should be connected with a buffer node. node.Call("connect", context.Get("destination")) @@ -105,19 +116,17 @@ func Start() { func channelAt(i int) *channel { if i == -1 { for _, ch := range channels { - if 0 < len(ch.l) { - continue + if len(ch.l) <= ch.nextInsertion { + return ch } - return ch } return nil } ch := channels[i] - // TODO: Can we append even though all data is not consumed? Need game timer? - if 0 < len(ch.l) { - return nil + if len(ch.l) <= ch.nextInsertion { + return ch } - return ch + return nil } func Append(i int, l []float32, r []float32) bool { @@ -129,6 +138,9 @@ func Append(i int, l []float32, r []float32) bool { if ch == nil { return false } + print(ch.nextInsertion) + ch.l = append(ch.l, make([]float32, ch.nextInsertion-len(ch.l))...) + ch.r = append(ch.r, make([]float32, ch.nextInsertion-len(ch.r))...) ch.l = append(ch.l, l...) ch.r = append(ch.r, r...) return true diff --git a/run.go b/run.go index dbb9fd793..ebcab0d0a 100644 --- a/run.go +++ b/run.go @@ -15,6 +15,7 @@ package ebiten import ( + "github.com/hajimehoshi/ebiten/internal/audio" "github.com/hajimehoshi/ebiten/internal/opengl" "github.com/hajimehoshi/ebiten/internal/ui" "time" @@ -69,6 +70,8 @@ func Run(f func(*Image) error, width, height, scale int, title string) error { if err := graphicsContext.postUpdate(); err != nil { return err } + // TODO: I'm not sure this is 'Update'. Is 'Tick' better? + audio.Update() ui.SwapBuffers() if err != nil { return err