123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450 |
- var printCharBuffers = [null, [], []]
- var UTF8Decoder = typeof TextDecoder !== 'undefined' ? new TextDecoder('utf8') : undefined
- var HEAP8 = null // Int8Array
- var HEAPU8 = null // Uint8Array
- var HEAP16 = null // Int16Array
- var HEAPU16 = null // Uint16Array
- var HEAP32 = null // Int32Array
- var HEAPU32 = null // Uint32Array
- var HEAPF32 = null // Float32Array
- var HEAPF64 = null // Float64Array
- //注入函数,打印字符串,C代码中打印字符串需要以\n结束
- function printChar(stream, curr) {
- var buffer = printCharBuffers[stream];
- //assert(buffer);
- if (curr === 0 || curr === 10) {
- //(stream === 1 ? out : err)(this.UTF8ArrayToString(buffer, 0));
- //buffer.length = 0;
- let str = UTF8ArrayToString(buffer, 0)
- console.log(str)//打印字符串
- buffer.length = 0;
- } else {
- buffer.push(curr);
- }
- }
- //注入函数,将字节数组转成字符数组
- function UTF8ArrayToString(heapOrArray, idx, maxBytesToRead) {
- var endIdx = idx + maxBytesToRead;
- var endPtr = idx;
- // TextDecoder needs to know the byte length in advance, it doesn't stop on
- // null terminator by itself. Also, use the length info to avoid running tiny
- // strings through TextDecoder, since .subarray() allocates garbage.
- // (As a tiny code save trick, compare endPtr against endIdx using a negation,
- // so that undefined means Infinity)
- while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr;
- if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) {
- return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr));
- }
- var str = '';
- // If building with TextDecoder, we have already computed the string length
- // above, so test loop end condition against that
- while (idx < endPtr) {
- // For UTF8 byte structure, see:
- // http://en.wikipedia.org/wiki/UTF-8#Description
- // https://www.ietf.org/rfc/rfc2279.txt
- // https://tools.ietf.org/html/rfc3629
- var u0 = heapOrArray[idx++];
- if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; }
- var u1 = heapOrArray[idx++] & 63;
- if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; }
- var u2 = heapOrArray[idx++] & 63;
- if ((u0 & 0xF0) == 0xE0) {
- u0 = ((u0 & 15) << 12) | (u1 << 6) | u2;
- } else {
- //if ((u0 & 0xF8) != 0xF0) warnOnce('Invalid UTF-8 leading byte ' + ptrToString(u0) + ' encountered when deserializing a UTF-8 string in wasm memory to a JS string!');
- u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63);
- }
- if (u0 < 0x10000) {
- str += String.fromCharCode(u0);
- } else {
- var ch = u0 - 0x10000;
- str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF));
- }
- }
- return str;
- }
- const wasmapi = {
- wasmInstance: null,//wasm实例
- wasmFuncs: null,//wasm导出函数
- wasmDataPtr: {//wasm模块的数据指针
- installBtsDataPtr: 0,//安装基站数据指针
- bleBtsDataPtr: 0,//蓝牙基站数据指针
- audioDataPtr: 0,//音频数据指针
- currentLocationCoordPtr: 0,//定位坐标数据指针
- accDataPtr: 0,//加速度指针
- },
- data: {
- audioDataList: [],//音频数据队列
- oneFrameLen: 12000,//一帧音频数据长度
- bleBtsMonitorSuccessFlag: false,//蓝牙基站监听成功标识符
- bleBtsDataList: [], //蓝牙基站队列
- installBtsInjectFlag: false,//安装基站已注入标识符
- accDataList: [],//加速度数据队列
- },
- ////wasm注入函数,将数据从源地址src拷贝长度为num的数据到目的地址dest
- _emscripten_memcpy_js(dest, src, num) {
- HEAPU8.copyWithin(dest, src, src + num)
- },
- _emscripten_resize_heap(requestedSize) {
- let oldSize = HEAPU8.length
- // With CAN_ADDRESS_2GB or MEMORY64, pointers are already unsigned.
- requestedSize >>>= 0
- this.abortOnCannotGrowMemory(requestedSize)
- },
- abortOnCannotGrowMemory(requestedSize) {
- abort(`Cannot enlarge memory arrays to size ${requestedSize} bytes (OOM). Either (1) compile with -sINITIAL_MEMORY=X with X higher than the current value ${HEAP8.length}, (2) compile with -sALLOW_MEMORY_GROWTH which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with -sABORTING_MALLOC=0`);
- },
- _fd_write(fd, iov, iovcnt, pnum) {
- let num = 0
- for (let i = 0; i < iovcnt; i++) {
- let ptr = HEAP32[((iov) >> 2)]
- let len = HEAP32[(((iov) + (4)) >> 2)]
- iov += 8
- for (let j = 0; j < len; j++) {
- printChar(fd, HEAPU8[ptr + j])
- }
- num += len
- }
- HEAP32[((pnum) >> 2)] = num
- return 0
- },
- _fd_close(fd) {
- abort('fd_close called without SYSCALLS_REQUIRE_FILESYSTEM');
- return 0
- },
- _fd_seek(fd, offset_low, offset_high, whence, newOffset) {
- abort('it should not be possible to operate on streams when !SYSCALLS_REQUIRE_FILESYSTEM')
- return 0;
- },
- _emscripten_date_now() {
- return new Date().getTime()
- },
- // __emscripten_get_now_is_monotonic() {
- // return 1
- // },
- // _emscripten_get_now() {
- // return new Date().getTime()
- // },
- //加载微信wasm模块
- loadWxWasm() {
- let self = this
- let configParam = {}
- configParam.emscripten_memcpy_js = this._emscripten_memcpy_js
- configParam.emscripten_resize_heap = this._emscripten_resize_heap
- configParam.fd_write = this._fd_write
- configParam.fd_close = this._fd_close
- configParam.fd_seek = this._fd_seek
- configParam.emscripten_date_now = this._emscripten_date_now
- // configParam._emscripten_get_now_is_monotonic = this.__emscripten_get_now_is_monotonic
- // configParam.emscripten_get_now = this._emscripten_get_now
- let importObject = {}
- importObject.env = configParam
- importObject.wasi_snapshot_preview1 = configParam
- //返回值res:{instance{}, Module{}}:包含instance和Module对象,instance中也包含Module。
- //js使用instance或者Module中Exports对象中的函数(包括用户自定义的函数和系统函数)完成既定功能
- //instantiate的第一个参数为绝对路径
- WXWebAssembly.instantiate("wasm/aplm8000sdk.wasm", importObject).then((res) => {
- self.wasmInstance = res.instance
- self.wasmFuncs = this.wasmInstance.exports
- if (self.wasmInstance.exports['memory']) {//初始化内存
- let buf = self.wasmInstance.exports['memory'].buffer
- HEAP8 = new Int8Array(buf)
- HEAPU8 = new Uint8Array(buf)
- HEAP16 = new Int16Array(buf)
- HEAPU16 = new Uint16Array(buf)
- HEAP32 = new Int32Array(buf)
- HEAPU32 = new Uint32Array(buf)
- HEAPF32 = new Float32Array(buf)
- HEAPF64 = new Float64Array(buf)
- }
- //wasm模块初始化
- self.wasmFuncs.main()
- //获得wasm模块路由基站数据指针
- self.wasmDataPtr.bleBtsDataPtr = self.wasmFuncs.exchange_js_get_route_bts_save_address()
- //获得wasm模块安装基站的数据指针
- self.wasmDataPtr.installBtsDataPtr = self.wasmFuncs.exchange_js_get_install_bts_save_address()
- //获得wasm模块音频数据指针
- self.wasmDataPtr.audioDataPtr = self.wasmFuncs.exchange_js_get_audio_data_save_address()
- //获得wasm模块定位坐标数据指针
- self.wasmDataPtr.currentLocationCoordPtr = self.wasmFuncs.exchange_js_get_current_location_coord_save_address()
- //获得wasm模块加速度数据指针
- self.wasmDataPtr.accDataPtr = self.wasmFuncs.exchange_js_get_acc_save_address()
- //通知主控模块开始监听蓝牙基站
- worker.postMessage({
- message: 'WORKER_MAIN_START_MONITOR_BLE_BTS',
- data: ''
- })
- // //通知主控模块开始录音
- // worker.postMessage({
- // message: 'WORKER_MAIN_START_REC',
- // data: ''
- // })
- // //通知主控模块开始读取本地文件
- // worker.postMessage({
- // message: 'WORKER_MAIN_NOTICE_DOWNLOAD_AUDIO_FILE',
- // data: ''
- // })
- }).catch((err) => {
- console.log("加载wasm对象出错", err)
- })
- },
- //保存蓝牙基站数据至本地
- saveBleBtsDataToLocal(dataList) {
- if (!dataList || dataList.length < 4) {
- return
- }
- //蓝牙基站监听成功,保存数据
- this.data.bleBtsMonitorSuccessFlag = true//蓝牙基站监听成功
- this.data.bleBtsDataList.splice(0, this.data.bleBtsDataList.length)
- this.data.bleBtsDataList = dataList
- //通知主控模块注入安装基站数据(只注入一次)
- if (!this.data.installBtsInjectFlag) {
- worker.postMessage({
- message: 'WORKER_MAIN_ORGANIZE_INSTALL_BTS_DATA',//通知主线程组织安装基站数据
- data: ''
- })
- }
- },
- //清除蓝牙基站设备(没有监听到本系统的蓝牙基站)
- clearBleBtsData() {
- this.data.bleBtsMonitorSuccessFlag = false//蓝牙基站监听失败
- this.data.bleBtsDataList.splice(0, this.data.bleBtsDataList.length)
- },
- //发送蓝牙基站数据至wasm模块
- sendBleBtsDataToWasm() {
- let dataList = []
- //监听蓝牙基站失败
- if (!this.data.bleBtsMonitorSuccessFlag) {
- return
- }
- //将数据保存至wasm模块
- dataList = this.data.bleBtsDataList
- let dataLen = dataList.length
- if (this.wasmDataPtr.bleBtsDataPtr > 0) {
- let ptr = this.wasmDataPtr.bleBtsDataPtr / 4//蓝牙基站数据在wasm模块按4字节存储
- for (let i = 0; i < dataLen; i++) {
- HEAP32[ptr + i] = dataList[i]//写入数据
- }
- } else {
- console.log("蓝牙指针尚未初始化")
- }
- //清除本地蓝牙基站数据
- this.data.bleBtsDataList.splice(0, this.data.bleBtsDataList.length)
- this.data.bleBtsMonitorSuccessFlag = false
- // // //TODO,打印一下看看效果,正式版本要去掉
- // if (this.wasmFuncs != null) {
- // this.wasmFuncs.exchange_js_notice_wasm_show_route_bts();
- // }
- },
- //发送安装基站数据至wasm模块
- sendInstallBtsDataToWasm(dataList) {
- //将数据保存至wasm模块
- if (this.wasmDataPtr.installBtsDataPtr > 0) {
- this.data.installBtsInjectFlag = true//注入标识符置1
- //向wasm模块注入数据
- let ptr = this.wasmDataPtr.installBtsDataPtr / 4//蓝牙基站数据在wasm模块按4字节存储
- for (let i = 0; i < dataList.length; i++) {
- HEAP32[ptr + i] = dataList[i]
- }
- ////TODO 打印看看效果
- //this.wasmFuncs.exchange_js_notice_wasm_show_install_bts()
- //向主线程发消息开始录音
- worker.postMessage({
- message: 'WORKER_MAIN_START_REC',
- data: ''
- })
- }
- // // TODO,打印一下看看效果,正式版本要去掉
- // if (this.wasmFuncs != null) {
- // this.wasmFuncs.exchange_js_notice_wasm_show_install_bts()
- // }
- },
- //处理音频数据,实施定位操作
- //buffer:录音数据,为二进制单字节(byte)数据数组
- processAudioData(buffer) {
- //注入蓝牙基站数据
- this.sendBleBtsDataToWasm()
- ////创建数据视图。
- //录音数据是arraryBuffer类型,该类型数据为二进制单字节(byte)数据数组,不能直接读写,需要在buffer上创建数据视图后方可操作数据
- const dataView = new DataView(buffer);//创建一个数据视图
- //遍历数据视图
- let sample = 0
- let dataLen = Math.floor(dataView.byteLength / 2) //一个采样点为两个字节
- if (dataLen > 0) {
- //把数据插入全局队列,以便实施成帧处理
- for (let i = 0; i < dataLen; i++) {
- sample = dataView.getInt16(2 * i, true)//数据大小端模式,true:小端模式,false:大端模式
- this.data.audioDataList.push(sample)
- }
- //计算全局队列中数据的帧数
- let frameCounter = Math.floor(this.data.audioDataList.length / this.data.oneFrameLen)
- if (frameCounter) {//至少有一帧数据
- //截取音频数据帧(可能是1帧,也可能是多帧。若是多帧,有可能导致处理超时)
- const dataList = this.data.audioDataList.splice(0, frameCounter * this.data.oneFrameLen)
- //把音频数据逐帧注入wasm模块
- let ptr = this.wasmDataPtr.audioDataPtr / 2//音频数据在wasm模块中按2字节存储
- for (let i = 0; i < frameCounter; i++) {
- //let beginTime = new Date().getTime()//开始计时
- //1、把数据注入wasm模块
- let baseIndex = i * this.data.oneFrameLen
- for (let j = 0; j < this.data.oneFrameLen; j++) {
- let item = dataList[baseIndex + j]
- HEAP16[ptr + j] = item//把音频数据注入wasm模块
- }
- //2、注入加速度数据
- let oneFrameAccDataList = []
- oneFrameAccDataList = this.organizeOneFrameAccData()//组织一秒加速度数据
- this.injectAccDataToWasm(oneFrameAccDataList)//注入数据
- //3、通知wasm模块处理音频数据
- let result = this.wasmFuncs.exchange_js_notice_wasm_start_work()
- //let stopTime = new Date().getTime() - beginTime//结束计时
- //console.log("耗时:", stopTime)
- //4、获取wasm模块处理音频数据的结果
- if (result != 1) {
- console.log("音频数据处理错误")
- } else {
- let item = []
- //定位坐标数据在wasm模块中按4字节存储
- let locationCoordPtr = this.wasmDataPtr.currentLocationCoordPtr / 4
- //a、从wasm模块读取音频数据处理结果
- for (let i = 0; i < 18; i++) {
- item.push(HEAP32[locationCoordPtr + i])
- }
- //TODO,b、使用定位结果这部分,需要二次开放商根据业务需求,做定制开发
- //使用定位结果
- if (item[0] === 1 && item[1] === 1) {
- let coord = {}
- coord.x = item[2]
- coord.y = item[3]
- //imu移动标识符
- const imuMoveFlag = item[17]//0:惯导计算出错,1:惯导计算成功,但手机未移动,50:惯导计算能成功,手机有移动
- if (imuMoveFlag == 50) {//手机有移动
- //将定位坐标发送至主线程
- worker.postMessage({
- message: 'WORKER_MAIN_CURRENT_LOCATION_COORD',
- data: coord
- })
- } else {//手机未移动或者出错
- console.log("imu move flag:", imuMoveFlag)
- }
- }
- // //向主线程发消息,通知读取音频文件
- // worker.postMessage({
- // message: 'WORKER_MAIN_NOTICE_READ_AUDIO_FILE',//读取音频文件
- // data: ''
- // })
- }
- }
- }
- }
- return
- },
- //缓存加速度数据
- storeAccData(oneAccData) {
- let item = {}
- item.timestamp = oneAccData.timestamp
- item.x = oneAccData.x
- item.y = oneAccData.y
- item.z = oneAccData.z
- this.data.accDataList.push(item)//缓存加速度
- },
- //组织一帧加速度数据(约250毫秒)
- organizeOneFrameAccData() {
- let oneFrameAccData = [] //一帧加速度数据
- if (this.data.accDataList.length > 0) {
- let stopTimestamp = this.data.accDataList[0].timestamp + 260//250毫秒的数据
- let accCounter = 0//计数器
- for (let k = 0; k < this.data.accDataList.length; k++) {
- let oneAcc = {}
- oneAcc = this.data.accDataList[k]
- if (oneAcc.timestamp <= stopTimestamp) {
- oneFrameAccData.push(oneAcc)
- accCounter++
- } else {
- break
- }
- }
- this.data.accDataList = this.data.accDataList.slice(accCounter)//截取加速度队列
- }
- return oneFrameAccData
- },
- //注入加速度到wasm模块
- injectAccDataToWasm(dataList) {
- let ptr = this.wasmDataPtr.accDataPtr / 4//加速度数据在wasm模块中按4字节存储
- let wLen = dataList.length;
- let item = {}
- if (wLen > 0) {
- //注入队列长度
- HEAPU32[ptr] = wLen //加速度队列长度
- ptr++
- //注入3轴加速度
- for (let i = 0; i < wLen; i++) {
- item = dataList[i]
- ptr = ptr + i * 3//修改数据指针
- HEAPF32[ptr] = item.x//x轴加速度
- HEAPF32[ptr + 1] = item.y//y轴加速度
- HEAPF32[ptr + 2] = item.z//z轴加速度
- }
- //保存数据
- this.wasmFuncs.exchange_js_notice_wasm_save_acc()
- }
- },
- //通知wasm模块释放内存
- noticeWasmFreeMemory() {
- this.wasmFuncs.exchange_js_notice_wasm_free_memory()
- }
- }
- export default wasmapi
|