audio/vorbis/internal/stb: Use stbvorbis.js

Fixes #641
This commit is contained in:
Hajime Hoshi 2018-07-22 06:27:57 +09:00
parent b2a4ddf853
commit 05ac690db5
12 changed files with 35 additions and 7713 deletions

View File

@ -1,4 +0,0 @@
*.wasm
*.wasm.map
*.wast

View File

@ -1,2 +0,0 @@
emcc -Os -o stbvorbis.js -g -DSTB_VORBIS_NO_INTEGER_CONVERSION -DSTB_VORBIS_NO_STDIO -s WASM=1 -s EXPORTED_FUNCTIONS='["_stb_vorbis_decode_memory_float"]' -s EXTRA_EXPORTED_RUNTIME_METHODS='["ccall","cwrap"]' -s ALLOW_MEMORY_GROWTH=1 stb_vorbis.c
go run genwasmjs.go < stbvorbis.wasm > wasm.js

View File

@ -20,31 +20,46 @@ import (
"github.com/gopherjs/gopherwasm/js"
)
var flatten = js.Global().Get("window").Call("eval", `(function(arr) {
var ch = arr.length;
var len = arr[0].length;
var result = new Float32Array(ch * len);
for (var j = 0; j < len; j++) {
for (var i = 0; i < ch; i++) {
result[j*ch+i] = arr[i][j];
}
}
return result;
})`)
func init() {
// Eval wasm.js first to set the Wasm binary to Module.
js.Global().Get("window").Call("eval", string(wasm_js))
js.Global().Get("window").Call("eval", string(stbvorbis_js))
js.Global().Get("window").Call("eval", string(decode_js))
ch := make(chan struct{})
js.Global().Get("_ebiten").Call("initializeVorbisDecoder", js.NewCallback(func([]js.Value) {
close(ch)
}))
<-ch
}
func DecodeVorbis(buf []byte) ([]float32, int, int, error) {
var r js.Value
ch := make(chan struct{})
arr := js.TypedArrayOf(buf)
r := js.Global().Get("_ebiten").Call("decodeVorbis", arr)
var f js.Callback
f = js.NewCallback(func(args []js.Value) {
r = args[0]
close(ch)
f.Release()
})
js.Global().Get("stbvorbis").Call("decode", arr).Call("then", f)
arr.Release()
<-ch
if r == js.Null() {
return nil, 0, 0, fmt.Errorf("audio/vorbis/internal/stb: decode failed")
}
data := make([]float32, r.Get("data").Get("length").Int())
channels := r.Get("data").Length()
flattened := flatten.Invoke(r.Get("data"))
data := make([]float32, flattened.Length())
arr = js.TypedArrayOf(data)
arr.Call("set", r.Get("data"))
arr.Call("set", flattened)
arr.Release()
return data, r.Get("channels").Int(), r.Get("sampleRate").Int(), nil
return data, channels, r.Get("sampleRate").Int(), nil
}

View File

@ -1,80 +0,0 @@
// 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.
var _ebiten = {};
(() => {
var decodeMemory = null;
var vorbisDecoderInitialized = null;
_ebiten.initializeVorbisDecoder = (callback) => {
Module.run();
vorbisDecoderInitialized = callback;
};
Module.onRuntimeInitialized = () => {
decodeMemory = Module.cwrap('stb_vorbis_decode_memory_float', 'number', ['number', 'number', 'number', 'number', 'number']);
if (vorbisDecoderInitialized) {
vorbisDecoderInitialized();
}
}
function arrayToHeap(typedArray){
const ptr = Module._malloc(typedArray.byteLength);
const heapBytes = new Uint8Array(Module.HEAPU8.buffer, ptr, typedArray.byteLength);
heapBytes.set(new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength));
return heapBytes;
}
function ptrToInt32(ptr) {
const a = new Int32Array(Module.HEAPU8.buffer, ptr, 1);
return a[0];
}
function ptrToFloat32(ptr) {
const a = new Float32Array(Module.HEAPU8.buffer, ptr, 1);
return a[0];
}
function ptrToFloat32s(ptr, length) {
const buf = new ArrayBuffer(length * Float32Array.BYTES_PER_ELEMENT);
const copied = new Float32Array(buf);
copied.set(new Float32Array(Module.HEAPU8.buffer, ptr, length));
return copied;
}
_ebiten.decodeVorbis = (buf) => {
const copiedBuf = arrayToHeap(buf);
const channelsPtr = Module._malloc(4);
const sampleRatePtr = Module._malloc(4);
const outputPtr = Module._malloc(4);
const length = decodeMemory(copiedBuf.byteOffset, copiedBuf.length, channelsPtr, sampleRatePtr, outputPtr);
if (length < 0) {
return null;
}
const channels = ptrToInt32(channelsPtr);
const result = {
data: ptrToFloat32s(ptrToInt32(outputPtr), length * channels),
channels: channels,
sampleRate: ptrToInt32(sampleRatePtr),
};
Module._free(copiedBuf.byteOffset);
Module._free(channelsPtr);
Module._free(sampleRatePtr);
Module._free(ptrToInt32(outputPtr));
Module._free(outputPtr);
return result;
};
})();

