audio-player: wasm decoding merged with pcm player

This commit is contained in:
Trek H 2019-07-23 17:57:03 +09:30
parent 1842319957
commit e23c1aac7e
2 changed files with 132 additions and 64 deletions

View File

@ -1,27 +1,73 @@
package main
import (
"fmt"
"bytes"
"reflect"
"syscall/js"
"unsafe"
"bitbucket.org/ausocean/av/codec/adpcm"
)
func main() {
c := make(chan struct{}, 0)
println("WASM Go Initialized")
// register functions
registerCallbacks()
<-c
dec := NewDecoder()
dec.Start()
}
func registerCallbacks() {
js.Global().Set("decode", js.FuncOf(decode))
// Decoder is a client side adpcm decoder
type Decoder struct {
inBuf []uint8
onImgLoadCb, initMemCb js.Func
console js.Value
done chan struct{}
}
func decode(this js.Value, args []js.Value) interface{} {
fmt.Println("calculating")
return adpcm.EncBytes(args[0].Int())
// NewDecoder returns a new instance of decoder
func NewDecoder() *Decoder {
return &Decoder{
console: js.Global().Get("console"),
done: make(chan struct{}),
}
}
func (s *Decoder) setupOnImgLoadCb() {
s.onImgLoadCb = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
// reader := bytes.NewReader(s.inBuf)
//DECODING HAPPENS HERE
decoded := bytes.NewBuffer(make([]byte, 0, len(s.inBuf)*4))
dec := adpcm.NewDecoder(decoded)
dec.Write(s.inBuf)
s.inBuf = decoded.Bytes()
return nil
})
}
func (s *Decoder) setupInitMemCb() {
// The length of the data array buffer is passed.
// Then the buf slice is initialized to that length.
// A pointer to that slice is passed back to the browser.
s.initMemCb = js.FuncOf(func(this js.Value, i []js.Value) interface{} {
length := i[0].Int()
s.console.Call("log", "length:", length)
s.inBuf = make([]uint8, length)
hdr := (*reflect.SliceHeader)(unsafe.Pointer(&s.inBuf))
ptr := uintptr(unsafe.Pointer(hdr.Data))
s.console.Call("log", "ptr:", ptr)
js.Global().Call("gotMem", ptr)
return nil
})
}
// Start sets up all the callbacks and waits for the close signal
// to be sent from the browser.
func (s *Decoder) Start() {
s.setupInitMemCb()
js.Global().Set("initMem", s.initMemCb)
s.setupOnImgLoadCb()
js.Global().Set("loadData", s.onImgLoadCb)
<-s.done
}

View File

@ -1,59 +1,81 @@
const go = new Go()
// memoryBytes is an Uint8Array pointing to the webassembly linear memory.
let memoryBytes;
let bytes;
let mod, inst
console.log("Initializing wasm...")
WebAssembly.instantiateStreaming(
fetch('lib.wasm'), go.importObject).then(
result => {
mod = result.module
inst = result.instance
memoryBytes = new Uint8Array(inst.exports.mem.buffer)
console.log("Initialization complete.")
run()
}
)
async function run() {
await go.run(inst)
inst = await WebAssembly.instantiate(mod, go.importObject) // reset instance
}
// gotMem sets the webassembly linear memory with the data buffer result
// at the slice header pointer passed from Go.
function gotMem(pointer) {
memoryBytes.set(bytes, pointer);
// Now the data can be loaded from the slice.
loadData();
}
// // displayImage takes the pointer to the target image in the wasm linear memory
// // and its length. Gets the resulting byte slice and creates an image blob.
// function displayImage(pointer, length) {
// let resultBytes = memoryBytes.slice(pointer, pointer + length);
// let blob = new Blob([resultBytes], {
// 'type': imageType
// });
// document.getElementById('targetImg').src = URL.createObjectURL(blob);
// }
// document.getElementById('input').addEventListener('change', function () {
// let reader = new FileReader();
// reader.onload = (ev) => {
// bytes = new Uint8Array(ev.target.result);
// initMem(bytes.length);
// let blob = new Blob([bytes], {
// 'type': imageType
// });
// document.getElementById("sourceImg").src = URL.createObjectURL(blob);
// };
// imageType = this.files[0].type;
// reader.readAsArrayBuffer(this.files[0]);
// });
window.onload = function () {
initWasm()
document.getElementById('input').addEventListener('change', playFile)
}
function playFile() {
console.log(decode(48000))
const input = event.target.files[0]
document.getElementById('input').addEventListener('change', function () {
const input = event.target.files[0]
const reader = new FileReader()
const reader = new FileReader()
reader.onload = event => playData(event.target.result)
reader.onerror = error => reject(error)
reader.readAsArrayBuffer(input)
}
reader.onload = event => {
bytes = new Uint8Array(event.target.result)
function playData(array) {
var data = new Uint8Array(array)
console.log("playing file")
var player = new PCMPlayer({
encoding: '16bitInt',
channels: 1,
sampleRate: 48000,
flushingTime: 2000
});
player.feed(data)
}
initMem(bytes.length)
function initWasm() {
if (!WebAssembly.instantiateStreaming) {
// polyfill
WebAssembly.instantiateStreaming = async (resp, importObject) => {
const source = await (await resp).arrayBuffer()
return await WebAssembly.instantiate(source, importObject)
// bytes should be decoded at this point, if not try memoryBytes.set(bytes, pointer)
console.log("playing file")
var player = new PCMPlayer({
encoding: '16bitInt',
channels: 1,
sampleRate: 48000,
flushingTime: 2000
});
player.feed(bytes)
}
}
const go = new Go()
let mod, inst
// memoryBytes is an Uint8Array pointing to the webassembly linear memory.
let memoryBytes;
console.log("Initializing wasm...")
WebAssembly.instantiateStreaming(
fetch('lib.wasm'), go.importObject).then(
result => {
mod = result.module
inst = result.instance
memoryBytes = new Uint8Array(inst.exports.mem.buffer)
console.log("Initialization complete.")
run()
}
)
async function run() {
await go.run(inst)
inst = await WebAssembly.instantiate(mod, go.importObject) // reset instance
}
reader.onerror = error => reject(error)
reader.readAsArrayBuffer(input)
})
}