mirror of https://bitbucket.org/ausocean/av.git
audio-player: wasm decoding merged with pcm player
This commit is contained in:
parent
1842319957
commit
e23c1aac7e
|
@ -1,27 +1,73 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"bytes"
|
||||||
|
"reflect"
|
||||||
"syscall/js"
|
"syscall/js"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"bitbucket.org/ausocean/av/codec/adpcm"
|
"bitbucket.org/ausocean/av/codec/adpcm"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
c := make(chan struct{}, 0)
|
dec := NewDecoder()
|
||||||
|
dec.Start()
|
||||||
println("WASM Go Initialized")
|
|
||||||
// register functions
|
|
||||||
registerCallbacks()
|
|
||||||
|
|
||||||
<-c
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func registerCallbacks() {
|
// Decoder is a client side adpcm decoder
|
||||||
js.Global().Set("decode", js.FuncOf(decode))
|
type Decoder struct {
|
||||||
|
inBuf []uint8
|
||||||
|
onImgLoadCb, initMemCb js.Func
|
||||||
|
console js.Value
|
||||||
|
done chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func decode(this js.Value, args []js.Value) interface{} {
|
// NewDecoder returns a new instance of decoder
|
||||||
fmt.Println("calculating")
|
func NewDecoder() *Decoder {
|
||||||
return adpcm.EncBytes(args[0].Int())
|
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
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,45 +1,10 @@
|
||||||
window.onload = function () {
|
const go = new Go()
|
||||||
initWasm()
|
// memoryBytes is an Uint8Array pointing to the webassembly linear memory.
|
||||||
document.getElementById('input').addEventListener('change', playFile)
|
let memoryBytes;
|
||||||
}
|
let bytes;
|
||||||
|
let mod, inst
|
||||||
function playFile() {
|
console.log("Initializing wasm...")
|
||||||
console.log(decode(48000))
|
WebAssembly.instantiateStreaming(
|
||||||
const input = event.target.files[0]
|
|
||||||
|
|
||||||
const reader = new FileReader()
|
|
||||||
reader.onload = event => playData(event.target.result)
|
|
||||||
reader.onerror = error => reject(error)
|
|
||||||
reader.readAsArrayBuffer(input)
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
function initWasm() {
|
|
||||||
if (!WebAssembly.instantiateStreaming) {
|
|
||||||
// polyfill
|
|
||||||
WebAssembly.instantiateStreaming = async (resp, importObject) => {
|
|
||||||
const source = await (await resp).arrayBuffer()
|
|
||||||
return await WebAssembly.instantiate(source, importObject)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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(
|
fetch('lib.wasm'), go.importObject).then(
|
||||||
result => {
|
result => {
|
||||||
mod = result.module
|
mod = result.module
|
||||||
|
@ -48,12 +13,69 @@ function initWasm() {
|
||||||
console.log("Initialization complete.")
|
console.log("Initialization complete.")
|
||||||
run()
|
run()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
async function run() {
|
async function run() {
|
||||||
await go.run(inst)
|
await go.run(inst)
|
||||||
inst = await WebAssembly.instantiate(mod, go.importObject) // reset instance
|
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 () {
|
||||||
|
|
||||||
|
document.getElementById('input').addEventListener('change', function () {
|
||||||
|
const input = event.target.files[0]
|
||||||
|
const reader = new FileReader()
|
||||||
|
|
||||||
|
reader.onload = event => {
|
||||||
|
bytes = new Uint8Array(event.target.result)
|
||||||
|
|
||||||
|
initMem(bytes.length)
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
|
reader.onerror = error => reject(error)
|
||||||
|
reader.readAsArrayBuffer(input)
|
||||||
|
|
||||||
|
})
|
||||||
}
|
}
|
Loading…
Reference in New Issue