diff --git a/audio/mp3/decode_js.go b/audio/mp3/decode_js.go index 002117f50..a88f0678c 100644 --- a/audio/mp3/decode_js.go +++ b/audio/mp3/decode_js.go @@ -24,8 +24,8 @@ import ( "math" "time" - "github.com/gopherjs/gopherjs/js" "github.com/hajimehoshi/ebiten/audio" + "github.com/hajimehoshi/gopherwasm/js" ) // TODO: This just uses decodeAudioData, that can treat audio files other than MP3. @@ -159,7 +159,7 @@ func Decode(context *audio.Context, src audio.ReadSeekCloser) (*Stream, error) { return s, nil } -var offlineAudioContextClass *js.Object +var offlineAudioContextClass = js.Null func init() { if klass := js.Global.Get("OfflineAudioContext"); klass != js.Undefined { @@ -173,7 +173,7 @@ func init() { } func decode(context *audio.Context, buf []byte, try int) (*Stream, error) { - if offlineAudioContextClass == nil { + if offlineAudioContextClass == js.Null { return nil, errors.New("audio/mp3: OfflineAudioContext is not available") } @@ -186,27 +186,30 @@ func decode(context *audio.Context, buf []byte, try int) (*Stream, error) { // TODO: 1 is a correct second argument? oc := offlineAudioContextClass.New(2, 1, context.SampleRate()) - oc.Call("decodeAudioData", js.NewArrayBuffer(buf), func(buf *js.Object) { - s.leftData = buf.Call("getChannelData", 0).Interface().([]float32) + a := js.ValueOf(buf).Get("buffer") + oc.Call("decodeAudioData", a, js.NewCallback(func(args []js.Value) { + buf := args[0] + s.leftData = float32ArrayToSlice(buf.Call("getChannelData", 0)) switch n := buf.Get("numberOfChannels").Int(); n { case 1: s.rightData = s.leftData close(ch) case 2: - s.rightData = buf.Call("getChannelData", 1).Interface().([]float32) + s.rightData = float32ArrayToSlice(buf.Call("getChannelData", 1)) close(ch) default: ch <- fmt.Errorf("audio/mp3: number of channels must be 1 or 2 but %d", n) } - }, func(err *js.Object) { - if err != nil { + }), js.NewCallback(func(args []js.Value) { + err := args[0] + if err != js.Null || err != js.Undefined { ch <- fmt.Errorf("audio/mp3: decodeAudioData failed: %v", err) } else { // On Safari, error value might be null and it is needed to retry decoding // from the next frame (#438). ch <- errTryAgain } - }) + })) timeout := time.Duration(math.Pow(2, float64(try))) * time.Second diff --git a/audio/mp3/float32_notwasm.go b/audio/mp3/float32_notwasm.go new file mode 100644 index 000000000..e897594d6 --- /dev/null +++ b/audio/mp3/float32_notwasm.go @@ -0,0 +1,26 @@ +// Copyright 2018 The Ebiten Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build js,!wasm + +package mp3 + +import ( + gjs "github.com/gopherjs/gopherjs/js" + "github.com/hajimehoshi/gopherwasm/js" +) + +func float32ArrayToSlice(arr js.Value) []float32 { + return js.GetInternalObject(arr).(*gjs.Object).Interface().([]float32) +} diff --git a/audio/mp3/float32_wasm.go b/audio/mp3/float32_wasm.go new file mode 100644 index 000000000..a11258c25 --- /dev/null +++ b/audio/mp3/float32_wasm.go @@ -0,0 +1,37 @@ +// Copyright 2018 The Ebiten Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build js,wasm + +package mp3 + +import ( + "reflect" + "syscall/js" + "unsafe" +) + +func float32ArrayToSlice(arr js.Value) []float32 { + bytes := make([]byte, arr.Length()*4) + js.ValueOf(bytes).Call("set", arr.Get("buffer")) + + bh := (*reflect.SliceHeader)(unsafe.Pointer(&bytes)) + var f []float32 + fh := (*reflect.SliceHeader)(unsafe.Pointer(&f)) + + fh.Data = bh.Data + fh.Len = bh.Len / 4 + fh.Cap = bh.Cap / 4 + return f +}