From 00b23ff54f0605b02fb0e9ea7da3904eba51b784 Mon Sep 17 00:00:00 2001 From: Georgi Gerganov Date: Sun, 18 Apr 2021 13:20:45 +0300 Subject: [PATCH] r2t2 - Transmit data through the PC speaker (#32) * inital implementation * remove file * ggwave-cli : txProtocol -> txProtocolId * ggwave : add custom protocol enum values * r2t2 : use cutom protocols * r2t2 : build only on Unix systems * r2t2 : remove thread * r2t2-rx : wip * r2t2 : wasm build ready + various fixes * r2t2 : error message * Update README.md * Update README.md * Update README.md * Update README.md * r2t2 : length 16 * r2t2 : use slow protocol by default * r2t2 : add timestamp * r2t2 : update html * r2t2 : update github link * r2t2 : more robust tx * r2t2 : add option to use beep command * emscripten : cannot use requestAnimationFrame when capturing audio This causes the queued audio buffer to grow indefinitely when the page is not focused, causing the process to run out of memory. * r2t2 : disable beep option * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md * r2t2 : add example to README --- README-tmpl.md | 1 + README.md | 1 + bindings/javascript/ggwave.js | 2 +- examples/CMakeLists.txt | 4 + examples/ggwave-cli/main.cpp | 10 +- examples/ggwave-common-sdl2.cpp | 3 +- examples/ggwave-rx/CMakeLists.txt | 1 - examples/ggwave-wasm/index-tmpl.html | 38 +- examples/r2t2/CMakeLists.txt | 71 + examples/r2t2/README.md | 58 + examples/r2t2/build_timestamp-tmpl.h | 1 + .../r2t2/ggwave-mod/include/ggwave/ggwave.h | 511 +++++++ examples/r2t2/ggwave-mod/src/ggwave.cpp | 1359 +++++++++++++++++ .../r2t2/ggwave-mod/src/reed-solomon/LICENSE | 21 + .../r2t2/ggwave-mod/src/reed-solomon/gf.hpp | 235 +++ .../r2t2/ggwave-mod/src/reed-solomon/poly.hpp | 94 ++ .../r2t2/ggwave-mod/src/reed-solomon/rs.hpp | 538 +++++++ examples/r2t2/ggwave-mod/src/resampler.cpp | 157 ++ examples/r2t2/ggwave-mod/src/resampler.h | 49 + examples/r2t2/index-tmpl.html | 174 +++ examples/r2t2/main.cpp | 136 ++ examples/r2t2/main.js | 55 + examples/r2t2/plucky.mp3 | Bin 0 -> 28003 bytes examples/r2t2/r2t2-rx.cpp | 369 +++++ examples/r2t2/style.css | 279 ++++ examples/spectrogram/main.cpp | 2 +- examples/waver/main.cpp | 2 +- include/ggwave/ggwave.h | 11 + 28 files changed, 4153 insertions(+), 29 deletions(-) create mode 100644 examples/r2t2/CMakeLists.txt create mode 100644 examples/r2t2/README.md create mode 100644 examples/r2t2/build_timestamp-tmpl.h create mode 100644 examples/r2t2/ggwave-mod/include/ggwave/ggwave.h create mode 100644 examples/r2t2/ggwave-mod/src/ggwave.cpp create mode 100644 examples/r2t2/ggwave-mod/src/reed-solomon/LICENSE create mode 100644 examples/r2t2/ggwave-mod/src/reed-solomon/gf.hpp create mode 100644 examples/r2t2/ggwave-mod/src/reed-solomon/poly.hpp create mode 100644 examples/r2t2/ggwave-mod/src/reed-solomon/rs.hpp create mode 100644 examples/r2t2/ggwave-mod/src/resampler.cpp create mode 100644 examples/r2t2/ggwave-mod/src/resampler.h create mode 100644 examples/r2t2/index-tmpl.html create mode 100644 examples/r2t2/main.cpp create mode 100644 examples/r2t2/main.js create mode 100644 examples/r2t2/plucky.mp3 create mode 100644 examples/r2t2/r2t2-rx.cpp create mode 100644 examples/r2t2/style.css diff --git a/README-tmpl.md b/README-tmpl.md index 71b77f6..02fa7ee 100644 --- a/README-tmpl.md +++ b/README-tmpl.md @@ -101,6 +101,7 @@ The [examples](https://github.com/ggerganov/ggwave/blob/master/examples/) folder | [ggwave-js](https://github.com/ggerganov/ggwave/blob/master/examples/ggwave-js) | Javascript example | Web Audio API | | [spectrogram](https://github.com/ggerganov/ggwave/blob/master/examples/spectrogram) | Spectrogram tool | SDL | | [ggweb-spike](https://gitlab.com/commonsguy/ggweb-spike) | Android example using a `WebView` to wrap `ggwave` into a simple app | WebAudio | +| [r2t2](https://gitlab.com/ggerganov/ggwave/blob/master/examples/r2t2) | Transmit data through the PC speaker | PC speaker | Other projects using **ggwave** or one of its prototypes: diff --git a/README.md b/README.md index ef54267..f32cdea 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,7 @@ The [examples](https://github.com/ggerganov/ggwave/blob/master/examples/) folder | [ggwave-js](https://github.com/ggerganov/ggwave/blob/master/examples/ggwave-js) | Javascript example | Web Audio API | | [spectrogram](https://github.com/ggerganov/ggwave/blob/master/examples/spectrogram) | Spectrogram tool | SDL | | [ggweb-spike](https://gitlab.com/commonsguy/ggweb-spike) | Android example using a `WebView` to wrap `ggwave` into a simple app | WebAudio | +| [r2t2](https://gitlab.com/ggerganov/ggwave/blob/master/examples/r2t2) | Transmit data through the PC speaker | PC speaker | Other projects using **ggwave** or one of its prototypes: diff --git a/bindings/javascript/ggwave.js b/bindings/javascript/ggwave.js index 05579b5..00e426d 100644 --- a/bindings/javascript/ggwave.js +++ b/bindings/javascript/ggwave.js @@ -6,7 +6,7 @@ var ggwave_factory = (function() { function(ggwave_factory) { ggwave_factory = ggwave_factory || {}; -var Module=typeof ggwave_factory!=="undefined"?ggwave_factory:{};var readyPromiseResolve,readyPromiseReject;Module["ready"]=new Promise(function(resolve,reject){readyPromiseResolve=resolve;readyPromiseReject=reject});var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=require("path").dirname(scriptDirectory)+"/"}else{scriptDirectory=__dirname+"/"}read_=function shell_read(filename,binary){var ret=tryParseAsDataURI(filename);if(ret){return binary?ret:ret.toString()}if(!nodeFS)nodeFS=require("fs");if(!nodePath)nodePath=require("path");filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/")}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status)};Module["inspect"]=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){var data=tryParseAsDataURI(f);if(data){return intArrayToString(data)}return read(f)}}readBinary=function readBinary(f){var data;data=tryParseAsDataURI(f);if(data){return data}if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs}else if(typeof arguments!="undefined"){arguments_=arguments}if(typeof quit==="function"){quit_=function(status){quit(status)}}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!=="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(_scriptDir){scriptDirectory=_scriptDir}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1)}else{scriptDirectory=""}{read_=function(url){try{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText}catch(err){var data=tryParseAsDataURI(url);if(data){return intArrayToString(data)}throw err}};if(ENVIRONMENT_IS_WORKER){readBinary=function(url){try{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}catch(err){var data=tryParseAsDataURI(url);if(data){return data}throw err}}}readAsync=function(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}var data=tryParseAsDataURI(url);if(data){onload(data.buffer);return}onerror()};xhr.onerror=onerror;xhr.send(null)}}setWindowTitle=function(title){document.title=title}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var tempRet0=0;var setTempRet0=function(value){tempRet0=value};var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(typeof WebAssembly!=="object"){abort("no native wasm support detected")}var wasmMemory;var ABORT=false;var EXITSTATUS;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}var UTF8Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf8"):undefined;function UTF8ArrayToString(heap,idx,maxBytesToRead){var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heap[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heap.subarray&&UTF8Decoder){return UTF8Decoder.decode(heap.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023)}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4}return len}var UTF16Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf-16le"):undefined;function UTF16ToString(ptr,maxBytesToRead){var endPtr=ptr;var idx=endPtr>>1;var maxIdx=idx+maxBytesToRead/2;while(!(idx>=maxIdx)&&HEAPU16[idx])++idx;endPtr=idx<<1;if(endPtr-ptr>32&&UTF16Decoder){return UTF16Decoder.decode(HEAPU8.subarray(ptr,endPtr))}else{var str="";for(var i=0;!(i>=maxBytesToRead/2);++i){var codeUnit=HEAP16[ptr+i*2>>1];if(codeUnit==0)break;str+=String.fromCharCode(codeUnit)}return str}}function stringToUTF16(str,outPtr,maxBytesToWrite){if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<2)return 0;maxBytesToWrite-=2;var startPtr=outPtr;var numCharsToWrite=maxBytesToWrite>1]=codeUnit;outPtr+=2}HEAP16[outPtr>>1]=0;return outPtr-startPtr}function lengthBytesUTF16(str){return str.length*2}function UTF32ToString(ptr,maxBytesToRead){var i=0;var str="";while(!(i>=maxBytesToRead/4)){var utf32=HEAP32[ptr+i*4>>2];if(utf32==0)break;++i;if(utf32>=65536){var ch=utf32-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}else{str+=String.fromCharCode(utf32)}}return str}function stringToUTF32(str,outPtr,maxBytesToWrite){if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<4)return 0;var startPtr=outPtr;var endPtr=startPtr+maxBytesToWrite-4;for(var i=0;i=55296&&codeUnit<=57343){var trailSurrogate=str.charCodeAt(++i);codeUnit=65536+((codeUnit&1023)<<10)|trailSurrogate&1023}HEAP32[outPtr>>2]=codeUnit;outPtr+=4;if(outPtr+4>endPtr)break}HEAP32[outPtr>>2]=0;return outPtr-startPtr}function lengthBytesUTF32(str){var len=0;for(var i=0;i=55296&&codeUnit<=57343)++i;len+=4}return len}function allocateUTF8(str){var size=lengthBytesUTF8(str)+1;var ret=_malloc(size);if(ret)stringToUTF8Array(str,HEAP8,ret,size);return ret}function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf)}var INITIAL_MEMORY=Module["INITIAL_MEMORY"]||16777216;var wasmTable;var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;__ATINIT__.push({func:function(){___wasm_call_ctors()}});function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what+="";err(what);ABORT=true;EXITSTATUS=1;what="abort("+what+"). Build with -s ASSERTIONS=1 for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject(e);throw e}function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="data:application/octet-stream;base64,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QYDABHENACAFIAFB/wFxIAIgA2siAkGAAiACQYACSSIBGxAfGiABRQRAA0AgACAFQYACECMgAkGAAmsiAkH/AUsNAAsLIAAgBSACECMLIAVBgAJqJAALJQEBfyMAQRBrIgMkACADIAI2AgwgACABIAJBABBoIANBEGokAAvwAwEDfyMAQdABayIAJAACQEHQ1wAtAABBAXENACMAQRBrIgEkAAJ/IAFBADYCDCABQdDXADYCBCABQdDXADYCACABQdHXADYCCCABCxDBASECIAFBEGokACACRQ0AIABBATYCwAEgAEKYgICAMDcDuAEgAEHJGDYCtAEgAEKBgICAgAE3AqwBIABCmICAgOAANwKkASAAQb8YNgKgASAAQoGAgIDwADcDmAEgAEKYgICAkAE3A5ABIABBsxg2AowBIABCg4CAgOAANwKEASAAQsCCgIAwNwJ8IABBpxg2AnggAEKDgICA0AA3A3AgAELAgoCA4AA3A2ggAEGeGDYCZCAAQoOAgIDAADcCXCAAQsCCgICQATcCVCAAQZMYNgJQIABCg4CAgDA3A0ggAEFAa0KogICAMDcDACAAQYsYNgI8IABCg4CAgCA3AjQgAEKogICA4AA3AiwgAEGGGDYCKCAAQoOAgIAQNwMgIABCqICAgJABNwMYIABB/xc2AhQgAEEANgIQIABBCTYCzAEgACAAQRBqNgLIASAAIAApA8gBNwMAIAAQlgEjAEEQayIBJAACfyABQQA2AgwgAUHQ1wA2AgQgAUHQ1wA2AgAgAUHR1wA2AgggAQsQvwEgAUEQaiQACyAAQdABaiQAQcTXAAsGACAAECALowIBBH8jAEFAaiICJAAgACgCACIDQQRrKAIAIQQgA0EIaygCACEFIAJBADYCFCACQcTNADYCECACIAA2AgwgAiABNgIIQQAhAyACQRhqQQBBJxAfGiAAIAVqIQACQCAEIAFBABAiBEAgAkEBNgI4IAQgAkEIaiAAIABBAUEAIAQoAgAoAhQRCQAgAEEAIAIoAiBBAUYbIQMMAQsgBCACQQhqIABBAUEAIAQoAgAoAhgRCAACQAJAIAIoAiwOAgABAgsgAigCHEEAIAIoAihBAUYbQQAgAigCJEEBRhtBACACKAIwQQFGGyEDDAELIAIoAiBBAUcEQCACKAIwDQEgAigCJEEBRw0BIAIoAihB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ACgCBCAEayIDaiACIAYgA0ECdSIHSxsiAyABayIFBEAgBCABIAUQKgsgBiAHSwRAIAAoAgQhASAAIAIgA2siAEEBTgR/IAEgAyAAECEgAGoFIAELNgIEDwsgACAEIAVqNgIEDwsgBARAIAAgBDYCBCAEECAgAEEANgIIIABCADcCAEEAIQULAkAgBkGAgICABE8NACAGIAVBAXUiAiACIAZJG0H/////AyAFQQJ1Qf////8BSRsiAkGAgICABE8NACAAIAJBAnQiBBAeIgI2AgAgACACNgIEIAAgAiAEajYCCCAAIANBAU4EfyACIAEgAxAhIANqBSACCzYCBA8LECkACyUBAn9BCBADIgAiAUHMFxBiIAFBvMwANgIAIABB3MwAQRcQBgALHQAgAQRAIAAgASgCABBAIAAgASgCBBBAIAEQIAsLSwECfyAAKAIEIgZBCHUhByAAKAIAIgAgASACIAZBAXEEfyADKAIAIAdqKAIABSAHCyADaiAEQQIgBkECcRsgBSAAKAIAKAIUEQkAC6MBACAAQQE6ADUCQCAAKAIEIAJHDQAgAEEBOgA0IAAoAhAiAkUEQCAAQQE2AiQgACADNgIYIAAgATYCECADQQFHDQEgACgCMEEBRw0BIABBAToANg8LIAEgAkYEQCAAKAIYIgJBAkYEQCAAIAM2AhggAyECCyAAKAIwQQFHDQEgAkEBRw0BIABBAToANg8LIABBAToANiAAIAAoAiRBAWo2AiQLC10BAX8gACgCECIDRQRAIABBATYCJCAAIAI2AhggACABNgIQDwsCQCABIANGBEAgACgCGEECRw0BIAAgAjYCGA8LIABBAToANiAAQQI2AhggACAAKAIkQQFqNgIkCwsUACAAQcTLADYCACAAQQRqEGAgAAsJAEGYygAQMgALJQEBfyMAQRBrIgMkACADIAI2AgwgACABIAJBLRBoIANBEGokAAueEQIPfwF+IwBB0ABrIgYkACAGIAE2AkwgBkE3aiEUIAZBOGohEkEAIQECQANAAkAgD0EASA0AQf////8HIA9rIAFIBEBB5NcBQT02AgBBfyEPDAELIAEgD2ohDwsgBigCTCILIQECQAJAAkAgCy0AACIHBEADQAJAAkAgB0H/AXEiB0UEQCABIQcMAQsgB0ElRw0BIAEhBwNAIAEtAAFBJUcNASAGIAFB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LABLQQBIBEBBACEDDAELIAEhBANAIAQiA0UEQEEAIQMMAgsgACADQQFrIgRqLQAAQQpHDQALIAIgACADIAIoAiQRBgAiBCADSQ0BIAAgA2ohACABIANrIQEgAigCFCEFCyAFIAAgARAhGiACIAIoAhQgAWo2AhQgASADaiEECyAEC0kAAkAgAUUNACABQcTPABAoIgFFDQAgASgCCCAAKAIIQX9zcQ0AIAAoAgwgASgCDEEAECJFDQAgACgCECABKAIQQQAQIg8LQQALUgEBfyAAKAIEIQQgACgCACIAIAECf0EAIAJFDQAaIARBCHUiASAEQQFxRQ0AGiACKAIAIAFqKAIACyACaiADQQIgBEECcRsgACgCACgCHBEHAAsKACAAIAFBABAiCwsAIAAQRBogABAgCxQAIABB2MsANgIAIABBBGoQYCAACwcAIAAoAgQLLAEBfwJ/IAAoAgBBDGsiACIBIAEoAghBAWsiATYCCCABQX9MCwRAIAAQIAsLewICfwF+IwBBMGsiACQAQQEgAEEgahAWBEBB5NcBKAIAGhAIAAsgAAJ/IABBEGoiASAANAIgNwMAIAELAn8gAEEIaiIBIABBIGpBBHI0AgA3AwAgAQsQxQE3AxggAEEoaiIBIAApAxg3AwAgASkDACECIABBMGokACACCx0AIABBmMsANgIAIABBxMsANgIAIABBBGogARBjCzcBAn8gARBYIgJBDWoQHiIDQQA2AgggAyACNgIEIAMgAjYCACAAIANBDGogASACQQFqECE2AgALCgAgAEHM2AEQFwsKACAAQbDYARAYC7sCAAJAIAFBFEsNAAJAAkACQAJAAkACQAJAAkACQAJAIAFBCWsOCgABAgMEBQYHCAkKCyACIAIoAgAiAUEEajYCACAAIAEoAgA2AgAPCyACIAIoAgAiAUEEajYCACAAIAE0AgA3AwAPCyACIAIoAgAiAUEEajYCACAAIAE1AgA3AwAPCyACIAIoAgBBB2pBeHEiAUEIajYCACAAIAEpAwA3AwAPCyACIAIoAgAiAUEEajYCACAAIAEyAQA3AwAPCyACIAIoAgAiAUEEajYCACAAIAEzAQA3AwAPCyACIAIoAgAiAUEEajYCACAAIAEwAAA3AwAPCyACIAIoAgAiAUEEajYCACAAIAExAAA3AwAPCyACIAIoAgBBB2pB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AQsLIAIgAzYCACAADwsgAiADNgIAIAEPCyACIAc2AgAgBw8LIAIgATYCACADIAE2AgAgAwsPAEHE1wBByNcAKAIAEDgLwwMCBX8CfkHI1wBCADcCAEHE1wBByNcANgIAAkAgACgCBCICRQ0AIAAoAgAiAyACQRRsaiEFQcjXACEAA0BByNcAKAIAIQICQAJAAkBByNcAIgEgAEYNAAJAIAIiAARAA0AgACIBKAIEIgANAAwCCwALQdDXACEBQdDXACgCACgCAEHI1wBGBEADQCABKAIAIgBBCGohASAAIAAoAggoAgBGDQALCyABKAIAIQELIAMoAgAiBCABKAIQSg0AIAJFBEBByNcAIgAhAgwCCwNAIAIiACgCECICIARKBEAgACgCACICDQEgACECDAMLIAIgBE4NAyAAKAIEIgINAAsgACICQQRqIQAMAQsgAUEEakHI1wAgAhsiACgCAA0BIAFByNcAIAIbIQILQSQQHiEBIAMpAgghBiADKAIQIQQgAykCACEHIAEgAjYCCCABQgA3AgAgASAENgIgIAEgBjcCGCABIAc3AhAgACABNgIAQcTXACgCACgCACICBEBBxNcAIAI2AgAgACgCACEBC0HI1wAoAgAgARAtQczXAEHM1wAoAgBBAWo2AgALIANBFGoiAyAFRg0BQcTXACgCACEADAALAAsLswMBB38gASAAKAIIIgQgACgCBCICa0EMbU0EQCAAIAEEfyACQQAgAUEMbEEMa0EMbkEMbEEMaiIAEB8gAGoFIAILNgIEDwsCQAJAAkAgAiAAKAIAIgZrQQxtIgUgAWoiA0HWqtWqAUkEQAJ/IAMgBCAGa0EMbSIEQQF0IgcgAyAHSxtB1arVqgEgBEGq1arVAEkbIgQEQCAEQdaq1aoBTw0DIARBDGwQHiEICyAIIAVBDGxqIgMLQQAgAUEMbEEMa0EMbkEMbEEMaiIBEB8iByABaiEFIAggBEEMbGohASACIAZGDQIDQCADQQxrIgNBADYCCCADQgA3AgAgAyACQQxrIgIoAgA2AgAgAyACKAIENgIEIAMgAigCCDYCCCACQQA2AgggAkIANwIAIAIgBkcNAAsgACABNgIIIAAoAgQhASAAIAU2AgQgACgCACECIAAgAzYCACABIAJGDQMDQCABQQxrIgAoAgAiAwRAIAFBCGsgAzYCACAD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AgwACwALIARBAToADAsPCyABLQAMDQAgAiEDDAELIANBAToADCACQQA6AAwgAiADKAIEIgA2AgAgAARAIAAgAjYCCAsgAyACKAIINgIIIAIoAggiACAAKAIAIAJHQQJ0aiADNgIAIAMgAjYCBCACIAM2AgggAiEBCyADIAMoAggiAC0ADDoADCAAQQE6AAwgAUEBOgAMIAAgACgCBCIBKAIAIgI2AgQgAgRAIAIgADYCCAsgASAAKAIINgIIIAAoAggiAiACKAIAIABHQQJ0aiABNgIAIAEgADYCACAAIAE2AggLowUBBH8gACgClAMhASAAQQA2ApQDIAEEQCABKAIkIgIEQCABIAI2AiggAhAgCyABKAIYIgIEQCABIAI2AhwgAhAgCyABKAIMIgIEQCABIAI2AhAgAhAgCyABKAIAIgIEQCABIAI2AgQgAhAgCyABECALIAAoAogDIgEEQCAAIAE2AowDIAEQIAsgACgC/AIiAQRAIAAgATYCgAMgARAgCyAAKALwAiIBBEAgACABNgL0AiABECALIAAoAuQCIgEEQCAAIAE2AugCIAEQIAsgACgC2AIiAQRAIAAgATYC3AIgARAgCyAAKAK8AiIBBEAgACABNgLAAiABECALIAAoArACIgEEQCAAIAE2ArQCIAEQIAsgACgCmAIiAwRAAn8gAyADIAAoApwCIgFGDQAaA0AgAUEMayICKAIAIgQEQCABQQhrIAQ2AgAgBBAgCyACIgEgA0cNAAsgACgCmAILIQEgACADNgKcAiABECALIAAoAogCIgEEQCAAIAE2AowCIAEQIAsgACgC/AEiAwRAAn8gAyADIAAoAoACIgFGDQAaA0AgAUEMayICKAIAIgQEQCABQQhrIAQ2AgAgBBAgCyACIgEgA0cNAAsgACgC/AELIQEgACADNgKAAiABECALIAAoAvABIgEEQCAAIAE2AvQBIAEQIAsgAEHgAWogACgC5AEQOCAAKALAASIBBEAgACABNgLEASABECALIAAoAqwBIgEEQCAAIAE2ArABIAEQIAsgACgCoAEiAQRAIAAgATYCpAEgARAgCyAAKAKUASIBBEAgACABNgKYASABECALIAAoAogBIgEEQCAAIAE2AowBIAEQIAsgACgCeCIBBEAgACABNgJ8IAEQIAsgACgCbCIBBEAgACABNgJwIAEQIAsgAAvCAwEEf0G41wAhAgJAQbjXACgCACIBRQRAQbjXACEBDAELA0ACQCAAIAEoAhAiA0gEQCABKAIAIgMNASABIQIMAwsgACADTA0CIAFBBGohAiABKAIEIgNFDQIgAiEBCyABIQIgAyEBDAALAAsgAigCACIDRQRAQRgQHiIDQQA2AhQgAyAANgIQIAMgATYCCCADQgA3AgAgAiADNgIAAn8gA0G01wAoAgAoAgAiAUUNABpBtNcAIAE2AgAgAigCAAshAUG41wAoAgAgARAtQbzXAEG81wAoAgBBAWo2AgALIAMoAhQiAQRAIAEQowEQIAsCQEG41wAoAgAiBEUNAEG41wAhAiAEIQEDQCACIAEgASgCECAASCIDGyECIAEgA0ECdGooAgAiAQ0ACyACQbjXAEYNACACKAIQIABKDQACQCACKAIEIgFFBEAgAigCCCIAKAIAIAJGDQEgAkEIaiEDA0AgAygCACIBQQhqIQMgASABKAIIIgAoAgBHDQALDAELA0AgASIAKAIAIgENAAsLIAJBtNcAKAIARgRAQbTXACAANgIAC0G81wBBvNcAKAIAQQFrNgIAIAQgAhCiASACECALC+cUAgt/AX0jAEHQAGsiBiQAIAAgASoCBDgCACAAIAEqAgg4AgQgACABKAIMIgI2AgggAEMAAIA/IAKylTgCDCAAAn8gASgCFCICQQZPBEAgBiACNgIwQbjJACgCAEHkFyAGQTBqECVBAAwBCyACQQJ0QcQiaigCAAs2AhAgAAJ/IAEoAhgiA0EGTwRAIAYgAzYCIEG4yQAoAgBB5BcgBkEgahAlIAEoAhghA0EADAELIANBAnRBxCJqKAIACzYCFCABKAIUIQIgACADNgIcIAAgAjYCGCABKAIMIQIgAEEQNgIwIABBATYCKCAAQwCAO0cgArKVIg04AiAgACANIA2SOAIsIABDAACAPyANlTgCJCAAQQBBAyABKAIAIgJBAEoiAxs2AjggACACQQFIQQR0NgI0IAEqAhAhDSAAIAI2AkQgACADOgBAIAAgDTgCPCAAQQA2AnQgAEIANwJsIAAgACgCCDYCaCAAQYDAABAeIgI2AmwgACACQYBAayIDNgJ0IAJBAEGAwAAQHxogAEEANgKAASAAQgA3AnggACADNgJwIABBgIABEB4iAjYCeCAAIAJBgIABaiID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IgRAIAEoAgwiAEUNAiAAQYjPABAoRSEDDAILIAAoAgwiBEUNAEEAIQMgBEHUzgAQKCIEBEAgAC0ACEEBcUUNAiAEIAEoAgwQsgEhAwwCCyAAKAIMIgRFDQEgBEHEzwAQKCIEBEAgAC0ACEEBcUUNAiAEIAEoAgwQWiEDDAILIAAoAgwiAEUNASAAQfTNABAoIgRFDQEgASgCDCIARQ0BIABB9M0AECgiAEUNASAFQQhqQQRyQQBBNBAfGiAFQQE2AjggBUF/NgIUIAUgBDYCECAFIAA2AgggACAFQQhqIAIoAgBBASAAKAIAKAIcEQcAIAUoAiAhAAJAIAIoAgBFDQAgAEEBRw0AIAIgBSgCGDYCAAsgAEEBRiEDDAELQQAhAwsgBUFAayQAIAMLPgACQCAAIAEgAC0ACEEYcQR/QQEFQQAhACABRQ0BIAFBpM4AECgiAUUNASABLQAIQRhxQQBHCxAiIQALIAALbQECfyAAIAEoAghBABAiBEAgASACIAMQQw8LIAAoAgwhBCAAQRBqIgUgASACIAMQWwJAIARBAkgNACAFIARBA3RqIQQgAEEYaiEAA0AgACABIAIgAxBbIABBCGoiACAETw0BIAEtADZFDQALCwsxACAAIAEoAghBABAiBEAgASACIAMQQw8LIAAoAggiACABIAIgAyAAKAIAKAIcEQcAC64BAQJ/IwBBgAJrIgMkAAJAIAEgAigCACACIAItAAsiAUEYdEEYdUEASCIEGyACKAIEIAEgBBsgAxCeASICQQFOBEACQCACQQtPBEAgAkEQakFwcSIEEB4hASAAIARBgICAgHhyNgIIIAAgATYCACAAIAI2AgQMAQsgACACOgALIAAhAQsgASADIAIQISACakEAOgAADAELIABCADcCACAAQQA2AggLIANBgAJqJAALGAAgACABKAIIQQAQIgRAIAEgAiADEEMLC6ABAQF/IwBBQGoiAyQAAn9BASAAIAFBABAiDQAaQQAgAUUNABpBACABQfTNABAoIgFFDQAaIANBCGpBBHJBAEE0EB8aIANBATYCOCADQX82AhQgAyAANgIQIAMgATYCCCABIANBCGogAigCAEEBIAEoAgAoAhwRBwAgAygCICIAQQFGBEAgAiADKAIYNgIACyAAQQFGCyEAIANBQGskACAAC00BAn8gAS0AACECAkAg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QU1QTEVfRk9STUFUX1VOREVGSU5FRABHR1dBVkVfU0FNUExFX0ZPUk1BVF9VOABHR1dBVkVfU0FNUExFX0ZPUk1BVF9JOABHR1dBVkVfU0FNUExFX0ZPUk1BVF9VMTYAR0dXQVZFX1NBTVBMRV9GT1JNQVRfSTE2AEdHV0FWRV9TQU1QTEVfRk9STUFUX0YzMgBUeFByb3RvY29sSWQAR0dXQVZFX1RYX1BST1RPQ09MX0FVRElCTEVfTk9STUFMAEdHV0FWRV9UWF9QUk9UT0NPTF9BVURJQkxFX0ZBU1QAR0dXQVZFX1RYX1BST1RPQ09MX0FVRElCTEVfRkFTVEVTVABHR1dBVkVfVFhfUFJPVE9DT0xfVUxUUkFTT1VORF9OT1JNQUwAR0dXQVZFX1RYX1BST1RPQ09MX1VMVFJBU09VTkRfRkFTVABHR1dBVkVfVFhfUFJPVE9DT0xfVUxUUkFTT1VORF9GQVNURVNUAEdHV0FWRV9UWF9QUk9UT0NPTF9EVF9OT1JNQUwAR0dXQVZFX1RYX1BST1RPQ09MX0RUX0ZBU1QAR0dXQVZFX1RYX1BST1RPQ09MX0RUX0ZBU1RFU1QAUGFyYW1ldGVycwBwYXlsb2FkTGVuZ3RoAHNhbXBsZVJhdGVJbnAAc2FtcGxlUmF0ZU91dABzYW1wbGVzUGVyRnJhbWUAc291bmRNYXJrZXJUaHJlc2hvbGQAc2FtcGxlRm9ybWF0SW5wAHNhbXBsZUZvcm1hdE91dABnZXREZWZhdWx0UGFyYW1ldGVycwBpbml0AGZyZWUAZW5jb2RlAGRlY29kZQAxOWdnd2F2ZV9TYW1wbGVGb3JtYXQAAADQKAAAhAYAADE5Z2d3YXZlX1R4UHJvdG9jb2xJZAAAANAoAACkBgAAMTdnZ3dhdmVfUGFyYW1ldGVycwAcKQAAxAYAAFAxN2dnd2F2ZV9QYXJhbWV0ZXJzAAAAAPwpAADgBgAAAAAAANgGAABQSzE3Z2d3YXZlX1BhcmFtZXRlcnMAAAD8KQAACAcAAAEAAADYBgAAaWkAdgB2aQD4BgAAaWlpAHZpaWkAZmlpAHZpaWYAAADYBgAAhCgAANgGAAAkKAAAhCgAAHZpaQBOMTBlbXNjcmlwdGVuMTFtZW1vcnlfdmlld0ljRUUAABwpAABoBwAAuAcAAIQoAAAwCAAAvAYAAIQoAABOMTBlbXNjcmlwdGVuM3ZhbEUAABwpAACkBwAATlN0M19fMjEyYmFzaWNfc3RyaW5nSWNOU18xMWNoYXJfdHJhaXRzSWNFRU5TXzlhbGxvY2F0b3JJY0VFRUUATlN0M19fMjIxX19iYXNpY19zdHJpbmdfY29tbW9uSUxiMUVFRQAAAAAcKQAA/wcAAKApAADABwAAAAAAAAEAAAAoCAAAAAAAAGlpaWlpaQAAMAgAAIQoAAAwCAAAaWlpaQBJbnZhbGlkIEdHV2F2ZSBpbnN0YW5jZSAlZAoARmFpbGVkIHRvIGluaXRpYWxpemUgR0dXYXZlIGluc3RhbmNlICVkCgBJbnZhbGlkIHBheWxvYWQgbGVnbnRoAEludmFsaWQgb3IgdW5zdXBwb3J0ZWQgY2FwdHVyZSBzYW1wbGUgZm9ybWF0AEludmFsaWQgb3IgdW5zdXBwb3J0ZWQgcGxheWJhY2sgc2FtcGxlIGZvcm1hdABJbnZhbGlkIHNhbXBsZXMgcGVyIGZyYW1lAEVycm9yOiBjYXB0dXJlIHNhbXBsZSByYXRlICglZyBIeikgbXVzdCBiZSA+PSAlZyBIegoASW52YWxpZCBjYXB0dXJlL3BsYXliYWNrIHNhbXBsZSByYXRlAEVycm9yOiBjYXB0dXJlIHNhbXBsZSByYXRlICglZyBIeikgbXVzdCBiZSA8PSAlZyBIegoATmVnYXRpdmUgZGF0YSBzaXplOiAlZAoAVHJ1bmNhdGluZyBkYXRhIGZyb20gJWQgdG8gJWQgYnl0ZXMKAEludmFsaWQgdm9sdW1lOiAlZAoARmFpbHVyZSBkdXJpbmcgY2FwdHVyZSAtIHByb3ZpZGVkIGJ5dGVzICglZCkgYXJlIG5vdCBtdWx0aXBsZSBvZiBzYW1wbGUgc2l6ZSAoJWQpCgBGYWlsdXJlIGR1cmluZyBjYXB0dXJlIC0gbW9yZSBzYW1wbGVzIHdlcmUgcHJvdmlkZWQgKCVkKSB0aGFuIHJlcXVlc3RlZCAoJWQpCgBBbmFseXppbmcgY2FwdHVyZWQgZGF0YSAuLgoARGVjb2RlZCBsZW5ndGggPSAlZCwgcHJvdG9jb2wgPSAnJXMnICglZCkKAFJlY2VpdmVkIHNvdW5kIGRhdGEgc3VjY2Vzc2Z1bGx5OiAn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cmlwdGVuOjp2YWwAZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8Y2hhcj4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8c2lnbmVkIGNoYXI+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PHVuc2lnbmVkIGNoYXI+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PHNob3J0PgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzx1bnNpZ25lZCBzaG9ydD4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8aW50PgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzx1bnNpZ25lZCBpbnQ+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PGxvbmc+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PHVuc2lnbmVkIGxvbmc+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PGludDhfdD4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8dWludDhfdD4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8aW50MTZfdD4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8dWludDE2X3Q+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PGludDMyX3Q+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PHVpbnQzMl90PgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzxmbG9hdD4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8ZG91YmxlPgBOU3QzX18yMTJiYXNpY19zdHJpbmdJaE5TXzExY2hhcl90cmFpdHNJaEVFTlNfOWFsbG9jYXRvckloRUVFRQAAAACgKQAAchQAAAAAAAABAAAAKAgAAAAAAABOU3QzX18yMTJiYXNpY19zdHJpbmdJd05TXzExY2hhcl90cmFpdHNJd0VFTlNfOWFsbG9jYXRvckl3RUVFRQAAoCkAAMwUAAAAAAAAAQAAACgIAAAAAAAATlN0M19fMjEyYmFzaWNfc3RyaW5nSURzTlNfMTFjaGFyX3RyYWl0c0lEc0VFTlNfOWFsbG9jYXRvcklEc0VFRUUAAACgKQAAJBUAAAAAAAABAAAAKAgAAAAAAABOU3QzX18yMTJiYXNpY19zdHJpbmdJRGlOU18xMWNoYXJfdHJhaXRzSURpRUVOU185YWxsb2NhdG9ySURpRUVFRQAAAKApAACAFQAAAAAAAAEAAAAoCAAAAAAAAE4xMGVtc2NyaXB0ZW4xMW1lbW9yeV92aWV3SWFFRQAAHCkAANwVAABOMTBlbXNjcmlwdGVuMTFtZW1vcnlfdmlld0loRUUAABwpAAAEFgAATjEwZW1zY3JpcHRlbjExbWVtb3J5X3ZpZXdJc0VFAAAcKQAALBYAAE4xMGVtc2NyaXB0ZW4xMW1lbW9yeV92aWV3SXRFRQAAHCkAAFQWAABOMTBlbXNjcmlwdGVuMTFtZW1vcnlfdmlld0lpRUUAABwpAAB8FgAATjEwZW1zY3JpcHRlbjExbWVtb3J5X3ZpZXdJakVFAAAcKQAApBYAAE4xMGVtc2NyaXB0ZW4xMW1lbW9yeV92aWV3SWxFRQAAHCkAAMwWAABOMTBlbXNjcmlwdGVuMTFtZW1vcnlfdmlld0ltRUUAABwpAAD0FgAATjEwZW1zY3JpcHRlbjExbWVtb3J5X3ZpZXdJZkVFAAAcKQAAHBcAAE4xMGVtc2NyaXB0ZW4xMW1lbW9yeV92aWV3SWRFRQAAHCkAAEQXAAAAAAAAAwAAAAQAAAAEAAAABgAAAIP5ogBETm4A/CkVANFXJwDdNPUAYtvAADyZlQBBkEMAY1H+ALveqwC3YcUAOm4kANJNQgBJBuAACeouAByS0QDrHf4AKbEcAOg+pwD1NYIARLsuAJzphAC0JnAAQX5fANaROQBTgzkAnPQ5AItfhAAo+b0A+B87AN7/lwAPmAUAES/vAApaiwBtH20Az342AAnLJwBGT7cAnmY/AC3qXwC6J3UA5evHAD178QD3OQcAklKKAPtr6gAfsV8ACF2NADADVgB7/EYA8KtrACC8zwA29JoA46kdAF5hkQAIG+YAhZllAKAUXwCNQGgAgNj/ACdzTQAGBjEAylYVAMmocwB74mAAa4zAABnERwDNZ8MACejcAFmDKgCLdsQAphyWAESv3QAZV9EApT4FAAUH/wAzfj8AwjLoAJhP3gC7fTIAJj3DAB5r7wCf+F4ANR86AH/yygDxhx0AfJAhAGokfADVbvoAMC13ABU7QwC1FMYAwxmdAK3EwgAsTUEADABdAIZ9RgDjcS0Am8aaADNiAAC00nwAtKeXADdV1QDXPvYAoxAYAE12/ABknSoAcNerAGN8+AB6sFcAFxXnAMBJVgA71tkAp4Q4ACQjywDWincAWlQjAAAfuQDxChsAGc7fAJ8x/wBmHmoAmVdhAKz7RwB+f9gAImW3ADLoiQDmv2AA78TNAGw2CQBdP9QAFt7XAFg73gDem5IA0iIoACiG6ADiWE0AxsoyAAjjFgDgfcsAF8BQAPMdpwAY4FsALhM0AIMSYgCDSAEA9Y5bAK2wfwAe6fIASEpDABBn0wCq3dgArl9CAGphzgAKKKQA05m0AAam8gBcd38Ao8KDAGE8iACKc3gAr4xaAG/XvQAtpmMA9L/LAI2B7wAmwWcAVcpFAMrZNgAoqNIAwmGNABLJdwAEJhQAEkabAMRZxADIxUQATbKRAAAX8wDUQ60AKUnlAP3VEAAAvvwAHpTMAHDO7gATPvUA7PGAALPnwwDH+CgAkwWUAMFxPgAuCbMAC0XzAIgSnACrIHsALrWfAEeSwgB7Mi8ADFVtAHKnkABr5x8AMcuWAHkWSgBBeeIA9N+JAOiUlwDi5oQAmTGXAIjtawBfXzYAu/0OAEiatABnpGwAcXJCAI1dMgCfFbgAvOUJAI0xJQD3dDkAMAUcAA0MAQBLCGgALO5YAEeqkAB05wIAvdYkAPd9pgBuSHIAnxbvAI6UpgC0kfYA0VNRAM8K8gAgmDMA9Ut+ALJjaADdPl8AQF0DAIWJfwBVUikAN2TAAG3YEAAySDIAW0x1AE5x1ABFVG4ACwnBACr1aQAUZtUAJwedAF0EUAC0O9sA6nbFAIf5FwBJa30AHSe6AJZpKQDGzKwArRRUAJDiagCI2YkALHJQAASkvgB3B5QA8zBwAAD8JwDqcagAZsJJAGTgPQCX3YMAoz+XAEOU/QANhowAMUHeAJI5nQDdcIwAF7fnAAjfOwAVNysAXICgAFqAkwAQEZIAD+jYAGyArwDb/0sAOJAPAFkYdgBipRUAYcu7AMeJuQAQQL0A0vIEAEl1JwDrtvYA2yK7AAoUqgCJJi8AZIN2AAk7MwAOlBoAUTqqAB2jwgCv7a4AXCYSAG3CTQAtepwAwFaXAAM/gwAJ8PYAK0CMAG0xmQA5tAcADCAVANjDWwD1ksQAxq1LAE7KpQCnN80A5qk2AKuSlADdQmgAGWPeAHaM7wBoi1IA/Ns3AK6hqwDfFTEAAK6hAAz72gBkTWYA7QW3ACllMABXVr8AR/86AGr5uQB1vvMAKJPfAKuAMABmjPYABMsVAPoiBgDZ5B0APbOkAFcbjwA2zQkATkLpABO+pAAzI7UA8KoaAE9lqADSwaUACz8PAFt4zQAj+XYAe4sEAIkXcgDGplMAb27iAO/rAACbSlgAxNq3AKpmugB2z88A0QIdALHxLQCMmcEAw613AIZI2gD3XaAAxoD0AKzwLwDd7JoAP1y8ANDebQCQxx8AKtu2AKMlOgAAr5oArVOTALZXBAApLbQAS4B+ANoHpwB2qg4Ae1mhABYSKgDcty0A+uX9AInb/gCJvv0A5HZsAAap/AA+gHAAhW4VAP2H/wAoPgcAYWczACoYhgBNveoAs+evAI9tbgCVZzkAMb9bAITXSAAw3xYAxy1DACVhNQDJcM4AMMu4AL9s/QCkAKIABWzkAFrdoAAhb0cAYhLSALlchABwYUkAa1bgAJlSAQBQVTcAHtW3ADPxxAATbl8AXTDkAIUuqQAdssMAoTI2AAi3pADqsdQAFvchAI9p5AAn/3cADAOAAI1ALQBPzaAAIKWZALOi0wAvXQoAtPlCABHaywB9vtAAm9vBAKsXvQDKooEACGpcAC5VFwAnAFUAfxTwAOEHhgAUC2QAlkGNAIe+3gDa/SoAayW2AHuJNAAF8/4Aub+eAGhqTwBKKqgAT8RaAC34vADXWpgA9MeVAA1NjQAgOqYApFdfABQ/sQCAOJUAzCABAHHdhgDJ3rYAv2D1AE1lEQABB2sAjLCsALLA0ABRVUgAHvsOAJVywwCjBjsAwEA1AAbcewDgRcwATin6ANbKyADo80EAfGTeAJtk2ADZvjEApJfDAHdY1ABp48UA8NoTALo6PABGGEYAVXVfANK99QBuksYArC5dAA5E7QAcPkIAYcSHACn96QDn1vMAInzKAG+RNQAI4MUA/9eNAG5q4gCw/cYAkwjBAHxddABrrbIAzW6dAD5yewDGEWoA98+pAClz3wC1yboAtwBRAOKyDQB0uiQA5X1gAHTYigANFSwAgRgMAH5mlAABKRYAn3p2AP39vgBWRe8A2X42AOzZEwCLurkAxJf8ADGoJwDxbsMAlMU2ANioVgC0qLUAz8wOABKJLQBvVzQALFaJAJnO4wDWILkAa16qAD4qnAARX8wA/QtKAOH0+wCOO20A4oYsAOnUhAD8tKkA7+7RAC41yQAvOWEAOCFEABvZyACB/AoA+0pqAC8c2ABTtIQATpmMAFQizAAqVdwAwMbWAAsZlgAacLgAaZVkACZaYAA/Uu4AfxEPAPS1EQD8y/UANLwtADS87gDoXcwA3V5gAGeOmwCSM+8AyRe4AGFYmwDhV7wAUYPGANg+EADdcUgALRzdAK8YoQAhLEYAWfPXANl6mACeVMAAT4b6AFYG/ADlea4AiSI2ADitIgBnk9wAVeiqAIImOADK55sAUQ2kAJkzsQCp1w4AaQVIAGWy8AB/iKcAiEyXAPnRNgAhkrMAe4JKAJjPIQBAn9wA3EdVAOF0OgBn60IA/p3fAF7UXwB7Z6QAuqx6AFX2ogAriCMAQbpVAFluCAAhKoYAOUeDAInj5gDlntQASftAAP9W6QAcD8oAxVmKAJT6KwDTwcUAD8XPANtargBHxYYAhUNiACGGOwAseZQAEGGHACpMewCALBoAQ78SAIgmkAB4PIkAqMTkAOXbewDEOsIAJvTqAPdnigANkr8AZaMrAD2TsQC9fAsApFHcACfdYwBp4d0AmpQZAKgplQBozigACe20AESfIABOmMoAcIJjAH58IwAPuTIAp/WOABRW5wAh8QgAtZ0qAG9+TQClGVEAtfmrAILf1gCW3WEAFjYCAMQ6nwCDoqEAcu1tADmNegCCuKkAazJcAEYnWwAANO0A0gB3APz0VQABWU0A4HGAAEHTxAALTUD7Ifk/AAAAAC1EdD4AAACAmEb4PAAAAGBRzHg7AAAAgIMb8DkAAABAICV6OAAAAIAiguM2AAAAAB3zaTUtKyAgIDBYMHgAKG51bGwpAEGwxQALQREACgAREREAAAAABQAAAAAAAAkAAAAACwAAAAAAAAAAEQAPChEREQMKBwABAAkLCwAACQYLAAALAAYRAAAAERERAEGBxgALIQsAAAAAAAAAABEACgoREREACgAAAgAJCwAAAAkACwAACwBBu8YACwEMAEHHxgALFQwAAAAADAAAAAAJDAAAAAAADAAADABB9cYACwEOAEGBxwALFQ0AAAAEDQAAAAAJDgAAAAAADgAADgBBr8cACwEQAEG7xwALHg8AAAAADwAAAAAJEAAAAAAAEAAAEAAAEgAAABISEgBB8scACw4SAAAAEhISAAAAAAAACQBBo8gACwELAEGvyAALFQoAAAAACgAAAAAJCwAAAAAACwAACwBB3cgACwEMAEHpyAALpAsMAAAAAAwAAAAACQwAAAAAAAwAAAwAADAxMjM0NTY3ODlBQkNERUYtMFgrMFggMFgtMHgrMHggMHgAaW5mAElORgBuYW4ATkFOAC4AAAAAECsAAHZlY3RvcgBzdGQ6OmJhZF9mdW5jdGlvbl9jYWxsAAAAAAAAAAwlAAAYAAAAMQAAADIAAABOU3QzX18yMTdiYWRfZnVuY3Rpb25fY2FsbEUARCkAAPAkAAC0JQAAYmFzaWNfc3RyaW5nAGNsb2NrX2dldHRpbWUoQ0xPQ0tfTU9OT1RPTklDKSBmYWlsZWQAX19jeGFfZ3VhcmRfYWNxdWlyZSBkZXRlY3RlZCByZWN1cnNpdmUgaW5pdGlhbGl6YXRpb24Ac3RkOjpleGNlcHRpb24AAAAAALQlAAAzAAAANAAAADUAAABTdDlleGNlcHRpb24AAAAAHCkAAKQlAAAAAAAA9CUAABcAAAA2AAAANwAAAAAAAAB8JgAAFQAAADgAAAA5AAAAU3QxMWxvZ2ljX2Vycm9yAEQpAADkJQAAtCUAAAAAAAAoJgAAFwAAADoAAAA3AAAAU3QxMmxlbmd0aF9lcnJvcgAAAABEKQAAFCYAAPQlAAAAAAAAXCYAABcAAAA7AAAANwAAAFN0MTJvdXRfb2ZfcmFuZ2UAAAAARCkAAEgmAAD0JQAAU3QxM3J1bnRpbWVfZXJyb3IAAABEKQAAaCYAALQlAABTdDl0eXBlX2luZm8AAAAAHCkAAIgmAABOMTBfX2N4eGFiaXYxMTZfX3NoaW1fdHlwZV9pbmZvRQAAAABEKQAAoCYAAJgmAABOMTBfX2N4eGFiaXYxMTdfX2NsYXNzX3R5cGVfaW5mb0UAAABEKQAA0CYAAMQmAABOMTBfX2N4eGFiaXYxMTdfX3BiYXNlX3R5cGVfaW5mb0UAAABEKQAAACcAAMQmAABOMTBfX2N4eGFiaXYxMTlfX3BvaW50ZXJfdHlwZV9pbmZvRQBEKQAAMCcAACQnAABOMTBfX2N4eGFiaXYxMjBfX2Z1bmN0aW9uX3R5cGVfaW5mb0UAAAAARCkAAGAnAADEJgAATjEwX19jeHhhYml2MTI5X19wb2ludGVyX3RvX21lbWJlcl90eXBlX2luZm9FAAAARCkAAJQnAAAkJwAAAAAAABQoAAA8AAAAPQAAAD4AAAA/AAAAQAAAAE4xMF9fY3h4YWJpdjEyM19fZnVuZGFtZW50YWxfdHlwZV9pbmZvRQBEKQAA7CcAAMQmAAB2AAAA2CcAACAoAABEbgAA2CcAACwoAABiAAAA2CcAADgoAABjAAAA2CcAAEQoAABoAAAA2CcAAFAoAABhAAAA2CcAAFwoAABzAAAA2CcAAGgoAAB0AAAA2CcAAHQoAABpAAAA2CcAAIAoAABqAAAA2CcAAIwoAABsAAAA2CcAAJgoAABtAAAA2CcAAKQoAABmAAAA2CcAALAoAABkAAAA2CcAALwoAAAAAAAACCkAADwAAABBAAAAPgAAAD8AAABCAAAATjEwX19jeHhhYml2MTE2X19lbnVtX3R5cGVfaW5mb0UAAAAARCkAAOQoAADEJgAAAAAAAPQmAAA8AAAAQwAAAD4AAAA/AAAARAAAAEUAAABGAAAARwAAAAAAAACMKQAAPAAAAEgAAAA+AAAAPwAAAEQAAABJAAAASgAAAEsAAABOMTBfX2N4eGFiaXYxMjBfX3NpX2NsYXNzX3R5cGVfaW5mb0UAAAAARCkAAGQpAAD0JgAAAAAAAOgpAAA8AAAATAAAAD4AAAA/AAAARAAAAE0AAABOAAAATwAAAE4xMF9fY3h4YWJpdjEyMV9fdm1pX2NsYXNzX3R5cGVfaW5mb0UAAABEKQAAwCkAAPQmAAAAAAAAVCcAADwAAABQAAAAPgAAAD8AAABRAEGQ1AALGf////8AgDtHAIA7RwAEAAAAAEBABQAAAAUAQdjVAAsCEGwAQZDWAAsBBQBBnNYACwEuAEG01gALCi8AAAAwAAAAMGwAQczWAAsBAgBB29YACwX//////wBBoNcACwOQblA=";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}function getBinary(file){try{if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}var binary=tryParseAsDataURI(file);if(binary){return binary}if(readBinary){return readBinary(file)}else{throw"both async and sync fetching of the wasm failed"}}catch(err){abort(err)}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)){if(typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw"failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary(wasmBinaryFile)})}else{if(readAsync){return new Promise(function(resolve,reject){readAsync(wasmBinaryFile,function(response){resolve(new Uint8Array(response))},reject)})}}}return Promise.resolve().then(function(){return getBinary(wasmBinaryFile)})}function createWasm(){var info={"a":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmMemory=Module["asm"]["E"];updateGlobalBufferAndViews(wasmMemory.buffer);wasmTable=Module["asm"]["F"];removeRunDependency("wasm-instantiate")}addRunDependency("wasm-instantiate");function receiveInstantiatedSource(output){receiveInstance(output["instance"])}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason)})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(receiveInstantiatedSource)})})}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync().catch(readyPromiseReject);return{}}function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){wasmTable.get(func)()}else{wasmTable.get(func)(callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}function _tzset(){if(_tzset.called)return;_tzset.called=true;var currentYear=(new Date).getFullYear();var winter=new Date(currentYear,0,1);var summer=new Date(currentYear,6,1);var winterOffset=winter.getTimezoneOffset();var summerOffset=summer.getTimezoneOffset();var stdTimezoneOffset=Math.max(winterOffset,summerOffset);HEAP32[__get_timezone()>>2]=stdTimezoneOffset*60;HEAP32[__get_daylight()>>2]=Number(winterOffset!=summerOffset);function extractZone(date){var match=date.toTimeString().match(/\(([A-Za-z ]+)\)$/);return match?match[1]:"GMT"}var winterName=extractZone(winter);var summerName=extractZone(summer);var winterNamePtr=allocateUTF8(winterName);var summerNamePtr=allocateUTF8(summerName);if(summerOffset>2]=winterNamePtr;HEAP32[__get_tzname()+4>>2]=summerNamePtr}else{HEAP32[__get_tzname()>>2]=summerNamePtr;HEAP32[__get_tzname()+4>>2]=winterNamePtr}}function _asctime_r(tmPtr,buf){var date={tm_sec:HEAP32[tmPtr>>2],tm_min:HEAP32[tmPtr+4>>2],tm_hour:HEAP32[tmPtr+8>>2],tm_mday:HEAP32[tmPtr+12>>2],tm_mon:HEAP32[tmPtr+16>>2],tm_year:HEAP32[tmPtr+20>>2],tm_wday:HEAP32[tmPtr+24>>2]};var days=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"];var months=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];var s=days[date.tm_wday]+" "+months[date.tm_mon]+(date.tm_mday<10?" ":" ")+date.tm_mday+(date.tm_hour<10?" 0":" ")+date.tm_hour+(date.tm_min<10?":0":":")+date.tm_min+(date.tm_sec<10?":0":":")+date.tm_sec+" "+(1900+date.tm_year)+"\n";stringToUTF8(s,buf,26);return buf}function ___asctime_r(a0,a1){return _asctime_r(a0,a1)}var ExceptionInfoAttrs={DESTRUCTOR_OFFSET:0,REFCOUNT_OFFSET:4,TYPE_OFFSET:8,CAUGHT_OFFSET:12,RETHROWN_OFFSET:13,SIZE:16};function ___cxa_allocate_exception(size){return _malloc(size+ExceptionInfoAttrs.SIZE)+ExceptionInfoAttrs.SIZE}function ExceptionInfo(excPtr){this.excPtr=excPtr;this.ptr=excPtr-ExceptionInfoAttrs.SIZE;this.set_type=function(type){HEAP32[this.ptr+ExceptionInfoAttrs.TYPE_OFFSET>>2]=type};this.get_type=function(){return HEAP32[this.ptr+ExceptionInfoAttrs.TYPE_OFFSET>>2]};this.set_destructor=function(destructor){HEAP32[this.ptr+ExceptionInfoAttrs.DESTRUCTOR_OFFSET>>2]=destructor};this.get_destructor=function(){return HEAP32[this.ptr+ExceptionInfoAttrs.DESTRUCTOR_OFFSET>>2]};this.set_refcount=function(refcount){HEAP32[this.ptr+ExceptionInfoAttrs.REFCOUNT_OFFSET>>2]=refcount};this.set_caught=function(caught){caught=caught?1:0;HEAP8[this.ptr+ExceptionInfoAttrs.CAUGHT_OFFSET>>0]=caught};this.get_caught=function(){return HEAP8[this.ptr+ExceptionInfoAttrs.CAUGHT_OFFSET>>0]!=0};this.set_rethrown=function(rethrown){rethrown=rethrown?1:0;HEAP8[this.ptr+ExceptionInfoAttrs.RETHROWN_OFFSET>>0]=rethrown};this.get_rethrown=function(){return HEAP8[this.ptr+ExceptionInfoAttrs.RETHROWN_OFFSET>>0]!=0};this.init=function(type,destructor){this.set_type(type);this.set_destructor(destructor);this.set_refcount(0);this.set_caught(false);this.set_rethrown(false)};this.add_ref=function(){var value=HEAP32[this.ptr+ExceptionInfoAttrs.REFCOUNT_OFFSET>>2];HEAP32[this.ptr+ExceptionInfoAttrs.REFCOUNT_OFFSET>>2]=value+1};this.release_ref=function(){var prev=HEAP32[this.ptr+ExceptionInfoAttrs.REFCOUNT_OFFSET>>2];HEAP32[this.ptr+ExceptionInfoAttrs.REFCOUNT_OFFSET>>2]=prev-1;return prev===1}}var exceptionLast=0;var uncaughtExceptionCount=0;function ___cxa_throw(ptr,type,destructor){var info=new ExceptionInfo(ptr);info.init(type,destructor);exceptionLast=ptr;uncaughtExceptionCount++;throw ptr}function _localtime_r(time,tmPtr){_tzset();var date=new Date(HEAP32[time>>2]*1e3);HEAP32[tmPtr>>2]=date.getSeconds();HEAP32[tmPtr+4>>2]=date.getMinutes();HEAP32[tmPtr+8>>2]=date.getHours();HEAP32[tmPtr+12>>2]=date.getDate();HEAP32[tmPtr+16>>2]=date.getMonth();HEAP32[tmPtr+20>>2]=date.getFullYear()-1900;HEAP32[tmPtr+24>>2]=date.getDay();var start=new Date(date.getFullYear(),0,1);var yday=(date.getTime()-start.getTime())/(1e3*60*60*24)|0;HEAP32[tmPtr+28>>2]=yday;HEAP32[tmPtr+36>>2]=-(date.getTimezoneOffset()*60);var summerOffset=new Date(date.getFullYear(),6,1).getTimezoneOffset();var winterOffset=start.getTimezoneOffset();var dst=(summerOffset!=winterOffset&&date.getTimezoneOffset()==Math.min(winterOffset,summerOffset))|0;HEAP32[tmPtr+32>>2]=dst;var zonePtr=HEAP32[__get_tzname()+(dst?4:0)>>2];HEAP32[tmPtr+40>>2]=zonePtr;return tmPtr}function ___localtime_r(a0,a1){return _localtime_r(a0,a1)}function getShiftFromSize(size){switch(size){case 1:return 0;case 2:return 1;case 4:return 2;case 8:return 3;default:throw new TypeError("Unknown type size: "+size)}}function embind_init_charCodes(){var codes=new Array(256);for(var i=0;i<256;++i){codes[i]=String.fromCharCode(i)}embind_charCodes=codes}var embind_charCodes=undefined;function readLatin1String(ptr){var ret="";var c=ptr;while(HEAPU8[c]){ret+=embind_charCodes[HEAPU8[c++]]}return ret}var awaitingDependencies={};var registeredTypes={};var typeDependencies={};var char_0=48;var char_9=57;function makeLegalFunctionName(name){if(undefined===name){return"_unknown"}name=name.replace(/[^a-zA-Z0-9_]/g,"$");var f=name.charCodeAt(0);if(f>=char_0&&f<=char_9){return"_"+name}else{return name}}function createNamedFunction(name,body){name=makeLegalFunctionName(name);return new Function("body","return function "+name+"() {\n"+' "use strict";'+" return body.apply(this, arguments);\n"+"};\n")(body)}function extendError(baseErrorType,errorName){var errorClass=createNamedFunction(errorName,function(message){this.name=errorName;this.message=message;var stack=new Error(message).stack;if(stack!==undefined){this.stack=this.toString()+"\n"+stack.replace(/^Error(:[^\n]*)?\n/,"")}});errorClass.prototype=Object.create(baseErrorType.prototype);errorClass.prototype.constructor=errorClass;errorClass.prototype.toString=function(){if(this.message===undefined){return this.name}else{return this.name+": "+this.message}};return errorClass}var BindingError=undefined;function throwBindingError(message){throw new BindingError(message)}var InternalError=undefined;function throwInternalError(message){throw new InternalError(message)}function whenDependentTypesAreResolved(myTypes,dependentTypes,getTypeConverters){myTypes.forEach(function(type){typeDependencies[type]=dependentTypes});function onComplete(typeConverters){var myTypeConverters=getTypeConverters(typeConverters);if(myTypeConverters.length!==myTypes.length){throwInternalError("Mismatched type converter count")}for(var i=0;i>shift])},destructorFunction:null})}function ClassHandle_isAliasOf(other){if(!(this instanceof ClassHandle)){return false}if(!(other instanceof ClassHandle)){return false}var leftClass=this.$$.ptrType.registeredClass;var left=this.$$.ptr;var rightClass=other.$$.ptrType.registeredClass;var right=other.$$.ptr;while(leftClass.baseClass){left=leftClass.upcast(left);leftClass=leftClass.baseClass}while(rightClass.baseClass){right=rightClass.upcast(right);rightClass=rightClass.baseClass}return leftClass===rightClass&&left===right}function shallowCopyInternalPointer(o){return{count:o.count,deleteScheduled:o.deleteScheduled,preservePointerOnDelete:o.preservePointerOnDelete,ptr:o.ptr,ptrType:o.ptrType,smartPtr:o.smartPtr,smartPtrType:o.smartPtrType}}function throwInstanceAlreadyDeleted(obj){function getInstanceTypeName(handle){return handle.$$.ptrType.registeredClass.name}throwBindingError(getInstanceTypeName(obj)+" instance already deleted")}var finalizationGroup=false;function detachFinalizer(handle){}function runDestructor($$){if($$.smartPtr){$$.smartPtrType.rawDestructor($$.smartPtr)}else{$$.ptrType.registeredClass.rawDestructor($$.ptr)}}function releaseClassHandle($$){$$.count.value-=1;var toDelete=0===$$.count.value;if(toDelete){runDestructor($$)}}function attachFinalizer(handle){if("undefined"===typeof FinalizationGroup){attachFinalizer=function(handle){return handle};return handle}finalizationGroup=new FinalizationGroup(function(iter){for(var result=iter.next();!result.done;result=iter.next()){var $$=result.value;if(!$$.ptr){console.warn("object already deleted: "+$$.ptr)}else{releaseClassHandle($$)}}});attachFinalizer=function(handle){finalizationGroup.register(handle,handle.$$,handle.$$);return handle};detachFinalizer=function(handle){finalizationGroup.unregister(handle.$$)};return attachFinalizer(handle)}function ClassHandle_clone(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.preservePointerOnDelete){this.$$.count.value+=1;return this}else{var clone=attachFinalizer(Object.create(Object.getPrototypeOf(this),{$$:{value:shallowCopyInternalPointer(this.$$)}}));clone.$$.count.value+=1;clone.$$.deleteScheduled=false;return clone}}function ClassHandle_delete(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}detachFinalizer(this);releaseClassHandle(this.$$);if(!this.$$.preservePointerOnDelete){this.$$.smartPtr=undefined;this.$$.ptr=undefined}}function ClassHandle_isDeleted(){return!this.$$.ptr}var delayFunction=undefined;var deletionQueue=[];function flushPendingDeletes(){while(deletionQueue.length){var obj=deletionQueue.pop();obj.$$.deleteScheduled=false;obj["delete"]()}}function ClassHandle_deleteLater(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}deletionQueue.push(this);if(deletionQueue.length===1&&delayFunction){delayFunction(flushPendingDeletes)}this.$$.deleteScheduled=true;return this}function init_ClassHandle(){ClassHandle.prototype["isAliasOf"]=ClassHandle_isAliasOf;ClassHandle.prototype["clone"]=ClassHandle_clone;ClassHandle.prototype["delete"]=ClassHandle_delete;ClassHandle.prototype["isDeleted"]=ClassHandle_isDeleted;ClassHandle.prototype["deleteLater"]=ClassHandle_deleteLater}function ClassHandle(){}var registeredPointers={};function ensureOverloadTable(proto,methodName,humanName){if(undefined===proto[methodName].overloadTable){var prevFunc=proto[methodName];proto[methodName]=function(){if(!proto[methodName].overloadTable.hasOwnProperty(arguments.length)){throwBindingError("Function '"+humanName+"' called with an invalid number of arguments ("+arguments.length+") - expects one of ("+proto[methodName].overloadTable+")!")}return proto[methodName].overloadTable[arguments.length].apply(this,arguments)};proto[methodName].overloadTable=[];proto[methodName].overloadTable[prevFunc.argCount]=prevFunc}}function exposePublicSymbol(name,value,numArguments){if(Module.hasOwnProperty(name)){if(undefined===numArguments||undefined!==Module[name].overloadTable&&undefined!==Module[name].overloadTable[numArguments]){throwBindingError("Cannot register public name '"+name+"' twice")}ensureOverloadTable(Module,name,name);if(Module.hasOwnProperty(numArguments)){throwBindingError("Cannot register multiple overloads of a function with the same number of arguments ("+numArguments+")!")}Module[name].overloadTable[numArguments]=value}else{Module[name]=value;if(undefined!==numArguments){Module[name].numArguments=numArguments}}}function RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast){this.name=name;this.constructor=constructor;this.instancePrototype=instancePrototype;this.rawDestructor=rawDestructor;this.baseClass=baseClass;this.getActualType=getActualType;this.upcast=upcast;this.downcast=downcast;this.pureVirtualFunctions=[]}function upcastPointer(ptr,ptrClass,desiredClass){while(ptrClass!==desiredClass){if(!ptrClass.upcast){throwBindingError("Expected null or instance of "+desiredClass.name+", got an instance of "+ptrClass.name)}ptr=ptrClass.upcast(ptr);ptrClass=ptrClass.baseClass}return ptr}function constNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError("null is not a valid "+this.name)}return 0}if(!handle.$$){throwBindingError('Cannot pass "'+_embind_repr(handle)+'" as a '+this.name)}if(!handle.$$.ptr){throwBindingError("Cannot pass deleted object as a pointer of type "+this.name)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}function genericPointerToWireType(destructors,handle){var ptr;if(handle===null){if(this.isReference){throwBindingError("null is not a valid "+this.name)}if(this.isSmartPointer){ptr=this.rawConstructor();if(destructors!==null){destructors.push(this.rawDestructor,ptr)}return ptr}else{return 0}}if(!handle.$$){throwBindingError('Cannot pass "'+_embind_repr(handle)+'" as a '+this.name)}if(!handle.$$.ptr){throwBindingError("Cannot pass deleted object as a pointer of type "+this.name)}if(!this.isConst&&handle.$$.ptrType.isConst){throwBindingError("Cannot convert argument of type "+(handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name)+" to parameter type "+this.name)}var handleClass=handle.$$.ptrType.registeredClass;ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);if(this.isSmartPointer){if(undefined===handle.$$.smartPtr){throwBindingError("Passing raw pointer to smart pointer is illegal")}switch(this.sharingPolicy){case 0:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{throwBindingError("Cannot convert argument of type "+(handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name)+" to parameter type "+this.name)}break;case 1:ptr=handle.$$.smartPtr;break;case 2:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{var clonedHandle=handle["clone"]();ptr=this.rawShare(ptr,__emval_register(function(){clonedHandle["delete"]()}));if(destructors!==null){destructors.push(this.rawDestructor,ptr)}}break;default:throwBindingError("Unsupporting sharing policy")}}return ptr}function nonConstNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError("null is not a valid "+this.name)}return 0}if(!handle.$$){throwBindingError('Cannot pass "'+_embind_repr(handle)+'" as a '+this.name)}if(!handle.$$.ptr){throwBindingError("Cannot pass deleted object as a pointer of type "+this.name)}if(handle.$$.ptrType.isConst){throwBindingError("Cannot convert argument of type "+handle.$$.ptrType.name+" to parameter type "+this.name)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}function simpleReadValueFromPointer(pointer){return this["fromWireType"](HEAPU32[pointer>>2])}function RegisteredPointer_getPointee(ptr){if(this.rawGetPointee){ptr=this.rawGetPointee(ptr)}return ptr}function RegisteredPointer_destructor(ptr){if(this.rawDestructor){this.rawDestructor(ptr)}}function RegisteredPointer_deleteObject(handle){if(handle!==null){handle["delete"]()}}function downcastPointer(ptr,ptrClass,desiredClass){if(ptrClass===desiredClass){return ptr}if(undefined===desiredClass.baseClass){return null}var rv=downcastPointer(ptr,ptrClass,desiredClass.baseClass);if(rv===null){return null}return desiredClass.downcast(rv)}function getInheritedInstanceCount(){return Object.keys(registeredInstances).length}function getLiveInheritedInstances(){var rv=[];for(var k in registeredInstances){if(registeredInstances.hasOwnProperty(k)){rv.push(registeredInstances[k])}}return rv}function setDelayFunction(fn){delayFunction=fn;if(deletionQueue.length&&delayFunction){delayFunction(flushPendingDeletes)}}function init_embind(){Module["getInheritedInstanceCount"]=getInheritedInstanceCount;Module["getLiveInheritedInstances"]=getLiveInheritedInstances;Module["flushPendingDeletes"]=flushPendingDeletes;Module["setDelayFunction"]=setDelayFunction}var registeredInstances={};function getBasestPointer(class_,ptr){if(ptr===undefined){throwBindingError("ptr should not be undefined")}while(class_.baseClass){ptr=class_.upcast(ptr);class_=class_.baseClass}return ptr}function getInheritedInstance(class_,ptr){ptr=getBasestPointer(class_,ptr);return registeredInstances[ptr]}function makeClassHandle(prototype,record){if(!record.ptrType||!record.ptr){throwInternalError("makeClassHandle requires ptr and ptrType")}var hasSmartPtrType=!!record.smartPtrType;var hasSmartPtr=!!record.smartPtr;if(hasSmartPtrType!==hasSmartPtr){throwInternalError("Both smartPtrType and smartPtr must be specified")}record.count={value:1};return attachFinalizer(Object.create(prototype,{$$:{value:record}}))}function RegisteredPointer_fromWireType(ptr){var rawPointer=this.getPointee(ptr);if(!rawPointer){this.destructor(ptr);return null}var registeredInstance=getInheritedInstance(this.registeredClass,rawPointer);if(undefined!==registeredInstance){if(0===registeredInstance.$$.count.value){registeredInstance.$$.ptr=rawPointer;registeredInstance.$$.smartPtr=ptr;return registeredInstance["clone"]()}else{var rv=registeredInstance["clone"]();this.destructor(ptr);return rv}}function makeDefaultHandle(){if(this.isSmartPointer){return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this.pointeeType,ptr:rawPointer,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this,ptr:ptr})}}var actualType=this.registeredClass.getActualType(rawPointer);var registeredPointerRecord=registeredPointers[actualType];if(!registeredPointerRecord){return makeDefaultHandle.call(this)}var toType;if(this.isConst){toType=registeredPointerRecord.constPointerType}else{toType=registeredPointerRecord.pointerType}var dp=downcastPointer(rawPointer,this.registeredClass,toType.registeredClass);if(dp===null){return makeDefaultHandle.call(this)}if(this.isSmartPointer){return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp})}}function init_RegisteredPointer(){RegisteredPointer.prototype.getPointee=RegisteredPointer_getPointee;RegisteredPointer.prototype.destructor=RegisteredPointer_destructor;RegisteredPointer.prototype["argPackAdvance"]=8;RegisteredPointer.prototype["readValueFromPointer"]=simpleReadValueFromPointer;RegisteredPointer.prototype["deleteObject"]=RegisteredPointer_deleteObject;RegisteredPointer.prototype["fromWireType"]=RegisteredPointer_fromWireType}function RegisteredPointer(name,registeredClass,isReference,isConst,isSmartPointer,pointeeType,sharingPolicy,rawGetPointee,rawConstructor,rawShare,rawDestructor){this.name=name;this.registeredClass=registeredClass;this.isReference=isReference;this.isConst=isConst;this.isSmartPointer=isSmartPointer;this.pointeeType=pointeeType;this.sharingPolicy=sharingPolicy;this.rawGetPointee=rawGetPointee;this.rawConstructor=rawConstructor;this.rawShare=rawShare;this.rawDestructor=rawDestructor;if(!isSmartPointer&®isteredClass.baseClass===undefined){if(isConst){this["toWireType"]=constNoSmartPtrRawPointerToWireType;this.destructorFunction=null}else{this["toWireType"]=nonConstNoSmartPtrRawPointerToWireType;this.destructorFunction=null}}else{this["toWireType"]=genericPointerToWireType}}function replacePublicSymbol(name,value,numArguments){if(!Module.hasOwnProperty(name)){throwInternalError("Replacing nonexistant public symbol")}if(undefined!==Module[name].overloadTable&&undefined!==numArguments){Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}}function dynCallLegacy(sig,ptr,args){if(args&&args.length){return Module["dynCall_"+sig].apply(null,[ptr].concat(args))}return Module["dynCall_"+sig].call(null,ptr)}function dynCall(sig,ptr,args){if(sig.indexOf("j")!=-1){return dynCallLegacy(sig,ptr,args)}return wasmTable.get(ptr).apply(null,args)}function getDynCaller(sig,ptr){assert(sig.indexOf("j")>=0,"getDynCaller should only be called with i64 sigs");var argCache=[];return function(){argCache.length=arguments.length;for(var i=0;i>2)+i])}return array}function runDestructors(destructors){while(destructors.length){var ptr=destructors.pop();var del=destructors.pop();del(ptr)}}function __embind_register_class_constructor(rawClassType,argCount,rawArgTypesAddr,invokerSignature,invoker,rawConstructor){assert(argCount>0);var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);invoker=embind__requireFunction(invokerSignature,invoker);var args=[rawConstructor];var destructors=[];whenDependentTypesAreResolved([],[rawClassType],function(classType){classType=classType[0];var humanName="constructor "+classType.name;if(undefined===classType.registeredClass.constructor_body){classType.registeredClass.constructor_body=[]}if(undefined!==classType.registeredClass.constructor_body[argCount-1]){throw new BindingError("Cannot register multiple constructors with identical number of parameters ("+(argCount-1)+") for class '"+classType.name+"'! Overload resolution is currently only performed using the parameter count, not actual type info!")}classType.registeredClass.constructor_body[argCount-1]=function unboundTypeHandler(){throwUnboundTypeError("Cannot construct "+classType.name+" due to unbound types",rawArgTypes)};whenDependentTypesAreResolved([],rawArgTypes,function(argTypes){classType.registeredClass.constructor_body[argCount-1]=function constructor_body(){if(arguments.length!==argCount-1){throwBindingError(humanName+" called with "+arguments.length+" arguments, expected "+(argCount-1))}destructors.length=0;args.length=argCount;for(var i=1;i4&&0===--emval_handle_array[handle].refcount){emval_handle_array[handle]=undefined;emval_free_list.push(handle)}}function count_emval_handles(){var count=0;for(var i=5;i>1])};case 2:return function(pointer){var heap=signed?HEAP32:HEAPU32;return this["fromWireType"](heap[pointer>>2])};default:throw new TypeError("Unknown integer type: "+name)}}function __embind_register_enum(rawType,name,size,isSigned){var shift=getShiftFromSize(size);name=readLatin1String(name);function ctor(){}ctor.values={};registerType(rawType,{name:name,constructor:ctor,"fromWireType":function(c){return this.constructor.values[c]},"toWireType":function(destructors,c){return c.value},"argPackAdvance":8,"readValueFromPointer":enumReadValueFromPointer(name,shift,isSigned),destructorFunction:null});exposePublicSymbol(name,ctor)}function requireRegisteredType(rawType,humanName){var impl=registeredTypes[rawType];if(undefined===impl){throwBindingError(humanName+" has unknown type "+getTypeName(rawType))}return impl}function __embind_register_enum_value(rawEnumType,name,enumValue){var enumType=requireRegisteredType(rawEnumType,"enum");name=readLatin1String(name);var Enum=enumType.constructor;var Value=Object.create(enumType.constructor.prototype,{value:{value:enumValue},constructor:{value:createNamedFunction(enumType.name+"_"+name,function(){})}});Enum.values[enumValue]=Value;Enum[name]=Value}function _embind_repr(v){if(v===null){return"null"}var t=typeof v;if(t==="object"||t==="array"||t==="function"){return v.toString()}else{return""+v}}function floatReadValueFromPointer(name,shift){switch(shift){case 2:return function(pointer){return this["fromWireType"](HEAPF32[pointer>>2])};case 3:return function(pointer){return this["fromWireType"](HEAPF64[pointer>>3])};default:throw new TypeError("Unknown float type: "+name)}}function __embind_register_float(rawType,name,size){var shift=getShiftFromSize(size);name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":function(value){return value},"toWireType":function(destructors,value){if(typeof value!=="number"&&typeof value!=="boolean"){throw new TypeError('Cannot convert "'+_embind_repr(value)+'" to '+this.name)}return value},"argPackAdvance":8,"readValueFromPointer":floatReadValueFromPointer(name,shift),destructorFunction:null})}function new_(constructor,argumentList){if(!(constructor instanceof Function)){throw new TypeError("new_ called with constructor type "+typeof constructor+" which is not a function")}var dummy=createNamedFunction(constructor.name||"unknownFunctionName",function(){});dummy.prototype=constructor.prototype;var obj=new dummy;var r=constructor.apply(obj,argumentList);return r instanceof Object?r:obj}function craftInvokerFunction(humanName,argTypes,classType,cppInvokerFunc,cppTargetFunc){var argCount=argTypes.length;if(argCount<2){throwBindingError("argTypes array size mismatch! Must at least get return value and 'this' types!")}var isClassMethodFunc=argTypes[1]!==null&&classType!==null;var needsDestructorStack=false;for(var i=1;i0?", ":"")+argsListWired}invokerFnBody+=(returns?"var rv = ":"")+"invoker(fn"+(argsListWired.length>0?", ":"")+argsListWired+");\n";if(needsDestructorStack){invokerFnBody+="runDestructors(destructors);\n"}else{for(var i=isClassMethodFunc?1:2;i>1]}:function readU16FromPointer(pointer){return HEAPU16[pointer>>1]};case 2:return signed?function readS32FromPointer(pointer){return HEAP32[pointer>>2]}:function readU32FromPointer(pointer){return HEAPU32[pointer>>2]};default:throw new TypeError("Unknown integer type: "+name)}}function __embind_register_integer(primitiveType,name,size,minRange,maxRange){name=readLatin1String(name);if(maxRange===-1){maxRange=4294967295}var shift=getShiftFromSize(size);var fromWireType=function(value){return value};if(minRange===0){var bitshift=32-8*size;fromWireType=function(value){return value<>>bitshift}}var isUnsignedType=name.indexOf("unsigned")!=-1;registerType(primitiveType,{name:name,"fromWireType":fromWireType,"toWireType":function(destructors,value){if(typeof value!=="number"&&typeof value!=="boolean"){throw new TypeError('Cannot convert "'+_embind_repr(value)+'" to '+this.name)}if(valuemaxRange){throw new TypeError('Passing a number "'+_embind_repr(value)+'" from JS side to C/C++ side to an argument of type "'+name+'", which is outside the valid range ['+minRange+", "+maxRange+"]!")}return isUnsignedType?value>>>0:value|0},"argPackAdvance":8,"readValueFromPointer":integerReadValueFromPointer(name,shift,minRange!==0),destructorFunction:null})}function __embind_register_memory_view(rawType,dataTypeIndex,name){var typeMapping=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array];var TA=typeMapping[dataTypeIndex];function decodeMemoryView(handle){handle=handle>>2;var heap=HEAPU32;var size=heap[handle];var data=heap[handle+1];return new TA(buffer,data,size)}name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":decodeMemoryView,"argPackAdvance":8,"readValueFromPointer":decodeMemoryView},{ignoreDuplicateRegistrations:true})}function __embind_register_std_string(rawType,name){name=readLatin1String(name);var stdStringIsUTF8=name==="std::string";registerType(rawType,{name:name,"fromWireType":function(value){var length=HEAPU32[value>>2];var str;if(stdStringIsUTF8){var decodeStartPtr=value+4;for(var i=0;i<=length;++i){var currentBytePtr=value+4+i;if(i==length||HEAPU8[currentBytePtr]==0){var maxRead=currentBytePtr-decodeStartPtr;var stringSegment=UTF8ToString(decodeStartPtr,maxRead);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+1}}}else{var a=new Array(length);for(var i=0;i>2]=length;if(stdStringIsUTF8&&valueIsOfTypeString){stringToUTF8(value,ptr+4,length+1)}else{if(valueIsOfTypeString){for(var i=0;i255){_free(ptr);throwBindingError("String has UTF-16 code units that do not fit in 8 bits")}HEAPU8[ptr+4+i]=charCode}}else{for(var i=0;i>2];var HEAP=getHeap();var str;var decodeStartPtr=value+4;for(var i=0;i<=length;++i){var currentBytePtr=value+4+i*charSize;if(i==length||HEAP[currentBytePtr>>shift]==0){var maxReadBytes=currentBytePtr-decodeStartPtr;var stringSegment=decodeString(decodeStartPtr,maxReadBytes);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+charSize}}_free(value);return str},"toWireType":function(destructors,value){if(!(typeof value==="string")){throwBindingError("Cannot pass non-string to C++ string type "+name)}var length=lengthBytesUTF(value);var ptr=_malloc(4+length+charSize);HEAPU32[ptr>>2]=length>>shift;encodeString(value,ptr+4,length+charSize);if(destructors!==null){destructors.push(_free,ptr)}return ptr},"argPackAdvance":8,"readValueFromPointer":simpleReadValueFromPointer,destructorFunction:function(ptr){_free(ptr)}})}function __embind_register_void(rawType,name){name=readLatin1String(name);registerType(rawType,{isVoid:true,name:name,"argPackAdvance":0,"fromWireType":function(){return undefined},"toWireType":function(destructors,o){return undefined}})}function __emval_incref(handle){if(handle>4){emval_handle_array[handle].refcount+=1}}function __emval_take_value(type,argv){type=requireRegisteredType(type,"_emval_take_value");var v=type["readValueFromPointer"](argv);return __emval_register(v)}function _abort(){abort()}var _emscripten_get_now;if(ENVIRONMENT_IS_NODE){_emscripten_get_now=function(){var t=process["hrtime"]();return t[0]*1e3+t[1]/1e6}}else if(typeof dateNow!=="undefined"){_emscripten_get_now=dateNow}else _emscripten_get_now=function(){return performance.now()};var _emscripten_get_now_is_monotonic=true;function setErrNo(value){HEAP32[___errno_location()>>2]=value;return value}function _clock_gettime(clk_id,tp){var now;if(clk_id===0){now=Date.now()}else if((clk_id===1||clk_id===4)&&_emscripten_get_now_is_monotonic){now=_emscripten_get_now()}else{setErrNo(28);return-1}HEAP32[tp>>2]=now/1e3|0;HEAP32[tp+4>>2]=now%1e3*1e3*1e3|0;return 0}function _emscripten_memcpy_big(dest,src,num){HEAPU8.copyWithin(dest,src,src+num)}function _emscripten_get_heap_size(){return HEAPU8.length}function emscripten_realloc_buffer(size){try{wasmMemory.grow(size-buffer.byteLength+65535>>>16);updateGlobalBufferAndViews(wasmMemory.buffer);return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){requestedSize=requestedSize>>>0;var oldSize=_emscripten_get_heap_size();var maxHeapSize=2147483648;if(requestedSize>maxHeapSize){return false}var minHeapSize=16777216;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(minHeapSize,requestedSize,overGrownHeapSize),65536));var replacement=emscripten_realloc_buffer(newSize);if(replacement){return true}}return false}var SYSCALLS={mappings:{},buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0}else{buffer.push(curr)}},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){return low}};function _fd_close(fd){return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){}function _fd_write(fd,iov,iovcnt,pnum){var num=0;for(var i=0;i>2];var len=HEAP32[iov+(i*8+4)>>2];for(var j=0;j>2]=num;return 0}function _setTempRet0($i){setTempRet0($i|0)}function _time(ptr){var ret=Date.now()/1e3|0;if(ptr){HEAP32[ptr>>2]=ret}return ret}embind_init_charCodes();BindingError=Module["BindingError"]=extendError(Error,"BindingError");InternalError=Module["InternalError"]=extendError(Error,"InternalError");init_ClassHandle();init_RegisteredPointer();init_embind();UnboundTypeError=Module["UnboundTypeError"]=extendError(Error,"UnboundTypeError");init_emval();var ASSERTIONS=false;function intArrayToString(array){var ret=[];for(var i=0;i255){if(ASSERTIONS){assert(false,"Character code "+chr+" ("+String.fromCharCode(chr)+") at offset "+i+" not in 0x00-0xFF.")}chr&=255}ret.push(String.fromCharCode(chr))}return ret.join("")}var decodeBase64=typeof atob==="function"?atob:function(input){var keyStr="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";var output="";var chr1,chr2,chr3;var enc1,enc2,enc3,enc4;var i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,"");do{enc1=keyStr.indexOf(input.charAt(i++));enc2=keyStr.indexOf(input.charAt(i++));enc3=keyStr.indexOf(input.charAt(i++));enc4=keyStr.indexOf(input.charAt(i++));chr1=enc1<<2|enc2>>4;chr2=(enc2&15)<<4|enc3>>2;chr3=(enc3&3)<<6|enc4;output=output+String.fromCharCode(chr1);if(enc3!==64){output=output+String.fromCharCode(chr2)}if(enc4!==64){output=output+String.fromCharCode(chr3)}}while(i0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();readyPromiseResolve(Module);if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}Module["run"]=run;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}noExitRuntime=true;run(); +var Module=typeof ggwave_factory!=="undefined"?ggwave_factory:{};var readyPromiseResolve,readyPromiseReject;Module["ready"]=new Promise(function(resolve,reject){readyPromiseResolve=resolve;readyPromiseReject=reject});var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=require("path").dirname(scriptDirectory)+"/"}else{scriptDirectory=__dirname+"/"}read_=function shell_read(filename,binary){var ret=tryParseAsDataURI(filename);if(ret){return binary?ret:ret.toString()}if(!nodeFS)nodeFS=require("fs");if(!nodePath)nodePath=require("path");filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/")}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status)};Module["inspect"]=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){var data=tryParseAsDataURI(f);if(data){return intArrayToString(data)}return read(f)}}readBinary=function readBinary(f){var data;data=tryParseAsDataURI(f);if(data){return data}if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs}else if(typeof arguments!="undefined"){arguments_=arguments}if(typeof quit==="function"){quit_=function(status){quit(status)}}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!=="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(_scriptDir){scriptDirectory=_scriptDir}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1)}else{scriptDirectory=""}{read_=function(url){try{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText}catch(err){var data=tryParseAsDataURI(url);if(data){return intArrayToString(data)}throw err}};if(ENVIRONMENT_IS_WORKER){readBinary=function(url){try{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}catch(err){var data=tryParseAsDataURI(url);if(data){return data}throw err}}}readAsync=function(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}var data=tryParseAsDataURI(url);if(data){onload(data.buffer);return}onerror()};xhr.onerror=onerror;xhr.send(null)}}setWindowTitle=function(title){document.title=title}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var tempRet0=0;var setTempRet0=function(value){tempRet0=value};var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(typeof WebAssembly!=="object"){abort("no native wasm support detected")}var wasmMemory;var ABORT=false;var EXITSTATUS;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}var UTF8Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf8"):undefined;function UTF8ArrayToString(heap,idx,maxBytesToRead){var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heap[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heap.subarray&&UTF8Decoder){return UTF8Decoder.decode(heap.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023)}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4}return len}var UTF16Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf-16le"):undefined;function UTF16ToString(ptr,maxBytesToRead){var endPtr=ptr;var idx=endPtr>>1;var maxIdx=idx+maxBytesToRead/2;while(!(idx>=maxIdx)&&HEAPU16[idx])++idx;endPtr=idx<<1;if(endPtr-ptr>32&&UTF16Decoder){return UTF16Decoder.decode(HEAPU8.subarray(ptr,endPtr))}else{var str="";for(var i=0;!(i>=maxBytesToRead/2);++i){var codeUnit=HEAP16[ptr+i*2>>1];if(codeUnit==0)break;str+=String.fromCharCode(codeUnit)}return str}}function stringToUTF16(str,outPtr,maxBytesToWrite){if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<2)return 0;maxBytesToWrite-=2;var startPtr=outPtr;var numCharsToWrite=maxBytesToWrite>1]=codeUnit;outPtr+=2}HEAP16[outPtr>>1]=0;return outPtr-startPtr}function lengthBytesUTF16(str){return str.length*2}function UTF32ToString(ptr,maxBytesToRead){var i=0;var str="";while(!(i>=maxBytesToRead/4)){var utf32=HEAP32[ptr+i*4>>2];if(utf32==0)break;++i;if(utf32>=65536){var ch=utf32-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}else{str+=String.fromCharCode(utf32)}}return str}function stringToUTF32(str,outPtr,maxBytesToWrite){if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<4)return 0;var startPtr=outPtr;var endPtr=startPtr+maxBytesToWrite-4;for(var i=0;i=55296&&codeUnit<=57343){var trailSurrogate=str.charCodeAt(++i);codeUnit=65536+((codeUnit&1023)<<10)|trailSurrogate&1023}HEAP32[outPtr>>2]=codeUnit;outPtr+=4;if(outPtr+4>endPtr)break}HEAP32[outPtr>>2]=0;return outPtr-startPtr}function lengthBytesUTF32(str){var len=0;for(var i=0;i=55296&&codeUnit<=57343)++i;len+=4}return len}function allocateUTF8(str){var size=lengthBytesUTF8(str)+1;var ret=_malloc(size);if(ret)stringToUTF8Array(str,HEAP8,ret,size);return ret}function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf)}var INITIAL_MEMORY=Module["INITIAL_MEMORY"]||16777216;var wasmTable;var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;__ATINIT__.push({func:function(){___wasm_call_ctors()}});function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what+="";err(what);ABORT=true;EXITSTATUS=1;what="abort("+what+"). Build with -s ASSERTIONS=1 for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject(e);throw e}function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="data:application/octet-stream;base64,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ACADIAIgBGtBfHEiBGoiAkEEayABNgIAIARBCUkNACADIAE2AgggAyABNgIEIAJBCGsgATYCACACQQxrIAE2AgAgBEEZSQ0AIAMgATYCGCADIAE2AhQgAyABNgIQIAMgATYCDCACQRBrIAE2AgAgAkEUayABNgIAIAJBGGsgATYCACACQRxrIAE2AgAgBCADQQRxQRhyIgRrIgJBIEkNACABrSIFQiCGIAWEIQUgAyAEaiEBA0AgASAFNwMYIAEgBTcDECABIAU3AwggASAFNwMAIAFBIGohASACQSBrIgJBH0sNAAsLIAALggQBA38gAkGABE8EQCAAIAEgAhAUGiAADwsgACACaiEDAkAgACABc0EDcUUEQAJAIAJBAUgEQCAAIQIMAQsgAEEDcUUEQCAAIQIMAQsgACECA0AgAiABLQAAOgAAIAFBAWohASACQQFqIgIgA08NASACQQNxDQALCwJAIANBfHEiBEHAAEkNACACIARBQGoiBUsNAANAIAIgASgCADYCACACIAEoAgQ2AgQgAiABKAIINgIIIAIgASgCDDYCDCACIAEoAhA2AhAgAiABKAIUNgIUIAIgASgCGDYCGCACIAEoAhw2AhwgAiABKAIgNgIgIAIgASgCJDYCJCACIAEoAig2AiggAiABKAIsNgIsIAIgASgCMDYCMCACIAEoAjQ2AjQgAiABKAI4NgI4IAIgASgCPDYCPCABQUBrIQEgAkFAayICIAVNDQALCyACIARPDQEDQCACIAEoAgA2AgAgAUEEaiEBIAJBBGoiAiAESQ0ACwwBCyADQQRJBEAgACECDAELIAAgA0EEayIESwRAIAAhAgwBCyAAIQIDQCACIAEtAAA6AAAgAiABLQABOgABIAIgAS0AAjoAAiACIAEtAAM6AAMgAUEEaiEBIAJBBGoiAiAETQ0ACwsgAiADSQRAA0AgAiABLQAAOgAAIAFBAWohASACQQFqIgIgA0cNAAsLIAALZQAgAkUEQCAAKAIEIAEoAgRGDwsgACABRgRAQQEPCwJ/IwBBEGsiAiAANgIIIAIgAigCCCgCBDYCDCACKAIMCwJ/IwBBEGsiACABNgIIIAAgACgCCCgCBDYCDCAAKAIMCxC7AUULFwAgAC0AAEEgcUUEQCABIAIgABBZGgsLbwEBfyMAQYACayIFJAACQCACIANMDQAg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IAAoAgAgA0dBAnRqIAE2AgAgASADNgIAIAMgATYCCCABKAIIIQILIAFBAToADCACQQA6AAwgAiACKAIAIgAoAgQiATYCACABBEAgASACNgIICyAAIAIoAgg2AgggAigCCCIBIAEoAgAgAkdBAnRqIAA2AgAgACACNgIEIAIgADYCCA8LAkAgBEUNACAELQAMDQAMAQsCQCABIAMoAgBHBEAgAyEBDAELIAMgASgCBCIANgIAIAEgAAR/IAAgAzYCCCADKAIIBSACCzYCCCADKAIIIgAgACgCACADR0ECdGogATYCACABIAM2AgQgAyABNgIIIAEoAgghAgsgAUEBOgAMIAJBADoADCACIAIoAgQiACgCACIBNgIEIAEEQCABIAI2AggLIAAgAigCCDYCCCACKAIIIgEgASgCACACR0ECdGogADYCACAAIAI2AgAgAiAANgIIDAILIARBDGohASADQQE6AAwgAiAAIAJGOgAMIAFBAToAACACIgEgAEcNAAsLC9AuAQx/IwBBEGsiDCQAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIABB9AFNBEBBjNkBKAIAIgVBECAAQQtqQXhxIABBC0kbIghBA3YiAnYiAUEDcQRAIAFBf3NBAXEgAmoiA0EDdCIBQbzZAWooAgAiBEEIaiEAAkAgBCgCCCICIAFBtNkBaiIBRgRAQYzZASAFQX4gA3dxNgIADAELQZzZASgCABogAiABNgIMIAEgAjYCCAsgBCADQQN0IgFBA3I2AgQgASAEaiIBIAEoAgRBAXI2AgQMDQsgCEGU2QEoAgAiCk0NASABBEACQEECIAJ0IgBBACAAa3IgASACdHEiAEEAIABrcUEBayIAIABBDHZBEHEiAnYiAUEFdkEIcSIAIAJyIAEgAHYiAUECdkEEcSIAciABIAB2IgFBAXZBAnEiAHIgASAAdiIBQQF2QQFxIgByIAEgAHZqIgNBA3QiAEG82QFqKAIAIgQoAggiASAAQbTZAWoiAEYEQEGM2QEgBUF+IAN3cSIFNgIADAELQZzZASgCABogASAANgIMIAAgATYCCAsgBEEIaiEAIAQgCEEDcjYCBCAEIAhqIgIgA0EDdCIBIAhrIgNBAXI2AgQgASAEaiADNgIAIAoEQCAKQQN2IgFBA3RBtNkBaiEHQaDZASgCACEEAn8gBUEB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AiwAS0EASARAQQAhAwwBCyABIQQDQCAEIgNFBEBBACEDDAILIAAgA0EBayIEai0AAEEKRw0ACyACIAAgAyACKAIkEQYAIgQgA0kNASAAIANqIQAgASADayEBIAIoAhQhBQsgBSAAIAEQIRogAiACKAIUIAFqNgIUIAEgA2ohBAsgBAtJAAJAIAFFDQAgAUHEzwAQKSIBRQ0AIAEoAgggACgCCEF/c3ENACAAKAIMIAEoAgxBABAiRQ0AIAAoAhAgASgCEEEAECIPC0EAC1IBAX8gACgCBCEEIAAoAgAiACABAn9BACACRQ0AGiAEQQh1IgEgBEEBcUUNABogAigCACABaigCAAsgAmogA0ECIARBAnEbIAAoAgAoAhwRBwALCgAgACABQQAQIgsLACAAEEMaIAAQHgsUACAAQdjLADYCACAAQQRqEGAgAAsHACAAKAIECywBAX8CfyAAKAIAQQxrIgAiASABKAIIQQFrIgE2AgggAUF/TAsEQCAAEB4LC3sCAn8BfiMAQTBrIgAkAEEBIABBIGoQFgRAQeTXASgCABoQCAALIAACfyAAQRBqIgEgADQCIDcDACABCwJ/IABBCGoiASAAQSBqQQRyNAIANwMAIAELEMUBNwMYIABBKGoiASAAKQMYNwMAIAEpAwAhAiAAQTBqJAAgAgsdACAAQZjLADYCACAAQcTLADYCACAAQQRqIAEQYws3AQJ/IAEQWCICQQ1qEB8iA0EANgIIIAMgAjYCBCADIAI2AgAgACADQQxqIAEgAkEBahAhNgIACwoAIABBzNgBEBcLCgAgAEGw2AEQGAu7AgACQCABQRRLDQACQAJAAkACQAJAAkACQAJAAkACQCABQQlrDgoAAQIDBAUGBwgJCgsgAiACKAIAIgFBBGo2AgAgACABKAIANgIADwsgAiACKAIAIgFBBGo2AgAgACABNAIANwMADwsgAiACKAIAIgFBBGo2AgAgACABNQIANwMADwsgAiACKAIAQQdqQXhxIgFBCGo2AgAgACABKQMANwMADwsgAiACKAIAIgFBBGo2AgAgACABMgEANwMADwsgAiACKAIAIgFBBGo2AgAgACABMwEANwMADwsgAiACKAIAIgFBBGo2AgAgACABMAAANwMADwsgAiACKAIAIgFBBGo2AgAgACABMQAANwMADwsgAiACKAIAQQdqQXhxIgFBCGo2AgAgACABKwMAOQMADwsgACACQQARBAALC0oBA38gACgCACwAAEEwa0EKSQRAA0AgACgCACIBLAAAIQMgACABQQFqNgIAIAMgAkEKbGpBMGshAiABLAABQTBrQQpJDQALCyACC80CAQN/IwBB0AFrIgQkACAEIAI2AswBQQAhAiAEQaABakEAQSgQIBogBCAEKALMATYCyAECQEEAIAEgBEHIAWogBEHQAGogBEGgAWogAxBGQQBIDQAgACgCTEEATiECIAAoAgAhBSAALABKQQBMBEAgACAFQV9xNgIACyAFQSBxIQYCfyAAKAIwBEAgACABIARByAFqIARB0ABqIARBoAFqIAMQRgwBCyAAQdAANgIwIAAgBEHQAGo2AhAgACAENgIcIAAgBDYCFCAAKAIsIQUgACAENgIsIAAgASAEQcgBaiAEQdAAaiAEQaABaiADEEYgBUUNABogAEEAQQAgACgCJBEGABogAEEANgIwIAAgBTYCLCAAQQA2AhwgAEEANgIQIAAoAhQaIABBADYCFEEACxogACAAKAIAIAZyNgIAIAJFDQALIARB0AFqJAALfgIBfwF+IAC9IgNCNIinQf8PcSICQf8PRwR8IAJFBEAgASAARAAAAAAAAAAAYQR/QQAFIABEAAAAAAAA8EOiIAEQaSEAIAEoAgBBQGoLNgIAIAAPCyABIAJB/gdrNgIAIANC/////////4eAf4NCgICAgICAgPA/hL8FIAALCxIAIABFBEBBAA8LIAAgARDUAQvMCQMFfwF+BHwjAEEwayIEJAACQAJAAkAgAL0iB0IgiKciAkH/////B3EiA0H61L2ABE0EQCACQf//P3FB+8MkRg0BIANB/LKLgARNBEAgB0IAWQRAIAEgAEQAAEBU+yH5v6AiAEQxY2IaYbTQvaAiCDkDACABIAAgCKFEMWNiGmG00L2gOQMIQQEhAgwFCyABIABEAABAVPsh+T+gIgBEMWNiGmG00D2gIgg5AwAgASAAIAihRDFjYhphtNA9oDkDCEF/IQIMBAsgB0IAWQRAIAEgAEQAAEBU+yEJwKAiAEQxY2IaYbTgvaAiCDkDACABIAAgCKFEMWNiGmG04L2gOQMIQQIhAgwECyABIABEAABAVPshCUCgIgBEMWNiGmG04D2gIgg5AwAgASAAIAihRDFjYhph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AgwgACgCDAsQbCEAIAFBEGokACAAC40DAgV/A3wgAEEANgIIIABCADcCACAAQYDAABAfIgE2AgAgACABQYBAayICNgIIIAFBAEGAwAAQICEDIABBADYCFCAAQgA3AgwgACACNgIEIABBgAYQHyIBNgIMIAAgAUGABmoiAjYCFCABQQBBgAYQICEEIABBADYCICAAQgA3AhggACACNgIQIABBgAIQHyIBNgIYIAAgAUGAAmoiAjYCICABQQBBgAIQICEFIABBADYCLCAAQgA3AiQgACACNgIcIABBgMAAEB8iAjYCJCAAIAJBgEBrIgE2AiwgACABNgIoIANBgICA/AM2AgBBASEBA0AgAbciBkQYLURU+yEJQKJEAAAAAAAAoD+iIgcQNCEIIAMgAUECdGogBkQYLURU+yFZP6IQR0QAAAAAAADgP6JEAAAAAAAA4D+gIAggB6O2u6K2OAIAIAFBAWoiAUGAEEcNAAsgAEIANwMwIABBQGtCADcDACAAQgA3AzggBUEAQYACECAaIARBAEGABhAgGiACQQBBgMAAECAaCwUAQbwiCxMAIABBBGpBACABKAIEQaQiRhsLXQECfyACKAIAIgIgACgCBCIEKAIAIgMgAiADSRsiAgRAIAEoAgAgACgCCCgCACACECsgACgCBCIEKAIAIQMLIAQgAyACazYCACAAKAIIIgAgACgCACACajYCACACCxQAIAFB/CA2AgAgASAAKQIENwIECxwBAX9BDBAfIgFB/CA2AgAgASAAKQIENwIEIAELBQBB7CALEwAgAEEEakEAIAEoAgRB1CBGGwszACACKAIAIgIEQCAAKAIEKAIAIAEoAgAgAhArCyAAKAIIIAIgACgCDCgCACgCFG42AgALHgAgAUGoHzYCACABIAApAgQ3AgQgASAAKAIMNgIMCyYBAX9BEBAfIgFBqB82AgAgASAAKQIENwIEIAEgACgCDDYCDCABC8cCAQV/IAAoAggoAgAgAC8BBGoiAyACKAIIKAIAIAIvAQRqIgRHBEAgBCADIAAtAAAQIRoLIAIgAC0AACIDOgAAIAAtAAAiBCABLQAAIgVrQQFqIgZBAU4EQEEAIQMDQAJAIAIoAggoAgAgAi8BBGogA2otAAAiBkUNACAFQQJJDQBBASEEA0AgASgCCCgCACABLwEEaiAEai0AACIHBEAg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IAE2AgAgASACNgIIIAEhAwsgAiACKAIIIgAtAAw6AAwgAEEBOgAMIANBAToADCAAIAAoAgAiASgCBCICNgIAIAIEQCACIAA2AggLIAEgACgCCDYCCCAAKAIIIgIgAigCACAAR0ECdGogATYCACABIAA2AgQgACABNgIIDwsgAigCCCIBIAEoAgAgAkZBAnRqKAIAIQIMAAsACyAEQQE6AAwLDwsgAS0ADA0AIAIhAwwBCyADQQE6AAwgAkEAOgAMIAIgAygCBCIANgIAIAAEQCAAIAI2AggLIAMgAigCCDYCCCACKAIIIgAgACgCACACR0ECdGogAzYCACADIAI2AgQgAiADNgIIIAIhAQsgAyADKAIIIgAtAAw6AAwgAEEBOgAMIAFBAToADCAAIAAoAgQiASgCACICNgIEIAIEQCACIAA2AggLIAEgACgCCDYCCCAAKAIIIgIgAigCACAAR0ECdGogATYCACABIAA2AgAgACABNgIIC/4FAQR/IAAoAqADIQEgAEEANgKgAyABBEAgASgCJCICBEAgASACNgIoIAIQHgsgASgCGCICBEAgASACNgIcIAIQHgsgASgCDCICBEAgASACNgIQIAIQHgsgASgCACICBEAgASACNgIEIAIQHgsgARAeCyAAKAKUAyIDBEACfyADIAMgACgCmAMiAUYNABoDQCABQQxrIgIoAgAiBARAIAFBCGsgBDYCACAEEB4LIAIiASADRw0ACyAAKAKUAwshASAAIAM2ApgDIAEQHgsgACgCiAMiAQRAIAAgATYCjAMgARAeCyAAKAL8AiIBBEAgACABNgKAAyABEB4LIAAoAvACIgEEQCAAIAE2AvQCIAEQHgsgACgC5AIiAQRAIAAgATYC6AIgARAeCyAAKALYAiIBBEAgACABNgLcAiABEB4LIAAoArwCIgEEQCAAIAE2AsACIAEQHgsgACgCsAIiAQRAIAAgATYCtAIgARAeCyAAKAKYAiIDBEACfyADIAMgACgCnAIiAUYNABoDQCABQQxrIgIoAgAiBARAIAFBCGsgBDYCACAEEB4LIAIiASADRw0ACyAAKAKYAgshASAAIAM2ApwCIAEQHgsgACgCiAIiAQRAIAAgATYCjAIgARAeCyAAKAL8ASIDBEACfyADIAMgACgCgAIiAUYNABoDQCABQQxrIgIoAgAiBARA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ACABNgIAIAAgAjYCBAwBCyAAIAI6AAsgACEBCyABIAMgAhAhIAJqQQA6AAAMAQsgAEIANwIAIABBADYCCAsgA0GAAmokAAugAQEBfyMAQUBqIgMkAAJ/QQEgACABQQAQIg0AGkEAIAFFDQAaQQAgAUH0zQAQKSIBRQ0AGiADQQhqQQRyQQBBNBAgGiADQQE2AjggA0F/NgIUIAMgADYCECADIAE2AgggASADQQhqIAIoAgBBASABKAIAKAIcEQcAIAMoAiAiAEEBRgRAIAIgAygCGDYCAAsgAEEBRgshACADQUBrJAAgAAtNAQJ/IAEtAAAhAgJAIAAtAAAiA0UNACACIANHDQADQCABLQABIQIgAC0AASIDRQ0BIAFBAWohASAAQQFqIQAgAiADRg0ACwsgAyACawsIACAAEF4QHguEAgEEfyMAQSBrIgMkACACKAIAIgRBcEkEQAJAAkAgBEELTwRAIARBEGpBcHEiBhAfIQUgAyAGQYCAgIB4cjYCCCADIAU2AgAgAyAENgIEDAELIAMgBDoACyADIQUgBEUNAQsgBSACQQRqIAQQIRoLIAQgBWpBADoAACADQRBqIAEgAyAAEQMAAkAgAywAGyIAQQBOBEAgAEH/AXEiAEEEahAvIgIgADYCACACQQRqIANBEGogABAhGgwBCyADKAIUIgFBBGoQLyICIAE2AgAgAkEEaiADKAIQIgAgARAhGiAAEB4LIAMsAAtBf0wEQCADKAIAEB4LIANBIGokACACDwsQRAALCAAgABBDEB4LBgBBgcsACzIBAX8jAEEQayIBJAAgASAAKAIENgIIIAEoAghBAToAACAAKAIIQQE6AAAgAUEQaiQACy4BAX8CQCAAKAIIIgAtAAAiAUEBRwR/IAFBAnENASAAQQI6AABBAQVBAAsPCwALNgECfyMAQRBrIgEkAAJ/IAEgACgCBDYCCCABKAIILQAARQsEQCAAEMEBIQILIAFBEGokACACCz8CAX8BfiMAQRBrIgEkACABIAApAwBCgJTr3AN+NwMAIAFBCGoiACABKQMANwMAIAApAwAhAiABQRBqJAAgAgtAAgJ/AX4jAEEQayICJAAjAEEQayIDJAAgARDDASEEIANBEGokACACIAQ3AwggACACKQMINwMAIAJBEGokACAAC1QCAX8BfiMAQSBrIgIkACACQQhq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2A1BogxBtNEAQcUOQQcgAEG00QBByQ5BCCABEARBBBAfIgBBFDYCAEEEEB8iAUEUNgIAQdgNQbcMQZwNQbwOQQkgAEGcDUHADkEKIAEQBEEEEB8iAEEYNgIAQQQQHyIBQRg2AgBB2A1BxwxBnA1BvA5BCSAAQZwNQcAOQQogARAEQdcMQQFB0A5BsA5BC0EMEAVB7AxBAkHUDkG8DkENQQ4QBUHxDEECQdwOQeQOQQ9BEBAFQfYMQQVBkA9ByBBBEUESEAVB/QxBA0HQEEHcEEETQRQQBQsL20sYAEGACAuZEVNhbXBsZUZvcm1hdABHR1dBVkVfU0FNUExFX0ZPUk1BVF9VTkRFRklORUQAR0dXQVZFX1NBTVBMRV9GT1JNQVRfVTgAR0dXQVZFX1NBTVBMRV9GT1JNQVRfSTgAR0dXQVZFX1NBTVBMRV9GT1JNQVRfVTE2AEdHV0FWRV9TQU1QTEVfRk9STUFUX0kxNgBHR1dBVkVfU0FNUExFX0ZPUk1BVF9GMzIAVHhQcm90b2NvbElkAEdHV0FWRV9UWF9QUk9UT0NPTF9BVURJQkxFX05PUk1BTABHR1dBVkVfVFhfUFJPVE9DT0xfQVVESUJMRV9GQVNUAEdHV0FWRV9UWF9QUk9UT0NPTF9BVURJQkxFX0ZBU1RFU1QAR0dXQVZFX1RYX1BST1RPQ09MX1VMVFJBU09VTkRfTk9STUFMAEdHV0FWRV9UWF9QUk9UT0NPTF9VTFRSQVNPVU5EX0ZBU1QAR0dXQVZFX1RYX1BST1RPQ09MX1VMVFJBU09VTkRfRkFTVEVTVABHR1dBVkVfVFhfUFJPVE9DT0xfRFRfTk9STUFMAEdHV0FWRV9UWF9QUk9UT0NPTF9EVF9GQVNUAEdHV0FWRV9UWF9QUk9UT0NPTF9EVF9GQVNURVNUAFBhcmFtZXRlcnMAcGF5bG9hZExlbmd0aABzYW1wbGVSYXRlSW5wAHNhbXBsZVJhdGVPdXQAc2FtcGxlc1BlckZyYW1lAHNvdW5kTWFya2VyVGhyZXNob2xkAHNhbXBsZUZvcm1hdElucABzYW1wbGVGb3JtYXRPdXQAZ2V0RGVmYXVsdFBhcmFtZXRlcnMAaW5pdABmcmVlAGVuY29kZQBkZWNvZGUAMTlnZ3dhdmVfU2FtcGxlRm9ybWF0AAAA0CgAAIQGAAAxOWdnd2F2ZV9UeFByb3RvY29sSWQAAADQKAAApAYAADE3Z2d3YXZlX1BhcmFtZXRlcnMAHCkAAMQGAABQMTdnZ3dhdmVfUGFyYW1ldGVycwAAAAD8KQAA4AYAAAAAAADYBgAAUEsxN2dnd2F2ZV9QYXJhbWV0ZXJzAAAA/CkAAAgHAAABAAAA2AYAAGlpAHYAdmkA+AYAAGlpaQB2aWlpAGZpaQB2aWlmAAAA2AYAAIQoAADYBgAAJCgAAIQoAAB2aWkATjEwZW1zY3JpcHRlbjExbWVtb3J5X3ZpZXdJY0VFAAAcKQAAaAcAALgHAACEKAAAMAgAALwGAACEKAAATjEwZW1zY3JpcHRlbjN2YWxFAAAcKQAApAcAAE5TdDNfXzIxMmJhc2ljX3N0cmluZ0ljTlNfMTFjaGFyX3RyYWl0c0ljRUVOU185YWxsb2NhdG9ySWNFRUVFAE5TdDNfXzIyMV9fYmFzaWNfc3RyaW5nX2NvbW1vbklMYjFFRUUAAAAAHCkAAP8HAACgKQAAwAcAAAAAAAABAAAAKAgAAAAAAABpaWlpaWkAADAIAACEKAAAMAgAAGlpaWkASW52YWxpZCBHR1dhdmUgaW5zdGFuY2UgJWQKAEZhaWxlZCB0byBpbml0aWFsaXplIEdHV2F2ZSBpbnN0YW5jZSAlZAoASW52YWxpZCBwYXlsb2FkIGxlZ250aABJbnZhbGlkIG9yIHVuc3VwcG9ydGVkIGNhcHR1cmUgc2FtcGxlIGZvcm1hdABJbnZhbGlkIG9yIHVuc3VwcG9ydGVkIHBsYXliYWNrIHNhbXBsZSBmb3JtYXQASW52YWxpZCBzYW1wbGVzIHBlciBmcmFtZQBFcnJvcjogY2FwdHVyZSBzYW1wbGUgcmF0ZSAoJWcgSHopIG11c3QgYmUgPj0gJWcgSHoKAEludmFsaWQgY2FwdHVyZS9wbGF5YmFjayBzYW1wbGUgcmF0ZQBFcnJvcjogY2FwdHVyZSBzYW1wbGUgcmF0ZSAoJWcgSHopIG11c3QgYmUgPD0gJWcgSHoKAE5lZ2F0aXZlIGRhdGEgc2l6ZTogJWQKAFRydW5jYXRpbmcgZGF0YSBmcm9tICVkIHRvICVkIGJ5dGVzCgBJbnZhbGlkIHZvbHVtZTogJWQKAEZhaWx1cmUgZHVyaW5nIGNhcHR1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Y29kZUUzJF8xAAAAHCkAACQRAAAAAAAAAQAAAAEAAAACAAAAAgAAAAQAAAB2b2lkAGJvb2wAY2hhcgBzaWduZWQgY2hhcgB1bnNpZ25lZCBjaGFyAHNob3J0AHVuc2lnbmVkIHNob3J0AGludAB1bnNpZ25lZCBpbnQAbG9uZwB1bnNpZ25lZCBsb25nAGZsb2F0AGRvdWJsZQBzdGQ6OnN0cmluZwBzdGQ6OmJhc2ljX3N0cmluZzx1bnNpZ25lZCBjaGFyPgBzdGQ6OndzdHJpbmcAc3RkOjp1MTZzdHJpbmcAc3RkOjp1MzJzdHJpbmcAZW1zY3JpcHRlbjo6dmFsAGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PGNoYXI+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PHNpZ25lZCBjaGFyPgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzx1bnNpZ25lZCBjaGFyPgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzxzaG9ydD4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8dW5zaWduZWQgc2hvcnQ+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PGludD4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8dW5zaWduZWQgaW50PgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzxsb25nPgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzx1bnNpZ25lZCBsb25nPgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzxpbnQ4X3Q+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PHVpbnQ4X3Q+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PGludDE2X3Q+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PHVpbnQxNl90PgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzxpbnQzMl90PgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzx1aW50MzJfdD4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8ZmxvYXQ+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PGRvdWJsZT4ATlN0M19fMjEyYmFzaWNfc3RyaW5nSWhOU18xMWNoYXJfdHJhaXRzSWhFRU5TXzlhbGxvY2F0b3JJaEVFRUUAAAAAoCkAAHIUAAAAAAAAAQAAACgIAAAAAAAATlN0M19fMjEyYmFzaWNfc3RyaW5nSXdOU18xMWNoYXJfdHJhaXRzSXdFRU5TXzlhbGxvY2F0b3JJd0VFRUUAAKApAADMFAAAAAAAAAEAAAAoCAAAAAAAAE5TdDNfXzIxMmJhc2ljX3N0cmluZ0lEc05TXzExY2hhcl90cmFpdHNJRHNFRU5TXzlhbGxvY2F0b3JJRHNFRUVFAAAAoCkAACQVAAAAAAAAAQAAACgIAAAAAAAATlN0M19fMjEyYmFzaWNfc3RyaW5nSURpTlNfMTFjaGFyX3RyYWl0c0lEaUVFTlNfOWFsbG9jYXRvcklEaUVFRUUAAACgKQAAgBUAAAAAAAABAAAAKAgAAAAAAABOMTBlbXNjcmlwdGVuMTFtZW1vcnlfdmlld0lhRUUAABwpAADcFQAATjEwZW1zY3JpcHRlbjExbWVtb3J5X3ZpZXdJaEVFAAAcKQAABBYAAE4xMGVtc2NyaXB0ZW4xMW1lbW9yeV92aWV3SXNFRQAAHCkAACwWAABOMTBlbXNjcmlwdGVuMTFtZW1vcnlfdmlld0l0RUUAABwpAABUFgAATjEwZW1zY3JpcHRlbjExbWVtb3J5X3ZpZXdJaUVFAAAcKQAAfBYAAE4xMGVtc2NyaXB0ZW4xMW1lbW9yeV92aWV3SWpFRQAAHCkAAKQWAABOMTBlbXNjcmlwdGVuMTFtZW1vcnlfdmlld0lsRUUAABwpAADMFgAATjEwZW1zY3JpcHRlbjExbWVtb3J5X3ZpZXdJbUVFAAAcKQAA9BYAAE4xMGVtc2NyaXB0ZW4xMW1lbW9yeV92aWV3SWZFRQAAHCkAABwXAABOMTBlbXNjcmlwdGVuMTFtZW1vcnlfdmlld0lkRUUAABwpAABEFwAAAAAAAAMAAAAEAAAABAAAAAYAAACD+aIARE5uAPwpFQDRVycA3TT1AGLbwAA8mZUAQZBDAGNR/gC73qsAt2HFADpuJADSTUIASQbgAAnqLgAcktEA6x3+ACmxHADoPqcA9TWCAES7LgCc6YQAtCZwAEF+XwDWkTkAU4M5AJz0OQCLX4QAKPm9APgfOwDe/5cAD5gFABEv7wAKWosAbR9tAM9+NgAJyycARk+3AJ5mPwAt6l8Auid1AOXrxwA9e/EA9zkHAJJSigD7a+oAH7FfAAhdjQAwA1YAe/xGAPCrawAgvM8ANvSaAOOpHQBeYZEACBvmAIWZZQCgFF8AjUBoAIDY/wAnc00ABgYxAMpWFQDJqHMAe+JgAGuMwAAZxEcAzWfDAAno3ABZgyoAi3bEAKYclgBEr90AGVfRAKU+BQAFB/8AM34/AMIy6ACYT94Au30yACY9wwAea+8An/heADUfOgB/8soA8YcdAHyQIQBqJHwA1W76ADAtdwAVO0MAtRTGAMMZnQCtxMIALE1BAAwAXQCGfUYA43EtAJvGmgAzYgAAtNJ8ALSnlwA3VdUA1z72AKMQGABNdvwAZJ0qAHDXqwBjfPgAerBXABcV5wDASVYAO9bZAKeEOAAkI8sA1op3AFpUIwAAH7kA8QobABnO3wCfMf8AZh5qAJlXYQCs+0cAfn/YACJltwAy6IkA5r9gAO/EzQBsNgkAXT/UABbe1wBYO94A3puSANIiKAAohugA4lhNAMbKMgAI4xYA4H3LABfAUADzHacAGOBbAC4TNACDEmIAg0gBAPWOWwCtsH8AHunyAEhKQwAQZ9MAqt3YAK5fQgBqYc4ACiikANOZtAAGpvIAXHd/AKPCgwBhPIgAinN4AK+MWgBv170ALaZjAPS/ywCNge8AJsFnAFXKRQDK2TYAKKjSAMJhjQASyXcABCYUABJGmwDEWcQAyMVEAE2ykQAAF/MA1EOtAClJ5QD91RAAAL78AB6UzABwzu4AEz71AOzxgACz58MAx/goAJMFlADBcT4ALgmzAAtF8wCIEpwAqyB7AC61nwBHksIAezIvAAxVbQByp5AAa+cfADHLlgB5FkoAQXniAPTfiQDolJcA4uaEAJkxlwCI7WsAX182ALv9DgBImrQAZ6RsAHFyQgCNXTIAnxW4ALzlCQCNMSUA93Q5ADAFHAANDAEASwhoACzuWABHqpAAdOcCAL3WJAD3faYAbkhyAJ8W7wCOlKYAtJH2ANFTUQDPCvIAIJgzAPVLfgCyY2gA3T5fAEBdAwCFiX8AVVIpADdkwABt2BAAMkgyAFtMdQBOcdQARVRuAAsJwQAq9WkAFGbVACcHnQBdBFAAtDvbAOp2xQCH+RcASWt9AB0nugCWaSkAxsysAK0UVACQ4moAiNmJACxyUAAEpL4AdweUAPMwcAAA/CcA6nGoAGbCSQBk4D0Al92DAKM/lwBDlP0ADYaMADFB3gCSOZ0A3XCMABe35wAI3zsAFTcrAFyAoABagJMAEBGSAA/o2ABsgK8A2/9LADiQDwBZGHYAYqUVAGHLuwDHibkAEEC9ANLyBABJdScA67b2ANsiuwAKFKoAiSYvAGSDdgAJOzMADpQaAFE6qgAdo8IAr+2uAFwmEgBtwk0ALXqcAMBWlwADP4MACfD2ACtAjABtMZkAObQHAAwgFQDYw1sA9ZLEAMatSwBOyqUApzfNAOapNgCrkpQA3UJoABlj3gB2jO8AaItSAPzbNwCuoasA3xUxAACuoQAM+9oAZE1mAO0FtwApZTAAV1a/AEf/OgBq+bkAdb7zACiT3wCrgDAAZoz2AATLFQD6IgYA2eQdAD2zpABXG48ANs0JAE5C6QATvqQAMyO1APCqGgBPZagA0sGlAAs/DwBbeM0AI/l2AHuLBACJF3IAxqZTAG9u4gDv6wAAm0pYAMTatwCqZroAds/PANECHQCx8S0AjJnBAMOtdwCGSNoA912gAMaA9ACs8C8A3eyaAD9cvADQ3m0AkMcfACrbtgCjJToAAK+aAK1TkwC2VwQAKS20AEuAfgDaB6cAdqoOAHtZoQAWEioA3LctAPrl/QCJ2/4Aib79AOR2bAAGqfwAPoBwAIVuFQD9h/8AKD4HAGFnMwAqGIYATb3qALPnrwCPbW4AlWc5ADG/WwCE10gAMN8WAMctQwAlYTUAyXDOADDLuAC/bP0ApACiAAVs5ABa3aAAIW9HAGIS0gC5XIQAcGFJAGtW4ACZUgEAUFU3AB7VtwAz8cQAE25fAF0w5ACFLqkAHbLDAKEyNgAIt6QA6rHUABb3IQCPaeQAJ/93AAwDgACNQC0AT82gACClmQCzotMAL10KALT5QgAR2ssAfb7QAJvbwQCrF70AyqKBAAhqXAAuVRcAJwBVAH8U8ADhB4YAFAtkAJZBjQCHvt4A2v0qAGsltgB7iTQABfP+ALm/ngBoak8ASiqoAE/EWgAt+LwA11qYAPTHlQANTY0AIDqmAKRXXwAUP7EAgDiVAMwgAQBx3YYAyd62AL9g9QBNZREAAQdrAIywrACywNAAUVVIAB77DgCVcsMAowY7AMBANQAG3HsA4EXMAE4p+gDWysgA6PNBAHxk3gCbZNgA2b4xAKSXwwB3WNQAaePFAPDaEwC6OjwARhhGAFV1XwDSvfUAbpLGAKwuXQAORO0AHD5CAGHEhwAp/ekA59bzACJ8ygBvkTUACODFAP/XjQBuauIAsP3GAJMIwQB8XXQAa62yAM1unQA+cnsAxhFqAPfPqQApc98Atcm6ALcAUQDisg0AdLokAOV9YAB02IoADRUsAIEYDAB+ZpQAASkWAJ96dgD9/b4AVkXvANl+NgDs2RMAi7q5AMSX/AAxqCcA8W7DAJTFNgDYqFYAtKi1AM/MDgASiS0Ab1c0ACxWiQCZzuMA1iC5AGteqgA+KpwAEV/MAP0LSgDh9PsAjjttAOKGLADp1IQA/LSpAO/u0QAuNckALzlhADghRAAb2cgAgfwKAPtKagAvHNgAU7SEAE6ZjABUIswAKlXcAMDG1gALGZYAGnC4AGmVZAAmWmAAP1LuAH8RDwD0tREA/Mv1ADS8LQA0vO4A6F3MAN1eYABnjpsAkjPvAMkXuABhWJsA4Ve8AFGDxgDYPhAA3XFIAC0c3QCvGKEAISxGAFnz1wDZepgAnlTAAE+G+gBWBvwA5XmuAIkiNgA4rSIAZ5PcAFXoqgCCJjgAyuebAFENpACZM7EAqdcOAGkFSABlsvAAf4inAIhMlwD50TYAIZKzAHuCSgCYzyEAQJ/cANxHVQDhdDoAZ+tCAP6d3wBe1F8Ae2ekALqsegBV9qIAK4gjAEG6VQBZbggAISqGADlHgwCJ4+YA5Z7UAEn7QAD/VukAHA/KAMVZigCU+isA08HFAA/FzwDbWq4AR8WGAIVDYgAhhjsALHmUABBhhwAqTHsAgCwaAEO/EgCIJpAAeDyJAKjE5ADl23sAxDrCACb06gD3Z4oADZK/AGWjKwA9k7EAvXwLAKRR3AAn3WMAaeHdAJqUGQCoKZUAaM4oAAnttABEnyAATpjKAHCCYwB+fCMAD7kyAKf1jgAUVucAIfEIALWdKgBvfk0ApRlRALX5qwCC39YAlt1hABY2AgDEOp8Ag6KhAHLtbQA5jXoAgripAGsyXABGJ1sAADTtANIAdwD89FUAAVlNAOBxgABB08QAC01A+yH5PwAAAAAtRHQ+AAAAgJhG+DwAAABgUcx4OwAAAICDG/A5AAAAQCAlejgAAACAIoLjNgAAAAAd82k1LSsgICAwWDB4AChudWxsKQBBsMUAC0ERAAoAERERAAAAAAUAAAAAAAAJAAAAAAsAAAAAAAAAABEADwoREREDCgcAAQAJCwsAAAkGCwAACwAGEQAAABEREQBBgcYACyELAAAAAAAAAAARAAoKERERAAoAAAIACQsAAAAJAAsAAAsAQbvGAAsBDABBx8YACxUMAAAAAAwAAAAACQwAAAAAAAwAAAwAQfXGAAsBDgBBgccACxUNAAAABA0AAAAACQ4AAAAAAA4AAA4AQa/HAAsBEABBu8cACx4PAAAAAA8AAAAACRAAAAAAABAAABAAABIAAAASEhIAQfLHAAsOEgAAABISEgAAAAAAAAkAQaPIAAsBCwBBr8gACxUKAAAAAAoAAAAACQsAAAAAAAsAAAsAQd3IAAsBDABB6cgAC6QLDAAAAAAMAAAAAAkMAAAAAAAMAAAMAAAwMTIzNDU2Nzg5QUJDREVGLTBYKzBYIDBYLTB4KzB4IDB4AGluZgBJTkYAbmFuAE5BTgAuAAAAABArAAB2ZWN0b3IAc3RkOjpiYWRfZnVuY3Rpb25fY2FsbAAAAAAAAAAMJQAAGAAAADEAAAAyAAAATlN0M19fMjE3YmFkX2Z1bmN0aW9uX2NhbGxFAEQpAADwJAAAtCUAAGJhc2ljX3N0cmluZwBjbG9ja19nZXR0aW1lKENMT0NLX01PTk9UT05JQykgZmFpbGVkAF9fY3hhX2d1YXJkX2FjcXVpcmUgZGV0ZWN0ZWQgcmVjdXJzaXZlIGluaXRpYWxpemF0aW9uAHN0ZDo6ZXhjZXB0aW9uAAAAAAC0JQAAMwAAADQAAAA1AAAAU3Q5ZXhjZXB0aW9uAAAAABwpAACkJQAAAAAAAPQlAAAXAAAANgAAADcAAAAAAAAAfCYAABUAAAA4AAAAOQAAAFN0MTFsb2dpY19lcnJvcgBEKQAA5CUAALQlAAAAAAAAKCYAABcAAAA6AAAANwAAAFN0MTJsZW5ndGhfZXJyb3IAAAAARCkAABQmAAD0JQAAAAAAAFwmAAAXAAAAOwAAADcAAABTdDEyb3V0X29mX3JhbmdlAAAAAEQpAABIJgAA9CUAAFN0MTNydW50aW1lX2Vycm9yAAAARCkAAGgmAAC0JQAAU3Q5dHlwZV9pbmZvAAAAABwpAACIJgAATjEwX19jeHhhYml2MTE2X19zaGltX3R5cGVfaW5mb0UAAAAARCkAAKAmAACYJgAATjEwX19jeHhhYml2MTE3X19jbGFzc190eXBlX2luZm9FAAAARCkAANAmAADEJgAATjEwX19jeHhhYml2MTE3X19wYmFzZV90eXBlX2luZm9FAAAARCkAAAAnAADEJgAATjEwX19jeHhhYml2MTE5X19wb2ludGVyX3R5cGVfaW5mb0UARCkAADAnAAAkJwAATjEwX19jeHhhYml2MTIwX19mdW5jdGlvbl90eXBlX2luZm9FAAAAAEQpAABgJwAAxCYAAE4xMF9fY3h4YWJpdjEyOV9fcG9pbnRlcl90b19tZW1iZXJfdHlwZV9pbmZvRQAAAEQpAACUJwAAJCcAAAAAAAAUKAAAPAAAAD0AAAA+AAAAPwAAAEAAAABOMTBfX2N4eGFiaXYxMjNfX2Z1bmRhbWVudGFsX3R5cGVfaW5mb0UARCkAAOwnAADEJgAAdgAAANgnAAAgKAAARG4AANgnAAAsKAAAYgAAANgnAAA4KAAAYwAAANgnAABEKAAAaAAAANgnAABQKAAAYQAAANgnAABcKAAAcwAAANgnAABoKAAAdAAAANgnAAB0KAAAaQAAANgnAACAKAAAagAAANgnAACMKAAAbAAAANgnAACYKAAAbQAAANgnAACkKAAAZgAAANgnAACwKAAAZAAAANgnAAC8KAAAAAAAAAgpAAA8AAAAQQAAAD4AAAA/AAAAQgAAAE4xMF9fY3h4YWJpdjExNl9fZW51bV90eXBlX2luZm9FAAAAAEQpAADkKAAAxCYAAAAAAAD0JgAAPAAAAEMAAAA+AAAAPwAAAEQAAABFAAAARgAAAEcAAAAAAAAAjCkAADwAAABIAAAAPgAAAD8AAABEAAAASQAAAEoAAABLAAAATjEwX19jeHhhYml2MTIwX19zaV9jbGFzc190eXBlX2luZm9FAAAAAEQpAABkKQAA9CYAAAAAAADoKQAAPAAAAEwAAAA+AAAAPwAAAEQAAABNAAAATgAAAE8AAABOMTBfX2N4eGFiaXYxMjFfX3ZtaV9jbGFzc190eXBlX2luZm9FAAAARCkAAMApAAD0JgAAAAAAAFQnAAA8AAAAUAAAAD4AAAA/AAAAUQBBkNQACxn/////AIA7RwCAO0cABAAAAABAQAUAAAAFAEHY1QALAhBsAEGQ1gALAQUAQZzWAAsBLgBBtNYACwovAAAAMAAAADBsAEHM1gALAQIAQdvWAAsF//////8AQaDXAAsDkG5Q";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}function getBinary(file){try{if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}var binary=tryParseAsDataURI(file);if(binary){return binary}if(readBinary){return readBinary(file)}else{throw"both async and sync fetching of the wasm failed"}}catch(err){abort(err)}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)){if(typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw"failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary(wasmBinaryFile)})}else{if(readAsync){return new Promise(function(resolve,reject){readAsync(wasmBinaryFile,function(response){resolve(new Uint8Array(response))},reject)})}}}return Promise.resolve().then(function(){return getBinary(wasmBinaryFile)})}function createWasm(){var info={"a":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmMemory=Module["asm"]["E"];updateGlobalBufferAndViews(wasmMemory.buffer);wasmTable=Module["asm"]["F"];removeRunDependency("wasm-instantiate")}addRunDependency("wasm-instantiate");function receiveInstantiatedSource(output){receiveInstance(output["instance"])}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason)})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(receiveInstantiatedSource)})})}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync().catch(readyPromiseReject);return{}}function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){wasmTable.get(func)()}else{wasmTable.get(func)(callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}function _tzset(){if(_tzset.called)return;_tzset.called=true;var currentYear=(new Date).getFullYear();var winter=new Date(currentYear,0,1);var summer=new Date(currentYear,6,1);var winterOffset=winter.getTimezoneOffset();var summerOffset=summer.getTimezoneOffset();var stdTimezoneOffset=Math.max(winterOffset,summerOffset);HEAP32[__get_timezone()>>2]=stdTimezoneOffset*60;HEAP32[__get_daylight()>>2]=Number(winterOffset!=summerOffset);function extractZone(date){var match=date.toTimeString().match(/\(([A-Za-z ]+)\)$/);return match?match[1]:"GMT"}var winterName=extractZone(winter);var summerName=extractZone(summer);var winterNamePtr=allocateUTF8(winterName);var summerNamePtr=allocateUTF8(summerName);if(summerOffset>2]=winterNamePtr;HEAP32[__get_tzname()+4>>2]=summerNamePtr}else{HEAP32[__get_tzname()>>2]=summerNamePtr;HEAP32[__get_tzname()+4>>2]=winterNamePtr}}function _asctime_r(tmPtr,buf){var date={tm_sec:HEAP32[tmPtr>>2],tm_min:HEAP32[tmPtr+4>>2],tm_hour:HEAP32[tmPtr+8>>2],tm_mday:HEAP32[tmPtr+12>>2],tm_mon:HEAP32[tmPtr+16>>2],tm_year:HEAP32[tmPtr+20>>2],tm_wday:HEAP32[tmPtr+24>>2]};var days=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"];var months=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];var s=days[date.tm_wday]+" "+months[date.tm_mon]+(date.tm_mday<10?" ":" ")+date.tm_mday+(date.tm_hour<10?" 0":" ")+date.tm_hour+(date.tm_min<10?":0":":")+date.tm_min+(date.tm_sec<10?":0":":")+date.tm_sec+" "+(1900+date.tm_year)+"\n";stringToUTF8(s,buf,26);return buf}function ___asctime_r(a0,a1){return _asctime_r(a0,a1)}var ExceptionInfoAttrs={DESTRUCTOR_OFFSET:0,REFCOUNT_OFFSET:4,TYPE_OFFSET:8,CAUGHT_OFFSET:12,RETHROWN_OFFSET:13,SIZE:16};function ___cxa_allocate_exception(size){return _malloc(size+ExceptionInfoAttrs.SIZE)+ExceptionInfoAttrs.SIZE}function ExceptionInfo(excPtr){this.excPtr=excPtr;this.ptr=excPtr-ExceptionInfoAttrs.SIZE;this.set_type=function(type){HEAP32[this.ptr+ExceptionInfoAttrs.TYPE_OFFSET>>2]=type};this.get_type=function(){return HEAP32[this.ptr+ExceptionInfoAttrs.TYPE_OFFSET>>2]};this.set_destructor=function(destructor){HEAP32[this.ptr+ExceptionInfoAttrs.DESTRUCTOR_OFFSET>>2]=destructor};this.get_destructor=function(){return HEAP32[this.ptr+ExceptionInfoAttrs.DESTRUCTOR_OFFSET>>2]};this.set_refcount=function(refcount){HEAP32[this.ptr+ExceptionInfoAttrs.REFCOUNT_OFFSET>>2]=refcount};this.set_caught=function(caught){caught=caught?1:0;HEAP8[this.ptr+ExceptionInfoAttrs.CAUGHT_OFFSET>>0]=caught};this.get_caught=function(){return HEAP8[this.ptr+ExceptionInfoAttrs.CAUGHT_OFFSET>>0]!=0};this.set_rethrown=function(rethrown){rethrown=rethrown?1:0;HEAP8[this.ptr+ExceptionInfoAttrs.RETHROWN_OFFSET>>0]=rethrown};this.get_rethrown=function(){return HEAP8[this.ptr+ExceptionInfoAttrs.RETHROWN_OFFSET>>0]!=0};this.init=function(type,destructor){this.set_type(type);this.set_destructor(destructor);this.set_refcount(0);this.set_caught(false);this.set_rethrown(false)};this.add_ref=function(){var value=HEAP32[this.ptr+ExceptionInfoAttrs.REFCOUNT_OFFSET>>2];HEAP32[this.ptr+ExceptionInfoAttrs.REFCOUNT_OFFSET>>2]=value+1};this.release_ref=function(){var prev=HEAP32[this.ptr+ExceptionInfoAttrs.REFCOUNT_OFFSET>>2];HEAP32[this.ptr+ExceptionInfoAttrs.REFCOUNT_OFFSET>>2]=prev-1;return prev===1}}var exceptionLast=0;var uncaughtExceptionCount=0;function ___cxa_throw(ptr,type,destructor){var info=new ExceptionInfo(ptr);info.init(type,destructor);exceptionLast=ptr;uncaughtExceptionCount++;throw ptr}function _localtime_r(time,tmPtr){_tzset();var date=new Date(HEAP32[time>>2]*1e3);HEAP32[tmPtr>>2]=date.getSeconds();HEAP32[tmPtr+4>>2]=date.getMinutes();HEAP32[tmPtr+8>>2]=date.getHours();HEAP32[tmPtr+12>>2]=date.getDate();HEAP32[tmPtr+16>>2]=date.getMonth();HEAP32[tmPtr+20>>2]=date.getFullYear()-1900;HEAP32[tmPtr+24>>2]=date.getDay();var start=new Date(date.getFullYear(),0,1);var yday=(date.getTime()-start.getTime())/(1e3*60*60*24)|0;HEAP32[tmPtr+28>>2]=yday;HEAP32[tmPtr+36>>2]=-(date.getTimezoneOffset()*60);var summerOffset=new Date(date.getFullYear(),6,1).getTimezoneOffset();var winterOffset=start.getTimezoneOffset();var dst=(summerOffset!=winterOffset&&date.getTimezoneOffset()==Math.min(winterOffset,summerOffset))|0;HEAP32[tmPtr+32>>2]=dst;var zonePtr=HEAP32[__get_tzname()+(dst?4:0)>>2];HEAP32[tmPtr+40>>2]=zonePtr;return tmPtr}function ___localtime_r(a0,a1){return _localtime_r(a0,a1)}function getShiftFromSize(size){switch(size){case 1:return 0;case 2:return 1;case 4:return 2;case 8:return 3;default:throw new TypeError("Unknown type size: "+size)}}function embind_init_charCodes(){var codes=new Array(256);for(var i=0;i<256;++i){codes[i]=String.fromCharCode(i)}embind_charCodes=codes}var embind_charCodes=undefined;function readLatin1String(ptr){var ret="";var c=ptr;while(HEAPU8[c]){ret+=embind_charCodes[HEAPU8[c++]]}return ret}var awaitingDependencies={};var registeredTypes={};var typeDependencies={};var char_0=48;var char_9=57;function makeLegalFunctionName(name){if(undefined===name){return"_unknown"}name=name.replace(/[^a-zA-Z0-9_]/g,"$");var f=name.charCodeAt(0);if(f>=char_0&&f<=char_9){return"_"+name}else{return name}}function createNamedFunction(name,body){name=makeLegalFunctionName(name);return new Function("body","return function "+name+"() {\n"+' "use strict";'+" return body.apply(this, arguments);\n"+"};\n")(body)}function extendError(baseErrorType,errorName){var errorClass=createNamedFunction(errorName,function(message){this.name=errorName;this.message=message;var stack=new Error(message).stack;if(stack!==undefined){this.stack=this.toString()+"\n"+stack.replace(/^Error(:[^\n]*)?\n/,"")}});errorClass.prototype=Object.create(baseErrorType.prototype);errorClass.prototype.constructor=errorClass;errorClass.prototype.toString=function(){if(this.message===undefined){return this.name}else{return this.name+": "+this.message}};return errorClass}var BindingError=undefined;function throwBindingError(message){throw new BindingError(message)}var InternalError=undefined;function throwInternalError(message){throw new InternalError(message)}function whenDependentTypesAreResolved(myTypes,dependentTypes,getTypeConverters){myTypes.forEach(function(type){typeDependencies[type]=dependentTypes});function onComplete(typeConverters){var myTypeConverters=getTypeConverters(typeConverters);if(myTypeConverters.length!==myTypes.length){throwInternalError("Mismatched type converter count")}for(var i=0;i>shift])},destructorFunction:null})}function ClassHandle_isAliasOf(other){if(!(this instanceof ClassHandle)){return false}if(!(other instanceof ClassHandle)){return false}var leftClass=this.$$.ptrType.registeredClass;var left=this.$$.ptr;var rightClass=other.$$.ptrType.registeredClass;var right=other.$$.ptr;while(leftClass.baseClass){left=leftClass.upcast(left);leftClass=leftClass.baseClass}while(rightClass.baseClass){right=rightClass.upcast(right);rightClass=rightClass.baseClass}return leftClass===rightClass&&left===right}function shallowCopyInternalPointer(o){return{count:o.count,deleteScheduled:o.deleteScheduled,preservePointerOnDelete:o.preservePointerOnDelete,ptr:o.ptr,ptrType:o.ptrType,smartPtr:o.smartPtr,smartPtrType:o.smartPtrType}}function throwInstanceAlreadyDeleted(obj){function getInstanceTypeName(handle){return handle.$$.ptrType.registeredClass.name}throwBindingError(getInstanceTypeName(obj)+" instance already deleted")}var finalizationGroup=false;function detachFinalizer(handle){}function runDestructor($$){if($$.smartPtr){$$.smartPtrType.rawDestructor($$.smartPtr)}else{$$.ptrType.registeredClass.rawDestructor($$.ptr)}}function releaseClassHandle($$){$$.count.value-=1;var toDelete=0===$$.count.value;if(toDelete){runDestructor($$)}}function attachFinalizer(handle){if("undefined"===typeof FinalizationGroup){attachFinalizer=function(handle){return handle};return handle}finalizationGroup=new FinalizationGroup(function(iter){for(var result=iter.next();!result.done;result=iter.next()){var $$=result.value;if(!$$.ptr){console.warn("object already deleted: "+$$.ptr)}else{releaseClassHandle($$)}}});attachFinalizer=function(handle){finalizationGroup.register(handle,handle.$$,handle.$$);return handle};detachFinalizer=function(handle){finalizationGroup.unregister(handle.$$)};return attachFinalizer(handle)}function ClassHandle_clone(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.preservePointerOnDelete){this.$$.count.value+=1;return this}else{var clone=attachFinalizer(Object.create(Object.getPrototypeOf(this),{$$:{value:shallowCopyInternalPointer(this.$$)}}));clone.$$.count.value+=1;clone.$$.deleteScheduled=false;return clone}}function ClassHandle_delete(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}detachFinalizer(this);releaseClassHandle(this.$$);if(!this.$$.preservePointerOnDelete){this.$$.smartPtr=undefined;this.$$.ptr=undefined}}function ClassHandle_isDeleted(){return!this.$$.ptr}var delayFunction=undefined;var deletionQueue=[];function flushPendingDeletes(){while(deletionQueue.length){var obj=deletionQueue.pop();obj.$$.deleteScheduled=false;obj["delete"]()}}function ClassHandle_deleteLater(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}deletionQueue.push(this);if(deletionQueue.length===1&&delayFunction){delayFunction(flushPendingDeletes)}this.$$.deleteScheduled=true;return this}function init_ClassHandle(){ClassHandle.prototype["isAliasOf"]=ClassHandle_isAliasOf;ClassHandle.prototype["clone"]=ClassHandle_clone;ClassHandle.prototype["delete"]=ClassHandle_delete;ClassHandle.prototype["isDeleted"]=ClassHandle_isDeleted;ClassHandle.prototype["deleteLater"]=ClassHandle_deleteLater}function ClassHandle(){}var registeredPointers={};function ensureOverloadTable(proto,methodName,humanName){if(undefined===proto[methodName].overloadTable){var prevFunc=proto[methodName];proto[methodName]=function(){if(!proto[methodName].overloadTable.hasOwnProperty(arguments.length)){throwBindingError("Function '"+humanName+"' called with an invalid number of arguments ("+arguments.length+") - expects one of ("+proto[methodName].overloadTable+")!")}return proto[methodName].overloadTable[arguments.length].apply(this,arguments)};proto[methodName].overloadTable=[];proto[methodName].overloadTable[prevFunc.argCount]=prevFunc}}function exposePublicSymbol(name,value,numArguments){if(Module.hasOwnProperty(name)){if(undefined===numArguments||undefined!==Module[name].overloadTable&&undefined!==Module[name].overloadTable[numArguments]){throwBindingError("Cannot register public name '"+name+"' twice")}ensureOverloadTable(Module,name,name);if(Module.hasOwnProperty(numArguments)){throwBindingError("Cannot register multiple overloads of a function with the same number of arguments ("+numArguments+")!")}Module[name].overloadTable[numArguments]=value}else{Module[name]=value;if(undefined!==numArguments){Module[name].numArguments=numArguments}}}function RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast){this.name=name;this.constructor=constructor;this.instancePrototype=instancePrototype;this.rawDestructor=rawDestructor;this.baseClass=baseClass;this.getActualType=getActualType;this.upcast=upcast;this.downcast=downcast;this.pureVirtualFunctions=[]}function upcastPointer(ptr,ptrClass,desiredClass){while(ptrClass!==desiredClass){if(!ptrClass.upcast){throwBindingError("Expected null or instance of "+desiredClass.name+", got an instance of "+ptrClass.name)}ptr=ptrClass.upcast(ptr);ptrClass=ptrClass.baseClass}return ptr}function constNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError("null is not a valid "+this.name)}return 0}if(!handle.$$){throwBindingError('Cannot pass "'+_embind_repr(handle)+'" as a '+this.name)}if(!handle.$$.ptr){throwBindingError("Cannot pass deleted object as a pointer of type "+this.name)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}function genericPointerToWireType(destructors,handle){var ptr;if(handle===null){if(this.isReference){throwBindingError("null is not a valid "+this.name)}if(this.isSmartPointer){ptr=this.rawConstructor();if(destructors!==null){destructors.push(this.rawDestructor,ptr)}return ptr}else{return 0}}if(!handle.$$){throwBindingError('Cannot pass "'+_embind_repr(handle)+'" as a '+this.name)}if(!handle.$$.ptr){throwBindingError("Cannot pass deleted object as a pointer of type "+this.name)}if(!this.isConst&&handle.$$.ptrType.isConst){throwBindingError("Cannot convert argument of type "+(handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name)+" to parameter type "+this.name)}var handleClass=handle.$$.ptrType.registeredClass;ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);if(this.isSmartPointer){if(undefined===handle.$$.smartPtr){throwBindingError("Passing raw pointer to smart pointer is illegal")}switch(this.sharingPolicy){case 0:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{throwBindingError("Cannot convert argument of type "+(handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name)+" to parameter type "+this.name)}break;case 1:ptr=handle.$$.smartPtr;break;case 2:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{var clonedHandle=handle["clone"]();ptr=this.rawShare(ptr,__emval_register(function(){clonedHandle["delete"]()}));if(destructors!==null){destructors.push(this.rawDestructor,ptr)}}break;default:throwBindingError("Unsupporting sharing policy")}}return ptr}function nonConstNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError("null is not a valid "+this.name)}return 0}if(!handle.$$){throwBindingError('Cannot pass "'+_embind_repr(handle)+'" as a '+this.name)}if(!handle.$$.ptr){throwBindingError("Cannot pass deleted object as a pointer of type "+this.name)}if(handle.$$.ptrType.isConst){throwBindingError("Cannot convert argument of type "+handle.$$.ptrType.name+" to parameter type "+this.name)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}function simpleReadValueFromPointer(pointer){return this["fromWireType"](HEAPU32[pointer>>2])}function RegisteredPointer_getPointee(ptr){if(this.rawGetPointee){ptr=this.rawGetPointee(ptr)}return ptr}function RegisteredPointer_destructor(ptr){if(this.rawDestructor){this.rawDestructor(ptr)}}function RegisteredPointer_deleteObject(handle){if(handle!==null){handle["delete"]()}}function downcastPointer(ptr,ptrClass,desiredClass){if(ptrClass===desiredClass){return ptr}if(undefined===desiredClass.baseClass){return null}var rv=downcastPointer(ptr,ptrClass,desiredClass.baseClass);if(rv===null){return null}return desiredClass.downcast(rv)}function getInheritedInstanceCount(){return Object.keys(registeredInstances).length}function getLiveInheritedInstances(){var rv=[];for(var k in registeredInstances){if(registeredInstances.hasOwnProperty(k)){rv.push(registeredInstances[k])}}return rv}function setDelayFunction(fn){delayFunction=fn;if(deletionQueue.length&&delayFunction){delayFunction(flushPendingDeletes)}}function init_embind(){Module["getInheritedInstanceCount"]=getInheritedInstanceCount;Module["getLiveInheritedInstances"]=getLiveInheritedInstances;Module["flushPendingDeletes"]=flushPendingDeletes;Module["setDelayFunction"]=setDelayFunction}var registeredInstances={};function getBasestPointer(class_,ptr){if(ptr===undefined){throwBindingError("ptr should not be undefined")}while(class_.baseClass){ptr=class_.upcast(ptr);class_=class_.baseClass}return ptr}function getInheritedInstance(class_,ptr){ptr=getBasestPointer(class_,ptr);return registeredInstances[ptr]}function makeClassHandle(prototype,record){if(!record.ptrType||!record.ptr){throwInternalError("makeClassHandle requires ptr and ptrType")}var hasSmartPtrType=!!record.smartPtrType;var hasSmartPtr=!!record.smartPtr;if(hasSmartPtrType!==hasSmartPtr){throwInternalError("Both smartPtrType and smartPtr must be specified")}record.count={value:1};return attachFinalizer(Object.create(prototype,{$$:{value:record}}))}function RegisteredPointer_fromWireType(ptr){var rawPointer=this.getPointee(ptr);if(!rawPointer){this.destructor(ptr);return null}var registeredInstance=getInheritedInstance(this.registeredClass,rawPointer);if(undefined!==registeredInstance){if(0===registeredInstance.$$.count.value){registeredInstance.$$.ptr=rawPointer;registeredInstance.$$.smartPtr=ptr;return registeredInstance["clone"]()}else{var rv=registeredInstance["clone"]();this.destructor(ptr);return rv}}function makeDefaultHandle(){if(this.isSmartPointer){return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this.pointeeType,ptr:rawPointer,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this,ptr:ptr})}}var actualType=this.registeredClass.getActualType(rawPointer);var registeredPointerRecord=registeredPointers[actualType];if(!registeredPointerRecord){return makeDefaultHandle.call(this)}var toType;if(this.isConst){toType=registeredPointerRecord.constPointerType}else{toType=registeredPointerRecord.pointerType}var dp=downcastPointer(rawPointer,this.registeredClass,toType.registeredClass);if(dp===null){return makeDefaultHandle.call(this)}if(this.isSmartPointer){return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp})}}function init_RegisteredPointer(){RegisteredPointer.prototype.getPointee=RegisteredPointer_getPointee;RegisteredPointer.prototype.destructor=RegisteredPointer_destructor;RegisteredPointer.prototype["argPackAdvance"]=8;RegisteredPointer.prototype["readValueFromPointer"]=simpleReadValueFromPointer;RegisteredPointer.prototype["deleteObject"]=RegisteredPointer_deleteObject;RegisteredPointer.prototype["fromWireType"]=RegisteredPointer_fromWireType}function RegisteredPointer(name,registeredClass,isReference,isConst,isSmartPointer,pointeeType,sharingPolicy,rawGetPointee,rawConstructor,rawShare,rawDestructor){this.name=name;this.registeredClass=registeredClass;this.isReference=isReference;this.isConst=isConst;this.isSmartPointer=isSmartPointer;this.pointeeType=pointeeType;this.sharingPolicy=sharingPolicy;this.rawGetPointee=rawGetPointee;this.rawConstructor=rawConstructor;this.rawShare=rawShare;this.rawDestructor=rawDestructor;if(!isSmartPointer&®isteredClass.baseClass===undefined){if(isConst){this["toWireType"]=constNoSmartPtrRawPointerToWireType;this.destructorFunction=null}else{this["toWireType"]=nonConstNoSmartPtrRawPointerToWireType;this.destructorFunction=null}}else{this["toWireType"]=genericPointerToWireType}}function replacePublicSymbol(name,value,numArguments){if(!Module.hasOwnProperty(name)){throwInternalError("Replacing nonexistant public symbol")}if(undefined!==Module[name].overloadTable&&undefined!==numArguments){Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}}function dynCallLegacy(sig,ptr,args){if(args&&args.length){return Module["dynCall_"+sig].apply(null,[ptr].concat(args))}return Module["dynCall_"+sig].call(null,ptr)}function dynCall(sig,ptr,args){if(sig.indexOf("j")!=-1){return dynCallLegacy(sig,ptr,args)}return wasmTable.get(ptr).apply(null,args)}function getDynCaller(sig,ptr){assert(sig.indexOf("j")>=0,"getDynCaller should only be called with i64 sigs");var argCache=[];return function(){argCache.length=arguments.length;for(var i=0;i>2)+i])}return array}function runDestructors(destructors){while(destructors.length){var ptr=destructors.pop();var del=destructors.pop();del(ptr)}}function __embind_register_class_constructor(rawClassType,argCount,rawArgTypesAddr,invokerSignature,invoker,rawConstructor){assert(argCount>0);var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);invoker=embind__requireFunction(invokerSignature,invoker);var args=[rawConstructor];var destructors=[];whenDependentTypesAreResolved([],[rawClassType],function(classType){classType=classType[0];var humanName="constructor "+classType.name;if(undefined===classType.registeredClass.constructor_body){classType.registeredClass.constructor_body=[]}if(undefined!==classType.registeredClass.constructor_body[argCount-1]){throw new BindingError("Cannot register multiple constructors with identical number of parameters ("+(argCount-1)+") for class '"+classType.name+"'! Overload resolution is currently only performed using the parameter count, not actual type info!")}classType.registeredClass.constructor_body[argCount-1]=function unboundTypeHandler(){throwUnboundTypeError("Cannot construct "+classType.name+" due to unbound types",rawArgTypes)};whenDependentTypesAreResolved([],rawArgTypes,function(argTypes){classType.registeredClass.constructor_body[argCount-1]=function constructor_body(){if(arguments.length!==argCount-1){throwBindingError(humanName+" called with "+arguments.length+" arguments, expected "+(argCount-1))}destructors.length=0;args.length=argCount;for(var i=1;i4&&0===--emval_handle_array[handle].refcount){emval_handle_array[handle]=undefined;emval_free_list.push(handle)}}function count_emval_handles(){var count=0;for(var i=5;i>1])};case 2:return function(pointer){var heap=signed?HEAP32:HEAPU32;return this["fromWireType"](heap[pointer>>2])};default:throw new TypeError("Unknown integer type: "+name)}}function __embind_register_enum(rawType,name,size,isSigned){var shift=getShiftFromSize(size);name=readLatin1String(name);function ctor(){}ctor.values={};registerType(rawType,{name:name,constructor:ctor,"fromWireType":function(c){return this.constructor.values[c]},"toWireType":function(destructors,c){return c.value},"argPackAdvance":8,"readValueFromPointer":enumReadValueFromPointer(name,shift,isSigned),destructorFunction:null});exposePublicSymbol(name,ctor)}function requireRegisteredType(rawType,humanName){var impl=registeredTypes[rawType];if(undefined===impl){throwBindingError(humanName+" has unknown type "+getTypeName(rawType))}return impl}function __embind_register_enum_value(rawEnumType,name,enumValue){var enumType=requireRegisteredType(rawEnumType,"enum");name=readLatin1String(name);var Enum=enumType.constructor;var Value=Object.create(enumType.constructor.prototype,{value:{value:enumValue},constructor:{value:createNamedFunction(enumType.name+"_"+name,function(){})}});Enum.values[enumValue]=Value;Enum[name]=Value}function _embind_repr(v){if(v===null){return"null"}var t=typeof v;if(t==="object"||t==="array"||t==="function"){return v.toString()}else{return""+v}}function floatReadValueFromPointer(name,shift){switch(shift){case 2:return function(pointer){return this["fromWireType"](HEAPF32[pointer>>2])};case 3:return function(pointer){return this["fromWireType"](HEAPF64[pointer>>3])};default:throw new TypeError("Unknown float type: "+name)}}function __embind_register_float(rawType,name,size){var shift=getShiftFromSize(size);name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":function(value){return value},"toWireType":function(destructors,value){if(typeof value!=="number"&&typeof value!=="boolean"){throw new TypeError('Cannot convert "'+_embind_repr(value)+'" to '+this.name)}return value},"argPackAdvance":8,"readValueFromPointer":floatReadValueFromPointer(name,shift),destructorFunction:null})}function new_(constructor,argumentList){if(!(constructor instanceof Function)){throw new TypeError("new_ called with constructor type "+typeof constructor+" which is not a function")}var dummy=createNamedFunction(constructor.name||"unknownFunctionName",function(){});dummy.prototype=constructor.prototype;var obj=new dummy;var r=constructor.apply(obj,argumentList);return r instanceof Object?r:obj}function craftInvokerFunction(humanName,argTypes,classType,cppInvokerFunc,cppTargetFunc){var argCount=argTypes.length;if(argCount<2){throwBindingError("argTypes array size mismatch! Must at least get return value and 'this' types!")}var isClassMethodFunc=argTypes[1]!==null&&classType!==null;var needsDestructorStack=false;for(var i=1;i0?", ":"")+argsListWired}invokerFnBody+=(returns?"var rv = ":"")+"invoker(fn"+(argsListWired.length>0?", ":"")+argsListWired+");\n";if(needsDestructorStack){invokerFnBody+="runDestructors(destructors);\n"}else{for(var i=isClassMethodFunc?1:2;i>1]}:function readU16FromPointer(pointer){return HEAPU16[pointer>>1]};case 2:return signed?function readS32FromPointer(pointer){return HEAP32[pointer>>2]}:function readU32FromPointer(pointer){return HEAPU32[pointer>>2]};default:throw new TypeError("Unknown integer type: "+name)}}function __embind_register_integer(primitiveType,name,size,minRange,maxRange){name=readLatin1String(name);if(maxRange===-1){maxRange=4294967295}var shift=getShiftFromSize(size);var fromWireType=function(value){return value};if(minRange===0){var bitshift=32-8*size;fromWireType=function(value){return value<>>bitshift}}var isUnsignedType=name.indexOf("unsigned")!=-1;registerType(primitiveType,{name:name,"fromWireType":fromWireType,"toWireType":function(destructors,value){if(typeof value!=="number"&&typeof value!=="boolean"){throw new TypeError('Cannot convert "'+_embind_repr(value)+'" to '+this.name)}if(valuemaxRange){throw new TypeError('Passing a number "'+_embind_repr(value)+'" from JS side to C/C++ side to an argument of type "'+name+'", which is outside the valid range ['+minRange+", "+maxRange+"]!")}return isUnsignedType?value>>>0:value|0},"argPackAdvance":8,"readValueFromPointer":integerReadValueFromPointer(name,shift,minRange!==0),destructorFunction:null})}function __embind_register_memory_view(rawType,dataTypeIndex,name){var typeMapping=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array];var TA=typeMapping[dataTypeIndex];function decodeMemoryView(handle){handle=handle>>2;var heap=HEAPU32;var size=heap[handle];var data=heap[handle+1];return new TA(buffer,data,size)}name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":decodeMemoryView,"argPackAdvance":8,"readValueFromPointer":decodeMemoryView},{ignoreDuplicateRegistrations:true})}function __embind_register_std_string(rawType,name){name=readLatin1String(name);var stdStringIsUTF8=name==="std::string";registerType(rawType,{name:name,"fromWireType":function(value){var length=HEAPU32[value>>2];var str;if(stdStringIsUTF8){var decodeStartPtr=value+4;for(var i=0;i<=length;++i){var currentBytePtr=value+4+i;if(i==length||HEAPU8[currentBytePtr]==0){var maxRead=currentBytePtr-decodeStartPtr;var stringSegment=UTF8ToString(decodeStartPtr,maxRead);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+1}}}else{var a=new Array(length);for(var i=0;i>2]=length;if(stdStringIsUTF8&&valueIsOfTypeString){stringToUTF8(value,ptr+4,length+1)}else{if(valueIsOfTypeString){for(var i=0;i255){_free(ptr);throwBindingError("String has UTF-16 code units that do not fit in 8 bits")}HEAPU8[ptr+4+i]=charCode}}else{for(var i=0;i>2];var HEAP=getHeap();var str;var decodeStartPtr=value+4;for(var i=0;i<=length;++i){var currentBytePtr=value+4+i*charSize;if(i==length||HEAP[currentBytePtr>>shift]==0){var maxReadBytes=currentBytePtr-decodeStartPtr;var stringSegment=decodeString(decodeStartPtr,maxReadBytes);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+charSize}}_free(value);return str},"toWireType":function(destructors,value){if(!(typeof value==="string")){throwBindingError("Cannot pass non-string to C++ string type "+name)}var length=lengthBytesUTF(value);var ptr=_malloc(4+length+charSize);HEAPU32[ptr>>2]=length>>shift;encodeString(value,ptr+4,length+charSize);if(destructors!==null){destructors.push(_free,ptr)}return ptr},"argPackAdvance":8,"readValueFromPointer":simpleReadValueFromPointer,destructorFunction:function(ptr){_free(ptr)}})}function __embind_register_void(rawType,name){name=readLatin1String(name);registerType(rawType,{isVoid:true,name:name,"argPackAdvance":0,"fromWireType":function(){return undefined},"toWireType":function(destructors,o){return undefined}})}function __emval_incref(handle){if(handle>4){emval_handle_array[handle].refcount+=1}}function __emval_take_value(type,argv){type=requireRegisteredType(type,"_emval_take_value");var v=type["readValueFromPointer"](argv);return __emval_register(v)}function _abort(){abort()}var _emscripten_get_now;if(ENVIRONMENT_IS_NODE){_emscripten_get_now=function(){var t=process["hrtime"]();return t[0]*1e3+t[1]/1e6}}else if(typeof dateNow!=="undefined"){_emscripten_get_now=dateNow}else _emscripten_get_now=function(){return performance.now()};var _emscripten_get_now_is_monotonic=true;function setErrNo(value){HEAP32[___errno_location()>>2]=value;return value}function _clock_gettime(clk_id,tp){var now;if(clk_id===0){now=Date.now()}else if((clk_id===1||clk_id===4)&&_emscripten_get_now_is_monotonic){now=_emscripten_get_now()}else{setErrNo(28);return-1}HEAP32[tp>>2]=now/1e3|0;HEAP32[tp+4>>2]=now%1e3*1e3*1e3|0;return 0}function _emscripten_memcpy_big(dest,src,num){HEAPU8.copyWithin(dest,src,src+num)}function _emscripten_get_heap_size(){return HEAPU8.length}function emscripten_realloc_buffer(size){try{wasmMemory.grow(size-buffer.byteLength+65535>>>16);updateGlobalBufferAndViews(wasmMemory.buffer);return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){requestedSize=requestedSize>>>0;var oldSize=_emscripten_get_heap_size();var maxHeapSize=2147483648;if(requestedSize>maxHeapSize){return false}var minHeapSize=16777216;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(minHeapSize,requestedSize,overGrownHeapSize),65536));var replacement=emscripten_realloc_buffer(newSize);if(replacement){return true}}return false}var SYSCALLS={mappings:{},buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0}else{buffer.push(curr)}},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){return low}};function _fd_close(fd){return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){}function _fd_write(fd,iov,iovcnt,pnum){var num=0;for(var i=0;i>2];var len=HEAP32[iov+(i*8+4)>>2];for(var j=0;j>2]=num;return 0}function _setTempRet0($i){setTempRet0($i|0)}function _time(ptr){var ret=Date.now()/1e3|0;if(ptr){HEAP32[ptr>>2]=ret}return ret}embind_init_charCodes();BindingError=Module["BindingError"]=extendError(Error,"BindingError");InternalError=Module["InternalError"]=extendError(Error,"InternalError");init_ClassHandle();init_RegisteredPointer();init_embind();UnboundTypeError=Module["UnboundTypeError"]=extendError(Error,"UnboundTypeError");init_emval();var ASSERTIONS=false;function intArrayToString(array){var ret=[];for(var i=0;i255){if(ASSERTIONS){assert(false,"Character code "+chr+" ("+String.fromCharCode(chr)+") at offset "+i+" not in 0x00-0xFF.")}chr&=255}ret.push(String.fromCharCode(chr))}return ret.join("")}var decodeBase64=typeof atob==="function"?atob:function(input){var keyStr="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";var output="";var chr1,chr2,chr3;var enc1,enc2,enc3,enc4;var i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,"");do{enc1=keyStr.indexOf(input.charAt(i++));enc2=keyStr.indexOf(input.charAt(i++));enc3=keyStr.indexOf(input.charAt(i++));enc4=keyStr.indexOf(input.charAt(i++));chr1=enc1<<2|enc2>>4;chr2=(enc2&15)<<4|enc3>>2;chr3=(enc3&3)<<6|enc4;output=output+String.fromCharCode(chr1);if(enc3!==64){output=output+String.fromCharCode(chr2)}if(enc4!==64){output=output+String.fromCharCode(chr3)}}while(i0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();readyPromiseResolve(Module);if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}Module["run"]=run;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}noExitRuntime=true;run(); return ggwave_factory.ready diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 1a44b4b..51e9377 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -84,6 +84,10 @@ else() add_subdirectory(ggwave-to-file) endif() +if (UNIX AND NOT APPLE) + add_subdirectory(r2t2) +endif() + if (GGWAVE_SUPPORT_SDL2) if (EMSCRIPTEN) # emscripten sdl2 examples diff --git a/examples/ggwave-cli/main.cpp b/examples/ggwave-cli/main.cpp index 9be6e68..1b097a2 100644 --- a/examples/ggwave-cli/main.cpp +++ b/examples/ggwave-cli/main.cpp @@ -24,7 +24,7 @@ int main(int argc, char** argv) { auto argm = parseCmdArguments(argc, argv); int captureId = argm["c"].empty() ? 0 : std::stoi(argm["c"]); int playbackId = argm["p"].empty() ? 0 : std::stoi(argm["p"]); - int txProtocol = argm["t"].empty() ? 1 : std::stoi(argm["t"]); + int txProtocolId = argm["t"].empty() ? 1 : std::stoi(argm["t"]); int payloadLength = argm["l"].empty() ? -1 : std::stoi(argm["l"]); bool printTones = argm.find("v") == argm.end() ? false : true; @@ -41,12 +41,12 @@ int main(int argc, char** argv) { printf(" -t%d : %s\n", protocol.first, protocol.second.name); } - if (txProtocol < 0 || txProtocol > (int) ggWave->getTxProtocols().size()) { - fprintf(stderr, "Unknown Tx protocol %d\n", txProtocol); + if (txProtocolId < 0 || txProtocolId > (int) ggWave->getTxProtocols().size()) { + fprintf(stderr, "Unknown Tx protocol %d\n", txProtocolId); return -3; } - printf("Selecting Tx protocol %d\n", txProtocol); + printf("Selecting Tx protocol %d\n", txProtocolId); std::mutex mutex; std::thread inputThread([&]() { @@ -76,7 +76,7 @@ int main(int argc, char** argv) { } { std::lock_guard lock(mutex); - ggWave->init(input.size(), input.data(), ggWave->getTxProtocol(txProtocol), 10); + ggWave->init(input.size(), input.data(), ggWave->getTxProtocol(txProtocolId), 10); } inputOld = input; } diff --git a/examples/ggwave-common-sdl2.cpp b/examples/ggwave-common-sdl2.cpp index 458c16d..8b0884e 100644 --- a/examples/ggwave-common-sdl2.cpp +++ b/examples/ggwave-common-sdl2.cpp @@ -169,7 +169,7 @@ bool GGWave_init( SDL_zero(g_obtainedSpecInp); if (captureId >= 0) { - printf("Attempt to open capture device %d : '%s' ...\n", captureId, SDL_GetAudioDeviceName(captureId, SDL_FALSE)); + printf("Attempt to open capture device %d : '%s' ...\n", captureId, SDL_GetAudioDeviceName(captureId, SDL_TRUE)); g_devIdInp = SDL_OpenAudioDevice(SDL_GetAudioDeviceName(captureId, SDL_TRUE), SDL_TRUE, &captureSpec, &g_obtainedSpecInp, 0); } else { printf("Attempt to open default capture device ...\n"); @@ -254,6 +254,7 @@ bool GGWave_mainLoop() { if (::getTime_ms(tLastNoData, tNow) > 500.0f) { g_ggWave->decode(cbWaveformInp); if ((int) SDL_GetQueuedAudioSize(g_devIdInp) > 32*g_ggWave->getSamplesPerFrame()*g_ggWave->getSampleSizeBytesInp()) { + fprintf(stderr, "Warning: slow processing, clearing queued audio buffer of %d bytes ...", SDL_GetQueuedAudioSize(g_devIdInp)); SDL_ClearQueuedAudio(g_devIdInp); } } else { diff --git a/examples/ggwave-rx/CMakeLists.txt b/examples/ggwave-rx/CMakeLists.txt index 562a228..dc4998a 100644 --- a/examples/ggwave-rx/CMakeLists.txt +++ b/examples/ggwave-rx/CMakeLists.txt @@ -11,5 +11,4 @@ target_link_libraries(${TARGET} PRIVATE ggwave ggwave-common ggwave-common-sdl2 - ${CMAKE_THREAD_LIBS_INIT} ) diff --git a/examples/ggwave-wasm/index-tmpl.html b/examples/ggwave-wasm/index-tmpl.html index 1bec239..977d612 100644 --- a/examples/ggwave-wasm/index-tmpl.html +++ b/examples/ggwave-wasm/index-tmpl.html @@ -158,7 +158,7 @@ var isiOS = /iPad|iPhone|iPod|CriOS/.test(navigator.userAgent) && !window.MSStream; var isInitialized = false; - var isAudioContextUnlocked = !isiOS; + var isAudioContextUnlocked = true; var htmlGreenLED = "
"; var htmlRedLED = "
"; @@ -193,7 +193,7 @@ } } - var isBrowserSupported = !isiOS; + var isBrowserSupported = true; { var el = document.getElementById('is-browser-supported'); if (isBrowserSupported) { @@ -229,7 +229,7 @@ postRun: [ (function() { document.getElementById("butInit").disabled = false; }) ], print: (function() { var element = document.getElementById('output'); - if (element) element.alue = ''; // clear browser cache + if (element) element.value = ''; // clear browser cache return function(text) { if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' '); console.log(text); @@ -293,7 +293,7 @@ Module.setStatus('Initializing...'); window.onerror = function(event) { - Module.setStatus('Exception thrown, see JavaScript console'); + Module.setStatus('Exception thrown: ' + JSON.stringify(event)); spinnerElement.style.display = 'none'; Module.setStatus = function(text) { if (text) Module.printErr('[post-exception status] ' + text); @@ -301,22 +301,22 @@ }; window.addEventListener('touchstart', function() { - if (isAudioContextUnlocked == false && SDL2.audioContext) { - var buffer = SDL2.audioContext.createBuffer(1, 1, 22050); - var source = SDL2.audioContext.createBufferSource(); - source.buffer = buffer; - source.connect(SDL2.audioContext.destination); - source.start(); + //if (isAudioContextUnlocked == false && SDL2.audioContext) { + // var buffer = SDL2.audioContext.createBuffer(1, 1, 22050); + // var source = SDL2.audioContext.createBufferSource(); + // source.buffer = buffer; + // source.connect(SDL2.audioContext.destination); + // source.start(); - setTimeout(function() { - if((source.playbackState === source.PLAYING_STATE || source.playbackState === source.FINISHED_STATE)) { - isAudioContextUnlocked = true; - Module.setStatus('Wab Audio API unlocked successfully!'); - } else { - Module.setStatus('Failed to unlock Web Audio APIi. This browser seems to not be supported'); - } - }, 0); - } + // setTimeout(function() { + // if((source.playbackState === source.PLAYING_STATE || source.playbackState === source.FINISHED_STATE)) { + // isAudioContextUnlocked = true; + // Module.setStatus('Wab Audio API unlocked successfully!'); + // } else { + // Module.setStatus('Failed to unlock Web Audio APIi. This browser seems to not be supported'); + // } + // }, 0); + //} }, false); function playSound(filename){ diff --git a/examples/r2t2/CMakeLists.txt b/examples/r2t2/CMakeLists.txt new file mode 100644 index 0000000..df64459 --- /dev/null +++ b/examples/r2t2/CMakeLists.txt @@ -0,0 +1,71 @@ +# +# r2t2 + +set(TARGET r2t2) + +if (NOT EMSCRIPTEN) + add_executable(${TARGET} + main.cpp + ggwave-mod/src/ggwave.cpp + ggwave-mod/src/resampler.cpp + ) + + target_include_directories(${TARGET} PRIVATE + .. + ggwave-mod/include + ggwave-mod/src + ) + + target_link_libraries(${TARGET} PRIVATE + ggwave-common + ) +endif() + +# +# r2t2-rx + +set(TARGET r2t2-rx) + +if (NOT EMSCRIPTEN) + add_executable(${TARGET} + r2t2-rx.cpp + ggwave-mod/src/ggwave.cpp + ggwave-mod/src/resampler.cpp + ) + + target_include_directories(${TARGET} PRIVATE + .. + ggwave-mod/include + ggwave-mod/src + ${SDL2_INCLUDE_DIRS} + ) + + target_link_libraries(${TARGET} PRIVATE + ggwave-common + ${SDL2_LIBRARIES} + ) +else() + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/build_timestamp-tmpl.h ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TARGET}/build_timestamp.h @ONLY) + + add_executable(${TARGET} + r2t2-rx.cpp + ggwave-mod/src/ggwave.cpp + ggwave-mod/src/resampler.cpp + ) + + target_include_directories(${TARGET} PRIVATE + .. + ggwave-mod/include + ggwave-mod/src + ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TARGET}/ + ) + + target_link_libraries(${TARGET} PRIVATE + ggwave-common + ) + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/index-tmpl.html ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TARGET}/index.html @ONLY) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/style.css ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TARGET}/style.css COPYONLY) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/main.js ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TARGET}/main.js COPYONLY) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/plucky.mp3 ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TARGET}/plucky.mp3 COPYONLY) +endif() diff --git a/examples/r2t2/README.md b/examples/r2t2/README.md new file mode 100644 index 0000000..0e9615d --- /dev/null +++ b/examples/r2t2/README.md @@ -0,0 +1,58 @@ +# r2t2 + +Transmit data with the PC speaker + + + +This is a command-line program that encodes short messages/data into audio and plays it via the motherboard's PC speaker. To use this tool, you need to attach a [piezo speaker/buzzer](https://en.wikipedia.org/wiki/Piezoelectric_speaker) to your motherboard. Some computers have such speaker already attached. + +You can then run the following command: + +```bash +echo test | sudo r2t2 +``` + +This will transmit the message `test` via sound through the buzzer. + +To receive the transmitted message, open the following page on your phone and place it near the speaker: + +https://r2t2.ggerganov.com + +## Applications + +This tool can be useful when you need to transmit data from air-gapped machines. The hardware requirements are very low-cost - you only need a PC speaker. Automated scripts can be configured to periodically emit some data about the machine, which can be received by someone nearby running the `r2t2` receiver application. + +## Requirements + +- [PC speaker / buzzer](https://www.amazon.com/SoundOriginal-Motherboard-Internal-Speaker-Buzzer/dp/B01DM56TFY/ref=sr_1_1_sspa?dchild=1&keywords=Motherboard+Speaker&qid=1614504288&sr=8-1-spons&psc=1&spLa=ZW5jcnlwdGVkUXVhbGlmaWVyPUEzTkpFVlk4SzRXS1lWJmVuY3J5cHRlZElkPUEwOTU3NzI3MkpCQUZJRFIxSzZGNSZlbmNyeXB0ZWRBZElkPUEwODk0ODQ4MlVBQzFSR1RHMTYyMiZ3aWRnZXROYW1lPXNwX2F0ZiZhY3Rpb249Y2xpY2tSZWRpcmVjdCZkb05vdExvZ0NsaWNrPXRydWU=) attached to the motherboard. + + Here are the ones that I use: + +

+ + + + + +
+ Talking buttons + + Talking buttons +
+

+

+ Img. Left: PC speaker plugged into a motherboard. Right: two PC speakers with a coin for size comparison +

+ +- Unix operating system +- The program requires to run as `sudo` in order to access the PC speaker + +## Build + +```bash +git clone https://github.com/ggerganov/ggwave --recursive +cd ggwave +mkdir build && cd build +make +./bin/r2t2 +``` diff --git a/examples/r2t2/build_timestamp-tmpl.h b/examples/r2t2/build_timestamp-tmpl.h new file mode 100644 index 0000000..63cb816 --- /dev/null +++ b/examples/r2t2/build_timestamp-tmpl.h @@ -0,0 +1 @@ +static const char * BUILD_TIMESTAMP="@GIT_DATE@ (@GIT_SHA1@)"; diff --git a/examples/r2t2/ggwave-mod/include/ggwave/ggwave.h b/examples/r2t2/ggwave-mod/include/ggwave/ggwave.h new file mode 100644 index 0000000..5753993 --- /dev/null +++ b/examples/r2t2/ggwave-mod/include/ggwave/ggwave.h @@ -0,0 +1,511 @@ +#ifndef GGWAVE_H +#define GGWAVE_H + +#ifdef GGWAVE_SHARED +# ifdef _WIN32 +# ifdef GGWAVE_BUILD +# define GGWAVE_API __declspec(dllexport) +# else +# define GGWAVE_API __declspec(dllimport) +# endif +# else +# define GGWAVE_API __attribute__ ((visibility ("default"))) +# endif +#else +# define GGWAVE_API +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + // + // C interface + // + + // Data format of the audio samples + typedef enum { + GGWAVE_SAMPLE_FORMAT_UNDEFINED, + GGWAVE_SAMPLE_FORMAT_U8, + GGWAVE_SAMPLE_FORMAT_I8, + GGWAVE_SAMPLE_FORMAT_U16, + GGWAVE_SAMPLE_FORMAT_I16, + GGWAVE_SAMPLE_FORMAT_F32, + } ggwave_SampleFormat; + + // TxProtocol ids + typedef enum { + GGWAVE_TX_PROTOCOL_AUDIBLE_NORMAL, + GGWAVE_TX_PROTOCOL_AUDIBLE_FAST, + GGWAVE_TX_PROTOCOL_AUDIBLE_FASTEST, + GGWAVE_TX_PROTOCOL_ULTRASOUND_NORMAL, + GGWAVE_TX_PROTOCOL_ULTRASOUND_FAST, + GGWAVE_TX_PROTOCOL_ULTRASOUND_FASTEST, + GGWAVE_TX_PROTOCOL_DT_NORMAL, + GGWAVE_TX_PROTOCOL_DT_FAST, + GGWAVE_TX_PROTOCOL_DT_FASTEST, + + GGWAVE_TX_PROTOCOL_CUSTOM_0, + GGWAVE_TX_PROTOCOL_CUSTOM_1, + GGWAVE_TX_PROTOCOL_CUSTOM_2, + GGWAVE_TX_PROTOCOL_CUSTOM_3, + GGWAVE_TX_PROTOCOL_CUSTOM_4, + GGWAVE_TX_PROTOCOL_CUSTOM_5, + GGWAVE_TX_PROTOCOL_CUSTOM_6, + GGWAVE_TX_PROTOCOL_CUSTOM_7, + GGWAVE_TX_PROTOCOL_CUSTOM_8, + GGWAVE_TX_PROTOCOL_CUSTOM_9, + } ggwave_TxProtocolId; + + // GGWave instance parameters + // + // If payloadLength <= 0, then GGWave will transmit with variable payload length + // depending on the provided payload. Sound markers are used to identify the + // start and end of the transmission. + // + // If payloadLength > 0, then the transmitted payload will be of the specified + // fixed length. In this case, no sound markers are emitted and a slightly + // different decoding scheme is applied. This is useful in cases where the + // length of the payload is known in advance. + // + // The sample rates are values typically between 8000 and 96000. + // Default value: GGWave::kBaseSampleRate + // + // The samplesPerFrame is the number of samples on which ggwave performs FFT. + // This affects the number of bins in the Fourier spectrum. + // Default value: GGWave::kDefaultSamplesPerFrame + // + typedef struct { + int payloadLength; // payload length + float sampleRateInp; // capture sample rate + float sampleRateOut; // playback sample rate + int samplesPerFrame; // number of samples per audio frame + float soundMarkerThreshold; // sound marker detection threshold + ggwave_SampleFormat sampleFormatInp; // format of the captured audio samples + ggwave_SampleFormat sampleFormatOut; // format of the playback audio samples + } ggwave_Parameters; + + // GGWave instances are identified with an integer and are stored + // in a private map container. Using void * caused some issues with + // the python module and unfortunately had to do it this way + typedef int ggwave_Instance; + + // Helper method to get default instance parameters + GGWAVE_API ggwave_Parameters ggwave_getDefaultParameters(void); + + // Create a new GGWave instance with the specified parameters + // + // The newly created instance is added to the internal map container. + // This function returns an id that can be used to identify this instance. + // Make sure to deallocate the instance at the end by calling ggwave_free() + // + GGWAVE_API ggwave_Instance ggwave_init(const ggwave_Parameters parameters); + + // Free a GGWave instance + GGWAVE_API void ggwave_free(ggwave_Instance instance); + + // Encode data into audio waveform + // + // instance - the GGWave instance to use + // dataBuffer - the data to encode + // dataSize - number of bytes in the input dataBuffer + // txProtocolId - the protocol to use for encoding + // volume - the volume of the generated waveform [0, 100] + // usually 25 is OK and you should not go over 50 + // outputBuffer - the generated audio waveform. must be big enough to fit the generated data + // query - if != 0, do not perform encoding. + // if == 1, return waveform size in bytes + // if != 1, return waveform size in samples + // + // returns the number of generated bytes or samples (see query) + // + // returns -1 if there was an error + // + // This function can be used to encode some binary data (payload) into an audio waveform. + // + // payload -> waveform + // + // When calling it, make sure that the outputBuffer is big enough to store the + // generated waveform. This means that its size must be at least: + // + // nSamples*sizeOfSample_bytes + // + // Where nSamples is the number of audio samples in the waveform and sizeOfSample_bytes + // is the size of a single sample in bytes based on the sampleFormatOut parameter + // specified during the initialization of the GGWave instance. + // + // If query != 0, then this function does not perform the actual encoding and just + // outputs the expected size of the waveform that would be generated if you call it + // with query == 0. This mechanism can be used to ask ggwave how much memory to + // allocate for the outputBuffer. For example: + // + // // this is the data to encode + // const char * payload = "test"; + // + // // query the number of bytes in the waveform + // int n = ggwave_encode(instance, payload, 4, GGWAVE_TX_PROTOCOL_AUDIBLE_FAST, 25, NULL, 1); + // + // // allocate the output buffer + // char waveform[n]; + // + // // generate the waveform + // ggwave_encode(instance, payload, 4, GGWAVE_TX_PROTOCOL_AUDIBLE_FAST, 25, waveform, 0); + // + // The dataBuffer can be any binary data that you would like to transmit (i.e. the payload). + // Usually, this is some text, but it can be any sequence of bytes. + // + // todo: + // - change the type of dataBuffer to const void * + // - change the type of outputBuffer to void * + // - rename dataBuffer to payloadBuffer + // - rename dataSize to payloadSize + // - rename outputBuffer to waveformBuffer + // + GGWAVE_API int ggwave_encode( + ggwave_Instance instance, + const char * dataBuffer, + int dataSize, + ggwave_TxProtocolId txProtocolId, + int volume, + char * outputBuffer, + int query); + + // Decode an audio waveform into data + // + // instance - the GGWave instance to use + // dataBuffer - the audio waveform + // dataSize - number of bytes in the input dataBuffer + // outputBuffer - stores the decoded data on success + // the maximum size of the output is GGWave::kMaxDataSize + // + // returns the number of decoded bytes + // + // Use this function to continuously provide audio samples to a GGWave instance. + // On each call, GGWave will analyze the provided data and if it detects a payload, + // it will return a non-zero result. + // + // waveform -> payload + // + // If the return value is -1 then there was an error during the decoding process. + // Usually can occur if there is a lot of background noise in the audio. + // + // If the return value is greater than 0, then there will be that number of bytes + // decoded in the outputBuffer + // + // Example: + // + // char payload[256]; + // + // while (true) { + // ... capture samplesPerFrame audio samples into waveform ... + // + // int ret = ggwave_decode(instance, waveform, samplesPerFrame*sizeOfSample_bytes, payload); + // if (ret > 0) { + // printf("Received payload: '%s'\n", payload); + // } + // } + // + // todo: + // - change the type of dataBuffer to const void * + // - change the type of outputBuffer to void * + // - rename dataBuffer to waveformBuffer + // - rename dataSize to waveformSize + // - rename outputBuffer to payloadBuffer + // + GGWAVE_API int ggwave_decode( + ggwave_Instance instance, + const char * dataBuffer, + int dataSize, + char * outputBuffer); + +#ifdef __cplusplus +} + +// +// C++ interface +// + +#include +#include +#include +#include +#include +#include + +class GGWave { +public: + static constexpr auto kBaseSampleRate = 48000.0f; + static constexpr auto kSampleRateMin = 6000.0f; + static constexpr auto kSampleRateMax = 96000.0f; + static constexpr auto kDefaultSamplesPerFrame = 1024; + static constexpr auto kDefaultVolume = 10; + static constexpr auto kDefaultSoundMarkerThreshold = 3.0f; + static constexpr auto kDefaultMarkerFrames = 16; + static constexpr auto kDefaultEncodedDataOffset = 3; + static constexpr auto kMaxSamplesPerFrame = 2048; + static constexpr auto kMaxDataBits = 256; + static constexpr auto kMaxDataSize = 256; + static constexpr auto kMaxLengthVarible = 140; + static constexpr auto kMaxLengthFixed = 16; + static constexpr auto kMaxSpectrumHistory = 4; + static constexpr auto kMaxRecordedFrames = 2048; + + using Parameters = ggwave_Parameters; + using SampleFormat = ggwave_SampleFormat; + using TxProtocolId = ggwave_TxProtocolId; + using RxProtocolId = ggwave_TxProtocolId; + + struct TxProtocol { + const char * name; // string identifier of the protocol + + int freqStart; // FFT bin index of the lowest frequency + int framesPerTx; // number of frames to transmit a single chunk of data + int bytesPerTx; // number of bytes in a chunk of data + + int nDataBitsPerTx() const { return 8*bytesPerTx; } + }; + + using RxProtocol = TxProtocol; + + using TxProtocols = std::map; + using RxProtocols = std::map; + + static const TxProtocols & getTxProtocols() { + static const TxProtocols kTxProtocols { + { GGWAVE_TX_PROTOCOL_AUDIBLE_NORMAL, { "Normal", 40, 9, 3, } }, + { GGWAVE_TX_PROTOCOL_AUDIBLE_FAST, { "Fast", 40, 6, 3, } }, + { GGWAVE_TX_PROTOCOL_AUDIBLE_FASTEST, { "Fastest", 40, 3, 3, } }, + { GGWAVE_TX_PROTOCOL_ULTRASOUND_NORMAL, { "[U] Normal", 320, 9, 3, } }, + { GGWAVE_TX_PROTOCOL_ULTRASOUND_FAST, { "[U] Fast", 320, 6, 3, } }, + { GGWAVE_TX_PROTOCOL_ULTRASOUND_FASTEST, { "[U] Fastest", 320, 3, 3, } }, + { GGWAVE_TX_PROTOCOL_DT_NORMAL, { "[DT] Normal", 24, 9, 1, } }, + { GGWAVE_TX_PROTOCOL_DT_FAST, { "[DT] Fast", 24, 6, 1, } }, + { GGWAVE_TX_PROTOCOL_DT_FASTEST, { "[DT] Fastest", 24, 3, 1, } }, + }; + + return kTxProtocols; + } + + struct ToneData { + double freq_hz; + double duration_ms; + }; + + using Tones = std::vector; + using WaveformTones = std::vector; + + using AmplitudeData = std::vector; + using AmplitudeDataI16 = std::vector; + using SpectrumData = std::vector; + using RecordedData = std::vector; + using TxRxData = std::vector; + + using CBWaveformOut = std::function; + using CBWaveformInp = std::function; + + GGWave(const Parameters & parameters); + ~GGWave(); + + static const Parameters & getDefaultParameters(); + + // set Tx data to encode + // + // This prepares the GGWave instance for transmission. + // To perform the actual encoding, the encode() method must be called + // + // returns false upon invalid parameters or failure to initialize + // + bool init(const std::string & text, const int volume = kDefaultVolume); + bool init(const std::string & text, const TxProtocol & txProtocol, const int volume = kDefaultVolume); + bool init(int dataSize, const char * dataBuffer, const int volume = kDefaultVolume); + bool init(int dataSize, const char * dataBuffer, const TxProtocol & txProtocol, const int volume = kDefaultVolume); + + // expected waveform size of the encoded Tx data in bytes + // + // When the output sampling rate is not equal to kBaseSampleRate the result of this method is overestimation of + // the actual number of bytes that would be produced + // + uint32_t encodeSize_bytes() const; + + // expected waveform size of the encoded Tx data in samples + // + // When the output sampling rate is not equal to kBaseSampleRate the result of this method is overestimation of + // the actual number of samples that would be produced + // + uint32_t encodeSize_samples() const; + + // encode Tx data into an audio waveform + // + // The generated waveform is returned by calling the cbWaveformOut callback. + // + // returns false if the encoding fails + // + bool encode(const CBWaveformOut & cbWaveformOut); + + // decode an audio waveform + // + // This methods calls cbWaveformInp multiple times (at least once) until it returns 0. + // Use the Rx methods to check if any data was decoded successfully. + // + void decode(const CBWaveformInp & cbWaveformInp); + + // instance state + const bool & hasTxData() const { return m_hasNewTxData; } + const bool & isReceiving() const { return m_receivingData; } + const bool & isAnalyzing() const { return m_analyzingData; } + + const int & getFramesToRecord() const { return m_framesToRecord; } + const int & getFramesLeftToRecord() const { return m_framesLeftToRecord; } + const int & getFramesToAnalyze() const { return m_framesToAnalyze; } + const int & getFramesLeftToAnalyze() const { return m_framesLeftToAnalyze; } + const int & getSamplesPerFrame() const { return m_samplesPerFrame; } + const int & getSampleSizeBytesInp() const { return m_sampleSizeBytesInp; } + const int & getSampleSizeBytesOut() const { return m_sampleSizeBytesOut; } + + const float & getSampleRateInp() const { return m_sampleRateInp; } + const float & getSampleRateOut() const { return m_sampleRateOut; } + const SampleFormat & getSampleFormatInp() const { return m_sampleFormatInp; } + const SampleFormat & getSampleFormatOut() const { return m_sampleFormatOut; } + + // Tx + + static TxProtocolId getDefaultTxProtocolId() { return GGWAVE_TX_PROTOCOL_AUDIBLE_FAST; } + static const TxProtocol & getDefaultTxProtocol() { return getTxProtocols().at(getDefaultTxProtocolId()); } + static const TxProtocol & getTxProtocol(int id) { return getTxProtocols().at(TxProtocolId(id)); } + static const TxProtocol & getTxProtocol(TxProtocolId id) { return getTxProtocols().at(id); } + + // get a list of the tones generated for the last waveform + // + // Call this method after calling encode() to get a list of the tones participating in the generated waveform + // + const WaveformTones & getWaveformTones() { return m_waveformTones; } + + bool takeTxAmplitudeI16(AmplitudeDataI16 & dst); + + // Rx + + bool stopReceiving(); + void setRxProtocols(const RxProtocols & rxProtocols) { m_rxProtocols = rxProtocols; } + const RxProtocols & getRxProtocols() const { return m_rxProtocols; } + + const TxRxData & getRxData() const { return m_rxData; } + const RxProtocol & getRxProtocol() const { return m_rxProtocol; } + const RxProtocolId & getRxProtocolId() const { return m_rxProtocolId; } + + int takeRxData(TxRxData & dst); + bool takeRxSpectrum(SpectrumData & dst); + bool takeRxAmplitude(AmplitudeData & dst); + + // compute FFT of real values + // + // src - input real-valued data, size is N + // dst - output complex-valued data, size is 2*N + // + // d is scaling factor + // N must be <= kMaxSamplesPerFrame + // + static bool computeFFTR(const float * src, float * dst, int N, float d); + +private: + void decode_fixed(); + void decode_variable(); + + int maxFramesPerTx() const; + int minBytesPerTx() const; + + double bitFreq(const TxProtocol & p, int bit) const { + return m_hzPerSample*p.freqStart + m_freqDelta_hz*bit; + } + + const float m_sampleRateInp; + const float m_sampleRateOut; + const int m_samplesPerFrame; + const float m_isamplesPerFrame; + const int m_sampleSizeBytesInp; + const int m_sampleSizeBytesOut; + const SampleFormat m_sampleFormatInp; + const SampleFormat m_sampleFormatOut; + + const float m_hzPerSample; + const float m_ihzPerSample; + + const int m_freqDelta_bin; + const float m_freqDelta_hz; + + const int m_nBitsInMarker; + const int m_nMarkerFrames; + const int m_encodedDataOffset; + + const float m_soundMarkerThreshold; + + // common + + bool m_isFixedPayloadLength; + int m_payloadLength; + + // Rx + bool m_receivingData; + bool m_analyzingData; + + int m_nMarkersSuccess; + int m_markerFreqStart; + int m_recvDuration_frames; + + int m_framesLeftToAnalyze; + int m_framesLeftToRecord; + int m_framesToAnalyze; + int m_framesToRecord; + int m_samplesNeeded; + + std::vector m_fftInp; // real + std::vector m_fftOut; // complex + + bool m_hasNewSpectrum; + bool m_hasNewAmplitude; + SpectrumData m_sampleSpectrum; + AmplitudeData m_sampleAmplitude; + AmplitudeData m_sampleAmplitudeResampled; + TxRxData m_sampleAmplitudeTmp; + + bool m_hasNewRxData; + int m_lastRxDataLength; + TxRxData m_rxData; + TxProtocol m_rxProtocol; + TxProtocolId m_rxProtocolId; + TxProtocols m_rxProtocols; + + int m_historyId; + AmplitudeData m_sampleAmplitudeAverage; + std::vector m_sampleAmplitudeHistory; + + RecordedData m_recordedAmplitude; + + int m_historyIdFixed; + std::vector m_spectrumHistoryFixed; + + // Tx + bool m_hasNewTxData; + float m_sendVolume; + + int m_txDataLength; + TxRxData m_txData; + TxRxData m_txDataEncoded; + + TxProtocol m_txProtocol; + + AmplitudeData m_outputBlock; + AmplitudeData m_outputBlockResampled; + TxRxData m_outputBlockTmp; + AmplitudeDataI16 m_outputBlockI16; + AmplitudeDataI16 m_txAmplitudeDataI16; + WaveformTones m_waveformTones; + + // Impl + // todo : move all members inside Impl + struct Impl; + std::unique_ptr m_impl; +}; + +#endif + +#endif diff --git a/examples/r2t2/ggwave-mod/src/ggwave.cpp b/examples/r2t2/ggwave-mod/src/ggwave.cpp new file mode 100644 index 0000000..07cc3d4 --- /dev/null +++ b/examples/r2t2/ggwave-mod/src/ggwave.cpp @@ -0,0 +1,1359 @@ +#include "ggwave/ggwave.h" + +#include "resampler.h" + +#include "reed-solomon/rs.hpp" + +#include +#include +#include +#include +#include +//#include + +// +// C interface +// + +namespace { +std::map g_instances; +} + +extern "C" +ggwave_Parameters ggwave_getDefaultParameters(void) { + return GGWave::getDefaultParameters(); +} + +extern "C" +ggwave_Instance ggwave_init(const ggwave_Parameters parameters) { + static ggwave_Instance curId = 0; + + g_instances[curId] = new GGWave({ + parameters.payloadLength, + parameters.sampleRateInp, + parameters.sampleRateOut, + parameters.samplesPerFrame, + parameters.soundMarkerThreshold, + parameters.sampleFormatInp, + parameters.sampleFormatOut}); + + return curId++; +} + +extern "C" +void ggwave_free(ggwave_Instance instance) { + delete (GGWave *) g_instances[instance]; + g_instances.erase(instance); +} + +extern "C" +int ggwave_encode( + ggwave_Instance instance, + const char * dataBuffer, + int dataSize, + ggwave_TxProtocolId txProtocolId, + int volume, + char * outputBuffer, + int query) { + GGWave * ggWave = (GGWave *) g_instances[instance]; + + if (ggWave == nullptr) { + fprintf(stderr, "Invalid GGWave instance %d\n", instance); + return -1; + } + + if (ggWave->init(dataSize, dataBuffer, ggWave->getTxProtocol(txProtocolId), volume) == false) { + fprintf(stderr, "Failed to initialize GGWave instance %d\n", instance); + return -1; + } + + if (query != 0) { + if (query == 1) { + return ggWave->encodeSize_bytes(); + } + + return ggWave->encodeSize_samples(); + } + + int nSamples = 0; + + GGWave::CBWaveformOut cbWaveformOut = [&](const void * data, uint32_t nBytes) { + char * p = (char *) data; + std::copy(p, p + nBytes, outputBuffer); + + nSamples = nBytes/ggWave->getSampleSizeBytesOut(); + }; + + if (ggWave->encode(cbWaveformOut) == false) { + fprintf(stderr, "Failed to encode data - GGWave instance %d\n", instance); + return -1; + } + + return nSamples; +} + +extern "C" +int ggwave_decode( + ggwave_Instance instance, + const char * dataBuffer, + int dataSize, + char * outputBuffer) { + GGWave * ggWave = (GGWave *) g_instances[instance]; + + GGWave::CBWaveformInp cbWaveformInp = [&](void * data, uint32_t nMaxBytes) -> uint32_t { + uint32_t nCopied = std::min((uint32_t) dataSize, nMaxBytes); + std::copy(dataBuffer, dataBuffer + nCopied, (char *) data); + + dataSize -= nCopied; + dataBuffer += nCopied; + + return nCopied; + }; + + ggWave->decode(cbWaveformInp); + + // todo : avoid allocation + GGWave::TxRxData rxData; + + auto rxDataLength = ggWave->takeRxData(rxData); + if (rxDataLength == -1) { + // failed to decode message + return -1; + } else if (rxDataLength > 0) { + std::copy(rxData.begin(), rxData.end(), outputBuffer); + } + + return rxDataLength; +} + +// +// C++ implementation +// + +namespace { + +// FFT routines taken from https://stackoverflow.com/a/37729648/4039976 + +int log2(int N) { + int k = N, i = 0; + while(k) { + k >>= 1; + i++; + } + return i - 1; +} + +int reverse(int N, int n) { + int j, p = 0; + for(j = 1; j <= log2(N); j++) { + if(n & (1 << (log2(N) - j))) + p |= 1 << (j - 1); + } + return p; +} + +void ordina(float * f1, int N) { + static thread_local float f2[2*GGWave::kMaxSamplesPerFrame]; + for (int i = 0; i < N; i++) { + int ir = reverse(N, i); + f2[2*i + 0] = f1[2*ir + 0]; + f2[2*i + 1] = f1[2*ir + 1]; + } + for (int j = 0; j < N; j++) { + f1[2*j + 0] = f2[2*j + 0]; + f1[2*j + 1] = f2[2*j + 1]; + } +} + +void transform(float * f, int N) { + ordina(f, N); //first: reverse order + float * W; + W = (float *)malloc(N*sizeof(float)); + W[2*1 + 0] = cos(-2.*M_PI/N); + W[2*1 + 1] = sin(-2.*M_PI/N); + W[2*0 + 0] = 1; + W[2*0 + 1] = 0; + for (int i = 2; i < N / 2; i++) { + W[2*i + 0] = cos(-2.*i*M_PI/N); + W[2*i + 1] = sin(-2.*i*M_PI/N); + } + int n = 1; + int a = N / 2; + for(int j = 0; j < log2(N); j++) { + for(int i = 0; i < N; i++) { + if(!(i & n)) { + int wi = (i * a) % (n * a); + int fi = i + n; + float a = W[2*wi + 0]; + float b = W[2*wi + 1]; + float c = f[2*fi + 0]; + float d = f[2*fi + 1]; + float temp[2] = { f[2*i + 0], f[2*i + 1] }; + float Temp[2] = { a*c - b*d, b*c + a*d }; + f[2*i + 0] = temp[0] + Temp[0]; + f[2*i + 1] = temp[1] + Temp[1]; + f[2*fi + 0] = temp[0] - Temp[0]; + f[2*fi + 1] = temp[1] - Temp[1]; + } + } + n *= 2; + a = a / 2; + } + free(W); +} + +void FFT(float * f, int N, float d) { + transform(f, N); + for (int i = 0; i < N; i++) { + f[2*i + 0] *= d; + f[2*i + 1] *= d; + } +} + +void FFT(const float * src, float * dst, int N, float d) { + for (int i = 0; i < N; ++i) { + dst[2*i + 0] = src[i]; + dst[2*i + 1] = 0.0f; + } + FFT(dst, N, d); +} + +inline void addAmplitudeSmooth( + const GGWave::AmplitudeData & src, + GGWave::AmplitudeData & dst, + float scalar, int startId, int finalId, int cycleMod, int nPerCycle) { + int nTotal = nPerCycle*finalId; + float frac = 0.15f; + float ds = frac*nTotal; + float ids = 1.0f/ds; + int nBegin = frac*nTotal; + int nEnd = (1.0f - frac)*nTotal; + for (int i = startId; i < finalId; i++) { + float k = cycleMod*finalId + i; + if (k < nBegin) { + dst[i] += scalar*src[i]*(k*ids); + } else if (k > nEnd) { + dst[i] += scalar*src[i]*(((float)(nTotal) - k)*ids); + } else { + dst[i] += scalar*src[i]; + } + } +} + +template +float getTime_ms(const T & tStart, const T & tEnd) { + return ((float)(std::chrono::duration_cast(tEnd - tStart).count()))/1000.0; +} + +int getECCBytesForLength(int len) { + return len < 4 ? 2 : std::max(4, 2*(len/5)); +} + +int bytesForSampleFormat(GGWave::SampleFormat sampleFormat) { + switch (sampleFormat) { + case GGWAVE_SAMPLE_FORMAT_UNDEFINED: return 0; break; + case GGWAVE_SAMPLE_FORMAT_U8: return sizeof(uint8_t); break; + case GGWAVE_SAMPLE_FORMAT_I8: return sizeof(int8_t); break; + case GGWAVE_SAMPLE_FORMAT_U16: return sizeof(uint16_t); break; + case GGWAVE_SAMPLE_FORMAT_I16: return sizeof(int16_t); break; + case GGWAVE_SAMPLE_FORMAT_F32: return sizeof(float); break; + }; + + fprintf(stderr, "Invalid sample format: %d\n", (int) sampleFormat); + + return 0; +} + +} + +struct GGWave::Impl { + Resampler resampler; +}; + +const GGWave::Parameters & GGWave::getDefaultParameters() { + static ggwave_Parameters result { + -1, // vaiable payload length + kBaseSampleRate, + kBaseSampleRate, + kDefaultSamplesPerFrame, + kDefaultSoundMarkerThreshold, + GGWAVE_SAMPLE_FORMAT_F32, + GGWAVE_SAMPLE_FORMAT_F32, + }; + + return result; +} + +GGWave::GGWave(const Parameters & parameters) : + m_sampleRateInp(parameters.sampleRateInp), + m_sampleRateOut(parameters.sampleRateOut), + m_samplesPerFrame(parameters.samplesPerFrame), + m_isamplesPerFrame(1.0f/m_samplesPerFrame), + m_sampleSizeBytesInp(bytesForSampleFormat(parameters.sampleFormatInp)), + m_sampleSizeBytesOut(bytesForSampleFormat(parameters.sampleFormatOut)), + m_sampleFormatInp(parameters.sampleFormatInp), + m_sampleFormatOut(parameters.sampleFormatOut), + m_hzPerSample(kBaseSampleRate/parameters.samplesPerFrame), + m_ihzPerSample(1.0f/m_hzPerSample), + m_freqDelta_bin(1), + m_freqDelta_hz(2*m_hzPerSample), + m_nBitsInMarker(16), + m_nMarkerFrames(parameters.payloadLength > 0 ? 0 : kDefaultMarkerFrames), + m_encodedDataOffset(parameters.payloadLength > 0 ? 0 : kDefaultEncodedDataOffset), + m_soundMarkerThreshold(parameters.soundMarkerThreshold), + // common + m_isFixedPayloadLength(parameters.payloadLength > 0), + m_payloadLength(parameters.payloadLength), + // Rx + m_samplesNeeded(m_samplesPerFrame), + m_fftInp(kMaxSamplesPerFrame), + m_fftOut(2*kMaxSamplesPerFrame), + m_hasNewSpectrum(false), + m_hasNewAmplitude(false), + m_sampleSpectrum(kMaxSamplesPerFrame), + m_sampleAmplitude(kMaxSamplesPerFrame + 128), // small extra space because sometimes resampling needs a few more samples + m_sampleAmplitudeResampled(8*kMaxSamplesPerFrame), // min input sampling rate is 0.125*kBaseSampleRate + m_sampleAmplitudeTmp(8*kMaxSamplesPerFrame*m_sampleSizeBytesInp), + m_hasNewRxData(false), + m_lastRxDataLength(0), + m_rxData(kMaxDataSize), + m_rxProtocol(getDefaultTxProtocol()), + m_rxProtocolId(getDefaultTxProtocolId()), + m_rxProtocols(getTxProtocols()), + m_historyId(0), + m_sampleAmplitudeAverage(kMaxSamplesPerFrame), + m_sampleAmplitudeHistory(kMaxSpectrumHistory), + m_historyIdFixed(0), + // Tx + m_hasNewTxData(false), + m_sendVolume(0.1), + m_txDataLength(0), + m_txData(kMaxDataSize), + m_txDataEncoded(kMaxDataSize), + m_outputBlock(kMaxSamplesPerFrame), + m_outputBlockResampled(2*kMaxSamplesPerFrame), + m_outputBlockTmp(kMaxRecordedFrames*kMaxSamplesPerFrame*m_sampleSizeBytesOut), + m_outputBlockI16(kMaxRecordedFrames*kMaxSamplesPerFrame), + m_impl(new Impl()) { + + if (m_payloadLength > 0) { + // fixed payload length + if (m_payloadLength > kMaxLengthFixed) { + throw std::runtime_error("Invalid payload legnth"); + } + + m_txDataLength = m_payloadLength; + + int totalLength = m_txDataLength + getECCBytesForLength(m_txDataLength); + int totalTxs = 2*(totalLength + minBytesPerTx() - 1)/minBytesPerTx(); + + m_spectrumHistoryFixed.resize(totalTxs*maxFramesPerTx()); + } else { + // variable payload length + m_recordedAmplitude.resize(kMaxRecordedFrames*kMaxSamplesPerFrame); + } + + if (m_sampleSizeBytesInp == 0) { + throw std::runtime_error("Invalid or unsupported capture sample format"); + } + + if (m_sampleSizeBytesOut == 0) { + throw std::runtime_error("Invalid or unsupported playback sample format"); + } + + if (parameters.samplesPerFrame > kMaxSamplesPerFrame) { + throw std::runtime_error("Invalid samples per frame"); + } + + if (m_sampleRateInp < kSampleRateMin) { + fprintf(stderr, "Error: capture sample rate (%g Hz) must be >= %g Hz\n", m_sampleRateInp, kSampleRateMin); + throw std::runtime_error("Invalid capture/playback sample rate"); + } + + if (m_sampleRateInp > kSampleRateMax) { + fprintf(stderr, "Error: capture sample rate (%g Hz) must be <= %g Hz\n", m_sampleRateInp, kSampleRateMax); + throw std::runtime_error("Invalid capture/playback sample rate"); + } + + init("", getDefaultTxProtocol(), 0); +} + +GGWave::~GGWave() { +} + +bool GGWave::init(const std::string & text, const int volume) { + return init(text.size(), text.data(), getDefaultTxProtocol(), volume); +} + +bool GGWave::init(const std::string & text, const TxProtocol & txProtocol, const int volume) { + return init(text.size(), text.data(), txProtocol, volume); +} + +bool GGWave::init(int dataSize, const char * dataBuffer, const int volume) { + return init(dataSize, dataBuffer, getDefaultTxProtocol(), volume); +} + +bool GGWave::init(int dataSize, const char * dataBuffer, const TxProtocol & txProtocol, const int volume) { + if (dataSize < 0) { + fprintf(stderr, "Negative data size: %d\n", dataSize); + return false; + } + + auto maxLength = m_isFixedPayloadLength ? m_payloadLength : kMaxLengthVarible; + if (dataSize > maxLength) { + fprintf(stderr, "Truncating data from %d to %d bytes\n", dataSize, maxLength); + dataSize = maxLength; + } + + if (volume < 0 || volume > 100) { + fprintf(stderr, "Invalid volume: %d\n", volume); + return false; + } + + m_txProtocol = txProtocol; + m_txDataLength = dataSize; + m_sendVolume = ((double)(volume))/100.0f; + + const uint8_t * text = reinterpret_cast(dataBuffer); + + m_hasNewTxData = false; + std::fill(m_txData.begin(), m_txData.end(), 0); + std::fill(m_txDataEncoded.begin(), m_txDataEncoded.end(), 0); + + if (m_txDataLength > 0) { + m_txData[0] = m_txDataLength; + for (int i = 0; i < m_txDataLength; ++i) m_txData[i + 1] = text[i]; + + m_hasNewTxData = true; + } + + if (m_isFixedPayloadLength) { + m_txDataLength = m_payloadLength; + } + + // Rx + m_receivingData = false; + m_analyzingData = false; + + m_framesToAnalyze = 0; + m_framesLeftToAnalyze = 0; + m_framesToRecord = 0; + m_framesLeftToRecord = 0; + + std::fill(m_sampleSpectrum.begin(), m_sampleSpectrum.end(), 0); + std::fill(m_sampleAmplitude.begin(), m_sampleAmplitude.end(), 0); + for (auto & s : m_sampleAmplitudeHistory) { + s.resize(kMaxSamplesPerFrame); + std::fill(s.begin(), s.end(), 0); + } + + std::fill(m_rxData.begin(), m_rxData.end(), 0); + + for (int i = 0; i < m_samplesPerFrame; ++i) { + m_fftOut[2*i + 0] = 0.0f; + m_fftOut[2*i + 1] = 0.0f; + } + + for (auto & s : m_spectrumHistoryFixed) { + s.resize(kMaxSamplesPerFrame); + std::fill(s.begin(), s.end(), 0); + } + + return true; +} + +uint32_t GGWave::encodeSize_bytes() const { + return encodeSize_samples()*m_sampleSizeBytesOut; +} + +uint32_t GGWave::encodeSize_samples() const { + if (m_hasNewTxData == false) { + return 0; + } + + float factor = 1.0f; + int samplesPerFrameOut = m_samplesPerFrame; + if (m_sampleRateOut != kBaseSampleRate) { + factor = kBaseSampleRate/m_sampleRateOut; + // note : +1 extra sample in order to overestimate the buffer size + samplesPerFrameOut = m_impl->resampler.resample(factor, m_samplesPerFrame, m_outputBlock.data(), nullptr) + 1; + } + int nECCBytesPerTx = getECCBytesForLength(m_txDataLength); + int sendDataLength = m_txDataLength + m_encodedDataOffset; + int totalBytes = sendDataLength + nECCBytesPerTx; + int totalDataFrames = ((totalBytes + m_txProtocol.bytesPerTx - 1)/m_txProtocol.bytesPerTx)*m_txProtocol.framesPerTx; + + return ( + m_nMarkerFrames + totalDataFrames + m_nMarkerFrames + )*samplesPerFrameOut; +} + +bool GGWave::encode(const CBWaveformOut & cbWaveformOut) { + int frameId = 0; + + m_impl->resampler.reset(); + + std::vector phaseOffsets(kMaxDataBits); + + for (int k = 0; k < (int) phaseOffsets.size(); ++k) { + phaseOffsets[k] = (M_PI*k)/(m_txProtocol.nDataBitsPerTx()); + } + + // note : what is the purpose of this shuffle ? I forgot .. :( + //std::random_device rd; + //std::mt19937 g(rd()); + + //std::shuffle(phaseOffsets.begin(), phaseOffsets.end(), g); + + std::vector dataBits(kMaxDataBits); + + std::vector bit1Amplitude(kMaxDataBits); + std::vector bit0Amplitude(kMaxDataBits); + + for (int k = 0; k < (int) dataBits.size(); ++k) { + double freq = bitFreq(m_txProtocol, k); + + bit1Amplitude[k].resize(kMaxSamplesPerFrame); + bit0Amplitude[k].resize(kMaxSamplesPerFrame); + + double phaseOffset = phaseOffsets[k]; + double curHzPerSample = m_hzPerSample; + double curIHzPerSample = 1.0/curHzPerSample; + for (int i = 0; i < m_samplesPerFrame; i++) { + double curi = i; + bit1Amplitude[k][i] = std::sin((2.0*M_PI)*(curi*m_isamplesPerFrame)*(freq*curIHzPerSample) + phaseOffset); + } + for (int i = 0; i < m_samplesPerFrame; i++) { + double curi = i; + bit0Amplitude[k][i] = std::sin((2.0*M_PI)*(curi*m_isamplesPerFrame)*((freq + m_hzPerSample*m_freqDelta_bin)*curIHzPerSample) + phaseOffset); + } + } + + int nECCBytesPerTx = getECCBytesForLength(m_txDataLength); + int sendDataLength = m_txDataLength + m_encodedDataOffset; + int totalBytes = sendDataLength + nECCBytesPerTx; + int totalDataFrames = 2*((totalBytes + m_txProtocol.bytesPerTx - 1)/m_txProtocol.bytesPerTx)*m_txProtocol.framesPerTx; + + if (m_isFixedPayloadLength == false) { + RS::ReedSolomon rsLength(1, m_encodedDataOffset - 1); + rsLength.Encode(m_txData.data(), m_txDataEncoded.data()); + } + + // first byte of m_txData contains the length of the payload, so we skip it: + RS::ReedSolomon rsData = RS::ReedSolomon(m_txDataLength, nECCBytesPerTx); + rsData.Encode(m_txData.data() + 1, m_txDataEncoded.data() + m_encodedDataOffset); + + float factor = kBaseSampleRate/m_sampleRateOut; + uint32_t offset = 0; + + m_waveformTones.clear(); + + while (m_hasNewTxData) { + std::fill(m_outputBlock.begin(), m_outputBlock.end(), 0.0f); + + std::uint16_t nFreq = 0; + m_waveformTones.push_back({}); + + if (frameId < m_nMarkerFrames) { + nFreq = m_nBitsInMarker; + + for (int i = 0; i < m_nBitsInMarker; ++i) { + m_waveformTones.back().push_back({}); + m_waveformTones.back().back().duration_ms = (1000.0*m_samplesPerFrame)/kBaseSampleRate; + if (i%2 == 0) { + ::addAmplitudeSmooth(bit1Amplitude[i], m_outputBlock, m_sendVolume, 0, m_samplesPerFrame, frameId, m_nMarkerFrames); + m_waveformTones.back().back().freq_hz = bitFreq(m_txProtocol, i); + } else { + ::addAmplitudeSmooth(bit0Amplitude[i], m_outputBlock, m_sendVolume, 0, m_samplesPerFrame, frameId, m_nMarkerFrames); + m_waveformTones.back().back().freq_hz = bitFreq(m_txProtocol, i) + m_hzPerSample; + } + } + } else if (frameId < m_nMarkerFrames + totalDataFrames) { + int dataOffset = frameId - m_nMarkerFrames; + int cycleModMain = dataOffset%m_txProtocol.framesPerTx; + dataOffset /= m_txProtocol.framesPerTx; + dataOffset *= m_txProtocol.bytesPerTx; + + std::fill(dataBits.begin(), dataBits.end(), 0); + + for (int j = 0; j < m_txProtocol.bytesPerTx; ++j) { + if (dataOffset % 2 == 0) { + uint8_t d = m_txDataEncoded[dataOffset/2 + j] & 15; + dataBits[(2*j + 0)*16 + d] = 1; + } else { + uint8_t d = m_txDataEncoded[dataOffset/2 + j] & 240; + dataBits[(2*j + 0)*16 + (d >> 4)] = 1; + } + } + + for (int k = 0; k < 2*m_txProtocol.bytesPerTx*16; ++k) { + if (dataBits[k] == 0) continue; + + ++nFreq; + m_waveformTones.back().push_back({}); + m_waveformTones.back().back().duration_ms = (1000.0*m_samplesPerFrame)/kBaseSampleRate; + if (k%2) { + ::addAmplitudeSmooth(bit0Amplitude[k/2], m_outputBlock, m_sendVolume, 0, m_samplesPerFrame, cycleModMain, m_txProtocol.framesPerTx); + m_waveformTones.back().back().freq_hz = bitFreq(m_txProtocol, k/2) + m_hzPerSample; + //printf("frameId = %d, freq = %g\n", frameId, m_waveformTones.back().back().freq_hz); + } else { + ::addAmplitudeSmooth(bit1Amplitude[k/2], m_outputBlock, m_sendVolume, 0, m_samplesPerFrame, cycleModMain, m_txProtocol.framesPerTx); + m_waveformTones.back().back().freq_hz = bitFreq(m_txProtocol, k/2); + //printf("frameId = %d, freq = %g\n", frameId, m_waveformTones.back().back().freq_hz); + } + } + } else if (frameId < m_nMarkerFrames + totalDataFrames + m_nMarkerFrames) { + nFreq = m_nBitsInMarker; + + int fId = frameId - (m_nMarkerFrames + totalDataFrames); + for (int i = 0; i < m_nBitsInMarker; ++i) { + m_waveformTones.back().push_back({}); + m_waveformTones.back().back().duration_ms = (1000.0*m_samplesPerFrame)/kBaseSampleRate; + if (i%2 == 0) { + addAmplitudeSmooth(bit0Amplitude[i], m_outputBlock, m_sendVolume, 0, m_samplesPerFrame, fId, m_nMarkerFrames); + m_waveformTones.back().back().freq_hz = bitFreq(m_txProtocol, i) + m_hzPerSample; + } else { + addAmplitudeSmooth(bit1Amplitude[i], m_outputBlock, m_sendVolume, 0, m_samplesPerFrame, fId, m_nMarkerFrames); + m_waveformTones.back().back().freq_hz = bitFreq(m_txProtocol, i); + } + } + } else { + m_hasNewTxData = false; + break; + } + + if (nFreq == 0) nFreq = 1; + float scale = 1.0f/nFreq; + for (int i = 0; i < m_samplesPerFrame; ++i) { + m_outputBlock[i] *= scale; + } + + int samplesPerFrameOut = m_samplesPerFrame; + if (m_sampleRateOut != kBaseSampleRate) { + samplesPerFrameOut = m_impl->resampler.resample(factor, m_samplesPerFrame, m_outputBlock.data(), m_outputBlockResampled.data()); + } else { + m_outputBlockResampled = m_outputBlock; + } + + // default output is in 16-bit signed int so we always compute it + for (int i = 0; i < samplesPerFrameOut; ++i) { + m_outputBlockI16[offset + i] = 32768*m_outputBlockResampled[i]; + } + + // convert from 32-bit float + switch (m_sampleFormatOut) { + case GGWAVE_SAMPLE_FORMAT_UNDEFINED: break; + case GGWAVE_SAMPLE_FORMAT_U8: + { + auto p = reinterpret_cast(m_outputBlockTmp.data()); + for (int i = 0; i < samplesPerFrameOut; ++i) { + p[offset + i] = 128*(m_outputBlockResampled[i] + 1.0f); + } + } break; + case GGWAVE_SAMPLE_FORMAT_I8: + { + auto p = reinterpret_cast(m_outputBlockTmp.data()); + for (int i = 0; i < samplesPerFrameOut; ++i) { + p[offset + i] = 128*m_outputBlockResampled[i]; + } + } break; + case GGWAVE_SAMPLE_FORMAT_U16: + { + auto p = reinterpret_cast(m_outputBlockTmp.data()); + for (int i = 0; i < samplesPerFrameOut; ++i) { + p[offset + i] = 32768*(m_outputBlockResampled[i] + 1.0f); + } + } break; + case GGWAVE_SAMPLE_FORMAT_I16: + { + // skip because we already have the data in m_outputBlockI16 + //auto p = reinterpret_cast(m_outputBlockTmp.data()); + //for (int i = 0; i < samplesPerFrameOut; ++i) { + // p[offset + i] = 32768*m_outputBlockResampled[i]; + //} + } break; + case GGWAVE_SAMPLE_FORMAT_F32: + { + auto p = reinterpret_cast(m_outputBlockTmp.data()); + for (int i = 0; i < samplesPerFrameOut; ++i) { + p[offset + i] = m_outputBlockResampled[i]; + } + } break; + } + + ++frameId; + offset += samplesPerFrameOut; + } + + switch (m_sampleFormatOut) { + case GGWAVE_SAMPLE_FORMAT_UNDEFINED: break; + case GGWAVE_SAMPLE_FORMAT_I16: + { + cbWaveformOut(m_outputBlockI16.data(), offset*m_sampleSizeBytesOut); + } break; + case GGWAVE_SAMPLE_FORMAT_U8: + case GGWAVE_SAMPLE_FORMAT_I8: + case GGWAVE_SAMPLE_FORMAT_U16: + case GGWAVE_SAMPLE_FORMAT_F32: + { + cbWaveformOut(m_outputBlockTmp.data(), offset*m_sampleSizeBytesOut); + } break; + } + + m_txAmplitudeDataI16.resize(offset); + for (uint32_t i = 0; i < offset; ++i) { + m_txAmplitudeDataI16[i] = m_outputBlockI16[i]; + } + + return true; +} + +void GGWave::decode(const CBWaveformInp & cbWaveformInp) { + while (m_hasNewTxData == false) { + // read capture data + float factor = m_sampleRateInp/kBaseSampleRate; + uint32_t nBytesNeeded = m_samplesNeeded*m_sampleSizeBytesInp; + + if (m_sampleRateInp != kBaseSampleRate) { + // note : predict 4 extra samples just to make sure we have enough data + nBytesNeeded = (m_impl->resampler.resample(1.0f/factor, m_samplesNeeded, m_sampleAmplitudeResampled.data(), nullptr) + 4)*m_sampleSizeBytesInp; + } + + uint32_t nBytesRecorded = 0; + + switch (m_sampleFormatInp) { + case GGWAVE_SAMPLE_FORMAT_UNDEFINED: break; + case GGWAVE_SAMPLE_FORMAT_U8: + case GGWAVE_SAMPLE_FORMAT_I8: + case GGWAVE_SAMPLE_FORMAT_U16: + case GGWAVE_SAMPLE_FORMAT_I16: + { + nBytesRecorded = cbWaveformInp(m_sampleAmplitudeTmp.data(), nBytesNeeded); + } break; + case GGWAVE_SAMPLE_FORMAT_F32: + { + nBytesRecorded = cbWaveformInp(m_sampleAmplitudeResampled.data(), nBytesNeeded); + } break; + } + + if (nBytesRecorded % m_sampleSizeBytesInp != 0) { + fprintf(stderr, "Failure during capture - provided bytes (%d) are not multiple of sample size (%d)\n", + nBytesRecorded, m_sampleSizeBytesInp); + m_samplesNeeded = m_samplesPerFrame; + break; + } + + if (nBytesRecorded > nBytesNeeded) { + fprintf(stderr, "Failure during capture - more samples were provided (%d) than requested (%d)\n", + nBytesRecorded/m_sampleSizeBytesInp, nBytesNeeded/m_sampleSizeBytesInp); + m_samplesNeeded = m_samplesPerFrame; + break; + } + + // convert to 32-bit float + int nSamplesRecorded = nBytesRecorded/m_sampleSizeBytesInp; + switch (m_sampleFormatInp) { + case GGWAVE_SAMPLE_FORMAT_UNDEFINED: break; + case GGWAVE_SAMPLE_FORMAT_U8: + { + constexpr float scale = 1.0f/128; + auto p = reinterpret_cast(m_sampleAmplitudeTmp.data()); + for (int i = 0; i < nSamplesRecorded; ++i) { + m_sampleAmplitudeResampled[i] = float(int16_t(*(p + i)) - 128)*scale; + } + } break; + case GGWAVE_SAMPLE_FORMAT_I8: + { + constexpr float scale = 1.0f/128; + auto p = reinterpret_cast(m_sampleAmplitudeTmp.data()); + for (int i = 0; i < nSamplesRecorded; ++i) { + m_sampleAmplitudeResampled[i] = float(*(p + i))*scale; + } + } break; + case GGWAVE_SAMPLE_FORMAT_U16: + { + constexpr float scale = 1.0f/32768; + auto p = reinterpret_cast(m_sampleAmplitudeTmp.data()); + for (int i = 0; i < nSamplesRecorded; ++i) { + m_sampleAmplitudeResampled[i] = float(int32_t(*(p + i)) - 32768)*scale; + } + } break; + case GGWAVE_SAMPLE_FORMAT_I16: + { + constexpr float scale = 1.0f/32768; + auto p = reinterpret_cast(m_sampleAmplitudeTmp.data()); + for (int i = 0; i < nSamplesRecorded; ++i) { + m_sampleAmplitudeResampled[i] = float(*(p + i))*scale; + } + } break; + case GGWAVE_SAMPLE_FORMAT_F32: break; + } + + if (nSamplesRecorded == 0) { + break; + } + + uint32_t offset = m_samplesPerFrame - m_samplesNeeded; + + if (m_sampleRateInp != kBaseSampleRate) { + if (nSamplesRecorded <= 2*Resampler::kWidth) { + m_samplesNeeded = m_samplesPerFrame; + break; + } + + // reset resampler state every minute + if (!m_receivingData && m_impl->resampler.nSamplesTotal() > 60.0f*factor*kBaseSampleRate) { + m_impl->resampler.reset(); + } + + int nSamplesResampled = offset + m_impl->resampler.resample(factor, nSamplesRecorded, m_sampleAmplitudeResampled.data(), m_sampleAmplitude.data() + offset); + nSamplesRecorded = nSamplesResampled; + } else { + for (int i = 0; i < nSamplesRecorded; ++i) { + m_sampleAmplitude[offset + i] = m_sampleAmplitudeResampled[i]; + } + } + + // we have enough bytes to do analysis + if (nSamplesRecorded >= m_samplesPerFrame) { + m_hasNewAmplitude = true; + + if (m_isFixedPayloadLength) { + decode_fixed(); + } else { + decode_variable(); + } + + int nExtraSamples = nSamplesRecorded - m_samplesPerFrame; + for (int i = 0; i < nExtraSamples; ++i) { + m_sampleAmplitude[i] = m_sampleAmplitude[m_samplesPerFrame + i]; + } + + m_samplesNeeded = m_samplesPerFrame - nExtraSamples; + } else { + m_samplesNeeded = m_samplesPerFrame - nSamplesRecorded; + break; + } + } +} + +bool GGWave::takeTxAmplitudeI16(AmplitudeDataI16 & dst) { + if (m_txAmplitudeDataI16.size() == 0) return false; + + dst = std::move(m_txAmplitudeDataI16); + + return true; +} + +bool GGWave::stopReceiving() { + if (m_receivingData == false) { + return false; + } + + m_receivingData = false; + + return true; +} + +int GGWave::takeRxData(TxRxData & dst) { + if (m_lastRxDataLength == 0) return 0; + + auto res = m_lastRxDataLength; + m_lastRxDataLength = 0; + + if (res != -1) { + dst = m_rxData; + } + + return res; +} + +bool GGWave::takeRxSpectrum(SpectrumData & dst) { + if (m_hasNewSpectrum == false) return false; + + m_hasNewSpectrum = false; + dst = m_sampleSpectrum; + + return true; +} + +bool GGWave::takeRxAmplitude(AmplitudeData & dst) { + if (m_hasNewAmplitude == false) return false; + + m_hasNewAmplitude = false; + dst = m_sampleAmplitude; + + return true; +} + +bool GGWave::computeFFTR(const float * src, float * dst, int N, float d) { + if (N > kMaxSamplesPerFrame) { + fprintf(stderr, "computeFFTR: N (%d) must be <= %d\n", N, GGWave::kMaxSamplesPerFrame); + return false; + } + + FFT(src, dst, N, d); + + return true; +} + +// +// Variable payload length +// + +void GGWave::decode_variable() { + m_sampleAmplitudeHistory[m_historyId] = m_sampleAmplitude; + + if (++m_historyId >= kMaxSpectrumHistory) { + m_historyId = 0; + } + + if (m_historyId == 0 || m_receivingData) { + m_hasNewSpectrum = true; + + std::fill(m_sampleAmplitudeAverage.begin(), m_sampleAmplitudeAverage.end(), 0.0f); + for (auto & s : m_sampleAmplitudeHistory) { + for (int i = 0; i < m_samplesPerFrame; ++i) { + m_sampleAmplitudeAverage[i] += s[i]; + } + } + + float norm = 1.0f/kMaxSpectrumHistory; + for (int i = 0; i < m_samplesPerFrame; ++i) { + m_sampleAmplitudeAverage[i] *= norm; + } + + // calculate spectrum + FFT(m_sampleAmplitudeAverage.data(), m_fftOut.data(), m_samplesPerFrame, 1.0); + + for (int i = 0; i < m_samplesPerFrame; ++i) { + m_sampleSpectrum[i] = (m_fftOut[2*i + 0]*m_fftOut[2*i + 0] + m_fftOut[2*i + 1]*m_fftOut[2*i + 1]); + } + for (int i = 1; i < m_samplesPerFrame/2; ++i) { + m_sampleSpectrum[i] += m_sampleSpectrum[m_samplesPerFrame - i]; + } + } + + if (m_framesLeftToRecord > 0) { + std::copy(m_sampleAmplitude.begin(), + m_sampleAmplitude.begin() + m_samplesPerFrame, + m_recordedAmplitude.data() + (m_framesToRecord - m_framesLeftToRecord)*m_samplesPerFrame); + + if (--m_framesLeftToRecord <= 0) { + m_analyzingData = true; + } + } + + if (m_analyzingData) { + fprintf(stderr, "Analyzing captured data ..\n"); + auto tStart = std::chrono::high_resolution_clock::now(); + + const int stepsPerFrame = 16; + const int step = m_samplesPerFrame/stepsPerFrame; + + bool isValid = false; + for (const auto & rxProtocolPair : m_rxProtocols) { + const auto & rxProtocolId = rxProtocolPair.first; + const auto & rxProtocol = rxProtocolPair.second; + + // skip Rx protocol if start frequency is different from detected one + if (rxProtocol.freqStart != m_markerFreqStart) { + continue; + } + + std::fill(m_sampleSpectrum.begin(), m_sampleSpectrum.end(), 0.0f); + + m_framesToAnalyze = m_nMarkerFrames*stepsPerFrame; + m_framesLeftToAnalyze = m_framesToAnalyze; + + // note : not sure if looping backwards here is more meaningful than looping forwards + for (int ii = m_nMarkerFrames*stepsPerFrame - 1; ii >= 0; --ii) { + bool knownLength = false; + + int decodedLength = 0; + const int offsetStart = ii; + for (int itx = 0; itx < 1024; ++itx) { + int offsetTx = offsetStart + itx*rxProtocol.framesPerTx*stepsPerFrame; + if (offsetTx >= m_recvDuration_frames*stepsPerFrame || (itx + 1)*rxProtocol.bytesPerTx >= (int) m_txDataEncoded.size()) { + break; + } + + std::copy( + m_recordedAmplitude.begin() + offsetTx*step, + m_recordedAmplitude.begin() + offsetTx*step + m_samplesPerFrame, m_fftInp.data()); + + // note : should we skip the first and last frame here as they are amplitude-smoothed? + for (int k = 1; k < rxProtocol.framesPerTx; ++k) { + for (int i = 0; i < m_samplesPerFrame; ++i) { + m_fftInp[i] += m_recordedAmplitude[(offsetTx + k*stepsPerFrame)*step + i]; + } + } + + FFT(m_fftInp.data(), m_fftOut.data(), m_samplesPerFrame, 1.0); + + for (int i = 0; i < m_samplesPerFrame; ++i) { + m_sampleSpectrum[i] = (m_fftOut[2*i + 0]*m_fftOut[2*i + 0] + m_fftOut[2*i + 1]*m_fftOut[2*i + 1]); + } + for (int i = 1; i < m_samplesPerFrame/2; ++i) { + m_sampleSpectrum[i] += m_sampleSpectrum[m_samplesPerFrame - i]; + } + + uint8_t curByte = 0; + for (int i = 0; i < 2*rxProtocol.bytesPerTx; ++i) { + double freq = m_hzPerSample*rxProtocol.freqStart; + int bin = std::round(freq*m_ihzPerSample) + 16*i; + + int kmax = 0; + double amax = 0.0; + for (int k = 0; k < 16; ++k) { + if (m_sampleSpectrum[bin + k] > amax) { + kmax = k; + amax = m_sampleSpectrum[bin + k]; + } + } + + if (i%2) { + curByte += (kmax << 4); + m_txDataEncoded[itx*rxProtocol.bytesPerTx + i/2] = curByte; + curByte = 0; + } else { + curByte = kmax; + } + } + + if (itx*rxProtocol.bytesPerTx > m_encodedDataOffset && knownLength == false) { + RS::ReedSolomon rsLength(1, m_encodedDataOffset - 1); + if ((rsLength.Decode(m_txDataEncoded.data(), m_rxData.data()) == 0) && (m_rxData[0] > 0 && m_rxData[0] <= 140)) { + knownLength = true; + decodedLength = m_rxData[0]; + + const int nTotalBytesExpected = m_encodedDataOffset + decodedLength + ::getECCBytesForLength(decodedLength); + const int nTotalFramesExpected = 2*m_nMarkerFrames + ((nTotalBytesExpected + rxProtocol.bytesPerTx - 1)/rxProtocol.bytesPerTx)*rxProtocol.framesPerTx; + if (m_recvDuration_frames > nTotalFramesExpected || + m_recvDuration_frames < nTotalFramesExpected - 2*m_nMarkerFrames) { + knownLength = false; + break; + } + } else { + break; + } + } + + { + const int nTotalBytesExpected = m_encodedDataOffset + decodedLength + ::getECCBytesForLength(decodedLength); + if (knownLength && itx*rxProtocol.bytesPerTx > nTotalBytesExpected + 1) { + break; + } + } + } + + if (knownLength) { + RS::ReedSolomon rsData(decodedLength, ::getECCBytesForLength(decodedLength)); + + if (rsData.Decode(m_txDataEncoded.data() + m_encodedDataOffset, m_rxData.data()) == 0) { + if (m_rxData[0] != 0) { + std::string s((char *) m_rxData.data(), decodedLength); + + fprintf(stderr, "Decoded length = %d, protocol = '%s' (%d)\n", decodedLength, rxProtocol.name, rxProtocolId); + fprintf(stderr, "Received sound data successfully: '%s'\n", s.c_str()); + + isValid = true; + m_hasNewRxData = true; + m_lastRxDataLength = decodedLength; + m_rxProtocol = rxProtocol; + m_rxProtocolId = TxProtocolId(rxProtocolId); + } + } + } + + if (isValid) { + break; + } + --m_framesLeftToAnalyze; + } + + if (isValid) break; + } + + m_framesToRecord = 0; + + if (isValid == false) { + fprintf(stderr, "Failed to capture sound data. Please try again (length = %d)\n", m_rxData[0]); + m_lastRxDataLength = -1; + m_framesToRecord = -1; + } + + m_receivingData = false; + m_analyzingData = false; + + std::fill(m_sampleSpectrum.begin(), m_sampleSpectrum.end(), 0.0f); + + m_framesToAnalyze = 0; + m_framesLeftToAnalyze = 0; + + auto tEnd = std::chrono::high_resolution_clock::now(); + fprintf(stderr, "Time to analyze: %g ms\n", getTime_ms(tStart, tEnd)); + } + + // check if receiving data + if (m_receivingData == false) { + bool isReceiving = false; + + for (const auto & rxProtocol : getTxProtocols()) { + int nDetectedMarkerBits = m_nBitsInMarker; + + for (int i = 0; i < m_nBitsInMarker; ++i) { + double freq = bitFreq(rxProtocol.second, i); + int bin = std::round(freq*m_ihzPerSample); + + if (i%2 == 0) { + if (m_sampleSpectrum[bin] <= m_soundMarkerThreshold*m_sampleSpectrum[bin + m_freqDelta_bin]) --nDetectedMarkerBits; + } else { + if (m_sampleSpectrum[bin] >= m_soundMarkerThreshold*m_sampleSpectrum[bin + m_freqDelta_bin]) --nDetectedMarkerBits; + } + } + + if (nDetectedMarkerBits == m_nBitsInMarker) { + m_markerFreqStart = rxProtocol.second.freqStart; + isReceiving = true; + break; + } + } + + if (isReceiving) { + if (++m_nMarkersSuccess >= 1) { + } else { + isReceiving = false; + } + } else { + m_nMarkersSuccess = 0; + } + + if (isReceiving) { + std::time_t timestamp = std::time(nullptr); + fprintf(stderr, "%sReceiving sound data ...\n", std::asctime(std::localtime(×tamp))); + + m_receivingData = true; + std::fill(m_rxData.begin(), m_rxData.end(), 0); + + // max recieve duration + m_recvDuration_frames = + 2*m_nMarkerFrames + + maxFramesPerTx()*((kMaxLengthVarible + ::getECCBytesForLength(kMaxLengthVarible))/minBytesPerTx() + 1); + + m_nMarkersSuccess = 0; + m_framesToRecord = m_recvDuration_frames; + m_framesLeftToRecord = m_recvDuration_frames; + } + } else { + bool isEnded = false; + + for (const auto & rxProtocol : getTxProtocols()) { + int nDetectedMarkerBits = m_nBitsInMarker; + + for (int i = 0; i < m_nBitsInMarker; ++i) { + double freq = bitFreq(rxProtocol.second, i); + int bin = std::round(freq*m_ihzPerSample); + + if (i%2 == 0) { + if (m_sampleSpectrum[bin] >= m_soundMarkerThreshold*m_sampleSpectrum[bin + m_freqDelta_bin]) nDetectedMarkerBits--; + } else { + if (m_sampleSpectrum[bin] <= m_soundMarkerThreshold*m_sampleSpectrum[bin + m_freqDelta_bin]) nDetectedMarkerBits--; + } + } + + if (nDetectedMarkerBits == m_nBitsInMarker) { + isEnded = true; + break; + } + } + + if (isEnded) { + if (++m_nMarkersSuccess >= 1) { + } else { + isEnded = false; + } + } else { + m_nMarkersSuccess = 0; + } + + if (isEnded && m_framesToRecord > 1) { + std::time_t timestamp = std::time(nullptr); + m_recvDuration_frames -= m_framesLeftToRecord - 1; + fprintf(stderr, "%sReceived end marker. Frames left = %d, recorded = %d\n", std::asctime(std::localtime(×tamp)), m_framesLeftToRecord, m_recvDuration_frames); + m_nMarkersSuccess = 0; + m_framesLeftToRecord = 1; + } + } +} + +// +// Fixed payload length + +void GGWave::decode_fixed() { + m_hasNewSpectrum = true; + + // calculate spectrum + FFT(m_sampleAmplitude.data(), m_fftOut.data(), m_samplesPerFrame, 1.0); + + for (int i = 0; i < m_samplesPerFrame; ++i) { + m_sampleSpectrum[i] = (m_fftOut[2*i + 0]*m_fftOut[2*i + 0] + m_fftOut[2*i + 1]*m_fftOut[2*i + 1]); + } + for (int i = 1; i < m_samplesPerFrame/2; ++i) { + m_sampleSpectrum[i] += m_sampleSpectrum[m_samplesPerFrame - i]; + } + + m_spectrumHistoryFixed[m_historyIdFixed] = m_sampleSpectrum; + + if (++m_historyIdFixed >= (int) m_spectrumHistoryFixed.size()) { + m_historyIdFixed = 0; + } + + bool isValid = false; + for (const auto & rxProtocolPair : m_rxProtocols) { + const auto & rxProtocolId = rxProtocolPair.first; + const auto & rxProtocol = rxProtocolPair.second; + + const int binStart = rxProtocol.freqStart; + const int binDelta = 16; + + const int totalLength = m_payloadLength + getECCBytesForLength(m_payloadLength); + const int totalTxs = 2*((totalLength + rxProtocol.bytesPerTx - 1)/rxProtocol.bytesPerTx); + + int historyStartId = m_historyIdFixed - totalTxs*rxProtocol.framesPerTx; + if (historyStartId < 0) { + historyStartId += m_spectrumHistoryFixed.size(); + } + + const int nTones = 2*rxProtocol.bytesPerTx; + std::vector detectedBins(2*totalLength); + + struct ToneData { + int nMax[16]; + }; + + std::vector tones(nTones); + + bool detectedSignal = true; + int txDetectedTotal = 0; + int txNeededTotal = 0; + for (int k = 0; k < totalTxs; ++k) { + if (k % 2 == 0) { + for (auto & tone : tones) { + std::fill(tone.nMax, tone.nMax + 16, 0); + } + } + + for (int i = 0; i < rxProtocol.framesPerTx; ++i) { + int historyId = historyStartId + k*rxProtocol.framesPerTx + i; + if (historyId >= (int) m_spectrumHistoryFixed.size()) { + historyId -= m_spectrumHistoryFixed.size(); + } + + for (int j = 0; j < rxProtocol.bytesPerTx; ++j) { + int f0bin = -1; + int f1bin = -1; + + double f0max = 0.0; + double f1max = 0.0; + + for (int b = 0; b < 16; ++b) { + { + const auto & v = m_spectrumHistoryFixed[historyId][binStart + 2*j*binDelta + b]; + + if (f0max <= v) { + f0max = v; + f0bin = b; + } + } + + { + const auto & v = m_spectrumHistoryFixed[historyId][binStart + 2*j*binDelta + b]; + + if (f1max <= v) { + f1max = v; + f1bin = b; + } + } + } + + if (k%2 == 0) tones[2*j + 0].nMax[f0bin]++; + if (k%2 == 1) tones[2*j + 1].nMax[f1bin]++; + } + } + if (k % 2 == 0) continue; + + int txDetected = 0; + int txNeeded = 0; + for (int j = 0; j < rxProtocol.bytesPerTx; ++j) { + if ((k/2)*rxProtocol.bytesPerTx + j >= totalLength) break; + txNeeded += 2; + for (int b = 0; b < 16; ++b) { + if (tones[2*j + 0].nMax[b] > rxProtocol.framesPerTx/2) { + detectedBins[2*((k/2)*rxProtocol.bytesPerTx + j) + 0] = b; + txDetected++; + } + if (tones[2*j + 1].nMax[b] > rxProtocol.framesPerTx/2) { + detectedBins[2*((k/2)*rxProtocol.bytesPerTx + j) + 1] = b; + txDetected++; + } + } + } + + txDetectedTotal += txDetected; + txNeededTotal += txNeeded; + } + + //if (rxProtocolId == GGWAVE_TX_PROTOCOL_DT_FAST) { + // printf("detected = %d, needed = %d\n", txDetectedTotal, txNeededTotal); + //} + + if (txDetectedTotal < 0.75*txNeededTotal) { + detectedSignal = false; + } + + if (detectedSignal) { + RS::ReedSolomon rsData(m_payloadLength, getECCBytesForLength(m_payloadLength)); + + for (int j = 0; j < totalLength; ++j) { + m_txDataEncoded[j] = (detectedBins[2*j + 1] << 4) + detectedBins[2*j + 0]; + } + + if (rsData.Decode(m_txDataEncoded.data(), m_rxData.data()) == 0) { + if (m_rxData[0] != 0) { + std::time_t timestamp = std::time(nullptr); + std::string tstr = std::asctime(std::localtime(×tamp)); + tstr.back() = 0; + fprintf(stderr, "[%s] Received: '%s'\n", tstr.c_str(), m_rxData.data()); + + isValid = true; + m_hasNewRxData = true; + m_lastRxDataLength = m_payloadLength; + m_rxProtocol = rxProtocol; + m_rxProtocolId = TxProtocolId(rxProtocolId); + } + } + } + + if (isValid) { + break; + } + } +} + +int GGWave::maxFramesPerTx() const { + int res = 0; + for (const auto & protocol : getTxProtocols()) { + res = std::max(res, protocol.second.framesPerTx); + } + return res; +} + +int GGWave::minBytesPerTx() const { + int res = getTxProtocols().begin()->second.bytesPerTx; + for (const auto & protocol : getTxProtocols()) { + res = std::min(res, protocol.second.bytesPerTx); + } + return res; +} + diff --git a/examples/r2t2/ggwave-mod/src/reed-solomon/LICENSE b/examples/r2t2/ggwave-mod/src/reed-solomon/LICENSE new file mode 100644 index 0000000..aaffd33 --- /dev/null +++ b/examples/r2t2/ggwave-mod/src/reed-solomon/LICENSE @@ -0,0 +1,21 @@ +Copyright © 2015 Mike Lubinets, github.com/mersinvald + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation files +(the “Software”), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/examples/r2t2/ggwave-mod/src/reed-solomon/gf.hpp b/examples/r2t2/ggwave-mod/src/reed-solomon/gf.hpp new file mode 100644 index 0000000..14a2831 --- /dev/null +++ b/examples/r2t2/ggwave-mod/src/reed-solomon/gf.hpp @@ -0,0 +1,235 @@ +/* Author: Mike Lubinets (aka mersinvald) + * Date: 29.12.15 + * + * See LICENSE */ + +#ifndef GF_H +#define GF_H + +#include "poly.hpp" + +#include +#include +#include + +namespace RS { + +namespace gf { + + +/* GF tables pre-calculated for 0x11d primitive polynomial */ + +const uint8_t exp[512] = { + 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26, 0x4c, + 0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9, 0x8f, 0x3, 0x6, 0xc, 0x18, 0x30, 0x60, 0xc0, 0x9d, + 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35, 0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23, 0x46, + 0x8c, 0x5, 0xa, 0x14, 0x28, 0x50, 0xa0, 0x5d, 0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1, 0x5f, + 0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc, 0x65, 0xca, 0x89, 0xf, 0x1e, 0x3c, 0x78, 0xf0, 0xfd, + 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f, 0xfe, 0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2, 0xd9, + 0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, 0xd, 0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce, 0x81, + 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93, 0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc, 0x85, + 0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9, 0x4f, 0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54, 0xa8, + 0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa, 0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73, 0xe6, + 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e, 0xfc, 0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff, 0xe3, + 0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4, 0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41, 0x82, + 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x7, 0xe, 0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6, 0x51, + 0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef, 0xc3, 0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x9, 0x12, + 0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5, 0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0xb, 0x16, 0x2c, + 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83, 0x1b, 0x36, 0x6c, 0xd8, 0xad, 0x47, 0x8e, 0x1, 0x2, + 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26, 0x4c, 0x98, + 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9, 0x8f, 0x3, 0x6, 0xc, 0x18, 0x30, 0x60, 0xc0, 0x9d, 0x27, + 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35, 0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23, 0x46, 0x8c, + 0x5, 0xa, 0x14, 0x28, 0x50, 0xa0, 0x5d, 0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1, 0x5f, 0xbe, + 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc, 0x65, 0xca, 0x89, 0xf, 0x1e, 0x3c, 0x78, 0xf0, 0xfd, 0xe7, + 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f, 0xfe, 0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2, 0xd9, 0xaf, + 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, 0xd, 0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce, 0x81, 0x1f, + 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93, 0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc, 0x85, 0x17, + 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9, 0x4f, 0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54, 0xa8, 0x4d, + 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa, 0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73, 0xe6, 0xd1, + 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e, 0xfc, 0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff, 0xe3, 0xdb, + 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4, 0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41, 0x82, 0x19, + 0x32, 0x64, 0xc8, 0x8d, 0x7, 0xe, 0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6, 0x51, 0xa2, + 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef, 0xc3, 0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x9, 0x12, 0x24, + 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5, 0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0xb, 0x16, 0x2c, 0x58, + 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83, 0x1b, 0x36, 0x6c, 0xd8, 0xad, 0x47, 0x8e, 0x1, 0x2 +}; + +const uint8_t log[256] = { + 0x0, 0x0, 0x1, 0x19, 0x2, 0x32, 0x1a, 0xc6, 0x3, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b, 0x4, + 0x64, 0xe0, 0xe, 0x34, 0x8d, 0xef, 0x81, 0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x8, 0x4c, 0x71, 0x5, + 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0xf, 0x21, 0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45, 0x1d, + 0xb5, 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9, 0xc9, 0x9a, 0x9, 0x78, 0x4d, 0xe4, 0x72, 0xa6, 0x6, + 0xbf, 0x8b, 0x62, 0x66, 0xdd, 0x30, 0xfd, 0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88, 0x36, + 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd, 0xf1, 0xd2, 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40, 0x1e, + 0x42, 0xb6, 0xa3, 0xc3, 0x48, 0x7e, 0x6e, 0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, 0xba, 0x3d, 0xca, + 0x5e, 0x9b, 0x9f, 0xa, 0x15, 0x79, 0x2b, 0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57, 0x7, + 0x70, 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0xd, 0x67, 0x4a, 0xde, 0xed, 0x31, 0xc5, 0xfe, 0x18, 0xe3, + 0xa5, 0x99, 0x77, 0x26, 0xb8, 0xb4, 0x7c, 0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e, 0x37, + 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd, 0x90, 0x87, 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61, 0xf2, + 0x56, 0xd3, 0xab, 0x14, 0x2a, 0x5d, 0x9e, 0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, 0x41, 0xa2, 0x1f, + 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76, 0xc4, 0x17, 0x49, 0xec, 0x7f, 0xc, 0x6f, 0xf6, 0x6c, + 0xa1, 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa, 0xfb, 0x60, 0x86, 0xb1, 0xbb, 0xcc, 0x3e, 0x5a, 0xcb, + 0x59, 0x5f, 0xb0, 0x9c, 0xa9, 0xa0, 0x51, 0xb, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7, 0x4f, + 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8, 0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf +}; + + + +/* ################################ + * # OPERATIONS OVER GALUA FIELDS # + * ################################ */ + +/* @brief Addition in Galua Fields + * @param x - left operand + * @param y - right operand + * @return x + y */ +inline uint8_t add(uint8_t x, uint8_t y) { + return x^y; +} + +/* ##### GF substraction ###### */ +/* @brief Substraction in Galua Fields + * @param x - left operand + * @param y - right operand + * @return x - y */ +inline uint8_t sub(uint8_t x, uint8_t y) { + return x^y; +} + +/* @brief Multiplication in Galua Fields + * @param x - left operand + * @param y - rifht operand + * @return x * y */ +inline uint8_t mul(uint16_t x, uint16_t y){ + if (x == 0 || y == 0) + return 0; + return exp[log[x] + log[y]]; +} + +/* @brief Division in Galua Fields + * @param x - dividend + * @param y - divisor + * @return x / y */ +inline uint8_t div(uint8_t x, uint8_t y){ + assert(y != 0); + if(x == 0) return 0; + return exp[(log[x] + 255 - log[y]) % 255]; +} + +/* @brief X in power Y w + * @param x - operand + * @param power - power + * @return x^power */ +inline uint8_t pow(uint8_t x, intmax_t power){ + intmax_t i = log[x]; + i *= power; + i %= 255; + if(i < 0) i = i + 255; + return exp[i]; +} + +/* @brief Inversion in Galua Fields + * @param x - number + * @return inversion of x */ +inline uint8_t inverse(uint8_t x){ + return exp[255 - log[x]]; /* == div(1, x); */ +} + +/* ########################## + * # POLYNOMIALS OPERATIONS # + * ########################## */ + +/* @brief Multiplication polynomial by scalar + * @param &p - source polynomial + * @param &newp - destination polynomial + * @param x - scalar */ +inline void +poly_scale(const Poly *p, Poly *newp, uint16_t x) { + newp->length = p->length; + for(uint16_t i = 0; i < p->length; i++){ + newp->at(i) = mul(p->at(i), x); + } +} + +/* @brief Addition of two polynomials + * @param &p - right operand polynomial + * @param &q - left operand polynomial + * @param &newp - destination polynomial */ +inline void +poly_add(const Poly *p, const Poly *q, Poly *newp) { + newp->length = poly_max(p->length, q->length); + memset(newp->ptr(), 0, newp->length * sizeof(uint8_t)); + + for(uint8_t i = 0; i < p->length; i++){ + newp->at(i + newp->length - p->length) = p->at(i); + } + + for(uint8_t i = 0; i < q->length; i++){ + newp->at(i + newp->length - q->length) ^= q->at(i); + } +} + + +/* @brief Multiplication of two polynomials + * @param &p - right operand polynomial + * @param &q - left operand polynomial + * @param &newp - destination polynomial */ +inline void +poly_mul(const Poly *p, const Poly *q, Poly *newp) { + newp->length = p->length + q->length - 1; + memset(newp->ptr(), 0, newp->length * sizeof(uint8_t)); + /* Compute the polynomial multiplication (just like the outer product of two vectors, + * we multiply each coefficients of p with all coefficients of q) */ + for(uint8_t j = 0; j < q->length; j++){ + for(uint8_t i = 0; i < p->length; i++){ + newp->at(i+j) ^= mul(p->at(i), q->at(j)); /* == r[i + j] = gf_add(r[i+j], gf_mul(p[i], q[j])) */ + } + } +} + +/* @brief Division of two polynomials + * @param &p - right operand polynomial + * @param &q - left operand polynomial + * @param &newp - destination polynomial */ +inline void +poly_div(const Poly *p, const Poly *q, Poly *newp) { + if(p->ptr() != newp->ptr()) { + memcpy(newp->ptr(), p->ptr(), p->length*sizeof(uint8_t)); + } + + newp->length = p->length; + + uint8_t coef; + + for(int i = 0; i < (p->length-(q->length-1)); i++){ + coef = newp->at(i); + if(coef != 0){ + for(uint8_t j = 1; j < q->length; j++){ + if(q->at(j) != 0) + newp->at(i+j) ^= mul(q->at(j), coef); + } + } + } + + size_t sep = p->length-(q->length-1); + memmove(newp->ptr(), newp->ptr()+sep, (newp->length-sep) * sizeof(uint8_t)); + newp->length = newp->length-sep; +} + +/* @brief Evaluation of polynomial in x + * @param &p - polynomial to evaluate + * @param x - evaluation point */ +inline int8_t +poly_eval(const Poly *p, uint16_t x) { + uint8_t y = p->at(0); + for(uint8_t i = 1; i < p->length; i++){ + y = mul(y, x) ^ p->at(i); + } + return y; +} + +} /* end of gf namespace */ + +} +#endif // GF_H + diff --git a/examples/r2t2/ggwave-mod/src/reed-solomon/poly.hpp b/examples/r2t2/ggwave-mod/src/reed-solomon/poly.hpp new file mode 100644 index 0000000..9e1b65f --- /dev/null +++ b/examples/r2t2/ggwave-mod/src/reed-solomon/poly.hpp @@ -0,0 +1,94 @@ +/* Author: Mike Lubinets (aka mersinvald) + * Date: 29.12.15 + * + * See LICENSE */ + +#ifndef POLY_H +#define POLY_H + +#include +#include +#include + +namespace RS { + +struct Poly { + Poly() + : length(0), _memory(NULL) {} + + Poly(uint8_t id, uint16_t offset, uint8_t size) \ + : length(0), _id(id), _size(size), _offset(offset), _memory(NULL) {} + + /* @brief Append number at the end of polynomial + * @param num - number to append + * @return false if polynomial can't be stretched */ + inline bool Append(uint8_t num) { + assert(length < _size); + ptr()[length++] = num; + return true; + } + + /* @brief Polynomial initialization */ + inline void Init(uint8_t id, uint16_t offset, uint8_t size, uint8_t** memory_ptr) { + this->_id = id; + this->_offset = offset; + this->_size = size; + this->length = 0; + this->_memory = memory_ptr; + } + + /* @brief Polynomial memory zeroing */ + inline void Reset() { + memset((void*)ptr(), 0, this->_size); + } + + /* @brief Copy polynomial to memory + * @param src - source byte-sequence + * @param size - size of polynomial + * @param offset - write offset */ + inline void Set(const uint8_t* src, uint8_t len, uint8_t offset = 0) { + assert(src && len <= this->_size-offset); + memcpy(ptr()+offset, src, len * sizeof(uint8_t)); + length = len + offset; + } + + #define poly_max(a, b) ((a > b) ? (a) : (b)) + + inline void Copy(const Poly* src) { + length = poly_max(length, src->length); + Set(src->ptr(), length); + } + + inline uint8_t& at(uint8_t i) const { + assert(i < _size); + return ptr()[i]; + } + + inline uint8_t id() const { + return _id; + } + + inline uint8_t size() const { + return _size; + } + + // Returns pointer to memory of this polynomial + inline uint8_t* ptr() const { + assert(_memory && *_memory); + return (*_memory) + _offset; + } + + uint8_t length; + +protected: + + uint8_t _id; + uint8_t _size; // Size of reserved memory for this polynomial + uint16_t _offset; // Offset in memory + uint8_t** _memory; // Pointer to pointer to memory +}; + + +} + +#endif // POLY_H diff --git a/examples/r2t2/ggwave-mod/src/reed-solomon/rs.hpp b/examples/r2t2/ggwave-mod/src/reed-solomon/rs.hpp new file mode 100644 index 0000000..202cdd5 --- /dev/null +++ b/examples/r2t2/ggwave-mod/src/reed-solomon/rs.hpp @@ -0,0 +1,538 @@ +/* Author: Mike Lubinets (aka mersinvald) + * Date: 29.12.15 + * + * See LICENSE */ + +#ifndef RS_HPP +#define RS_HPP + +#include "poly.hpp" +#include "gf.hpp" + +#include +#include +#include +#include + +namespace RS { + +#define MSG_CNT 3 // message-length polynomials count +#define POLY_CNT 14 // (ecc_length*2)-length polynomialc count + +class ReedSolomon { +public: + const uint8_t msg_length; + const uint8_t ecc_length; + + uint8_t * generator_cache = nullptr; + bool generator_cached = false; + + ReedSolomon(uint8_t msg_length_p, uint8_t ecc_length_p) : + msg_length(msg_length_p), ecc_length(ecc_length_p) { + generator_cache = new uint8_t[ecc_length + 1]; + + const uint8_t enc_len = msg_length + ecc_length; + const uint8_t poly_len = ecc_length * 2; + uint8_t** memptr = &memory; + uint16_t offset = 0; + + /* Initialize first six polys manually cause their amount depends on template parameters */ + + polynoms[0].Init(ID_MSG_IN, offset, enc_len, memptr); + offset += enc_len; + + polynoms[1].Init(ID_MSG_OUT, offset, enc_len, memptr); + offset += enc_len; + + for(uint8_t i = ID_GENERATOR; i < ID_MSG_E; i++) { + polynoms[i].Init(i, offset, poly_len, memptr); + offset += poly_len; + } + + polynoms[5].Init(ID_MSG_E, offset, enc_len, memptr); + offset += enc_len; + + for(uint8_t i = ID_TPOLY3; i < ID_ERR_EVAL+2; i++) { + polynoms[i].Init(i, offset, poly_len, memptr); + offset += poly_len; + } + } + + ~ReedSolomon() { + delete [] generator_cache; + // Dummy destructor, gcc-generated one crashes programm + memory = NULL; + } + + /* @brief Message block encoding + * @param *src - input message buffer (msg_lenth size) + * @param *dst - output buffer for ecc (ecc_length size at least) */ + void EncodeBlock(const void* src, void* dst) { + assert(msg_length + ecc_length < 256); + + ///* Allocating memory on stack for polynomials storage */ + //uint8_t stack_memory[MSG_CNT * msg_length + POLY_CNT * ecc_length * 2]; + //this->memory = stack_memory; + + // gg : allocation is now on the heap + std::vector stack_memory(MSG_CNT * msg_length + POLY_CNT * ecc_length * 2); + this->memory = stack_memory.data(); + + const uint8_t* src_ptr = (const uint8_t*) src; + uint8_t* dst_ptr = (uint8_t*) dst; + + Poly *msg_in = &polynoms[ID_MSG_IN]; + Poly *msg_out = &polynoms[ID_MSG_OUT]; + Poly *gen = &polynoms[ID_GENERATOR]; + + // Weird shit, but without reseting msg_in it simply doesn't work + msg_in->Reset(); + msg_out->Reset(); + + // Using cached generator or generating new one + if(generator_cached) { + gen->Set(generator_cache, ecc_length + 1); + } else { + GeneratorPoly(); + memcpy(generator_cache, gen->ptr(), gen->length); + generator_cached = true; + } + + // Copying input message to internal polynomial + msg_in->Set(src_ptr, msg_length); + msg_out->Set(src_ptr, msg_length); + msg_out->length = msg_in->length + ecc_length; + + // Here all the magic happens + uint8_t coef = 0; // cache + for(uint8_t i = 0; i < msg_length; i++){ + coef = msg_out->at(i); + if(coef != 0){ + for(uint32_t j = 1; j < gen->length; j++){ + msg_out->at(i+j) ^= gf::mul(gen->at(j), coef); + } + } + } + + // Copying ECC to the output buffer + memcpy(dst_ptr, msg_out->ptr()+msg_length, ecc_length * sizeof(uint8_t)); + } + + /* @brief Message encoding + * @param *src - input message buffer (msg_lenth size) + * @param *dst - output buffer (msg_length + ecc_length size at least) */ + void Encode(const void* src, void* dst) { + uint8_t* dst_ptr = (uint8_t*) dst; + + // Copying message to the output buffer + memcpy(dst_ptr, src, msg_length * sizeof(uint8_t)); + + // Calling EncodeBlock to write ecc to out[ut buffer + EncodeBlock(src, dst_ptr+msg_length); + } + + /* @brief Message block decoding + * @param *src - encoded message buffer (msg_length size) + * @param *ecc - ecc buffer (ecc_length size) + * @param *msg_out - output buffer (msg_length size at least) + * @param *erase_pos - known errors positions + * @param erase_count - count of known errors + * @return RESULT_SUCCESS if successfull, error code otherwise */ + int DecodeBlock(const void* src, const void* ecc, void* dst, uint8_t* erase_pos = NULL, size_t erase_count = 0) { + assert(msg_length + ecc_length < 256); + + const uint8_t *src_ptr = (const uint8_t*) src; + const uint8_t *ecc_ptr = (const uint8_t*) ecc; + uint8_t *dst_ptr = (uint8_t*) dst; + + const uint8_t src_len = msg_length + ecc_length; + const uint8_t dst_len = msg_length; + + bool ok; + + ///* Allocation memory on stack */ + //uint8_t stack_memory[MSG_CNT * msg_length + POLY_CNT * ecc_length * 2]; + //this->memory = stack_memory; + + // gg : allocation is now on the heap + std::vector stack_memory(MSG_CNT * msg_length + POLY_CNT * ecc_length * 2); + this->memory = stack_memory.data(); + + Poly *msg_in = &polynoms[ID_MSG_IN]; + Poly *msg_out = &polynoms[ID_MSG_OUT]; + Poly *epos = &polynoms[ID_ERASURES]; + + // Copying message to polynomials memory + msg_in->Set(src_ptr, msg_length); + msg_in->Set(ecc_ptr, ecc_length, msg_length); + msg_out->Copy(msg_in); + + // Copying known errors to polynomial + if(erase_pos == NULL) { + epos->length = 0; + } else { + epos->Set(erase_pos, erase_count); + for(uint8_t i = 0; i < epos->length; i++){ + msg_in->at(epos->at(i)) = 0; + } + } + + // Too many errors + if(epos->length > ecc_length) return 1; + + Poly *synd = &polynoms[ID_SYNDROMES]; + Poly *eloc = &polynoms[ID_ERRORS_LOC]; + Poly *reloc = &polynoms[ID_TPOLY1]; + Poly *err = &polynoms[ID_ERRORS]; + Poly *forney = &polynoms[ID_FORNEY]; + + // Calculating syndrome + CalcSyndromes(msg_in); + + // Checking for errors + bool has_errors = false; + for(uint8_t i = 0; i < synd->length; i++) { + if(synd->at(i) != 0) { + has_errors = true; + break; + } + } + + // Going to exit if no errors + if(!has_errors) goto return_corrected_msg; + + CalcForneySyndromes(synd, epos, src_len); + FindErrorLocator(forney, NULL, epos->length); + + // Reversing syndrome + // TODO optimize through special Poly flag + reloc->length = eloc->length; + for(int8_t i = eloc->length-1, j = 0; i >= 0; i--, j++){ + reloc->at(j) = eloc->at(i); + } + + // Fing errors + ok = FindErrors(reloc, src_len); + if(!ok) return 1; + + // Error happened while finding errors (so helpfull :D) + if(err->length == 0) return 1; + + /* Adding found errors with known */ + for(uint8_t i = 0; i < err->length; i++) { + epos->Append(err->at(i)); + } + + // Correcting errors + CorrectErrata(synd, epos, msg_in); + + return_corrected_msg: + // Wrighting corrected message to output buffer + msg_out->length = dst_len; + memcpy(dst_ptr, msg_out->ptr(), msg_out->length * sizeof(uint8_t)); + return 0; + } + + /* @brief Message block decoding + * @param *src - encoded message buffer (msg_length + ecc_length size) + * @param *msg_out - output buffer (msg_length size at least) + * @param *erase_pos - known errors positions + * @param erase_count - count of known errors + * @return RESULT_SUCCESS if successfull, error code otherwise */ + int Decode(const void* src, void* dst, uint8_t* erase_pos = NULL, size_t erase_count = 0) { + const uint8_t *src_ptr = (const uint8_t*) src; + const uint8_t *ecc_ptr = src_ptr + msg_length; + + return DecodeBlock(src, ecc_ptr, dst, erase_pos, erase_count); + } + +#ifndef DEBUG +private: +#endif + + enum POLY_ID { + ID_MSG_IN = 0, + ID_MSG_OUT, + ID_GENERATOR, // 3 + ID_TPOLY1, // T for Temporary + ID_TPOLY2, + + ID_MSG_E, // 5 + + ID_TPOLY3, // 6 + ID_TPOLY4, + + ID_SYNDROMES, + ID_FORNEY, + + ID_ERASURES_LOC, + ID_ERRORS_LOC, + + ID_ERASURES, + ID_ERRORS, + + ID_COEF_POS, + ID_ERR_EVAL + }; + + // Pointer for polynomials memory on stack + uint8_t* memory; + Poly polynoms[MSG_CNT + POLY_CNT]; + + void GeneratorPoly() { + Poly *gen = polynoms + ID_GENERATOR; + gen->at(0) = 1; + gen->length = 1; + + Poly *mulp = polynoms + ID_TPOLY1; + Poly *temp = polynoms + ID_TPOLY2; + mulp->length = 2; + + for(int8_t i = 0; i < ecc_length; i++){ + mulp->at(0) = 1; + mulp->at(1) = gf::pow(2, i); + + gf::poly_mul(gen, mulp, temp); + + gen->Copy(temp); + } + } + + void CalcSyndromes(const Poly *msg) { + Poly *synd = &polynoms[ID_SYNDROMES]; + synd->length = ecc_length+1; + synd->at(0) = 0; + for(uint8_t i = 1; i < ecc_length+1; i++){ + synd->at(i) = gf::poly_eval(msg, gf::pow(2, i-1)); + } + } + + void FindErrataLocator(const Poly *epos) { + Poly *errata_loc = &polynoms[ID_ERASURES_LOC]; + Poly *mulp = &polynoms[ID_TPOLY1]; + Poly *addp = &polynoms[ID_TPOLY2]; + Poly *apol = &polynoms[ID_TPOLY3]; + Poly *temp = &polynoms[ID_TPOLY4]; + + errata_loc->length = 1; + errata_loc->at(0) = 1; + + mulp->length = 1; + addp->length = 2; + + for(uint8_t i = 0; i < epos->length; i++){ + mulp->at(0) = 1; + addp->at(0) = gf::pow(2, epos->at(i)); + addp->at(1) = 0; + + gf::poly_add(mulp, addp, apol); + gf::poly_mul(errata_loc, apol, temp); + + errata_loc->Copy(temp); + } + } + + void FindErrorEvaluator(const Poly *synd, const Poly *errata_loc, Poly *dst, uint8_t ecclen) { + Poly *mulp = &polynoms[ID_TPOLY1]; + gf::poly_mul(synd, errata_loc, mulp); + + Poly *divisor = &polynoms[ID_TPOLY2]; + divisor->length = ecclen+2; + + divisor->Reset(); + divisor->at(0) = 1; + + gf::poly_div(mulp, divisor, dst); + } + + void CorrectErrata(const Poly *synd, const Poly *err_pos, const Poly *msg_in) { + Poly *c_pos = &polynoms[ID_COEF_POS]; + Poly *corrected = &polynoms[ID_MSG_OUT]; + c_pos->length = err_pos->length; + + for(uint8_t i = 0; i < err_pos->length; i++) + c_pos->at(i) = msg_in->length - 1 - err_pos->at(i); + + /* uses t_poly 1, 2, 3, 4 */ + FindErrataLocator(c_pos); + Poly *errata_loc = &polynoms[ID_ERASURES_LOC]; + + /* reversing syndromes */ + Poly *rsynd = &polynoms[ID_TPOLY3]; + rsynd->length = synd->length; + + for(int8_t i = synd->length-1, j = 0; i >= 0; i--, j++) { + rsynd->at(j) = synd->at(i); + } + + /* getting reversed error evaluator polynomial */ + Poly *re_eval = &polynoms[ID_TPOLY4]; + + /* uses T_POLY 1, 2 */ + FindErrorEvaluator(rsynd, errata_loc, re_eval, errata_loc->length-1); + + /* reversing it back */ + Poly *e_eval = &polynoms[ID_ERR_EVAL]; + e_eval->length = re_eval->length; + for(int8_t i = re_eval->length-1, j = 0; i >= 0; i--, j++) { + e_eval->at(j) = re_eval->at(i); + } + + Poly *X = &polynoms[ID_TPOLY1]; /* this will store errors positions */ + X->length = 0; + + int16_t l; + for(uint8_t i = 0; i < c_pos->length; i++){ + l = 255 - c_pos->at(i); + X->Append(gf::pow(2, -l)); + } + + /* Magnitude polynomial + Shit just got real */ + Poly *E = &polynoms[ID_MSG_E]; + E->Reset(); + E->length = msg_in->length; + + uint8_t Xi_inv; + + Poly *err_loc_prime_temp = &polynoms[ID_TPOLY2]; + + uint8_t err_loc_prime; + uint8_t y; + + for(uint8_t i = 0; i < X->length; i++){ + Xi_inv = gf::inverse(X->at(i)); + + err_loc_prime_temp->length = 0; + for(uint8_t j = 0; j < X->length; j++){ + if(j != i){ + err_loc_prime_temp->Append(gf::sub(1, gf::mul(Xi_inv, X->at(j)))); + } + } + + err_loc_prime = 1; + for(uint8_t j = 0; j < err_loc_prime_temp->length; j++){ + err_loc_prime = gf::mul(err_loc_prime, err_loc_prime_temp->at(j)); + } + + y = gf::poly_eval(re_eval, Xi_inv); + y = gf::mul(gf::pow(X->at(i), 1), y); + + E->at(err_pos->at(i)) = gf::div(y, err_loc_prime); + } + + gf::poly_add(msg_in, E, corrected); + } + + bool FindErrorLocator(const Poly *synd, Poly *erase_loc = NULL, size_t erase_count = 0) { + Poly *error_loc = &polynoms[ID_ERRORS_LOC]; + Poly *err_loc = &polynoms[ID_TPOLY1]; + Poly *old_loc = &polynoms[ID_TPOLY2]; + Poly *temp = &polynoms[ID_TPOLY3]; + Poly *temp2 = &polynoms[ID_TPOLY4]; + + if(erase_loc != NULL) { + err_loc->Copy(erase_loc); + old_loc->Copy(erase_loc); + } else { + err_loc->length = 1; + old_loc->length = 1; + err_loc->at(0) = 1; + old_loc->at(0) = 1; + } + + uint8_t synd_shift = 0; + if(synd->length > ecc_length) { + synd_shift = synd->length - ecc_length; + } + + uint8_t K = 0; + uint8_t delta = 0; + uint8_t index; + + for(uint8_t i = 0; i < ecc_length - erase_count; i++){ + if(erase_loc != NULL) + K = erase_count + i + synd_shift; + else + K = i + synd_shift; + + delta = synd->at(K); + for(uint8_t j = 1; j < err_loc->length; j++) { + index = err_loc->length - j - 1; + delta ^= gf::mul(err_loc->at(index), synd->at(K-j)); + } + + old_loc->Append(0); + + if(delta != 0) { + if(old_loc->length > err_loc->length) { + gf::poly_scale(old_loc, temp, delta); + gf::poly_scale(err_loc, old_loc, gf::inverse(delta)); + err_loc->Copy(temp); + } + gf::poly_scale(old_loc, temp, delta); + gf::poly_add(err_loc, temp, temp2); + err_loc->Copy(temp2); + } + } + + uint32_t shift = 0; + while(err_loc->length && err_loc->at(shift) == 0) shift++; + + uint32_t errs = err_loc->length - shift - 1; + if(((errs - erase_count) * 2 + erase_count) > ecc_length){ + return false; /* Error count is greater then we can fix! */ + } + + memcpy(error_loc->ptr(), err_loc->ptr() + shift, (err_loc->length - shift) * sizeof(uint8_t)); + error_loc->length = (err_loc->length - shift); + return true; + } + + bool FindErrors(const Poly *error_loc, size_t msg_in_size) { + Poly *err = &polynoms[ID_ERRORS]; + + uint8_t errs = error_loc->length - 1; + err->length = 0; + + for(uint8_t i = 0; i < msg_in_size; i++) { + if(gf::poly_eval(error_loc, gf::pow(2, i)) == 0) { + err->Append(msg_in_size - 1 - i); + } + } + + /* Sanity check: + * the number of err/errata positions found + * should be exactly the same as the length of the errata locator polynomial */ + if(err->length != errs) + /* couldn't find error locations */ + return false; + return true; + } + + void CalcForneySyndromes(const Poly *synd, const Poly *erasures_pos, size_t msg_in_size) { + Poly *erase_pos_reversed = &polynoms[ID_TPOLY1]; + Poly *forney_synd = &polynoms[ID_FORNEY]; + erase_pos_reversed->length = 0; + + for(uint8_t i = 0; i < erasures_pos->length; i++){ + erase_pos_reversed->Append(msg_in_size - 1 - erasures_pos->at(i)); + } + + forney_synd->Reset(); + forney_synd->Set(synd->ptr()+1, synd->length-1); + + uint8_t x; + for(uint8_t i = 0; i < erasures_pos->length; i++) { + x = gf::pow(2, erase_pos_reversed->at(i)); + for(int8_t j = 0; j < forney_synd->length - 1; j++){ + forney_synd->at(j) = gf::mul(forney_synd->at(j), x) ^ forney_synd->at(j+1); + } + } + } +}; + +} + +#endif // RS_HPP + diff --git a/examples/r2t2/ggwave-mod/src/resampler.cpp b/examples/r2t2/ggwave-mod/src/resampler.cpp new file mode 100644 index 0000000..4b68eb5 --- /dev/null +++ b/examples/r2t2/ggwave-mod/src/resampler.cpp @@ -0,0 +1,157 @@ +#include "resampler.h" + +#include +#include +#include + +namespace { +double linear_interp(double first_number, double second_number, double fraction) { + return (first_number + ((second_number - first_number)*fraction)); +} +} + +Resampler::Resampler() : + m_sincTable(kWidth*kSamplesPerZeroCrossing), + m_delayBuffer(3*kWidth), + m_edgeSamples(kWidth), + m_samplesInp(2048) { + make_sinc(); + reset(); +} + +void Resampler::reset() { + m_state = {}; + std::fill(m_edgeSamples.begin(), m_edgeSamples.end(), 0.0f); + std::fill(m_delayBuffer.begin(), m_delayBuffer.end(), 0.0f); + std::fill(m_samplesInp.begin(), m_samplesInp.end(), 0.0f); +} + +int Resampler::resample( + float factor, + int nSamples, + const float * samplesInp, + float * samplesOut) { + int idxInp = -1; + int idxOut = 0; + int notDone = 1; + float data_in = 0.0f; + float data_out = 0.0f; + double one_over_factor = 1.0; + + auto stateSave = m_state; + + m_state.nSamplesTotal += nSamples; + + if (samplesOut) { + assert(nSamples > kWidth); + if ((int) m_samplesInp.size() < nSamples + kWidth) { + m_samplesInp.resize(nSamples + kWidth); + } + for (int i = 0; i < kWidth; ++i) { + m_samplesInp[i] = m_edgeSamples[i]; + m_edgeSamples[i] = samplesInp[nSamples - kWidth + i]; + } + for (int i = 0; i < nSamples; ++i) { + m_samplesInp[i + kWidth] = samplesInp[i]; + } + samplesInp = m_samplesInp.data(); + } + + while (notDone) { + while (m_state.timeLast < m_state.timeInt) { + if (++idxInp >= nSamples) { + notDone = 0; + break; + } else { + data_in = samplesInp[idxInp]; + } + //printf("xxxx idxInp = %d\n", idxInp); + if (samplesOut) new_data(data_in); + m_state.timeLast += 1; + } + + if (notDone == false) break; + + double temp1 = 0.0; + int left_limit = m_state.timeNow - kWidth + 1; /* leftmost neighboring sample used for interp.*/ + int right_limit = m_state.timeNow + kWidth; /* rightmost leftmost neighboring sample used for interp.*/ + if (left_limit < 0) left_limit = 0; + if (right_limit > m_state.nSamplesTotal + kWidth) right_limit = m_state.nSamplesTotal + kWidth; + if (factor < 1.0) { + for (int j = left_limit; j < right_limit; j++) { + temp1 += gimme_data(j - m_state.timeInt)*sinc(m_state.timeNow - (double) j); + } + data_out = temp1; + } + else { + one_over_factor = 1.0 / factor; + for (int j = left_limit; j < right_limit; j++) { + temp1 += gimme_data(j - m_state.timeInt)*one_over_factor*sinc(one_over_factor*(m_state.timeNow - (double) j)); + } + data_out = temp1; + } + + if (samplesOut) { + //printf("inp = %d, l = %d, r = %d, n = %d, a = %d, b = %d\n", idxInp, left_limit, right_limit, m_state.nSamplesTotal, left_limit - m_state.timeInt, right_limit - m_state.timeInt - 1); + samplesOut[idxOut] = data_out; + } + ++idxOut; + + m_state.timeNow += factor; + m_state.timeLast = m_state.timeInt; + m_state.timeInt = m_state.timeNow; + while (m_state.timeLast < m_state.timeInt) { + if (++idxInp >= nSamples) { + notDone = 0; + break; + } else { + data_in = samplesInp[idxInp]; + } + if (samplesOut) new_data(data_in); + m_state.timeLast += 1; + } + //printf("last idxInp = %d, nSamples = %d\n", idxInp, nSamples); + } + + if (samplesOut == nullptr) { + m_state = stateSave; + } + + return idxOut; +} + +float Resampler::gimme_data(int j) const { + return m_delayBuffer[(int) j + kWidth]; +} + +void Resampler::new_data(float data) { + for (int i = 0; i < kDelaySize - 5; i++) { + m_delayBuffer[i] = m_delayBuffer[i + 1]; + } + m_delayBuffer[kDelaySize - 5] = data; +} + +void Resampler::make_sinc() { + double temp, win_freq, win; + win_freq = M_PI/kWidth/kSamplesPerZeroCrossing; + m_sincTable[0] = 1.0; + for (int i = 1; i < kWidth*kSamplesPerZeroCrossing; i++) { + temp = (double) i*M_PI/kSamplesPerZeroCrossing; + m_sincTable[i] = sin(temp)/temp; + win = 0.5 + 0.5*cos(win_freq*i); + m_sincTable[i] *= win; + } +} + +double Resampler::sinc(double x) const { + int low; + double temp, delta; + if (fabs(x) >= kWidth - 1) { + return 0.0; + } else { + temp = fabs(x)*(double) kSamplesPerZeroCrossing; + low = temp; /* these are interpolation steps */ + delta = temp - low; /* and can be ommited if desired */ + return linear_interp(m_sincTable[low], m_sincTable[low + 1], delta); + } +} diff --git a/examples/r2t2/ggwave-mod/src/resampler.h b/examples/r2t2/ggwave-mod/src/resampler.h new file mode 100644 index 0000000..87804c5 --- /dev/null +++ b/examples/r2t2/ggwave-mod/src/resampler.h @@ -0,0 +1,49 @@ +#pragma once + +#include +#include + +class Resampler { +public: + // this controls the number of neighboring samples + // which are used to interpolate the new samples. The + // processing time is linearly related to this width + static const int kWidth = 64; + + Resampler(); + + void reset(); + + int nSamplesTotal() const { return m_state.nSamplesTotal; } + + int resample( + float factor, + int nSamples, + const float * samplesInp, + float * samplesOut); + +private: + float gimme_data(int j) const; + void new_data(float data); + void make_sinc(); + double sinc(double x) const; + + static const int kDelaySize = 140; + + // this defines how finely the sinc function is sampled for storage in the table + static const int kSamplesPerZeroCrossing = 32; + + std::vector m_sincTable; + std::vector m_delayBuffer; + std::vector m_edgeSamples; + std::vector m_samplesInp; + + struct State { + int nSamplesTotal = 0; + int timeInt = 0; + int timeLast = 0; + double timeNow = 0.0; + }; + + State m_state; +}; diff --git a/examples/r2t2/index-tmpl.html b/examples/r2t2/index-tmpl.html new file mode 100644 index 0000000..7a2064d --- /dev/null +++ b/examples/r2t2/index-tmpl.html @@ -0,0 +1,174 @@ + + + + + r2t2 + + + + + + + +
+

r2t2

+ + Press the Init button and place the microphone near the PC speaker to receive messages + +

+ + + +
+ +

+ +

Standard output:

+ + +
+
Downloading...
+ +
+ +
+
+ +
+ + | + Build time: @GIT_DATE@ | + Commit hash: @GIT_SHA1@ | + Commit subject: @GIT_COMMIT_SUBJECT@ | + +
+ + + + + + + + diff --git a/examples/r2t2/main.cpp b/examples/r2t2/main.cpp new file mode 100644 index 0000000..cd59714 --- /dev/null +++ b/examples/r2t2/main.cpp @@ -0,0 +1,136 @@ +#include "ggwave/ggwave.h" + +#include "ggwave-common.h" + +#include +#include +#include +#include +#include +#include + +#define CONSOLE "/dev/tty0" + +#include +#include +#include +#include + +void processTone(int fd, double freq_hz, long duration_ms, bool useBeep, bool printTones) { + if (printTones) { + printf("TONE %8.2f Hz %5ld ms\n", freq_hz, duration_ms); + return; + } + + if (useBeep) { + static char cmd[128]; + snprintf(cmd, 128, "beep -f %g -l %ld", freq_hz, duration_ms); + system(cmd); + return; + } + + long pitch = std::round(1193180.0/freq_hz); + long ms = std::round(duration_ms); + ioctl(fd, KDMKTONE, (ms<<16)|pitch); + usleep(ms*1000); +} + +int main(int argc, char** argv) { + printf("Usage: %s [-tN] [-lN]\n", argv[0]); + printf(" -p - print tones, no playback\n"); + //printf(" -b - use 'beep' command\n"); + printf(" -tN - transmission protocol\n"); + printf(" -lN - fixed payload length of size N, N in [1, %d]\n", GGWave::kMaxLengthFixed); + printf("\n"); + + const GGWave::TxProtocols protocols = { + { GGWAVE_TX_PROTOCOL_CUSTOM_0, { "[R2T2] Normal", 64, 9, 1, } }, + { GGWAVE_TX_PROTOCOL_CUSTOM_1, { "[R2T2] Fast", 64, 6, 1, } }, + { GGWAVE_TX_PROTOCOL_CUSTOM_2, { "[R2T2] Fastest", 64, 3, 1, } }, + }; + + auto argm = parseCmdArguments(argc, argv); + bool printTones = argm.find("p") != argm.end(); + bool useBeep = false; //argm.find("b") != argm.end(); + int txProtocolId = argm["t"].empty() ? GGWAVE_TX_PROTOCOL_CUSTOM_0 : std::stoi(argm["t"]); + int payloadLength = argm["l"].empty() ? 16 : std::stoi(argm["l"]); + + GGWave ggWave({ + payloadLength, + GGWave::kBaseSampleRate, + GGWave::kBaseSampleRate, + GGWave::kDefaultSamplesPerFrame, + GGWave::kDefaultSoundMarkerThreshold, + GGWAVE_SAMPLE_FORMAT_F32, + GGWAVE_SAMPLE_FORMAT_F32}); + + printf("Available Tx protocols:\n"); + for (const auto & protocol : protocols) { + printf(" -t%d : %s\n", protocol.first, protocol.second.name); + } + + if (protocols.find(GGWave::TxProtocolId(txProtocolId)) == protocols.end()) { + fprintf(stderr, "Unknown Tx protocol %d\n", txProtocolId); + return -3; + } + + printf("Selecting Tx protocol %d\n", txProtocolId); + + int fd = 1; + if (useBeep == false && printTones == false) { + if (ioctl(fd, KDMKTONE, 0)) { + fd = open(CONSOLE, O_RDONLY); + } + if (fd < 0) { + perror(CONSOLE); + fprintf(stderr, "This program must be run as root\n"); + return 1; + } + } + + fprintf(stderr, "Enter a text message:\n"); + + std::string message; + std::getline(std::cin, message); + + printf("\n"); + + if (message.size() == 0) { + fprintf(stderr, "Invalid message: size = 0\n"); + return -2; + } + + if ((int) message.size() > payloadLength) { + fprintf(stderr, "Invalid message: size > %d\n", payloadLength); + return -3; + } + + ggWave.init(message.size(), message.data(), protocols.at(GGWave::TxProtocolId(txProtocolId)), 10); + + GGWave::CBWaveformOut tmp = [](const void * , uint32_t ){}; + ggWave.encode(tmp); + + int nFrames = 0; + double lastF = -1.0f; + + auto tones = ggWave.getWaveformTones(); + for (auto & tonesCur : tones) { + if (tonesCur.size() == 0) continue; + const auto & tone = tonesCur.front(); + if (tone.freq_hz != lastF) { + if (nFrames > 0) { + processTone(fd, lastF, nFrames*tone.duration_ms, useBeep, printTones); + } + nFrames = 0; + lastF = tone.freq_hz; + } + ++nFrames; + } + + if (nFrames > 0) { + const auto & tone = tones.front().front(); + processTone(fd, lastF, nFrames*tone.duration_ms, useBeep, printTones); + } + + return 0; +} diff --git a/examples/r2t2/main.js b/examples/r2t2/main.js new file mode 100644 index 0000000..ee39e55 --- /dev/null +++ b/examples/r2t2/main.js @@ -0,0 +1,55 @@ +function transmitText(sText) { + var r = new Uint8Array(256); + for (var i = 0; i < sText.length; ++i) { + r[i] = sText.charCodeAt(i); + } + + var buffer = Module._malloc(256); + Module.writeArrayToMemory(r, buffer, 256); + Module._sendData(sText.length, buffer, protocolId, volume); + Module._free(buffer); +} + +var firstTimeFail = false; +var peerInfo = document.querySelector('a#peer-info'); + +function updatePeerInfo() { + if (typeof Module === 'undefined') return; + var framesLeftToRecord = Module._getFramesLeftToRecord(); + var framesToRecord = Module._getFramesToRecord(); + var framesLeftToAnalyze = Module._getFramesLeftToAnalyze(); + var framesToAnalyze = Module._getFramesToAnalyze(); + + if (framesToAnalyze > 0) { + peerInfo.innerHTML= + "Analyzing Rx data: "; + peerReceive.innerHTML= ""; + } else if (framesLeftToRecord > Math.max(0, 0.05*framesToRecord)) { + firstTimeFail = true; + peerInfo.innerHTML= + "Transmission in progress: "; + } else if (framesToRecord > 0) { + peerInfo.innerHTML= "Analyzing Rx data ..."; + } else if (framesToRecord == 0) { + peerInfo.innerHTML= "

Listening for waves ...

"; + } else if (framesToRecord == -1) { + if (firstTimeFail) { + playSound("/media/case-closed"); + firstTimeFail = false; + } + peerInfo.innerHTML= "

Failed to decode Rx data

"; + } +} + +function updateRx() { + if (typeof Module === 'undefined') return; + Module._getText(bufferRx); + var result = ""; + for (var i = 0; i < 140; ++i){ + result += (String.fromCharCode((Module.HEAPU8)[bufferRx + i])); + brx[i] = (Module.HEAPU8)[bufferRx + i]; + } + document.getElementById('rxData').innerHTML = result; +} diff --git a/examples/r2t2/plucky.mp3 b/examples/r2t2/plucky.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..367a0e90b38a5969c5fcd6f1421fa432fc3f09a0 GIT binary patch literal 28003 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 Udj2Ek{r}}V|NrCvFHhkA01tk+TmS$7 literal 0 HcmV?d00001 diff --git a/examples/r2t2/r2t2-rx.cpp b/examples/r2t2/r2t2-rx.cpp new file mode 100644 index 0000000..9189d22 --- /dev/null +++ b/examples/r2t2/r2t2-rx.cpp @@ -0,0 +1,369 @@ +#include "ggwave-common.h" + +#include "ggwave/ggwave.h" + +#ifdef __EMSCRIPTEN__ +#include "build_timestamp.h" +#include +#else +#define EMSCRIPTEN_KEEPALIVE +#endif + +#include +#include + +#include +#include +#include + +namespace { + +std::string g_defaultCaptureDeviceName = ""; + +SDL_AudioDeviceID g_devIdInp = 0; +SDL_AudioDeviceID g_devIdOut = 0; + +SDL_AudioSpec g_obtainedSpecInp; +SDL_AudioSpec g_obtainedSpecOut; + +GGWave *g_ggWave = nullptr; + +} + +static std::function g_doInit; +static std::function g_setWindowSize; +static std::function g_mainUpdate; + +void mainUpdate(void *) { + g_mainUpdate(); +} + +// JS interface + +extern "C" { + EMSCRIPTEN_KEEPALIVE + int sendData(int textLength, const char * text, int protocolId, int volume) { + g_ggWave->init(textLength, text, g_ggWave->getTxProtocol(protocolId), volume); + return 0; + } + + EMSCRIPTEN_KEEPALIVE + int getText(char * text) { + std::copy(g_ggWave->getRxData().begin(), g_ggWave->getRxData().end(), text); + return 0; + } + + EMSCRIPTEN_KEEPALIVE + float getSampleRate() { return g_ggWave->getSampleRateInp(); } + + EMSCRIPTEN_KEEPALIVE + int getFramesToRecord() { return g_ggWave->getFramesToRecord(); } + + EMSCRIPTEN_KEEPALIVE + int getFramesLeftToRecord() { return g_ggWave->getFramesLeftToRecord(); } + + EMSCRIPTEN_KEEPALIVE + int getFramesToAnalyze() { return g_ggWave->getFramesToAnalyze(); } + + EMSCRIPTEN_KEEPALIVE + int getFramesLeftToAnalyze() { return g_ggWave->getFramesLeftToAnalyze(); } + + EMSCRIPTEN_KEEPALIVE + int hasDeviceOutput() { return g_devIdOut; } + + EMSCRIPTEN_KEEPALIVE + int hasDeviceCapture() { return g_devIdInp; } + + EMSCRIPTEN_KEEPALIVE + int doInit() { + return g_doInit(); + } +} + +void GGWave_setDefaultCaptureDeviceName(std::string name) { + g_defaultCaptureDeviceName = std::move(name); +} + +bool GGWave_init( + const int playbackId, + const int captureId, + const int payloadLength, + const float sampleRateOffset) { + + if (g_devIdInp && g_devIdOut) { + return false; + } + + if (g_devIdInp == 0 && g_devIdOut == 0) { + SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); + + if (SDL_Init(SDL_INIT_AUDIO) < 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError()); + return (1); + } + + SDL_SetHintWithPriority(SDL_HINT_AUDIO_RESAMPLING_MODE, "medium", SDL_HINT_OVERRIDE); + + { + int nDevices = SDL_GetNumAudioDevices(SDL_FALSE); + printf("Found %d playback devices:\n", nDevices); + for (int i = 0; i < nDevices; i++) { + printf(" - Playback device #%d: '%s'\n", i, SDL_GetAudioDeviceName(i, SDL_FALSE)); + } + } + { + int nDevices = SDL_GetNumAudioDevices(SDL_TRUE); + printf("Found %d capture devices:\n", nDevices); + for (int i = 0; i < nDevices; i++) { + printf(" - Capture device #%d: '%s'\n", i, SDL_GetAudioDeviceName(i, SDL_TRUE)); + } + } + } + + bool reinit = false; + + if (g_devIdOut == 0) { + printf("Initializing playback ...\n"); + + SDL_AudioSpec playbackSpec; + SDL_zero(playbackSpec); + + playbackSpec.freq = GGWave::kBaseSampleRate + sampleRateOffset; + playbackSpec.format = AUDIO_S16SYS; + playbackSpec.channels = 1; + playbackSpec.samples = 16*1024; + playbackSpec.callback = NULL; + + SDL_zero(g_obtainedSpecOut); + + if (playbackId >= 0) { + printf("Attempt to open playback device %d : '%s' ...\n", playbackId, SDL_GetAudioDeviceName(playbackId, SDL_FALSE)); + g_devIdOut = SDL_OpenAudioDevice(SDL_GetAudioDeviceName(playbackId, SDL_FALSE), SDL_FALSE, &playbackSpec, &g_obtainedSpecOut, 0); + } else { + printf("Attempt to open default playback device ...\n"); + g_devIdOut = SDL_OpenAudioDevice(NULL, SDL_FALSE, &playbackSpec, &g_obtainedSpecOut, 0); + } + + if (!g_devIdOut) { + printf("Couldn't open an audio device for playback: %s!\n", SDL_GetError()); + g_devIdOut = 0; + } else { + printf("Obtained spec for output device (SDL Id = %d):\n", g_devIdOut); + printf(" - Sample rate: %d (required: %d)\n", g_obtainedSpecOut.freq, playbackSpec.freq); + printf(" - Format: %d (required: %d)\n", g_obtainedSpecOut.format, playbackSpec.format); + printf(" - Channels: %d (required: %d)\n", g_obtainedSpecOut.channels, playbackSpec.channels); + printf(" - Samples per frame: %d (required: %d)\n", g_obtainedSpecOut.samples, playbackSpec.samples); + + if (g_obtainedSpecOut.format != playbackSpec.format || + g_obtainedSpecOut.channels != playbackSpec.channels || + g_obtainedSpecOut.samples != playbackSpec.samples) { + g_devIdOut = 0; + SDL_CloseAudio(); + fprintf(stderr, "Failed to initialize playback SDL_OpenAudio!"); + + return false; + } + + reinit = true; + } + } + + if (g_devIdInp == 0) { + SDL_AudioSpec captureSpec; + captureSpec = g_obtainedSpecOut; + captureSpec.freq = GGWave::kBaseSampleRate + sampleRateOffset; + captureSpec.format = AUDIO_F32SYS; + captureSpec.samples = 1024; + + SDL_zero(g_obtainedSpecInp); + + if (captureId >= 0) { + printf("Attempt to open capture device %d : '%s' ...\n", captureId, SDL_GetAudioDeviceName(captureId, SDL_TRUE)); + g_devIdInp = SDL_OpenAudioDevice(SDL_GetAudioDeviceName(captureId, SDL_TRUE), SDL_TRUE, &captureSpec, &g_obtainedSpecInp, 0); + } else { + printf("Attempt to open default capture device ...\n"); + g_devIdInp = SDL_OpenAudioDevice(g_defaultCaptureDeviceName.empty() ? nullptr : g_defaultCaptureDeviceName.c_str(), + SDL_TRUE, &captureSpec, &g_obtainedSpecInp, 0); + } + if (!g_devIdInp) { + printf("Couldn't open an audio device for capture: %s!\n", SDL_GetError()); + g_devIdInp = 0; + } else { + printf("Obtained spec for input device (SDL Id = %d):\n", g_devIdInp); + printf(" - Sample rate: %d\n", g_obtainedSpecInp.freq); + printf(" - Format: %d (required: %d)\n", g_obtainedSpecInp.format, captureSpec.format); + printf(" - Channels: %d (required: %d)\n", g_obtainedSpecInp.channels, captureSpec.channels); + printf(" - Samples per frame: %d\n", g_obtainedSpecInp.samples); + + reinit = true; + } + } + + GGWave::SampleFormat sampleFormatInp = GGWAVE_SAMPLE_FORMAT_UNDEFINED; + GGWave::SampleFormat sampleFormatOut = GGWAVE_SAMPLE_FORMAT_UNDEFINED; + + switch (g_obtainedSpecInp.format) { + case AUDIO_U8: sampleFormatInp = GGWAVE_SAMPLE_FORMAT_U8; break; + case AUDIO_S8: sampleFormatInp = GGWAVE_SAMPLE_FORMAT_I8; break; + case AUDIO_U16SYS: sampleFormatInp = GGWAVE_SAMPLE_FORMAT_U16; break; + case AUDIO_S16SYS: sampleFormatInp = GGWAVE_SAMPLE_FORMAT_I16; break; + case AUDIO_S32SYS: sampleFormatInp = GGWAVE_SAMPLE_FORMAT_F32; break; + case AUDIO_F32SYS: sampleFormatInp = GGWAVE_SAMPLE_FORMAT_F32; break; + } + + switch (g_obtainedSpecOut.format) { + case AUDIO_U8: sampleFormatOut = GGWAVE_SAMPLE_FORMAT_U8; break; + case AUDIO_S8: sampleFormatOut = GGWAVE_SAMPLE_FORMAT_I8; break; + case AUDIO_U16SYS: sampleFormatOut = GGWAVE_SAMPLE_FORMAT_U16; break; + case AUDIO_S16SYS: sampleFormatOut = GGWAVE_SAMPLE_FORMAT_I16; break; + case AUDIO_S32SYS: sampleFormatOut = GGWAVE_SAMPLE_FORMAT_F32; break; + case AUDIO_F32SYS: sampleFormatOut = GGWAVE_SAMPLE_FORMAT_F32; break; + break; + } + + if (reinit) { + if (g_ggWave) delete g_ggWave; + + g_ggWave = new GGWave({ + payloadLength, + (float) g_obtainedSpecInp.freq, + (float) g_obtainedSpecOut.freq, + GGWave::kDefaultSamplesPerFrame, + GGWave::kDefaultSoundMarkerThreshold, + sampleFormatInp, + sampleFormatOut}); + } + + return true; +} + +GGWave *& GGWave_instance() { return g_ggWave; } + +bool GGWave_mainLoop() { + if (g_devIdInp == 0 && g_devIdOut == 0) { + return false; + } + + static GGWave::CBWaveformOut cbWaveformOut = [&](const void * data, uint32_t nBytes) { + SDL_QueueAudio(g_devIdOut, data, nBytes); + }; + + static GGWave::CBWaveformInp cbWaveformInp = [&](void * data, uint32_t nMaxBytes) { + return SDL_DequeueAudio(g_devIdInp, data, nMaxBytes); + }; + + if (g_ggWave->hasTxData() == false) { + SDL_PauseAudioDevice(g_devIdOut, SDL_FALSE); + + static auto tLastNoData = std::chrono::high_resolution_clock::now(); + auto tNow = std::chrono::high_resolution_clock::now(); + + if ((int) SDL_GetQueuedAudioSize(g_devIdOut) < g_ggWave->getSamplesPerFrame()*g_ggWave->getSampleSizeBytesOut()) { + SDL_PauseAudioDevice(g_devIdInp, SDL_FALSE); + if (::getTime_ms(tLastNoData, tNow) > 500.0f) { + g_ggWave->decode(cbWaveformInp); + if ((int) SDL_GetQueuedAudioSize(g_devIdInp) > 32*g_ggWave->getSamplesPerFrame()*g_ggWave->getSampleSizeBytesInp()) { + fprintf(stderr, "Warning: slow processing, clearing queued audio buffer of %d bytes ...", SDL_GetQueuedAudioSize(g_devIdInp)); + SDL_ClearQueuedAudio(g_devIdInp); + } + } else { + SDL_ClearQueuedAudio(g_devIdInp); + } + } else { + tLastNoData = tNow; + } + } else { + SDL_PauseAudioDevice(g_devIdOut, SDL_TRUE); + SDL_PauseAudioDevice(g_devIdInp, SDL_TRUE); + + g_ggWave->encode(cbWaveformOut); + } + + return true; +} + +bool GGWave_deinit() { + if (g_devIdInp == 0 && g_devIdOut == 0) { + return false; + } + + delete g_ggWave; + g_ggWave = nullptr; + + SDL_PauseAudioDevice(g_devIdInp, 1); + SDL_CloseAudioDevice(g_devIdInp); + SDL_PauseAudioDevice(g_devIdOut, 1); + SDL_CloseAudioDevice(g_devIdOut); + + g_devIdInp = 0; + g_devIdOut = 0; + + return true; +} + +int main(int argc, char** argv) { +#ifdef __EMSCRIPTEN__ + printf("Build time: %s\n", BUILD_TIMESTAMP); + printf("Press the Init button to start\n"); + + if (argv[1]) { + GGWave_setDefaultCaptureDeviceName(argv[1]); + } +#endif + + const GGWave::TxProtocols protocols = { + { GGWAVE_TX_PROTOCOL_CUSTOM_0, { "[R2T2] Normal", 64, 9, 1, } }, + { GGWAVE_TX_PROTOCOL_CUSTOM_1, { "[R2T2] Fast", 64, 6, 1, } }, + { GGWAVE_TX_PROTOCOL_CUSTOM_2, { "[R2T2] Fastest", 64, 3, 1, } }, + }; + + auto argm = parseCmdArguments(argc, argv); + int captureId = argm["c"].empty() ? 0 : std::stoi(argm["c"]); + + bool isInitialized = false; + + g_doInit = [&]() { + if (GGWave_init(0, captureId, 16, 0) == false) { + fprintf(stderr, "Failed to initialize GGWave\n"); + return false; + } + + g_ggWave->setRxProtocols(protocols); + + isInitialized = true; + + return true; + }; + + g_mainUpdate = [&]() { + if (isInitialized == false) { + return true; + } + + GGWave_mainLoop(); + + return true; + }; + +#ifdef __EMSCRIPTEN__ + emscripten_set_main_loop_arg(mainUpdate, NULL, 60, true); +#else + if (g_doInit() == false) { + printf("Error: failed to initialize audio\n"); + return -2; + } + + while (true) { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + if (g_mainUpdate() == false) break; + } + + GGWave_deinit(); + + // Cleanup + SDL_CloseAudio(); + SDL_Quit(); +#endif + + return 0; +} diff --git a/examples/r2t2/style.css b/examples/r2t2/style.css new file mode 100644 index 0000000..6b269f7 --- /dev/null +++ b/examples/r2t2/style.css @@ -0,0 +1,279 @@ +body { + margin: 0; background-color: white; + -webkit-font-smoothing: subpixel-antialiased; + font-smoothing: subpixel-antialiased; +} +#screen { + margin: 0; + padding: 0; + font-size: 13px; + height: 100%; + font: sans-serif; +} +.no-sel { + -moz-user-select: none; + -webkit-user-select: none; + -webkit-touch-callout: none; + -ms-user-select:none; + user-select:none; + -o-user-select:none; +} +.cell { + pointer-events: none; +} +.cell-version { + padding-left: 4px; + padding-top: 0.5em; + text-align: left; + display: inline-block; + float: left; + color: rgba(0, 0, 0, 0.75); +} +.cell-about { + padding-right: 24px; + padding-top: 0.5em; + text-align: right; + display: inline-block; + float: right; +} +.nav-link { + text-decoration: none; + color: rgba(0, 0, 0, 1.0); +} + +#main-container { + font-size:12px; + font-family: monospace; +} + +textarea { + font-size:12px; + font-family: monospace; +} + +.emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; } +div.emscripten { text-align: center; } +div.emscripten_border { border: 1px solid black; } + +canvas.emscripten { border: 0px none; background-color: black; } + +.spinner { + height: 30px; + width: 30px; + margin: 0; + margin-top: 20px; + margin-left: 20px; + display: inline-block; + vertical-align: top; + + -webkit-animation: rotation .8s linear infinite; + -moz-animation: rotation .8s linear infinite; + -o-animation: rotation .8s linear infinite; + animation: rotation 0.8s linear infinite; + + border-left: 5px solid rgb(235, 235, 235); + border-right: 5px solid rgb(235, 235, 235); + border-bottom: 5px solid rgb(235, 235, 235); + border-top: 5px solid rgb(120, 120, 120); + + border-radius: 100%; + background-color: rgb(189, 215, 46); +} + +@-webkit-keyframes rotation { + from {-webkit-transform: rotate(0deg);} + to {-webkit-transform: rotate(360deg);} +} +@-moz-keyframes rotation { + from {-moz-transform: rotate(0deg);} + to {-moz-transform: rotate(360deg);} +} +@-o-keyframes rotation { + from {-o-transform: rotate(0deg);} + to {-o-transform: rotate(360deg);} +} +@keyframes rotation { + from {transform: rotate(0deg);} + to {transform: rotate(360deg);} +} + +#status { + display: inline-block; + vertical-align: top; + margin-top: 30px; + margin-left: 20px; + font-weight: bold; + color: rgb(120, 120, 120); +} + +#progress { + height: 20px; + width: 30px; +} + +#output { + width: 100%; + height: 200px; + margin: 0 auto; + margin-top: 10px; + border-left: 0px; + border-right: 0px; + padding-left: 0px; + padding-right: 0px; + background-color: black; + color: white; + font-size:10px; + font-family: 'Lucida Console', Monaco, monospace; + outline: none; +} + +.led-box { + height: 30px; + width: 25%; + margin: 10px 0; + float: left; +} + +.led-box p { + font-size: 12px; + text-align: center; + margin: 1em; +} + +.led-red { + margin: 0 auto; + width: 12px; + height: 12px; + background-color: #F00; + border-radius: 50%; + box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #441313 0 -1px 9px, rgba(255, 0, 0, 0.5) 0 2px 12px; + -webkit-animation: blinkRed 0.5s infinite; + -moz-animation: blinkRed 0.5s infinite; + -ms-animation: blinkRed 0.5s infinite; + -o-animation: blinkRed 0.5s infinite; + animation: blinkRed 0.5s infinite; +} + +@-webkit-keyframes blinkRed { + from { background-color: #F00; } + 50% { background-color: #A00; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #441313 0 -1px 9px, rgba(255, 0, 0, 0.5) 0 2px 0;} + to { background-color: #F00; } +} +@-moz-keyframes blinkRed { + from { background-color: #F00; } + 50% { background-color: #A00; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #441313 0 -1px 9px, rgba(255, 0, 0, 0.5) 0 2px 0;} + to { background-color: #F00; } +} +@-ms-keyframes blinkRed { + from { background-color: #F00; } + 50% { background-color: #A00; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #441313 0 -1px 9px, rgba(255, 0, 0, 0.5) 0 2px 0;} + to { background-color: #F00; } +} +@-o-keyframes blinkRed { + from { background-color: #F00; } + 50% { background-color: #A00; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #441313 0 -1px 9px, rgba(255, 0, 0, 0.5) 0 2px 0;} + to { background-color: #F00; } +} +@keyframes blinkRed { + from { background-color: #F00; } + 50% { background-color: #A00; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #441313 0 -1px 9px, rgba(255, 0, 0, 0.5) 0 2px 0;} + to { background-color: #F00; } +} + +.led-yellow { + margin: 0 auto; + width: 12px; + height: 12px; + background-color: #FF0; + border-radius: 50%; + box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #808002 0 -1px 9px, #FF0 0 2px 12px; + -webkit-animation: blinkYellow 1s infinite; + -moz-animation: blinkYellow 1s infinite; + -ms-animation: blinkYellow 1s infinite; + -o-animation: blinkYellow 1s infinite; + animation: blinkYellow 1s infinite; +} + +@-webkit-keyframes blinkYellow { + from { background-color: #FF0; } + 50% { background-color: #AA0; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #808002 0 -1px 9px, #FF0 0 2px 0; } + to { background-color: #FF0; } +} +@-moz-keyframes blinkYellow { + from { background-color: #FF0; } + 50% { background-color: #AA0; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #808002 0 -1px 9px, #FF0 0 2px 0; } + to { background-color: #FF0; } +} +@-ms-keyframes blinkYellow { + from { background-color: #FF0; } + 50% { background-color: #AA0; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #808002 0 -1px 9px, #FF0 0 2px 0; } + to { background-color: #FF0; } +} +@-o-keyframes blinkYellow { + from { background-color: #FF0; } + 50% { background-color: #AA0; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #808002 0 -1px 9px, #FF0 0 2px 0; } + to { background-color: #FF0; } +} +@keyframes blinkYellow { + from { background-color: #FF0; } + 50% { background-color: #AA0; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #808002 0 -1px 9px, #FF0 0 2px 0; } + to { background-color: #FF0; } +} + +.led-green { + margin: 0 auto; + width: 12px; + height: 12px; + background-color: #ABFF00; + border-radius: 50%; + box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #304701 0 -1px 9px, #89FF00 0 2px 12px; +} + +.led-blue { + margin: 0 auto; + width: 18px; + height: 18px; + background-color: #24E0FF; + border-radius: 50%; + box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #006 0 -1px 9px, #3F8CFF 0 2px 14px; +} + +table td { + border: 1px solid #e8e8e8; +} +table th, table td { + padding: 10px 10px; +} +table td { + border: 1px solid #e8e8e8; +} +table th, table td { + padding: 10px 10px; +} +td[Attributes Style] { + text-align: -webkit-center; +} +td { + display: table-cell; + vertical-align: inherit; +} +table { + margin-bottom: 30px; + width: 800px; + text-align: left; + color: #3f3f3f; + border-collapse: collapse; + border: 1px solid #e8e8e8; +} +table { + margin-bottom: 30px; + width: 800px; + text-align: left; + color: #3f3f3f; + border-collapse: collapse; + border: 1px solid #e8e8e8; +} +table { + border-collapse: separate; + border-spacing: 2px; +} diff --git a/examples/spectrogram/main.cpp b/examples/spectrogram/main.cpp index ac51386..c33880b 100644 --- a/examples/spectrogram/main.cpp +++ b/examples/spectrogram/main.cpp @@ -556,7 +556,7 @@ int main(int argc, char** argv) { }; #ifdef __EMSCRIPTEN__ - emscripten_set_main_loop_arg(mainUpdate, NULL, 0, true); + emscripten_set_main_loop_arg(mainUpdate, NULL, 60, true); #else if (g_doInit() == false) { printf("Error: failed to initialize audio\n"); diff --git a/examples/waver/main.cpp b/examples/waver/main.cpp index ba72040..bcd4969 100644 --- a/examples/waver/main.cpp +++ b/examples/waver/main.cpp @@ -303,7 +303,7 @@ int main(int argc, char** argv) { }; #ifdef __EMSCRIPTEN__ - emscripten_set_main_loop_arg(mainUpdate, NULL, 0, true); + emscripten_set_main_loop_arg(mainUpdate, NULL, 60, true); #else if (g_doInit() == false) { printf("Error: failed to initialize audio\n"); diff --git a/include/ggwave/ggwave.h b/include/ggwave/ggwave.h index 58f7d37..5753993 100644 --- a/include/ggwave/ggwave.h +++ b/include/ggwave/ggwave.h @@ -44,6 +44,17 @@ extern "C" { GGWAVE_TX_PROTOCOL_DT_NORMAL, GGWAVE_TX_PROTOCOL_DT_FAST, GGWAVE_TX_PROTOCOL_DT_FASTEST, + + GGWAVE_TX_PROTOCOL_CUSTOM_0, + GGWAVE_TX_PROTOCOL_CUSTOM_1, + GGWAVE_TX_PROTOCOL_CUSTOM_2, + GGWAVE_TX_PROTOCOL_CUSTOM_3, + GGWAVE_TX_PROTOCOL_CUSTOM_4, + GGWAVE_TX_PROTOCOL_CUSTOM_5, + GGWAVE_TX_PROTOCOL_CUSTOM_6, + GGWAVE_TX_PROTOCOL_CUSTOM_7, + GGWAVE_TX_PROTOCOL_CUSTOM_8, + GGWAVE_TX_PROTOCOL_CUSTOM_9, } ggwave_TxProtocolId; // GGWave instance parameters