View File

@ -1,6 +0,0 @@
// Code generated by file2byteslice. DO NOT EDIT.
// (gofmt is fine after generating)
package stb
var decode_js = []byte("// Copyright 2018 The Ebiten Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nvar _ebiten = {};\n\n(() => {\n var decodeMemory = null;\n var vorbisDecoderInitialized = null;\n\n _ebiten.initializeVorbisDecoder = (callback) => {\n Module.run();\n vorbisDecoderInitialized = callback;\n };\n\n Module.onRuntimeInitialized = () => {\n decodeMemory = Module.cwrap('stb_vorbis_decode_memory_float', 'number', ['number', 'number', 'number', 'number', 'number']);\n if (vorbisDecoderInitialized) {\n vorbisDecoderInitialized();\n }\n }\n\n function arrayToHeap(typedArray){\n const ptr = Module._malloc(typedArray.byteLength);\n const heapBytes = new Uint8Array(Module.HEAPU8.buffer, ptr, typedArray.byteLength);\n heapBytes.set(new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength));\n return heapBytes;\n }\n\n function ptrToInt32(ptr) {\n const a = new Int32Array(Module.HEAPU8.buffer, ptr, 1);\n return a[0];\n }\n\n function ptrToFloat32(ptr) {\n const a = new Float32Array(Module.HEAPU8.buffer, ptr, 1);\n return a[0];\n }\n\n function ptrToFloat32s(ptr, length) {\n const buf = new ArrayBuffer(length * Float32Array.BYTES_PER_ELEMENT);\n const copied = new Float32Array(buf);\n copied.set(new Float32Array(Module.HEAPU8.buffer, ptr, length));\n return copied;\n }\n\n _ebiten.decodeVorbis = (buf) => {\n const copiedBuf = arrayToHeap(buf);\n const channelsPtr = Module._malloc(4);\n const sampleRatePtr = Module._malloc(4);\n const outputPtr = Module._malloc(4);\n const length = decodeMemory(copiedBuf.byteOffset, copiedBuf.length, channelsPtr, sampleRatePtr, outputPtr);\n if (length < 0) {\n return null;\n }\n const channels = ptrToInt32(channelsPtr);\n const result = {\n data: ptrToFloat32s(ptrToInt32(outputPtr), length * channels),\n channels: channels,\n sampleRate: ptrToInt32(sampleRatePtr),\n };\n\n Module._free(copiedBuf.byteOffset);\n Module._free(channelsPtr);\n Module._free(sampleRatePtr);\n Module._free(ptrToInt32(outputPtr));\n Module._free(outputPtr);\n return result;\n };\n})();\n")

View File

@ -14,7 +14,9 @@
package stb
//go:generate bash build.sh
//go:generate file2byteslice -package=stb -input=decode.js -output=decodejs_file.go -var=decode_js
// stbvorbis.js
// URL: https://github.com/hajimehoshi/stbvorbis.js
// License: Apache License 2.0
// Commit: ac1c2ee9d24eb6085eb1e968f55e0fb32cacc03a
//go:generate file2byteslice -package=stb -input=stbvorbis.js -output=stbvorbisjs_file.go -var=stbvorbis_js
//go:generate file2byteslice -package=stb -input=wasm.js -output=wasmjs_file.go -var=wasm_js

View File

@ -1,43 +0,0 @@
// 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 ignore
package main
import (
"encoding/base64"
"fmt"
"io/ioutil"
"os"
)
func run() error {
bin, err := ioutil.ReadAll(os.Stdin)
if err != nil {
return err
}
fmt.Println("// Code generated by genwasmjs.go. DO NOT EDIT.")
fmt.Println("")
fmt.Println("var Module = typeof Module !== 'undefined' ? Module : {};")
fmt.Printf("Module['wasmBinary'] = Uint8Array.from(atob(%q), c => c.charCodeAt(0));\n", base64.StdEncoding.EncodeToString(bin))
return nil
}
func main() {
if err := run(); err != nil {
panic(err)
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long