speaker-calibration 2.2.206 → 2.2.207
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintignore +71 -71
- package/.eslintrc.json +40 -40
- package/.github/workflows/update-phrases.yml +37 -0
- package/.prettierignore +69 -69
- package/.prettierrc +14 -14
- package/LICENSE +20 -20
- package/README.md +133 -133
- package/__mocks__/fileMock.js +1 -1
- package/__mocks__/styleMock.js +1 -1
- package/babel.config.js +3 -3
- package/coverage/clover.xml +71 -71
- package/coverage/coverage-final.json +224 -224
- package/coverage/lcov-report/PythonServerInterface.js.html +265 -265
- package/coverage/lcov-report/base.css +354 -354
- package/coverage/lcov-report/block-navigation.js +82 -82
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +123 -123
- package/coverage/lcov-report/prettify.css +101 -101
- package/coverage/lcov-report/prettify.js +937 -937
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +189 -189
- package/coverage/lcov-report/src/index.html +121 -121
- package/coverage/lcov-report/src/server/PythonServerInterface.js.html +268 -268
- package/coverage/lcov-report/src/server/index.html +123 -123
- package/coverage/lcov-report/src/tasks/audioCalibrator.js.html +499 -499
- package/coverage/lcov-report/src/tasks/audioRecorder.js.html +412 -412
- package/coverage/lcov-report/src/tasks/index.html +143 -143
- package/coverage/lcov-report/src/tasks/volume/index.html +123 -123
- package/coverage/lcov-report/src/tasks/volume/volume.js.html +409 -409
- package/coverage/lcov-report/src/utils.js.html +172 -172
- package/coverage/lcov.info +91 -91
- package/dist/Procfile +0 -0
- package/dist/example/NoSleep.min.js +1 -1
- package/dist/example/credentials.json.gpg +0 -0
- package/dist/example/fetch-languages-sheets.js +77 -77
- package/dist/example/i18n.js +27366 -27366
- package/dist/example/index.html +47 -47
- package/dist/example/listener.html +79 -79
- package/dist/example/listener.js +152 -152
- package/dist/example/server.js +51 -51
- package/dist/example/speaker.html +145 -145
- package/dist/example/speakerUI.js +273 -273
- package/dist/example/styles.css +99 -99
- package/dist/main.js +17 -17
- package/dist/main.js.LICENSE.txt +0 -0
- package/dist/mlsGen.js +6814 -6814
- package/dist/mlsGen.wasm +0 -0
- package/dist/package-lock.json +1018 -1018
- package/dist/package.json +18 -18
- package/doc/AudioCalibrator.html +417 -417
- package/doc/AudioPeer.html +251 -251
- package/doc/AudioRecorder.html +195 -195
- package/doc/ImpulseResponse.html +215 -215
- package/doc/Listener.html +308 -308
- package/doc/MlsGenInterface.html +226 -226
- package/doc/MyEventEmitter.html +274 -274
- package/doc/PythonServerAPI.html +109 -109
- package/doc/Speaker-Calibration-UML-Diagram.png +0 -0
- package/doc/Speaker.html +276 -276
- package/doc/Takes%20a%20target%20element%20where%20html%20elements%20will%20be%20appended..html +128 -128
- package/doc/Takes%20the%20url%20of%20the%20current%20site%0Aand%20a%20target%20element%20where%20html%20elements%20will%20be%20appended..html +138 -138
- package/doc/Takes%20the%20url%20of%20the%20current%20site%20and%20a%20target%20element%20where%20html%20elements%20will%20be%20appended..html +137 -137
- package/doc/Volume.html +88 -88
- package/doc/audioCalibrator.js.html +179 -179
- package/doc/audioPeer.js.html +175 -175
- package/doc/audioRecorder.js.html +163 -163
- package/doc/creates%20a%20new%20AudioRecorder%20instance.%20%0ASets%20up%20the%20audio%20context%20and%20file%20reader..html +114 -114
- package/doc/fonts/OpenSans-Bold-webfont.eot +0 -0
- package/doc/fonts/OpenSans-Bold-webfont.svg +1829 -1829
- package/doc/fonts/OpenSans-Bold-webfont.woff +0 -0
- package/doc/fonts/OpenSans-BoldItalic-webfont.eot +0 -0
- package/doc/fonts/OpenSans-BoldItalic-webfont.svg +1829 -1829
- package/doc/fonts/OpenSans-BoldItalic-webfont.woff +0 -0
- package/doc/fonts/OpenSans-Italic-webfont.eot +0 -0
- package/doc/fonts/OpenSans-Italic-webfont.svg +1829 -1829
- package/doc/fonts/OpenSans-Italic-webfont.woff +0 -0
- package/doc/fonts/OpenSans-Light-webfont.eot +0 -0
- package/doc/fonts/OpenSans-Light-webfont.svg +1830 -1830
- package/doc/fonts/OpenSans-Light-webfont.woff +0 -0
- package/doc/fonts/OpenSans-LightItalic-webfont.eot +0 -0
- package/doc/fonts/OpenSans-LightItalic-webfont.svg +1834 -1834
- package/doc/fonts/OpenSans-LightItalic-webfont.woff +0 -0
- package/doc/fonts/OpenSans-Regular-webfont.eot +0 -0
- package/doc/fonts/OpenSans-Regular-webfont.svg +1830 -1830
- package/doc/fonts/OpenSans-Regular-webfont.woff +0 -0
- package/doc/global.html +308 -308
- package/doc/index.html +58 -58
- package/doc/listener.js.html +170 -170
- package/doc/mlsGen_mlsGenInterface.js.html +117 -117
- package/doc/myEventEmitter.js.html +124 -124
- package/doc/peer-connection_audioPeer.js.html +188 -188
- package/doc/peer-connection_listener.js.html +311 -311
- package/doc/peer-connection_speaker.js.html +381 -381
- package/doc/sc-activity-diagram.png +0 -0
- package/doc/scripts/linenumber.js +25 -25
- package/doc/scripts/prettify/Apache-License-2.0.txt +202 -202
- package/doc/scripts/prettify/lang-css.js +24 -24
- package/doc/scripts/prettify/prettify.js +640 -640
- package/doc/server_PythonServerAPI.js.html +160 -160
- package/doc/speaker.js.html +248 -248
- package/doc/styles/jsdoc-default.css +371 -371
- package/doc/styles/prettify-jsdoc.css +111 -111
- package/doc/styles/prettify-tomorrow.css +163 -163
- package/doc/tasks_audioCalibrator.js.html +207 -207
- package/doc/tasks_audioRecorder.js.html +190 -190
- package/doc/tasks_impulse-response_impulseResponse.js.html +442 -442
- package/doc/tasks_impulse-response_mlsGen_mlsGenInterface.js.html +175 -175
- package/doc/tasks_volume_volume.js.html +185 -185
- package/doc/utils.js.html +105 -105
- package/jest.config.js +173 -173
- package/makefile +74 -0
- package/netlify.toml +26 -26
- package/package.json +73 -73
- package/src/config/firebase.js +26 -26
- package/src/index.html +21 -21
- package/src/main.js +23 -23
- package/src/myEventEmitter.js +83 -83
- package/src/peer-connection/audioPeer.js +178 -178
- package/src/peer-connection/listener.js +362 -360
- package/src/peer-connection/peerErrors.js +25 -25
- package/src/peer-connection/speaker.js +736 -736
- package/src/powerCheck.js +98 -98
- package/src/server/PythonServerAPI.js +869 -869
- package/src/tasks/audioCalibrator.js +336 -336
- package/src/tasks/audioRecorder.js +315 -315
- package/src/tasks/combination/combination.js +3008 -3008
- package/src/tasks/combination/mlsGen/mlsGen.cpp +98 -98
- package/src/tasks/combination/mlsGen/mlsGen.hpp +303 -303
- package/src/tasks/combination/mlsGen/mlsGenInterface.js +131 -131
- package/src/tasks/combination/mlsGen/mlsGenTest.cpp +180 -180
- package/src/tasks/impulse-response/impulseResponse.js +610 -610
- package/src/tasks/impulse-response/mlsGen/mlsGen.cpp +98 -98
- package/src/tasks/impulse-response/mlsGen/mlsGen.hpp +303 -303
- package/src/tasks/impulse-response/mlsGen/mlsGenInterface.js +131 -131
- package/src/tasks/impulse-response/mlsGen/mlsGenTest.cpp +180 -180
- package/src/tasks/volume/volume.cpp +2 -2
- package/src/tasks/volume/volume.hpp +22 -22
- package/src/tasks/volume/volume.js +279 -279
- package/src/utils.js +205 -205
- package/webpack.config.js +37 -37
- package/.gitignore +0 -81
package/dist/main.js
CHANGED
|
@@ -25,7 +25,7 @@ return /******/ (function() { // webpackBootstrap
|
|
|
25
25
|
\************************/
|
|
26
26
|
/***/ (function(module) {
|
|
27
27
|
|
|
28
|
-
eval("\nvar createMLSGenModule = (() => {\n var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined;\n \n return (\nfunction(createMLSGenModule) {\n createMLSGenModule = createMLSGenModule || {};\n\nvar Module = typeof createMLSGenModule !== \"undefined\" ? createMLSGenModule : {};\n\nvar readyPromiseResolve, readyPromiseReject;\n\nModule[\"ready\"] = new Promise(function(resolve, reject) {\n readyPromiseResolve = resolve;\n readyPromiseReject = reject;\n});\n\nif (!Object.getOwnPropertyDescriptor(Module[\"ready\"], \"_main\")) {\n Object.defineProperty(Module[\"ready\"], \"_main\", {\n configurable: true,\n get: function() {\n abort(\"You are getting _main on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js\");\n }\n });\n Object.defineProperty(Module[\"ready\"], \"_main\", {\n configurable: true,\n set: function() {\n abort(\"You are setting _main on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js\");\n }\n });\n}\n\nif (!Object.getOwnPropertyDescriptor(Module[\"ready\"], \"___getTypeName\")) {\n Object.defineProperty(Module[\"ready\"], \"___getTypeName\", {\n configurable: true,\n get: function() {\n abort(\"You are getting ___getTypeName on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js\");\n }\n });\n Object.defineProperty(Module[\"ready\"], \"___getTypeName\", {\n configurable: true,\n set: function() {\n abort(\"You are setting ___getTypeName on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js\");\n }\n });\n}\n\nif (!Object.getOwnPropertyDescriptor(Module[\"ready\"], \"___embind_register_native_and_builtin_types\")) {\n Object.defineProperty(Module[\"ready\"], \"___embind_register_native_and_builtin_types\", {\n configurable: true,\n get: function() {\n abort(\"You are getting ___embind_register_native_and_builtin_types on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js\");\n }\n });\n Object.defineProperty(Module[\"ready\"], \"___embind_register_native_and_builtin_types\", {\n configurable: true,\n set: function() {\n abort(\"You are setting ___embind_register_native_and_builtin_types on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js\");\n }\n });\n}\n\nif (!Object.getOwnPropertyDescriptor(Module[\"ready\"], \"___stdio_exit\")) {\n Object.defineProperty(Module[\"ready\"], \"___stdio_exit\", {\n configurable: true,\n get: function() {\n abort(\"You are getting ___stdio_exit on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js\");\n }\n });\n Object.defineProperty(Module[\"ready\"], \"___stdio_exit\", {\n configurable: true,\n set: function() {\n abort(\"You are setting ___stdio_exit on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js\");\n }\n });\n}\n\nif (!Object.getOwnPropertyDescriptor(Module[\"ready\"], \"__ZN6__asan9FakeStack17AddrIsInFakeStackEm\")) {\n Object.defineProperty(Module[\"ready\"], \"__ZN6__asan9FakeStack17AddrIsInFakeStackEm\", {\n configurable: true,\n get: function() {\n abort(\"You are getting __ZN6__asan9FakeStack17AddrIsInFakeStackEm on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js\");\n }\n });\n Object.defineProperty(Module[\"ready\"], \"__ZN6__asan9FakeStack17AddrIsInFakeStackEm\", {\n configurable: true,\n set: function() {\n abort(\"You are setting __ZN6__asan9FakeStack17AddrIsInFakeStackEm on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js\");\n }\n });\n}\n\nif (!Object.getOwnPropertyDescriptor(Module[\"ready\"], \"__ZN6__asan9FakeStack8AllocateEmmm\")) {\n Object.defineProperty(Module[\"ready\"], \"__ZN6__asan9FakeStack8AllocateEmmm\", {\n configurable: true,\n get: function() {\n abort(\"You are getting __ZN6__asan9FakeStack8AllocateEmmm on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js\");\n }\n });\n Object.defineProperty(Module[\"ready\"], \"__ZN6__asan9FakeStack8AllocateEmmm\", {\n configurable: true,\n set: function() {\n abort(\"You are setting __ZN6__asan9FakeStack8AllocateEmmm on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js\");\n }\n });\n}\n\nif (!Object.getOwnPropertyDescriptor(Module[\"ready\"], \"onRuntimeInitialized\")) {\n Object.defineProperty(Module[\"ready\"], \"onRuntimeInitialized\", {\n configurable: true,\n get: function() {\n abort(\"You are getting onRuntimeInitialized on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js\");\n }\n });\n Object.defineProperty(Module[\"ready\"], \"onRuntimeInitialized\", {\n configurable: true,\n set: function() {\n abort(\"You are setting onRuntimeInitialized on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js\");\n }\n });\n}\n\nvar moduleOverrides = Object.assign({}, Module);\n\nvar arguments_ = [];\n\nvar thisProgram = \"./this.program\";\n\nvar quit_ = (status, toThrow) => {\n throw toThrow;\n};\n\nvar ENVIRONMENT_IS_WEB = true;\n\nvar ENVIRONMENT_IS_WORKER = false;\n\nvar ENVIRONMENT_IS_NODE = false;\n\nvar ENVIRONMENT_IS_SHELL = false;\n\nif (Module[\"ENVIRONMENT\"]) {\n throw new Error(\"Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -s ENVIRONMENT=web or -s ENVIRONMENT=node)\");\n}\n\nvar scriptDirectory = \"\";\n\nfunction locateFile(path) {\n if (Module[\"locateFile\"]) {\n return Module[\"locateFile\"](path, scriptDirectory);\n }\n return scriptDirectory + path;\n}\n\nvar read_, readAsync, readBinary, setWindowTitle;\n\nfunction logExceptionOnExit(e) {\n if (e instanceof ExitStatus) return;\n let toLog = e;\n if (e && typeof e === \"object\" && e.stack) {\n toLog = [ e, e.stack ];\n }\n err(\"exiting due to exception: \" + toLog);\n}\n\nif (ENVIRONMENT_IS_SHELL) {\n if (typeof process === \"object\" && \"function\" === \"function\" || typeof window === \"object\" || typeof importScripts === \"function\") throw new Error(\"not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)\");\n if (typeof read != \"undefined\") {\n read_ = function shell_read(f) {\n return read(f);\n };\n }\n readBinary = function readBinary(f) {\n let data;\n if (typeof readbuffer === \"function\") {\n return new Uint8Array(readbuffer(f));\n }\n data = read(f, \"binary\");\n assert(typeof data === \"object\");\n return data;\n };\n readAsync = function readAsync(f, onload, onerror) {\n setTimeout(() => onload(readBinary(f)), 0);\n };\n if (typeof scriptArgs != \"undefined\") {\n arguments_ = scriptArgs;\n } else if (typeof arguments != \"undefined\") {\n arguments_ = arguments;\n }\n if (typeof quit === \"function\") {\n quit_ = ((status, toThrow) => {\n logExceptionOnExit(toThrow);\n quit(status);\n });\n }\n if (typeof print !== \"undefined\") {\n if (typeof console === \"undefined\") console = {};\n console.log = print;\n console.warn = console.error = typeof printErr !== \"undefined\" ? printErr : print;\n }\n} else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {\n if (ENVIRONMENT_IS_WORKER) {\n scriptDirectory = self.location.href;\n } else if (typeof document !== \"undefined\" && document.currentScript) {\n scriptDirectory = document.currentScript.src;\n }\n if (_scriptDir) {\n scriptDirectory = _scriptDir;\n }\n if (scriptDirectory.indexOf(\"blob:\") !== 0) {\n scriptDirectory = scriptDirectory.substr(0, scriptDirectory.replace(/[?#].*/, \"\").lastIndexOf(\"/\") + 1);\n } else {\n scriptDirectory = \"\";\n }\n if (!(typeof window === \"object\" || typeof importScripts === \"function\")) throw new Error(\"not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)\");\n {\n read_ = (url => {\n var xhr = new XMLHttpRequest();\n xhr.open(\"GET\", url, false);\n xhr.send(null);\n return xhr.responseText;\n });\n if (ENVIRONMENT_IS_WORKER) {\n readBinary = (url => {\n var xhr = new XMLHttpRequest();\n xhr.open(\"GET\", url, false);\n xhr.responseType = \"arraybuffer\";\n xhr.send(null);\n return new Uint8Array(xhr.response);\n });\n }\n readAsync = ((url, onload, onerror) => {\n var xhr = new XMLHttpRequest();\n xhr.open(\"GET\", url, true);\n xhr.responseType = \"arraybuffer\";\n xhr.onload = (() => {\n if (xhr.status == 200 || xhr.status == 0 && xhr.response) {\n onload(xhr.response);\n return;\n }\n onerror();\n });\n xhr.onerror = onerror;\n xhr.send(null);\n });\n }\n setWindowTitle = (title => document.title = title);\n} else {\n throw new Error(\"environment detection error\");\n}\n\nvar out = Module[\"print\"] || console.log.bind(console);\n\nvar err = Module[\"printErr\"] || console.warn.bind(console);\n\nObject.assign(Module, moduleOverrides);\n\nmoduleOverrides = null;\n\nif (Module[\"arguments\"]) arguments_ = Module[\"arguments\"];\n\nif (!Object.getOwnPropertyDescriptor(Module, \"arguments\")) {\n Object.defineProperty(Module, \"arguments\", {\n configurable: true,\n get: function() {\n abort(\"Module.arguments has been replaced with plain arguments_ (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)\");\n }\n });\n}\n\nif (Module[\"thisProgram\"]) thisProgram = Module[\"thisProgram\"];\n\nif (!Object.getOwnPropertyDescriptor(Module, \"thisProgram\")) {\n Object.defineProperty(Module, \"thisProgram\", {\n configurable: true,\n get: function() {\n abort(\"Module.thisProgram has been replaced with plain thisProgram (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)\");\n }\n });\n}\n\nif (Module[\"quit\"]) quit_ = Module[\"quit\"];\n\nif (!Object.getOwnPropertyDescriptor(Module, \"quit\")) {\n Object.defineProperty(Module, \"quit\", {\n configurable: true,\n get: function() {\n abort(\"Module.quit has been replaced with plain quit_ (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)\");\n }\n });\n}\n\nassert(typeof Module[\"memoryInitializerPrefixURL\"] === \"undefined\", \"Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead\");\n\nassert(typeof Module[\"pthreadMainPrefixURL\"] === \"undefined\", \"Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead\");\n\nassert(typeof Module[\"cdInitializerPrefixURL\"] === \"undefined\", \"Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead\");\n\nassert(typeof Module[\"filePackagePrefixURL\"] === \"undefined\", \"Module.filePackagePrefixURL option was removed, use Module.locateFile instead\");\n\nassert(typeof Module[\"read\"] === \"undefined\", \"Module.read option was removed (modify read_ in JS)\");\n\nassert(typeof Module[\"readAsync\"] === \"undefined\", \"Module.readAsync option was removed (modify readAsync in JS)\");\n\nassert(typeof Module[\"readBinary\"] === \"undefined\", \"Module.readBinary option was removed (modify readBinary in JS)\");\n\nassert(typeof Module[\"setWindowTitle\"] === \"undefined\", \"Module.setWindowTitle option was removed (modify setWindowTitle in JS)\");\n\nassert(typeof Module[\"TOTAL_MEMORY\"] === \"undefined\", \"Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY\");\n\nif (!Object.getOwnPropertyDescriptor(Module, \"read\")) {\n Object.defineProperty(Module, \"read\", {\n configurable: true,\n get: function() {\n abort(\"Module.read has been replaced with plain read_ (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)\");\n }\n });\n}\n\nif (!Object.getOwnPropertyDescriptor(Module, \"readAsync\")) {\n Object.defineProperty(Module, \"readAsync\", {\n configurable: true,\n get: function() {\n abort(\"Module.readAsync has been replaced with plain readAsync (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)\");\n }\n });\n}\n\nif (!Object.getOwnPropertyDescriptor(Module, \"readBinary\")) {\n Object.defineProperty(Module, \"readBinary\", {\n configurable: true,\n get: function() {\n abort(\"Module.readBinary has been replaced with plain readBinary (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)\");\n }\n });\n}\n\nif (!Object.getOwnPropertyDescriptor(Module, \"setWindowTitle\")) {\n Object.defineProperty(Module, \"setWindowTitle\", {\n configurable: true,\n get: function() {\n abort(\"Module.setWindowTitle has been replaced with plain setWindowTitle (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)\");\n }\n });\n}\n\nassert(!ENVIRONMENT_IS_WORKER, \"worker environment detected but not enabled at build time. Add 'worker' to `-s ENVIRONMENT` to enable.\");\n\nassert(!ENVIRONMENT_IS_NODE, \"node environment detected but not enabled at build time. Add 'node' to `-s ENVIRONMENT` to enable.\");\n\nassert(!ENVIRONMENT_IS_SHELL, \"shell environment detected but not enabled at build time. Add 'shell' to `-s ENVIRONMENT` to enable.\");\n\nvar POINTER_SIZE = 4;\n\nfunction warnOnce(text) {\n if (!warnOnce.shown) warnOnce.shown = {};\n if (!warnOnce.shown[text]) {\n warnOnce.shown[text] = 1;\n err(text);\n }\n}\n\nfunction convertJsFunctionToWasm(func, sig) {\n if (typeof WebAssembly.Function === \"function\") {\n var typeNames = {\n \"i\": \"i32\",\n \"j\": \"i64\",\n \"f\": \"f32\",\n \"d\": \"f64\"\n };\n var type = {\n parameters: [],\n results: sig[0] == \"v\" ? [] : [ typeNames[sig[0]] ]\n };\n for (var i = 1; i < sig.length; ++i) {\n type.parameters.push(typeNames[sig[i]]);\n }\n return new WebAssembly.Function(type, func);\n }\n var typeSection = [ 1, 0, 1, 96 ];\n var sigRet = sig.slice(0, 1);\n var sigParam = sig.slice(1);\n var typeCodes = {\n \"i\": 127,\n \"j\": 126,\n \"f\": 125,\n \"d\": 124\n };\n typeSection.push(sigParam.length);\n for (var i = 0; i < sigParam.length; ++i) {\n typeSection.push(typeCodes[sigParam[i]]);\n }\n if (sigRet == \"v\") {\n typeSection.push(0);\n } else {\n typeSection = typeSection.concat([ 1, typeCodes[sigRet] ]);\n }\n typeSection[1] = typeSection.length - 2;\n var bytes = new Uint8Array([ 0, 97, 115, 109, 1, 0, 0, 0 ].concat(typeSection, [ 2, 7, 1, 1, 101, 1, 102, 0, 0, 7, 5, 1, 1, 102, 0, 0 ]));\n var module = new WebAssembly.Module(bytes);\n var instance = new WebAssembly.Instance(module, {\n \"e\": {\n \"f\": func\n }\n });\n var wrappedFunc = instance.exports[\"f\"];\n return wrappedFunc;\n}\n\nvar freeTableIndexes = [];\n\nvar functionsInTableMap;\n\nfunction getEmptyTableSlot() {\n if (freeTableIndexes.length) {\n return freeTableIndexes.pop();\n }\n try {\n wasmTable.grow(1);\n } catch (err) {\n if (!(err instanceof RangeError)) {\n throw err;\n }\n throw \"Unable to grow wasm table. Set ALLOW_TABLE_GROWTH.\";\n }\n return wasmTable.length - 1;\n}\n\nfunction updateTableMap(offset, count) {\n for (var i = offset; i < offset + count; i++) {\n var item = getWasmTableEntry(i);\n if (item) {\n functionsInTableMap.set(item, i);\n }\n }\n}\n\nvar tempRet0 = 0;\n\nvar setTempRet0 = value => {\n tempRet0 = value;\n};\n\nvar wasmBinary;\n\nif (Module[\"wasmBinary\"]) wasmBinary = Module[\"wasmBinary\"];\n\nif (!Object.getOwnPropertyDescriptor(Module, \"wasmBinary\")) {\n Object.defineProperty(Module, \"wasmBinary\", {\n configurable: true,\n get: function() {\n abort(\"Module.wasmBinary has been replaced with plain wasmBinary (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)\");\n }\n });\n}\n\nvar noExitRuntime = Module[\"noExitRuntime\"] || false;\n\nif (!Object.getOwnPropertyDescriptor(Module, \"noExitRuntime\")) {\n Object.defineProperty(Module, \"noExitRuntime\", {\n configurable: true,\n get: function() {\n abort(\"Module.noExitRuntime has been replaced with plain noExitRuntime (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)\");\n }\n });\n}\n\nif (typeof WebAssembly !== \"object\") {\n abort(\"no native wasm support detected\");\n}\n\nfunction _asan_js_load_1(ptr) {\n if (runtimeInitialized) return _asan_c_load_1(ptr);\n return HEAP8[ptr];\n}\n\nfunction _asan_js_load_1u(ptr) {\n if (runtimeInitialized) return _asan_c_load_1u(ptr);\n return HEAPU8[ptr];\n}\n\nfunction _asan_js_load_2(ptr) {\n if (runtimeInitialized) return _asan_c_load_2(ptr);\n return HEAP16[ptr];\n}\n\nfunction _asan_js_load_2u(ptr) {\n if (runtimeInitialized) return _asan_c_load_2u(ptr);\n return HEAPU16[ptr];\n}\n\nfunction _asan_js_load_4(ptr) {\n if (runtimeInitialized) return _asan_c_load_4(ptr);\n return HEAP32[ptr];\n}\n\nfunction _asan_js_load_4u(ptr) {\n if (runtimeInitialized) return _asan_c_load_4u(ptr) >>> 0;\n return HEAPU32[ptr];\n}\n\nfunction _asan_js_load_f(ptr) {\n if (runtimeInitialized) return _asan_c_load_f(ptr);\n return HEAPF32[ptr];\n}\n\nfunction _asan_js_load_d(ptr) {\n if (runtimeInitialized) return _asan_c_load_d(ptr);\n return HEAPF64[ptr];\n}\n\nfunction _asan_js_store_1(ptr, val) {\n if (runtimeInitialized) return _asan_c_store_1(ptr, val);\n return HEAP8[ptr] = val;\n}\n\nfunction _asan_js_store_1u(ptr, val) {\n if (runtimeInitialized) return _asan_c_store_1u(ptr, val);\n return HEAPU8[ptr] = val;\n}\n\nfunction _asan_js_store_2(ptr, val) {\n if (runtimeInitialized) return _asan_c_store_2(ptr, val);\n return HEAP16[ptr] = val;\n}\n\nfunction _asan_js_store_4(ptr, val) {\n if (runtimeInitialized) return _asan_c_store_4(ptr, val);\n return HEAP32[ptr] = val;\n}\n\nfunction _asan_js_store_4u(ptr, val) {\n if (runtimeInitialized) return _asan_c_store_4u(ptr, val) >>> 0;\n return HEAPU32[ptr] = val;\n}\n\nfunction _asan_js_store_f(ptr, val) {\n if (runtimeInitialized) return _asan_c_store_f(ptr, val);\n return HEAPF32[ptr] = val;\n}\n\nfunction _asan_js_store_d(ptr, val) {\n if (runtimeInitialized) return _asan_c_store_d(ptr, val);\n return HEAPF64[ptr] = val;\n}\n\nvar wasmMemory;\n\nvar ABORT = false;\n\nvar EXITSTATUS;\n\nfunction assert(condition, text) {\n if (!condition) {\n abort(\"Assertion failed\" + (text ? \": \" + text : \"\"));\n }\n}\n\nfunction getCFunc(ident) {\n var func = Module[\"_\" + ident];\n assert(func, \"Cannot call unknown function \" + ident + \", make sure it is exported\");\n return func;\n}\n\nfunction ccall(ident, returnType, argTypes, args, opts) {\n var toC = {\n \"string\": function(str) {\n var ret = 0;\n if (str !== null && str !== undefined && str !== 0) {\n var len = (str.length << 2) + 1;\n ret = stackAlloc(len);\n stringToUTF8(str, ret, len);\n }\n return ret;\n },\n \"array\": function(arr) {\n var ret = stackAlloc(arr.length);\n writeArrayToMemory(arr, ret);\n return ret;\n }\n };\n function convertReturnValue(ret) {\n if (returnType === \"string\") return UTF8ToString(ret);\n if (returnType === \"boolean\") return Boolean(ret);\n return ret;\n }\n var func = getCFunc(ident);\n var cArgs = [];\n var stack = 0;\n assert(returnType !== \"array\", 'Return type should not be \"array\".');\n if (args) {\n for (var i = 0; i < args.length; i++) {\n var converter = toC[argTypes[i]];\n if (converter) {\n if (stack === 0) stack = stackSave();\n cArgs[i] = converter(args[i]);\n } else {\n cArgs[i] = args[i];\n }\n }\n }\n var ret = func.apply(null, cArgs);\n function onDone(ret) {\n if (stack !== 0) stackRestore(stack);\n return convertReturnValue(ret);\n }\n ret = onDone(ret);\n return ret;\n}\n\nvar ALLOC_STACK = 1;\n\nvar UTF8Decoder = typeof TextDecoder !== \"undefined\" ? new TextDecoder(\"utf8\") : undefined;\n\nfunction UTF8ArrayToString(heap, idx, maxBytesToRead) {\n var endIdx = idx + maxBytesToRead;\n var endPtr = idx;\n while (heap[endPtr] && !(endPtr >= endIdx)) ++endPtr;\n if (endPtr - idx > 16 && heap.subarray && UTF8Decoder) {\n return UTF8Decoder.decode(heap.subarray(idx, endPtr));\n } else {\n var str = \"\";\n while (idx < endPtr) {\n var u0 = heap[idx++];\n if (!(u0 & 128)) {\n str += String.fromCharCode(u0);\n continue;\n }\n var u1 = heap[idx++] & 63;\n if ((u0 & 224) == 192) {\n str += String.fromCharCode((u0 & 31) << 6 | u1);\n continue;\n }\n var u2 = heap[idx++] & 63;\n if ((u0 & 240) == 224) {\n u0 = (u0 & 15) << 12 | u1 << 6 | u2;\n } else {\n if ((u0 & 248) != 240) warnOnce(\"Invalid UTF-8 leading byte 0x\" + u0.toString(16) + \" encountered when deserializing a UTF-8 string in wasm memory to a JS string!\");\n u0 = (u0 & 7) << 18 | u1 << 12 | u2 << 6 | heap[idx++] & 63;\n }\n if (u0 < 65536) {\n str += String.fromCharCode(u0);\n } else {\n var ch = u0 - 65536;\n str += String.fromCharCode(55296 | ch >> 10, 56320 | ch & 1023);\n }\n }\n }\n return str;\n}\n\nfunction UTF8ToString(ptr, maxBytesToRead) {\n return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : \"\";\n}\n\nfunction stringToUTF8Array(str, heap, outIdx, maxBytesToWrite) {\n if (!(maxBytesToWrite > 0)) return 0;\n var startIdx = outIdx;\n var endIdx = outIdx + maxBytesToWrite - 1;\n for (var i = 0; i < str.length; ++i) {\n var u = str.charCodeAt(i);\n if (u >= 55296 && u <= 57343) {\n var u1 = str.charCodeAt(++i);\n u = 65536 + ((u & 1023) << 10) | u1 & 1023;\n }\n if (u <= 127) {\n if (outIdx >= endIdx) break;\n heap[outIdx++] = u;\n } else if (u <= 2047) {\n if (outIdx + 1 >= endIdx) break;\n heap[outIdx++] = 192 | u >> 6;\n heap[outIdx++] = 128 | u & 63;\n } else if (u <= 65535) {\n if (outIdx + 2 >= endIdx) break;\n heap[outIdx++] = 224 | u >> 12;\n heap[outIdx++] = 128 | u >> 6 & 63;\n heap[outIdx++] = 128 | u & 63;\n } else {\n if (outIdx + 3 >= endIdx) break;\n if (u > 1114111) warnOnce(\"Invalid Unicode code point 0x\" + u.toString(16) + \" encountered when serializing a JS string to a UTF-8 string in wasm memory! (Valid unicode code points should be in range 0-0x10FFFF).\");\n heap[outIdx++] = 240 | u >> 18;\n heap[outIdx++] = 128 | u >> 12 & 63;\n heap[outIdx++] = 128 | u >> 6 & 63;\n heap[outIdx++] = 128 | u & 63;\n }\n }\n heap[outIdx] = 0;\n return outIdx - startIdx;\n}\n\nfunction stringToUTF8(str, outPtr, maxBytesToWrite) {\n assert(typeof maxBytesToWrite == \"number\", \"stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!\");\n return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite);\n}\n\nfunction lengthBytesUTF8(str) {\n var len = 0;\n for (var i = 0; i < str.length; ++i) {\n var u = str.charCodeAt(i);\n if (u >= 55296 && u <= 57343) u = 65536 + ((u & 1023) << 10) | str.charCodeAt(++i) & 1023;\n if (u <= 127) ++len; else if (u <= 2047) len += 2; else if (u <= 65535) len += 3; else len += 4;\n }\n return len;\n}\n\nvar UTF16Decoder = typeof TextDecoder !== \"undefined\" ? new TextDecoder(\"utf-16le\") : undefined;\n\nfunction UTF16ToString(ptr, maxBytesToRead) {\n assert(ptr % 2 == 0, \"Pointer passed to UTF16ToString must be aligned to two bytes!\");\n var endPtr = ptr;\n var idx = endPtr >> 1;\n var maxIdx = idx + maxBytesToRead / 2;\n while (!(idx >= maxIdx) && _asan_js_load_2u(idx)) ++idx;\n endPtr = idx << 1;\n if (endPtr - ptr > 32 && UTF16Decoder) {\n return UTF16Decoder.decode(HEAPU8.subarray(ptr, endPtr));\n } else {\n var str = \"\";\n for (var i = 0; !(i >= maxBytesToRead / 2); ++i) {\n var codeUnit = _asan_js_load_2(ptr + i * 2 >> 1);\n if (codeUnit == 0) break;\n str += String.fromCharCode(codeUnit);\n }\n return str;\n }\n}\n\nfunction stringToUTF16(str, outPtr, maxBytesToWrite) {\n assert(outPtr % 2 == 0, \"Pointer passed to stringToUTF16 must be aligned to two bytes!\");\n assert(typeof maxBytesToWrite == \"number\", \"stringToUTF16(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!\");\n if (maxBytesToWrite === undefined) {\n maxBytesToWrite = 2147483647;\n }\n if (maxBytesToWrite < 2) return 0;\n maxBytesToWrite -= 2;\n var startPtr = outPtr;\n var numCharsToWrite = maxBytesToWrite < str.length * 2 ? maxBytesToWrite / 2 : str.length;\n for (var i = 0; i < numCharsToWrite; ++i) {\n var codeUnit = str.charCodeAt(i);\n _asan_js_store_2(outPtr >> 1, codeUnit);\n outPtr += 2;\n }\n _asan_js_store_2(outPtr >> 1, 0);\n return outPtr - startPtr;\n}\n\nfunction lengthBytesUTF16(str) {\n return str.length * 2;\n}\n\nfunction UTF32ToString(ptr, maxBytesToRead) {\n assert(ptr % 4 == 0, \"Pointer passed to UTF32ToString must be aligned to four bytes!\");\n var i = 0;\n var str = \"\";\n while (!(i >= maxBytesToRead / 4)) {\n var utf32 = _asan_js_load_4(ptr + i * 4 >> 2);\n if (utf32 == 0) break;\n ++i;\n if (utf32 >= 65536) {\n var ch = utf32 - 65536;\n str += String.fromCharCode(55296 | ch >> 10, 56320 | ch & 1023);\n } else {\n str += String.fromCharCode(utf32);\n }\n }\n return str;\n}\n\nfunction stringToUTF32(str, outPtr, maxBytesToWrite) {\n assert(outPtr % 4 == 0, \"Pointer passed to stringToUTF32 must be aligned to four bytes!\");\n assert(typeof maxBytesToWrite == \"number\", \"stringToUTF32(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!\");\n if (maxBytesToWrite === undefined) {\n maxBytesToWrite = 2147483647;\n }\n if (maxBytesToWrite < 4) return 0;\n var startPtr = outPtr;\n var endPtr = startPtr + maxBytesToWrite - 4;\n for (var i = 0; i < str.length; ++i) {\n var codeUnit = str.charCodeAt(i);\n if (codeUnit >= 55296 && codeUnit <= 57343) {\n var trailSurrogate = str.charCodeAt(++i);\n codeUnit = 65536 + ((codeUnit & 1023) << 10) | trailSurrogate & 1023;\n }\n _asan_js_store_4(outPtr >> 2, codeUnit);\n outPtr += 4;\n if (outPtr + 4 > endPtr) break;\n }\n _asan_js_store_4(outPtr >> 2, 0);\n return outPtr - startPtr;\n}\n\nfunction lengthBytesUTF32(str) {\n var len = 0;\n for (var i = 0; i < str.length; ++i) {\n var codeUnit = str.charCodeAt(i);\n if (codeUnit >= 55296 && codeUnit <= 57343) ++i;\n len += 4;\n }\n return len;\n}\n\nfunction allocateUTF8(str) {\n var size = lengthBytesUTF8(str) + 1;\n var ret = _malloc(size);\n if (ret) stringToUTF8Array(str, HEAP8, ret, size);\n return ret;\n}\n\nfunction writeArrayToMemory(array, buffer) {\n assert(array.length >= 0, \"writeArrayToMemory array must have a length (should be an array or typed array)\");\n HEAP8.set(array, buffer);\n}\n\nfunction writeAsciiToMemory(str, buffer, dontAddNull) {\n for (var i = 0; i < str.length; ++i) {\n assert(str.charCodeAt(i) === (str.charCodeAt(i) & 255));\n _asan_js_store_1(buffer++ >> 0, str.charCodeAt(i));\n }\n if (!dontAddNull) _asan_js_store_1(buffer >> 0, 0);\n}\n\nvar buffer, HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64;\n\nfunction updateGlobalBufferAndViews(buf) {\n buffer = buf;\n Module[\"HEAP8\"] = HEAP8 = new Int8Array(buf);\n Module[\"HEAP16\"] = HEAP16 = new Int16Array(buf);\n Module[\"HEAP32\"] = HEAP32 = new Int32Array(buf);\n Module[\"HEAPU8\"] = HEAPU8 = new Uint8Array(buf);\n Module[\"HEAPU16\"] = HEAPU16 = new Uint16Array(buf);\n Module[\"HEAPU32\"] = HEAPU32 = new Uint32Array(buf);\n Module[\"HEAPF32\"] = HEAPF32 = new Float32Array(buf);\n Module[\"HEAPF64\"] = HEAPF64 = new Float64Array(buf);\n}\n\nvar TOTAL_STACK = 5242880;\n\nif (Module[\"TOTAL_STACK\"]) assert(TOTAL_STACK === Module[\"TOTAL_STACK\"], \"the stack size can no longer be determined at runtime\");\n\nvar INITIAL_MEMORY = Module[\"INITIAL_MEMORY\"] || 79101952;\n\nif (!Object.getOwnPropertyDescriptor(Module, \"INITIAL_MEMORY\")) {\n Object.defineProperty(Module, \"INITIAL_MEMORY\", {\n configurable: true,\n get: function() {\n abort(\"Module.INITIAL_MEMORY has been replaced with plain INITIAL_MEMORY (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)\");\n }\n });\n}\n\nassert(INITIAL_MEMORY >= TOTAL_STACK, \"INITIAL_MEMORY should be larger than TOTAL_STACK, was \" + INITIAL_MEMORY + \"! (TOTAL_STACK=\" + TOTAL_STACK + \")\");\n\nassert(typeof Int32Array !== \"undefined\" && typeof Float64Array !== \"undefined\" && Int32Array.prototype.subarray !== undefined && Int32Array.prototype.set !== undefined, \"JS engine does not provide full typed array support\");\n\nassert(!Module[\"wasmMemory\"], \"Use of `wasmMemory` detected. Use -s IMPORTED_MEMORY to define wasmMemory externally\");\n\nassert(INITIAL_MEMORY == 79101952, \"Detected runtime INITIAL_MEMORY setting. Use -s IMPORTED_MEMORY to define wasmMemory dynamically\");\n\nvar wasmTable;\n\nfunction writeStackCookie() {\n var max = _emscripten_stack_get_end();\n assert((max & 3) == 0);\n _asan_js_store_4(max + 4 >> 2, 34821223);\n _asan_js_store_4(max + 8 >> 2, 2310721022);\n}\n\nfunction checkStackCookie() {\n if (ABORT) return;\n var max = _emscripten_stack_get_end();\n var cookie1 = _asan_js_load_4u(max + 4 >> 2);\n var cookie2 = _asan_js_load_4u(max + 8 >> 2);\n if (cookie1 != 34821223 || cookie2 != 2310721022) {\n abort(\"Stack overflow! Stack cookie has been overwritten, expected hex dwords 0x89BACDFE and 0x2135467, but received 0x\" + cookie2.toString(16) + \" 0x\" + cookie1.toString(16));\n }\n}\n\n(function() {\n var h16 = new Int16Array(1);\n var h8 = new Int8Array(h16.buffer);\n h16[0] = 25459;\n if (h8[0] !== 115 || h8[1] !== 99) throw \"Runtime error: expected the system to be little-endian! (Run with -s SUPPORT_BIG_ENDIAN=1 to bypass)\";\n})();\n\nvar __ATPRERUN__ = [];\n\nvar __ATINIT__ = [];\n\nvar __ATEXIT__ = [];\n\nvar __ATPOSTRUN__ = [];\n\nvar runtimeInitialized = false;\n\nvar runtimeExited = false;\n\nvar runtimeKeepaliveCounter = 0;\n\nfunction keepRuntimeAlive() {\n return noExitRuntime || runtimeKeepaliveCounter > 0;\n}\n\nfunction preRun() {\n if (Module[\"preRun\"]) {\n if (typeof Module[\"preRun\"] == \"function\") Module[\"preRun\"] = [ Module[\"preRun\"] ];\n while (Module[\"preRun\"].length) {\n addOnPreRun(Module[\"preRun\"].shift());\n }\n }\n callRuntimeCallbacks(__ATPRERUN__);\n}\n\nfunction initRuntime() {\n checkStackCookie();\n assert(!runtimeInitialized);\n runtimeInitialized = true;\n if (!Module[\"noFSInit\"] && !FS.init.initialized) FS.init();\n FS.ignorePermissions = false;\n TTY.init();\n callRuntimeCallbacks(__ATINIT__);\n}\n\nfunction exitRuntime() {\n checkStackCookie();\n ___funcs_on_exit();\n callRuntimeCallbacks(__ATEXIT__);\n FS.quit();\n TTY.shutdown();\n runtimeExited = true;\n}\n\nfunction postRun() {\n checkStackCookie();\n if (Module[\"postRun\"]) {\n if (typeof Module[\"postRun\"] == \"function\") Module[\"postRun\"] = [ Module[\"postRun\"] ];\n while (Module[\"postRun\"].length) {\n addOnPostRun(Module[\"postRun\"].shift());\n }\n }\n callRuntimeCallbacks(__ATPOSTRUN__);\n}\n\nfunction addOnPreRun(cb) {\n __ATPRERUN__.unshift(cb);\n}\n\nfunction addOnInit(cb) {\n __ATINIT__.unshift(cb);\n}\n\nfunction addOnPostRun(cb) {\n __ATPOSTRUN__.unshift(cb);\n}\n\nassert(Math.imul, \"This browser does not support Math.imul(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill\");\n\nassert(Math.fround, \"This browser does not support Math.fround(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill\");\n\nassert(Math.clz32, \"This browser does not support Math.clz32(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill\");\n\nassert(Math.trunc, \"This browser does not support Math.trunc(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill\");\n\nvar runDependencies = 0;\n\nvar runDependencyWatcher = null;\n\nvar dependenciesFulfilled = null;\n\nvar runDependencyTracking = {};\n\nfunction getUniqueRunDependency(id) {\n var orig = id;\n while (1) {\n if (!runDependencyTracking[id]) return id;\n id = orig + Math.random();\n }\n}\n\nfunction addRunDependency(id) {\n runDependencies++;\n if (Module[\"monitorRunDependencies\"]) {\n Module[\"monitorRunDependencies\"](runDependencies);\n }\n if (id) {\n assert(!runDependencyTracking[id]);\n runDependencyTracking[id] = 1;\n if (runDependencyWatcher === null && typeof setInterval !== \"undefined\") {\n runDependencyWatcher = setInterval(function() {\n if (ABORT) {\n clearInterval(runDependencyWatcher);\n runDependencyWatcher = null;\n return;\n }\n var shown = false;\n for (var dep in runDependencyTracking) {\n if (!shown) {\n shown = true;\n err(\"still waiting on run dependencies:\");\n }\n err(\"dependency: \" + dep);\n }\n if (shown) {\n err(\"(end of list)\");\n }\n }, 1e4);\n }\n } else {\n err(\"warning: run dependency added without ID\");\n }\n}\n\nfunction removeRunDependency(id) {\n runDependencies--;\n if (Module[\"monitorRunDependencies\"]) {\n Module[\"monitorRunDependencies\"](runDependencies);\n }\n if (id) {\n assert(runDependencyTracking[id]);\n delete runDependencyTracking[id];\n } else {\n err(\"warning: run dependency removed without ID\");\n }\n if (runDependencies == 0) {\n if (runDependencyWatcher !== null) {\n clearInterval(runDependencyWatcher);\n runDependencyWatcher = null;\n }\n if (dependenciesFulfilled) {\n var callback = dependenciesFulfilled;\n dependenciesFulfilled = null;\n callback();\n }\n }\n}\n\nModule[\"preloadedImages\"] = {};\n\nModule[\"preloadedAudios\"] = {};\n\nfunction abort(what) {\n {\n if (Module[\"onAbort\"]) {\n Module[\"onAbort\"](what);\n }\n }\n what = \"Aborted(\" + what + \")\";\n err(what);\n ABORT = true;\n EXITSTATUS = 1;\n var e = new WebAssembly.RuntimeError(what);\n readyPromiseReject(e);\n throw e;\n}\n\nvar dataURIPrefix = \"data:application/octet-stream;base64,\";\n\nfunction isDataURI(filename) {\n return filename.startsWith(dataURIPrefix);\n}\n\nfunction isFileURI(filename) {\n return filename.startsWith(\"file://\");\n}\n\nfunction createExportWrapper(name, fixedasm) {\n return function() {\n var displayName = name;\n var asm = fixedasm;\n if (!fixedasm) {\n asm = Module[\"asm\"];\n }\n assert(runtimeInitialized, \"native function `\" + displayName + \"` called before runtime initialization\");\n assert(!runtimeExited, \"native function `\" + displayName + \"` called after runtime exit (use NO_EXIT_RUNTIME to keep it alive after main() exits)\");\n if (!asm[name]) {\n assert(asm[name], \"exported native function `\" + displayName + \"` not found\");\n }\n return asm[name].apply(null, arguments);\n };\n}\n\nvar wasmBinaryFile;\n\nwasmBinaryFile = \"mlsGen.wasm\";\n\nif (!isDataURI(wasmBinaryFile)) {\n wasmBinaryFile = locateFile(wasmBinaryFile);\n}\n\nfunction getBinary(file) {\n try {\n if (file == wasmBinaryFile && wasmBinary) {\n return new Uint8Array(wasmBinary);\n }\n if (readBinary) {\n return readBinary(file);\n } else {\n throw \"both async and sync fetching of the wasm failed\";\n }\n } catch (err) {\n abort(err);\n }\n}\n\nfunction getBinaryPromise() {\n if (!wasmBinary && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER)) {\n if (typeof fetch === \"function\") {\n return fetch(wasmBinaryFile, {\n credentials: \"same-origin\"\n }).then(function(response) {\n if (!response[\"ok\"]) {\n throw \"failed to load wasm binary file at '\" + wasmBinaryFile + \"'\";\n }\n return response[\"arrayBuffer\"]();\n }).catch(function() {\n return getBinary(wasmBinaryFile);\n });\n }\n }\n return Promise.resolve().then(function() {\n return getBinary(wasmBinaryFile);\n });\n}\n\nvar wasmOffsetConverter;\n\nfunction WasmOffsetConverter(wasmBytes, wasmModule) {\n var offset = 8;\n var funcidx = 0;\n this.offset_map = {};\n this.func_starts = [];\n this.name_map = {};\n this.import_functions = 0;\n var buffer = wasmBytes;\n function unsignedLEB128() {\n var result = 0;\n var shift = 0;\n do {\n var byte = buffer[offset++];\n result += (byte & 127) << shift;\n shift += 7;\n } while (byte & 128);\n return result;\n }\n function skipLimits() {\n var flags = unsignedLEB128();\n unsignedLEB128();\n var hasMax = (flags & 1) != 0;\n if (hasMax) {\n unsignedLEB128();\n }\n }\n binary_parse: while (offset < buffer.length) {\n var type = buffer[offset++];\n var end = unsignedLEB128() + offset;\n switch (type) {\n case 2:\n var count = unsignedLEB128();\n while (count-- > 0) {\n offset = unsignedLEB128() + offset;\n offset = unsignedLEB128() + offset;\n switch (buffer[offset++]) {\n case 0:\n ++funcidx;\n unsignedLEB128();\n break;\n\n case 1:\n ++offset;\n skipLimits();\n break;\n\n case 2:\n skipLimits();\n break;\n\n case 3:\n offset += 2;\n break;\n\n default:\n throw \"bad import kind\";\n }\n }\n this.import_functions = funcidx;\n break;\n\n case 10:\n var count = unsignedLEB128();\n while (count-- > 0) {\n var size = unsignedLEB128();\n this.offset_map[funcidx++] = offset;\n this.func_starts.push(offset);\n offset += size;\n }\n break binary_parse;\n }\n offset = end;\n }\n var sections = WebAssembly.Module.customSections(wasmModule, \"name\");\n for (var i = 0; i < sections.length; ++i) {\n buffer = new Uint8Array(sections[i]);\n if (buffer[0] != 1) continue;\n offset = 1;\n unsignedLEB128();\n var count = unsignedLEB128();\n while (count-- > 0) {\n var index = unsignedLEB128();\n var length = unsignedLEB128();\n this.name_map[index] = UTF8ArrayToString(buffer, offset, length);\n offset += length;\n }\n }\n}\n\nWasmOffsetConverter.prototype.convert = function(funcidx, offset) {\n return this.offset_map[funcidx] + offset;\n};\n\nWasmOffsetConverter.prototype.getIndex = function(offset) {\n var lo = 0;\n var hi = this.func_starts.length;\n var mid;\n while (lo < hi) {\n mid = Math.floor((lo + hi) / 2);\n if (this.func_starts[mid] > offset) {\n hi = mid;\n } else {\n lo = mid + 1;\n }\n }\n return lo + this.import_functions - 1;\n};\n\nWasmOffsetConverter.prototype.isSameFunc = function(offset1, offset2) {\n return this.getIndex(offset1) == this.getIndex(offset2);\n};\n\nWasmOffsetConverter.prototype.getName = function(offset) {\n var index = this.getIndex(offset);\n return this.name_map[index] || \"wasm-function[\" + index + \"]\";\n};\n\nfunction resetPrototype(constructor, attrs) {\n var object = Object.create(constructor.prototype);\n return Object.assign(object, attrs);\n}\n\nfunction createWasm() {\n var info = {\n \"env\": asmLibraryArg,\n \"wasi_snapshot_preview1\": asmLibraryArg\n };\n function receiveInstance(instance, module) {\n var exports = instance.exports;\n Module[\"asm\"] = exports;\n wasmMemory = Module[\"asm\"][\"memory\"];\n assert(wasmMemory, \"memory not found in wasm exports\");\n updateGlobalBufferAndViews(wasmMemory.buffer);\n wasmTable = Module[\"asm\"][\"__indirect_function_table\"];\n assert(wasmTable, \"table not found in wasm exports\");\n addOnInit(Module[\"asm\"][\"__wasm_call_ctors\"]);\n removeRunDependency(\"wasm-instantiate\");\n }\n addRunDependency(\"wasm-instantiate\");\n var trueModule = Module;\n function receiveInstantiationResult(result) {\n assert(Module === trueModule, \"the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?\");\n trueModule = null;\n receiveInstance(result[\"instance\"]);\n }\n function instantiateArrayBuffer(receiver) {\n var savedBinary;\n return getBinaryPromise().then(function(binary) {\n savedBinary = binary;\n return WebAssembly.instantiate(binary, info);\n }).then(function(instance) {\n wasmOffsetConverter = new WasmOffsetConverter(savedBinary, instance.module);\n return instance;\n }).then(receiver, function(reason) {\n err(\"failed to asynchronously prepare wasm: \" + reason);\n if (isFileURI(wasmBinaryFile)) {\n err(\"warning: Loading from a file URI (\" + wasmBinaryFile + \") is not supported in most browsers. See https://emscripten.org/docs/getting_started/FAQ.html#how-do-i-run-a-local-webserver-for-testing-why-does-my-program-stall-in-downloading-or-preparing\");\n }\n abort(reason);\n });\n }\n function instantiateAsync() {\n if (!wasmBinary && typeof WebAssembly.instantiateStreaming === \"function\" && !isDataURI(wasmBinaryFile) && typeof fetch === \"function\") {\n return fetch(wasmBinaryFile, {\n credentials: \"same-origin\"\n }).then(function(response) {\n var result = WebAssembly.instantiateStreaming(response, info);\n var clonedResponsePromise = response.clone().arrayBuffer();\n return result.then(function(instantiationResult) {\n clonedResponsePromise.then(function(arrayBufferResult) {\n wasmOffsetConverter = new WasmOffsetConverter(new Uint8Array(arrayBufferResult), instantiationResult.module);\n receiveInstantiationResult(instantiationResult);\n }, function(reason) {\n err(\"failed to initialize offset-converter: \" + reason);\n });\n }, function(reason) {\n err(\"wasm streaming compile failed: \" + reason);\n err(\"falling back to ArrayBuffer instantiation\");\n return instantiateArrayBuffer(receiveInstantiationResult);\n });\n });\n } else {\n return instantiateArrayBuffer(receiveInstantiationResult);\n }\n }\n if (Module[\"instantiateWasm\"]) {\n wasmOffsetConverter = resetPrototype(WasmOffsetConverter, Module[\"wasmOffsetData\"]);\n try {\n var exports = Module[\"instantiateWasm\"](info, receiveInstance);\n return exports;\n } catch (e) {\n err(\"Module.instantiateWasm callback failed with error: \" + e);\n return false;\n }\n }\n instantiateAsync().catch(readyPromiseReject);\n return {};\n}\n\nvar tempDouble;\n\nvar tempI64;\n\nvar ASM_CONSTS = {\n 9944289: function() {\n return withBuiltinMalloc(function() {\n return allocateUTF8(Module[\"ASAN_OPTIONS\"] || 0);\n });\n },\n 9944386: function() {\n return withBuiltinMalloc(function() {\n return allocateUTF8(Module[\"LSAN_OPTIONS\"] || 0);\n });\n },\n 9944483: function() {\n return withBuiltinMalloc(function() {\n return allocateUTF8(Module[\"UBSAN_OPTIONS\"] || 0);\n });\n },\n 9944581: function() {\n var setting = Module[\"printWithColors\"];\n if (setting != null) {\n return setting;\n } else {\n return ENVIRONMENT_IS_NODE && process.stderr.isTTY;\n }\n }\n};\n\nfunction callRuntimeCallbacks(callbacks) {\n while (callbacks.length > 0) {\n var callback = callbacks.shift();\n if (typeof callback == \"function\") {\n callback(Module);\n continue;\n }\n var func = callback.func;\n if (typeof func === \"number\") {\n if (callback.arg === undefined) {\n getWasmTableEntry(func)();\n } else {\n getWasmTableEntry(func)(callback.arg);\n }\n } else {\n func(callback.arg === undefined ? null : callback.arg);\n }\n }\n}\n\nfunction demangle(func) {\n warnOnce(\"warning: build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling\");\n return func;\n}\n\nfunction demangleAll(text) {\n var regex = /\\b_Z[\\w\\d_]+/g;\n return text.replace(regex, function(x) {\n var y = demangle(x);\n return x === y ? x : y + \" [\" + x + \"]\";\n });\n}\n\nvar wasmTableMirror = [];\n\nfunction getWasmTableEntry(funcPtr) {\n var func = wasmTableMirror[funcPtr];\n if (!func) {\n if (funcPtr >= wasmTableMirror.length) wasmTableMirror.length = funcPtr + 1;\n wasmTableMirror[funcPtr] = func = wasmTable.get(funcPtr);\n }\n assert(wasmTable.get(funcPtr) == func, \"JavaScript-side Wasm function table mirror is out of date!\");\n return func;\n}\n\nfunction jsStackTrace() {\n var error = new Error();\n if (!error.stack) {\n try {\n throw new Error();\n } catch (e) {\n error = e;\n }\n if (!error.stack) {\n return \"(no stack trace available)\";\n }\n }\n return error.stack.toString();\n}\n\nfunction setWasmTableEntry(idx, func) {\n wasmTable.set(idx, func);\n wasmTableMirror[idx] = func;\n}\n\nfunction ___assert_fail(condition, filename, line, func) {\n abort(\"Assertion failed: \" + UTF8ToString(condition) + \", at: \" + [ filename ? UTF8ToString(filename) : \"unknown filename\", line, func ? UTF8ToString(func) : \"unknown function\" ]);\n}\n\nvar PATH = {\n splitPath: function(filename) {\n var splitPathRe = /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\n return splitPathRe.exec(filename).slice(1);\n },\n normalizeArray: function(parts, allowAboveRoot) {\n var up = 0;\n for (var i = parts.length - 1; i >= 0; i--) {\n var last = parts[i];\n if (last === \".\") {\n parts.splice(i, 1);\n } else if (last === \"..\") {\n parts.splice(i, 1);\n up++;\n } else if (up) {\n parts.splice(i, 1);\n up--;\n }\n }\n if (allowAboveRoot) {\n for (;up; up--) {\n parts.unshift(\"..\");\n }\n }\n return parts;\n },\n normalize: function(path) {\n var isAbsolute = path.charAt(0) === \"/\", trailingSlash = path.substr(-1) === \"/\";\n path = PATH.normalizeArray(path.split(\"/\").filter(function(p) {\n return !!p;\n }), !isAbsolute).join(\"/\");\n if (!path && !isAbsolute) {\n path = \".\";\n }\n if (path && trailingSlash) {\n path += \"/\";\n }\n return (isAbsolute ? \"/\" : \"\") + path;\n },\n dirname: function(path) {\n var result = PATH.splitPath(path), root = result[0], dir = result[1];\n if (!root && !dir) {\n return \".\";\n }\n if (dir) {\n dir = dir.substr(0, dir.length - 1);\n }\n return root + dir;\n },\n basename: function(path) {\n if (path === \"/\") return \"/\";\n path = PATH.normalize(path);\n path = path.replace(/\\/$/, \"\");\n var lastSlash = path.lastIndexOf(\"/\");\n if (lastSlash === -1) return path;\n return path.substr(lastSlash + 1);\n },\n extname: function(path) {\n return PATH.splitPath(path)[3];\n },\n join: function() {\n var paths = Array.prototype.slice.call(arguments, 0);\n return PATH.normalize(paths.join(\"/\"));\n },\n join2: function(l, r) {\n return PATH.normalize(l + \"/\" + r);\n }\n};\n\nfunction getRandomDevice() {\n if (typeof crypto === \"object\" && typeof crypto[\"getRandomValues\"] === \"function\") {\n var randomBuffer = new Uint8Array(1);\n return function() {\n crypto.getRandomValues(randomBuffer);\n return randomBuffer[0];\n };\n } else return function() {\n abort(\"no cryptographic support found for randomDevice. consider polyfilling it if you want to use something insecure like Math.random(), e.g. put this in a --pre-js: var crypto = { getRandomValues: function(array) { for (var i = 0; i < array.length; i++) array[i] = (Math.random()*256)|0 } };\");\n };\n}\n\nvar PATH_FS = {\n resolve: function() {\n var resolvedPath = \"\", resolvedAbsolute = false;\n for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n var path = i >= 0 ? arguments[i] : FS.cwd();\n if (typeof path !== \"string\") {\n throw new TypeError(\"Arguments to path.resolve must be strings\");\n } else if (!path) {\n return \"\";\n }\n resolvedPath = path + \"/\" + resolvedPath;\n resolvedAbsolute = path.charAt(0) === \"/\";\n }\n resolvedPath = PATH.normalizeArray(resolvedPath.split(\"/\").filter(function(p) {\n return !!p;\n }), !resolvedAbsolute).join(\"/\");\n return (resolvedAbsolute ? \"/\" : \"\") + resolvedPath || \".\";\n },\n relative: function(from, to) {\n from = PATH_FS.resolve(from).substr(1);\n to = PATH_FS.resolve(to).substr(1);\n function trim(arr) {\n var start = 0;\n for (;start < arr.length; start++) {\n if (arr[start] !== \"\") break;\n }\n var end = arr.length - 1;\n for (;end >= 0; end--) {\n if (arr[end] !== \"\") break;\n }\n if (start > end) return [];\n return arr.slice(start, end - start + 1);\n }\n var fromParts = trim(from.split(\"/\"));\n var toParts = trim(to.split(\"/\"));\n var length = Math.min(fromParts.length, toParts.length);\n var samePartsLength = length;\n for (var i = 0; i < length; i++) {\n if (fromParts[i] !== toParts[i]) {\n samePartsLength = i;\n break;\n }\n }\n var outputParts = [];\n for (var i = samePartsLength; i < fromParts.length; i++) {\n outputParts.push(\"..\");\n }\n outputParts = outputParts.concat(toParts.slice(samePartsLength));\n return outputParts.join(\"/\");\n }\n};\n\nvar TTY = {\n ttys: [],\n init: function() {},\n shutdown: function() {},\n register: function(dev, ops) {\n TTY.ttys[dev] = {\n input: [],\n output: [],\n ops: ops\n };\n FS.registerDevice(dev, TTY.stream_ops);\n },\n stream_ops: {\n open: function(stream) {\n var tty = TTY.ttys[stream.node.rdev];\n if (!tty) {\n throw new FS.ErrnoError(43);\n }\n stream.tty = tty;\n stream.seekable = false;\n },\n close: function(stream) {\n stream.tty.ops.flush(stream.tty);\n },\n flush: function(stream) {\n stream.tty.ops.flush(stream.tty);\n },\n read: function(stream, buffer, offset, length, pos) {\n if (!stream.tty || !stream.tty.ops.get_char) {\n throw new FS.ErrnoError(60);\n }\n var bytesRead = 0;\n for (var i = 0; i < length; i++) {\n var result;\n try {\n result = stream.tty.ops.get_char(stream.tty);\n } catch (e) {\n throw new FS.ErrnoError(29);\n }\n if (result === undefined && bytesRead === 0) {\n throw new FS.ErrnoError(6);\n }\n if (result === null || result === undefined) break;\n bytesRead++;\n buffer[offset + i] = result;\n }\n if (bytesRead) {\n stream.node.timestamp = Date.now();\n }\n return bytesRead;\n },\n write: function(stream, buffer, offset, length, pos) {\n if (!stream.tty || !stream.tty.ops.put_char) {\n throw new FS.ErrnoError(60);\n }\n try {\n for (var i = 0; i < length; i++) {\n stream.tty.ops.put_char(stream.tty, buffer[offset + i]);\n }\n } catch (e) {\n throw new FS.ErrnoError(29);\n }\n if (length) {\n stream.node.timestamp = Date.now();\n }\n return i;\n }\n },\n default_tty_ops: {\n get_char: function(tty) {\n if (!tty.input.length) {\n var result = null;\n if (typeof window != \"undefined\" && typeof window.prompt == \"function\") {\n result = window.prompt(\"Input: \");\n if (result !== null) {\n result += \"\\n\";\n }\n } else if (typeof readline == \"function\") {\n result = readline();\n if (result !== null) {\n result += \"\\n\";\n }\n }\n if (!result) {\n return null;\n }\n tty.input = intArrayFromString(result, true);\n }\n return tty.input.shift();\n },\n put_char: function(tty, val) {\n if (val === null || val === 10) {\n out(UTF8ArrayToString(tty.output, 0));\n tty.output = [];\n } else {\n if (val != 0) tty.output.push(val);\n }\n },\n flush: function(tty) {\n if (tty.output && tty.output.length > 0) {\n out(UTF8ArrayToString(tty.output, 0));\n tty.output = [];\n }\n }\n },\n default_tty1_ops: {\n put_char: function(tty, val) {\n if (val === null || val === 10) {\n err(UTF8ArrayToString(tty.output, 0));\n tty.output = [];\n } else {\n if (val != 0) tty.output.push(val);\n }\n },\n flush: function(tty) {\n if (tty.output && tty.output.length > 0) {\n err(UTF8ArrayToString(tty.output, 0));\n tty.output = [];\n }\n }\n }\n};\n\nfunction zeroMemory(address, size) {\n HEAPU8.fill(0, address, address + size);\n}\n\nfunction alignMemory(size, alignment) {\n assert(alignment, \"alignment argument is required\");\n return Math.ceil(size / alignment) * alignment;\n}\n\nfunction mmapAlloc(size) {\n size = alignMemory(size, 65536);\n var ptr = _memalign(65536, size);\n if (!ptr) return 0;\n zeroMemory(ptr, size);\n return ptr;\n}\n\nvar MEMFS = {\n ops_table: null,\n mount: function(mount) {\n return MEMFS.createNode(null, \"/\", 16384 | 511, 0);\n },\n createNode: function(parent, name, mode, dev) {\n if (FS.isBlkdev(mode) || FS.isFIFO(mode)) {\n throw new FS.ErrnoError(63);\n }\n if (!MEMFS.ops_table) {\n MEMFS.ops_table = {\n dir: {\n node: {\n getattr: MEMFS.node_ops.getattr,\n setattr: MEMFS.node_ops.setattr,\n lookup: MEMFS.node_ops.lookup,\n mknod: MEMFS.node_ops.mknod,\n rename: MEMFS.node_ops.rename,\n unlink: MEMFS.node_ops.unlink,\n rmdir: MEMFS.node_ops.rmdir,\n readdir: MEMFS.node_ops.readdir,\n symlink: MEMFS.node_ops.symlink\n },\n stream: {\n llseek: MEMFS.stream_ops.llseek\n }\n },\n file: {\n node: {\n getattr: MEMFS.node_ops.getattr,\n setattr: MEMFS.node_ops.setattr\n },\n stream: {\n llseek: MEMFS.stream_ops.llseek,\n read: MEMFS.stream_ops.read,\n write: MEMFS.stream_ops.write,\n allocate: MEMFS.stream_ops.allocate,\n mmap: MEMFS.stream_ops.mmap,\n msync: MEMFS.stream_ops.msync\n }\n },\n link: {\n node: {\n getattr: MEMFS.node_ops.getattr,\n setattr: MEMFS.node_ops.setattr,\n readlink: MEMFS.node_ops.readlink\n },\n stream: {}\n },\n chrdev: {\n node: {\n getattr: MEMFS.node_ops.getattr,\n setattr: MEMFS.node_ops.setattr\n },\n stream: FS.chrdev_stream_ops\n }\n };\n }\n var node = FS.createNode(parent, name, mode, dev);\n if (FS.isDir(node.mode)) {\n node.node_ops = MEMFS.ops_table.dir.node;\n node.stream_ops = MEMFS.ops_table.dir.stream;\n node.contents = {};\n } else if (FS.isFile(node.mode)) {\n node.node_ops = MEMFS.ops_table.file.node;\n node.stream_ops = MEMFS.ops_table.file.stream;\n node.usedBytes = 0;\n node.contents = null;\n } else if (FS.isLink(node.mode)) {\n node.node_ops = MEMFS.ops_table.link.node;\n node.stream_ops = MEMFS.ops_table.link.stream;\n } else if (FS.isChrdev(node.mode)) {\n node.node_ops = MEMFS.ops_table.chrdev.node;\n node.stream_ops = MEMFS.ops_table.chrdev.stream;\n }\n node.timestamp = Date.now();\n if (parent) {\n parent.contents[name] = node;\n parent.timestamp = node.timestamp;\n }\n return node;\n },\n getFileDataAsTypedArray: function(node) {\n if (!node.contents) return new Uint8Array(0);\n if (node.contents.subarray) return node.contents.subarray(0, node.usedBytes);\n return new Uint8Array(node.contents);\n },\n expandFileStorage: function(node, newCapacity) {\n var prevCapacity = node.contents ? node.contents.length : 0;\n if (prevCapacity >= newCapacity) return;\n var CAPACITY_DOUBLING_MAX = 1024 * 1024;\n newCapacity = Math.max(newCapacity, prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2 : 1.125) >>> 0);\n if (prevCapacity != 0) newCapacity = Math.max(newCapacity, 256);\n var oldContents = node.contents;\n node.contents = new Uint8Array(newCapacity);\n if (node.usedBytes > 0) node.contents.set(oldContents.subarray(0, node.usedBytes), 0);\n },\n resizeFileStorage: function(node, newSize) {\n if (node.usedBytes == newSize) return;\n if (newSize == 0) {\n node.contents = null;\n node.usedBytes = 0;\n } else {\n var oldContents = node.contents;\n node.contents = new Uint8Array(newSize);\n if (oldContents) {\n node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes)));\n }\n node.usedBytes = newSize;\n }\n },\n node_ops: {\n getattr: function(node) {\n var attr = {};\n attr.dev = FS.isChrdev(node.mode) ? node.id : 1;\n attr.ino = node.id;\n attr.mode = node.mode;\n attr.nlink = 1;\n attr.uid = 0;\n attr.gid = 0;\n attr.rdev = node.rdev;\n if (FS.isDir(node.mode)) {\n attr.size = 4096;\n } else if (FS.isFile(node.mode)) {\n attr.size = node.usedBytes;\n } else if (FS.isLink(node.mode)) {\n attr.size = node.link.length;\n } else {\n attr.size = 0;\n }\n attr.atime = new Date(node.timestamp);\n attr.mtime = new Date(node.timestamp);\n attr.ctime = new Date(node.timestamp);\n attr.blksize = 4096;\n attr.blocks = Math.ceil(attr.size / attr.blksize);\n return attr;\n },\n setattr: function(node, attr) {\n if (attr.mode !== undefined) {\n node.mode = attr.mode;\n }\n if (attr.timestamp !== undefined) {\n node.timestamp = attr.timestamp;\n }\n if (attr.size !== undefined) {\n MEMFS.resizeFileStorage(node, attr.size);\n }\n },\n lookup: function(parent, name) {\n throw FS.genericErrors[44];\n },\n mknod: function(parent, name, mode, dev) {\n return MEMFS.createNode(parent, name, mode, dev);\n },\n rename: function(old_node, new_dir, new_name) {\n if (FS.isDir(old_node.mode)) {\n var new_node;\n try {\n new_node = FS.lookupNode(new_dir, new_name);\n } catch (e) {}\n if (new_node) {\n for (var i in new_node.contents) {\n throw new FS.ErrnoError(55);\n }\n }\n }\n delete old_node.parent.contents[old_node.name];\n old_node.parent.timestamp = Date.now();\n old_node.name = new_name;\n new_dir.contents[new_name] = old_node;\n new_dir.timestamp = old_node.parent.timestamp;\n old_node.parent = new_dir;\n },\n unlink: function(parent, name) {\n delete parent.contents[name];\n parent.timestamp = Date.now();\n },\n rmdir: function(parent, name) {\n var node = FS.lookupNode(parent, name);\n for (var i in node.contents) {\n throw new FS.ErrnoError(55);\n }\n delete parent.contents[name];\n parent.timestamp = Date.now();\n },\n readdir: function(node) {\n var entries = [ \".\", \"..\" ];\n for (var key in node.contents) {\n if (!node.contents.hasOwnProperty(key)) {\n continue;\n }\n entries.push(key);\n }\n return entries;\n },\n symlink: function(parent, newname, oldpath) {\n var node = MEMFS.createNode(parent, newname, 511 | 40960, 0);\n node.link = oldpath;\n return node;\n },\n readlink: function(node) {\n if (!FS.isLink(node.mode)) {\n throw new FS.ErrnoError(28);\n }\n return node.link;\n }\n },\n stream_ops: {\n read: function(stream, buffer, offset, length, position) {\n var contents = stream.node.contents;\n if (position >= stream.node.usedBytes) return 0;\n var size = Math.min(stream.node.usedBytes - position, length);\n assert(size >= 0);\n if (size > 8 && contents.subarray) {\n buffer.set(contents.subarray(position, position + size), offset);\n } else {\n for (var i = 0; i < size; i++) buffer[offset + i] = contents[position + i];\n }\n return size;\n },\n write: function(stream, buffer, offset, length, position, canOwn) {\n assert(!(buffer instanceof ArrayBuffer));\n if (!length) return 0;\n var node = stream.node;\n node.timestamp = Date.now();\n if (buffer.subarray && (!node.contents || node.contents.subarray)) {\n if (canOwn) {\n assert(position === 0, \"canOwn must imply no weird position inside the file\");\n node.contents = buffer.subarray(offset, offset + length);\n node.usedBytes = length;\n return length;\n } else if (node.usedBytes === 0 && position === 0) {\n node.contents = buffer.slice(offset, offset + length);\n node.usedBytes = length;\n return length;\n } else if (position + length <= node.usedBytes) {\n node.contents.set(buffer.subarray(offset, offset + length), position);\n return length;\n }\n }\n MEMFS.expandFileStorage(node, position + length);\n if (node.contents.subarray && buffer.subarray) {\n node.contents.set(buffer.subarray(offset, offset + length), position);\n } else {\n for (var i = 0; i < length; i++) {\n node.contents[position + i] = buffer[offset + i];\n }\n }\n node.usedBytes = Math.max(node.usedBytes, position + length);\n return length;\n },\n llseek: function(stream, offset, whence) {\n var position = offset;\n if (whence === 1) {\n position += stream.position;\n } else if (whence === 2) {\n if (FS.isFile(stream.node.mode)) {\n position += stream.node.usedBytes;\n }\n }\n if (position < 0) {\n throw new FS.ErrnoError(28);\n }\n return position;\n },\n allocate: function(stream, offset, length) {\n MEMFS.expandFileStorage(stream.node, offset + length);\n stream.node.usedBytes = Math.max(stream.node.usedBytes, offset + length);\n },\n mmap: function(stream, address, length, position, prot, flags) {\n if (address !== 0) {\n throw new FS.ErrnoError(28);\n }\n if (!FS.isFile(stream.node.mode)) {\n throw new FS.ErrnoError(43);\n }\n var ptr;\n var allocated;\n var contents = stream.node.contents;\n if (!(flags & 2) && contents.buffer === buffer) {\n allocated = false;\n ptr = contents.byteOffset;\n } else {\n if (position > 0 || position + length < contents.length) {\n if (contents.subarray) {\n contents = contents.subarray(position, position + length);\n } else {\n contents = Array.prototype.slice.call(contents, position, position + length);\n }\n }\n allocated = true;\n ptr = mmapAlloc(length);\n if (!ptr) {\n throw new FS.ErrnoError(48);\n }\n HEAP8.set(contents, ptr);\n }\n return {\n ptr: ptr,\n allocated: allocated\n };\n },\n msync: function(stream, buffer, offset, length, mmapFlags) {\n if (!FS.isFile(stream.node.mode)) {\n throw new FS.ErrnoError(43);\n }\n if (mmapFlags & 2) {\n return 0;\n }\n var bytesWritten = MEMFS.stream_ops.write(stream, buffer, 0, length, offset, false);\n return 0;\n }\n }\n};\n\nfunction asyncLoad(url, onload, onerror, noRunDep) {\n var dep = !noRunDep ? getUniqueRunDependency(\"al \" + url) : \"\";\n readAsync(url, function(arrayBuffer) {\n assert(arrayBuffer, 'Loading data file \"' + url + '\" failed (no arrayBuffer).');\n onload(new Uint8Array(arrayBuffer));\n if (dep) removeRunDependency(dep);\n }, function(event) {\n if (onerror) {\n onerror();\n } else {\n throw 'Loading data file \"' + url + '\" failed.';\n }\n });\n if (dep) addRunDependency(dep);\n}\n\nvar ERRNO_MESSAGES = {\n 0: \"Success\",\n 1: \"Arg list too long\",\n 2: \"Permission denied\",\n 3: \"Address already in use\",\n 4: \"Address not available\",\n 5: \"Address family not supported by protocol family\",\n 6: \"No more processes\",\n 7: \"Socket already connected\",\n 8: \"Bad file number\",\n 9: \"Trying to read unreadable message\",\n 10: \"Mount device busy\",\n 11: \"Operation canceled\",\n 12: \"No children\",\n 13: \"Connection aborted\",\n 14: \"Connection refused\",\n 15: \"Connection reset by peer\",\n 16: \"File locking deadlock error\",\n 17: \"Destination address required\",\n 18: \"Math arg out of domain of func\",\n 19: \"Quota exceeded\",\n 20: \"File exists\",\n 21: \"Bad address\",\n 22: \"File too large\",\n 23: \"Host is unreachable\",\n 24: \"Identifier removed\",\n 25: \"Illegal byte sequence\",\n 26: \"Connection already in progress\",\n 27: \"Interrupted system call\",\n 28: \"Invalid argument\",\n 29: \"I/O error\",\n 30: \"Socket is already connected\",\n 31: \"Is a directory\",\n 32: \"Too many symbolic links\",\n 33: \"Too many open files\",\n 34: \"Too many links\",\n 35: \"Message too long\",\n 36: \"Multihop attempted\",\n 37: \"File or path name too long\",\n 38: \"Network interface is not configured\",\n 39: \"Connection reset by network\",\n 40: \"Network is unreachable\",\n 41: \"Too many open files in system\",\n 42: \"No buffer space available\",\n 43: \"No such device\",\n 44: \"No such file or directory\",\n 45: \"Exec format error\",\n 46: \"No record locks available\",\n 47: \"The link has been severed\",\n 48: \"Not enough core\",\n 49: \"No message of desired type\",\n 50: \"Protocol not available\",\n 51: \"No space left on device\",\n 52: \"Function not implemented\",\n 53: \"Socket is not connected\",\n 54: \"Not a directory\",\n 55: \"Directory not empty\",\n 56: \"State not recoverable\",\n 57: \"Socket operation on non-socket\",\n 59: \"Not a typewriter\",\n 60: \"No such device or address\",\n 61: \"Value too large for defined data type\",\n 62: \"Previous owner died\",\n 63: \"Not super-user\",\n 64: \"Broken pipe\",\n 65: \"Protocol error\",\n 66: \"Unknown protocol\",\n 67: \"Protocol wrong type for socket\",\n 68: \"Math result not representable\",\n 69: \"Read only file system\",\n 70: \"Illegal seek\",\n 71: \"No such process\",\n 72: \"Stale file handle\",\n 73: \"Connection timed out\",\n 74: \"Text file busy\",\n 75: \"Cross-device link\",\n 100: \"Device not a stream\",\n 101: \"Bad font file fmt\",\n 102: \"Invalid slot\",\n 103: \"Invalid request code\",\n 104: \"No anode\",\n 105: \"Block device required\",\n 106: \"Channel number out of range\",\n 107: \"Level 3 halted\",\n 108: \"Level 3 reset\",\n 109: \"Link number out of range\",\n 110: \"Protocol driver not attached\",\n 111: \"No CSI structure available\",\n 112: \"Level 2 halted\",\n 113: \"Invalid exchange\",\n 114: \"Invalid request descriptor\",\n 115: \"Exchange full\",\n 116: \"No data (for no delay io)\",\n 117: \"Timer expired\",\n 118: \"Out of streams resources\",\n 119: \"Machine is not on the network\",\n 120: \"Package not installed\",\n 121: \"The object is remote\",\n 122: \"Advertise error\",\n 123: \"Srmount error\",\n 124: \"Communication error on send\",\n 125: \"Cross mount point (not really error)\",\n 126: \"Given log. name not unique\",\n 127: \"f.d. invalid for this operation\",\n 128: \"Remote address changed\",\n 129: \"Can access a needed shared lib\",\n 130: \"Accessing a corrupted shared lib\",\n 131: \".lib section in a.out corrupted\",\n 132: \"Attempting to link in too many libs\",\n 133: \"Attempting to exec a shared library\",\n 135: \"Streams pipe error\",\n 136: \"Too many users\",\n 137: \"Socket type not supported\",\n 138: \"Not supported\",\n 139: \"Protocol family not supported\",\n 140: \"Can't send after socket shutdown\",\n 141: \"Too many references\",\n 142: \"Host is down\",\n 148: \"No medium (in tape drive)\",\n 156: \"Level 2 not synchronized\"\n};\n\nvar ERRNO_CODES = {};\n\nvar FS = {\n root: null,\n mounts: [],\n devices: {},\n streams: [],\n nextInode: 1,\n nameTable: null,\n currentPath: \"/\",\n initialized: false,\n ignorePermissions: true,\n ErrnoError: null,\n genericErrors: {},\n filesystems: null,\n syncFSRequests: 0,\n lookupPath: (path, opts = {}) => {\n path = PATH_FS.resolve(FS.cwd(), path);\n if (!path) return {\n path: \"\",\n node: null\n };\n var defaults = {\n follow_mount: true,\n recurse_count: 0\n };\n for (var key in defaults) {\n if (opts[key] === undefined) {\n opts[key] = defaults[key];\n }\n }\n if (opts.recurse_count > 8) {\n throw new FS.ErrnoError(32);\n }\n var parts = PATH.normalizeArray(path.split(\"/\").filter(p => !!p), false);\n var current = FS.root;\n var current_path = \"/\";\n for (var i = 0; i < parts.length; i++) {\n var islast = i === parts.length - 1;\n if (islast && opts.parent) {\n break;\n }\n current = FS.lookupNode(current, parts[i]);\n current_path = PATH.join2(current_path, parts[i]);\n if (FS.isMountpoint(current)) {\n if (!islast || islast && opts.follow_mount) {\n current = current.mounted.root;\n }\n }\n if (!islast || opts.follow) {\n var count = 0;\n while (FS.isLink(current.mode)) {\n var link = FS.readlink(current_path);\n current_path = PATH_FS.resolve(PATH.dirname(current_path), link);\n var lookup = FS.lookupPath(current_path, {\n recurse_count: opts.recurse_count\n });\n current = lookup.node;\n if (count++ > 40) {\n throw new FS.ErrnoError(32);\n }\n }\n }\n }\n return {\n path: current_path,\n node: current\n };\n },\n getPath: node => {\n var path;\n while (true) {\n if (FS.isRoot(node)) {\n var mount = node.mount.mountpoint;\n if (!path) return mount;\n return mount[mount.length - 1] !== \"/\" ? mount + \"/\" + path : mount + path;\n }\n path = path ? node.name + \"/\" + path : node.name;\n node = node.parent;\n }\n },\n hashName: (parentid, name) => {\n var hash = 0;\n for (var i = 0; i < name.length; i++) {\n hash = (hash << 5) - hash + name.charCodeAt(i) | 0;\n }\n return (parentid + hash >>> 0) % FS.nameTable.length;\n },\n hashAddNode: node => {\n var hash = FS.hashName(node.parent.id, node.name);\n node.name_next = FS.nameTable[hash];\n FS.nameTable[hash] = node;\n },\n hashRemoveNode: node => {\n var hash = FS.hashName(node.parent.id, node.name);\n if (FS.nameTable[hash] === node) {\n FS.nameTable[hash] = node.name_next;\n } else {\n var current = FS.nameTable[hash];\n while (current) {\n if (current.name_next === node) {\n current.name_next = node.name_next;\n break;\n }\n current = current.name_next;\n }\n }\n },\n lookupNode: (parent, name) => {\n var errCode = FS.mayLookup(parent);\n if (errCode) {\n throw new FS.ErrnoError(errCode, parent);\n }\n var hash = FS.hashName(parent.id, name);\n for (var node = FS.nameTable[hash]; node; node = node.name_next) {\n var nodeName = node.name;\n if (node.parent.id === parent.id && nodeName === name) {\n return node;\n }\n }\n return FS.lookup(parent, name);\n },\n createNode: (parent, name, mode, rdev) => {\n assert(typeof parent === \"object\");\n var node = new FS.FSNode(parent, name, mode, rdev);\n FS.hashAddNode(node);\n return node;\n },\n destroyNode: node => {\n FS.hashRemoveNode(node);\n },\n isRoot: node => {\n return node === node.parent;\n },\n isMountpoint: node => {\n return !!node.mounted;\n },\n isFile: mode => {\n return (mode & 61440) === 32768;\n },\n isDir: mode => {\n return (mode & 61440) === 16384;\n },\n isLink: mode => {\n return (mode & 61440) === 40960;\n },\n isChrdev: mode => {\n return (mode & 61440) === 8192;\n },\n isBlkdev: mode => {\n return (mode & 61440) === 24576;\n },\n isFIFO: mode => {\n return (mode & 61440) === 4096;\n },\n isSocket: mode => {\n return (mode & 49152) === 49152;\n },\n flagModes: {\n \"r\": 0,\n \"r+\": 2,\n \"w\": 577,\n \"w+\": 578,\n \"a\": 1089,\n \"a+\": 1090\n },\n modeStringToFlags: str => {\n var flags = FS.flagModes[str];\n if (typeof flags === \"undefined\") {\n throw new Error(\"Unknown file open mode: \" + str);\n }\n return flags;\n },\n flagsToPermissionString: flag => {\n var perms = [ \"r\", \"w\", \"rw\" ][flag & 3];\n if (flag & 512) {\n perms += \"w\";\n }\n return perms;\n },\n nodePermissions: (node, perms) => {\n if (FS.ignorePermissions) {\n return 0;\n }\n if (perms.includes(\"r\") && !(node.mode & 292)) {\n return 2;\n } else if (perms.includes(\"w\") && !(node.mode & 146)) {\n return 2;\n } else if (perms.includes(\"x\") && !(node.mode & 73)) {\n return 2;\n }\n return 0;\n },\n mayLookup: dir => {\n var errCode = FS.nodePermissions(dir, \"x\");\n if (errCode) return errCode;\n if (!dir.node_ops.lookup) return 2;\n return 0;\n },\n mayCreate: (dir, name) => {\n try {\n var node = FS.lookupNode(dir, name);\n return 20;\n } catch (e) {}\n return FS.nodePermissions(dir, \"wx\");\n },\n mayDelete: (dir, name, isdir) => {\n var node;\n try {\n node = FS.lookupNode(dir, name);\n } catch (e) {\n return e.errno;\n }\n var errCode = FS.nodePermissions(dir, \"wx\");\n if (errCode) {\n return errCode;\n }\n if (isdir) {\n if (!FS.isDir(node.mode)) {\n return 54;\n }\n if (FS.isRoot(node) || FS.getPath(node) === FS.cwd()) {\n return 10;\n }\n } else {\n if (FS.isDir(node.mode)) {\n return 31;\n }\n }\n return 0;\n },\n mayOpen: (node, flags) => {\n if (!node) {\n return 44;\n }\n if (FS.isLink(node.mode)) {\n return 32;\n } else if (FS.isDir(node.mode)) {\n if (FS.flagsToPermissionString(flags) !== \"r\" || flags & 512) {\n return 31;\n }\n }\n return FS.nodePermissions(node, FS.flagsToPermissionString(flags));\n },\n MAX_OPEN_FDS: 4096,\n nextfd: (fd_start = 0, fd_end = FS.MAX_OPEN_FDS) => {\n for (var fd = fd_start; fd <= fd_end; fd++) {\n if (!FS.streams[fd]) {\n return fd;\n }\n }\n throw new FS.ErrnoError(33);\n },\n getStream: fd => FS.streams[fd],\n createStream: (stream, fd_start, fd_end) => {\n if (!FS.FSStream) {\n FS.FSStream = function() {};\n FS.FSStream.prototype = {\n object: {\n get: function() {\n return this.node;\n },\n set: function(val) {\n this.node = val;\n }\n },\n isRead: {\n get: function() {\n return (this.flags & 2097155) !== 1;\n }\n },\n isWrite: {\n get: function() {\n return (this.flags & 2097155) !== 0;\n }\n },\n isAppend: {\n get: function() {\n return this.flags & 1024;\n }\n }\n };\n }\n stream = Object.assign(new FS.FSStream(), stream);\n var fd = FS.nextfd(fd_start, fd_end);\n stream.fd = fd;\n FS.streams[fd] = stream;\n return stream;\n },\n closeStream: fd => {\n FS.streams[fd] = null;\n },\n chrdev_stream_ops: {\n open: stream => {\n var device = FS.getDevice(stream.node.rdev);\n stream.stream_ops = device.stream_ops;\n if (stream.stream_ops.open) {\n stream.stream_ops.open(stream);\n }\n },\n llseek: () => {\n throw new FS.ErrnoError(70);\n }\n },\n major: dev => dev >> 8,\n minor: dev => dev & 255,\n makedev: (ma, mi) => ma << 8 | mi,\n registerDevice: (dev, ops) => {\n FS.devices[dev] = {\n stream_ops: ops\n };\n },\n getDevice: dev => FS.devices[dev],\n getMounts: mount => {\n var mounts = [];\n var check = [ mount ];\n while (check.length) {\n var m = check.pop();\n mounts.push(m);\n check.push.apply(check, m.mounts);\n }\n return mounts;\n },\n syncfs: (populate, callback) => {\n if (typeof populate === \"function\") {\n callback = populate;\n populate = false;\n }\n FS.syncFSRequests++;\n if (FS.syncFSRequests > 1) {\n err(\"warning: \" + FS.syncFSRequests + \" FS.syncfs operations in flight at once, probably just doing extra work\");\n }\n var mounts = FS.getMounts(FS.root.mount);\n var completed = 0;\n function doCallback(errCode) {\n assert(FS.syncFSRequests > 0);\n FS.syncFSRequests--;\n return callback(errCode);\n }\n function done(errCode) {\n if (errCode) {\n if (!done.errored) {\n done.errored = true;\n return doCallback(errCode);\n }\n return;\n }\n if (++completed >= mounts.length) {\n doCallback(null);\n }\n }\n mounts.forEach(mount => {\n if (!mount.type.syncfs) {\n return done(null);\n }\n mount.type.syncfs(mount, populate, done);\n });\n },\n mount: (type, opts, mountpoint) => {\n if (typeof type === \"string\") {\n throw type;\n }\n var root = mountpoint === \"/\";\n var pseudo = !mountpoint;\n var node;\n if (root && FS.root) {\n throw new FS.ErrnoError(10);\n } else if (!root && !pseudo) {\n var lookup = FS.lookupPath(mountpoint, {\n follow_mount: false\n });\n mountpoint = lookup.path;\n node = lookup.node;\n if (FS.isMountpoint(node)) {\n throw new FS.ErrnoError(10);\n }\n if (!FS.isDir(node.mode)) {\n throw new FS.ErrnoError(54);\n }\n }\n var mount = {\n type: type,\n opts: opts,\n mountpoint: mountpoint,\n mounts: []\n };\n var mountRoot = type.mount(mount);\n mountRoot.mount = mount;\n mount.root = mountRoot;\n if (root) {\n FS.root = mountRoot;\n } else if (node) {\n node.mounted = mount;\n if (node.mount) {\n node.mount.mounts.push(mount);\n }\n }\n return mountRoot;\n },\n unmount: mountpoint => {\n var lookup = FS.lookupPath(mountpoint, {\n follow_mount: false\n });\n if (!FS.isMountpoint(lookup.node)) {\n throw new FS.ErrnoError(28);\n }\n var node = lookup.node;\n var mount = node.mounted;\n var mounts = FS.getMounts(mount);\n Object.keys(FS.nameTable).forEach(hash => {\n var current = FS.nameTable[hash];\n while (current) {\n var next = current.name_next;\n if (mounts.includes(current.mount)) {\n FS.destroyNode(current);\n }\n current = next;\n }\n });\n node.mounted = null;\n var idx = node.mount.mounts.indexOf(mount);\n assert(idx !== -1);\n node.mount.mounts.splice(idx, 1);\n },\n lookup: (parent, name) => {\n return parent.node_ops.lookup(parent, name);\n },\n mknod: (path, mode, dev) => {\n var lookup = FS.lookupPath(path, {\n parent: true\n });\n var parent = lookup.node;\n var name = PATH.basename(path);\n if (!name || name === \".\" || name === \"..\") {\n throw new FS.ErrnoError(28);\n }\n var errCode = FS.mayCreate(parent, name);\n if (errCode) {\n throw new FS.ErrnoError(errCode);\n }\n if (!parent.node_ops.mknod) {\n throw new FS.ErrnoError(63);\n }\n return parent.node_ops.mknod(parent, name, mode, dev);\n },\n create: (path, mode) => {\n mode = mode !== undefined ? mode : 438;\n mode &= 4095;\n mode |= 32768;\n return FS.mknod(path, mode, 0);\n },\n mkdir: (path, mode) => {\n mode = mode !== undefined ? mode : 511;\n mode &= 511 | 512;\n mode |= 16384;\n return FS.mknod(path, mode, 0);\n },\n mkdirTree: (path, mode) => {\n var dirs = path.split(\"/\");\n var d = \"\";\n for (var i = 0; i < dirs.length; ++i) {\n if (!dirs[i]) continue;\n d += \"/\" + dirs[i];\n try {\n FS.mkdir(d, mode);\n } catch (e) {\n if (e.errno != 20) throw e;\n }\n }\n },\n mkdev: (path, mode, dev) => {\n if (typeof dev === \"undefined\") {\n dev = mode;\n mode = 438;\n }\n mode |= 8192;\n return FS.mknod(path, mode, dev);\n },\n symlink: (oldpath, newpath) => {\n if (!PATH_FS.resolve(oldpath)) {\n throw new FS.ErrnoError(44);\n }\n var lookup = FS.lookupPath(newpath, {\n parent: true\n });\n var parent = lookup.node;\n if (!parent) {\n throw new FS.ErrnoError(44);\n }\n var newname = PATH.basename(newpath);\n var errCode = FS.mayCreate(parent, newname);\n if (errCode) {\n throw new FS.ErrnoError(errCode);\n }\n if (!parent.node_ops.symlink) {\n throw new FS.ErrnoError(63);\n }\n return parent.node_ops.symlink(parent, newname, oldpath);\n },\n rename: (old_path, new_path) => {\n var old_dirname = PATH.dirname(old_path);\n var new_dirname = PATH.dirname(new_path);\n var old_name = PATH.basename(old_path);\n var new_name = PATH.basename(new_path);\n var lookup, old_dir, new_dir;\n lookup = FS.lookupPath(old_path, {\n parent: true\n });\n old_dir = lookup.node;\n lookup = FS.lookupPath(new_path, {\n parent: true\n });\n new_dir = lookup.node;\n if (!old_dir || !new_dir) throw new FS.ErrnoError(44);\n if (old_dir.mount !== new_dir.mount) {\n throw new FS.ErrnoError(75);\n }\n var old_node = FS.lookupNode(old_dir, old_name);\n var relative = PATH_FS.relative(old_path, new_dirname);\n if (relative.charAt(0) !== \".\") {\n throw new FS.ErrnoError(28);\n }\n relative = PATH_FS.relative(new_path, old_dirname);\n if (relative.charAt(0) !== \".\") {\n throw new FS.ErrnoError(55);\n }\n var new_node;\n try {\n new_node = FS.lookupNode(new_dir, new_name);\n } catch (e) {}\n if (old_node === new_node) {\n return;\n }\n var isdir = FS.isDir(old_node.mode);\n var errCode = FS.mayDelete(old_dir, old_name, isdir);\n if (errCode) {\n throw new FS.ErrnoError(errCode);\n }\n errCode = new_node ? FS.mayDelete(new_dir, new_name, isdir) : FS.mayCreate(new_dir, new_name);\n if (errCode) {\n throw new FS.ErrnoError(errCode);\n }\n if (!old_dir.node_ops.rename) {\n throw new FS.ErrnoError(63);\n }\n if (FS.isMountpoint(old_node) || new_node && FS.isMountpoint(new_node)) {\n throw new FS.ErrnoError(10);\n }\n if (new_dir !== old_dir) {\n errCode = FS.nodePermissions(old_dir, \"w\");\n if (errCode) {\n throw new FS.ErrnoError(errCode);\n }\n }\n FS.hashRemoveNode(old_node);\n try {\n old_dir.node_ops.rename(old_node, new_dir, new_name);\n } catch (e) {\n throw e;\n } finally {\n FS.hashAddNode(old_node);\n }\n },\n rmdir: path => {\n var lookup = FS.lookupPath(path, {\n parent: true\n });\n var parent = lookup.node;\n var name = PATH.basename(path);\n var node = FS.lookupNode(parent, name);\n var errCode = FS.mayDelete(parent, name, true);\n if (errCode) {\n throw new FS.ErrnoError(errCode);\n }\n if (!parent.node_ops.rmdir) {\n throw new FS.ErrnoError(63);\n }\n if (FS.isMountpoint(node)) {\n throw new FS.ErrnoError(10);\n }\n parent.node_ops.rmdir(parent, name);\n FS.destroyNode(node);\n },\n readdir: path => {\n var lookup = FS.lookupPath(path, {\n follow: true\n });\n var node = lookup.node;\n if (!node.node_ops.readdir) {\n throw new FS.ErrnoError(54);\n }\n return node.node_ops.readdir(node);\n },\n unlink: path => {\n var lookup = FS.lookupPath(path, {\n parent: true\n });\n var parent = lookup.node;\n if (!parent) {\n throw new FS.ErrnoError(44);\n }\n var name = PATH.basename(path);\n var node = FS.lookupNode(parent, name);\n var errCode = FS.mayDelete(parent, name, false);\n if (errCode) {\n throw new FS.ErrnoError(errCode);\n }\n if (!parent.node_ops.unlink) {\n throw new FS.ErrnoError(63);\n }\n if (FS.isMountpoint(node)) {\n throw new FS.ErrnoError(10);\n }\n parent.node_ops.unlink(parent, name);\n FS.destroyNode(node);\n },\n readlink: path => {\n var lookup = FS.lookupPath(path);\n var link = lookup.node;\n if (!link) {\n throw new FS.ErrnoError(44);\n }\n if (!link.node_ops.readlink) {\n throw new FS.ErrnoError(28);\n }\n return PATH_FS.resolve(FS.getPath(link.parent), link.node_ops.readlink(link));\n },\n stat: (path, dontFollow) => {\n var lookup = FS.lookupPath(path, {\n follow: !dontFollow\n });\n var node = lookup.node;\n if (!node) {\n throw new FS.ErrnoError(44);\n }\n if (!node.node_ops.getattr) {\n throw new FS.ErrnoError(63);\n }\n return node.node_ops.getattr(node);\n },\n lstat: path => {\n return FS.stat(path, true);\n },\n chmod: (path, mode, dontFollow) => {\n var node;\n if (typeof path === \"string\") {\n var lookup = FS.lookupPath(path, {\n follow: !dontFollow\n });\n node = lookup.node;\n } else {\n node = path;\n }\n if (!node.node_ops.setattr) {\n throw new FS.ErrnoError(63);\n }\n node.node_ops.setattr(node, {\n mode: mode & 4095 | node.mode & ~4095,\n timestamp: Date.now()\n });\n },\n lchmod: (path, mode) => {\n FS.chmod(path, mode, true);\n },\n fchmod: (fd, mode) => {\n var stream = FS.getStream(fd);\n if (!stream) {\n throw new FS.ErrnoError(8);\n }\n FS.chmod(stream.node, mode);\n },\n chown: (path, uid, gid, dontFollow) => {\n var node;\n if (typeof path === \"string\") {\n var lookup = FS.lookupPath(path, {\n follow: !dontFollow\n });\n node = lookup.node;\n } else {\n node = path;\n }\n if (!node.node_ops.setattr) {\n throw new FS.ErrnoError(63);\n }\n node.node_ops.setattr(node, {\n timestamp: Date.now()\n });\n },\n lchown: (path, uid, gid) => {\n FS.chown(path, uid, gid, true);\n },\n fchown: (fd, uid, gid) => {\n var stream = FS.getStream(fd);\n if (!stream) {\n throw new FS.ErrnoError(8);\n }\n FS.chown(stream.node, uid, gid);\n },\n truncate: (path, len) => {\n if (len < 0) {\n throw new FS.ErrnoError(28);\n }\n var node;\n if (typeof path === \"string\") {\n var lookup = FS.lookupPath(path, {\n follow: true\n });\n node = lookup.node;\n } else {\n node = path;\n }\n if (!node.node_ops.setattr) {\n throw new FS.ErrnoError(63);\n }\n if (FS.isDir(node.mode)) {\n throw new FS.ErrnoError(31);\n }\n if (!FS.isFile(node.mode)) {\n throw new FS.ErrnoError(28);\n }\n var errCode = FS.nodePermissions(node, \"w\");\n if (errCode) {\n throw new FS.ErrnoError(errCode);\n }\n node.node_ops.setattr(node, {\n size: len,\n timestamp: Date.now()\n });\n },\n ftruncate: (fd, len) => {\n var stream = FS.getStream(fd);\n if (!stream) {\n throw new FS.ErrnoError(8);\n }\n if ((stream.flags & 2097155) === 0) {\n throw new FS.ErrnoError(28);\n }\n FS.truncate(stream.node, len);\n },\n utime: (path, atime, mtime) => {\n var lookup = FS.lookupPath(path, {\n follow: true\n });\n var node = lookup.node;\n node.node_ops.setattr(node, {\n timestamp: Math.max(atime, mtime)\n });\n },\n open: (path, flags, mode, fd_start, fd_end) => {\n if (path === \"\") {\n throw new FS.ErrnoError(44);\n }\n flags = typeof flags === \"string\" ? FS.modeStringToFlags(flags) : flags;\n mode = typeof mode === \"undefined\" ? 438 : mode;\n if (flags & 64) {\n mode = mode & 4095 | 32768;\n } else {\n mode = 0;\n }\n var node;\n if (typeof path === \"object\") {\n node = path;\n } else {\n path = PATH.normalize(path);\n try {\n var lookup = FS.lookupPath(path, {\n follow: !(flags & 131072)\n });\n node = lookup.node;\n } catch (e) {}\n }\n var created = false;\n if (flags & 64) {\n if (node) {\n if (flags & 128) {\n throw new FS.ErrnoError(20);\n }\n } else {\n node = FS.mknod(path, mode, 0);\n created = true;\n }\n }\n if (!node) {\n throw new FS.ErrnoError(44);\n }\n if (FS.isChrdev(node.mode)) {\n flags &= ~512;\n }\n if (flags & 65536 && !FS.isDir(node.mode)) {\n throw new FS.ErrnoError(54);\n }\n if (!created) {\n var errCode = FS.mayOpen(node, flags);\n if (errCode) {\n throw new FS.ErrnoError(errCode);\n }\n }\n if (flags & 512) {\n FS.truncate(node, 0);\n }\n flags &= ~(128 | 512 | 131072);\n var stream = FS.createStream({\n node: node,\n path: FS.getPath(node),\n flags: flags,\n seekable: true,\n position: 0,\n stream_ops: node.stream_ops,\n ungotten: [],\n error: false\n }, fd_start, fd_end);\n if (stream.stream_ops.open) {\n stream.stream_ops.open(stream);\n }\n if (Module[\"logReadFiles\"] && !(flags & 1)) {\n if (!FS.readFiles) FS.readFiles = {};\n if (!(path in FS.readFiles)) {\n FS.readFiles[path] = 1;\n }\n }\n return stream;\n },\n close: stream => {\n if (FS.isClosed(stream)) {\n throw new FS.ErrnoError(8);\n }\n if (stream.getdents) stream.getdents = null;\n try {\n if (stream.stream_ops.close) {\n stream.stream_ops.close(stream);\n }\n } catch (e) {\n throw e;\n } finally {\n FS.closeStream(stream.fd);\n }\n stream.fd = null;\n },\n isClosed: stream => {\n return stream.fd === null;\n },\n llseek: (stream, offset, whence) => {\n if (FS.isClosed(stream)) {\n throw new FS.ErrnoError(8);\n }\n if (!stream.seekable || !stream.stream_ops.llseek) {\n throw new FS.ErrnoError(70);\n }\n if (whence != 0 && whence != 1 && whence != 2) {\n throw new FS.ErrnoError(28);\n }\n stream.position = stream.stream_ops.llseek(stream, offset, whence);\n stream.ungotten = [];\n return stream.position;\n },\n read: (stream, buffer, offset, length, position) => {\n if (length < 0 || position < 0) {\n throw new FS.ErrnoError(28);\n }\n if (FS.isClosed(stream)) {\n throw new FS.ErrnoError(8);\n }\n if ((stream.flags & 2097155) === 1) {\n throw new FS.ErrnoError(8);\n }\n if (FS.isDir(stream.node.mode)) {\n throw new FS.ErrnoError(31);\n }\n if (!stream.stream_ops.read) {\n throw new FS.ErrnoError(28);\n }\n var seeking = typeof position !== \"undefined\";\n if (!seeking) {\n position = stream.position;\n } else if (!stream.seekable) {\n throw new FS.ErrnoError(70);\n }\n var bytesRead = stream.stream_ops.read(stream, buffer, offset, length, position);\n if (!seeking) stream.position += bytesRead;\n return bytesRead;\n },\n write: (stream, buffer, offset, length, position, canOwn) => {\n if (length < 0 || position < 0) {\n throw new FS.ErrnoError(28);\n }\n if (FS.isClosed(stream)) {\n throw new FS.ErrnoError(8);\n }\n if ((stream.flags & 2097155) === 0) {\n throw new FS.ErrnoError(8);\n }\n if (FS.isDir(stream.node.mode)) {\n throw new FS.ErrnoError(31);\n }\n if (!stream.stream_ops.write) {\n throw new FS.ErrnoError(28);\n }\n if (stream.seekable && stream.flags & 1024) {\n FS.llseek(stream, 0, 2);\n }\n var seeking = typeof position !== \"undefined\";\n if (!seeking) {\n position = stream.position;\n } else if (!stream.seekable) {\n throw new FS.ErrnoError(70);\n }\n var bytesWritten = stream.stream_ops.write(stream, buffer, offset, length, position, canOwn);\n if (!seeking) stream.position += bytesWritten;\n return bytesWritten;\n },\n allocate: (stream, offset, length) => {\n if (FS.isClosed(stream)) {\n throw new FS.ErrnoError(8);\n }\n if (offset < 0 || length <= 0) {\n throw new FS.ErrnoError(28);\n }\n if ((stream.flags & 2097155) === 0) {\n throw new FS.ErrnoError(8);\n }\n if (!FS.isFile(stream.node.mode) && !FS.isDir(stream.node.mode)) {\n throw new FS.ErrnoError(43);\n }\n if (!stream.stream_ops.allocate) {\n throw new FS.ErrnoError(138);\n }\n stream.stream_ops.allocate(stream, offset, length);\n },\n mmap: (stream, address, length, position, prot, flags) => {\n if ((prot & 2) !== 0 && (flags & 2) === 0 && (stream.flags & 2097155) !== 2) {\n throw new FS.ErrnoError(2);\n }\n if ((stream.flags & 2097155) === 1) {\n throw new FS.ErrnoError(2);\n }\n if (!stream.stream_ops.mmap) {\n throw new FS.ErrnoError(43);\n }\n return stream.stream_ops.mmap(stream, address, length, position, prot, flags);\n },\n msync: (stream, buffer, offset, length, mmapFlags) => {\n if (!stream || !stream.stream_ops.msync) {\n return 0;\n }\n return stream.stream_ops.msync(stream, buffer, offset, length, mmapFlags);\n },\n munmap: stream => 0,\n ioctl: (stream, cmd, arg) => {\n if (!stream.stream_ops.ioctl) {\n throw new FS.ErrnoError(59);\n }\n return stream.stream_ops.ioctl(stream, cmd, arg);\n },\n readFile: (path, opts = {}) => {\n opts.flags = opts.flags || 0;\n opts.encoding = opts.encoding || \"binary\";\n if (opts.encoding !== \"utf8\" && opts.encoding !== \"binary\") {\n throw new Error('Invalid encoding type \"' + opts.encoding + '\"');\n }\n var ret;\n var stream = FS.open(path, opts.flags);\n var stat = FS.stat(path);\n var length = stat.size;\n var buf = new Uint8Array(length);\n FS.read(stream, buf, 0, length, 0);\n if (opts.encoding === \"utf8\") {\n ret = UTF8ArrayToString(buf, 0);\n } else if (opts.encoding === \"binary\") {\n ret = buf;\n }\n FS.close(stream);\n return ret;\n },\n writeFile: (path, data, opts = {}) => {\n opts.flags = opts.flags || 577;\n var stream = FS.open(path, opts.flags, opts.mode);\n if (typeof data === \"string\") {\n var buf = new Uint8Array(lengthBytesUTF8(data) + 1);\n var actualNumBytes = stringToUTF8Array(data, buf, 0, buf.length);\n FS.write(stream, buf, 0, actualNumBytes, undefined, opts.canOwn);\n } else if (ArrayBuffer.isView(data)) {\n FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn);\n } else {\n throw new Error(\"Unsupported data type\");\n }\n FS.close(stream);\n },\n cwd: () => FS.currentPath,\n chdir: path => {\n var lookup = FS.lookupPath(path, {\n follow: true\n });\n if (lookup.node === null) {\n throw new FS.ErrnoError(44);\n }\n if (!FS.isDir(lookup.node.mode)) {\n throw new FS.ErrnoError(54);\n }\n var errCode = FS.nodePermissions(lookup.node, \"x\");\n if (errCode) {\n throw new FS.ErrnoError(errCode);\n }\n FS.currentPath = lookup.path;\n },\n createDefaultDirectories: () => {\n FS.mkdir(\"/tmp\");\n FS.mkdir(\"/home\");\n FS.mkdir(\"/home/web_user\");\n },\n createDefaultDevices: () => {\n FS.mkdir(\"/dev\");\n FS.registerDevice(FS.makedev(1, 3), {\n read: () => 0,\n write: (stream, buffer, offset, length, pos) => length\n });\n FS.mkdev(\"/dev/null\", FS.makedev(1, 3));\n TTY.register(FS.makedev(5, 0), TTY.default_tty_ops);\n TTY.register(FS.makedev(6, 0), TTY.default_tty1_ops);\n FS.mkdev(\"/dev/tty\", FS.makedev(5, 0));\n FS.mkdev(\"/dev/tty1\", FS.makedev(6, 0));\n var random_device = getRandomDevice();\n FS.createDevice(\"/dev\", \"random\", random_device);\n FS.createDevice(\"/dev\", \"urandom\", random_device);\n FS.mkdir(\"/dev/shm\");\n FS.mkdir(\"/dev/shm/tmp\");\n },\n createSpecialDirectories: () => {\n FS.mkdir(\"/proc\");\n var proc_self = FS.mkdir(\"/proc/self\");\n FS.mkdir(\"/proc/self/fd\");\n FS.mount({\n mount: () => {\n var node = FS.createNode(proc_self, \"fd\", 16384 | 511, 73);\n node.node_ops = {\n lookup: (parent, name) => {\n var fd = +name;\n var stream = FS.getStream(fd);\n if (!stream) throw new FS.ErrnoError(8);\n var ret = {\n parent: null,\n mount: {\n mountpoint: \"fake\"\n },\n node_ops: {\n readlink: () => stream.path\n }\n };\n ret.parent = ret;\n return ret;\n }\n };\n return node;\n }\n }, {}, \"/proc/self/fd\");\n },\n createStandardStreams: () => {\n if (Module[\"stdin\"]) {\n FS.createDevice(\"/dev\", \"stdin\", Module[\"stdin\"]);\n } else {\n FS.symlink(\"/dev/tty\", \"/dev/stdin\");\n }\n if (Module[\"stdout\"]) {\n FS.createDevice(\"/dev\", \"stdout\", null, Module[\"stdout\"]);\n } else {\n FS.symlink(\"/dev/tty\", \"/dev/stdout\");\n }\n if (Module[\"stderr\"]) {\n FS.createDevice(\"/dev\", \"stderr\", null, Module[\"stderr\"]);\n } else {\n FS.symlink(\"/dev/tty1\", \"/dev/stderr\");\n }\n var stdin = FS.open(\"/dev/stdin\", 0);\n var stdout = FS.open(\"/dev/stdout\", 1);\n var stderr = FS.open(\"/dev/stderr\", 1);\n assert(stdin.fd === 0, \"invalid handle for stdin (\" + stdin.fd + \")\");\n assert(stdout.fd === 1, \"invalid handle for stdout (\" + stdout.fd + \")\");\n assert(stderr.fd === 2, \"invalid handle for stderr (\" + stderr.fd + \")\");\n },\n ensureErrnoError: () => {\n if (FS.ErrnoError) return;\n FS.ErrnoError = function ErrnoError(errno, node) {\n this.node = node;\n this.setErrno = function(errno) {\n this.errno = errno;\n for (var key in ERRNO_CODES) {\n if (ERRNO_CODES[key] === errno) {\n this.code = key;\n break;\n }\n }\n };\n this.setErrno(errno);\n this.message = ERRNO_MESSAGES[errno];\n if (this.stack) {\n Object.defineProperty(this, \"stack\", {\n value: new Error().stack,\n writable: true\n });\n this.stack = demangleAll(this.stack);\n }\n };\n FS.ErrnoError.prototype = new Error();\n FS.ErrnoError.prototype.constructor = FS.ErrnoError;\n [ 44 ].forEach(code => {\n FS.genericErrors[code] = new FS.ErrnoError(code);\n FS.genericErrors[code].stack = \"<generic error, no stack>\";\n });\n },\n staticInit: () => {\n FS.ensureErrnoError();\n FS.nameTable = new Array(4096);\n FS.mount(MEMFS, {}, \"/\");\n FS.createDefaultDirectories();\n FS.createDefaultDevices();\n FS.createSpecialDirectories();\n FS.filesystems = {\n \"MEMFS\": MEMFS\n };\n },\n init: (input, output, error) => {\n assert(!FS.init.initialized, \"FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)\");\n FS.init.initialized = true;\n FS.ensureErrnoError();\n Module[\"stdin\"] = input || Module[\"stdin\"];\n Module[\"stdout\"] = output || Module[\"stdout\"];\n Module[\"stderr\"] = error || Module[\"stderr\"];\n FS.createStandardStreams();\n },\n quit: () => {\n FS.init.initialized = false;\n ___stdio_exit();\n for (var i = 0; i < FS.streams.length; i++) {\n var stream = FS.streams[i];\n if (!stream) {\n continue;\n }\n FS.close(stream);\n }\n },\n getMode: (canRead, canWrite) => {\n var mode = 0;\n if (canRead) mode |= 292 | 73;\n if (canWrite) mode |= 146;\n return mode;\n },\n findObject: (path, dontResolveLastLink) => {\n var ret = FS.analyzePath(path, dontResolveLastLink);\n if (ret.exists) {\n return ret.object;\n } else {\n return null;\n }\n },\n analyzePath: (path, dontResolveLastLink) => {\n try {\n var lookup = FS.lookupPath(path, {\n follow: !dontResolveLastLink\n });\n path = lookup.path;\n } catch (e) {}\n var ret = {\n isRoot: false,\n exists: false,\n error: 0,\n name: null,\n path: null,\n object: null,\n parentExists: false,\n parentPath: null,\n parentObject: null\n };\n try {\n var lookup = FS.lookupPath(path, {\n parent: true\n });\n ret.parentExists = true;\n ret.parentPath = lookup.path;\n ret.parentObject = lookup.node;\n ret.name = PATH.basename(path);\n lookup = FS.lookupPath(path, {\n follow: !dontResolveLastLink\n });\n ret.exists = true;\n ret.path = lookup.path;\n ret.object = lookup.node;\n ret.name = lookup.node.name;\n ret.isRoot = lookup.path === \"/\";\n } catch (e) {\n ret.error = e.errno;\n }\n return ret;\n },\n createPath: (parent, path, canRead, canWrite) => {\n parent = typeof parent === \"string\" ? parent : FS.getPath(parent);\n var parts = path.split(\"/\").reverse();\n while (parts.length) {\n var part = parts.pop();\n if (!part) continue;\n var current = PATH.join2(parent, part);\n try {\n FS.mkdir(current);\n } catch (e) {}\n parent = current;\n }\n return current;\n },\n createFile: (parent, name, properties, canRead, canWrite) => {\n var path = PATH.join2(typeof parent === \"string\" ? parent : FS.getPath(parent), name);\n var mode = FS.getMode(canRead, canWrite);\n return FS.create(path, mode);\n },\n createDataFile: (parent, name, data, canRead, canWrite, canOwn) => {\n var path = name;\n if (parent) {\n parent = typeof parent === \"string\" ? parent : FS.getPath(parent);\n path = name ? PATH.join2(parent, name) : parent;\n }\n var mode = FS.getMode(canRead, canWrite);\n var node = FS.create(path, mode);\n if (data) {\n if (typeof data === \"string\") {\n var arr = new Array(data.length);\n for (var i = 0, len = data.length; i < len; ++i) arr[i] = data.charCodeAt(i);\n data = arr;\n }\n FS.chmod(node, mode | 146);\n var stream = FS.open(node, 577);\n FS.write(stream, data, 0, data.length, 0, canOwn);\n FS.close(stream);\n FS.chmod(node, mode);\n }\n return node;\n },\n createDevice: (parent, name, input, output) => {\n var path = PATH.join2(typeof parent === \"string\" ? parent : FS.getPath(parent), name);\n var mode = FS.getMode(!!input, !!output);\n if (!FS.createDevice.major) FS.createDevice.major = 64;\n var dev = FS.makedev(FS.createDevice.major++, 0);\n FS.registerDevice(dev, {\n open: stream => {\n stream.seekable = false;\n },\n close: stream => {\n if (output && output.buffer && output.buffer.length) {\n output(10);\n }\n },\n read: (stream, buffer, offset, length, pos) => {\n var bytesRead = 0;\n for (var i = 0; i < length; i++) {\n var result;\n try {\n result = input();\n } catch (e) {\n throw new FS.ErrnoError(29);\n }\n if (result === undefined && bytesRead === 0) {\n throw new FS.ErrnoError(6);\n }\n if (result === null || result === undefined) break;\n bytesRead++;\n buffer[offset + i] = result;\n }\n if (bytesRead) {\n stream.node.timestamp = Date.now();\n }\n return bytesRead;\n },\n write: (stream, buffer, offset, length, pos) => {\n for (var i = 0; i < length; i++) {\n try {\n output(buffer[offset + i]);\n } catch (e) {\n throw new FS.ErrnoError(29);\n }\n }\n if (length) {\n stream.node.timestamp = Date.now();\n }\n return i;\n }\n });\n return FS.mkdev(path, mode, dev);\n },\n forceLoadFile: obj => {\n if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true;\n if (typeof XMLHttpRequest !== \"undefined\") {\n throw new Error(\"Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.\");\n } else if (read_) {\n try {\n obj.contents = intArrayFromString(read_(obj.url), true);\n obj.usedBytes = obj.contents.length;\n } catch (e) {\n throw new FS.ErrnoError(29);\n }\n } else {\n throw new Error(\"Cannot load without read() or XMLHttpRequest.\");\n }\n },\n createLazyFile: (parent, name, url, canRead, canWrite) => {\n function LazyUint8Array() {\n this.lengthKnown = false;\n this.chunks = [];\n }\n LazyUint8Array.prototype.get = function LazyUint8Array_get(idx) {\n if (idx > this.length - 1 || idx < 0) {\n return undefined;\n }\n var chunkOffset = idx % this.chunkSize;\n var chunkNum = idx / this.chunkSize | 0;\n return this.getter(chunkNum)[chunkOffset];\n };\n LazyUint8Array.prototype.setDataGetter = function LazyUint8Array_setDataGetter(getter) {\n this.getter = getter;\n };\n LazyUint8Array.prototype.cacheLength = function LazyUint8Array_cacheLength() {\n var xhr = new XMLHttpRequest();\n xhr.open(\"HEAD\", url, false);\n xhr.send(null);\n if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error(\"Couldn't load \" + url + \". Status: \" + xhr.status);\n var datalength = Number(xhr.getResponseHeader(\"Content-length\"));\n var header;\n var hasByteServing = (header = xhr.getResponseHeader(\"Accept-Ranges\")) && header === \"bytes\";\n var usesGzip = (header = xhr.getResponseHeader(\"Content-Encoding\")) && header === \"gzip\";\n var chunkSize = 1024 * 1024;\n if (!hasByteServing) chunkSize = datalength;\n var doXHR = (from, to) => {\n if (from > to) throw new Error(\"invalid range (\" + from + \", \" + to + \") or no bytes requested!\");\n if (to > datalength - 1) throw new Error(\"only \" + datalength + \" bytes available! programmer error!\");\n var xhr = new XMLHttpRequest();\n xhr.open(\"GET\", url, false);\n if (datalength !== chunkSize) xhr.setRequestHeader(\"Range\", \"bytes=\" + from + \"-\" + to);\n xhr.responseType = \"arraybuffer\";\n if (xhr.overrideMimeType) {\n xhr.overrideMimeType(\"text/plain; charset=x-user-defined\");\n }\n xhr.send(null);\n if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error(\"Couldn't load \" + url + \". Status: \" + xhr.status);\n if (xhr.response !== undefined) {\n return new Uint8Array(xhr.response || []);\n } else {\n return intArrayFromString(xhr.responseText || \"\", true);\n }\n };\n var lazyArray = this;\n lazyArray.setDataGetter(chunkNum => {\n var start = chunkNum * chunkSize;\n var end = (chunkNum + 1) * chunkSize - 1;\n end = Math.min(end, datalength - 1);\n if (typeof lazyArray.chunks[chunkNum] === \"undefined\") {\n lazyArray.chunks[chunkNum] = doXHR(start, end);\n }\n if (typeof lazyArray.chunks[chunkNum] === \"undefined\") throw new Error(\"doXHR failed!\");\n return lazyArray.chunks[chunkNum];\n });\n if (usesGzip || !datalength) {\n chunkSize = datalength = 1;\n datalength = this.getter(0).length;\n chunkSize = datalength;\n out(\"LazyFiles on gzip forces download of the whole file when length is accessed\");\n }\n this._length = datalength;\n this._chunkSize = chunkSize;\n this.lengthKnown = true;\n };\n if (typeof XMLHttpRequest !== \"undefined\") {\n if (!ENVIRONMENT_IS_WORKER) throw \"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc\";\n var lazyArray = new LazyUint8Array();\n Object.defineProperties(lazyArray, {\n length: {\n get: function() {\n if (!this.lengthKnown) {\n this.cacheLength();\n }\n return this._length;\n }\n },\n chunkSize: {\n get: function() {\n if (!this.lengthKnown) {\n this.cacheLength();\n }\n return this._chunkSize;\n }\n }\n });\n var properties = {\n isDevice: false,\n contents: lazyArray\n };\n } else {\n var properties = {\n isDevice: false,\n url: url\n };\n }\n var node = FS.createFile(parent, name, properties, canRead, canWrite);\n if (properties.contents) {\n node.contents = properties.contents;\n } else if (properties.url) {\n node.contents = null;\n node.url = properties.url;\n }\n Object.defineProperties(node, {\n usedBytes: {\n get: function() {\n return this.contents.length;\n }\n }\n });\n var stream_ops = {};\n var keys = Object.keys(node.stream_ops);\n keys.forEach(key => {\n var fn = node.stream_ops[key];\n stream_ops[key] = function forceLoadLazyFile() {\n FS.forceLoadFile(node);\n return fn.apply(null, arguments);\n };\n });\n stream_ops.read = ((stream, buffer, offset, length, position) => {\n FS.forceLoadFile(node);\n var contents = stream.node.contents;\n if (position >= contents.length) return 0;\n var size = Math.min(contents.length - position, length);\n assert(size >= 0);\n if (contents.slice) {\n for (var i = 0; i < size; i++) {\n buffer[offset + i] = contents[position + i];\n }\n } else {\n for (var i = 0; i < size; i++) {\n buffer[offset + i] = contents.get(position + i);\n }\n }\n return size;\n });\n node.stream_ops = stream_ops;\n return node;\n },\n createPreloadedFile: (parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) => {\n var fullname = name ? PATH_FS.resolve(PATH.join2(parent, name)) : parent;\n var dep = getUniqueRunDependency(\"cp \" + fullname);\n function processData(byteArray) {\n function finish(byteArray) {\n if (preFinish) preFinish();\n if (!dontCreateFile) {\n FS.createDataFile(parent, name, byteArray, canRead, canWrite, canOwn);\n }\n if (onload) onload();\n removeRunDependency(dep);\n }\n if (Browser.handledByPreloadPlugin(byteArray, fullname, finish, () => {\n if (onerror) onerror();\n removeRunDependency(dep);\n })) {\n return;\n }\n finish(byteArray);\n }\n addRunDependency(dep);\n if (typeof url == \"string\") {\n asyncLoad(url, byteArray => processData(byteArray), onerror);\n } else {\n processData(url);\n }\n },\n indexedDB: () => {\n return window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;\n },\n DB_NAME: () => {\n return \"EM_FS_\" + window.location.pathname;\n },\n DB_VERSION: 20,\n DB_STORE_NAME: \"FILE_DATA\",\n saveFilesToDB: (paths, onload, onerror) => {\n onload = onload || (() => {});\n onerror = onerror || (() => {});\n var indexedDB = FS.indexedDB();\n try {\n var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION);\n } catch (e) {\n return onerror(e);\n }\n openRequest.onupgradeneeded = (() => {\n out(\"creating db\");\n var db = openRequest.result;\n db.createObjectStore(FS.DB_STORE_NAME);\n });\n openRequest.onsuccess = (() => {\n var db = openRequest.result;\n var transaction = db.transaction([ FS.DB_STORE_NAME ], \"readwrite\");\n var files = transaction.objectStore(FS.DB_STORE_NAME);\n var ok = 0, fail = 0, total = paths.length;\n function finish() {\n if (fail == 0) onload(); else onerror();\n }\n paths.forEach(path => {\n var putRequest = files.put(FS.analyzePath(path).object.contents, path);\n putRequest.onsuccess = (() => {\n ok++;\n if (ok + fail == total) finish();\n });\n putRequest.onerror = (() => {\n fail++;\n if (ok + fail == total) finish();\n });\n });\n transaction.onerror = onerror;\n });\n openRequest.onerror = onerror;\n },\n loadFilesFromDB: (paths, onload, onerror) => {\n onload = onload || (() => {});\n onerror = onerror || (() => {});\n var indexedDB = FS.indexedDB();\n try {\n var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION);\n } catch (e) {\n return onerror(e);\n }\n openRequest.onupgradeneeded = onerror;\n openRequest.onsuccess = (() => {\n var db = openRequest.result;\n try {\n var transaction = db.transaction([ FS.DB_STORE_NAME ], \"readonly\");\n } catch (e) {\n onerror(e);\n return;\n }\n var files = transaction.objectStore(FS.DB_STORE_NAME);\n var ok = 0, fail = 0, total = paths.length;\n function finish() {\n if (fail == 0) onload(); else onerror();\n }\n paths.forEach(path => {\n var getRequest = files.get(path);\n getRequest.onsuccess = (() => {\n if (FS.analyzePath(path).exists) {\n FS.unlink(path);\n }\n FS.createDataFile(PATH.dirname(path), PATH.basename(path), getRequest.result, true, true, true);\n ok++;\n if (ok + fail == total) finish();\n });\n getRequest.onerror = (() => {\n fail++;\n if (ok + fail == total) finish();\n });\n });\n transaction.onerror = onerror;\n });\n openRequest.onerror = onerror;\n },\n absolutePath: () => {\n abort(\"FS.absolutePath has been removed; use PATH_FS.resolve instead\");\n },\n createFolder: () => {\n abort(\"FS.createFolder has been removed; use FS.mkdir instead\");\n },\n createLink: () => {\n abort(\"FS.createLink has been removed; use FS.symlink instead\");\n },\n joinPath: () => {\n abort(\"FS.joinPath has been removed; use PATH.join instead\");\n },\n mmapAlloc: () => {\n abort(\"FS.mmapAlloc has been replaced by the top level function mmapAlloc\");\n },\n standardizePath: () => {\n abort(\"FS.standardizePath has been removed; use PATH.normalize instead\");\n }\n};\n\nvar SYSCALLS = {\n mappings: {},\n DEFAULT_POLLMASK: 5,\n calculateAt: function(dirfd, path, allowEmpty) {\n if (path[0] === \"/\") {\n return path;\n }\n var dir;\n if (dirfd === -100) {\n dir = FS.cwd();\n } else {\n var dirstream = FS.getStream(dirfd);\n if (!dirstream) throw new FS.ErrnoError(8);\n dir = dirstream.path;\n }\n if (path.length == 0) {\n if (!allowEmpty) {\n throw new FS.ErrnoError(44);\n }\n return dir;\n }\n return PATH.join2(dir, path);\n },\n doStat: function(func, path, buf) {\n try {\n var stat = func(path);\n } catch (e) {\n if (e && e.node && PATH.normalize(path) !== PATH.normalize(FS.getPath(e.node))) {\n return -54;\n }\n throw e;\n }\n _asan_js_store_4(buf >> 2, stat.dev);\n _asan_js_store_4(buf + 4 >> 2, 0);\n _asan_js_store_4(buf + 8 >> 2, stat.ino);\n _asan_js_store_4(buf + 12 >> 2, stat.mode);\n _asan_js_store_4(buf + 16 >> 2, stat.nlink);\n _asan_js_store_4(buf + 20 >> 2, stat.uid);\n _asan_js_store_4(buf + 24 >> 2, stat.gid);\n _asan_js_store_4(buf + 28 >> 2, stat.rdev);\n _asan_js_store_4(buf + 32 >> 2, 0);\n tempI64 = [ stat.size >>> 0, (tempDouble = stat.size, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ], \n _asan_js_store_4(buf + 40 >> 2, tempI64[0]), _asan_js_store_4(buf + 44 >> 2, tempI64[1]);\n _asan_js_store_4(buf + 48 >> 2, 4096);\n _asan_js_store_4(buf + 52 >> 2, stat.blocks);\n _asan_js_store_4(buf + 56 >> 2, stat.atime.getTime() / 1e3 | 0);\n _asan_js_store_4(buf + 60 >> 2, 0);\n _asan_js_store_4(buf + 64 >> 2, stat.mtime.getTime() / 1e3 | 0);\n _asan_js_store_4(buf + 68 >> 2, 0);\n _asan_js_store_4(buf + 72 >> 2, stat.ctime.getTime() / 1e3 | 0);\n _asan_js_store_4(buf + 76 >> 2, 0);\n tempI64 = [ stat.ino >>> 0, (tempDouble = stat.ino, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ], \n _asan_js_store_4(buf + 80 >> 2, tempI64[0]), _asan_js_store_4(buf + 84 >> 2, tempI64[1]);\n return 0;\n },\n doMsync: function(addr, stream, len, flags, offset) {\n var buffer = HEAPU8.slice(addr, addr + len);\n FS.msync(stream, buffer, offset, len, flags);\n },\n doMkdir: function(path, mode) {\n path = PATH.normalize(path);\n if (path[path.length - 1] === \"/\") path = path.substr(0, path.length - 1);\n FS.mkdir(path, mode, 0);\n return 0;\n },\n doMknod: function(path, mode, dev) {\n switch (mode & 61440) {\n case 32768:\n case 8192:\n case 24576:\n case 4096:\n case 49152:\n break;\n\n default:\n return -28;\n }\n FS.mknod(path, mode, dev);\n return 0;\n },\n doReadlink: function(path, buf, bufsize) {\n if (bufsize <= 0) return -28;\n var ret = FS.readlink(path);\n var len = Math.min(bufsize, lengthBytesUTF8(ret));\n var endChar = _asan_js_load_1(buf + len);\n stringToUTF8(ret, buf, bufsize + 1);\n _asan_js_store_1(buf + len, endChar);\n return len;\n },\n doAccess: function(path, amode) {\n if (amode & ~7) {\n return -28;\n }\n var lookup = FS.lookupPath(path, {\n follow: true\n });\n var node = lookup.node;\n if (!node) {\n return -44;\n }\n var perms = \"\";\n if (amode & 4) perms += \"r\";\n if (amode & 2) perms += \"w\";\n if (amode & 1) perms += \"x\";\n if (perms && FS.nodePermissions(node, perms)) {\n return -2;\n }\n return 0;\n },\n doDup: function(path, flags, suggestFD) {\n var suggest = FS.getStream(suggestFD);\n if (suggest) FS.close(suggest);\n return FS.open(path, flags, 0, suggestFD, suggestFD).fd;\n },\n doReadv: function(stream, iov, iovcnt, offset) {\n var ret = 0;\n for (var i = 0; i < iovcnt; i++) {\n var ptr = _asan_js_load_4(iov + i * 8 >> 2);\n var len = _asan_js_load_4(iov + (i * 8 + 4) >> 2);\n var curr = FS.read(stream, HEAP8, ptr, len, offset);\n if (curr < 0) return -1;\n ret += curr;\n if (curr < len) break;\n }\n return ret;\n },\n doWritev: function(stream, iov, iovcnt, offset) {\n var ret = 0;\n for (var i = 0; i < iovcnt; i++) {\n var ptr = _asan_js_load_4(iov + i * 8 >> 2);\n var len = _asan_js_load_4(iov + (i * 8 + 4) >> 2);\n var curr = FS.write(stream, HEAP8, ptr, len, offset);\n if (curr < 0) return -1;\n ret += curr;\n }\n return ret;\n },\n varargs: undefined,\n get: function() {\n assert(SYSCALLS.varargs != undefined);\n SYSCALLS.varargs += 4;\n var ret = _asan_js_load_4(SYSCALLS.varargs - 4 >> 2);\n return ret;\n },\n getStr: function(ptr) {\n var ret = UTF8ToString(ptr);\n return ret;\n },\n getStreamFromFD: function(fd) {\n var stream = FS.getStream(fd);\n if (!stream) throw new FS.ErrnoError(8);\n return stream;\n },\n get64: function(low, high) {\n if (low >= 0) assert(high === 0); else assert(high === -1);\n return low;\n }\n};\n\nfunction ___syscall_dup(fd) {\n try {\n var old = SYSCALLS.getStreamFromFD(fd);\n return FS.open(old.path, old.flags, 0).fd;\n } catch (e) {\n if (typeof FS === \"undefined\" || !(e instanceof FS.ErrnoError)) throw e;\n return -e.errno;\n }\n}\n\nfunction ___syscall_open(path, flags, varargs) {\n SYSCALLS.varargs = varargs;\n try {\n var pathname = SYSCALLS.getStr(path);\n var mode = varargs ? SYSCALLS.get() : 0;\n var stream = FS.open(pathname, flags, mode);\n return stream.fd;\n } catch (e) {\n if (typeof FS === \"undefined\" || !(e instanceof FS.ErrnoError)) throw e;\n return -e.errno;\n }\n}\n\nfunction ___syscall_stat64(path, buf) {\n try {\n path = SYSCALLS.getStr(path);\n return SYSCALLS.doStat(FS.stat, path, buf);\n } catch (e) {\n if (typeof FS === \"undefined\" || !(e instanceof FS.ErrnoError)) throw e;\n return -e.errno;\n }\n}\n\nfunction __embind_register_bigint(primitiveType, name, size, minRange, maxRange) {}\n\nfunction getShiftFromSize(size) {\n switch (size) {\n case 1:\n return 0;\n\n case 2:\n return 1;\n\n case 4:\n return 2;\n\n case 8:\n return 3;\n\n default:\n throw new TypeError(\"Unknown type size: \" + size);\n }\n}\n\nfunction embind_init_charCodes() {\n var codes = new Array(256);\n for (var i = 0; i < 256; ++i) {\n codes[i] = String.fromCharCode(i);\n }\n embind_charCodes = codes;\n}\n\nvar embind_charCodes = undefined;\n\nfunction readLatin1String(ptr) {\n var ret = \"\";\n var c = ptr;\n while (_asan_js_load_1u(c)) {\n ret += embind_charCodes[_asan_js_load_1u(c++)];\n }\n return ret;\n}\n\nvar awaitingDependencies = {};\n\nvar registeredTypes = {};\n\nvar typeDependencies = {};\n\nvar char_0 = 48;\n\nvar char_9 = 57;\n\nfunction makeLegalFunctionName(name) {\n if (undefined === name) {\n return \"_unknown\";\n }\n name = name.replace(/[^a-zA-Z0-9_]/g, \"$\");\n var f = name.charCodeAt(0);\n if (f >= char_0 && f <= char_9) {\n return \"_\" + name;\n } else {\n return name;\n }\n}\n\nfunction createNamedFunction(name, body) {\n name = makeLegalFunctionName(name);\n return new Function(\"body\", \"return function \" + name + \"() {\\n\" + ' \"use strict\";' + \" return body.apply(this, arguments);\\n\" + \"};\\n\")(body);\n}\n\nfunction extendError(baseErrorType, errorName) {\n var errorClass = createNamedFunction(errorName, function(message) {\n this.name = errorName;\n this.message = message;\n var stack = new Error(message).stack;\n if (stack !== undefined) {\n this.stack = this.toString() + \"\\n\" + stack.replace(/^Error(:[^\\n]*)?\\n/, \"\");\n }\n });\n errorClass.prototype = Object.create(baseErrorType.prototype);\n errorClass.prototype.constructor = errorClass;\n errorClass.prototype.toString = function() {\n if (this.message === undefined) {\n return this.name;\n } else {\n return this.name + \": \" + this.message;\n }\n };\n return errorClass;\n}\n\nvar BindingError = undefined;\n\nfunction throwBindingError(message) {\n throw new BindingError(message);\n}\n\nvar InternalError = undefined;\n\nfunction throwInternalError(message) {\n throw new InternalError(message);\n}\n\nfunction whenDependentTypesAreResolved(myTypes, dependentTypes, getTypeConverters) {\n myTypes.forEach(function(type) {\n typeDependencies[type] = dependentTypes;\n });\n function onComplete(typeConverters) {\n var myTypeConverters = getTypeConverters(typeConverters);\n if (myTypeConverters.length !== myTypes.length) {\n throwInternalError(\"Mismatched type converter count\");\n }\n for (var i = 0; i < myTypes.length; ++i) {\n registerType(myTypes[i], myTypeConverters[i]);\n }\n }\n var typeConverters = new Array(dependentTypes.length);\n var unregisteredTypes = [];\n var registered = 0;\n dependentTypes.forEach(function(dt, i) {\n if (registeredTypes.hasOwnProperty(dt)) {\n typeConverters[i] = registeredTypes[dt];\n } else {\n unregisteredTypes.push(dt);\n if (!awaitingDependencies.hasOwnProperty(dt)) {\n awaitingDependencies[dt] = [];\n }\n awaitingDependencies[dt].push(function() {\n typeConverters[i] = registeredTypes[dt];\n ++registered;\n if (registered === unregisteredTypes.length) {\n onComplete(typeConverters);\n }\n });\n }\n });\n if (0 === unregisteredTypes.length) {\n onComplete(typeConverters);\n }\n}\n\nfunction registerType(rawType, registeredInstance, options = {}) {\n if (!(\"argPackAdvance\" in registeredInstance)) {\n throw new TypeError(\"registerType registeredInstance requires argPackAdvance\");\n }\n var name = registeredInstance.name;\n if (!rawType) {\n throwBindingError('type \"' + name + '\" must have a positive integer typeid pointer');\n }\n if (registeredTypes.hasOwnProperty(rawType)) {\n if (options.ignoreDuplicateRegistrations) {\n return;\n } else {\n throwBindingError(\"Cannot register type '\" + name + \"' twice\");\n }\n }\n registeredTypes[rawType] = registeredInstance;\n delete typeDependencies[rawType];\n if (awaitingDependencies.hasOwnProperty(rawType)) {\n var callbacks = awaitingDependencies[rawType];\n delete awaitingDependencies[rawType];\n callbacks.forEach(function(cb) {\n cb();\n });\n }\n}\n\nfunction __embind_register_bool(rawType, name, size, trueValue, falseValue) {\n var shift = getShiftFromSize(size);\n name = readLatin1String(name);\n registerType(rawType, {\n name: name,\n \"fromWireType\": function(wt) {\n return !!wt;\n },\n \"toWireType\": function(destructors, o) {\n return o ? trueValue : falseValue;\n },\n \"argPackAdvance\": 8,\n \"readValueFromPointer\": function(pointer) {\n var heap;\n if (size === 1) {\n heap = HEAP8;\n } else if (size === 2) {\n heap = HEAP16;\n } else if (size === 4) {\n heap = HEAP32;\n } else {\n throw new TypeError(\"Unknown boolean type size: \" + name);\n }\n return this[\"fromWireType\"](heap[pointer >> shift]);\n },\n destructorFunction: null\n });\n}\n\nfunction ClassHandle_isAliasOf(other) {\n if (!(this instanceof ClassHandle)) {\n return false;\n }\n if (!(other instanceof ClassHandle)) {\n return false;\n }\n var leftClass = this.$$.ptrType.registeredClass;\n var left = this.$$.ptr;\n var rightClass = other.$$.ptrType.registeredClass;\n var right = other.$$.ptr;\n while (leftClass.baseClass) {\n left = leftClass.upcast(left);\n leftClass = leftClass.baseClass;\n }\n while (rightClass.baseClass) {\n right = rightClass.upcast(right);\n rightClass = rightClass.baseClass;\n }\n return leftClass === rightClass && left === right;\n}\n\nfunction shallowCopyInternalPointer(o) {\n return {\n count: o.count,\n deleteScheduled: o.deleteScheduled,\n preservePointerOnDelete: o.preservePointerOnDelete,\n ptr: o.ptr,\n ptrType: o.ptrType,\n smartPtr: o.smartPtr,\n smartPtrType: o.smartPtrType\n };\n}\n\nfunction throwInstanceAlreadyDeleted(obj) {\n function getInstanceTypeName(handle) {\n return handle.$$.ptrType.registeredClass.name;\n }\n throwBindingError(getInstanceTypeName(obj) + \" instance already deleted\");\n}\n\nvar finalizationRegistry = false;\n\nfunction detachFinalizer(handle) {}\n\nfunction runDestructor($$) {\n if ($$.smartPtr) {\n $$.smartPtrType.rawDestructor($$.smartPtr);\n } else {\n $$.ptrType.registeredClass.rawDestructor($$.ptr);\n }\n}\n\nfunction releaseClassHandle($$) {\n $$.count.value -= 1;\n var toDelete = 0 === $$.count.value;\n if (toDelete) {\n runDestructor($$);\n }\n}\n\nfunction downcastPointer(ptr, ptrClass, desiredClass) {\n if (ptrClass === desiredClass) {\n return ptr;\n }\n if (undefined === desiredClass.baseClass) {\n return null;\n }\n var rv = downcastPointer(ptr, ptrClass, desiredClass.baseClass);\n if (rv === null) {\n return null;\n }\n return desiredClass.downcast(rv);\n}\n\nvar registeredPointers = {};\n\nfunction getInheritedInstanceCount() {\n return Object.keys(registeredInstances).length;\n}\n\nfunction getLiveInheritedInstances() {\n var rv = [];\n for (var k in registeredInstances) {\n if (registeredInstances.hasOwnProperty(k)) {\n rv.push(registeredInstances[k]);\n }\n }\n return rv;\n}\n\nvar deletionQueue = [];\n\nfunction flushPendingDeletes() {\n while (deletionQueue.length) {\n var obj = deletionQueue.pop();\n obj.$$.deleteScheduled = false;\n obj[\"delete\"]();\n }\n}\n\nvar delayFunction = undefined;\n\nfunction setDelayFunction(fn) {\n delayFunction = fn;\n if (deletionQueue.length && delayFunction) {\n delayFunction(flushPendingDeletes);\n }\n}\n\nfunction init_embind() {\n Module[\"getInheritedInstanceCount\"] = getInheritedInstanceCount;\n Module[\"getLiveInheritedInstances\"] = getLiveInheritedInstances;\n Module[\"flushPendingDeletes\"] = flushPendingDeletes;\n Module[\"setDelayFunction\"] = setDelayFunction;\n}\n\nvar registeredInstances = {};\n\nfunction getBasestPointer(class_, ptr) {\n if (ptr === undefined) {\n throwBindingError(\"ptr should not be undefined\");\n }\n while (class_.baseClass) {\n ptr = class_.upcast(ptr);\n class_ = class_.baseClass;\n }\n return ptr;\n}\n\nfunction getInheritedInstance(class_, ptr) {\n ptr = getBasestPointer(class_, ptr);\n return registeredInstances[ptr];\n}\n\nfunction makeClassHandle(prototype, record) {\n if (!record.ptrType || !record.ptr) {\n throwInternalError(\"makeClassHandle requires ptr and ptrType\");\n }\n var hasSmartPtrType = !!record.smartPtrType;\n var hasSmartPtr = !!record.smartPtr;\n if (hasSmartPtrType !== hasSmartPtr) {\n throwInternalError(\"Both smartPtrType and smartPtr must be specified\");\n }\n record.count = {\n value: 1\n };\n return attachFinalizer(Object.create(prototype, {\n $$: {\n value: record\n }\n }));\n}\n\nfunction RegisteredPointer_fromWireType(ptr) {\n var rawPointer = this.getPointee(ptr);\n if (!rawPointer) {\n this.destructor(ptr);\n return null;\n }\n var registeredInstance = getInheritedInstance(this.registeredClass, rawPointer);\n if (undefined !== registeredInstance) {\n if (0 === registeredInstance.$$.count.value) {\n registeredInstance.$$.ptr = rawPointer;\n registeredInstance.$$.smartPtr = ptr;\n return registeredInstance[\"clone\"]();\n } else {\n var rv = registeredInstance[\"clone\"]();\n this.destructor(ptr);\n return rv;\n }\n }\n function makeDefaultHandle() {\n if (this.isSmartPointer) {\n return makeClassHandle(this.registeredClass.instancePrototype, {\n ptrType: this.pointeeType,\n ptr: rawPointer,\n smartPtrType: this,\n smartPtr: ptr\n });\n } else {\n return makeClassHandle(this.registeredClass.instancePrototype, {\n ptrType: this,\n ptr: ptr\n });\n }\n }\n var actualType = this.registeredClass.getActualType(rawPointer);\n var registeredPointerRecord = registeredPointers[actualType];\n if (!registeredPointerRecord) {\n return makeDefaultHandle.call(this);\n }\n var toType;\n if (this.isConst) {\n toType = registeredPointerRecord.constPointerType;\n } else {\n toType = registeredPointerRecord.pointerType;\n }\n var dp = downcastPointer(rawPointer, this.registeredClass, toType.registeredClass);\n if (dp === null) {\n return makeDefaultHandle.call(this);\n }\n if (this.isSmartPointer) {\n return makeClassHandle(toType.registeredClass.instancePrototype, {\n ptrType: toType,\n ptr: dp,\n smartPtrType: this,\n smartPtr: ptr\n });\n } else {\n return makeClassHandle(toType.registeredClass.instancePrototype, {\n ptrType: toType,\n ptr: dp\n });\n }\n}\n\nfunction attachFinalizer(handle) {\n if (\"undefined\" === typeof FinalizationRegistry) {\n attachFinalizer = (handle => handle);\n return handle;\n }\n finalizationRegistry = new FinalizationRegistry(info => {\n console.warn(info.leakWarning.stack.replace(/^Error: /, \"\"));\n releaseClassHandle(info.$$);\n });\n attachFinalizer = (handle => {\n var $$ = handle.$$;\n var hasSmartPtr = !!$$.smartPtr;\n if (hasSmartPtr) {\n var info = {\n $$: $$\n };\n var cls = $$.ptrType.registeredClass;\n info.leakWarning = new Error(\"Embind found a leaked C++ instance \" + cls.name + \" <0x\" + $$.ptr.toString(16) + \">.\\n\" + \"We'll free it automatically in this case, but this functionality is not reliable across various environments.\\n\" + \"Make sure to invoke .delete() manually once you're done with the instance instead.\\n\" + \"Originally allocated\");\n if (\"captureStackTrace\" in Error) {\n Error.captureStackTrace(info.leakWarning, RegisteredPointer_fromWireType);\n }\n finalizationRegistry.register(handle, info, handle);\n }\n return handle;\n });\n detachFinalizer = (handle => finalizationRegistry.unregister(handle));\n return attachFinalizer(handle);\n}\n\nfunction ClassHandle_clone() {\n if (!this.$$.ptr) {\n throwInstanceAlreadyDeleted(this);\n }\n if (this.$$.preservePointerOnDelete) {\n this.$$.count.value += 1;\n return this;\n } else {\n var clone = attachFinalizer(Object.create(Object.getPrototypeOf(this), {\n $$: {\n value: shallowCopyInternalPointer(this.$$)\n }\n }));\n clone.$$.count.value += 1;\n clone.$$.deleteScheduled = false;\n return clone;\n }\n}\n\nfunction ClassHandle_delete() {\n if (!this.$$.ptr) {\n throwInstanceAlreadyDeleted(this);\n }\n if (this.$$.deleteScheduled && !this.$$.preservePointerOnDelete) {\n throwBindingError(\"Object already scheduled for deletion\");\n }\n detachFinalizer(this);\n releaseClassHandle(this.$$);\n if (!this.$$.preservePointerOnDelete) {\n this.$$.smartPtr = undefined;\n this.$$.ptr = undefined;\n }\n}\n\nfunction ClassHandle_isDeleted() {\n return !this.$$.ptr;\n}\n\nfunction ClassHandle_deleteLater() {\n if (!this.$$.ptr) {\n throwInstanceAlreadyDeleted(this);\n }\n if (this.$$.deleteScheduled && !this.$$.preservePointerOnDelete) {\n throwBindingError(\"Object already scheduled for deletion\");\n }\n deletionQueue.push(this);\n if (deletionQueue.length === 1 && delayFunction) {\n delayFunction(flushPendingDeletes);\n }\n this.$$.deleteScheduled = true;\n return this;\n}\n\nfunction init_ClassHandle() {\n ClassHandle.prototype[\"isAliasOf\"] = ClassHandle_isAliasOf;\n ClassHandle.prototype[\"clone\"] = ClassHandle_clone;\n ClassHandle.prototype[\"delete\"] = ClassHandle_delete;\n ClassHandle.prototype[\"isDeleted\"] = ClassHandle_isDeleted;\n ClassHandle.prototype[\"deleteLater\"] = ClassHandle_deleteLater;\n}\n\nfunction ClassHandle() {}\n\nfunction ensureOverloadTable(proto, methodName, humanName) {\n if (undefined === proto[methodName].overloadTable) {\n var prevFunc = proto[methodName];\n proto[methodName] = function() {\n if (!proto[methodName].overloadTable.hasOwnProperty(arguments.length)) {\n throwBindingError(\"Function '\" + humanName + \"' called with an invalid number of arguments (\" + arguments.length + \") - expects one of (\" + proto[methodName].overloadTable + \")!\");\n }\n return proto[methodName].overloadTable[arguments.length].apply(this, arguments);\n };\n proto[methodName].overloadTable = [];\n proto[methodName].overloadTable[prevFunc.argCount] = prevFunc;\n }\n}\n\nfunction exposePublicSymbol(name, value, numArguments) {\n if (Module.hasOwnProperty(name)) {\n if (undefined === numArguments || undefined !== Module[name].overloadTable && undefined !== Module[name].overloadTable[numArguments]) {\n throwBindingError(\"Cannot register public name '\" + name + \"' twice\");\n }\n ensureOverloadTable(Module, name, name);\n if (Module.hasOwnProperty(numArguments)) {\n throwBindingError(\"Cannot register multiple overloads of a function with the same number of arguments (\" + numArguments + \")!\");\n }\n Module[name].overloadTable[numArguments] = value;\n } else {\n Module[name] = value;\n if (undefined !== numArguments) {\n Module[name].numArguments = numArguments;\n }\n }\n}\n\nfunction RegisteredClass(name, constructor, instancePrototype, rawDestructor, baseClass, getActualType, upcast, downcast) {\n this.name = name;\n this.constructor = constructor;\n this.instancePrototype = instancePrototype;\n this.rawDestructor = rawDestructor;\n this.baseClass = baseClass;\n this.getActualType = getActualType;\n this.upcast = upcast;\n this.downcast = downcast;\n this.pureVirtualFunctions = [];\n}\n\nfunction upcastPointer(ptr, ptrClass, desiredClass) {\n while (ptrClass !== desiredClass) {\n if (!ptrClass.upcast) {\n throwBindingError(\"Expected null or instance of \" + desiredClass.name + \", got an instance of \" + ptrClass.name);\n }\n ptr = ptrClass.upcast(ptr);\n ptrClass = ptrClass.baseClass;\n }\n return ptr;\n}\n\nfunction constNoSmartPtrRawPointerToWireType(destructors, handle) {\n if (handle === null) {\n if (this.isReference) {\n throwBindingError(\"null is not a valid \" + this.name);\n }\n return 0;\n }\n if (!handle.$$) {\n throwBindingError('Cannot pass \"' + _embind_repr(handle) + '\" as a ' + this.name);\n }\n if (!handle.$$.ptr) {\n throwBindingError(\"Cannot pass deleted object as a pointer of type \" + this.name);\n }\n var handleClass = handle.$$.ptrType.registeredClass;\n var ptr = upcastPointer(handle.$$.ptr, handleClass, this.registeredClass);\n return ptr;\n}\n\nfunction genericPointerToWireType(destructors, handle) {\n var ptr;\n if (handle === null) {\n if (this.isReference) {\n throwBindingError(\"null is not a valid \" + this.name);\n }\n if (this.isSmartPointer) {\n ptr = this.rawConstructor();\n if (destructors !== null) {\n destructors.push(this.rawDestructor, ptr);\n }\n return ptr;\n } else {\n return 0;\n }\n }\n if (!handle.$$) {\n throwBindingError('Cannot pass \"' + _embind_repr(handle) + '\" as a ' + this.name);\n }\n if (!handle.$$.ptr) {\n throwBindingError(\"Cannot pass deleted object as a pointer of type \" + this.name);\n }\n if (!this.isConst && handle.$$.ptrType.isConst) {\n throwBindingError(\"Cannot convert argument of type \" + (handle.$$.smartPtrType ? handle.$$.smartPtrType.name : handle.$$.ptrType.name) + \" to parameter type \" + this.name);\n }\n var handleClass = handle.$$.ptrType.registeredClass;\n ptr = upcastPointer(handle.$$.ptr, handleClass, this.registeredClass);\n if (this.isSmartPointer) {\n if (undefined === handle.$$.smartPtr) {\n throwBindingError(\"Passing raw pointer to smart pointer is illegal\");\n }\n switch (this.sharingPolicy) {\n case 0:\n if (handle.$$.smartPtrType === this) {\n ptr = handle.$$.smartPtr;\n } else {\n throwBindingError(\"Cannot convert argument of type \" + (handle.$$.smartPtrType ? handle.$$.smartPtrType.name : handle.$$.ptrType.name) + \" to parameter type \" + this.name);\n }\n break;\n\n case 1:\n ptr = handle.$$.smartPtr;\n break;\n\n case 2:\n if (handle.$$.smartPtrType === this) {\n ptr = handle.$$.smartPtr;\n } else {\n var clonedHandle = handle[\"clone\"]();\n ptr = this.rawShare(ptr, Emval.toHandle(function() {\n clonedHandle[\"delete\"]();\n }));\n if (destructors !== null) {\n destructors.push(this.rawDestructor, ptr);\n }\n }\n break;\n\n default:\n throwBindingError(\"Unsupporting sharing policy\");\n }\n }\n return ptr;\n}\n\nfunction nonConstNoSmartPtrRawPointerToWireType(destructors, handle) {\n if (handle === null) {\n if (this.isReference) {\n throwBindingError(\"null is not a valid \" + this.name);\n }\n return 0;\n }\n if (!handle.$$) {\n throwBindingError('Cannot pass \"' + _embind_repr(handle) + '\" as a ' + this.name);\n }\n if (!handle.$$.ptr) {\n throwBindingError(\"Cannot pass deleted object as a pointer of type \" + this.name);\n }\n if (handle.$$.ptrType.isConst) {\n throwBindingError(\"Cannot convert argument of type \" + handle.$$.ptrType.name + \" to parameter type \" + this.name);\n }\n var handleClass = handle.$$.ptrType.registeredClass;\n var ptr = upcastPointer(handle.$$.ptr, handleClass, this.registeredClass);\n return ptr;\n}\n\nfunction simpleReadValueFromPointer(pointer) {\n return this[\"fromWireType\"](_asan_js_load_4u(pointer >> 2));\n}\n\nfunction RegisteredPointer_getPointee(ptr) {\n if (this.rawGetPointee) {\n ptr = this.rawGetPointee(ptr);\n }\n return ptr;\n}\n\nfunction RegisteredPointer_destructor(ptr) {\n if (this.rawDestructor) {\n this.rawDestructor(ptr);\n }\n}\n\nfunction RegisteredPointer_deleteObject(handle) {\n if (handle !== null) {\n handle[\"delete\"]();\n }\n}\n\nfunction init_RegisteredPointer() {\n RegisteredPointer.prototype.getPointee = RegisteredPointer_getPointee;\n RegisteredPointer.prototype.destructor = RegisteredPointer_destructor;\n RegisteredPointer.prototype[\"argPackAdvance\"] = 8;\n RegisteredPointer.prototype[\"readValueFromPointer\"] = simpleReadValueFromPointer;\n RegisteredPointer.prototype[\"deleteObject\"] = RegisteredPointer_deleteObject;\n RegisteredPointer.prototype[\"fromWireType\"] = RegisteredPointer_fromWireType;\n}\n\nfunction RegisteredPointer(name, registeredClass, isReference, isConst, isSmartPointer, pointeeType, sharingPolicy, rawGetPointee, rawConstructor, rawShare, rawDestructor) {\n this.name = name;\n this.registeredClass = registeredClass;\n this.isReference = isReference;\n this.isConst = isConst;\n this.isSmartPointer = isSmartPointer;\n this.pointeeType = pointeeType;\n this.sharingPolicy = sharingPolicy;\n this.rawGetPointee = rawGetPointee;\n this.rawConstructor = rawConstructor;\n this.rawShare = rawShare;\n this.rawDestructor = rawDestructor;\n if (!isSmartPointer && registeredClass.baseClass === undefined) {\n if (isConst) {\n this[\"toWireType\"] = constNoSmartPtrRawPointerToWireType;\n this.destructorFunction = null;\n } else {\n this[\"toWireType\"] = nonConstNoSmartPtrRawPointerToWireType;\n this.destructorFunction = null;\n }\n } else {\n this[\"toWireType\"] = genericPointerToWireType;\n }\n}\n\nfunction replacePublicSymbol(name, value, numArguments) {\n if (!Module.hasOwnProperty(name)) {\n throwInternalError(\"Replacing nonexistant public symbol\");\n }\n if (undefined !== Module[name].overloadTable && undefined !== numArguments) {\n Module[name].overloadTable[numArguments] = value;\n } else {\n Module[name] = value;\n Module[name].argCount = numArguments;\n }\n}\n\nfunction dynCallLegacy(sig, ptr, args) {\n assert(\"dynCall_\" + sig in Module, \"bad function pointer type - no table for sig '\" + sig + \"'\");\n if (args && args.length) {\n assert(args.length === sig.substring(1).replace(/j/g, \"--\").length);\n } else {\n assert(sig.length == 1);\n }\n var f = Module[\"dynCall_\" + sig];\n return args && args.length ? f.apply(null, [ ptr ].concat(args)) : f.call(null, ptr);\n}\n\nfunction dynCall(sig, ptr, args) {\n if (sig.includes(\"j\")) {\n return dynCallLegacy(sig, ptr, args);\n }\n assert(getWasmTableEntry(ptr), \"missing table entry in dynCall: \" + ptr);\n return getWasmTableEntry(ptr).apply(null, args);\n}\n\nfunction getDynCaller(sig, ptr) {\n assert(sig.includes(\"j\"), \"getDynCaller should only be called with i64 sigs\");\n var argCache = [];\n return function() {\n argCache.length = 0;\n Object.assign(argCache, arguments);\n return dynCall(sig, ptr, argCache);\n };\n}\n\nfunction embind__requireFunction(signature, rawFunction) {\n signature = readLatin1String(signature);\n function makeDynCaller() {\n if (signature.includes(\"j\")) {\n return getDynCaller(signature, rawFunction);\n }\n return getWasmTableEntry(rawFunction);\n }\n var fp = makeDynCaller();\n if (typeof fp !== \"function\") {\n throwBindingError(\"unknown function pointer with signature \" + signature + \": \" + rawFunction);\n }\n return fp;\n}\n\nvar UnboundTypeError = undefined;\n\nfunction getTypeName(type) {\n var ptr = ___getTypeName(type);\n var rv = readLatin1String(ptr);\n _free(ptr);\n return rv;\n}\n\nfunction throwUnboundTypeError(message, types) {\n var unboundTypes = [];\n var seen = {};\n function visit(type) {\n if (seen[type]) {\n return;\n }\n if (registeredTypes[type]) {\n return;\n }\n if (typeDependencies[type]) {\n typeDependencies[type].forEach(visit);\n return;\n }\n unboundTypes.push(type);\n seen[type] = true;\n }\n types.forEach(visit);\n throw new UnboundTypeError(message + \": \" + unboundTypes.map(getTypeName).join([ \", \" ]));\n}\n\nfunction __embind_register_class(rawType, rawPointerType, rawConstPointerType, baseClassRawType, getActualTypeSignature, getActualType, upcastSignature, upcast, downcastSignature, downcast, name, destructorSignature, rawDestructor) {\n name = readLatin1String(name);\n getActualType = embind__requireFunction(getActualTypeSignature, getActualType);\n if (upcast) {\n upcast = embind__requireFunction(upcastSignature, upcast);\n }\n if (downcast) {\n downcast = embind__requireFunction(downcastSignature, downcast);\n }\n rawDestructor = embind__requireFunction(destructorSignature, rawDestructor);\n var legalFunctionName = makeLegalFunctionName(name);\n exposePublicSymbol(legalFunctionName, function() {\n throwUnboundTypeError(\"Cannot construct \" + name + \" due to unbound types\", [ baseClassRawType ]);\n });\n whenDependentTypesAreResolved([ rawType, rawPointerType, rawConstPointerType ], baseClassRawType ? [ baseClassRawType ] : [], function(base) {\n base = base[0];\n var baseClass;\n var basePrototype;\n if (baseClassRawType) {\n baseClass = base.registeredClass;\n basePrototype = baseClass.instancePrototype;\n } else {\n basePrototype = ClassHandle.prototype;\n }\n var constructor = createNamedFunction(legalFunctionName, function() {\n if (Object.getPrototypeOf(this) !== instancePrototype) {\n throw new BindingError(\"Use 'new' to construct \" + name);\n }\n if (undefined === registeredClass.constructor_body) {\n throw new BindingError(name + \" has no accessible constructor\");\n }\n var body = registeredClass.constructor_body[arguments.length];\n if (undefined === body) {\n throw new BindingError(\"Tried to invoke ctor of \" + name + \" with invalid number of parameters (\" + arguments.length + \") - expected (\" + Object.keys(registeredClass.constructor_body).toString() + \") parameters instead!\");\n }\n return body.apply(this, arguments);\n });\n var instancePrototype = Object.create(basePrototype, {\n constructor: {\n value: constructor\n }\n });\n constructor.prototype = instancePrototype;\n var registeredClass = new RegisteredClass(name, constructor, instancePrototype, rawDestructor, baseClass, getActualType, upcast, downcast);\n var referenceConverter = new RegisteredPointer(name, registeredClass, true, false, false);\n var pointerConverter = new RegisteredPointer(name + \"*\", registeredClass, false, false, false);\n var constPointerConverter = new RegisteredPointer(name + \" const*\", registeredClass, false, true, false);\n registeredPointers[rawType] = {\n pointerType: pointerConverter,\n constPointerType: constPointerConverter\n };\n replacePublicSymbol(legalFunctionName, constructor);\n return [ referenceConverter, pointerConverter, constPointerConverter ];\n });\n}\n\nfunction heap32VectorToArray(count, firstElement) {\n var array = [];\n for (var i = 0; i < count; i++) {\n array.push(_asan_js_load_4((firstElement >> 2) + i));\n }\n return array;\n}\n\nfunction runDestructors(destructors) {\n while (destructors.length) {\n var ptr = destructors.pop();\n var del = destructors.pop();\n del(ptr);\n }\n}\n\nfunction __embind_register_class_constructor(rawClassType, argCount, rawArgTypesAddr, invokerSignature, invoker, rawConstructor) {\n assert(argCount > 0);\n var rawArgTypes = heap32VectorToArray(argCount, rawArgTypesAddr);\n invoker = embind__requireFunction(invokerSignature, invoker);\n whenDependentTypesAreResolved([], [ rawClassType ], function(classType) {\n classType = classType[0];\n var humanName = \"constructor \" + classType.name;\n if (undefined === classType.registeredClass.constructor_body) {\n classType.registeredClass.constructor_body = [];\n }\n if (undefined !== classType.registeredClass.constructor_body[argCount - 1]) {\n 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!\");\n }\n classType.registeredClass.constructor_body[argCount - 1] = (() => {\n throwUnboundTypeError(\"Cannot construct \" + classType.name + \" due to unbound types\", rawArgTypes);\n });\n whenDependentTypesAreResolved([], rawArgTypes, function(argTypes) {\n argTypes.splice(1, 0, null);\n classType.registeredClass.constructor_body[argCount - 1] = craftInvokerFunction(humanName, argTypes, null, invoker, rawConstructor);\n return [];\n });\n return [];\n });\n}\n\nfunction new_(constructor, argumentList) {\n if (!(constructor instanceof Function)) {\n throw new TypeError(\"new_ called with constructor type \" + typeof constructor + \" which is not a function\");\n }\n var dummy = createNamedFunction(constructor.name || \"unknownFunctionName\", function() {});\n dummy.prototype = constructor.prototype;\n var obj = new dummy();\n var r = constructor.apply(obj, argumentList);\n return r instanceof Object ? r : obj;\n}\n\nfunction craftInvokerFunction(humanName, argTypes, classType, cppInvokerFunc, cppTargetFunc) {\n var argCount = argTypes.length;\n if (argCount < 2) {\n throwBindingError(\"argTypes array size mismatch! Must at least get return value and 'this' types!\");\n }\n var isClassMethodFunc = argTypes[1] !== null && classType !== null;\n var needsDestructorStack = false;\n for (var i = 1; i < argTypes.length; ++i) {\n if (argTypes[i] !== null && argTypes[i].destructorFunction === undefined) {\n needsDestructorStack = true;\n break;\n }\n }\n var returns = argTypes[0].name !== \"void\";\n var argsList = \"\";\n var argsListWired = \"\";\n for (var i = 0; i < argCount - 2; ++i) {\n argsList += (i !== 0 ? \", \" : \"\") + \"arg\" + i;\n argsListWired += (i !== 0 ? \", \" : \"\") + \"arg\" + i + \"Wired\";\n }\n var invokerFnBody = \"return function \" + makeLegalFunctionName(humanName) + \"(\" + argsList + \") {\\n\" + \"if (arguments.length !== \" + (argCount - 2) + \") {\\n\" + \"throwBindingError('function \" + humanName + \" called with ' + arguments.length + ' arguments, expected \" + (argCount - 2) + \" args!');\\n\" + \"}\\n\";\n if (needsDestructorStack) {\n invokerFnBody += \"var destructors = [];\\n\";\n }\n var dtorStack = needsDestructorStack ? \"destructors\" : \"null\";\n var args1 = [ \"throwBindingError\", \"invoker\", \"fn\", \"runDestructors\", \"retType\", \"classParam\" ];\n var args2 = [ throwBindingError, cppInvokerFunc, cppTargetFunc, runDestructors, argTypes[0], argTypes[1] ];\n if (isClassMethodFunc) {\n invokerFnBody += \"var thisWired = classParam.toWireType(\" + dtorStack + \", this);\\n\";\n }\n for (var i = 0; i < argCount - 2; ++i) {\n invokerFnBody += \"var arg\" + i + \"Wired = argType\" + i + \".toWireType(\" + dtorStack + \", arg\" + i + \"); // \" + argTypes[i + 2].name + \"\\n\";\n args1.push(\"argType\" + i);\n args2.push(argTypes[i + 2]);\n }\n if (isClassMethodFunc) {\n argsListWired = \"thisWired\" + (argsListWired.length > 0 ? \", \" : \"\") + argsListWired;\n }\n invokerFnBody += (returns ? \"var rv = \" : \"\") + \"invoker(fn\" + (argsListWired.length > 0 ? \", \" : \"\") + argsListWired + \");\\n\";\n if (needsDestructorStack) {\n invokerFnBody += \"runDestructors(destructors);\\n\";\n } else {\n for (var i = isClassMethodFunc ? 1 : 2; i < argTypes.length; ++i) {\n var paramName = i === 1 ? \"thisWired\" : \"arg\" + (i - 2) + \"Wired\";\n if (argTypes[i].destructorFunction !== null) {\n invokerFnBody += paramName + \"_dtor(\" + paramName + \"); // \" + argTypes[i].name + \"\\n\";\n args1.push(paramName + \"_dtor\");\n args2.push(argTypes[i].destructorFunction);\n }\n }\n }\n if (returns) {\n invokerFnBody += \"var ret = retType.fromWireType(rv);\\n\" + \"return ret;\\n\";\n } else {}\n invokerFnBody += \"}\\n\";\n args1.push(invokerFnBody);\n var invokerFunction = new_(Function, args1).apply(null, args2);\n return invokerFunction;\n}\n\nfunction __embind_register_class_function(rawClassType, methodName, argCount, rawArgTypesAddr, invokerSignature, rawInvoker, context, isPureVirtual) {\n var rawArgTypes = heap32VectorToArray(argCount, rawArgTypesAddr);\n methodName = readLatin1String(methodName);\n rawInvoker = embind__requireFunction(invokerSignature, rawInvoker);\n whenDependentTypesAreResolved([], [ rawClassType ], function(classType) {\n classType = classType[0];\n var humanName = classType.name + \".\" + methodName;\n if (methodName.startsWith(\"@@\")) {\n methodName = Symbol[methodName.substring(2)];\n }\n if (isPureVirtual) {\n classType.registeredClass.pureVirtualFunctions.push(methodName);\n }\n function unboundTypesHandler() {\n throwUnboundTypeError(\"Cannot call \" + humanName + \" due to unbound types\", rawArgTypes);\n }\n var proto = classType.registeredClass.instancePrototype;\n var method = proto[methodName];\n if (undefined === method || undefined === method.overloadTable && method.className !== classType.name && method.argCount === argCount - 2) {\n unboundTypesHandler.argCount = argCount - 2;\n unboundTypesHandler.className = classType.name;\n proto[methodName] = unboundTypesHandler;\n } else {\n ensureOverloadTable(proto, methodName, humanName);\n proto[methodName].overloadTable[argCount - 2] = unboundTypesHandler;\n }\n whenDependentTypesAreResolved([], rawArgTypes, function(argTypes) {\n var memberFunction = craftInvokerFunction(humanName, argTypes, classType, rawInvoker, context);\n if (undefined === proto[methodName].overloadTable) {\n memberFunction.argCount = argCount - 2;\n proto[methodName] = memberFunction;\n } else {\n proto[methodName].overloadTable[argCount - 2] = memberFunction;\n }\n return [];\n });\n return [];\n });\n}\n\nvar emval_free_list = [];\n\nvar emval_handle_array = [ {}, {\n value: undefined\n}, {\n value: null\n}, {\n value: true\n}, {\n value: false\n} ];\n\nfunction __emval_decref(handle) {\n if (handle > 4 && 0 === --emval_handle_array[handle].refcount) {\n emval_handle_array[handle] = undefined;\n emval_free_list.push(handle);\n }\n}\n\nfunction count_emval_handles() {\n var count = 0;\n for (var i = 5; i < emval_handle_array.length; ++i) {\n if (emval_handle_array[i] !== undefined) {\n ++count;\n }\n }\n return count;\n}\n\nfunction get_first_emval() {\n for (var i = 5; i < emval_handle_array.length; ++i) {\n if (emval_handle_array[i] !== undefined) {\n return emval_handle_array[i];\n }\n }\n return null;\n}\n\nfunction init_emval() {\n Module[\"count_emval_handles\"] = count_emval_handles;\n Module[\"get_first_emval\"] = get_first_emval;\n}\n\nvar Emval = {\n toValue: function(handle) {\n if (!handle) {\n throwBindingError(\"Cannot use deleted val. handle = \" + handle);\n }\n return emval_handle_array[handle].value;\n },\n toHandle: function(value) {\n switch (value) {\n case undefined:\n {\n return 1;\n }\n\n case null:\n {\n return 2;\n }\n\n case true:\n {\n return 3;\n }\n\n case false:\n {\n return 4;\n }\n\n default:\n {\n var handle = emval_free_list.length ? emval_free_list.pop() : emval_handle_array.length;\n emval_handle_array[handle] = {\n refcount: 1,\n value: value\n };\n return handle;\n }\n }\n }\n};\n\nfunction __embind_register_emval(rawType, name) {\n name = readLatin1String(name);\n registerType(rawType, {\n name: name,\n \"fromWireType\": function(handle) {\n var rv = Emval.toValue(handle);\n __emval_decref(handle);\n return rv;\n },\n \"toWireType\": function(destructors, value) {\n return Emval.toHandle(value);\n },\n \"argPackAdvance\": 8,\n \"readValueFromPointer\": simpleReadValueFromPointer,\n destructorFunction: null\n });\n}\n\nfunction _embind_repr(v) {\n if (v === null) {\n return \"null\";\n }\n var t = typeof v;\n if (t === \"object\" || t === \"array\" || t === \"function\") {\n return v.toString();\n } else {\n return \"\" + v;\n }\n}\n\nfunction floatReadValueFromPointer(name, shift) {\n switch (shift) {\n case 2:\n return function(pointer) {\n return this[\"fromWireType\"](_asan_js_load_f(pointer >> 2));\n };\n\n case 3:\n return function(pointer) {\n return this[\"fromWireType\"](_asan_js_load_d(pointer >> 3));\n };\n\n default:\n throw new TypeError(\"Unknown float type: \" + name);\n }\n}\n\nfunction __embind_register_float(rawType, name, size) {\n var shift = getShiftFromSize(size);\n name = readLatin1String(name);\n registerType(rawType, {\n name: name,\n \"fromWireType\": function(value) {\n return value;\n },\n \"toWireType\": function(destructors, value) {\n if (typeof value !== \"number\" && typeof value !== \"boolean\") {\n throw new TypeError('Cannot convert \"' + _embind_repr(value) + '\" to ' + this.name);\n }\n return value;\n },\n \"argPackAdvance\": 8,\n \"readValueFromPointer\": floatReadValueFromPointer(name, shift),\n destructorFunction: null\n });\n}\n\nfunction __embind_register_function(name, argCount, rawArgTypesAddr, signature, rawInvoker, fn) {\n var argTypes = heap32VectorToArray(argCount, rawArgTypesAddr);\n name = readLatin1String(name);\n rawInvoker = embind__requireFunction(signature, rawInvoker);\n exposePublicSymbol(name, function() {\n throwUnboundTypeError(\"Cannot call \" + name + \" due to unbound types\", argTypes);\n }, argCount - 1);\n whenDependentTypesAreResolved([], argTypes, function(argTypes) {\n var invokerArgsArray = [ argTypes[0], null ].concat(argTypes.slice(1));\n replacePublicSymbol(name, craftInvokerFunction(name, invokerArgsArray, null, rawInvoker, fn), argCount - 1);\n return [];\n });\n}\n\nfunction integerReadValueFromPointer(name, shift, signed) {\n switch (shift) {\n case 0:\n return signed ? function readS8FromPointer(pointer) {\n return _asan_js_load_1(pointer);\n } : function readU8FromPointer(pointer) {\n return _asan_js_load_1u(pointer);\n };\n\n case 1:\n return signed ? function readS16FromPointer(pointer) {\n return _asan_js_load_2(pointer >> 1);\n } : function readU16FromPointer(pointer) {\n return _asan_js_load_2u(pointer >> 1);\n };\n\n case 2:\n return signed ? function readS32FromPointer(pointer) {\n return _asan_js_load_4(pointer >> 2);\n } : function readU32FromPointer(pointer) {\n return _asan_js_load_4u(pointer >> 2);\n };\n\n default:\n throw new TypeError(\"Unknown integer type: \" + name);\n }\n}\n\nfunction __embind_register_integer(primitiveType, name, size, minRange, maxRange) {\n name = readLatin1String(name);\n if (maxRange === -1) {\n maxRange = 4294967295;\n }\n var shift = getShiftFromSize(size);\n var fromWireType = value => value;\n if (minRange === 0) {\n var bitshift = 32 - 8 * size;\n fromWireType = (value => value << bitshift >>> bitshift);\n }\n var isUnsignedType = name.includes(\"unsigned\");\n var checkAssertions = (value, toTypeName) => {\n if (typeof value !== \"number\" && typeof value !== \"boolean\") {\n throw new TypeError('Cannot convert \"' + _embind_repr(value) + '\" to ' + toTypeName);\n }\n if (value < minRange || value > maxRange) {\n 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 + \"]!\");\n }\n };\n var toWireType;\n if (isUnsignedType) {\n toWireType = function(destructors, value) {\n checkAssertions(value, this.name);\n return value >>> 0;\n };\n } else {\n toWireType = function(destructors, value) {\n checkAssertions(value, this.name);\n return value;\n };\n }\n registerType(primitiveType, {\n name: name,\n \"fromWireType\": fromWireType,\n \"toWireType\": toWireType,\n \"argPackAdvance\": 8,\n \"readValueFromPointer\": integerReadValueFromPointer(name, shift, minRange !== 0),\n destructorFunction: null\n });\n}\n\nfunction __embind_register_memory_view(rawType, dataTypeIndex, name) {\n var typeMapping = [ Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array ];\n var TA = typeMapping[dataTypeIndex];\n function decodeMemoryView(handle) {\n handle = handle >> 2;\n var heap = HEAPU32;\n var size = heap[handle];\n var data = heap[handle + 1];\n return new TA(buffer, data, size);\n }\n name = readLatin1String(name);\n registerType(rawType, {\n name: name,\n \"fromWireType\": decodeMemoryView,\n \"argPackAdvance\": 8,\n \"readValueFromPointer\": decodeMemoryView\n }, {\n ignoreDuplicateRegistrations: true\n });\n}\n\nfunction __embind_register_std_string(rawType, name) {\n name = readLatin1String(name);\n var stdStringIsUTF8 = name === \"std::string\";\n registerType(rawType, {\n name: name,\n \"fromWireType\": function(value) {\n var length = _asan_js_load_4u(value >> 2);\n var str;\n if (stdStringIsUTF8) {\n var decodeStartPtr = value + 4;\n for (var i = 0; i <= length; ++i) {\n var currentBytePtr = value + 4 + i;\n if (i == length || _asan_js_load_1u(currentBytePtr) == 0) {\n var maxRead = currentBytePtr - decodeStartPtr;\n var stringSegment = UTF8ToString(decodeStartPtr, maxRead);\n if (str === undefined) {\n str = stringSegment;\n } else {\n str += String.fromCharCode(0);\n str += stringSegment;\n }\n decodeStartPtr = currentBytePtr + 1;\n }\n }\n } else {\n var a = new Array(length);\n for (var i = 0; i < length; ++i) {\n a[i] = String.fromCharCode(_asan_js_load_1u(value + 4 + i));\n }\n str = a.join(\"\");\n }\n _free(value);\n return str;\n },\n \"toWireType\": function(destructors, value) {\n if (value instanceof ArrayBuffer) {\n value = new Uint8Array(value);\n }\n var getLength;\n var valueIsOfTypeString = typeof value === \"string\";\n if (!(valueIsOfTypeString || value instanceof Uint8Array || value instanceof Uint8ClampedArray || value instanceof Int8Array)) {\n throwBindingError(\"Cannot pass non-string to std::string\");\n }\n if (stdStringIsUTF8 && valueIsOfTypeString) {\n getLength = (() => lengthBytesUTF8(value));\n } else {\n getLength = (() => value.length);\n }\n var length = getLength();\n var ptr = _malloc(4 + length + 1);\n _asan_js_store_4u(ptr >> 2, length);\n if (stdStringIsUTF8 && valueIsOfTypeString) {\n stringToUTF8(value, ptr + 4, length + 1);\n } else {\n if (valueIsOfTypeString) {\n for (var i = 0; i < length; ++i) {\n var charCode = value.charCodeAt(i);\n if (charCode > 255) {\n _free(ptr);\n throwBindingError(\"String has UTF-16 code units that do not fit in 8 bits\");\n }\n _asan_js_store_1u(ptr + 4 + i, charCode);\n }\n } else {\n for (var i = 0; i < length; ++i) {\n _asan_js_store_1u(ptr + 4 + i, value[i]);\n }\n }\n }\n if (destructors !== null) {\n destructors.push(_free, ptr);\n }\n return ptr;\n },\n \"argPackAdvance\": 8,\n \"readValueFromPointer\": simpleReadValueFromPointer,\n destructorFunction: function(ptr) {\n _free(ptr);\n }\n });\n}\n\nfunction __embind_register_std_wstring(rawType, charSize, name) {\n name = readLatin1String(name);\n var decodeString, encodeString, getHeap, lengthBytesUTF, shift;\n if (charSize === 2) {\n decodeString = UTF16ToString;\n encodeString = stringToUTF16;\n lengthBytesUTF = lengthBytesUTF16;\n getHeap = (() => HEAPU16);\n shift = 1;\n } else if (charSize === 4) {\n decodeString = UTF32ToString;\n encodeString = stringToUTF32;\n lengthBytesUTF = lengthBytesUTF32;\n getHeap = (() => HEAPU32);\n shift = 2;\n }\n registerType(rawType, {\n name: name,\n \"fromWireType\": function(value) {\n var length = _asan_js_load_4u(value >> 2);\n var HEAP = getHeap();\n var str;\n var decodeStartPtr = value + 4;\n for (var i = 0; i <= length; ++i) {\n var currentBytePtr = value + 4 + i * charSize;\n if (i == length || HEAP[currentBytePtr >> shift] == 0) {\n var maxReadBytes = currentBytePtr - decodeStartPtr;\n var stringSegment = decodeString(decodeStartPtr, maxReadBytes);\n if (str === undefined) {\n str = stringSegment;\n } else {\n str += String.fromCharCode(0);\n str += stringSegment;\n }\n decodeStartPtr = currentBytePtr + charSize;\n }\n }\n _free(value);\n return str;\n },\n \"toWireType\": function(destructors, value) {\n if (!(typeof value === \"string\")) {\n throwBindingError(\"Cannot pass non-string to C++ string type \" + name);\n }\n var length = lengthBytesUTF(value);\n var ptr = _malloc(4 + length + charSize);\n _asan_js_store_4u(ptr >> 2, length >> shift);\n encodeString(value, ptr + 4, length + charSize);\n if (destructors !== null) {\n destructors.push(_free, ptr);\n }\n return ptr;\n },\n \"argPackAdvance\": 8,\n \"readValueFromPointer\": simpleReadValueFromPointer,\n destructorFunction: function(ptr) {\n _free(ptr);\n }\n });\n}\n\nfunction __embind_register_void(rawType, name) {\n name = readLatin1String(name);\n registerType(rawType, {\n isVoid: true,\n name: name,\n \"argPackAdvance\": 0,\n \"fromWireType\": function() {\n return undefined;\n },\n \"toWireType\": function(destructors, o) {\n return undefined;\n }\n });\n}\n\nfunction __emval_incref(handle) {\n if (handle > 4) {\n emval_handle_array[handle].refcount += 1;\n }\n}\n\nfunction requireRegisteredType(rawType, humanName) {\n var impl = registeredTypes[rawType];\n if (undefined === impl) {\n throwBindingError(humanName + \" has unknown type \" + getTypeName(rawType));\n }\n return impl;\n}\n\nfunction __emval_take_value(type, argv) {\n type = requireRegisteredType(type, \"_emval_take_value\");\n var v = type[\"readValueFromPointer\"](argv);\n return Emval.toHandle(v);\n}\n\nfunction _abort() {\n abort(\"native code called abort()\");\n}\n\nvar readAsmConstArgsArray = [];\n\nfunction readAsmConstArgs(sigPtr, buf) {\n assert(Array.isArray(readAsmConstArgsArray));\n assert(buf % 16 == 0);\n readAsmConstArgsArray.length = 0;\n var ch;\n buf >>= 2;\n while (ch = _asan_js_load_1u(sigPtr++)) {\n assert(ch === 100 || ch === 102 || ch === 105);\n var readAsmConstArgsDouble = ch < 105;\n if (readAsmConstArgsDouble && buf & 1) buf++;\n readAsmConstArgsArray.push(readAsmConstArgsDouble ? _asan_js_load_d(buf++ >> 1) : _asan_js_load_4(buf));\n ++buf;\n }\n return readAsmConstArgsArray;\n}\n\nfunction _emscripten_asm_const_int(code, sigPtr, argbuf) {\n var args = readAsmConstArgs(sigPtr, argbuf);\n if (!ASM_CONSTS.hasOwnProperty(code)) abort(\"No EM_ASM constant found at address \" + code);\n return ASM_CONSTS[code].apply(null, args);\n}\n\nfunction _emscripten_asm_const_double(a0, a1, a2) {\n return _emscripten_asm_const_int(a0, a1, a2);\n}\n\nfunction syscallMmap2(addr, len, prot, flags, fd, off) {\n off <<= 12;\n var ptr;\n var allocated = false;\n if ((flags & 16) !== 0 && addr % 65536 !== 0) {\n return -28;\n }\n if ((flags & 32) !== 0) {\n ptr = mmapAlloc(len);\n if (!ptr) return -48;\n allocated = true;\n } else {\n var info = FS.getStream(fd);\n if (!info) return -8;\n var res = FS.mmap(info, addr, len, off, prot, flags);\n ptr = res.ptr;\n allocated = res.allocated;\n }\n SYSCALLS.mappings[ptr] = {\n malloc: ptr,\n len: len,\n allocated: allocated,\n fd: fd,\n prot: prot,\n flags: flags,\n offset: off\n };\n return ptr;\n}\n\nfunction withBuiltinMalloc(func) {\n var prev_malloc = typeof _malloc !== \"undefined\" ? _malloc : undefined;\n var prev_memalign = typeof _memalign !== \"undefined\" ? _memalign : undefined;\n var prev_free = typeof _free !== \"undefined\" ? _free : undefined;\n _malloc = _emscripten_builtin_malloc;\n _memalign = _emscripten_builtin_memalign;\n _free = _emscripten_builtin_free;\n try {\n return func();\n } finally {\n _malloc = prev_malloc;\n _memalign = prev_memalign;\n _free = prev_free;\n }\n}\n\nfunction _emscripten_builtin_mmap2(addr, len, prot, flags, fd, off) {\n return withBuiltinMalloc(function() {\n return syscallMmap2(addr, len, prot, flags, fd, off);\n });\n}\n\nfunction syscallMunmap(addr, len) {\n var info = SYSCALLS.mappings[addr];\n if (len === 0 || !info) {\n return -28;\n }\n if (len === info.len) {\n var stream = FS.getStream(info.fd);\n if (stream) {\n if (info.prot & 2) {\n SYSCALLS.doMsync(addr, stream, len, info.flags, info.offset);\n }\n FS.munmap(stream);\n }\n SYSCALLS.mappings[addr] = null;\n if (info.allocated) {\n _free(info.malloc);\n }\n }\n return 0;\n}\n\nfunction _emscripten_builtin_munmap(addr, len) {\n return withBuiltinMalloc(function() {\n return syscallMunmap(addr, len);\n });\n}\n\nfunction _emscripten_console_error(str) {\n assert(typeof str === \"number\");\n console.error(UTF8ToString(str));\n}\n\nfunction _emscripten_get_heap_max() {\n return HEAPU8.length;\n}\n\nfunction _emscripten_get_module_name(buf, length) {\n return stringToUTF8(wasmBinaryFile, buf, length);\n}\n\nvar _emscripten_get_now;\n\n_emscripten_get_now = (() => performance.now());\n\nvar UNWIND_CACHE = {};\n\nfunction convertFrameToPC(frame) {\n assert(wasmOffsetConverter);\n var match;\n if (match = /\\bwasm-function\\[\\d+\\]:(0x[0-9a-f]+)/.exec(frame)) {\n return +match[1];\n } else if (match = /\\bwasm-function\\[(\\d+)\\]:(\\d+)/.exec(frame)) {\n return wasmOffsetConverter.convert(+match[1], +match[2]);\n } else if (match = /:(\\d+):\\d+(?:\\)|$)/.exec(frame)) {\n return 2147483648 | +match[1];\n }\n return 0;\n}\n\nfunction convertPCtoSourceLocation(pc) {\n if (UNWIND_CACHE.last_get_source_pc == pc) return UNWIND_CACHE.last_source;\n var match;\n var source;\n if (!source) {\n var frame = UNWIND_CACHE[pc];\n if (!frame) return null;\n if (match = /\\((.*):(\\d+):(\\d+)\\)$/.exec(frame)) {\n source = {\n file: match[1],\n line: match[2],\n column: match[3]\n };\n } else if (match = /@(.*):(\\d+):(\\d+)/.exec(frame)) {\n source = {\n file: match[1],\n line: match[2],\n column: match[3]\n };\n }\n }\n UNWIND_CACHE.last_get_source_pc = pc;\n UNWIND_CACHE.last_source = source;\n return source;\n}\n\nfunction _emscripten_pc_get_column(pc) {\n var result = convertPCtoSourceLocation(pc);\n return result ? result.column || 0 : 0;\n}\n\nfunction _emscripten_pc_get_file(pc) {\n return withBuiltinMalloc(function() {\n var result = convertPCtoSourceLocation(pc);\n if (!result) return 0;\n if (_emscripten_pc_get_file.ret) _free(_emscripten_pc_get_file.ret);\n _emscripten_pc_get_file.ret = allocateUTF8(result.file);\n return _emscripten_pc_get_file.ret;\n });\n}\n\nfunction _emscripten_pc_get_function(pc) {\n return withBuiltinMalloc(function() {\n var name;\n if (pc & 2147483648) {\n var frame = UNWIND_CACHE[pc];\n if (!frame) return 0;\n var match;\n if (match = /^\\s+at (.*) \\(.*\\)$/.exec(frame)) {\n name = match[1];\n } else if (match = /^(.+?)@/.exec(frame)) {\n name = match[1];\n } else {\n return 0;\n }\n } else {\n name = wasmOffsetConverter.getName(pc);\n }\n if (_emscripten_pc_get_function.ret) _free(_emscripten_pc_get_function.ret);\n _emscripten_pc_get_function.ret = allocateUTF8(name);\n return _emscripten_pc_get_function.ret;\n });\n}\n\nfunction _emscripten_pc_get_line(pc) {\n var result = convertPCtoSourceLocation(pc);\n return result ? result.line : 0;\n}\n\nfunction abortOnCannotGrowMemory(requestedSize) {\n abort(\"Cannot enlarge memory arrays to size \" + requestedSize + \" bytes (OOM). Either (1) compile with -s INITIAL_MEMORY=X with X higher than the current value \" + HEAP8.length + \", (2) compile with -s ALLOW_MEMORY_GROWTH=1 which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 \");\n}\n\nfunction _emscripten_resize_heap(requestedSize) {\n var oldSize = HEAPU8.length;\n requestedSize = requestedSize >>> 0;\n abortOnCannotGrowMemory(requestedSize);\n}\n\nfunction _emscripten_return_address(level) {\n var callstack = new Error().stack.split(\"\\n\");\n if (callstack[0] == \"Error\") {\n callstack.shift();\n }\n return convertFrameToPC(callstack[level + 2]);\n}\n\nfunction saveInUnwindCache(callstack) {\n callstack.forEach(function(frame) {\n var pc = convertFrameToPC(frame);\n if (pc) {\n UNWIND_CACHE[pc] = frame;\n }\n });\n}\n\nfunction _emscripten_stack_snapshot() {\n var callstack = new Error().stack.split(\"\\n\");\n if (callstack[0] == \"Error\") {\n callstack.shift();\n }\n saveInUnwindCache(callstack);\n UNWIND_CACHE.last_addr = convertFrameToPC(callstack[2]);\n UNWIND_CACHE.last_stack = callstack;\n return UNWIND_CACHE.last_addr;\n}\n\nfunction _emscripten_stack_unwind_buffer(addr, buffer, count) {\n var stack;\n if (UNWIND_CACHE.last_addr == addr) {\n stack = UNWIND_CACHE.last_stack;\n } else {\n stack = new Error().stack.split(\"\\n\");\n if (stack[0] == \"Error\") {\n stack.shift();\n }\n saveInUnwindCache(stack);\n }\n var offset = 2;\n while (stack[offset] && convertFrameToPC(stack[offset]) != addr) {\n ++offset;\n }\n for (var i = 0; i < count && stack[i + offset]; ++i) {\n _asan_js_store_4(buffer + i * 4 >> 2, convertFrameToPC(stack[i + offset]));\n }\n return i;\n}\n\nvar ENV = {};\n\nfunction getExecutableName() {\n return thisProgram || \"./this.program\";\n}\n\nfunction getEnvStrings() {\n if (!getEnvStrings.strings) {\n var lang = (typeof navigator === \"object\" && navigator.languages && navigator.languages[0] || \"C\").replace(\"-\", \"_\") + \".UTF-8\";\n var env = {\n \"USER\": \"web_user\",\n \"LOGNAME\": \"web_user\",\n \"PATH\": \"/\",\n \"PWD\": \"/\",\n \"HOME\": \"/home/web_user\",\n \"LANG\": lang,\n \"_\": getExecutableName()\n };\n for (var x in ENV) {\n if (ENV[x] === undefined) delete env[x]; else env[x] = ENV[x];\n }\n var strings = [];\n for (var x in env) {\n strings.push(x + \"=\" + env[x]);\n }\n getEnvStrings.strings = strings;\n }\n return getEnvStrings.strings;\n}\n\nfunction _environ_get(__environ, environ_buf) {\n var bufSize = 0;\n getEnvStrings().forEach(function(string, i) {\n var ptr = environ_buf + bufSize;\n _asan_js_store_4(__environ + i * 4 >> 2, ptr);\n writeAsciiToMemory(string, ptr);\n bufSize += string.length + 1;\n });\n return 0;\n}\n\nfunction _environ_sizes_get(penviron_count, penviron_buf_size) {\n var strings = getEnvStrings();\n _asan_js_store_4(penviron_count >> 2, strings.length);\n var bufSize = 0;\n strings.forEach(function(string) {\n bufSize += string.length + 1;\n });\n _asan_js_store_4(penviron_buf_size >> 2, bufSize);\n return 0;\n}\n\nfunction _fd_close(fd) {\n try {\n var stream = SYSCALLS.getStreamFromFD(fd);\n FS.close(stream);\n return 0;\n } catch (e) {\n if (typeof FS === \"undefined\" || !(e instanceof FS.ErrnoError)) throw e;\n return e.errno;\n }\n}\n\nfunction _fd_read(fd, iov, iovcnt, pnum) {\n try {\n var stream = SYSCALLS.getStreamFromFD(fd);\n var num = SYSCALLS.doReadv(stream, iov, iovcnt);\n _asan_js_store_4(pnum >> 2, num);\n return 0;\n } catch (e) {\n if (typeof FS === \"undefined\" || !(e instanceof FS.ErrnoError)) throw e;\n return e.errno;\n }\n}\n\nfunction _fd_write(fd, iov, iovcnt, pnum) {\n try {\n var stream = SYSCALLS.getStreamFromFD(fd);\n var num = SYSCALLS.doWritev(stream, iov, iovcnt);\n _asan_js_store_4(pnum >> 2, num);\n return 0;\n } catch (e) {\n if (typeof FS === \"undefined\" || !(e instanceof FS.ErrnoError)) throw e;\n return e.errno;\n }\n}\n\nfunction _proc_exit(code) {\n procExit(code);\n}\n\nfunction _setTempRet0(val) {\n setTempRet0(val);\n}\n\nvar FSNode = function(parent, name, mode, rdev) {\n if (!parent) {\n parent = this;\n }\n this.parent = parent;\n this.mount = parent.mount;\n this.mounted = null;\n this.id = FS.nextInode++;\n this.name = name;\n this.mode = mode;\n this.node_ops = {};\n this.stream_ops = {};\n this.rdev = rdev;\n};\n\nvar readMode = 292 | 73;\n\nvar writeMode = 146;\n\nObject.defineProperties(FSNode.prototype, {\n read: {\n get: function() {\n return (this.mode & readMode) === readMode;\n },\n set: function(val) {\n val ? this.mode |= readMode : this.mode &= ~readMode;\n }\n },\n write: {\n get: function() {\n return (this.mode & writeMode) === writeMode;\n },\n set: function(val) {\n val ? this.mode |= writeMode : this.mode &= ~writeMode;\n }\n },\n isFolder: {\n get: function() {\n return FS.isDir(this.mode);\n }\n },\n isDevice: {\n get: function() {\n return FS.isChrdev(this.mode);\n }\n }\n});\n\nFS.FSNode = FSNode;\n\nFS.staticInit();\n\nERRNO_CODES = {\n \"EPERM\": 63,\n \"ENOENT\": 44,\n \"ESRCH\": 71,\n \"EINTR\": 27,\n \"EIO\": 29,\n \"ENXIO\": 60,\n \"E2BIG\": 1,\n \"ENOEXEC\": 45,\n \"EBADF\": 8,\n \"ECHILD\": 12,\n \"EAGAIN\": 6,\n \"EWOULDBLOCK\": 6,\n \"ENOMEM\": 48,\n \"EACCES\": 2,\n \"EFAULT\": 21,\n \"ENOTBLK\": 105,\n \"EBUSY\": 10,\n \"EEXIST\": 20,\n \"EXDEV\": 75,\n \"ENODEV\": 43,\n \"ENOTDIR\": 54,\n \"EISDIR\": 31,\n \"EINVAL\": 28,\n \"ENFILE\": 41,\n \"EMFILE\": 33,\n \"ENOTTY\": 59,\n \"ETXTBSY\": 74,\n \"EFBIG\": 22,\n \"ENOSPC\": 51,\n \"ESPIPE\": 70,\n \"EROFS\": 69,\n \"EMLINK\": 34,\n \"EPIPE\": 64,\n \"EDOM\": 18,\n \"ERANGE\": 68,\n \"ENOMSG\": 49,\n \"EIDRM\": 24,\n \"ECHRNG\": 106,\n \"EL2NSYNC\": 156,\n \"EL3HLT\": 107,\n \"EL3RST\": 108,\n \"ELNRNG\": 109,\n \"EUNATCH\": 110,\n \"ENOCSI\": 111,\n \"EL2HLT\": 112,\n \"EDEADLK\": 16,\n \"ENOLCK\": 46,\n \"EBADE\": 113,\n \"EBADR\": 114,\n \"EXFULL\": 115,\n \"ENOANO\": 104,\n \"EBADRQC\": 103,\n \"EBADSLT\": 102,\n \"EDEADLOCK\": 16,\n \"EBFONT\": 101,\n \"ENOSTR\": 100,\n \"ENODATA\": 116,\n \"ETIME\": 117,\n \"ENOSR\": 118,\n \"ENONET\": 119,\n \"ENOPKG\": 120,\n \"EREMOTE\": 121,\n \"ENOLINK\": 47,\n \"EADV\": 122,\n \"ESRMNT\": 123,\n \"ECOMM\": 124,\n \"EPROTO\": 65,\n \"EMULTIHOP\": 36,\n \"EDOTDOT\": 125,\n \"EBADMSG\": 9,\n \"ENOTUNIQ\": 126,\n \"EBADFD\": 127,\n \"EREMCHG\": 128,\n \"ELIBACC\": 129,\n \"ELIBBAD\": 130,\n \"ELIBSCN\": 131,\n \"ELIBMAX\": 132,\n \"ELIBEXEC\": 133,\n \"ENOSYS\": 52,\n \"ENOTEMPTY\": 55,\n \"ENAMETOOLONG\": 37,\n \"ELOOP\": 32,\n \"EOPNOTSUPP\": 138,\n \"EPFNOSUPPORT\": 139,\n \"ECONNRESET\": 15,\n \"ENOBUFS\": 42,\n \"EAFNOSUPPORT\": 5,\n \"EPROTOTYPE\": 67,\n \"ENOTSOCK\": 57,\n \"ENOPROTOOPT\": 50,\n \"ESHUTDOWN\": 140,\n \"ECONNREFUSED\": 14,\n \"EADDRINUSE\": 3,\n \"ECONNABORTED\": 13,\n \"ENETUNREACH\": 40,\n \"ENETDOWN\": 38,\n \"ETIMEDOUT\": 73,\n \"EHOSTDOWN\": 142,\n \"EHOSTUNREACH\": 23,\n \"EINPROGRESS\": 26,\n \"EALREADY\": 7,\n \"EDESTADDRREQ\": 17,\n \"EMSGSIZE\": 35,\n \"EPROTONOSUPPORT\": 66,\n \"ESOCKTNOSUPPORT\": 137,\n \"EADDRNOTAVAIL\": 4,\n \"ENETRESET\": 39,\n \"EISCONN\": 30,\n \"ENOTCONN\": 53,\n \"ETOOMANYREFS\": 141,\n \"EUSERS\": 136,\n \"EDQUOT\": 19,\n \"ESTALE\": 72,\n \"ENOTSUP\": 138,\n \"ENOMEDIUM\": 148,\n \"EILSEQ\": 25,\n \"EOVERFLOW\": 61,\n \"ECANCELED\": 11,\n \"ENOTRECOVERABLE\": 56,\n \"EOWNERDEAD\": 62,\n \"ESTRPIPE\": 135\n};\n\nembind_init_charCodes();\n\nBindingError = Module[\"BindingError\"] = extendError(Error, \"BindingError\");\n\nInternalError = Module[\"InternalError\"] = extendError(Error, \"InternalError\");\n\ninit_ClassHandle();\n\ninit_embind();\n\ninit_RegisteredPointer();\n\nUnboundTypeError = Module[\"UnboundTypeError\"] = extendError(Error, \"UnboundTypeError\");\n\ninit_emval();\n\nvar ASSERTIONS = true;\n\nfunction intArrayFromString(stringy, dontAddNull, length) {\n var len = length > 0 ? length : lengthBytesUTF8(stringy) + 1;\n var u8array = new Array(len);\n var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length);\n if (dontAddNull) u8array.length = numBytesWritten;\n return u8array;\n}\n\nvar asmLibraryArg = {\n \"__assert_fail\": ___assert_fail,\n \"__syscall_dup\": ___syscall_dup,\n \"__syscall_open\": ___syscall_open,\n \"__syscall_stat64\": ___syscall_stat64,\n \"_embind_register_bigint\": __embind_register_bigint,\n \"_embind_register_bool\": __embind_register_bool,\n \"_embind_register_class\": __embind_register_class,\n \"_embind_register_class_constructor\": __embind_register_class_constructor,\n \"_embind_register_class_function\": __embind_register_class_function,\n \"_embind_register_emval\": __embind_register_emval,\n \"_embind_register_float\": __embind_register_float,\n \"_embind_register_function\": __embind_register_function,\n \"_embind_register_integer\": __embind_register_integer,\n \"_embind_register_memory_view\": __embind_register_memory_view,\n \"_embind_register_std_string\": __embind_register_std_string,\n \"_embind_register_std_wstring\": __embind_register_std_wstring,\n \"_embind_register_void\": __embind_register_void,\n \"_emval_decref\": __emval_decref,\n \"_emval_incref\": __emval_incref,\n \"_emval_take_value\": __emval_take_value,\n \"abort\": _abort,\n \"emscripten_asm_const_double\": _emscripten_asm_const_double,\n \"emscripten_asm_const_int\": _emscripten_asm_const_int,\n \"emscripten_builtin_mmap2\": _emscripten_builtin_mmap2,\n \"emscripten_builtin_munmap\": _emscripten_builtin_munmap,\n \"emscripten_console_error\": _emscripten_console_error,\n \"emscripten_get_heap_max\": _emscripten_get_heap_max,\n \"emscripten_get_module_name\": _emscripten_get_module_name,\n \"emscripten_get_now\": _emscripten_get_now,\n \"emscripten_pc_get_column\": _emscripten_pc_get_column,\n \"emscripten_pc_get_file\": _emscripten_pc_get_file,\n \"emscripten_pc_get_function\": _emscripten_pc_get_function,\n \"emscripten_pc_get_line\": _emscripten_pc_get_line,\n \"emscripten_resize_heap\": _emscripten_resize_heap,\n \"emscripten_return_address\": _emscripten_return_address,\n \"emscripten_stack_snapshot\": _emscripten_stack_snapshot,\n \"emscripten_stack_unwind_buffer\": _emscripten_stack_unwind_buffer,\n \"environ_get\": _environ_get,\n \"environ_sizes_get\": _environ_sizes_get,\n \"fd_close\": _fd_close,\n \"fd_read\": _fd_read,\n \"fd_write\": _fd_write,\n \"proc_exit\": _proc_exit,\n \"setTempRet0\": _setTempRet0\n};\n\nvar asm = createWasm();\n\nvar ___wasm_call_ctors = Module[\"___wasm_call_ctors\"] = createExportWrapper(\"__wasm_call_ctors\");\n\nvar ___getTypeName = Module[\"___getTypeName\"] = createExportWrapper(\"__getTypeName\");\n\nvar ___embind_register_native_and_builtin_types = Module[\"___embind_register_native_and_builtin_types\"] = createExportWrapper(\"__embind_register_native_and_builtin_types\");\n\nvar ___errno_location = Module[\"___errno_location\"] = createExportWrapper(\"__errno_location\");\n\nvar ___stdio_exit = Module[\"___stdio_exit\"] = createExportWrapper(\"__stdio_exit\");\n\nvar ___funcs_on_exit = Module[\"___funcs_on_exit\"] = createExportWrapper(\"__funcs_on_exit\");\n\nvar _malloc = Module[\"_malloc\"] = createExportWrapper(\"malloc\");\n\nvar _free = Module[\"_free\"] = createExportWrapper(\"free\");\n\nvar _memalign = Module[\"_memalign\"] = createExportWrapper(\"memalign\");\n\nvar _emscripten_builtin_malloc = Module[\"_emscripten_builtin_malloc\"] = createExportWrapper(\"emscripten_builtin_malloc\");\n\nvar _emscripten_builtin_free = Module[\"_emscripten_builtin_free\"] = createExportWrapper(\"emscripten_builtin_free\");\n\nvar _emscripten_builtin_memalign = Module[\"_emscripten_builtin_memalign\"] = createExportWrapper(\"emscripten_builtin_memalign\");\n\nvar _emscripten_stack_init = Module[\"_emscripten_stack_init\"] = function() {\n return (_emscripten_stack_init = Module[\"_emscripten_stack_init\"] = Module[\"asm\"][\"emscripten_stack_init\"]).apply(null, arguments);\n};\n\nvar _emscripten_stack_get_free = Module[\"_emscripten_stack_get_free\"] = function() {\n return (_emscripten_stack_get_free = Module[\"_emscripten_stack_get_free\"] = Module[\"asm\"][\"emscripten_stack_get_free\"]).apply(null, arguments);\n};\n\nvar _emscripten_stack_get_base = Module[\"_emscripten_stack_get_base\"] = function() {\n return (_emscripten_stack_get_base = Module[\"_emscripten_stack_get_base\"] = Module[\"asm\"][\"emscripten_stack_get_base\"]).apply(null, arguments);\n};\n\nvar _emscripten_stack_get_end = Module[\"_emscripten_stack_get_end\"] = function() {\n return (_emscripten_stack_get_end = Module[\"_emscripten_stack_get_end\"] = Module[\"asm\"][\"emscripten_stack_get_end\"]).apply(null, arguments);\n};\n\nvar stackSave = Module[\"stackSave\"] = createExportWrapper(\"stackSave\");\n\nvar stackRestore = Module[\"stackRestore\"] = createExportWrapper(\"stackRestore\");\n\nvar stackAlloc = Module[\"stackAlloc\"] = createExportWrapper(\"stackAlloc\");\n\nvar __ZN6__asan9FakeStack17AddrIsInFakeStackEm = Module[\"__ZN6__asan9FakeStack17AddrIsInFakeStackEm\"] = createExportWrapper(\"_ZN6__asan9FakeStack17AddrIsInFakeStackEm\");\n\nvar __ZN6__asan9FakeStack8AllocateEmmm = Module[\"__ZN6__asan9FakeStack8AllocateEmmm\"] = createExportWrapper(\"_ZN6__asan9FakeStack8AllocateEmmm\");\n\nvar _asan_c_load_1 = Module[\"_asan_c_load_1\"] = createExportWrapper(\"asan_c_load_1\");\n\nvar _asan_c_load_1u = Module[\"_asan_c_load_1u\"] = createExportWrapper(\"asan_c_load_1u\");\n\nvar _asan_c_load_2 = Module[\"_asan_c_load_2\"] = createExportWrapper(\"asan_c_load_2\");\n\nvar _asan_c_load_2u = Module[\"_asan_c_load_2u\"] = createExportWrapper(\"asan_c_load_2u\");\n\nvar _asan_c_load_4 = Module[\"_asan_c_load_4\"] = createExportWrapper(\"asan_c_load_4\");\n\nvar _asan_c_load_4u = Module[\"_asan_c_load_4u\"] = createExportWrapper(\"asan_c_load_4u\");\n\nvar _asan_c_load_f = Module[\"_asan_c_load_f\"] = createExportWrapper(\"asan_c_load_f\");\n\nvar _asan_c_load_d = Module[\"_asan_c_load_d\"] = createExportWrapper(\"asan_c_load_d\");\n\nvar _asan_c_store_1 = Module[\"_asan_c_store_1\"] = createExportWrapper(\"asan_c_store_1\");\n\nvar _asan_c_store_1u = Module[\"_asan_c_store_1u\"] = createExportWrapper(\"asan_c_store_1u\");\n\nvar _asan_c_store_2 = Module[\"_asan_c_store_2\"] = createExportWrapper(\"asan_c_store_2\");\n\nvar _asan_c_store_2u = Module[\"_asan_c_store_2u\"] = createExportWrapper(\"asan_c_store_2u\");\n\nvar _asan_c_store_4 = Module[\"_asan_c_store_4\"] = createExportWrapper(\"asan_c_store_4\");\n\nvar _asan_c_store_4u = Module[\"_asan_c_store_4u\"] = createExportWrapper(\"asan_c_store_4u\");\n\nvar _asan_c_store_f = Module[\"_asan_c_store_f\"] = createExportWrapper(\"asan_c_store_f\");\n\nvar _asan_c_store_d = Module[\"_asan_c_store_d\"] = createExportWrapper(\"asan_c_store_d\");\n\nvar dynCall_jii = Module[\"dynCall_jii\"] = createExportWrapper(\"dynCall_jii\");\n\nif (!Object.getOwnPropertyDescriptor(Module, \"intArrayFromString\")) Module[\"intArrayFromString\"] = (() => abort(\"'intArrayFromString' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"intArrayToString\")) Module[\"intArrayToString\"] = (() => abort(\"'intArrayToString' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"ccall\")) Module[\"ccall\"] = (() => abort(\"'ccall' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"cwrap\")) Module[\"cwrap\"] = (() => abort(\"'cwrap' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"setValue\")) Module[\"setValue\"] = (() => abort(\"'setValue' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"getValue\")) Module[\"getValue\"] = (() => abort(\"'getValue' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"allocate\")) Module[\"allocate\"] = (() => abort(\"'allocate' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"UTF8ArrayToString\")) Module[\"UTF8ArrayToString\"] = (() => abort(\"'UTF8ArrayToString' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"UTF8ToString\")) Module[\"UTF8ToString\"] = (() => abort(\"'UTF8ToString' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"stringToUTF8Array\")) Module[\"stringToUTF8Array\"] = (() => abort(\"'stringToUTF8Array' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"stringToUTF8\")) Module[\"stringToUTF8\"] = (() => abort(\"'stringToUTF8' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"lengthBytesUTF8\")) Module[\"lengthBytesUTF8\"] = (() => abort(\"'lengthBytesUTF8' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"stackTrace\")) Module[\"stackTrace\"] = (() => abort(\"'stackTrace' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"addOnPreRun\")) Module[\"addOnPreRun\"] = (() => abort(\"'addOnPreRun' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"addOnInit\")) Module[\"addOnInit\"] = (() => abort(\"'addOnInit' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"addOnPreMain\")) Module[\"addOnPreMain\"] = (() => abort(\"'addOnPreMain' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"addOnExit\")) Module[\"addOnExit\"] = (() => abort(\"'addOnExit' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"addOnPostRun\")) Module[\"addOnPostRun\"] = (() => abort(\"'addOnPostRun' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"writeStringToMemory\")) Module[\"writeStringToMemory\"] = (() => abort(\"'writeStringToMemory' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"writeArrayToMemory\")) Module[\"writeArrayToMemory\"] = (() => abort(\"'writeArrayToMemory' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"writeAsciiToMemory\")) Module[\"writeAsciiToMemory\"] = (() => abort(\"'writeAsciiToMemory' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"addRunDependency\")) Module[\"addRunDependency\"] = (() => abort(\"'addRunDependency' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"removeRunDependency\")) Module[\"removeRunDependency\"] = (() => abort(\"'removeRunDependency' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"FS_createFolder\")) Module[\"FS_createFolder\"] = (() => abort(\"'FS_createFolder' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"FS_createPath\")) Module[\"FS_createPath\"] = (() => abort(\"'FS_createPath' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"FS_createDataFile\")) Module[\"FS_createDataFile\"] = (() => abort(\"'FS_createDataFile' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"FS_createPreloadedFile\")) Module[\"FS_createPreloadedFile\"] = (() => abort(\"'FS_createPreloadedFile' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"FS_createLazyFile\")) Module[\"FS_createLazyFile\"] = (() => abort(\"'FS_createLazyFile' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"FS_createLink\")) Module[\"FS_createLink\"] = (() => abort(\"'FS_createLink' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"FS_createDevice\")) Module[\"FS_createDevice\"] = (() => abort(\"'FS_createDevice' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"FS_unlink\")) Module[\"FS_unlink\"] = (() => abort(\"'FS_unlink' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"getLEB\")) Module[\"getLEB\"] = (() => abort(\"'getLEB' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"getFunctionTables\")) Module[\"getFunctionTables\"] = (() => abort(\"'getFunctionTables' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"alignFunctionTables\")) Module[\"alignFunctionTables\"] = (() => abort(\"'alignFunctionTables' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"registerFunctions\")) Module[\"registerFunctions\"] = (() => abort(\"'registerFunctions' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"addFunction\")) Module[\"addFunction\"] = (() => abort(\"'addFunction' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"removeFunction\")) Module[\"removeFunction\"] = (() => abort(\"'removeFunction' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"getFuncWrapper\")) Module[\"getFuncWrapper\"] = (() => abort(\"'getFuncWrapper' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"prettyPrint\")) Module[\"prettyPrint\"] = (() => abort(\"'prettyPrint' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"dynCall\")) Module[\"dynCall\"] = (() => abort(\"'dynCall' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"getCompilerSetting\")) Module[\"getCompilerSetting\"] = (() => abort(\"'getCompilerSetting' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"print\")) Module[\"print\"] = (() => abort(\"'print' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"printErr\")) Module[\"printErr\"] = (() => abort(\"'printErr' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"getTempRet0\")) Module[\"getTempRet0\"] = (() => abort(\"'getTempRet0' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"setTempRet0\")) Module[\"setTempRet0\"] = (() => abort(\"'setTempRet0' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"callMain\")) Module[\"callMain\"] = (() => abort(\"'callMain' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"abort\")) Module[\"abort\"] = (() => abort(\"'abort' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"keepRuntimeAlive\")) Module[\"keepRuntimeAlive\"] = (() => abort(\"'keepRuntimeAlive' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"WasmOffsetConverter\")) Module[\"WasmOffsetConverter\"] = (() => abort(\"'WasmOffsetConverter' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"zeroMemory\")) Module[\"zeroMemory\"] = (() => abort(\"'zeroMemory' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"stringToNewUTF8\")) Module[\"stringToNewUTF8\"] = (() => abort(\"'stringToNewUTF8' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"setFileTime\")) Module[\"setFileTime\"] = (() => abort(\"'setFileTime' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"abortOnCannotGrowMemory\")) Module[\"abortOnCannotGrowMemory\"] = (() => abort(\"'abortOnCannotGrowMemory' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"emscripten_realloc_buffer\")) Module[\"emscripten_realloc_buffer\"] = (() => abort(\"'emscripten_realloc_buffer' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"ENV\")) Module[\"ENV\"] = (() => abort(\"'ENV' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"withStackSave\")) Module[\"withStackSave\"] = (() => abort(\"'withStackSave' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"ERRNO_CODES\")) Module[\"ERRNO_CODES\"] = (() => abort(\"'ERRNO_CODES' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"ERRNO_MESSAGES\")) Module[\"ERRNO_MESSAGES\"] = (() => abort(\"'ERRNO_MESSAGES' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"setErrNo\")) Module[\"setErrNo\"] = (() => abort(\"'setErrNo' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"inetPton4\")) Module[\"inetPton4\"] = (() => abort(\"'inetPton4' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"inetNtop4\")) Module[\"inetNtop4\"] = (() => abort(\"'inetNtop4' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"inetPton6\")) Module[\"inetPton6\"] = (() => abort(\"'inetPton6' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"inetNtop6\")) Module[\"inetNtop6\"] = (() => abort(\"'inetNtop6' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"readSockaddr\")) Module[\"readSockaddr\"] = (() => abort(\"'readSockaddr' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"writeSockaddr\")) Module[\"writeSockaddr\"] = (() => abort(\"'writeSockaddr' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"DNS\")) Module[\"DNS\"] = (() => abort(\"'DNS' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"getHostByName\")) Module[\"getHostByName\"] = (() => abort(\"'getHostByName' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"Protocols\")) Module[\"Protocols\"] = (() => abort(\"'Protocols' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"Sockets\")) Module[\"Sockets\"] = (() => abort(\"'Sockets' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"getRandomDevice\")) Module[\"getRandomDevice\"] = (() => abort(\"'getRandomDevice' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"traverseStack\")) Module[\"traverseStack\"] = (() => abort(\"'traverseStack' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"convertFrameToPC\")) Module[\"convertFrameToPC\"] = (() => abort(\"'convertFrameToPC' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"UNWIND_CACHE\")) Module[\"UNWIND_CACHE\"] = (() => abort(\"'UNWIND_CACHE' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"saveInUnwindCache\")) Module[\"saveInUnwindCache\"] = (() => abort(\"'saveInUnwindCache' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"convertPCtoSourceLocation\")) Module[\"convertPCtoSourceLocation\"] = (() => abort(\"'convertPCtoSourceLocation' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"withBuiltinMalloc\")) Module[\"withBuiltinMalloc\"] = (() => abort(\"'withBuiltinMalloc' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"readAsmConstArgsArray\")) Module[\"readAsmConstArgsArray\"] = (() => abort(\"'readAsmConstArgsArray' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"readAsmConstArgs\")) Module[\"readAsmConstArgs\"] = (() => abort(\"'readAsmConstArgs' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"mainThreadEM_ASM\")) Module[\"mainThreadEM_ASM\"] = (() => abort(\"'mainThreadEM_ASM' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"jstoi_q\")) Module[\"jstoi_q\"] = (() => abort(\"'jstoi_q' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"jstoi_s\")) Module[\"jstoi_s\"] = (() => abort(\"'jstoi_s' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"getExecutableName\")) Module[\"getExecutableName\"] = (() => abort(\"'getExecutableName' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"listenOnce\")) Module[\"listenOnce\"] = (() => abort(\"'listenOnce' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"autoResumeAudioContext\")) Module[\"autoResumeAudioContext\"] = (() => abort(\"'autoResumeAudioContext' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"dynCallLegacy\")) Module[\"dynCallLegacy\"] = (() => abort(\"'dynCallLegacy' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"getDynCaller\")) Module[\"getDynCaller\"] = (() => abort(\"'getDynCaller' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"dynCall\")) Module[\"dynCall\"] = (() => abort(\"'dynCall' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"callRuntimeCallbacks\")) Module[\"callRuntimeCallbacks\"] = (() => abort(\"'callRuntimeCallbacks' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"wasmTableMirror\")) Module[\"wasmTableMirror\"] = (() => abort(\"'wasmTableMirror' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"setWasmTableEntry\")) Module[\"setWasmTableEntry\"] = (() => abort(\"'setWasmTableEntry' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"getWasmTableEntry\")) Module[\"getWasmTableEntry\"] = (() => abort(\"'getWasmTableEntry' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"handleException\")) Module[\"handleException\"] = (() => abort(\"'handleException' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"runtimeKeepalivePush\")) Module[\"runtimeKeepalivePush\"] = (() => abort(\"'runtimeKeepalivePush' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"runtimeKeepalivePop\")) Module[\"runtimeKeepalivePop\"] = (() => abort(\"'runtimeKeepalivePop' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"callUserCallback\")) Module[\"callUserCallback\"] = (() => abort(\"'callUserCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"maybeExit\")) Module[\"maybeExit\"] = (() => abort(\"'maybeExit' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"safeSetTimeout\")) Module[\"safeSetTimeout\"] = (() => abort(\"'safeSetTimeout' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"asmjsMangle\")) Module[\"asmjsMangle\"] = (() => abort(\"'asmjsMangle' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"asyncLoad\")) Module[\"asyncLoad\"] = (() => abort(\"'asyncLoad' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"alignMemory\")) Module[\"alignMemory\"] = (() => abort(\"'alignMemory' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"mmapAlloc\")) Module[\"mmapAlloc\"] = (() => abort(\"'mmapAlloc' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"reallyNegative\")) Module[\"reallyNegative\"] = (() => abort(\"'reallyNegative' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"unSign\")) Module[\"unSign\"] = (() => abort(\"'unSign' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"reSign\")) Module[\"reSign\"] = (() => abort(\"'reSign' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"formatString\")) Module[\"formatString\"] = (() => abort(\"'formatString' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"PATH\")) Module[\"PATH\"] = (() => abort(\"'PATH' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"PATH_FS\")) Module[\"PATH_FS\"] = (() => abort(\"'PATH_FS' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"SYSCALLS\")) Module[\"SYSCALLS\"] = (() => abort(\"'SYSCALLS' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"syscallMmap2\")) Module[\"syscallMmap2\"] = (() => abort(\"'syscallMmap2' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"syscallMunmap\")) Module[\"syscallMunmap\"] = (() => abort(\"'syscallMunmap' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"getSocketFromFD\")) Module[\"getSocketFromFD\"] = (() => abort(\"'getSocketFromFD' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"getSocketAddress\")) Module[\"getSocketAddress\"] = (() => abort(\"'getSocketAddress' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"JSEvents\")) Module[\"JSEvents\"] = (() => abort(\"'JSEvents' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"registerKeyEventCallback\")) Module[\"registerKeyEventCallback\"] = (() => abort(\"'registerKeyEventCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"specialHTMLTargets\")) Module[\"specialHTMLTargets\"] = (() => abort(\"'specialHTMLTargets' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"maybeCStringToJsString\")) Module[\"maybeCStringToJsString\"] = (() => abort(\"'maybeCStringToJsString' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"findEventTarget\")) Module[\"findEventTarget\"] = (() => abort(\"'findEventTarget' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"findCanvasEventTarget\")) Module[\"findCanvasEventTarget\"] = (() => abort(\"'findCanvasEventTarget' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"getBoundingClientRect\")) Module[\"getBoundingClientRect\"] = (() => abort(\"'getBoundingClientRect' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"fillMouseEventData\")) Module[\"fillMouseEventData\"] = (() => abort(\"'fillMouseEventData' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"registerMouseEventCallback\")) Module[\"registerMouseEventCallback\"] = (() => abort(\"'registerMouseEventCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"registerWheelEventCallback\")) Module[\"registerWheelEventCallback\"] = (() => abort(\"'registerWheelEventCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"registerUiEventCallback\")) Module[\"registerUiEventCallback\"] = (() => abort(\"'registerUiEventCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"registerFocusEventCallback\")) Module[\"registerFocusEventCallback\"] = (() => abort(\"'registerFocusEventCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"fillDeviceOrientationEventData\")) Module[\"fillDeviceOrientationEventData\"] = (() => abort(\"'fillDeviceOrientationEventData' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"registerDeviceOrientationEventCallback\")) Module[\"registerDeviceOrientationEventCallback\"] = (() => abort(\"'registerDeviceOrientationEventCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"fillDeviceMotionEventData\")) Module[\"fillDeviceMotionEventData\"] = (() => abort(\"'fillDeviceMotionEventData' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"registerDeviceMotionEventCallback\")) Module[\"registerDeviceMotionEventCallback\"] = (() => abort(\"'registerDeviceMotionEventCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"screenOrientation\")) Module[\"screenOrientation\"] = (() => abort(\"'screenOrientation' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"fillOrientationChangeEventData\")) Module[\"fillOrientationChangeEventData\"] = (() => abort(\"'fillOrientationChangeEventData' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"registerOrientationChangeEventCallback\")) Module[\"registerOrientationChangeEventCallback\"] = (() => abort(\"'registerOrientationChangeEventCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"fillFullscreenChangeEventData\")) Module[\"fillFullscreenChangeEventData\"] = (() => abort(\"'fillFullscreenChangeEventData' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"registerFullscreenChangeEventCallback\")) Module[\"registerFullscreenChangeEventCallback\"] = (() => abort(\"'registerFullscreenChangeEventCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"registerRestoreOldStyle\")) Module[\"registerRestoreOldStyle\"] = (() => abort(\"'registerRestoreOldStyle' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"hideEverythingExceptGivenElement\")) Module[\"hideEverythingExceptGivenElement\"] = (() => abort(\"'hideEverythingExceptGivenElement' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"restoreHiddenElements\")) Module[\"restoreHiddenElements\"] = (() => abort(\"'restoreHiddenElements' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"setLetterbox\")) Module[\"setLetterbox\"] = (() => abort(\"'setLetterbox' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"currentFullscreenStrategy\")) Module[\"currentFullscreenStrategy\"] = (() => abort(\"'currentFullscreenStrategy' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"restoreOldWindowedStyle\")) Module[\"restoreOldWindowedStyle\"] = (() => abort(\"'restoreOldWindowedStyle' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"softFullscreenResizeWebGLRenderTarget\")) Module[\"softFullscreenResizeWebGLRenderTarget\"] = (() => abort(\"'softFullscreenResizeWebGLRenderTarget' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"doRequestFullscreen\")) Module[\"doRequestFullscreen\"] = (() => abort(\"'doRequestFullscreen' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"fillPointerlockChangeEventData\")) Module[\"fillPointerlockChangeEventData\"] = (() => abort(\"'fillPointerlockChangeEventData' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"registerPointerlockChangeEventCallback\")) Module[\"registerPointerlockChangeEventCallback\"] = (() => abort(\"'registerPointerlockChangeEventCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"registerPointerlockErrorEventCallback\")) Module[\"registerPointerlockErrorEventCallback\"] = (() => abort(\"'registerPointerlockErrorEventCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"requestPointerLock\")) Module[\"requestPointerLock\"] = (() => abort(\"'requestPointerLock' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"fillVisibilityChangeEventData\")) Module[\"fillVisibilityChangeEventData\"] = (() => abort(\"'fillVisibilityChangeEventData' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"registerVisibilityChangeEventCallback\")) Module[\"registerVisibilityChangeEventCallback\"] = (() => abort(\"'registerVisibilityChangeEventCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"registerTouchEventCallback\")) Module[\"registerTouchEventCallback\"] = (() => abort(\"'registerTouchEventCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"fillGamepadEventData\")) Module[\"fillGamepadEventData\"] = (() => abort(\"'fillGamepadEventData' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"registerGamepadEventCallback\")) Module[\"registerGamepadEventCallback\"] = (() => abort(\"'registerGamepadEventCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"registerBeforeUnloadEventCallback\")) Module[\"registerBeforeUnloadEventCallback\"] = (() => abort(\"'registerBeforeUnloadEventCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"fillBatteryEventData\")) Module[\"fillBatteryEventData\"] = (() => abort(\"'fillBatteryEventData' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"battery\")) Module[\"battery\"] = (() => abort(\"'battery' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"registerBatteryEventCallback\")) Module[\"registerBatteryEventCallback\"] = (() => abort(\"'registerBatteryEventCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"setCanvasElementSize\")) Module[\"setCanvasElementSize\"] = (() => abort(\"'setCanvasElementSize' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"getCanvasElementSize\")) Module[\"getCanvasElementSize\"] = (() => abort(\"'getCanvasElementSize' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"demangle\")) Module[\"demangle\"] = (() => abort(\"'demangle' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"demangleAll\")) Module[\"demangleAll\"] = (() => abort(\"'demangleAll' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"jsStackTrace\")) Module[\"jsStackTrace\"] = (() => abort(\"'jsStackTrace' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"stackTrace\")) Module[\"stackTrace\"] = (() => abort(\"'stackTrace' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"getEnvStrings\")) Module[\"getEnvStrings\"] = (() => abort(\"'getEnvStrings' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"checkWasiClock\")) Module[\"checkWasiClock\"] = (() => abort(\"'checkWasiClock' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"writeI53ToI64\")) Module[\"writeI53ToI64\"] = (() => abort(\"'writeI53ToI64' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"writeI53ToI64Clamped\")) Module[\"writeI53ToI64Clamped\"] = (() => abort(\"'writeI53ToI64Clamped' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"writeI53ToI64Signaling\")) Module[\"writeI53ToI64Signaling\"] = (() => abort(\"'writeI53ToI64Signaling' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"writeI53ToU64Clamped\")) Module[\"writeI53ToU64Clamped\"] = (() => abort(\"'writeI53ToU64Clamped' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"writeI53ToU64Signaling\")) Module[\"writeI53ToU64Signaling\"] = (() => abort(\"'writeI53ToU64Signaling' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"readI53FromI64\")) Module[\"readI53FromI64\"] = (() => abort(\"'readI53FromI64' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"readI53FromU64\")) Module[\"readI53FromU64\"] = (() => abort(\"'readI53FromU64' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"convertI32PairToI53\")) Module[\"convertI32PairToI53\"] = (() => abort(\"'convertI32PairToI53' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"convertU32PairToI53\")) Module[\"convertU32PairToI53\"] = (() => abort(\"'convertU32PairToI53' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"setImmediateWrapped\")) Module[\"setImmediateWrapped\"] = (() => abort(\"'setImmediateWrapped' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"clearImmediateWrapped\")) Module[\"clearImmediateWrapped\"] = (() => abort(\"'clearImmediateWrapped' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"polyfillSetImmediate\")) Module[\"polyfillSetImmediate\"] = (() => abort(\"'polyfillSetImmediate' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"uncaughtExceptionCount\")) Module[\"uncaughtExceptionCount\"] = (() => abort(\"'uncaughtExceptionCount' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"exceptionLast\")) Module[\"exceptionLast\"] = (() => abort(\"'exceptionLast' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"exceptionCaught\")) Module[\"exceptionCaught\"] = (() => abort(\"'exceptionCaught' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"ExceptionInfo\")) Module[\"ExceptionInfo\"] = (() => abort(\"'ExceptionInfo' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"CatchInfo\")) Module[\"CatchInfo\"] = (() => abort(\"'CatchInfo' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"exception_addRef\")) Module[\"exception_addRef\"] = (() => abort(\"'exception_addRef' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"exception_decRef\")) Module[\"exception_decRef\"] = (() => abort(\"'exception_decRef' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"Browser\")) Module[\"Browser\"] = (() => abort(\"'Browser' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"funcWrappers\")) Module[\"funcWrappers\"] = (() => abort(\"'funcWrappers' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"getFuncWrapper\")) Module[\"getFuncWrapper\"] = (() => abort(\"'getFuncWrapper' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"setMainLoop\")) Module[\"setMainLoop\"] = (() => abort(\"'setMainLoop' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"wget\")) Module[\"wget\"] = (() => abort(\"'wget' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"FS\")) Module[\"FS\"] = (() => abort(\"'FS' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"MEMFS\")) Module[\"MEMFS\"] = (() => abort(\"'MEMFS' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"TTY\")) Module[\"TTY\"] = (() => abort(\"'TTY' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"PIPEFS\")) Module[\"PIPEFS\"] = (() => abort(\"'PIPEFS' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"SOCKFS\")) Module[\"SOCKFS\"] = (() => abort(\"'SOCKFS' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"_setNetworkCallback\")) Module[\"_setNetworkCallback\"] = (() => abort(\"'_setNetworkCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"tempFixedLengthArray\")) Module[\"tempFixedLengthArray\"] = (() => abort(\"'tempFixedLengthArray' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"miniTempWebGLFloatBuffers\")) Module[\"miniTempWebGLFloatBuffers\"] = (() => abort(\"'miniTempWebGLFloatBuffers' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"heapObjectForWebGLType\")) Module[\"heapObjectForWebGLType\"] = (() => abort(\"'heapObjectForWebGLType' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"heapAccessShiftForWebGLHeap\")) Module[\"heapAccessShiftForWebGLHeap\"] = (() => abort(\"'heapAccessShiftForWebGLHeap' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"GL\")) Module[\"GL\"] = (() => abort(\"'GL' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"emscriptenWebGLGet\")) Module[\"emscriptenWebGLGet\"] = (() => abort(\"'emscriptenWebGLGet' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"computeUnpackAlignedImageSize\")) Module[\"computeUnpackAlignedImageSize\"] = (() => abort(\"'computeUnpackAlignedImageSize' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"emscriptenWebGLGetTexPixelData\")) Module[\"emscriptenWebGLGetTexPixelData\"] = (() => abort(\"'emscriptenWebGLGetTexPixelData' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"emscriptenWebGLGetUniform\")) Module[\"emscriptenWebGLGetUniform\"] = (() => abort(\"'emscriptenWebGLGetUniform' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"webglGetUniformLocation\")) Module[\"webglGetUniformLocation\"] = (() => abort(\"'webglGetUniformLocation' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"webglPrepareUniformLocationsBeforeFirstUse\")) Module[\"webglPrepareUniformLocationsBeforeFirstUse\"] = (() => abort(\"'webglPrepareUniformLocationsBeforeFirstUse' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"webglGetLeftBracePos\")) Module[\"webglGetLeftBracePos\"] = (() => abort(\"'webglGetLeftBracePos' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"emscriptenWebGLGetVertexAttrib\")) Module[\"emscriptenWebGLGetVertexAttrib\"] = (() => abort(\"'emscriptenWebGLGetVertexAttrib' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"writeGLArray\")) Module[\"writeGLArray\"] = (() => abort(\"'writeGLArray' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"AL\")) Module[\"AL\"] = (() => abort(\"'AL' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"SDL_unicode\")) Module[\"SDL_unicode\"] = (() => abort(\"'SDL_unicode' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"SDL_ttfContext\")) Module[\"SDL_ttfContext\"] = (() => abort(\"'SDL_ttfContext' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"SDL_audio\")) Module[\"SDL_audio\"] = (() => abort(\"'SDL_audio' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"SDL\")) Module[\"SDL\"] = (() => abort(\"'SDL' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"SDL_gfx\")) Module[\"SDL_gfx\"] = (() => abort(\"'SDL_gfx' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"GLUT\")) Module[\"GLUT\"] = (() => abort(\"'GLUT' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"EGL\")) Module[\"EGL\"] = (() => abort(\"'EGL' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"GLFW_Window\")) Module[\"GLFW_Window\"] = (() => abort(\"'GLFW_Window' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"GLFW\")) Module[\"GLFW\"] = (() => abort(\"'GLFW' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"GLEW\")) Module[\"GLEW\"] = (() => abort(\"'GLEW' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"IDBStore\")) Module[\"IDBStore\"] = (() => abort(\"'IDBStore' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"runAndAbortIfError\")) Module[\"runAndAbortIfError\"] = (() => abort(\"'runAndAbortIfError' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"InternalError\")) Module[\"InternalError\"] = (() => abort(\"'InternalError' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"BindingError\")) Module[\"BindingError\"] = (() => abort(\"'BindingError' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"UnboundTypeError\")) Module[\"UnboundTypeError\"] = (() => abort(\"'UnboundTypeError' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"PureVirtualError\")) Module[\"PureVirtualError\"] = (() => abort(\"'PureVirtualError' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"init_embind\")) Module[\"init_embind\"] = (() => abort(\"'init_embind' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"throwInternalError\")) Module[\"throwInternalError\"] = (() => abort(\"'throwInternalError' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"throwBindingError\")) Module[\"throwBindingError\"] = (() => abort(\"'throwBindingError' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"throwUnboundTypeError\")) Module[\"throwUnboundTypeError\"] = (() => abort(\"'throwUnboundTypeError' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"ensureOverloadTable\")) Module[\"ensureOverloadTable\"] = (() => abort(\"'ensureOverloadTable' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"exposePublicSymbol\")) Module[\"exposePublicSymbol\"] = (() => abort(\"'exposePublicSymbol' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"replacePublicSymbol\")) Module[\"replacePublicSymbol\"] = (() => abort(\"'replacePublicSymbol' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"extendError\")) Module[\"extendError\"] = (() => abort(\"'extendError' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"createNamedFunction\")) Module[\"createNamedFunction\"] = (() => abort(\"'createNamedFunction' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"registeredInstances\")) Module[\"registeredInstances\"] = (() => abort(\"'registeredInstances' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"getBasestPointer\")) Module[\"getBasestPointer\"] = (() => abort(\"'getBasestPointer' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"registerInheritedInstance\")) Module[\"registerInheritedInstance\"] = (() => abort(\"'registerInheritedInstance' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"unregisterInheritedInstance\")) Module[\"unregisterInheritedInstance\"] = (() => abort(\"'unregisterInheritedInstance' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"getInheritedInstance\")) Module[\"getInheritedInstance\"] = (() => abort(\"'getInheritedInstance' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"getInheritedInstanceCount\")) Module[\"getInheritedInstanceCount\"] = (() => abort(\"'getInheritedInstanceCount' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"getLiveInheritedInstances\")) Module[\"getLiveInheritedInstances\"] = (() => abort(\"'getLiveInheritedInstances' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"registeredTypes\")) Module[\"registeredTypes\"] = (() => abort(\"'registeredTypes' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"awaitingDependencies\")) Module[\"awaitingDependencies\"] = (() => abort(\"'awaitingDependencies' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"typeDependencies\")) Module[\"typeDependencies\"] = (() => abort(\"'typeDependencies' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"registeredPointers\")) Module[\"registeredPointers\"] = (() => abort(\"'registeredPointers' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"registerType\")) Module[\"registerType\"] = (() => abort(\"'registerType' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"whenDependentTypesAreResolved\")) Module[\"whenDependentTypesAreResolved\"] = (() => abort(\"'whenDependentTypesAreResolved' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"embind_charCodes\")) Module[\"embind_charCodes\"] = (() => abort(\"'embind_charCodes' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"embind_init_charCodes\")) Module[\"embind_init_charCodes\"] = (() => abort(\"'embind_init_charCodes' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"readLatin1String\")) Module[\"readLatin1String\"] = (() => abort(\"'readLatin1String' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"getTypeName\")) Module[\"getTypeName\"] = (() => abort(\"'getTypeName' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"heap32VectorToArray\")) Module[\"heap32VectorToArray\"] = (() => abort(\"'heap32VectorToArray' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"requireRegisteredType\")) Module[\"requireRegisteredType\"] = (() => abort(\"'requireRegisteredType' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"getShiftFromSize\")) Module[\"getShiftFromSize\"] = (() => abort(\"'getShiftFromSize' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"integerReadValueFromPointer\")) Module[\"integerReadValueFromPointer\"] = (() => abort(\"'integerReadValueFromPointer' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"enumReadValueFromPointer\")) Module[\"enumReadValueFromPointer\"] = (() => abort(\"'enumReadValueFromPointer' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"floatReadValueFromPointer\")) Module[\"floatReadValueFromPointer\"] = (() => abort(\"'floatReadValueFromPointer' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"simpleReadValueFromPointer\")) Module[\"simpleReadValueFromPointer\"] = (() => abort(\"'simpleReadValueFromPointer' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"runDestructors\")) Module[\"runDestructors\"] = (() => abort(\"'runDestructors' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"new_\")) Module[\"new_\"] = (() => abort(\"'new_' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"craftInvokerFunction\")) Module[\"craftInvokerFunction\"] = (() => abort(\"'craftInvokerFunction' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"embind__requireFunction\")) Module[\"embind__requireFunction\"] = (() => abort(\"'embind__requireFunction' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"tupleRegistrations\")) Module[\"tupleRegistrations\"] = (() => abort(\"'tupleRegistrations' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"structRegistrations\")) Module[\"structRegistrations\"] = (() => abort(\"'structRegistrations' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"genericPointerToWireType\")) Module[\"genericPointerToWireType\"] = (() => abort(\"'genericPointerToWireType' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"constNoSmartPtrRawPointerToWireType\")) Module[\"constNoSmartPtrRawPointerToWireType\"] = (() => abort(\"'constNoSmartPtrRawPointerToWireType' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"nonConstNoSmartPtrRawPointerToWireType\")) Module[\"nonConstNoSmartPtrRawPointerToWireType\"] = (() => abort(\"'nonConstNoSmartPtrRawPointerToWireType' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"init_RegisteredPointer\")) Module[\"init_RegisteredPointer\"] = (() => abort(\"'init_RegisteredPointer' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"RegisteredPointer\")) Module[\"RegisteredPointer\"] = (() => abort(\"'RegisteredPointer' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"RegisteredPointer_getPointee\")) Module[\"RegisteredPointer_getPointee\"] = (() => abort(\"'RegisteredPointer_getPointee' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"RegisteredPointer_destructor\")) Module[\"RegisteredPointer_destructor\"] = (() => abort(\"'RegisteredPointer_destructor' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"RegisteredPointer_deleteObject\")) Module[\"RegisteredPointer_deleteObject\"] = (() => abort(\"'RegisteredPointer_deleteObject' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"RegisteredPointer_fromWireType\")) Module[\"RegisteredPointer_fromWireType\"] = (() => abort(\"'RegisteredPointer_fromWireType' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"runDestructor\")) Module[\"runDestructor\"] = (() => abort(\"'runDestructor' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"releaseClassHandle\")) Module[\"releaseClassHandle\"] = (() => abort(\"'releaseClassHandle' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"finalizationRegistry\")) Module[\"finalizationRegistry\"] = (() => abort(\"'finalizationRegistry' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"detachFinalizer_deps\")) Module[\"detachFinalizer_deps\"] = (() => abort(\"'detachFinalizer_deps' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"detachFinalizer\")) Module[\"detachFinalizer\"] = (() => abort(\"'detachFinalizer' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"attachFinalizer\")) Module[\"attachFinalizer\"] = (() => abort(\"'attachFinalizer' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"makeClassHandle\")) Module[\"makeClassHandle\"] = (() => abort(\"'makeClassHandle' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"init_ClassHandle\")) Module[\"init_ClassHandle\"] = (() => abort(\"'init_ClassHandle' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"ClassHandle\")) Module[\"ClassHandle\"] = (() => abort(\"'ClassHandle' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"ClassHandle_isAliasOf\")) Module[\"ClassHandle_isAliasOf\"] = (() => abort(\"'ClassHandle_isAliasOf' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"throwInstanceAlreadyDeleted\")) Module[\"throwInstanceAlreadyDeleted\"] = (() => abort(\"'throwInstanceAlreadyDeleted' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"ClassHandle_clone\")) Module[\"ClassHandle_clone\"] = (() => abort(\"'ClassHandle_clone' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"ClassHandle_delete\")) Module[\"ClassHandle_delete\"] = (() => abort(\"'ClassHandle_delete' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"deletionQueue\")) Module[\"deletionQueue\"] = (() => abort(\"'deletionQueue' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"ClassHandle_isDeleted\")) Module[\"ClassHandle_isDeleted\"] = (() => abort(\"'ClassHandle_isDeleted' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"ClassHandle_deleteLater\")) Module[\"ClassHandle_deleteLater\"] = (() => abort(\"'ClassHandle_deleteLater' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"flushPendingDeletes\")) Module[\"flushPendingDeletes\"] = (() => abort(\"'flushPendingDeletes' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"delayFunction\")) Module[\"delayFunction\"] = (() => abort(\"'delayFunction' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"setDelayFunction\")) Module[\"setDelayFunction\"] = (() => abort(\"'setDelayFunction' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"RegisteredClass\")) Module[\"RegisteredClass\"] = (() => abort(\"'RegisteredClass' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"shallowCopyInternalPointer\")) Module[\"shallowCopyInternalPointer\"] = (() => abort(\"'shallowCopyInternalPointer' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"downcastPointer\")) Module[\"downcastPointer\"] = (() => abort(\"'downcastPointer' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"upcastPointer\")) Module[\"upcastPointer\"] = (() => abort(\"'upcastPointer' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"validateThis\")) Module[\"validateThis\"] = (() => abort(\"'validateThis' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"char_0\")) Module[\"char_0\"] = (() => abort(\"'char_0' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"char_9\")) Module[\"char_9\"] = (() => abort(\"'char_9' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"makeLegalFunctionName\")) Module[\"makeLegalFunctionName\"] = (() => abort(\"'makeLegalFunctionName' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"emval_handle_array\")) Module[\"emval_handle_array\"] = (() => abort(\"'emval_handle_array' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"emval_free_list\")) Module[\"emval_free_list\"] = (() => abort(\"'emval_free_list' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"emval_symbols\")) Module[\"emval_symbols\"] = (() => abort(\"'emval_symbols' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"init_emval\")) Module[\"init_emval\"] = (() => abort(\"'init_emval' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"count_emval_handles\")) Module[\"count_emval_handles\"] = (() => abort(\"'count_emval_handles' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"get_first_emval\")) Module[\"get_first_emval\"] = (() => abort(\"'get_first_emval' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"getStringOrSymbol\")) Module[\"getStringOrSymbol\"] = (() => abort(\"'getStringOrSymbol' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"Emval\")) Module[\"Emval\"] = (() => abort(\"'Emval' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"emval_newers\")) Module[\"emval_newers\"] = (() => abort(\"'emval_newers' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"craftEmvalAllocator\")) Module[\"craftEmvalAllocator\"] = (() => abort(\"'craftEmvalAllocator' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"emval_get_global\")) Module[\"emval_get_global\"] = (() => abort(\"'emval_get_global' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"emval_methodCallers\")) Module[\"emval_methodCallers\"] = (() => abort(\"'emval_methodCallers' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"emval_registeredMethods\")) Module[\"emval_registeredMethods\"] = (() => abort(\"'emval_registeredMethods' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"warnOnce\")) Module[\"warnOnce\"] = (() => abort(\"'warnOnce' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"stackSave\")) Module[\"stackSave\"] = (() => abort(\"'stackSave' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"stackRestore\")) Module[\"stackRestore\"] = (() => abort(\"'stackRestore' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"stackAlloc\")) Module[\"stackAlloc\"] = (() => abort(\"'stackAlloc' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"AsciiToString\")) Module[\"AsciiToString\"] = (() => abort(\"'AsciiToString' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"stringToAscii\")) Module[\"stringToAscii\"] = (() => abort(\"'stringToAscii' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"UTF16ToString\")) Module[\"UTF16ToString\"] = (() => abort(\"'UTF16ToString' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"stringToUTF16\")) Module[\"stringToUTF16\"] = (() => abort(\"'stringToUTF16' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"lengthBytesUTF16\")) Module[\"lengthBytesUTF16\"] = (() => abort(\"'lengthBytesUTF16' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"UTF32ToString\")) Module[\"UTF32ToString\"] = (() => abort(\"'UTF32ToString' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"stringToUTF32\")) Module[\"stringToUTF32\"] = (() => abort(\"'stringToUTF32' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"lengthBytesUTF32\")) Module[\"lengthBytesUTF32\"] = (() => abort(\"'lengthBytesUTF32' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"allocateUTF8\")) Module[\"allocateUTF8\"] = (() => abort(\"'allocateUTF8' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nif (!Object.getOwnPropertyDescriptor(Module, \"allocateUTF8OnStack\")) Module[\"allocateUTF8OnStack\"] = (() => abort(\"'allocateUTF8OnStack' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\n\nModule[\"writeStackCookie\"] = writeStackCookie;\n\nModule[\"checkStackCookie\"] = checkStackCookie;\n\nif (!Object.getOwnPropertyDescriptor(Module, \"ALLOC_NORMAL\")) Object.defineProperty(Module, \"ALLOC_NORMAL\", {\n configurable: true,\n get: function() {\n abort(\"'ALLOC_NORMAL' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\");\n }\n});\n\nif (!Object.getOwnPropertyDescriptor(Module, \"ALLOC_STACK\")) Object.defineProperty(Module, \"ALLOC_STACK\", {\n configurable: true,\n get: function() {\n abort(\"'ALLOC_STACK' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\");\n }\n});\n\nvar calledRun;\n\nfunction ExitStatus(status) {\n this.name = \"ExitStatus\";\n this.message = \"Program terminated with exit(\" + status + \")\";\n this.status = status;\n}\n\ndependenciesFulfilled = function runCaller() {\n if (!calledRun) run();\n if (!calledRun) dependenciesFulfilled = runCaller;\n};\n\nfunction stackCheckInit() {\n _emscripten_stack_init();\n writeStackCookie();\n}\n\nfunction run(args) {\n args = args || arguments_;\n if (runDependencies > 0) {\n return;\n }\n stackCheckInit();\n preRun();\n if (runDependencies > 0) {\n return;\n }\n function doRun() {\n if (calledRun) return;\n calledRun = true;\n Module[\"calledRun\"] = true;\n if (ABORT) return;\n initRuntime();\n readyPromiseResolve(Module);\n if (Module[\"onRuntimeInitialized\"]) Module[\"onRuntimeInitialized\"]();\n assert(!Module[\"_main\"], 'compiled without a main, but one is present. if you added it from JS, use Module[\"onRuntimeInitialized\"]');\n postRun();\n }\n if (Module[\"setStatus\"]) {\n Module[\"setStatus\"](\"Running...\");\n setTimeout(function() {\n setTimeout(function() {\n Module[\"setStatus\"](\"\");\n }, 1);\n doRun();\n }, 1);\n } else {\n doRun();\n }\n checkStackCookie();\n}\n\nModule[\"run\"] = run;\n\nfunction procExit(code) {\n EXITSTATUS = code;\n if (!keepRuntimeAlive()) {\n if (Module[\"onExit\"]) Module[\"onExit\"](code);\n ABORT = true;\n }\n quit_(code, new ExitStatus(code));\n}\n\nif (Module[\"preInit\"]) {\n if (typeof Module[\"preInit\"] == \"function\") Module[\"preInit\"] = [ Module[\"preInit\"] ];\n while (Module[\"preInit\"].length > 0) {\n Module[\"preInit\"].pop()();\n }\n}\n\nrun();\n\n\n return createMLSGenModule.ready\n}\n);\n})();\nif (true)\n module.exports = createMLSGenModule;\nelse {}\n\n\n//# sourceURL=webpack://speakerCalibrator/./dist/mlsGen.js?");
|
|
28
|
+
eval("\r\nvar createMLSGenModule = (() => {\r\n var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined;\r\n \r\n return (\r\nfunction(createMLSGenModule) {\r\n createMLSGenModule = createMLSGenModule || {};\r\n\r\nvar Module = typeof createMLSGenModule !== \"undefined\" ? createMLSGenModule : {};\r\n\r\nvar readyPromiseResolve, readyPromiseReject;\r\n\r\nModule[\"ready\"] = new Promise(function(resolve, reject) {\r\n readyPromiseResolve = resolve;\r\n readyPromiseReject = reject;\r\n});\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module[\"ready\"], \"_main\")) {\r\n Object.defineProperty(Module[\"ready\"], \"_main\", {\r\n configurable: true,\r\n get: function() {\r\n abort(\"You are getting _main on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js\");\r\n }\r\n });\r\n Object.defineProperty(Module[\"ready\"], \"_main\", {\r\n configurable: true,\r\n set: function() {\r\n abort(\"You are setting _main on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js\");\r\n }\r\n });\r\n}\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module[\"ready\"], \"___getTypeName\")) {\r\n Object.defineProperty(Module[\"ready\"], \"___getTypeName\", {\r\n configurable: true,\r\n get: function() {\r\n abort(\"You are getting ___getTypeName on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js\");\r\n }\r\n });\r\n Object.defineProperty(Module[\"ready\"], \"___getTypeName\", {\r\n configurable: true,\r\n set: function() {\r\n abort(\"You are setting ___getTypeName on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js\");\r\n }\r\n });\r\n}\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module[\"ready\"], \"___embind_register_native_and_builtin_types\")) {\r\n Object.defineProperty(Module[\"ready\"], \"___embind_register_native_and_builtin_types\", {\r\n configurable: true,\r\n get: function() {\r\n abort(\"You are getting ___embind_register_native_and_builtin_types on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js\");\r\n }\r\n });\r\n Object.defineProperty(Module[\"ready\"], \"___embind_register_native_and_builtin_types\", {\r\n configurable: true,\r\n set: function() {\r\n abort(\"You are setting ___embind_register_native_and_builtin_types on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js\");\r\n }\r\n });\r\n}\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module[\"ready\"], \"___stdio_exit\")) {\r\n Object.defineProperty(Module[\"ready\"], \"___stdio_exit\", {\r\n configurable: true,\r\n get: function() {\r\n abort(\"You are getting ___stdio_exit on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js\");\r\n }\r\n });\r\n Object.defineProperty(Module[\"ready\"], \"___stdio_exit\", {\r\n configurable: true,\r\n set: function() {\r\n abort(\"You are setting ___stdio_exit on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js\");\r\n }\r\n });\r\n}\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module[\"ready\"], \"__ZN6__asan9FakeStack17AddrIsInFakeStackEm\")) {\r\n Object.defineProperty(Module[\"ready\"], \"__ZN6__asan9FakeStack17AddrIsInFakeStackEm\", {\r\n configurable: true,\r\n get: function() {\r\n abort(\"You are getting __ZN6__asan9FakeStack17AddrIsInFakeStackEm on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js\");\r\n }\r\n });\r\n Object.defineProperty(Module[\"ready\"], \"__ZN6__asan9FakeStack17AddrIsInFakeStackEm\", {\r\n configurable: true,\r\n set: function() {\r\n abort(\"You are setting __ZN6__asan9FakeStack17AddrIsInFakeStackEm on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js\");\r\n }\r\n });\r\n}\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module[\"ready\"], \"__ZN6__asan9FakeStack8AllocateEmmm\")) {\r\n Object.defineProperty(Module[\"ready\"], \"__ZN6__asan9FakeStack8AllocateEmmm\", {\r\n configurable: true,\r\n get: function() {\r\n abort(\"You are getting __ZN6__asan9FakeStack8AllocateEmmm on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js\");\r\n }\r\n });\r\n Object.defineProperty(Module[\"ready\"], \"__ZN6__asan9FakeStack8AllocateEmmm\", {\r\n configurable: true,\r\n set: function() {\r\n abort(\"You are setting __ZN6__asan9FakeStack8AllocateEmmm on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js\");\r\n }\r\n });\r\n}\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module[\"ready\"], \"onRuntimeInitialized\")) {\r\n Object.defineProperty(Module[\"ready\"], \"onRuntimeInitialized\", {\r\n configurable: true,\r\n get: function() {\r\n abort(\"You are getting onRuntimeInitialized on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js\");\r\n }\r\n });\r\n Object.defineProperty(Module[\"ready\"], \"onRuntimeInitialized\", {\r\n configurable: true,\r\n set: function() {\r\n abort(\"You are setting onRuntimeInitialized on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js\");\r\n }\r\n });\r\n}\r\n\r\nvar moduleOverrides = Object.assign({}, Module);\r\n\r\nvar arguments_ = [];\r\n\r\nvar thisProgram = \"./this.program\";\r\n\r\nvar quit_ = (status, toThrow) => {\r\n throw toThrow;\r\n};\r\n\r\nvar ENVIRONMENT_IS_WEB = true;\r\n\r\nvar ENVIRONMENT_IS_WORKER = false;\r\n\r\nvar ENVIRONMENT_IS_NODE = false;\r\n\r\nvar ENVIRONMENT_IS_SHELL = false;\r\n\r\nif (Module[\"ENVIRONMENT\"]) {\r\n throw new Error(\"Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -s ENVIRONMENT=web or -s ENVIRONMENT=node)\");\r\n}\r\n\r\nvar scriptDirectory = \"\";\r\n\r\nfunction locateFile(path) {\r\n if (Module[\"locateFile\"]) {\r\n return Module[\"locateFile\"](path, scriptDirectory);\r\n }\r\n return scriptDirectory + path;\r\n}\r\n\r\nvar read_, readAsync, readBinary, setWindowTitle;\r\n\r\nfunction logExceptionOnExit(e) {\r\n if (e instanceof ExitStatus) return;\r\n let toLog = e;\r\n if (e && typeof e === \"object\" && e.stack) {\r\n toLog = [ e, e.stack ];\r\n }\r\n err(\"exiting due to exception: \" + toLog);\r\n}\r\n\r\nif (ENVIRONMENT_IS_SHELL) {\r\n if (typeof process === \"object\" && \"function\" === \"function\" || typeof window === \"object\" || typeof importScripts === \"function\") throw new Error(\"not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)\");\r\n if (typeof read != \"undefined\") {\r\n read_ = function shell_read(f) {\r\n return read(f);\r\n };\r\n }\r\n readBinary = function readBinary(f) {\r\n let data;\r\n if (typeof readbuffer === \"function\") {\r\n return new Uint8Array(readbuffer(f));\r\n }\r\n data = read(f, \"binary\");\r\n assert(typeof data === \"object\");\r\n return data;\r\n };\r\n readAsync = function readAsync(f, onload, onerror) {\r\n setTimeout(() => onload(readBinary(f)), 0);\r\n };\r\n if (typeof scriptArgs != \"undefined\") {\r\n arguments_ = scriptArgs;\r\n } else if (typeof arguments != \"undefined\") {\r\n arguments_ = arguments;\r\n }\r\n if (typeof quit === \"function\") {\r\n quit_ = ((status, toThrow) => {\r\n logExceptionOnExit(toThrow);\r\n quit(status);\r\n });\r\n }\r\n if (typeof print !== \"undefined\") {\r\n if (typeof console === \"undefined\") console = {};\r\n console.log = print;\r\n console.warn = console.error = typeof printErr !== \"undefined\" ? printErr : print;\r\n }\r\n} else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {\r\n if (ENVIRONMENT_IS_WORKER) {\r\n scriptDirectory = self.location.href;\r\n } else if (typeof document !== \"undefined\" && document.currentScript) {\r\n scriptDirectory = document.currentScript.src;\r\n }\r\n if (_scriptDir) {\r\n scriptDirectory = _scriptDir;\r\n }\r\n if (scriptDirectory.indexOf(\"blob:\") !== 0) {\r\n scriptDirectory = scriptDirectory.substr(0, scriptDirectory.replace(/[?#].*/, \"\").lastIndexOf(\"/\") + 1);\r\n } else {\r\n scriptDirectory = \"\";\r\n }\r\n if (!(typeof window === \"object\" || typeof importScripts === \"function\")) throw new Error(\"not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)\");\r\n {\r\n read_ = (url => {\r\n var xhr = new XMLHttpRequest();\r\n xhr.open(\"GET\", url, false);\r\n xhr.send(null);\r\n return xhr.responseText;\r\n });\r\n if (ENVIRONMENT_IS_WORKER) {\r\n readBinary = (url => {\r\n var xhr = new XMLHttpRequest();\r\n xhr.open(\"GET\", url, false);\r\n xhr.responseType = \"arraybuffer\";\r\n xhr.send(null);\r\n return new Uint8Array(xhr.response);\r\n });\r\n }\r\n readAsync = ((url, onload, onerror) => {\r\n var xhr = new XMLHttpRequest();\r\n xhr.open(\"GET\", url, true);\r\n xhr.responseType = \"arraybuffer\";\r\n xhr.onload = (() => {\r\n if (xhr.status == 200 || xhr.status == 0 && xhr.response) {\r\n onload(xhr.response);\r\n return;\r\n }\r\n onerror();\r\n });\r\n xhr.onerror = onerror;\r\n xhr.send(null);\r\n });\r\n }\r\n setWindowTitle = (title => document.title = title);\r\n} else {\r\n throw new Error(\"environment detection error\");\r\n}\r\n\r\nvar out = Module[\"print\"] || console.log.bind(console);\r\n\r\nvar err = Module[\"printErr\"] || console.warn.bind(console);\r\n\r\nObject.assign(Module, moduleOverrides);\r\n\r\nmoduleOverrides = null;\r\n\r\nif (Module[\"arguments\"]) arguments_ = Module[\"arguments\"];\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"arguments\")) {\r\n Object.defineProperty(Module, \"arguments\", {\r\n configurable: true,\r\n get: function() {\r\n abort(\"Module.arguments has been replaced with plain arguments_ (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)\");\r\n }\r\n });\r\n}\r\n\r\nif (Module[\"thisProgram\"]) thisProgram = Module[\"thisProgram\"];\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"thisProgram\")) {\r\n Object.defineProperty(Module, \"thisProgram\", {\r\n configurable: true,\r\n get: function() {\r\n abort(\"Module.thisProgram has been replaced with plain thisProgram (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)\");\r\n }\r\n });\r\n}\r\n\r\nif (Module[\"quit\"]) quit_ = Module[\"quit\"];\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"quit\")) {\r\n Object.defineProperty(Module, \"quit\", {\r\n configurable: true,\r\n get: function() {\r\n abort(\"Module.quit has been replaced with plain quit_ (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)\");\r\n }\r\n });\r\n}\r\n\r\nassert(typeof Module[\"memoryInitializerPrefixURL\"] === \"undefined\", \"Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead\");\r\n\r\nassert(typeof Module[\"pthreadMainPrefixURL\"] === \"undefined\", \"Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead\");\r\n\r\nassert(typeof Module[\"cdInitializerPrefixURL\"] === \"undefined\", \"Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead\");\r\n\r\nassert(typeof Module[\"filePackagePrefixURL\"] === \"undefined\", \"Module.filePackagePrefixURL option was removed, use Module.locateFile instead\");\r\n\r\nassert(typeof Module[\"read\"] === \"undefined\", \"Module.read option was removed (modify read_ in JS)\");\r\n\r\nassert(typeof Module[\"readAsync\"] === \"undefined\", \"Module.readAsync option was removed (modify readAsync in JS)\");\r\n\r\nassert(typeof Module[\"readBinary\"] === \"undefined\", \"Module.readBinary option was removed (modify readBinary in JS)\");\r\n\r\nassert(typeof Module[\"setWindowTitle\"] === \"undefined\", \"Module.setWindowTitle option was removed (modify setWindowTitle in JS)\");\r\n\r\nassert(typeof Module[\"TOTAL_MEMORY\"] === \"undefined\", \"Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY\");\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"read\")) {\r\n Object.defineProperty(Module, \"read\", {\r\n configurable: true,\r\n get: function() {\r\n abort(\"Module.read has been replaced with plain read_ (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)\");\r\n }\r\n });\r\n}\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"readAsync\")) {\r\n Object.defineProperty(Module, \"readAsync\", {\r\n configurable: true,\r\n get: function() {\r\n abort(\"Module.readAsync has been replaced with plain readAsync (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)\");\r\n }\r\n });\r\n}\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"readBinary\")) {\r\n Object.defineProperty(Module, \"readBinary\", {\r\n configurable: true,\r\n get: function() {\r\n abort(\"Module.readBinary has been replaced with plain readBinary (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)\");\r\n }\r\n });\r\n}\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"setWindowTitle\")) {\r\n Object.defineProperty(Module, \"setWindowTitle\", {\r\n configurable: true,\r\n get: function() {\r\n abort(\"Module.setWindowTitle has been replaced with plain setWindowTitle (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)\");\r\n }\r\n });\r\n}\r\n\r\nassert(!ENVIRONMENT_IS_WORKER, \"worker environment detected but not enabled at build time. Add 'worker' to `-s ENVIRONMENT` to enable.\");\r\n\r\nassert(!ENVIRONMENT_IS_NODE, \"node environment detected but not enabled at build time. Add 'node' to `-s ENVIRONMENT` to enable.\");\r\n\r\nassert(!ENVIRONMENT_IS_SHELL, \"shell environment detected but not enabled at build time. Add 'shell' to `-s ENVIRONMENT` to enable.\");\r\n\r\nvar POINTER_SIZE = 4;\r\n\r\nfunction warnOnce(text) {\r\n if (!warnOnce.shown) warnOnce.shown = {};\r\n if (!warnOnce.shown[text]) {\r\n warnOnce.shown[text] = 1;\r\n err(text);\r\n }\r\n}\r\n\r\nfunction convertJsFunctionToWasm(func, sig) {\r\n if (typeof WebAssembly.Function === \"function\") {\r\n var typeNames = {\r\n \"i\": \"i32\",\r\n \"j\": \"i64\",\r\n \"f\": \"f32\",\r\n \"d\": \"f64\"\r\n };\r\n var type = {\r\n parameters: [],\r\n results: sig[0] == \"v\" ? [] : [ typeNames[sig[0]] ]\r\n };\r\n for (var i = 1; i < sig.length; ++i) {\r\n type.parameters.push(typeNames[sig[i]]);\r\n }\r\n return new WebAssembly.Function(type, func);\r\n }\r\n var typeSection = [ 1, 0, 1, 96 ];\r\n var sigRet = sig.slice(0, 1);\r\n var sigParam = sig.slice(1);\r\n var typeCodes = {\r\n \"i\": 127,\r\n \"j\": 126,\r\n \"f\": 125,\r\n \"d\": 124\r\n };\r\n typeSection.push(sigParam.length);\r\n for (var i = 0; i < sigParam.length; ++i) {\r\n typeSection.push(typeCodes[sigParam[i]]);\r\n }\r\n if (sigRet == \"v\") {\r\n typeSection.push(0);\r\n } else {\r\n typeSection = typeSection.concat([ 1, typeCodes[sigRet] ]);\r\n }\r\n typeSection[1] = typeSection.length - 2;\r\n var bytes = new Uint8Array([ 0, 97, 115, 109, 1, 0, 0, 0 ].concat(typeSection, [ 2, 7, 1, 1, 101, 1, 102, 0, 0, 7, 5, 1, 1, 102, 0, 0 ]));\r\n var module = new WebAssembly.Module(bytes);\r\n var instance = new WebAssembly.Instance(module, {\r\n \"e\": {\r\n \"f\": func\r\n }\r\n });\r\n var wrappedFunc = instance.exports[\"f\"];\r\n return wrappedFunc;\r\n}\r\n\r\nvar freeTableIndexes = [];\r\n\r\nvar functionsInTableMap;\r\n\r\nfunction getEmptyTableSlot() {\r\n if (freeTableIndexes.length) {\r\n return freeTableIndexes.pop();\r\n }\r\n try {\r\n wasmTable.grow(1);\r\n } catch (err) {\r\n if (!(err instanceof RangeError)) {\r\n throw err;\r\n }\r\n throw \"Unable to grow wasm table. Set ALLOW_TABLE_GROWTH.\";\r\n }\r\n return wasmTable.length - 1;\r\n}\r\n\r\nfunction updateTableMap(offset, count) {\r\n for (var i = offset; i < offset + count; i++) {\r\n var item = getWasmTableEntry(i);\r\n if (item) {\r\n functionsInTableMap.set(item, i);\r\n }\r\n }\r\n}\r\n\r\nvar tempRet0 = 0;\r\n\r\nvar setTempRet0 = value => {\r\n tempRet0 = value;\r\n};\r\n\r\nvar wasmBinary;\r\n\r\nif (Module[\"wasmBinary\"]) wasmBinary = Module[\"wasmBinary\"];\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"wasmBinary\")) {\r\n Object.defineProperty(Module, \"wasmBinary\", {\r\n configurable: true,\r\n get: function() {\r\n abort(\"Module.wasmBinary has been replaced with plain wasmBinary (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)\");\r\n }\r\n });\r\n}\r\n\r\nvar noExitRuntime = Module[\"noExitRuntime\"] || false;\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"noExitRuntime\")) {\r\n Object.defineProperty(Module, \"noExitRuntime\", {\r\n configurable: true,\r\n get: function() {\r\n abort(\"Module.noExitRuntime has been replaced with plain noExitRuntime (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)\");\r\n }\r\n });\r\n}\r\n\r\nif (typeof WebAssembly !== \"object\") {\r\n abort(\"no native wasm support detected\");\r\n}\r\n\r\nfunction _asan_js_load_1(ptr) {\r\n if (runtimeInitialized) return _asan_c_load_1(ptr);\r\n return HEAP8[ptr];\r\n}\r\n\r\nfunction _asan_js_load_1u(ptr) {\r\n if (runtimeInitialized) return _asan_c_load_1u(ptr);\r\n return HEAPU8[ptr];\r\n}\r\n\r\nfunction _asan_js_load_2(ptr) {\r\n if (runtimeInitialized) return _asan_c_load_2(ptr);\r\n return HEAP16[ptr];\r\n}\r\n\r\nfunction _asan_js_load_2u(ptr) {\r\n if (runtimeInitialized) return _asan_c_load_2u(ptr);\r\n return HEAPU16[ptr];\r\n}\r\n\r\nfunction _asan_js_load_4(ptr) {\r\n if (runtimeInitialized) return _asan_c_load_4(ptr);\r\n return HEAP32[ptr];\r\n}\r\n\r\nfunction _asan_js_load_4u(ptr) {\r\n if (runtimeInitialized) return _asan_c_load_4u(ptr) >>> 0;\r\n return HEAPU32[ptr];\r\n}\r\n\r\nfunction _asan_js_load_f(ptr) {\r\n if (runtimeInitialized) return _asan_c_load_f(ptr);\r\n return HEAPF32[ptr];\r\n}\r\n\r\nfunction _asan_js_load_d(ptr) {\r\n if (runtimeInitialized) return _asan_c_load_d(ptr);\r\n return HEAPF64[ptr];\r\n}\r\n\r\nfunction _asan_js_store_1(ptr, val) {\r\n if (runtimeInitialized) return _asan_c_store_1(ptr, val);\r\n return HEAP8[ptr] = val;\r\n}\r\n\r\nfunction _asan_js_store_1u(ptr, val) {\r\n if (runtimeInitialized) return _asan_c_store_1u(ptr, val);\r\n return HEAPU8[ptr] = val;\r\n}\r\n\r\nfunction _asan_js_store_2(ptr, val) {\r\n if (runtimeInitialized) return _asan_c_store_2(ptr, val);\r\n return HEAP16[ptr] = val;\r\n}\r\n\r\nfunction _asan_js_store_4(ptr, val) {\r\n if (runtimeInitialized) return _asan_c_store_4(ptr, val);\r\n return HEAP32[ptr] = val;\r\n}\r\n\r\nfunction _asan_js_store_4u(ptr, val) {\r\n if (runtimeInitialized) return _asan_c_store_4u(ptr, val) >>> 0;\r\n return HEAPU32[ptr] = val;\r\n}\r\n\r\nfunction _asan_js_store_f(ptr, val) {\r\n if (runtimeInitialized) return _asan_c_store_f(ptr, val);\r\n return HEAPF32[ptr] = val;\r\n}\r\n\r\nfunction _asan_js_store_d(ptr, val) {\r\n if (runtimeInitialized) return _asan_c_store_d(ptr, val);\r\n return HEAPF64[ptr] = val;\r\n}\r\n\r\nvar wasmMemory;\r\n\r\nvar ABORT = false;\r\n\r\nvar EXITSTATUS;\r\n\r\nfunction assert(condition, text) {\r\n if (!condition) {\r\n abort(\"Assertion failed\" + (text ? \": \" + text : \"\"));\r\n }\r\n}\r\n\r\nfunction getCFunc(ident) {\r\n var func = Module[\"_\" + ident];\r\n assert(func, \"Cannot call unknown function \" + ident + \", make sure it is exported\");\r\n return func;\r\n}\r\n\r\nfunction ccall(ident, returnType, argTypes, args, opts) {\r\n var toC = {\r\n \"string\": function(str) {\r\n var ret = 0;\r\n if (str !== null && str !== undefined && str !== 0) {\r\n var len = (str.length << 2) + 1;\r\n ret = stackAlloc(len);\r\n stringToUTF8(str, ret, len);\r\n }\r\n return ret;\r\n },\r\n \"array\": function(arr) {\r\n var ret = stackAlloc(arr.length);\r\n writeArrayToMemory(arr, ret);\r\n return ret;\r\n }\r\n };\r\n function convertReturnValue(ret) {\r\n if (returnType === \"string\") return UTF8ToString(ret);\r\n if (returnType === \"boolean\") return Boolean(ret);\r\n return ret;\r\n }\r\n var func = getCFunc(ident);\r\n var cArgs = [];\r\n var stack = 0;\r\n assert(returnType !== \"array\", 'Return type should not be \"array\".');\r\n if (args) {\r\n for (var i = 0; i < args.length; i++) {\r\n var converter = toC[argTypes[i]];\r\n if (converter) {\r\n if (stack === 0) stack = stackSave();\r\n cArgs[i] = converter(args[i]);\r\n } else {\r\n cArgs[i] = args[i];\r\n }\r\n }\r\n }\r\n var ret = func.apply(null, cArgs);\r\n function onDone(ret) {\r\n if (stack !== 0) stackRestore(stack);\r\n return convertReturnValue(ret);\r\n }\r\n ret = onDone(ret);\r\n return ret;\r\n}\r\n\r\nvar ALLOC_STACK = 1;\r\n\r\nvar UTF8Decoder = typeof TextDecoder !== \"undefined\" ? new TextDecoder(\"utf8\") : undefined;\r\n\r\nfunction UTF8ArrayToString(heap, idx, maxBytesToRead) {\r\n var endIdx = idx + maxBytesToRead;\r\n var endPtr = idx;\r\n while (heap[endPtr] && !(endPtr >= endIdx)) ++endPtr;\r\n if (endPtr - idx > 16 && heap.subarray && UTF8Decoder) {\r\n return UTF8Decoder.decode(heap.subarray(idx, endPtr));\r\n } else {\r\n var str = \"\";\r\n while (idx < endPtr) {\r\n var u0 = heap[idx++];\r\n if (!(u0 & 128)) {\r\n str += String.fromCharCode(u0);\r\n continue;\r\n }\r\n var u1 = heap[idx++] & 63;\r\n if ((u0 & 224) == 192) {\r\n str += String.fromCharCode((u0 & 31) << 6 | u1);\r\n continue;\r\n }\r\n var u2 = heap[idx++] & 63;\r\n if ((u0 & 240) == 224) {\r\n u0 = (u0 & 15) << 12 | u1 << 6 | u2;\r\n } else {\r\n if ((u0 & 248) != 240) warnOnce(\"Invalid UTF-8 leading byte 0x\" + u0.toString(16) + \" encountered when deserializing a UTF-8 string in wasm memory to a JS string!\");\r\n u0 = (u0 & 7) << 18 | u1 << 12 | u2 << 6 | heap[idx++] & 63;\r\n }\r\n if (u0 < 65536) {\r\n str += String.fromCharCode(u0);\r\n } else {\r\n var ch = u0 - 65536;\r\n str += String.fromCharCode(55296 | ch >> 10, 56320 | ch & 1023);\r\n }\r\n }\r\n }\r\n return str;\r\n}\r\n\r\nfunction UTF8ToString(ptr, maxBytesToRead) {\r\n return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : \"\";\r\n}\r\n\r\nfunction stringToUTF8Array(str, heap, outIdx, maxBytesToWrite) {\r\n if (!(maxBytesToWrite > 0)) return 0;\r\n var startIdx = outIdx;\r\n var endIdx = outIdx + maxBytesToWrite - 1;\r\n for (var i = 0; i < str.length; ++i) {\r\n var u = str.charCodeAt(i);\r\n if (u >= 55296 && u <= 57343) {\r\n var u1 = str.charCodeAt(++i);\r\n u = 65536 + ((u & 1023) << 10) | u1 & 1023;\r\n }\r\n if (u <= 127) {\r\n if (outIdx >= endIdx) break;\r\n heap[outIdx++] = u;\r\n } else if (u <= 2047) {\r\n if (outIdx + 1 >= endIdx) break;\r\n heap[outIdx++] = 192 | u >> 6;\r\n heap[outIdx++] = 128 | u & 63;\r\n } else if (u <= 65535) {\r\n if (outIdx + 2 >= endIdx) break;\r\n heap[outIdx++] = 224 | u >> 12;\r\n heap[outIdx++] = 128 | u >> 6 & 63;\r\n heap[outIdx++] = 128 | u & 63;\r\n } else {\r\n if (outIdx + 3 >= endIdx) break;\r\n if (u > 1114111) warnOnce(\"Invalid Unicode code point 0x\" + u.toString(16) + \" encountered when serializing a JS string to a UTF-8 string in wasm memory! (Valid unicode code points should be in range 0-0x10FFFF).\");\r\n heap[outIdx++] = 240 | u >> 18;\r\n heap[outIdx++] = 128 | u >> 12 & 63;\r\n heap[outIdx++] = 128 | u >> 6 & 63;\r\n heap[outIdx++] = 128 | u & 63;\r\n }\r\n }\r\n heap[outIdx] = 0;\r\n return outIdx - startIdx;\r\n}\r\n\r\nfunction stringToUTF8(str, outPtr, maxBytesToWrite) {\r\n assert(typeof maxBytesToWrite == \"number\", \"stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!\");\r\n return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite);\r\n}\r\n\r\nfunction lengthBytesUTF8(str) {\r\n var len = 0;\r\n for (var i = 0; i < str.length; ++i) {\r\n var u = str.charCodeAt(i);\r\n if (u >= 55296 && u <= 57343) u = 65536 + ((u & 1023) << 10) | str.charCodeAt(++i) & 1023;\r\n if (u <= 127) ++len; else if (u <= 2047) len += 2; else if (u <= 65535) len += 3; else len += 4;\r\n }\r\n return len;\r\n}\r\n\r\nvar UTF16Decoder = typeof TextDecoder !== \"undefined\" ? new TextDecoder(\"utf-16le\") : undefined;\r\n\r\nfunction UTF16ToString(ptr, maxBytesToRead) {\r\n assert(ptr % 2 == 0, \"Pointer passed to UTF16ToString must be aligned to two bytes!\");\r\n var endPtr = ptr;\r\n var idx = endPtr >> 1;\r\n var maxIdx = idx + maxBytesToRead / 2;\r\n while (!(idx >= maxIdx) && _asan_js_load_2u(idx)) ++idx;\r\n endPtr = idx << 1;\r\n if (endPtr - ptr > 32 && UTF16Decoder) {\r\n return UTF16Decoder.decode(HEAPU8.subarray(ptr, endPtr));\r\n } else {\r\n var str = \"\";\r\n for (var i = 0; !(i >= maxBytesToRead / 2); ++i) {\r\n var codeUnit = _asan_js_load_2(ptr + i * 2 >> 1);\r\n if (codeUnit == 0) break;\r\n str += String.fromCharCode(codeUnit);\r\n }\r\n return str;\r\n }\r\n}\r\n\r\nfunction stringToUTF16(str, outPtr, maxBytesToWrite) {\r\n assert(outPtr % 2 == 0, \"Pointer passed to stringToUTF16 must be aligned to two bytes!\");\r\n assert(typeof maxBytesToWrite == \"number\", \"stringToUTF16(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!\");\r\n if (maxBytesToWrite === undefined) {\r\n maxBytesToWrite = 2147483647;\r\n }\r\n if (maxBytesToWrite < 2) return 0;\r\n maxBytesToWrite -= 2;\r\n var startPtr = outPtr;\r\n var numCharsToWrite = maxBytesToWrite < str.length * 2 ? maxBytesToWrite / 2 : str.length;\r\n for (var i = 0; i < numCharsToWrite; ++i) {\r\n var codeUnit = str.charCodeAt(i);\r\n _asan_js_store_2(outPtr >> 1, codeUnit);\r\n outPtr += 2;\r\n }\r\n _asan_js_store_2(outPtr >> 1, 0);\r\n return outPtr - startPtr;\r\n}\r\n\r\nfunction lengthBytesUTF16(str) {\r\n return str.length * 2;\r\n}\r\n\r\nfunction UTF32ToString(ptr, maxBytesToRead) {\r\n assert(ptr % 4 == 0, \"Pointer passed to UTF32ToString must be aligned to four bytes!\");\r\n var i = 0;\r\n var str = \"\";\r\n while (!(i >= maxBytesToRead / 4)) {\r\n var utf32 = _asan_js_load_4(ptr + i * 4 >> 2);\r\n if (utf32 == 0) break;\r\n ++i;\r\n if (utf32 >= 65536) {\r\n var ch = utf32 - 65536;\r\n str += String.fromCharCode(55296 | ch >> 10, 56320 | ch & 1023);\r\n } else {\r\n str += String.fromCharCode(utf32);\r\n }\r\n }\r\n return str;\r\n}\r\n\r\nfunction stringToUTF32(str, outPtr, maxBytesToWrite) {\r\n assert(outPtr % 4 == 0, \"Pointer passed to stringToUTF32 must be aligned to four bytes!\");\r\n assert(typeof maxBytesToWrite == \"number\", \"stringToUTF32(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!\");\r\n if (maxBytesToWrite === undefined) {\r\n maxBytesToWrite = 2147483647;\r\n }\r\n if (maxBytesToWrite < 4) return 0;\r\n var startPtr = outPtr;\r\n var endPtr = startPtr + maxBytesToWrite - 4;\r\n for (var i = 0; i < str.length; ++i) {\r\n var codeUnit = str.charCodeAt(i);\r\n if (codeUnit >= 55296 && codeUnit <= 57343) {\r\n var trailSurrogate = str.charCodeAt(++i);\r\n codeUnit = 65536 + ((codeUnit & 1023) << 10) | trailSurrogate & 1023;\r\n }\r\n _asan_js_store_4(outPtr >> 2, codeUnit);\r\n outPtr += 4;\r\n if (outPtr + 4 > endPtr) break;\r\n }\r\n _asan_js_store_4(outPtr >> 2, 0);\r\n return outPtr - startPtr;\r\n}\r\n\r\nfunction lengthBytesUTF32(str) {\r\n var len = 0;\r\n for (var i = 0; i < str.length; ++i) {\r\n var codeUnit = str.charCodeAt(i);\r\n if (codeUnit >= 55296 && codeUnit <= 57343) ++i;\r\n len += 4;\r\n }\r\n return len;\r\n}\r\n\r\nfunction allocateUTF8(str) {\r\n var size = lengthBytesUTF8(str) + 1;\r\n var ret = _malloc(size);\r\n if (ret) stringToUTF8Array(str, HEAP8, ret, size);\r\n return ret;\r\n}\r\n\r\nfunction writeArrayToMemory(array, buffer) {\r\n assert(array.length >= 0, \"writeArrayToMemory array must have a length (should be an array or typed array)\");\r\n HEAP8.set(array, buffer);\r\n}\r\n\r\nfunction writeAsciiToMemory(str, buffer, dontAddNull) {\r\n for (var i = 0; i < str.length; ++i) {\r\n assert(str.charCodeAt(i) === (str.charCodeAt(i) & 255));\r\n _asan_js_store_1(buffer++ >> 0, str.charCodeAt(i));\r\n }\r\n if (!dontAddNull) _asan_js_store_1(buffer >> 0, 0);\r\n}\r\n\r\nvar buffer, HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64;\r\n\r\nfunction updateGlobalBufferAndViews(buf) {\r\n buffer = buf;\r\n Module[\"HEAP8\"] = HEAP8 = new Int8Array(buf);\r\n Module[\"HEAP16\"] = HEAP16 = new Int16Array(buf);\r\n Module[\"HEAP32\"] = HEAP32 = new Int32Array(buf);\r\n Module[\"HEAPU8\"] = HEAPU8 = new Uint8Array(buf);\r\n Module[\"HEAPU16\"] = HEAPU16 = new Uint16Array(buf);\r\n Module[\"HEAPU32\"] = HEAPU32 = new Uint32Array(buf);\r\n Module[\"HEAPF32\"] = HEAPF32 = new Float32Array(buf);\r\n Module[\"HEAPF64\"] = HEAPF64 = new Float64Array(buf);\r\n}\r\n\r\nvar TOTAL_STACK = 5242880;\r\n\r\nif (Module[\"TOTAL_STACK\"]) assert(TOTAL_STACK === Module[\"TOTAL_STACK\"], \"the stack size can no longer be determined at runtime\");\r\n\r\nvar INITIAL_MEMORY = Module[\"INITIAL_MEMORY\"] || 79101952;\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"INITIAL_MEMORY\")) {\r\n Object.defineProperty(Module, \"INITIAL_MEMORY\", {\r\n configurable: true,\r\n get: function() {\r\n abort(\"Module.INITIAL_MEMORY has been replaced with plain INITIAL_MEMORY (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)\");\r\n }\r\n });\r\n}\r\n\r\nassert(INITIAL_MEMORY >= TOTAL_STACK, \"INITIAL_MEMORY should be larger than TOTAL_STACK, was \" + INITIAL_MEMORY + \"! (TOTAL_STACK=\" + TOTAL_STACK + \")\");\r\n\r\nassert(typeof Int32Array !== \"undefined\" && typeof Float64Array !== \"undefined\" && Int32Array.prototype.subarray !== undefined && Int32Array.prototype.set !== undefined, \"JS engine does not provide full typed array support\");\r\n\r\nassert(!Module[\"wasmMemory\"], \"Use of `wasmMemory` detected. Use -s IMPORTED_MEMORY to define wasmMemory externally\");\r\n\r\nassert(INITIAL_MEMORY == 79101952, \"Detected runtime INITIAL_MEMORY setting. Use -s IMPORTED_MEMORY to define wasmMemory dynamically\");\r\n\r\nvar wasmTable;\r\n\r\nfunction writeStackCookie() {\r\n var max = _emscripten_stack_get_end();\r\n assert((max & 3) == 0);\r\n _asan_js_store_4(max + 4 >> 2, 34821223);\r\n _asan_js_store_4(max + 8 >> 2, 2310721022);\r\n}\r\n\r\nfunction checkStackCookie() {\r\n if (ABORT) return;\r\n var max = _emscripten_stack_get_end();\r\n var cookie1 = _asan_js_load_4u(max + 4 >> 2);\r\n var cookie2 = _asan_js_load_4u(max + 8 >> 2);\r\n if (cookie1 != 34821223 || cookie2 != 2310721022) {\r\n abort(\"Stack overflow! Stack cookie has been overwritten, expected hex dwords 0x89BACDFE and 0x2135467, but received 0x\" + cookie2.toString(16) + \" 0x\" + cookie1.toString(16));\r\n }\r\n}\r\n\r\n(function() {\r\n var h16 = new Int16Array(1);\r\n var h8 = new Int8Array(h16.buffer);\r\n h16[0] = 25459;\r\n if (h8[0] !== 115 || h8[1] !== 99) throw \"Runtime error: expected the system to be little-endian! (Run with -s SUPPORT_BIG_ENDIAN=1 to bypass)\";\r\n})();\r\n\r\nvar __ATPRERUN__ = [];\r\n\r\nvar __ATINIT__ = [];\r\n\r\nvar __ATEXIT__ = [];\r\n\r\nvar __ATPOSTRUN__ = [];\r\n\r\nvar runtimeInitialized = false;\r\n\r\nvar runtimeExited = false;\r\n\r\nvar runtimeKeepaliveCounter = 0;\r\n\r\nfunction keepRuntimeAlive() {\r\n return noExitRuntime || runtimeKeepaliveCounter > 0;\r\n}\r\n\r\nfunction preRun() {\r\n if (Module[\"preRun\"]) {\r\n if (typeof Module[\"preRun\"] == \"function\") Module[\"preRun\"] = [ Module[\"preRun\"] ];\r\n while (Module[\"preRun\"].length) {\r\n addOnPreRun(Module[\"preRun\"].shift());\r\n }\r\n }\r\n callRuntimeCallbacks(__ATPRERUN__);\r\n}\r\n\r\nfunction initRuntime() {\r\n checkStackCookie();\r\n assert(!runtimeInitialized);\r\n runtimeInitialized = true;\r\n if (!Module[\"noFSInit\"] && !FS.init.initialized) FS.init();\r\n FS.ignorePermissions = false;\r\n TTY.init();\r\n callRuntimeCallbacks(__ATINIT__);\r\n}\r\n\r\nfunction exitRuntime() {\r\n checkStackCookie();\r\n ___funcs_on_exit();\r\n callRuntimeCallbacks(__ATEXIT__);\r\n FS.quit();\r\n TTY.shutdown();\r\n runtimeExited = true;\r\n}\r\n\r\nfunction postRun() {\r\n checkStackCookie();\r\n if (Module[\"postRun\"]) {\r\n if (typeof Module[\"postRun\"] == \"function\") Module[\"postRun\"] = [ Module[\"postRun\"] ];\r\n while (Module[\"postRun\"].length) {\r\n addOnPostRun(Module[\"postRun\"].shift());\r\n }\r\n }\r\n callRuntimeCallbacks(__ATPOSTRUN__);\r\n}\r\n\r\nfunction addOnPreRun(cb) {\r\n __ATPRERUN__.unshift(cb);\r\n}\r\n\r\nfunction addOnInit(cb) {\r\n __ATINIT__.unshift(cb);\r\n}\r\n\r\nfunction addOnPostRun(cb) {\r\n __ATPOSTRUN__.unshift(cb);\r\n}\r\n\r\nassert(Math.imul, \"This browser does not support Math.imul(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill\");\r\n\r\nassert(Math.fround, \"This browser does not support Math.fround(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill\");\r\n\r\nassert(Math.clz32, \"This browser does not support Math.clz32(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill\");\r\n\r\nassert(Math.trunc, \"This browser does not support Math.trunc(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill\");\r\n\r\nvar runDependencies = 0;\r\n\r\nvar runDependencyWatcher = null;\r\n\r\nvar dependenciesFulfilled = null;\r\n\r\nvar runDependencyTracking = {};\r\n\r\nfunction getUniqueRunDependency(id) {\r\n var orig = id;\r\n while (1) {\r\n if (!runDependencyTracking[id]) return id;\r\n id = orig + Math.random();\r\n }\r\n}\r\n\r\nfunction addRunDependency(id) {\r\n runDependencies++;\r\n if (Module[\"monitorRunDependencies\"]) {\r\n Module[\"monitorRunDependencies\"](runDependencies);\r\n }\r\n if (id) {\r\n assert(!runDependencyTracking[id]);\r\n runDependencyTracking[id] = 1;\r\n if (runDependencyWatcher === null && typeof setInterval !== \"undefined\") {\r\n runDependencyWatcher = setInterval(function() {\r\n if (ABORT) {\r\n clearInterval(runDependencyWatcher);\r\n runDependencyWatcher = null;\r\n return;\r\n }\r\n var shown = false;\r\n for (var dep in runDependencyTracking) {\r\n if (!shown) {\r\n shown = true;\r\n err(\"still waiting on run dependencies:\");\r\n }\r\n err(\"dependency: \" + dep);\r\n }\r\n if (shown) {\r\n err(\"(end of list)\");\r\n }\r\n }, 1e4);\r\n }\r\n } else {\r\n err(\"warning: run dependency added without ID\");\r\n }\r\n}\r\n\r\nfunction removeRunDependency(id) {\r\n runDependencies--;\r\n if (Module[\"monitorRunDependencies\"]) {\r\n Module[\"monitorRunDependencies\"](runDependencies);\r\n }\r\n if (id) {\r\n assert(runDependencyTracking[id]);\r\n delete runDependencyTracking[id];\r\n } else {\r\n err(\"warning: run dependency removed without ID\");\r\n }\r\n if (runDependencies == 0) {\r\n if (runDependencyWatcher !== null) {\r\n clearInterval(runDependencyWatcher);\r\n runDependencyWatcher = null;\r\n }\r\n if (dependenciesFulfilled) {\r\n var callback = dependenciesFulfilled;\r\n dependenciesFulfilled = null;\r\n callback();\r\n }\r\n }\r\n}\r\n\r\nModule[\"preloadedImages\"] = {};\r\n\r\nModule[\"preloadedAudios\"] = {};\r\n\r\nfunction abort(what) {\r\n {\r\n if (Module[\"onAbort\"]) {\r\n Module[\"onAbort\"](what);\r\n }\r\n }\r\n what = \"Aborted(\" + what + \")\";\r\n err(what);\r\n ABORT = true;\r\n EXITSTATUS = 1;\r\n var e = new WebAssembly.RuntimeError(what);\r\n readyPromiseReject(e);\r\n throw e;\r\n}\r\n\r\nvar dataURIPrefix = \"data:application/octet-stream;base64,\";\r\n\r\nfunction isDataURI(filename) {\r\n return filename.startsWith(dataURIPrefix);\r\n}\r\n\r\nfunction isFileURI(filename) {\r\n return filename.startsWith(\"file://\");\r\n}\r\n\r\nfunction createExportWrapper(name, fixedasm) {\r\n return function() {\r\n var displayName = name;\r\n var asm = fixedasm;\r\n if (!fixedasm) {\r\n asm = Module[\"asm\"];\r\n }\r\n assert(runtimeInitialized, \"native function `\" + displayName + \"` called before runtime initialization\");\r\n assert(!runtimeExited, \"native function `\" + displayName + \"` called after runtime exit (use NO_EXIT_RUNTIME to keep it alive after main() exits)\");\r\n if (!asm[name]) {\r\n assert(asm[name], \"exported native function `\" + displayName + \"` not found\");\r\n }\r\n return asm[name].apply(null, arguments);\r\n };\r\n}\r\n\r\nvar wasmBinaryFile;\r\n\r\nwasmBinaryFile = \"mlsGen.wasm\";\r\n\r\nif (!isDataURI(wasmBinaryFile)) {\r\n wasmBinaryFile = locateFile(wasmBinaryFile);\r\n}\r\n\r\nfunction getBinary(file) {\r\n try {\r\n if (file == wasmBinaryFile && wasmBinary) {\r\n return new Uint8Array(wasmBinary);\r\n }\r\n if (readBinary) {\r\n return readBinary(file);\r\n } else {\r\n throw \"both async and sync fetching of the wasm failed\";\r\n }\r\n } catch (err) {\r\n abort(err);\r\n }\r\n}\r\n\r\nfunction getBinaryPromise() {\r\n if (!wasmBinary && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER)) {\r\n if (typeof fetch === \"function\") {\r\n return fetch(wasmBinaryFile, {\r\n credentials: \"same-origin\"\r\n }).then(function(response) {\r\n if (!response[\"ok\"]) {\r\n throw \"failed to load wasm binary file at '\" + wasmBinaryFile + \"'\";\r\n }\r\n return response[\"arrayBuffer\"]();\r\n }).catch(function() {\r\n return getBinary(wasmBinaryFile);\r\n });\r\n }\r\n }\r\n return Promise.resolve().then(function() {\r\n return getBinary(wasmBinaryFile);\r\n });\r\n}\r\n\r\nvar wasmOffsetConverter;\r\n\r\nfunction WasmOffsetConverter(wasmBytes, wasmModule) {\r\n var offset = 8;\r\n var funcidx = 0;\r\n this.offset_map = {};\r\n this.func_starts = [];\r\n this.name_map = {};\r\n this.import_functions = 0;\r\n var buffer = wasmBytes;\r\n function unsignedLEB128() {\r\n var result = 0;\r\n var shift = 0;\r\n do {\r\n var byte = buffer[offset++];\r\n result += (byte & 127) << shift;\r\n shift += 7;\r\n } while (byte & 128);\r\n return result;\r\n }\r\n function skipLimits() {\r\n var flags = unsignedLEB128();\r\n unsignedLEB128();\r\n var hasMax = (flags & 1) != 0;\r\n if (hasMax) {\r\n unsignedLEB128();\r\n }\r\n }\r\n binary_parse: while (offset < buffer.length) {\r\n var type = buffer[offset++];\r\n var end = unsignedLEB128() + offset;\r\n switch (type) {\r\n case 2:\r\n var count = unsignedLEB128();\r\n while (count-- > 0) {\r\n offset = unsignedLEB128() + offset;\r\n offset = unsignedLEB128() + offset;\r\n switch (buffer[offset++]) {\r\n case 0:\r\n ++funcidx;\r\n unsignedLEB128();\r\n break;\r\n\r\n case 1:\r\n ++offset;\r\n skipLimits();\r\n break;\r\n\r\n case 2:\r\n skipLimits();\r\n break;\r\n\r\n case 3:\r\n offset += 2;\r\n break;\r\n\r\n default:\r\n throw \"bad import kind\";\r\n }\r\n }\r\n this.import_functions = funcidx;\r\n break;\r\n\r\n case 10:\r\n var count = unsignedLEB128();\r\n while (count-- > 0) {\r\n var size = unsignedLEB128();\r\n this.offset_map[funcidx++] = offset;\r\n this.func_starts.push(offset);\r\n offset += size;\r\n }\r\n break binary_parse;\r\n }\r\n offset = end;\r\n }\r\n var sections = WebAssembly.Module.customSections(wasmModule, \"name\");\r\n for (var i = 0; i < sections.length; ++i) {\r\n buffer = new Uint8Array(sections[i]);\r\n if (buffer[0] != 1) continue;\r\n offset = 1;\r\n unsignedLEB128();\r\n var count = unsignedLEB128();\r\n while (count-- > 0) {\r\n var index = unsignedLEB128();\r\n var length = unsignedLEB128();\r\n this.name_map[index] = UTF8ArrayToString(buffer, offset, length);\r\n offset += length;\r\n }\r\n }\r\n}\r\n\r\nWasmOffsetConverter.prototype.convert = function(funcidx, offset) {\r\n return this.offset_map[funcidx] + offset;\r\n};\r\n\r\nWasmOffsetConverter.prototype.getIndex = function(offset) {\r\n var lo = 0;\r\n var hi = this.func_starts.length;\r\n var mid;\r\n while (lo < hi) {\r\n mid = Math.floor((lo + hi) / 2);\r\n if (this.func_starts[mid] > offset) {\r\n hi = mid;\r\n } else {\r\n lo = mid + 1;\r\n }\r\n }\r\n return lo + this.import_functions - 1;\r\n};\r\n\r\nWasmOffsetConverter.prototype.isSameFunc = function(offset1, offset2) {\r\n return this.getIndex(offset1) == this.getIndex(offset2);\r\n};\r\n\r\nWasmOffsetConverter.prototype.getName = function(offset) {\r\n var index = this.getIndex(offset);\r\n return this.name_map[index] || \"wasm-function[\" + index + \"]\";\r\n};\r\n\r\nfunction resetPrototype(constructor, attrs) {\r\n var object = Object.create(constructor.prototype);\r\n return Object.assign(object, attrs);\r\n}\r\n\r\nfunction createWasm() {\r\n var info = {\r\n \"env\": asmLibraryArg,\r\n \"wasi_snapshot_preview1\": asmLibraryArg\r\n };\r\n function receiveInstance(instance, module) {\r\n var exports = instance.exports;\r\n Module[\"asm\"] = exports;\r\n wasmMemory = Module[\"asm\"][\"memory\"];\r\n assert(wasmMemory, \"memory not found in wasm exports\");\r\n updateGlobalBufferAndViews(wasmMemory.buffer);\r\n wasmTable = Module[\"asm\"][\"__indirect_function_table\"];\r\n assert(wasmTable, \"table not found in wasm exports\");\r\n addOnInit(Module[\"asm\"][\"__wasm_call_ctors\"]);\r\n removeRunDependency(\"wasm-instantiate\");\r\n }\r\n addRunDependency(\"wasm-instantiate\");\r\n var trueModule = Module;\r\n function receiveInstantiationResult(result) {\r\n assert(Module === trueModule, \"the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?\");\r\n trueModule = null;\r\n receiveInstance(result[\"instance\"]);\r\n }\r\n function instantiateArrayBuffer(receiver) {\r\n var savedBinary;\r\n return getBinaryPromise().then(function(binary) {\r\n savedBinary = binary;\r\n return WebAssembly.instantiate(binary, info);\r\n }).then(function(instance) {\r\n wasmOffsetConverter = new WasmOffsetConverter(savedBinary, instance.module);\r\n return instance;\r\n }).then(receiver, function(reason) {\r\n err(\"failed to asynchronously prepare wasm: \" + reason);\r\n if (isFileURI(wasmBinaryFile)) {\r\n err(\"warning: Loading from a file URI (\" + wasmBinaryFile + \") is not supported in most browsers. See https://emscripten.org/docs/getting_started/FAQ.html#how-do-i-run-a-local-webserver-for-testing-why-does-my-program-stall-in-downloading-or-preparing\");\r\n }\r\n abort(reason);\r\n });\r\n }\r\n function instantiateAsync() {\r\n if (!wasmBinary && typeof WebAssembly.instantiateStreaming === \"function\" && !isDataURI(wasmBinaryFile) && typeof fetch === \"function\") {\r\n return fetch(wasmBinaryFile, {\r\n credentials: \"same-origin\"\r\n }).then(function(response) {\r\n var result = WebAssembly.instantiateStreaming(response, info);\r\n var clonedResponsePromise = response.clone().arrayBuffer();\r\n return result.then(function(instantiationResult) {\r\n clonedResponsePromise.then(function(arrayBufferResult) {\r\n wasmOffsetConverter = new WasmOffsetConverter(new Uint8Array(arrayBufferResult), instantiationResult.module);\r\n receiveInstantiationResult(instantiationResult);\r\n }, function(reason) {\r\n err(\"failed to initialize offset-converter: \" + reason);\r\n });\r\n }, function(reason) {\r\n err(\"wasm streaming compile failed: \" + reason);\r\n err(\"falling back to ArrayBuffer instantiation\");\r\n return instantiateArrayBuffer(receiveInstantiationResult);\r\n });\r\n });\r\n } else {\r\n return instantiateArrayBuffer(receiveInstantiationResult);\r\n }\r\n }\r\n if (Module[\"instantiateWasm\"]) {\r\n wasmOffsetConverter = resetPrototype(WasmOffsetConverter, Module[\"wasmOffsetData\"]);\r\n try {\r\n var exports = Module[\"instantiateWasm\"](info, receiveInstance);\r\n return exports;\r\n } catch (e) {\r\n err(\"Module.instantiateWasm callback failed with error: \" + e);\r\n return false;\r\n }\r\n }\r\n instantiateAsync().catch(readyPromiseReject);\r\n return {};\r\n}\r\n\r\nvar tempDouble;\r\n\r\nvar tempI64;\r\n\r\nvar ASM_CONSTS = {\r\n 9944289: function() {\r\n return withBuiltinMalloc(function() {\r\n return allocateUTF8(Module[\"ASAN_OPTIONS\"] || 0);\r\n });\r\n },\r\n 9944386: function() {\r\n return withBuiltinMalloc(function() {\r\n return allocateUTF8(Module[\"LSAN_OPTIONS\"] || 0);\r\n });\r\n },\r\n 9944483: function() {\r\n return withBuiltinMalloc(function() {\r\n return allocateUTF8(Module[\"UBSAN_OPTIONS\"] || 0);\r\n });\r\n },\r\n 9944581: function() {\r\n var setting = Module[\"printWithColors\"];\r\n if (setting != null) {\r\n return setting;\r\n } else {\r\n return ENVIRONMENT_IS_NODE && process.stderr.isTTY;\r\n }\r\n }\r\n};\r\n\r\nfunction callRuntimeCallbacks(callbacks) {\r\n while (callbacks.length > 0) {\r\n var callback = callbacks.shift();\r\n if (typeof callback == \"function\") {\r\n callback(Module);\r\n continue;\r\n }\r\n var func = callback.func;\r\n if (typeof func === \"number\") {\r\n if (callback.arg === undefined) {\r\n getWasmTableEntry(func)();\r\n } else {\r\n getWasmTableEntry(func)(callback.arg);\r\n }\r\n } else {\r\n func(callback.arg === undefined ? null : callback.arg);\r\n }\r\n }\r\n}\r\n\r\nfunction demangle(func) {\r\n warnOnce(\"warning: build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling\");\r\n return func;\r\n}\r\n\r\nfunction demangleAll(text) {\r\n var regex = /\\b_Z[\\w\\d_]+/g;\r\n return text.replace(regex, function(x) {\r\n var y = demangle(x);\r\n return x === y ? x : y + \" [\" + x + \"]\";\r\n });\r\n}\r\n\r\nvar wasmTableMirror = [];\r\n\r\nfunction getWasmTableEntry(funcPtr) {\r\n var func = wasmTableMirror[funcPtr];\r\n if (!func) {\r\n if (funcPtr >= wasmTableMirror.length) wasmTableMirror.length = funcPtr + 1;\r\n wasmTableMirror[funcPtr] = func = wasmTable.get(funcPtr);\r\n }\r\n assert(wasmTable.get(funcPtr) == func, \"JavaScript-side Wasm function table mirror is out of date!\");\r\n return func;\r\n}\r\n\r\nfunction jsStackTrace() {\r\n var error = new Error();\r\n if (!error.stack) {\r\n try {\r\n throw new Error();\r\n } catch (e) {\r\n error = e;\r\n }\r\n if (!error.stack) {\r\n return \"(no stack trace available)\";\r\n }\r\n }\r\n return error.stack.toString();\r\n}\r\n\r\nfunction setWasmTableEntry(idx, func) {\r\n wasmTable.set(idx, func);\r\n wasmTableMirror[idx] = func;\r\n}\r\n\r\nfunction ___assert_fail(condition, filename, line, func) {\r\n abort(\"Assertion failed: \" + UTF8ToString(condition) + \", at: \" + [ filename ? UTF8ToString(filename) : \"unknown filename\", line, func ? UTF8ToString(func) : \"unknown function\" ]);\r\n}\r\n\r\nvar PATH = {\r\n splitPath: function(filename) {\r\n var splitPathRe = /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\r\n return splitPathRe.exec(filename).slice(1);\r\n },\r\n normalizeArray: function(parts, allowAboveRoot) {\r\n var up = 0;\r\n for (var i = parts.length - 1; i >= 0; i--) {\r\n var last = parts[i];\r\n if (last === \".\") {\r\n parts.splice(i, 1);\r\n } else if (last === \"..\") {\r\n parts.splice(i, 1);\r\n up++;\r\n } else if (up) {\r\n parts.splice(i, 1);\r\n up--;\r\n }\r\n }\r\n if (allowAboveRoot) {\r\n for (;up; up--) {\r\n parts.unshift(\"..\");\r\n }\r\n }\r\n return parts;\r\n },\r\n normalize: function(path) {\r\n var isAbsolute = path.charAt(0) === \"/\", trailingSlash = path.substr(-1) === \"/\";\r\n path = PATH.normalizeArray(path.split(\"/\").filter(function(p) {\r\n return !!p;\r\n }), !isAbsolute).join(\"/\");\r\n if (!path && !isAbsolute) {\r\n path = \".\";\r\n }\r\n if (path && trailingSlash) {\r\n path += \"/\";\r\n }\r\n return (isAbsolute ? \"/\" : \"\") + path;\r\n },\r\n dirname: function(path) {\r\n var result = PATH.splitPath(path), root = result[0], dir = result[1];\r\n if (!root && !dir) {\r\n return \".\";\r\n }\r\n if (dir) {\r\n dir = dir.substr(0, dir.length - 1);\r\n }\r\n return root + dir;\r\n },\r\n basename: function(path) {\r\n if (path === \"/\") return \"/\";\r\n path = PATH.normalize(path);\r\n path = path.replace(/\\/$/, \"\");\r\n var lastSlash = path.lastIndexOf(\"/\");\r\n if (lastSlash === -1) return path;\r\n return path.substr(lastSlash + 1);\r\n },\r\n extname: function(path) {\r\n return PATH.splitPath(path)[3];\r\n },\r\n join: function() {\r\n var paths = Array.prototype.slice.call(arguments, 0);\r\n return PATH.normalize(paths.join(\"/\"));\r\n },\r\n join2: function(l, r) {\r\n return PATH.normalize(l + \"/\" + r);\r\n }\r\n};\r\n\r\nfunction getRandomDevice() {\r\n if (typeof crypto === \"object\" && typeof crypto[\"getRandomValues\"] === \"function\") {\r\n var randomBuffer = new Uint8Array(1);\r\n return function() {\r\n crypto.getRandomValues(randomBuffer);\r\n return randomBuffer[0];\r\n };\r\n } else return function() {\r\n abort(\"no cryptographic support found for randomDevice. consider polyfilling it if you want to use something insecure like Math.random(), e.g. put this in a --pre-js: var crypto = { getRandomValues: function(array) { for (var i = 0; i < array.length; i++) array[i] = (Math.random()*256)|0 } };\");\r\n };\r\n}\r\n\r\nvar PATH_FS = {\r\n resolve: function() {\r\n var resolvedPath = \"\", resolvedAbsolute = false;\r\n for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\r\n var path = i >= 0 ? arguments[i] : FS.cwd();\r\n if (typeof path !== \"string\") {\r\n throw new TypeError(\"Arguments to path.resolve must be strings\");\r\n } else if (!path) {\r\n return \"\";\r\n }\r\n resolvedPath = path + \"/\" + resolvedPath;\r\n resolvedAbsolute = path.charAt(0) === \"/\";\r\n }\r\n resolvedPath = PATH.normalizeArray(resolvedPath.split(\"/\").filter(function(p) {\r\n return !!p;\r\n }), !resolvedAbsolute).join(\"/\");\r\n return (resolvedAbsolute ? \"/\" : \"\") + resolvedPath || \".\";\r\n },\r\n relative: function(from, to) {\r\n from = PATH_FS.resolve(from).substr(1);\r\n to = PATH_FS.resolve(to).substr(1);\r\n function trim(arr) {\r\n var start = 0;\r\n for (;start < arr.length; start++) {\r\n if (arr[start] !== \"\") break;\r\n }\r\n var end = arr.length - 1;\r\n for (;end >= 0; end--) {\r\n if (arr[end] !== \"\") break;\r\n }\r\n if (start > end) return [];\r\n return arr.slice(start, end - start + 1);\r\n }\r\n var fromParts = trim(from.split(\"/\"));\r\n var toParts = trim(to.split(\"/\"));\r\n var length = Math.min(fromParts.length, toParts.length);\r\n var samePartsLength = length;\r\n for (var i = 0; i < length; i++) {\r\n if (fromParts[i] !== toParts[i]) {\r\n samePartsLength = i;\r\n break;\r\n }\r\n }\r\n var outputParts = [];\r\n for (var i = samePartsLength; i < fromParts.length; i++) {\r\n outputParts.push(\"..\");\r\n }\r\n outputParts = outputParts.concat(toParts.slice(samePartsLength));\r\n return outputParts.join(\"/\");\r\n }\r\n};\r\n\r\nvar TTY = {\r\n ttys: [],\r\n init: function() {},\r\n shutdown: function() {},\r\n register: function(dev, ops) {\r\n TTY.ttys[dev] = {\r\n input: [],\r\n output: [],\r\n ops: ops\r\n };\r\n FS.registerDevice(dev, TTY.stream_ops);\r\n },\r\n stream_ops: {\r\n open: function(stream) {\r\n var tty = TTY.ttys[stream.node.rdev];\r\n if (!tty) {\r\n throw new FS.ErrnoError(43);\r\n }\r\n stream.tty = tty;\r\n stream.seekable = false;\r\n },\r\n close: function(stream) {\r\n stream.tty.ops.flush(stream.tty);\r\n },\r\n flush: function(stream) {\r\n stream.tty.ops.flush(stream.tty);\r\n },\r\n read: function(stream, buffer, offset, length, pos) {\r\n if (!stream.tty || !stream.tty.ops.get_char) {\r\n throw new FS.ErrnoError(60);\r\n }\r\n var bytesRead = 0;\r\n for (var i = 0; i < length; i++) {\r\n var result;\r\n try {\r\n result = stream.tty.ops.get_char(stream.tty);\r\n } catch (e) {\r\n throw new FS.ErrnoError(29);\r\n }\r\n if (result === undefined && bytesRead === 0) {\r\n throw new FS.ErrnoError(6);\r\n }\r\n if (result === null || result === undefined) break;\r\n bytesRead++;\r\n buffer[offset + i] = result;\r\n }\r\n if (bytesRead) {\r\n stream.node.timestamp = Date.now();\r\n }\r\n return bytesRead;\r\n },\r\n write: function(stream, buffer, offset, length, pos) {\r\n if (!stream.tty || !stream.tty.ops.put_char) {\r\n throw new FS.ErrnoError(60);\r\n }\r\n try {\r\n for (var i = 0; i < length; i++) {\r\n stream.tty.ops.put_char(stream.tty, buffer[offset + i]);\r\n }\r\n } catch (e) {\r\n throw new FS.ErrnoError(29);\r\n }\r\n if (length) {\r\n stream.node.timestamp = Date.now();\r\n }\r\n return i;\r\n }\r\n },\r\n default_tty_ops: {\r\n get_char: function(tty) {\r\n if (!tty.input.length) {\r\n var result = null;\r\n if (typeof window != \"undefined\" && typeof window.prompt == \"function\") {\r\n result = window.prompt(\"Input: \");\r\n if (result !== null) {\r\n result += \"\\n\";\r\n }\r\n } else if (typeof readline == \"function\") {\r\n result = readline();\r\n if (result !== null) {\r\n result += \"\\n\";\r\n }\r\n }\r\n if (!result) {\r\n return null;\r\n }\r\n tty.input = intArrayFromString(result, true);\r\n }\r\n return tty.input.shift();\r\n },\r\n put_char: function(tty, val) {\r\n if (val === null || val === 10) {\r\n out(UTF8ArrayToString(tty.output, 0));\r\n tty.output = [];\r\n } else {\r\n if (val != 0) tty.output.push(val);\r\n }\r\n },\r\n flush: function(tty) {\r\n if (tty.output && tty.output.length > 0) {\r\n out(UTF8ArrayToString(tty.output, 0));\r\n tty.output = [];\r\n }\r\n }\r\n },\r\n default_tty1_ops: {\r\n put_char: function(tty, val) {\r\n if (val === null || val === 10) {\r\n err(UTF8ArrayToString(tty.output, 0));\r\n tty.output = [];\r\n } else {\r\n if (val != 0) tty.output.push(val);\r\n }\r\n },\r\n flush: function(tty) {\r\n if (tty.output && tty.output.length > 0) {\r\n err(UTF8ArrayToString(tty.output, 0));\r\n tty.output = [];\r\n }\r\n }\r\n }\r\n};\r\n\r\nfunction zeroMemory(address, size) {\r\n HEAPU8.fill(0, address, address + size);\r\n}\r\n\r\nfunction alignMemory(size, alignment) {\r\n assert(alignment, \"alignment argument is required\");\r\n return Math.ceil(size / alignment) * alignment;\r\n}\r\n\r\nfunction mmapAlloc(size) {\r\n size = alignMemory(size, 65536);\r\n var ptr = _memalign(65536, size);\r\n if (!ptr) return 0;\r\n zeroMemory(ptr, size);\r\n return ptr;\r\n}\r\n\r\nvar MEMFS = {\r\n ops_table: null,\r\n mount: function(mount) {\r\n return MEMFS.createNode(null, \"/\", 16384 | 511, 0);\r\n },\r\n createNode: function(parent, name, mode, dev) {\r\n if (FS.isBlkdev(mode) || FS.isFIFO(mode)) {\r\n throw new FS.ErrnoError(63);\r\n }\r\n if (!MEMFS.ops_table) {\r\n MEMFS.ops_table = {\r\n dir: {\r\n node: {\r\n getattr: MEMFS.node_ops.getattr,\r\n setattr: MEMFS.node_ops.setattr,\r\n lookup: MEMFS.node_ops.lookup,\r\n mknod: MEMFS.node_ops.mknod,\r\n rename: MEMFS.node_ops.rename,\r\n unlink: MEMFS.node_ops.unlink,\r\n rmdir: MEMFS.node_ops.rmdir,\r\n readdir: MEMFS.node_ops.readdir,\r\n symlink: MEMFS.node_ops.symlink\r\n },\r\n stream: {\r\n llseek: MEMFS.stream_ops.llseek\r\n }\r\n },\r\n file: {\r\n node: {\r\n getattr: MEMFS.node_ops.getattr,\r\n setattr: MEMFS.node_ops.setattr\r\n },\r\n stream: {\r\n llseek: MEMFS.stream_ops.llseek,\r\n read: MEMFS.stream_ops.read,\r\n write: MEMFS.stream_ops.write,\r\n allocate: MEMFS.stream_ops.allocate,\r\n mmap: MEMFS.stream_ops.mmap,\r\n msync: MEMFS.stream_ops.msync\r\n }\r\n },\r\n link: {\r\n node: {\r\n getattr: MEMFS.node_ops.getattr,\r\n setattr: MEMFS.node_ops.setattr,\r\n readlink: MEMFS.node_ops.readlink\r\n },\r\n stream: {}\r\n },\r\n chrdev: {\r\n node: {\r\n getattr: MEMFS.node_ops.getattr,\r\n setattr: MEMFS.node_ops.setattr\r\n },\r\n stream: FS.chrdev_stream_ops\r\n }\r\n };\r\n }\r\n var node = FS.createNode(parent, name, mode, dev);\r\n if (FS.isDir(node.mode)) {\r\n node.node_ops = MEMFS.ops_table.dir.node;\r\n node.stream_ops = MEMFS.ops_table.dir.stream;\r\n node.contents = {};\r\n } else if (FS.isFile(node.mode)) {\r\n node.node_ops = MEMFS.ops_table.file.node;\r\n node.stream_ops = MEMFS.ops_table.file.stream;\r\n node.usedBytes = 0;\r\n node.contents = null;\r\n } else if (FS.isLink(node.mode)) {\r\n node.node_ops = MEMFS.ops_table.link.node;\r\n node.stream_ops = MEMFS.ops_table.link.stream;\r\n } else if (FS.isChrdev(node.mode)) {\r\n node.node_ops = MEMFS.ops_table.chrdev.node;\r\n node.stream_ops = MEMFS.ops_table.chrdev.stream;\r\n }\r\n node.timestamp = Date.now();\r\n if (parent) {\r\n parent.contents[name] = node;\r\n parent.timestamp = node.timestamp;\r\n }\r\n return node;\r\n },\r\n getFileDataAsTypedArray: function(node) {\r\n if (!node.contents) return new Uint8Array(0);\r\n if (node.contents.subarray) return node.contents.subarray(0, node.usedBytes);\r\n return new Uint8Array(node.contents);\r\n },\r\n expandFileStorage: function(node, newCapacity) {\r\n var prevCapacity = node.contents ? node.contents.length : 0;\r\n if (prevCapacity >= newCapacity) return;\r\n var CAPACITY_DOUBLING_MAX = 1024 * 1024;\r\n newCapacity = Math.max(newCapacity, prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2 : 1.125) >>> 0);\r\n if (prevCapacity != 0) newCapacity = Math.max(newCapacity, 256);\r\n var oldContents = node.contents;\r\n node.contents = new Uint8Array(newCapacity);\r\n if (node.usedBytes > 0) node.contents.set(oldContents.subarray(0, node.usedBytes), 0);\r\n },\r\n resizeFileStorage: function(node, newSize) {\r\n if (node.usedBytes == newSize) return;\r\n if (newSize == 0) {\r\n node.contents = null;\r\n node.usedBytes = 0;\r\n } else {\r\n var oldContents = node.contents;\r\n node.contents = new Uint8Array(newSize);\r\n if (oldContents) {\r\n node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes)));\r\n }\r\n node.usedBytes = newSize;\r\n }\r\n },\r\n node_ops: {\r\n getattr: function(node) {\r\n var attr = {};\r\n attr.dev = FS.isChrdev(node.mode) ? node.id : 1;\r\n attr.ino = node.id;\r\n attr.mode = node.mode;\r\n attr.nlink = 1;\r\n attr.uid = 0;\r\n attr.gid = 0;\r\n attr.rdev = node.rdev;\r\n if (FS.isDir(node.mode)) {\r\n attr.size = 4096;\r\n } else if (FS.isFile(node.mode)) {\r\n attr.size = node.usedBytes;\r\n } else if (FS.isLink(node.mode)) {\r\n attr.size = node.link.length;\r\n } else {\r\n attr.size = 0;\r\n }\r\n attr.atime = new Date(node.timestamp);\r\n attr.mtime = new Date(node.timestamp);\r\n attr.ctime = new Date(node.timestamp);\r\n attr.blksize = 4096;\r\n attr.blocks = Math.ceil(attr.size / attr.blksize);\r\n return attr;\r\n },\r\n setattr: function(node, attr) {\r\n if (attr.mode !== undefined) {\r\n node.mode = attr.mode;\r\n }\r\n if (attr.timestamp !== undefined) {\r\n node.timestamp = attr.timestamp;\r\n }\r\n if (attr.size !== undefined) {\r\n MEMFS.resizeFileStorage(node, attr.size);\r\n }\r\n },\r\n lookup: function(parent, name) {\r\n throw FS.genericErrors[44];\r\n },\r\n mknod: function(parent, name, mode, dev) {\r\n return MEMFS.createNode(parent, name, mode, dev);\r\n },\r\n rename: function(old_node, new_dir, new_name) {\r\n if (FS.isDir(old_node.mode)) {\r\n var new_node;\r\n try {\r\n new_node = FS.lookupNode(new_dir, new_name);\r\n } catch (e) {}\r\n if (new_node) {\r\n for (var i in new_node.contents) {\r\n throw new FS.ErrnoError(55);\r\n }\r\n }\r\n }\r\n delete old_node.parent.contents[old_node.name];\r\n old_node.parent.timestamp = Date.now();\r\n old_node.name = new_name;\r\n new_dir.contents[new_name] = old_node;\r\n new_dir.timestamp = old_node.parent.timestamp;\r\n old_node.parent = new_dir;\r\n },\r\n unlink: function(parent, name) {\r\n delete parent.contents[name];\r\n parent.timestamp = Date.now();\r\n },\r\n rmdir: function(parent, name) {\r\n var node = FS.lookupNode(parent, name);\r\n for (var i in node.contents) {\r\n throw new FS.ErrnoError(55);\r\n }\r\n delete parent.contents[name];\r\n parent.timestamp = Date.now();\r\n },\r\n readdir: function(node) {\r\n var entries = [ \".\", \"..\" ];\r\n for (var key in node.contents) {\r\n if (!node.contents.hasOwnProperty(key)) {\r\n continue;\r\n }\r\n entries.push(key);\r\n }\r\n return entries;\r\n },\r\n symlink: function(parent, newname, oldpath) {\r\n var node = MEMFS.createNode(parent, newname, 511 | 40960, 0);\r\n node.link = oldpath;\r\n return node;\r\n },\r\n readlink: function(node) {\r\n if (!FS.isLink(node.mode)) {\r\n throw new FS.ErrnoError(28);\r\n }\r\n return node.link;\r\n }\r\n },\r\n stream_ops: {\r\n read: function(stream, buffer, offset, length, position) {\r\n var contents = stream.node.contents;\r\n if (position >= stream.node.usedBytes) return 0;\r\n var size = Math.min(stream.node.usedBytes - position, length);\r\n assert(size >= 0);\r\n if (size > 8 && contents.subarray) {\r\n buffer.set(contents.subarray(position, position + size), offset);\r\n } else {\r\n for (var i = 0; i < size; i++) buffer[offset + i] = contents[position + i];\r\n }\r\n return size;\r\n },\r\n write: function(stream, buffer, offset, length, position, canOwn) {\r\n assert(!(buffer instanceof ArrayBuffer));\r\n if (!length) return 0;\r\n var node = stream.node;\r\n node.timestamp = Date.now();\r\n if (buffer.subarray && (!node.contents || node.contents.subarray)) {\r\n if (canOwn) {\r\n assert(position === 0, \"canOwn must imply no weird position inside the file\");\r\n node.contents = buffer.subarray(offset, offset + length);\r\n node.usedBytes = length;\r\n return length;\r\n } else if (node.usedBytes === 0 && position === 0) {\r\n node.contents = buffer.slice(offset, offset + length);\r\n node.usedBytes = length;\r\n return length;\r\n } else if (position + length <= node.usedBytes) {\r\n node.contents.set(buffer.subarray(offset, offset + length), position);\r\n return length;\r\n }\r\n }\r\n MEMFS.expandFileStorage(node, position + length);\r\n if (node.contents.subarray && buffer.subarray) {\r\n node.contents.set(buffer.subarray(offset, offset + length), position);\r\n } else {\r\n for (var i = 0; i < length; i++) {\r\n node.contents[position + i] = buffer[offset + i];\r\n }\r\n }\r\n node.usedBytes = Math.max(node.usedBytes, position + length);\r\n return length;\r\n },\r\n llseek: function(stream, offset, whence) {\r\n var position = offset;\r\n if (whence === 1) {\r\n position += stream.position;\r\n } else if (whence === 2) {\r\n if (FS.isFile(stream.node.mode)) {\r\n position += stream.node.usedBytes;\r\n }\r\n }\r\n if (position < 0) {\r\n throw new FS.ErrnoError(28);\r\n }\r\n return position;\r\n },\r\n allocate: function(stream, offset, length) {\r\n MEMFS.expandFileStorage(stream.node, offset + length);\r\n stream.node.usedBytes = Math.max(stream.node.usedBytes, offset + length);\r\n },\r\n mmap: function(stream, address, length, position, prot, flags) {\r\n if (address !== 0) {\r\n throw new FS.ErrnoError(28);\r\n }\r\n if (!FS.isFile(stream.node.mode)) {\r\n throw new FS.ErrnoError(43);\r\n }\r\n var ptr;\r\n var allocated;\r\n var contents = stream.node.contents;\r\n if (!(flags & 2) && contents.buffer === buffer) {\r\n allocated = false;\r\n ptr = contents.byteOffset;\r\n } else {\r\n if (position > 0 || position + length < contents.length) {\r\n if (contents.subarray) {\r\n contents = contents.subarray(position, position + length);\r\n } else {\r\n contents = Array.prototype.slice.call(contents, position, position + length);\r\n }\r\n }\r\n allocated = true;\r\n ptr = mmapAlloc(length);\r\n if (!ptr) {\r\n throw new FS.ErrnoError(48);\r\n }\r\n HEAP8.set(contents, ptr);\r\n }\r\n return {\r\n ptr: ptr,\r\n allocated: allocated\r\n };\r\n },\r\n msync: function(stream, buffer, offset, length, mmapFlags) {\r\n if (!FS.isFile(stream.node.mode)) {\r\n throw new FS.ErrnoError(43);\r\n }\r\n if (mmapFlags & 2) {\r\n return 0;\r\n }\r\n var bytesWritten = MEMFS.stream_ops.write(stream, buffer, 0, length, offset, false);\r\n return 0;\r\n }\r\n }\r\n};\r\n\r\nfunction asyncLoad(url, onload, onerror, noRunDep) {\r\n var dep = !noRunDep ? getUniqueRunDependency(\"al \" + url) : \"\";\r\n readAsync(url, function(arrayBuffer) {\r\n assert(arrayBuffer, 'Loading data file \"' + url + '\" failed (no arrayBuffer).');\r\n onload(new Uint8Array(arrayBuffer));\r\n if (dep) removeRunDependency(dep);\r\n }, function(event) {\r\n if (onerror) {\r\n onerror();\r\n } else {\r\n throw 'Loading data file \"' + url + '\" failed.';\r\n }\r\n });\r\n if (dep) addRunDependency(dep);\r\n}\r\n\r\nvar ERRNO_MESSAGES = {\r\n 0: \"Success\",\r\n 1: \"Arg list too long\",\r\n 2: \"Permission denied\",\r\n 3: \"Address already in use\",\r\n 4: \"Address not available\",\r\n 5: \"Address family not supported by protocol family\",\r\n 6: \"No more processes\",\r\n 7: \"Socket already connected\",\r\n 8: \"Bad file number\",\r\n 9: \"Trying to read unreadable message\",\r\n 10: \"Mount device busy\",\r\n 11: \"Operation canceled\",\r\n 12: \"No children\",\r\n 13: \"Connection aborted\",\r\n 14: \"Connection refused\",\r\n 15: \"Connection reset by peer\",\r\n 16: \"File locking deadlock error\",\r\n 17: \"Destination address required\",\r\n 18: \"Math arg out of domain of func\",\r\n 19: \"Quota exceeded\",\r\n 20: \"File exists\",\r\n 21: \"Bad address\",\r\n 22: \"File too large\",\r\n 23: \"Host is unreachable\",\r\n 24: \"Identifier removed\",\r\n 25: \"Illegal byte sequence\",\r\n 26: \"Connection already in progress\",\r\n 27: \"Interrupted system call\",\r\n 28: \"Invalid argument\",\r\n 29: \"I/O error\",\r\n 30: \"Socket is already connected\",\r\n 31: \"Is a directory\",\r\n 32: \"Too many symbolic links\",\r\n 33: \"Too many open files\",\r\n 34: \"Too many links\",\r\n 35: \"Message too long\",\r\n 36: \"Multihop attempted\",\r\n 37: \"File or path name too long\",\r\n 38: \"Network interface is not configured\",\r\n 39: \"Connection reset by network\",\r\n 40: \"Network is unreachable\",\r\n 41: \"Too many open files in system\",\r\n 42: \"No buffer space available\",\r\n 43: \"No such device\",\r\n 44: \"No such file or directory\",\r\n 45: \"Exec format error\",\r\n 46: \"No record locks available\",\r\n 47: \"The link has been severed\",\r\n 48: \"Not enough core\",\r\n 49: \"No message of desired type\",\r\n 50: \"Protocol not available\",\r\n 51: \"No space left on device\",\r\n 52: \"Function not implemented\",\r\n 53: \"Socket is not connected\",\r\n 54: \"Not a directory\",\r\n 55: \"Directory not empty\",\r\n 56: \"State not recoverable\",\r\n 57: \"Socket operation on non-socket\",\r\n 59: \"Not a typewriter\",\r\n 60: \"No such device or address\",\r\n 61: \"Value too large for defined data type\",\r\n 62: \"Previous owner died\",\r\n 63: \"Not super-user\",\r\n 64: \"Broken pipe\",\r\n 65: \"Protocol error\",\r\n 66: \"Unknown protocol\",\r\n 67: \"Protocol wrong type for socket\",\r\n 68: \"Math result not representable\",\r\n 69: \"Read only file system\",\r\n 70: \"Illegal seek\",\r\n 71: \"No such process\",\r\n 72: \"Stale file handle\",\r\n 73: \"Connection timed out\",\r\n 74: \"Text file busy\",\r\n 75: \"Cross-device link\",\r\n 100: \"Device not a stream\",\r\n 101: \"Bad font file fmt\",\r\n 102: \"Invalid slot\",\r\n 103: \"Invalid request code\",\r\n 104: \"No anode\",\r\n 105: \"Block device required\",\r\n 106: \"Channel number out of range\",\r\n 107: \"Level 3 halted\",\r\n 108: \"Level 3 reset\",\r\n 109: \"Link number out of range\",\r\n 110: \"Protocol driver not attached\",\r\n 111: \"No CSI structure available\",\r\n 112: \"Level 2 halted\",\r\n 113: \"Invalid exchange\",\r\n 114: \"Invalid request descriptor\",\r\n 115: \"Exchange full\",\r\n 116: \"No data (for no delay io)\",\r\n 117: \"Timer expired\",\r\n 118: \"Out of streams resources\",\r\n 119: \"Machine is not on the network\",\r\n 120: \"Package not installed\",\r\n 121: \"The object is remote\",\r\n 122: \"Advertise error\",\r\n 123: \"Srmount error\",\r\n 124: \"Communication error on send\",\r\n 125: \"Cross mount point (not really error)\",\r\n 126: \"Given log. name not unique\",\r\n 127: \"f.d. invalid for this operation\",\r\n 128: \"Remote address changed\",\r\n 129: \"Can access a needed shared lib\",\r\n 130: \"Accessing a corrupted shared lib\",\r\n 131: \".lib section in a.out corrupted\",\r\n 132: \"Attempting to link in too many libs\",\r\n 133: \"Attempting to exec a shared library\",\r\n 135: \"Streams pipe error\",\r\n 136: \"Too many users\",\r\n 137: \"Socket type not supported\",\r\n 138: \"Not supported\",\r\n 139: \"Protocol family not supported\",\r\n 140: \"Can't send after socket shutdown\",\r\n 141: \"Too many references\",\r\n 142: \"Host is down\",\r\n 148: \"No medium (in tape drive)\",\r\n 156: \"Level 2 not synchronized\"\r\n};\r\n\r\nvar ERRNO_CODES = {};\r\n\r\nvar FS = {\r\n root: null,\r\n mounts: [],\r\n devices: {},\r\n streams: [],\r\n nextInode: 1,\r\n nameTable: null,\r\n currentPath: \"/\",\r\n initialized: false,\r\n ignorePermissions: true,\r\n ErrnoError: null,\r\n genericErrors: {},\r\n filesystems: null,\r\n syncFSRequests: 0,\r\n lookupPath: (path, opts = {}) => {\r\n path = PATH_FS.resolve(FS.cwd(), path);\r\n if (!path) return {\r\n path: \"\",\r\n node: null\r\n };\r\n var defaults = {\r\n follow_mount: true,\r\n recurse_count: 0\r\n };\r\n for (var key in defaults) {\r\n if (opts[key] === undefined) {\r\n opts[key] = defaults[key];\r\n }\r\n }\r\n if (opts.recurse_count > 8) {\r\n throw new FS.ErrnoError(32);\r\n }\r\n var parts = PATH.normalizeArray(path.split(\"/\").filter(p => !!p), false);\r\n var current = FS.root;\r\n var current_path = \"/\";\r\n for (var i = 0; i < parts.length; i++) {\r\n var islast = i === parts.length - 1;\r\n if (islast && opts.parent) {\r\n break;\r\n }\r\n current = FS.lookupNode(current, parts[i]);\r\n current_path = PATH.join2(current_path, parts[i]);\r\n if (FS.isMountpoint(current)) {\r\n if (!islast || islast && opts.follow_mount) {\r\n current = current.mounted.root;\r\n }\r\n }\r\n if (!islast || opts.follow) {\r\n var count = 0;\r\n while (FS.isLink(current.mode)) {\r\n var link = FS.readlink(current_path);\r\n current_path = PATH_FS.resolve(PATH.dirname(current_path), link);\r\n var lookup = FS.lookupPath(current_path, {\r\n recurse_count: opts.recurse_count\r\n });\r\n current = lookup.node;\r\n if (count++ > 40) {\r\n throw new FS.ErrnoError(32);\r\n }\r\n }\r\n }\r\n }\r\n return {\r\n path: current_path,\r\n node: current\r\n };\r\n },\r\n getPath: node => {\r\n var path;\r\n while (true) {\r\n if (FS.isRoot(node)) {\r\n var mount = node.mount.mountpoint;\r\n if (!path) return mount;\r\n return mount[mount.length - 1] !== \"/\" ? mount + \"/\" + path : mount + path;\r\n }\r\n path = path ? node.name + \"/\" + path : node.name;\r\n node = node.parent;\r\n }\r\n },\r\n hashName: (parentid, name) => {\r\n var hash = 0;\r\n for (var i = 0; i < name.length; i++) {\r\n hash = (hash << 5) - hash + name.charCodeAt(i) | 0;\r\n }\r\n return (parentid + hash >>> 0) % FS.nameTable.length;\r\n },\r\n hashAddNode: node => {\r\n var hash = FS.hashName(node.parent.id, node.name);\r\n node.name_next = FS.nameTable[hash];\r\n FS.nameTable[hash] = node;\r\n },\r\n hashRemoveNode: node => {\r\n var hash = FS.hashName(node.parent.id, node.name);\r\n if (FS.nameTable[hash] === node) {\r\n FS.nameTable[hash] = node.name_next;\r\n } else {\r\n var current = FS.nameTable[hash];\r\n while (current) {\r\n if (current.name_next === node) {\r\n current.name_next = node.name_next;\r\n break;\r\n }\r\n current = current.name_next;\r\n }\r\n }\r\n },\r\n lookupNode: (parent, name) => {\r\n var errCode = FS.mayLookup(parent);\r\n if (errCode) {\r\n throw new FS.ErrnoError(errCode, parent);\r\n }\r\n var hash = FS.hashName(parent.id, name);\r\n for (var node = FS.nameTable[hash]; node; node = node.name_next) {\r\n var nodeName = node.name;\r\n if (node.parent.id === parent.id && nodeName === name) {\r\n return node;\r\n }\r\n }\r\n return FS.lookup(parent, name);\r\n },\r\n createNode: (parent, name, mode, rdev) => {\r\n assert(typeof parent === \"object\");\r\n var node = new FS.FSNode(parent, name, mode, rdev);\r\n FS.hashAddNode(node);\r\n return node;\r\n },\r\n destroyNode: node => {\r\n FS.hashRemoveNode(node);\r\n },\r\n isRoot: node => {\r\n return node === node.parent;\r\n },\r\n isMountpoint: node => {\r\n return !!node.mounted;\r\n },\r\n isFile: mode => {\r\n return (mode & 61440) === 32768;\r\n },\r\n isDir: mode => {\r\n return (mode & 61440) === 16384;\r\n },\r\n isLink: mode => {\r\n return (mode & 61440) === 40960;\r\n },\r\n isChrdev: mode => {\r\n return (mode & 61440) === 8192;\r\n },\r\n isBlkdev: mode => {\r\n return (mode & 61440) === 24576;\r\n },\r\n isFIFO: mode => {\r\n return (mode & 61440) === 4096;\r\n },\r\n isSocket: mode => {\r\n return (mode & 49152) === 49152;\r\n },\r\n flagModes: {\r\n \"r\": 0,\r\n \"r+\": 2,\r\n \"w\": 577,\r\n \"w+\": 578,\r\n \"a\": 1089,\r\n \"a+\": 1090\r\n },\r\n modeStringToFlags: str => {\r\n var flags = FS.flagModes[str];\r\n if (typeof flags === \"undefined\") {\r\n throw new Error(\"Unknown file open mode: \" + str);\r\n }\r\n return flags;\r\n },\r\n flagsToPermissionString: flag => {\r\n var perms = [ \"r\", \"w\", \"rw\" ][flag & 3];\r\n if (flag & 512) {\r\n perms += \"w\";\r\n }\r\n return perms;\r\n },\r\n nodePermissions: (node, perms) => {\r\n if (FS.ignorePermissions) {\r\n return 0;\r\n }\r\n if (perms.includes(\"r\") && !(node.mode & 292)) {\r\n return 2;\r\n } else if (perms.includes(\"w\") && !(node.mode & 146)) {\r\n return 2;\r\n } else if (perms.includes(\"x\") && !(node.mode & 73)) {\r\n return 2;\r\n }\r\n return 0;\r\n },\r\n mayLookup: dir => {\r\n var errCode = FS.nodePermissions(dir, \"x\");\r\n if (errCode) return errCode;\r\n if (!dir.node_ops.lookup) return 2;\r\n return 0;\r\n },\r\n mayCreate: (dir, name) => {\r\n try {\r\n var node = FS.lookupNode(dir, name);\r\n return 20;\r\n } catch (e) {}\r\n return FS.nodePermissions(dir, \"wx\");\r\n },\r\n mayDelete: (dir, name, isdir) => {\r\n var node;\r\n try {\r\n node = FS.lookupNode(dir, name);\r\n } catch (e) {\r\n return e.errno;\r\n }\r\n var errCode = FS.nodePermissions(dir, \"wx\");\r\n if (errCode) {\r\n return errCode;\r\n }\r\n if (isdir) {\r\n if (!FS.isDir(node.mode)) {\r\n return 54;\r\n }\r\n if (FS.isRoot(node) || FS.getPath(node) === FS.cwd()) {\r\n return 10;\r\n }\r\n } else {\r\n if (FS.isDir(node.mode)) {\r\n return 31;\r\n }\r\n }\r\n return 0;\r\n },\r\n mayOpen: (node, flags) => {\r\n if (!node) {\r\n return 44;\r\n }\r\n if (FS.isLink(node.mode)) {\r\n return 32;\r\n } else if (FS.isDir(node.mode)) {\r\n if (FS.flagsToPermissionString(flags) !== \"r\" || flags & 512) {\r\n return 31;\r\n }\r\n }\r\n return FS.nodePermissions(node, FS.flagsToPermissionString(flags));\r\n },\r\n MAX_OPEN_FDS: 4096,\r\n nextfd: (fd_start = 0, fd_end = FS.MAX_OPEN_FDS) => {\r\n for (var fd = fd_start; fd <= fd_end; fd++) {\r\n if (!FS.streams[fd]) {\r\n return fd;\r\n }\r\n }\r\n throw new FS.ErrnoError(33);\r\n },\r\n getStream: fd => FS.streams[fd],\r\n createStream: (stream, fd_start, fd_end) => {\r\n if (!FS.FSStream) {\r\n FS.FSStream = function() {};\r\n FS.FSStream.prototype = {\r\n object: {\r\n get: function() {\r\n return this.node;\r\n },\r\n set: function(val) {\r\n this.node = val;\r\n }\r\n },\r\n isRead: {\r\n get: function() {\r\n return (this.flags & 2097155) !== 1;\r\n }\r\n },\r\n isWrite: {\r\n get: function() {\r\n return (this.flags & 2097155) !== 0;\r\n }\r\n },\r\n isAppend: {\r\n get: function() {\r\n return this.flags & 1024;\r\n }\r\n }\r\n };\r\n }\r\n stream = Object.assign(new FS.FSStream(), stream);\r\n var fd = FS.nextfd(fd_start, fd_end);\r\n stream.fd = fd;\r\n FS.streams[fd] = stream;\r\n return stream;\r\n },\r\n closeStream: fd => {\r\n FS.streams[fd] = null;\r\n },\r\n chrdev_stream_ops: {\r\n open: stream => {\r\n var device = FS.getDevice(stream.node.rdev);\r\n stream.stream_ops = device.stream_ops;\r\n if (stream.stream_ops.open) {\r\n stream.stream_ops.open(stream);\r\n }\r\n },\r\n llseek: () => {\r\n throw new FS.ErrnoError(70);\r\n }\r\n },\r\n major: dev => dev >> 8,\r\n minor: dev => dev & 255,\r\n makedev: (ma, mi) => ma << 8 | mi,\r\n registerDevice: (dev, ops) => {\r\n FS.devices[dev] = {\r\n stream_ops: ops\r\n };\r\n },\r\n getDevice: dev => FS.devices[dev],\r\n getMounts: mount => {\r\n var mounts = [];\r\n var check = [ mount ];\r\n while (check.length) {\r\n var m = check.pop();\r\n mounts.push(m);\r\n check.push.apply(check, m.mounts);\r\n }\r\n return mounts;\r\n },\r\n syncfs: (populate, callback) => {\r\n if (typeof populate === \"function\") {\r\n callback = populate;\r\n populate = false;\r\n }\r\n FS.syncFSRequests++;\r\n if (FS.syncFSRequests > 1) {\r\n err(\"warning: \" + FS.syncFSRequests + \" FS.syncfs operations in flight at once, probably just doing extra work\");\r\n }\r\n var mounts = FS.getMounts(FS.root.mount);\r\n var completed = 0;\r\n function doCallback(errCode) {\r\n assert(FS.syncFSRequests > 0);\r\n FS.syncFSRequests--;\r\n return callback(errCode);\r\n }\r\n function done(errCode) {\r\n if (errCode) {\r\n if (!done.errored) {\r\n done.errored = true;\r\n return doCallback(errCode);\r\n }\r\n return;\r\n }\r\n if (++completed >= mounts.length) {\r\n doCallback(null);\r\n }\r\n }\r\n mounts.forEach(mount => {\r\n if (!mount.type.syncfs) {\r\n return done(null);\r\n }\r\n mount.type.syncfs(mount, populate, done);\r\n });\r\n },\r\n mount: (type, opts, mountpoint) => {\r\n if (typeof type === \"string\") {\r\n throw type;\r\n }\r\n var root = mountpoint === \"/\";\r\n var pseudo = !mountpoint;\r\n var node;\r\n if (root && FS.root) {\r\n throw new FS.ErrnoError(10);\r\n } else if (!root && !pseudo) {\r\n var lookup = FS.lookupPath(mountpoint, {\r\n follow_mount: false\r\n });\r\n mountpoint = lookup.path;\r\n node = lookup.node;\r\n if (FS.isMountpoint(node)) {\r\n throw new FS.ErrnoError(10);\r\n }\r\n if (!FS.isDir(node.mode)) {\r\n throw new FS.ErrnoError(54);\r\n }\r\n }\r\n var mount = {\r\n type: type,\r\n opts: opts,\r\n mountpoint: mountpoint,\r\n mounts: []\r\n };\r\n var mountRoot = type.mount(mount);\r\n mountRoot.mount = mount;\r\n mount.root = mountRoot;\r\n if (root) {\r\n FS.root = mountRoot;\r\n } else if (node) {\r\n node.mounted = mount;\r\n if (node.mount) {\r\n node.mount.mounts.push(mount);\r\n }\r\n }\r\n return mountRoot;\r\n },\r\n unmount: mountpoint => {\r\n var lookup = FS.lookupPath(mountpoint, {\r\n follow_mount: false\r\n });\r\n if (!FS.isMountpoint(lookup.node)) {\r\n throw new FS.ErrnoError(28);\r\n }\r\n var node = lookup.node;\r\n var mount = node.mounted;\r\n var mounts = FS.getMounts(mount);\r\n Object.keys(FS.nameTable).forEach(hash => {\r\n var current = FS.nameTable[hash];\r\n while (current) {\r\n var next = current.name_next;\r\n if (mounts.includes(current.mount)) {\r\n FS.destroyNode(current);\r\n }\r\n current = next;\r\n }\r\n });\r\n node.mounted = null;\r\n var idx = node.mount.mounts.indexOf(mount);\r\n assert(idx !== -1);\r\n node.mount.mounts.splice(idx, 1);\r\n },\r\n lookup: (parent, name) => {\r\n return parent.node_ops.lookup(parent, name);\r\n },\r\n mknod: (path, mode, dev) => {\r\n var lookup = FS.lookupPath(path, {\r\n parent: true\r\n });\r\n var parent = lookup.node;\r\n var name = PATH.basename(path);\r\n if (!name || name === \".\" || name === \"..\") {\r\n throw new FS.ErrnoError(28);\r\n }\r\n var errCode = FS.mayCreate(parent, name);\r\n if (errCode) {\r\n throw new FS.ErrnoError(errCode);\r\n }\r\n if (!parent.node_ops.mknod) {\r\n throw new FS.ErrnoError(63);\r\n }\r\n return parent.node_ops.mknod(parent, name, mode, dev);\r\n },\r\n create: (path, mode) => {\r\n mode = mode !== undefined ? mode : 438;\r\n mode &= 4095;\r\n mode |= 32768;\r\n return FS.mknod(path, mode, 0);\r\n },\r\n mkdir: (path, mode) => {\r\n mode = mode !== undefined ? mode : 511;\r\n mode &= 511 | 512;\r\n mode |= 16384;\r\n return FS.mknod(path, mode, 0);\r\n },\r\n mkdirTree: (path, mode) => {\r\n var dirs = path.split(\"/\");\r\n var d = \"\";\r\n for (var i = 0; i < dirs.length; ++i) {\r\n if (!dirs[i]) continue;\r\n d += \"/\" + dirs[i];\r\n try {\r\n FS.mkdir(d, mode);\r\n } catch (e) {\r\n if (e.errno != 20) throw e;\r\n }\r\n }\r\n },\r\n mkdev: (path, mode, dev) => {\r\n if (typeof dev === \"undefined\") {\r\n dev = mode;\r\n mode = 438;\r\n }\r\n mode |= 8192;\r\n return FS.mknod(path, mode, dev);\r\n },\r\n symlink: (oldpath, newpath) => {\r\n if (!PATH_FS.resolve(oldpath)) {\r\n throw new FS.ErrnoError(44);\r\n }\r\n var lookup = FS.lookupPath(newpath, {\r\n parent: true\r\n });\r\n var parent = lookup.node;\r\n if (!parent) {\r\n throw new FS.ErrnoError(44);\r\n }\r\n var newname = PATH.basename(newpath);\r\n var errCode = FS.mayCreate(parent, newname);\r\n if (errCode) {\r\n throw new FS.ErrnoError(errCode);\r\n }\r\n if (!parent.node_ops.symlink) {\r\n throw new FS.ErrnoError(63);\r\n }\r\n return parent.node_ops.symlink(parent, newname, oldpath);\r\n },\r\n rename: (old_path, new_path) => {\r\n var old_dirname = PATH.dirname(old_path);\r\n var new_dirname = PATH.dirname(new_path);\r\n var old_name = PATH.basename(old_path);\r\n var new_name = PATH.basename(new_path);\r\n var lookup, old_dir, new_dir;\r\n lookup = FS.lookupPath(old_path, {\r\n parent: true\r\n });\r\n old_dir = lookup.node;\r\n lookup = FS.lookupPath(new_path, {\r\n parent: true\r\n });\r\n new_dir = lookup.node;\r\n if (!old_dir || !new_dir) throw new FS.ErrnoError(44);\r\n if (old_dir.mount !== new_dir.mount) {\r\n throw new FS.ErrnoError(75);\r\n }\r\n var old_node = FS.lookupNode(old_dir, old_name);\r\n var relative = PATH_FS.relative(old_path, new_dirname);\r\n if (relative.charAt(0) !== \".\") {\r\n throw new FS.ErrnoError(28);\r\n }\r\n relative = PATH_FS.relative(new_path, old_dirname);\r\n if (relative.charAt(0) !== \".\") {\r\n throw new FS.ErrnoError(55);\r\n }\r\n var new_node;\r\n try {\r\n new_node = FS.lookupNode(new_dir, new_name);\r\n } catch (e) {}\r\n if (old_node === new_node) {\r\n return;\r\n }\r\n var isdir = FS.isDir(old_node.mode);\r\n var errCode = FS.mayDelete(old_dir, old_name, isdir);\r\n if (errCode) {\r\n throw new FS.ErrnoError(errCode);\r\n }\r\n errCode = new_node ? FS.mayDelete(new_dir, new_name, isdir) : FS.mayCreate(new_dir, new_name);\r\n if (errCode) {\r\n throw new FS.ErrnoError(errCode);\r\n }\r\n if (!old_dir.node_ops.rename) {\r\n throw new FS.ErrnoError(63);\r\n }\r\n if (FS.isMountpoint(old_node) || new_node && FS.isMountpoint(new_node)) {\r\n throw new FS.ErrnoError(10);\r\n }\r\n if (new_dir !== old_dir) {\r\n errCode = FS.nodePermissions(old_dir, \"w\");\r\n if (errCode) {\r\n throw new FS.ErrnoError(errCode);\r\n }\r\n }\r\n FS.hashRemoveNode(old_node);\r\n try {\r\n old_dir.node_ops.rename(old_node, new_dir, new_name);\r\n } catch (e) {\r\n throw e;\r\n } finally {\r\n FS.hashAddNode(old_node);\r\n }\r\n },\r\n rmdir: path => {\r\n var lookup = FS.lookupPath(path, {\r\n parent: true\r\n });\r\n var parent = lookup.node;\r\n var name = PATH.basename(path);\r\n var node = FS.lookupNode(parent, name);\r\n var errCode = FS.mayDelete(parent, name, true);\r\n if (errCode) {\r\n throw new FS.ErrnoError(errCode);\r\n }\r\n if (!parent.node_ops.rmdir) {\r\n throw new FS.ErrnoError(63);\r\n }\r\n if (FS.isMountpoint(node)) {\r\n throw new FS.ErrnoError(10);\r\n }\r\n parent.node_ops.rmdir(parent, name);\r\n FS.destroyNode(node);\r\n },\r\n readdir: path => {\r\n var lookup = FS.lookupPath(path, {\r\n follow: true\r\n });\r\n var node = lookup.node;\r\n if (!node.node_ops.readdir) {\r\n throw new FS.ErrnoError(54);\r\n }\r\n return node.node_ops.readdir(node);\r\n },\r\n unlink: path => {\r\n var lookup = FS.lookupPath(path, {\r\n parent: true\r\n });\r\n var parent = lookup.node;\r\n if (!parent) {\r\n throw new FS.ErrnoError(44);\r\n }\r\n var name = PATH.basename(path);\r\n var node = FS.lookupNode(parent, name);\r\n var errCode = FS.mayDelete(parent, name, false);\r\n if (errCode) {\r\n throw new FS.ErrnoError(errCode);\r\n }\r\n if (!parent.node_ops.unlink) {\r\n throw new FS.ErrnoError(63);\r\n }\r\n if (FS.isMountpoint(node)) {\r\n throw new FS.ErrnoError(10);\r\n }\r\n parent.node_ops.unlink(parent, name);\r\n FS.destroyNode(node);\r\n },\r\n readlink: path => {\r\n var lookup = FS.lookupPath(path);\r\n var link = lookup.node;\r\n if (!link) {\r\n throw new FS.ErrnoError(44);\r\n }\r\n if (!link.node_ops.readlink) {\r\n throw new FS.ErrnoError(28);\r\n }\r\n return PATH_FS.resolve(FS.getPath(link.parent), link.node_ops.readlink(link));\r\n },\r\n stat: (path, dontFollow) => {\r\n var lookup = FS.lookupPath(path, {\r\n follow: !dontFollow\r\n });\r\n var node = lookup.node;\r\n if (!node) {\r\n throw new FS.ErrnoError(44);\r\n }\r\n if (!node.node_ops.getattr) {\r\n throw new FS.ErrnoError(63);\r\n }\r\n return node.node_ops.getattr(node);\r\n },\r\n lstat: path => {\r\n return FS.stat(path, true);\r\n },\r\n chmod: (path, mode, dontFollow) => {\r\n var node;\r\n if (typeof path === \"string\") {\r\n var lookup = FS.lookupPath(path, {\r\n follow: !dontFollow\r\n });\r\n node = lookup.node;\r\n } else {\r\n node = path;\r\n }\r\n if (!node.node_ops.setattr) {\r\n throw new FS.ErrnoError(63);\r\n }\r\n node.node_ops.setattr(node, {\r\n mode: mode & 4095 | node.mode & ~4095,\r\n timestamp: Date.now()\r\n });\r\n },\r\n lchmod: (path, mode) => {\r\n FS.chmod(path, mode, true);\r\n },\r\n fchmod: (fd, mode) => {\r\n var stream = FS.getStream(fd);\r\n if (!stream) {\r\n throw new FS.ErrnoError(8);\r\n }\r\n FS.chmod(stream.node, mode);\r\n },\r\n chown: (path, uid, gid, dontFollow) => {\r\n var node;\r\n if (typeof path === \"string\") {\r\n var lookup = FS.lookupPath(path, {\r\n follow: !dontFollow\r\n });\r\n node = lookup.node;\r\n } else {\r\n node = path;\r\n }\r\n if (!node.node_ops.setattr) {\r\n throw new FS.ErrnoError(63);\r\n }\r\n node.node_ops.setattr(node, {\r\n timestamp: Date.now()\r\n });\r\n },\r\n lchown: (path, uid, gid) => {\r\n FS.chown(path, uid, gid, true);\r\n },\r\n fchown: (fd, uid, gid) => {\r\n var stream = FS.getStream(fd);\r\n if (!stream) {\r\n throw new FS.ErrnoError(8);\r\n }\r\n FS.chown(stream.node, uid, gid);\r\n },\r\n truncate: (path, len) => {\r\n if (len < 0) {\r\n throw new FS.ErrnoError(28);\r\n }\r\n var node;\r\n if (typeof path === \"string\") {\r\n var lookup = FS.lookupPath(path, {\r\n follow: true\r\n });\r\n node = lookup.node;\r\n } else {\r\n node = path;\r\n }\r\n if (!node.node_ops.setattr) {\r\n throw new FS.ErrnoError(63);\r\n }\r\n if (FS.isDir(node.mode)) {\r\n throw new FS.ErrnoError(31);\r\n }\r\n if (!FS.isFile(node.mode)) {\r\n throw new FS.ErrnoError(28);\r\n }\r\n var errCode = FS.nodePermissions(node, \"w\");\r\n if (errCode) {\r\n throw new FS.ErrnoError(errCode);\r\n }\r\n node.node_ops.setattr(node, {\r\n size: len,\r\n timestamp: Date.now()\r\n });\r\n },\r\n ftruncate: (fd, len) => {\r\n var stream = FS.getStream(fd);\r\n if (!stream) {\r\n throw new FS.ErrnoError(8);\r\n }\r\n if ((stream.flags & 2097155) === 0) {\r\n throw new FS.ErrnoError(28);\r\n }\r\n FS.truncate(stream.node, len);\r\n },\r\n utime: (path, atime, mtime) => {\r\n var lookup = FS.lookupPath(path, {\r\n follow: true\r\n });\r\n var node = lookup.node;\r\n node.node_ops.setattr(node, {\r\n timestamp: Math.max(atime, mtime)\r\n });\r\n },\r\n open: (path, flags, mode, fd_start, fd_end) => {\r\n if (path === \"\") {\r\n throw new FS.ErrnoError(44);\r\n }\r\n flags = typeof flags === \"string\" ? FS.modeStringToFlags(flags) : flags;\r\n mode = typeof mode === \"undefined\" ? 438 : mode;\r\n if (flags & 64) {\r\n mode = mode & 4095 | 32768;\r\n } else {\r\n mode = 0;\r\n }\r\n var node;\r\n if (typeof path === \"object\") {\r\n node = path;\r\n } else {\r\n path = PATH.normalize(path);\r\n try {\r\n var lookup = FS.lookupPath(path, {\r\n follow: !(flags & 131072)\r\n });\r\n node = lookup.node;\r\n } catch (e) {}\r\n }\r\n var created = false;\r\n if (flags & 64) {\r\n if (node) {\r\n if (flags & 128) {\r\n throw new FS.ErrnoError(20);\r\n }\r\n } else {\r\n node = FS.mknod(path, mode, 0);\r\n created = true;\r\n }\r\n }\r\n if (!node) {\r\n throw new FS.ErrnoError(44);\r\n }\r\n if (FS.isChrdev(node.mode)) {\r\n flags &= ~512;\r\n }\r\n if (flags & 65536 && !FS.isDir(node.mode)) {\r\n throw new FS.ErrnoError(54);\r\n }\r\n if (!created) {\r\n var errCode = FS.mayOpen(node, flags);\r\n if (errCode) {\r\n throw new FS.ErrnoError(errCode);\r\n }\r\n }\r\n if (flags & 512) {\r\n FS.truncate(node, 0);\r\n }\r\n flags &= ~(128 | 512 | 131072);\r\n var stream = FS.createStream({\r\n node: node,\r\n path: FS.getPath(node),\r\n flags: flags,\r\n seekable: true,\r\n position: 0,\r\n stream_ops: node.stream_ops,\r\n ungotten: [],\r\n error: false\r\n }, fd_start, fd_end);\r\n if (stream.stream_ops.open) {\r\n stream.stream_ops.open(stream);\r\n }\r\n if (Module[\"logReadFiles\"] && !(flags & 1)) {\r\n if (!FS.readFiles) FS.readFiles = {};\r\n if (!(path in FS.readFiles)) {\r\n FS.readFiles[path] = 1;\r\n }\r\n }\r\n return stream;\r\n },\r\n close: stream => {\r\n if (FS.isClosed(stream)) {\r\n throw new FS.ErrnoError(8);\r\n }\r\n if (stream.getdents) stream.getdents = null;\r\n try {\r\n if (stream.stream_ops.close) {\r\n stream.stream_ops.close(stream);\r\n }\r\n } catch (e) {\r\n throw e;\r\n } finally {\r\n FS.closeStream(stream.fd);\r\n }\r\n stream.fd = null;\r\n },\r\n isClosed: stream => {\r\n return stream.fd === null;\r\n },\r\n llseek: (stream, offset, whence) => {\r\n if (FS.isClosed(stream)) {\r\n throw new FS.ErrnoError(8);\r\n }\r\n if (!stream.seekable || !stream.stream_ops.llseek) {\r\n throw new FS.ErrnoError(70);\r\n }\r\n if (whence != 0 && whence != 1 && whence != 2) {\r\n throw new FS.ErrnoError(28);\r\n }\r\n stream.position = stream.stream_ops.llseek(stream, offset, whence);\r\n stream.ungotten = [];\r\n return stream.position;\r\n },\r\n read: (stream, buffer, offset, length, position) => {\r\n if (length < 0 || position < 0) {\r\n throw new FS.ErrnoError(28);\r\n }\r\n if (FS.isClosed(stream)) {\r\n throw new FS.ErrnoError(8);\r\n }\r\n if ((stream.flags & 2097155) === 1) {\r\n throw new FS.ErrnoError(8);\r\n }\r\n if (FS.isDir(stream.node.mode)) {\r\n throw new FS.ErrnoError(31);\r\n }\r\n if (!stream.stream_ops.read) {\r\n throw new FS.ErrnoError(28);\r\n }\r\n var seeking = typeof position !== \"undefined\";\r\n if (!seeking) {\r\n position = stream.position;\r\n } else if (!stream.seekable) {\r\n throw new FS.ErrnoError(70);\r\n }\r\n var bytesRead = stream.stream_ops.read(stream, buffer, offset, length, position);\r\n if (!seeking) stream.position += bytesRead;\r\n return bytesRead;\r\n },\r\n write: (stream, buffer, offset, length, position, canOwn) => {\r\n if (length < 0 || position < 0) {\r\n throw new FS.ErrnoError(28);\r\n }\r\n if (FS.isClosed(stream)) {\r\n throw new FS.ErrnoError(8);\r\n }\r\n if ((stream.flags & 2097155) === 0) {\r\n throw new FS.ErrnoError(8);\r\n }\r\n if (FS.isDir(stream.node.mode)) {\r\n throw new FS.ErrnoError(31);\r\n }\r\n if (!stream.stream_ops.write) {\r\n throw new FS.ErrnoError(28);\r\n }\r\n if (stream.seekable && stream.flags & 1024) {\r\n FS.llseek(stream, 0, 2);\r\n }\r\n var seeking = typeof position !== \"undefined\";\r\n if (!seeking) {\r\n position = stream.position;\r\n } else if (!stream.seekable) {\r\n throw new FS.ErrnoError(70);\r\n }\r\n var bytesWritten = stream.stream_ops.write(stream, buffer, offset, length, position, canOwn);\r\n if (!seeking) stream.position += bytesWritten;\r\n return bytesWritten;\r\n },\r\n allocate: (stream, offset, length) => {\r\n if (FS.isClosed(stream)) {\r\n throw new FS.ErrnoError(8);\r\n }\r\n if (offset < 0 || length <= 0) {\r\n throw new FS.ErrnoError(28);\r\n }\r\n if ((stream.flags & 2097155) === 0) {\r\n throw new FS.ErrnoError(8);\r\n }\r\n if (!FS.isFile(stream.node.mode) && !FS.isDir(stream.node.mode)) {\r\n throw new FS.ErrnoError(43);\r\n }\r\n if (!stream.stream_ops.allocate) {\r\n throw new FS.ErrnoError(138);\r\n }\r\n stream.stream_ops.allocate(stream, offset, length);\r\n },\r\n mmap: (stream, address, length, position, prot, flags) => {\r\n if ((prot & 2) !== 0 && (flags & 2) === 0 && (stream.flags & 2097155) !== 2) {\r\n throw new FS.ErrnoError(2);\r\n }\r\n if ((stream.flags & 2097155) === 1) {\r\n throw new FS.ErrnoError(2);\r\n }\r\n if (!stream.stream_ops.mmap) {\r\n throw new FS.ErrnoError(43);\r\n }\r\n return stream.stream_ops.mmap(stream, address, length, position, prot, flags);\r\n },\r\n msync: (stream, buffer, offset, length, mmapFlags) => {\r\n if (!stream || !stream.stream_ops.msync) {\r\n return 0;\r\n }\r\n return stream.stream_ops.msync(stream, buffer, offset, length, mmapFlags);\r\n },\r\n munmap: stream => 0,\r\n ioctl: (stream, cmd, arg) => {\r\n if (!stream.stream_ops.ioctl) {\r\n throw new FS.ErrnoError(59);\r\n }\r\n return stream.stream_ops.ioctl(stream, cmd, arg);\r\n },\r\n readFile: (path, opts = {}) => {\r\n opts.flags = opts.flags || 0;\r\n opts.encoding = opts.encoding || \"binary\";\r\n if (opts.encoding !== \"utf8\" && opts.encoding !== \"binary\") {\r\n throw new Error('Invalid encoding type \"' + opts.encoding + '\"');\r\n }\r\n var ret;\r\n var stream = FS.open(path, opts.flags);\r\n var stat = FS.stat(path);\r\n var length = stat.size;\r\n var buf = new Uint8Array(length);\r\n FS.read(stream, buf, 0, length, 0);\r\n if (opts.encoding === \"utf8\") {\r\n ret = UTF8ArrayToString(buf, 0);\r\n } else if (opts.encoding === \"binary\") {\r\n ret = buf;\r\n }\r\n FS.close(stream);\r\n return ret;\r\n },\r\n writeFile: (path, data, opts = {}) => {\r\n opts.flags = opts.flags || 577;\r\n var stream = FS.open(path, opts.flags, opts.mode);\r\n if (typeof data === \"string\") {\r\n var buf = new Uint8Array(lengthBytesUTF8(data) + 1);\r\n var actualNumBytes = stringToUTF8Array(data, buf, 0, buf.length);\r\n FS.write(stream, buf, 0, actualNumBytes, undefined, opts.canOwn);\r\n } else if (ArrayBuffer.isView(data)) {\r\n FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn);\r\n } else {\r\n throw new Error(\"Unsupported data type\");\r\n }\r\n FS.close(stream);\r\n },\r\n cwd: () => FS.currentPath,\r\n chdir: path => {\r\n var lookup = FS.lookupPath(path, {\r\n follow: true\r\n });\r\n if (lookup.node === null) {\r\n throw new FS.ErrnoError(44);\r\n }\r\n if (!FS.isDir(lookup.node.mode)) {\r\n throw new FS.ErrnoError(54);\r\n }\r\n var errCode = FS.nodePermissions(lookup.node, \"x\");\r\n if (errCode) {\r\n throw new FS.ErrnoError(errCode);\r\n }\r\n FS.currentPath = lookup.path;\r\n },\r\n createDefaultDirectories: () => {\r\n FS.mkdir(\"/tmp\");\r\n FS.mkdir(\"/home\");\r\n FS.mkdir(\"/home/web_user\");\r\n },\r\n createDefaultDevices: () => {\r\n FS.mkdir(\"/dev\");\r\n FS.registerDevice(FS.makedev(1, 3), {\r\n read: () => 0,\r\n write: (stream, buffer, offset, length, pos) => length\r\n });\r\n FS.mkdev(\"/dev/null\", FS.makedev(1, 3));\r\n TTY.register(FS.makedev(5, 0), TTY.default_tty_ops);\r\n TTY.register(FS.makedev(6, 0), TTY.default_tty1_ops);\r\n FS.mkdev(\"/dev/tty\", FS.makedev(5, 0));\r\n FS.mkdev(\"/dev/tty1\", FS.makedev(6, 0));\r\n var random_device = getRandomDevice();\r\n FS.createDevice(\"/dev\", \"random\", random_device);\r\n FS.createDevice(\"/dev\", \"urandom\", random_device);\r\n FS.mkdir(\"/dev/shm\");\r\n FS.mkdir(\"/dev/shm/tmp\");\r\n },\r\n createSpecialDirectories: () => {\r\n FS.mkdir(\"/proc\");\r\n var proc_self = FS.mkdir(\"/proc/self\");\r\n FS.mkdir(\"/proc/self/fd\");\r\n FS.mount({\r\n mount: () => {\r\n var node = FS.createNode(proc_self, \"fd\", 16384 | 511, 73);\r\n node.node_ops = {\r\n lookup: (parent, name) => {\r\n var fd = +name;\r\n var stream = FS.getStream(fd);\r\n if (!stream) throw new FS.ErrnoError(8);\r\n var ret = {\r\n parent: null,\r\n mount: {\r\n mountpoint: \"fake\"\r\n },\r\n node_ops: {\r\n readlink: () => stream.path\r\n }\r\n };\r\n ret.parent = ret;\r\n return ret;\r\n }\r\n };\r\n return node;\r\n }\r\n }, {}, \"/proc/self/fd\");\r\n },\r\n createStandardStreams: () => {\r\n if (Module[\"stdin\"]) {\r\n FS.createDevice(\"/dev\", \"stdin\", Module[\"stdin\"]);\r\n } else {\r\n FS.symlink(\"/dev/tty\", \"/dev/stdin\");\r\n }\r\n if (Module[\"stdout\"]) {\r\n FS.createDevice(\"/dev\", \"stdout\", null, Module[\"stdout\"]);\r\n } else {\r\n FS.symlink(\"/dev/tty\", \"/dev/stdout\");\r\n }\r\n if (Module[\"stderr\"]) {\r\n FS.createDevice(\"/dev\", \"stderr\", null, Module[\"stderr\"]);\r\n } else {\r\n FS.symlink(\"/dev/tty1\", \"/dev/stderr\");\r\n }\r\n var stdin = FS.open(\"/dev/stdin\", 0);\r\n var stdout = FS.open(\"/dev/stdout\", 1);\r\n var stderr = FS.open(\"/dev/stderr\", 1);\r\n assert(stdin.fd === 0, \"invalid handle for stdin (\" + stdin.fd + \")\");\r\n assert(stdout.fd === 1, \"invalid handle for stdout (\" + stdout.fd + \")\");\r\n assert(stderr.fd === 2, \"invalid handle for stderr (\" + stderr.fd + \")\");\r\n },\r\n ensureErrnoError: () => {\r\n if (FS.ErrnoError) return;\r\n FS.ErrnoError = function ErrnoError(errno, node) {\r\n this.node = node;\r\n this.setErrno = function(errno) {\r\n this.errno = errno;\r\n for (var key in ERRNO_CODES) {\r\n if (ERRNO_CODES[key] === errno) {\r\n this.code = key;\r\n break;\r\n }\r\n }\r\n };\r\n this.setErrno(errno);\r\n this.message = ERRNO_MESSAGES[errno];\r\n if (this.stack) {\r\n Object.defineProperty(this, \"stack\", {\r\n value: new Error().stack,\r\n writable: true\r\n });\r\n this.stack = demangleAll(this.stack);\r\n }\r\n };\r\n FS.ErrnoError.prototype = new Error();\r\n FS.ErrnoError.prototype.constructor = FS.ErrnoError;\r\n [ 44 ].forEach(code => {\r\n FS.genericErrors[code] = new FS.ErrnoError(code);\r\n FS.genericErrors[code].stack = \"<generic error, no stack>\";\r\n });\r\n },\r\n staticInit: () => {\r\n FS.ensureErrnoError();\r\n FS.nameTable = new Array(4096);\r\n FS.mount(MEMFS, {}, \"/\");\r\n FS.createDefaultDirectories();\r\n FS.createDefaultDevices();\r\n FS.createSpecialDirectories();\r\n FS.filesystems = {\r\n \"MEMFS\": MEMFS\r\n };\r\n },\r\n init: (input, output, error) => {\r\n assert(!FS.init.initialized, \"FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)\");\r\n FS.init.initialized = true;\r\n FS.ensureErrnoError();\r\n Module[\"stdin\"] = input || Module[\"stdin\"];\r\n Module[\"stdout\"] = output || Module[\"stdout\"];\r\n Module[\"stderr\"] = error || Module[\"stderr\"];\r\n FS.createStandardStreams();\r\n },\r\n quit: () => {\r\n FS.init.initialized = false;\r\n ___stdio_exit();\r\n for (var i = 0; i < FS.streams.length; i++) {\r\n var stream = FS.streams[i];\r\n if (!stream) {\r\n continue;\r\n }\r\n FS.close(stream);\r\n }\r\n },\r\n getMode: (canRead, canWrite) => {\r\n var mode = 0;\r\n if (canRead) mode |= 292 | 73;\r\n if (canWrite) mode |= 146;\r\n return mode;\r\n },\r\n findObject: (path, dontResolveLastLink) => {\r\n var ret = FS.analyzePath(path, dontResolveLastLink);\r\n if (ret.exists) {\r\n return ret.object;\r\n } else {\r\n return null;\r\n }\r\n },\r\n analyzePath: (path, dontResolveLastLink) => {\r\n try {\r\n var lookup = FS.lookupPath(path, {\r\n follow: !dontResolveLastLink\r\n });\r\n path = lookup.path;\r\n } catch (e) {}\r\n var ret = {\r\n isRoot: false,\r\n exists: false,\r\n error: 0,\r\n name: null,\r\n path: null,\r\n object: null,\r\n parentExists: false,\r\n parentPath: null,\r\n parentObject: null\r\n };\r\n try {\r\n var lookup = FS.lookupPath(path, {\r\n parent: true\r\n });\r\n ret.parentExists = true;\r\n ret.parentPath = lookup.path;\r\n ret.parentObject = lookup.node;\r\n ret.name = PATH.basename(path);\r\n lookup = FS.lookupPath(path, {\r\n follow: !dontResolveLastLink\r\n });\r\n ret.exists = true;\r\n ret.path = lookup.path;\r\n ret.object = lookup.node;\r\n ret.name = lookup.node.name;\r\n ret.isRoot = lookup.path === \"/\";\r\n } catch (e) {\r\n ret.error = e.errno;\r\n }\r\n return ret;\r\n },\r\n createPath: (parent, path, canRead, canWrite) => {\r\n parent = typeof parent === \"string\" ? parent : FS.getPath(parent);\r\n var parts = path.split(\"/\").reverse();\r\n while (parts.length) {\r\n var part = parts.pop();\r\n if (!part) continue;\r\n var current = PATH.join2(parent, part);\r\n try {\r\n FS.mkdir(current);\r\n } catch (e) {}\r\n parent = current;\r\n }\r\n return current;\r\n },\r\n createFile: (parent, name, properties, canRead, canWrite) => {\r\n var path = PATH.join2(typeof parent === \"string\" ? parent : FS.getPath(parent), name);\r\n var mode = FS.getMode(canRead, canWrite);\r\n return FS.create(path, mode);\r\n },\r\n createDataFile: (parent, name, data, canRead, canWrite, canOwn) => {\r\n var path = name;\r\n if (parent) {\r\n parent = typeof parent === \"string\" ? parent : FS.getPath(parent);\r\n path = name ? PATH.join2(parent, name) : parent;\r\n }\r\n var mode = FS.getMode(canRead, canWrite);\r\n var node = FS.create(path, mode);\r\n if (data) {\r\n if (typeof data === \"string\") {\r\n var arr = new Array(data.length);\r\n for (var i = 0, len = data.length; i < len; ++i) arr[i] = data.charCodeAt(i);\r\n data = arr;\r\n }\r\n FS.chmod(node, mode | 146);\r\n var stream = FS.open(node, 577);\r\n FS.write(stream, data, 0, data.length, 0, canOwn);\r\n FS.close(stream);\r\n FS.chmod(node, mode);\r\n }\r\n return node;\r\n },\r\n createDevice: (parent, name, input, output) => {\r\n var path = PATH.join2(typeof parent === \"string\" ? parent : FS.getPath(parent), name);\r\n var mode = FS.getMode(!!input, !!output);\r\n if (!FS.createDevice.major) FS.createDevice.major = 64;\r\n var dev = FS.makedev(FS.createDevice.major++, 0);\r\n FS.registerDevice(dev, {\r\n open: stream => {\r\n stream.seekable = false;\r\n },\r\n close: stream => {\r\n if (output && output.buffer && output.buffer.length) {\r\n output(10);\r\n }\r\n },\r\n read: (stream, buffer, offset, length, pos) => {\r\n var bytesRead = 0;\r\n for (var i = 0; i < length; i++) {\r\n var result;\r\n try {\r\n result = input();\r\n } catch (e) {\r\n throw new FS.ErrnoError(29);\r\n }\r\n if (result === undefined && bytesRead === 0) {\r\n throw new FS.ErrnoError(6);\r\n }\r\n if (result === null || result === undefined) break;\r\n bytesRead++;\r\n buffer[offset + i] = result;\r\n }\r\n if (bytesRead) {\r\n stream.node.timestamp = Date.now();\r\n }\r\n return bytesRead;\r\n },\r\n write: (stream, buffer, offset, length, pos) => {\r\n for (var i = 0; i < length; i++) {\r\n try {\r\n output(buffer[offset + i]);\r\n } catch (e) {\r\n throw new FS.ErrnoError(29);\r\n }\r\n }\r\n if (length) {\r\n stream.node.timestamp = Date.now();\r\n }\r\n return i;\r\n }\r\n });\r\n return FS.mkdev(path, mode, dev);\r\n },\r\n forceLoadFile: obj => {\r\n if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true;\r\n if (typeof XMLHttpRequest !== \"undefined\") {\r\n throw new Error(\"Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.\");\r\n } else if (read_) {\r\n try {\r\n obj.contents = intArrayFromString(read_(obj.url), true);\r\n obj.usedBytes = obj.contents.length;\r\n } catch (e) {\r\n throw new FS.ErrnoError(29);\r\n }\r\n } else {\r\n throw new Error(\"Cannot load without read() or XMLHttpRequest.\");\r\n }\r\n },\r\n createLazyFile: (parent, name, url, canRead, canWrite) => {\r\n function LazyUint8Array() {\r\n this.lengthKnown = false;\r\n this.chunks = [];\r\n }\r\n LazyUint8Array.prototype.get = function LazyUint8Array_get(idx) {\r\n if (idx > this.length - 1 || idx < 0) {\r\n return undefined;\r\n }\r\n var chunkOffset = idx % this.chunkSize;\r\n var chunkNum = idx / this.chunkSize | 0;\r\n return this.getter(chunkNum)[chunkOffset];\r\n };\r\n LazyUint8Array.prototype.setDataGetter = function LazyUint8Array_setDataGetter(getter) {\r\n this.getter = getter;\r\n };\r\n LazyUint8Array.prototype.cacheLength = function LazyUint8Array_cacheLength() {\r\n var xhr = new XMLHttpRequest();\r\n xhr.open(\"HEAD\", url, false);\r\n xhr.send(null);\r\n if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error(\"Couldn't load \" + url + \". Status: \" + xhr.status);\r\n var datalength = Number(xhr.getResponseHeader(\"Content-length\"));\r\n var header;\r\n var hasByteServing = (header = xhr.getResponseHeader(\"Accept-Ranges\")) && header === \"bytes\";\r\n var usesGzip = (header = xhr.getResponseHeader(\"Content-Encoding\")) && header === \"gzip\";\r\n var chunkSize = 1024 * 1024;\r\n if (!hasByteServing) chunkSize = datalength;\r\n var doXHR = (from, to) => {\r\n if (from > to) throw new Error(\"invalid range (\" + from + \", \" + to + \") or no bytes requested!\");\r\n if (to > datalength - 1) throw new Error(\"only \" + datalength + \" bytes available! programmer error!\");\r\n var xhr = new XMLHttpRequest();\r\n xhr.open(\"GET\", url, false);\r\n if (datalength !== chunkSize) xhr.setRequestHeader(\"Range\", \"bytes=\" + from + \"-\" + to);\r\n xhr.responseType = \"arraybuffer\";\r\n if (xhr.overrideMimeType) {\r\n xhr.overrideMimeType(\"text/plain; charset=x-user-defined\");\r\n }\r\n xhr.send(null);\r\n if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error(\"Couldn't load \" + url + \". Status: \" + xhr.status);\r\n if (xhr.response !== undefined) {\r\n return new Uint8Array(xhr.response || []);\r\n } else {\r\n return intArrayFromString(xhr.responseText || \"\", true);\r\n }\r\n };\r\n var lazyArray = this;\r\n lazyArray.setDataGetter(chunkNum => {\r\n var start = chunkNum * chunkSize;\r\n var end = (chunkNum + 1) * chunkSize - 1;\r\n end = Math.min(end, datalength - 1);\r\n if (typeof lazyArray.chunks[chunkNum] === \"undefined\") {\r\n lazyArray.chunks[chunkNum] = doXHR(start, end);\r\n }\r\n if (typeof lazyArray.chunks[chunkNum] === \"undefined\") throw new Error(\"doXHR failed!\");\r\n return lazyArray.chunks[chunkNum];\r\n });\r\n if (usesGzip || !datalength) {\r\n chunkSize = datalength = 1;\r\n datalength = this.getter(0).length;\r\n chunkSize = datalength;\r\n out(\"LazyFiles on gzip forces download of the whole file when length is accessed\");\r\n }\r\n this._length = datalength;\r\n this._chunkSize = chunkSize;\r\n this.lengthKnown = true;\r\n };\r\n if (typeof XMLHttpRequest !== \"undefined\") {\r\n if (!ENVIRONMENT_IS_WORKER) throw \"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc\";\r\n var lazyArray = new LazyUint8Array();\r\n Object.defineProperties(lazyArray, {\r\n length: {\r\n get: function() {\r\n if (!this.lengthKnown) {\r\n this.cacheLength();\r\n }\r\n return this._length;\r\n }\r\n },\r\n chunkSize: {\r\n get: function() {\r\n if (!this.lengthKnown) {\r\n this.cacheLength();\r\n }\r\n return this._chunkSize;\r\n }\r\n }\r\n });\r\n var properties = {\r\n isDevice: false,\r\n contents: lazyArray\r\n };\r\n } else {\r\n var properties = {\r\n isDevice: false,\r\n url: url\r\n };\r\n }\r\n var node = FS.createFile(parent, name, properties, canRead, canWrite);\r\n if (properties.contents) {\r\n node.contents = properties.contents;\r\n } else if (properties.url) {\r\n node.contents = null;\r\n node.url = properties.url;\r\n }\r\n Object.defineProperties(node, {\r\n usedBytes: {\r\n get: function() {\r\n return this.contents.length;\r\n }\r\n }\r\n });\r\n var stream_ops = {};\r\n var keys = Object.keys(node.stream_ops);\r\n keys.forEach(key => {\r\n var fn = node.stream_ops[key];\r\n stream_ops[key] = function forceLoadLazyFile() {\r\n FS.forceLoadFile(node);\r\n return fn.apply(null, arguments);\r\n };\r\n });\r\n stream_ops.read = ((stream, buffer, offset, length, position) => {\r\n FS.forceLoadFile(node);\r\n var contents = stream.node.contents;\r\n if (position >= contents.length) return 0;\r\n var size = Math.min(contents.length - position, length);\r\n assert(size >= 0);\r\n if (contents.slice) {\r\n for (var i = 0; i < size; i++) {\r\n buffer[offset + i] = contents[position + i];\r\n }\r\n } else {\r\n for (var i = 0; i < size; i++) {\r\n buffer[offset + i] = contents.get(position + i);\r\n }\r\n }\r\n return size;\r\n });\r\n node.stream_ops = stream_ops;\r\n return node;\r\n },\r\n createPreloadedFile: (parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) => {\r\n var fullname = name ? PATH_FS.resolve(PATH.join2(parent, name)) : parent;\r\n var dep = getUniqueRunDependency(\"cp \" + fullname);\r\n function processData(byteArray) {\r\n function finish(byteArray) {\r\n if (preFinish) preFinish();\r\n if (!dontCreateFile) {\r\n FS.createDataFile(parent, name, byteArray, canRead, canWrite, canOwn);\r\n }\r\n if (onload) onload();\r\n removeRunDependency(dep);\r\n }\r\n if (Browser.handledByPreloadPlugin(byteArray, fullname, finish, () => {\r\n if (onerror) onerror();\r\n removeRunDependency(dep);\r\n })) {\r\n return;\r\n }\r\n finish(byteArray);\r\n }\r\n addRunDependency(dep);\r\n if (typeof url == \"string\") {\r\n asyncLoad(url, byteArray => processData(byteArray), onerror);\r\n } else {\r\n processData(url);\r\n }\r\n },\r\n indexedDB: () => {\r\n return window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;\r\n },\r\n DB_NAME: () => {\r\n return \"EM_FS_\" + window.location.pathname;\r\n },\r\n DB_VERSION: 20,\r\n DB_STORE_NAME: \"FILE_DATA\",\r\n saveFilesToDB: (paths, onload, onerror) => {\r\n onload = onload || (() => {});\r\n onerror = onerror || (() => {});\r\n var indexedDB = FS.indexedDB();\r\n try {\r\n var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION);\r\n } catch (e) {\r\n return onerror(e);\r\n }\r\n openRequest.onupgradeneeded = (() => {\r\n out(\"creating db\");\r\n var db = openRequest.result;\r\n db.createObjectStore(FS.DB_STORE_NAME);\r\n });\r\n openRequest.onsuccess = (() => {\r\n var db = openRequest.result;\r\n var transaction = db.transaction([ FS.DB_STORE_NAME ], \"readwrite\");\r\n var files = transaction.objectStore(FS.DB_STORE_NAME);\r\n var ok = 0, fail = 0, total = paths.length;\r\n function finish() {\r\n if (fail == 0) onload(); else onerror();\r\n }\r\n paths.forEach(path => {\r\n var putRequest = files.put(FS.analyzePath(path).object.contents, path);\r\n putRequest.onsuccess = (() => {\r\n ok++;\r\n if (ok + fail == total) finish();\r\n });\r\n putRequest.onerror = (() => {\r\n fail++;\r\n if (ok + fail == total) finish();\r\n });\r\n });\r\n transaction.onerror = onerror;\r\n });\r\n openRequest.onerror = onerror;\r\n },\r\n loadFilesFromDB: (paths, onload, onerror) => {\r\n onload = onload || (() => {});\r\n onerror = onerror || (() => {});\r\n var indexedDB = FS.indexedDB();\r\n try {\r\n var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION);\r\n } catch (e) {\r\n return onerror(e);\r\n }\r\n openRequest.onupgradeneeded = onerror;\r\n openRequest.onsuccess = (() => {\r\n var db = openRequest.result;\r\n try {\r\n var transaction = db.transaction([ FS.DB_STORE_NAME ], \"readonly\");\r\n } catch (e) {\r\n onerror(e);\r\n return;\r\n }\r\n var files = transaction.objectStore(FS.DB_STORE_NAME);\r\n var ok = 0, fail = 0, total = paths.length;\r\n function finish() {\r\n if (fail == 0) onload(); else onerror();\r\n }\r\n paths.forEach(path => {\r\n var getRequest = files.get(path);\r\n getRequest.onsuccess = (() => {\r\n if (FS.analyzePath(path).exists) {\r\n FS.unlink(path);\r\n }\r\n FS.createDataFile(PATH.dirname(path), PATH.basename(path), getRequest.result, true, true, true);\r\n ok++;\r\n if (ok + fail == total) finish();\r\n });\r\n getRequest.onerror = (() => {\r\n fail++;\r\n if (ok + fail == total) finish();\r\n });\r\n });\r\n transaction.onerror = onerror;\r\n });\r\n openRequest.onerror = onerror;\r\n },\r\n absolutePath: () => {\r\n abort(\"FS.absolutePath has been removed; use PATH_FS.resolve instead\");\r\n },\r\n createFolder: () => {\r\n abort(\"FS.createFolder has been removed; use FS.mkdir instead\");\r\n },\r\n createLink: () => {\r\n abort(\"FS.createLink has been removed; use FS.symlink instead\");\r\n },\r\n joinPath: () => {\r\n abort(\"FS.joinPath has been removed; use PATH.join instead\");\r\n },\r\n mmapAlloc: () => {\r\n abort(\"FS.mmapAlloc has been replaced by the top level function mmapAlloc\");\r\n },\r\n standardizePath: () => {\r\n abort(\"FS.standardizePath has been removed; use PATH.normalize instead\");\r\n }\r\n};\r\n\r\nvar SYSCALLS = {\r\n mappings: {},\r\n DEFAULT_POLLMASK: 5,\r\n calculateAt: function(dirfd, path, allowEmpty) {\r\n if (path[0] === \"/\") {\r\n return path;\r\n }\r\n var dir;\r\n if (dirfd === -100) {\r\n dir = FS.cwd();\r\n } else {\r\n var dirstream = FS.getStream(dirfd);\r\n if (!dirstream) throw new FS.ErrnoError(8);\r\n dir = dirstream.path;\r\n }\r\n if (path.length == 0) {\r\n if (!allowEmpty) {\r\n throw new FS.ErrnoError(44);\r\n }\r\n return dir;\r\n }\r\n return PATH.join2(dir, path);\r\n },\r\n doStat: function(func, path, buf) {\r\n try {\r\n var stat = func(path);\r\n } catch (e) {\r\n if (e && e.node && PATH.normalize(path) !== PATH.normalize(FS.getPath(e.node))) {\r\n return -54;\r\n }\r\n throw e;\r\n }\r\n _asan_js_store_4(buf >> 2, stat.dev);\r\n _asan_js_store_4(buf + 4 >> 2, 0);\r\n _asan_js_store_4(buf + 8 >> 2, stat.ino);\r\n _asan_js_store_4(buf + 12 >> 2, stat.mode);\r\n _asan_js_store_4(buf + 16 >> 2, stat.nlink);\r\n _asan_js_store_4(buf + 20 >> 2, stat.uid);\r\n _asan_js_store_4(buf + 24 >> 2, stat.gid);\r\n _asan_js_store_4(buf + 28 >> 2, stat.rdev);\r\n _asan_js_store_4(buf + 32 >> 2, 0);\r\n tempI64 = [ stat.size >>> 0, (tempDouble = stat.size, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ], \r\n _asan_js_store_4(buf + 40 >> 2, tempI64[0]), _asan_js_store_4(buf + 44 >> 2, tempI64[1]);\r\n _asan_js_store_4(buf + 48 >> 2, 4096);\r\n _asan_js_store_4(buf + 52 >> 2, stat.blocks);\r\n _asan_js_store_4(buf + 56 >> 2, stat.atime.getTime() / 1e3 | 0);\r\n _asan_js_store_4(buf + 60 >> 2, 0);\r\n _asan_js_store_4(buf + 64 >> 2, stat.mtime.getTime() / 1e3 | 0);\r\n _asan_js_store_4(buf + 68 >> 2, 0);\r\n _asan_js_store_4(buf + 72 >> 2, stat.ctime.getTime() / 1e3 | 0);\r\n _asan_js_store_4(buf + 76 >> 2, 0);\r\n tempI64 = [ stat.ino >>> 0, (tempDouble = stat.ino, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ], \r\n _asan_js_store_4(buf + 80 >> 2, tempI64[0]), _asan_js_store_4(buf + 84 >> 2, tempI64[1]);\r\n return 0;\r\n },\r\n doMsync: function(addr, stream, len, flags, offset) {\r\n var buffer = HEAPU8.slice(addr, addr + len);\r\n FS.msync(stream, buffer, offset, len, flags);\r\n },\r\n doMkdir: function(path, mode) {\r\n path = PATH.normalize(path);\r\n if (path[path.length - 1] === \"/\") path = path.substr(0, path.length - 1);\r\n FS.mkdir(path, mode, 0);\r\n return 0;\r\n },\r\n doMknod: function(path, mode, dev) {\r\n switch (mode & 61440) {\r\n case 32768:\r\n case 8192:\r\n case 24576:\r\n case 4096:\r\n case 49152:\r\n break;\r\n\r\n default:\r\n return -28;\r\n }\r\n FS.mknod(path, mode, dev);\r\n return 0;\r\n },\r\n doReadlink: function(path, buf, bufsize) {\r\n if (bufsize <= 0) return -28;\r\n var ret = FS.readlink(path);\r\n var len = Math.min(bufsize, lengthBytesUTF8(ret));\r\n var endChar = _asan_js_load_1(buf + len);\r\n stringToUTF8(ret, buf, bufsize + 1);\r\n _asan_js_store_1(buf + len, endChar);\r\n return len;\r\n },\r\n doAccess: function(path, amode) {\r\n if (amode & ~7) {\r\n return -28;\r\n }\r\n var lookup = FS.lookupPath(path, {\r\n follow: true\r\n });\r\n var node = lookup.node;\r\n if (!node) {\r\n return -44;\r\n }\r\n var perms = \"\";\r\n if (amode & 4) perms += \"r\";\r\n if (amode & 2) perms += \"w\";\r\n if (amode & 1) perms += \"x\";\r\n if (perms && FS.nodePermissions(node, perms)) {\r\n return -2;\r\n }\r\n return 0;\r\n },\r\n doDup: function(path, flags, suggestFD) {\r\n var suggest = FS.getStream(suggestFD);\r\n if (suggest) FS.close(suggest);\r\n return FS.open(path, flags, 0, suggestFD, suggestFD).fd;\r\n },\r\n doReadv: function(stream, iov, iovcnt, offset) {\r\n var ret = 0;\r\n for (var i = 0; i < iovcnt; i++) {\r\n var ptr = _asan_js_load_4(iov + i * 8 >> 2);\r\n var len = _asan_js_load_4(iov + (i * 8 + 4) >> 2);\r\n var curr = FS.read(stream, HEAP8, ptr, len, offset);\r\n if (curr < 0) return -1;\r\n ret += curr;\r\n if (curr < len) break;\r\n }\r\n return ret;\r\n },\r\n doWritev: function(stream, iov, iovcnt, offset) {\r\n var ret = 0;\r\n for (var i = 0; i < iovcnt; i++) {\r\n var ptr = _asan_js_load_4(iov + i * 8 >> 2);\r\n var len = _asan_js_load_4(iov + (i * 8 + 4) >> 2);\r\n var curr = FS.write(stream, HEAP8, ptr, len, offset);\r\n if (curr < 0) return -1;\r\n ret += curr;\r\n }\r\n return ret;\r\n },\r\n varargs: undefined,\r\n get: function() {\r\n assert(SYSCALLS.varargs != undefined);\r\n SYSCALLS.varargs += 4;\r\n var ret = _asan_js_load_4(SYSCALLS.varargs - 4 >> 2);\r\n return ret;\r\n },\r\n getStr: function(ptr) {\r\n var ret = UTF8ToString(ptr);\r\n return ret;\r\n },\r\n getStreamFromFD: function(fd) {\r\n var stream = FS.getStream(fd);\r\n if (!stream) throw new FS.ErrnoError(8);\r\n return stream;\r\n },\r\n get64: function(low, high) {\r\n if (low >= 0) assert(high === 0); else assert(high === -1);\r\n return low;\r\n }\r\n};\r\n\r\nfunction ___syscall_dup(fd) {\r\n try {\r\n var old = SYSCALLS.getStreamFromFD(fd);\r\n return FS.open(old.path, old.flags, 0).fd;\r\n } catch (e) {\r\n if (typeof FS === \"undefined\" || !(e instanceof FS.ErrnoError)) throw e;\r\n return -e.errno;\r\n }\r\n}\r\n\r\nfunction ___syscall_open(path, flags, varargs) {\r\n SYSCALLS.varargs = varargs;\r\n try {\r\n var pathname = SYSCALLS.getStr(path);\r\n var mode = varargs ? SYSCALLS.get() : 0;\r\n var stream = FS.open(pathname, flags, mode);\r\n return stream.fd;\r\n } catch (e) {\r\n if (typeof FS === \"undefined\" || !(e instanceof FS.ErrnoError)) throw e;\r\n return -e.errno;\r\n }\r\n}\r\n\r\nfunction ___syscall_stat64(path, buf) {\r\n try {\r\n path = SYSCALLS.getStr(path);\r\n return SYSCALLS.doStat(FS.stat, path, buf);\r\n } catch (e) {\r\n if (typeof FS === \"undefined\" || !(e instanceof FS.ErrnoError)) throw e;\r\n return -e.errno;\r\n }\r\n}\r\n\r\nfunction __embind_register_bigint(primitiveType, name, size, minRange, maxRange) {}\r\n\r\nfunction getShiftFromSize(size) {\r\n switch (size) {\r\n case 1:\r\n return 0;\r\n\r\n case 2:\r\n return 1;\r\n\r\n case 4:\r\n return 2;\r\n\r\n case 8:\r\n return 3;\r\n\r\n default:\r\n throw new TypeError(\"Unknown type size: \" + size);\r\n }\r\n}\r\n\r\nfunction embind_init_charCodes() {\r\n var codes = new Array(256);\r\n for (var i = 0; i < 256; ++i) {\r\n codes[i] = String.fromCharCode(i);\r\n }\r\n embind_charCodes = codes;\r\n}\r\n\r\nvar embind_charCodes = undefined;\r\n\r\nfunction readLatin1String(ptr) {\r\n var ret = \"\";\r\n var c = ptr;\r\n while (_asan_js_load_1u(c)) {\r\n ret += embind_charCodes[_asan_js_load_1u(c++)];\r\n }\r\n return ret;\r\n}\r\n\r\nvar awaitingDependencies = {};\r\n\r\nvar registeredTypes = {};\r\n\r\nvar typeDependencies = {};\r\n\r\nvar char_0 = 48;\r\n\r\nvar char_9 = 57;\r\n\r\nfunction makeLegalFunctionName(name) {\r\n if (undefined === name) {\r\n return \"_unknown\";\r\n }\r\n name = name.replace(/[^a-zA-Z0-9_]/g, \"$\");\r\n var f = name.charCodeAt(0);\r\n if (f >= char_0 && f <= char_9) {\r\n return \"_\" + name;\r\n } else {\r\n return name;\r\n }\r\n}\r\n\r\nfunction createNamedFunction(name, body) {\r\n name = makeLegalFunctionName(name);\r\n return new Function(\"body\", \"return function \" + name + \"() {\\n\" + ' \"use strict\";' + \" return body.apply(this, arguments);\\n\" + \"};\\n\")(body);\r\n}\r\n\r\nfunction extendError(baseErrorType, errorName) {\r\n var errorClass = createNamedFunction(errorName, function(message) {\r\n this.name = errorName;\r\n this.message = message;\r\n var stack = new Error(message).stack;\r\n if (stack !== undefined) {\r\n this.stack = this.toString() + \"\\n\" + stack.replace(/^Error(:[^\\n]*)?\\n/, \"\");\r\n }\r\n });\r\n errorClass.prototype = Object.create(baseErrorType.prototype);\r\n errorClass.prototype.constructor = errorClass;\r\n errorClass.prototype.toString = function() {\r\n if (this.message === undefined) {\r\n return this.name;\r\n } else {\r\n return this.name + \": \" + this.message;\r\n }\r\n };\r\n return errorClass;\r\n}\r\n\r\nvar BindingError = undefined;\r\n\r\nfunction throwBindingError(message) {\r\n throw new BindingError(message);\r\n}\r\n\r\nvar InternalError = undefined;\r\n\r\nfunction throwInternalError(message) {\r\n throw new InternalError(message);\r\n}\r\n\r\nfunction whenDependentTypesAreResolved(myTypes, dependentTypes, getTypeConverters) {\r\n myTypes.forEach(function(type) {\r\n typeDependencies[type] = dependentTypes;\r\n });\r\n function onComplete(typeConverters) {\r\n var myTypeConverters = getTypeConverters(typeConverters);\r\n if (myTypeConverters.length !== myTypes.length) {\r\n throwInternalError(\"Mismatched type converter count\");\r\n }\r\n for (var i = 0; i < myTypes.length; ++i) {\r\n registerType(myTypes[i], myTypeConverters[i]);\r\n }\r\n }\r\n var typeConverters = new Array(dependentTypes.length);\r\n var unregisteredTypes = [];\r\n var registered = 0;\r\n dependentTypes.forEach(function(dt, i) {\r\n if (registeredTypes.hasOwnProperty(dt)) {\r\n typeConverters[i] = registeredTypes[dt];\r\n } else {\r\n unregisteredTypes.push(dt);\r\n if (!awaitingDependencies.hasOwnProperty(dt)) {\r\n awaitingDependencies[dt] = [];\r\n }\r\n awaitingDependencies[dt].push(function() {\r\n typeConverters[i] = registeredTypes[dt];\r\n ++registered;\r\n if (registered === unregisteredTypes.length) {\r\n onComplete(typeConverters);\r\n }\r\n });\r\n }\r\n });\r\n if (0 === unregisteredTypes.length) {\r\n onComplete(typeConverters);\r\n }\r\n}\r\n\r\nfunction registerType(rawType, registeredInstance, options = {}) {\r\n if (!(\"argPackAdvance\" in registeredInstance)) {\r\n throw new TypeError(\"registerType registeredInstance requires argPackAdvance\");\r\n }\r\n var name = registeredInstance.name;\r\n if (!rawType) {\r\n throwBindingError('type \"' + name + '\" must have a positive integer typeid pointer');\r\n }\r\n if (registeredTypes.hasOwnProperty(rawType)) {\r\n if (options.ignoreDuplicateRegistrations) {\r\n return;\r\n } else {\r\n throwBindingError(\"Cannot register type '\" + name + \"' twice\");\r\n }\r\n }\r\n registeredTypes[rawType] = registeredInstance;\r\n delete typeDependencies[rawType];\r\n if (awaitingDependencies.hasOwnProperty(rawType)) {\r\n var callbacks = awaitingDependencies[rawType];\r\n delete awaitingDependencies[rawType];\r\n callbacks.forEach(function(cb) {\r\n cb();\r\n });\r\n }\r\n}\r\n\r\nfunction __embind_register_bool(rawType, name, size, trueValue, falseValue) {\r\n var shift = getShiftFromSize(size);\r\n name = readLatin1String(name);\r\n registerType(rawType, {\r\n name: name,\r\n \"fromWireType\": function(wt) {\r\n return !!wt;\r\n },\r\n \"toWireType\": function(destructors, o) {\r\n return o ? trueValue : falseValue;\r\n },\r\n \"argPackAdvance\": 8,\r\n \"readValueFromPointer\": function(pointer) {\r\n var heap;\r\n if (size === 1) {\r\n heap = HEAP8;\r\n } else if (size === 2) {\r\n heap = HEAP16;\r\n } else if (size === 4) {\r\n heap = HEAP32;\r\n } else {\r\n throw new TypeError(\"Unknown boolean type size: \" + name);\r\n }\r\n return this[\"fromWireType\"](heap[pointer >> shift]);\r\n },\r\n destructorFunction: null\r\n });\r\n}\r\n\r\nfunction ClassHandle_isAliasOf(other) {\r\n if (!(this instanceof ClassHandle)) {\r\n return false;\r\n }\r\n if (!(other instanceof ClassHandle)) {\r\n return false;\r\n }\r\n var leftClass = this.$$.ptrType.registeredClass;\r\n var left = this.$$.ptr;\r\n var rightClass = other.$$.ptrType.registeredClass;\r\n var right = other.$$.ptr;\r\n while (leftClass.baseClass) {\r\n left = leftClass.upcast(left);\r\n leftClass = leftClass.baseClass;\r\n }\r\n while (rightClass.baseClass) {\r\n right = rightClass.upcast(right);\r\n rightClass = rightClass.baseClass;\r\n }\r\n return leftClass === rightClass && left === right;\r\n}\r\n\r\nfunction shallowCopyInternalPointer(o) {\r\n return {\r\n count: o.count,\r\n deleteScheduled: o.deleteScheduled,\r\n preservePointerOnDelete: o.preservePointerOnDelete,\r\n ptr: o.ptr,\r\n ptrType: o.ptrType,\r\n smartPtr: o.smartPtr,\r\n smartPtrType: o.smartPtrType\r\n };\r\n}\r\n\r\nfunction throwInstanceAlreadyDeleted(obj) {\r\n function getInstanceTypeName(handle) {\r\n return handle.$$.ptrType.registeredClass.name;\r\n }\r\n throwBindingError(getInstanceTypeName(obj) + \" instance already deleted\");\r\n}\r\n\r\nvar finalizationRegistry = false;\r\n\r\nfunction detachFinalizer(handle) {}\r\n\r\nfunction runDestructor($$) {\r\n if ($$.smartPtr) {\r\n $$.smartPtrType.rawDestructor($$.smartPtr);\r\n } else {\r\n $$.ptrType.registeredClass.rawDestructor($$.ptr);\r\n }\r\n}\r\n\r\nfunction releaseClassHandle($$) {\r\n $$.count.value -= 1;\r\n var toDelete = 0 === $$.count.value;\r\n if (toDelete) {\r\n runDestructor($$);\r\n }\r\n}\r\n\r\nfunction downcastPointer(ptr, ptrClass, desiredClass) {\r\n if (ptrClass === desiredClass) {\r\n return ptr;\r\n }\r\n if (undefined === desiredClass.baseClass) {\r\n return null;\r\n }\r\n var rv = downcastPointer(ptr, ptrClass, desiredClass.baseClass);\r\n if (rv === null) {\r\n return null;\r\n }\r\n return desiredClass.downcast(rv);\r\n}\r\n\r\nvar registeredPointers = {};\r\n\r\nfunction getInheritedInstanceCount() {\r\n return Object.keys(registeredInstances).length;\r\n}\r\n\r\nfunction getLiveInheritedInstances() {\r\n var rv = [];\r\n for (var k in registeredInstances) {\r\n if (registeredInstances.hasOwnProperty(k)) {\r\n rv.push(registeredInstances[k]);\r\n }\r\n }\r\n return rv;\r\n}\r\n\r\nvar deletionQueue = [];\r\n\r\nfunction flushPendingDeletes() {\r\n while (deletionQueue.length) {\r\n var obj = deletionQueue.pop();\r\n obj.$$.deleteScheduled = false;\r\n obj[\"delete\"]();\r\n }\r\n}\r\n\r\nvar delayFunction = undefined;\r\n\r\nfunction setDelayFunction(fn) {\r\n delayFunction = fn;\r\n if (deletionQueue.length && delayFunction) {\r\n delayFunction(flushPendingDeletes);\r\n }\r\n}\r\n\r\nfunction init_embind() {\r\n Module[\"getInheritedInstanceCount\"] = getInheritedInstanceCount;\r\n Module[\"getLiveInheritedInstances\"] = getLiveInheritedInstances;\r\n Module[\"flushPendingDeletes\"] = flushPendingDeletes;\r\n Module[\"setDelayFunction\"] = setDelayFunction;\r\n}\r\n\r\nvar registeredInstances = {};\r\n\r\nfunction getBasestPointer(class_, ptr) {\r\n if (ptr === undefined) {\r\n throwBindingError(\"ptr should not be undefined\");\r\n }\r\n while (class_.baseClass) {\r\n ptr = class_.upcast(ptr);\r\n class_ = class_.baseClass;\r\n }\r\n return ptr;\r\n}\r\n\r\nfunction getInheritedInstance(class_, ptr) {\r\n ptr = getBasestPointer(class_, ptr);\r\n return registeredInstances[ptr];\r\n}\r\n\r\nfunction makeClassHandle(prototype, record) {\r\n if (!record.ptrType || !record.ptr) {\r\n throwInternalError(\"makeClassHandle requires ptr and ptrType\");\r\n }\r\n var hasSmartPtrType = !!record.smartPtrType;\r\n var hasSmartPtr = !!record.smartPtr;\r\n if (hasSmartPtrType !== hasSmartPtr) {\r\n throwInternalError(\"Both smartPtrType and smartPtr must be specified\");\r\n }\r\n record.count = {\r\n value: 1\r\n };\r\n return attachFinalizer(Object.create(prototype, {\r\n $$: {\r\n value: record\r\n }\r\n }));\r\n}\r\n\r\nfunction RegisteredPointer_fromWireType(ptr) {\r\n var rawPointer = this.getPointee(ptr);\r\n if (!rawPointer) {\r\n this.destructor(ptr);\r\n return null;\r\n }\r\n var registeredInstance = getInheritedInstance(this.registeredClass, rawPointer);\r\n if (undefined !== registeredInstance) {\r\n if (0 === registeredInstance.$$.count.value) {\r\n registeredInstance.$$.ptr = rawPointer;\r\n registeredInstance.$$.smartPtr = ptr;\r\n return registeredInstance[\"clone\"]();\r\n } else {\r\n var rv = registeredInstance[\"clone\"]();\r\n this.destructor(ptr);\r\n return rv;\r\n }\r\n }\r\n function makeDefaultHandle() {\r\n if (this.isSmartPointer) {\r\n return makeClassHandle(this.registeredClass.instancePrototype, {\r\n ptrType: this.pointeeType,\r\n ptr: rawPointer,\r\n smartPtrType: this,\r\n smartPtr: ptr\r\n });\r\n } else {\r\n return makeClassHandle(this.registeredClass.instancePrototype, {\r\n ptrType: this,\r\n ptr: ptr\r\n });\r\n }\r\n }\r\n var actualType = this.registeredClass.getActualType(rawPointer);\r\n var registeredPointerRecord = registeredPointers[actualType];\r\n if (!registeredPointerRecord) {\r\n return makeDefaultHandle.call(this);\r\n }\r\n var toType;\r\n if (this.isConst) {\r\n toType = registeredPointerRecord.constPointerType;\r\n } else {\r\n toType = registeredPointerRecord.pointerType;\r\n }\r\n var dp = downcastPointer(rawPointer, this.registeredClass, toType.registeredClass);\r\n if (dp === null) {\r\n return makeDefaultHandle.call(this);\r\n }\r\n if (this.isSmartPointer) {\r\n return makeClassHandle(toType.registeredClass.instancePrototype, {\r\n ptrType: toType,\r\n ptr: dp,\r\n smartPtrType: this,\r\n smartPtr: ptr\r\n });\r\n } else {\r\n return makeClassHandle(toType.registeredClass.instancePrototype, {\r\n ptrType: toType,\r\n ptr: dp\r\n });\r\n }\r\n}\r\n\r\nfunction attachFinalizer(handle) {\r\n if (\"undefined\" === typeof FinalizationRegistry) {\r\n attachFinalizer = (handle => handle);\r\n return handle;\r\n }\r\n finalizationRegistry = new FinalizationRegistry(info => {\r\n console.warn(info.leakWarning.stack.replace(/^Error: /, \"\"));\r\n releaseClassHandle(info.$$);\r\n });\r\n attachFinalizer = (handle => {\r\n var $$ = handle.$$;\r\n var hasSmartPtr = !!$$.smartPtr;\r\n if (hasSmartPtr) {\r\n var info = {\r\n $$: $$\r\n };\r\n var cls = $$.ptrType.registeredClass;\r\n info.leakWarning = new Error(\"Embind found a leaked C++ instance \" + cls.name + \" <0x\" + $$.ptr.toString(16) + \">.\\n\" + \"We'll free it automatically in this case, but this functionality is not reliable across various environments.\\n\" + \"Make sure to invoke .delete() manually once you're done with the instance instead.\\n\" + \"Originally allocated\");\r\n if (\"captureStackTrace\" in Error) {\r\n Error.captureStackTrace(info.leakWarning, RegisteredPointer_fromWireType);\r\n }\r\n finalizationRegistry.register(handle, info, handle);\r\n }\r\n return handle;\r\n });\r\n detachFinalizer = (handle => finalizationRegistry.unregister(handle));\r\n return attachFinalizer(handle);\r\n}\r\n\r\nfunction ClassHandle_clone() {\r\n if (!this.$$.ptr) {\r\n throwInstanceAlreadyDeleted(this);\r\n }\r\n if (this.$$.preservePointerOnDelete) {\r\n this.$$.count.value += 1;\r\n return this;\r\n } else {\r\n var clone = attachFinalizer(Object.create(Object.getPrototypeOf(this), {\r\n $$: {\r\n value: shallowCopyInternalPointer(this.$$)\r\n }\r\n }));\r\n clone.$$.count.value += 1;\r\n clone.$$.deleteScheduled = false;\r\n return clone;\r\n }\r\n}\r\n\r\nfunction ClassHandle_delete() {\r\n if (!this.$$.ptr) {\r\n throwInstanceAlreadyDeleted(this);\r\n }\r\n if (this.$$.deleteScheduled && !this.$$.preservePointerOnDelete) {\r\n throwBindingError(\"Object already scheduled for deletion\");\r\n }\r\n detachFinalizer(this);\r\n releaseClassHandle(this.$$);\r\n if (!this.$$.preservePointerOnDelete) {\r\n this.$$.smartPtr = undefined;\r\n this.$$.ptr = undefined;\r\n }\r\n}\r\n\r\nfunction ClassHandle_isDeleted() {\r\n return !this.$$.ptr;\r\n}\r\n\r\nfunction ClassHandle_deleteLater() {\r\n if (!this.$$.ptr) {\r\n throwInstanceAlreadyDeleted(this);\r\n }\r\n if (this.$$.deleteScheduled && !this.$$.preservePointerOnDelete) {\r\n throwBindingError(\"Object already scheduled for deletion\");\r\n }\r\n deletionQueue.push(this);\r\n if (deletionQueue.length === 1 && delayFunction) {\r\n delayFunction(flushPendingDeletes);\r\n }\r\n this.$$.deleteScheduled = true;\r\n return this;\r\n}\r\n\r\nfunction init_ClassHandle() {\r\n ClassHandle.prototype[\"isAliasOf\"] = ClassHandle_isAliasOf;\r\n ClassHandle.prototype[\"clone\"] = ClassHandle_clone;\r\n ClassHandle.prototype[\"delete\"] = ClassHandle_delete;\r\n ClassHandle.prototype[\"isDeleted\"] = ClassHandle_isDeleted;\r\n ClassHandle.prototype[\"deleteLater\"] = ClassHandle_deleteLater;\r\n}\r\n\r\nfunction ClassHandle() {}\r\n\r\nfunction ensureOverloadTable(proto, methodName, humanName) {\r\n if (undefined === proto[methodName].overloadTable) {\r\n var prevFunc = proto[methodName];\r\n proto[methodName] = function() {\r\n if (!proto[methodName].overloadTable.hasOwnProperty(arguments.length)) {\r\n throwBindingError(\"Function '\" + humanName + \"' called with an invalid number of arguments (\" + arguments.length + \") - expects one of (\" + proto[methodName].overloadTable + \")!\");\r\n }\r\n return proto[methodName].overloadTable[arguments.length].apply(this, arguments);\r\n };\r\n proto[methodName].overloadTable = [];\r\n proto[methodName].overloadTable[prevFunc.argCount] = prevFunc;\r\n }\r\n}\r\n\r\nfunction exposePublicSymbol(name, value, numArguments) {\r\n if (Module.hasOwnProperty(name)) {\r\n if (undefined === numArguments || undefined !== Module[name].overloadTable && undefined !== Module[name].overloadTable[numArguments]) {\r\n throwBindingError(\"Cannot register public name '\" + name + \"' twice\");\r\n }\r\n ensureOverloadTable(Module, name, name);\r\n if (Module.hasOwnProperty(numArguments)) {\r\n throwBindingError(\"Cannot register multiple overloads of a function with the same number of arguments (\" + numArguments + \")!\");\r\n }\r\n Module[name].overloadTable[numArguments] = value;\r\n } else {\r\n Module[name] = value;\r\n if (undefined !== numArguments) {\r\n Module[name].numArguments = numArguments;\r\n }\r\n }\r\n}\r\n\r\nfunction RegisteredClass(name, constructor, instancePrototype, rawDestructor, baseClass, getActualType, upcast, downcast) {\r\n this.name = name;\r\n this.constructor = constructor;\r\n this.instancePrototype = instancePrototype;\r\n this.rawDestructor = rawDestructor;\r\n this.baseClass = baseClass;\r\n this.getActualType = getActualType;\r\n this.upcast = upcast;\r\n this.downcast = downcast;\r\n this.pureVirtualFunctions = [];\r\n}\r\n\r\nfunction upcastPointer(ptr, ptrClass, desiredClass) {\r\n while (ptrClass !== desiredClass) {\r\n if (!ptrClass.upcast) {\r\n throwBindingError(\"Expected null or instance of \" + desiredClass.name + \", got an instance of \" + ptrClass.name);\r\n }\r\n ptr = ptrClass.upcast(ptr);\r\n ptrClass = ptrClass.baseClass;\r\n }\r\n return ptr;\r\n}\r\n\r\nfunction constNoSmartPtrRawPointerToWireType(destructors, handle) {\r\n if (handle === null) {\r\n if (this.isReference) {\r\n throwBindingError(\"null is not a valid \" + this.name);\r\n }\r\n return 0;\r\n }\r\n if (!handle.$$) {\r\n throwBindingError('Cannot pass \"' + _embind_repr(handle) + '\" as a ' + this.name);\r\n }\r\n if (!handle.$$.ptr) {\r\n throwBindingError(\"Cannot pass deleted object as a pointer of type \" + this.name);\r\n }\r\n var handleClass = handle.$$.ptrType.registeredClass;\r\n var ptr = upcastPointer(handle.$$.ptr, handleClass, this.registeredClass);\r\n return ptr;\r\n}\r\n\r\nfunction genericPointerToWireType(destructors, handle) {\r\n var ptr;\r\n if (handle === null) {\r\n if (this.isReference) {\r\n throwBindingError(\"null is not a valid \" + this.name);\r\n }\r\n if (this.isSmartPointer) {\r\n ptr = this.rawConstructor();\r\n if (destructors !== null) {\r\n destructors.push(this.rawDestructor, ptr);\r\n }\r\n return ptr;\r\n } else {\r\n return 0;\r\n }\r\n }\r\n if (!handle.$$) {\r\n throwBindingError('Cannot pass \"' + _embind_repr(handle) + '\" as a ' + this.name);\r\n }\r\n if (!handle.$$.ptr) {\r\n throwBindingError(\"Cannot pass deleted object as a pointer of type \" + this.name);\r\n }\r\n if (!this.isConst && handle.$$.ptrType.isConst) {\r\n throwBindingError(\"Cannot convert argument of type \" + (handle.$$.smartPtrType ? handle.$$.smartPtrType.name : handle.$$.ptrType.name) + \" to parameter type \" + this.name);\r\n }\r\n var handleClass = handle.$$.ptrType.registeredClass;\r\n ptr = upcastPointer(handle.$$.ptr, handleClass, this.registeredClass);\r\n if (this.isSmartPointer) {\r\n if (undefined === handle.$$.smartPtr) {\r\n throwBindingError(\"Passing raw pointer to smart pointer is illegal\");\r\n }\r\n switch (this.sharingPolicy) {\r\n case 0:\r\n if (handle.$$.smartPtrType === this) {\r\n ptr = handle.$$.smartPtr;\r\n } else {\r\n throwBindingError(\"Cannot convert argument of type \" + (handle.$$.smartPtrType ? handle.$$.smartPtrType.name : handle.$$.ptrType.name) + \" to parameter type \" + this.name);\r\n }\r\n break;\r\n\r\n case 1:\r\n ptr = handle.$$.smartPtr;\r\n break;\r\n\r\n case 2:\r\n if (handle.$$.smartPtrType === this) {\r\n ptr = handle.$$.smartPtr;\r\n } else {\r\n var clonedHandle = handle[\"clone\"]();\r\n ptr = this.rawShare(ptr, Emval.toHandle(function() {\r\n clonedHandle[\"delete\"]();\r\n }));\r\n if (destructors !== null) {\r\n destructors.push(this.rawDestructor, ptr);\r\n }\r\n }\r\n break;\r\n\r\n default:\r\n throwBindingError(\"Unsupporting sharing policy\");\r\n }\r\n }\r\n return ptr;\r\n}\r\n\r\nfunction nonConstNoSmartPtrRawPointerToWireType(destructors, handle) {\r\n if (handle === null) {\r\n if (this.isReference) {\r\n throwBindingError(\"null is not a valid \" + this.name);\r\n }\r\n return 0;\r\n }\r\n if (!handle.$$) {\r\n throwBindingError('Cannot pass \"' + _embind_repr(handle) + '\" as a ' + this.name);\r\n }\r\n if (!handle.$$.ptr) {\r\n throwBindingError(\"Cannot pass deleted object as a pointer of type \" + this.name);\r\n }\r\n if (handle.$$.ptrType.isConst) {\r\n throwBindingError(\"Cannot convert argument of type \" + handle.$$.ptrType.name + \" to parameter type \" + this.name);\r\n }\r\n var handleClass = handle.$$.ptrType.registeredClass;\r\n var ptr = upcastPointer(handle.$$.ptr, handleClass, this.registeredClass);\r\n return ptr;\r\n}\r\n\r\nfunction simpleReadValueFromPointer(pointer) {\r\n return this[\"fromWireType\"](_asan_js_load_4u(pointer >> 2));\r\n}\r\n\r\nfunction RegisteredPointer_getPointee(ptr) {\r\n if (this.rawGetPointee) {\r\n ptr = this.rawGetPointee(ptr);\r\n }\r\n return ptr;\r\n}\r\n\r\nfunction RegisteredPointer_destructor(ptr) {\r\n if (this.rawDestructor) {\r\n this.rawDestructor(ptr);\r\n }\r\n}\r\n\r\nfunction RegisteredPointer_deleteObject(handle) {\r\n if (handle !== null) {\r\n handle[\"delete\"]();\r\n }\r\n}\r\n\r\nfunction init_RegisteredPointer() {\r\n RegisteredPointer.prototype.getPointee = RegisteredPointer_getPointee;\r\n RegisteredPointer.prototype.destructor = RegisteredPointer_destructor;\r\n RegisteredPointer.prototype[\"argPackAdvance\"] = 8;\r\n RegisteredPointer.prototype[\"readValueFromPointer\"] = simpleReadValueFromPointer;\r\n RegisteredPointer.prototype[\"deleteObject\"] = RegisteredPointer_deleteObject;\r\n RegisteredPointer.prototype[\"fromWireType\"] = RegisteredPointer_fromWireType;\r\n}\r\n\r\nfunction RegisteredPointer(name, registeredClass, isReference, isConst, isSmartPointer, pointeeType, sharingPolicy, rawGetPointee, rawConstructor, rawShare, rawDestructor) {\r\n this.name = name;\r\n this.registeredClass = registeredClass;\r\n this.isReference = isReference;\r\n this.isConst = isConst;\r\n this.isSmartPointer = isSmartPointer;\r\n this.pointeeType = pointeeType;\r\n this.sharingPolicy = sharingPolicy;\r\n this.rawGetPointee = rawGetPointee;\r\n this.rawConstructor = rawConstructor;\r\n this.rawShare = rawShare;\r\n this.rawDestructor = rawDestructor;\r\n if (!isSmartPointer && registeredClass.baseClass === undefined) {\r\n if (isConst) {\r\n this[\"toWireType\"] = constNoSmartPtrRawPointerToWireType;\r\n this.destructorFunction = null;\r\n } else {\r\n this[\"toWireType\"] = nonConstNoSmartPtrRawPointerToWireType;\r\n this.destructorFunction = null;\r\n }\r\n } else {\r\n this[\"toWireType\"] = genericPointerToWireType;\r\n }\r\n}\r\n\r\nfunction replacePublicSymbol(name, value, numArguments) {\r\n if (!Module.hasOwnProperty(name)) {\r\n throwInternalError(\"Replacing nonexistant public symbol\");\r\n }\r\n if (undefined !== Module[name].overloadTable && undefined !== numArguments) {\r\n Module[name].overloadTable[numArguments] = value;\r\n } else {\r\n Module[name] = value;\r\n Module[name].argCount = numArguments;\r\n }\r\n}\r\n\r\nfunction dynCallLegacy(sig, ptr, args) {\r\n assert(\"dynCall_\" + sig in Module, \"bad function pointer type - no table for sig '\" + sig + \"'\");\r\n if (args && args.length) {\r\n assert(args.length === sig.substring(1).replace(/j/g, \"--\").length);\r\n } else {\r\n assert(sig.length == 1);\r\n }\r\n var f = Module[\"dynCall_\" + sig];\r\n return args && args.length ? f.apply(null, [ ptr ].concat(args)) : f.call(null, ptr);\r\n}\r\n\r\nfunction dynCall(sig, ptr, args) {\r\n if (sig.includes(\"j\")) {\r\n return dynCallLegacy(sig, ptr, args);\r\n }\r\n assert(getWasmTableEntry(ptr), \"missing table entry in dynCall: \" + ptr);\r\n return getWasmTableEntry(ptr).apply(null, args);\r\n}\r\n\r\nfunction getDynCaller(sig, ptr) {\r\n assert(sig.includes(\"j\"), \"getDynCaller should only be called with i64 sigs\");\r\n var argCache = [];\r\n return function() {\r\n argCache.length = 0;\r\n Object.assign(argCache, arguments);\r\n return dynCall(sig, ptr, argCache);\r\n };\r\n}\r\n\r\nfunction embind__requireFunction(signature, rawFunction) {\r\n signature = readLatin1String(signature);\r\n function makeDynCaller() {\r\n if (signature.includes(\"j\")) {\r\n return getDynCaller(signature, rawFunction);\r\n }\r\n return getWasmTableEntry(rawFunction);\r\n }\r\n var fp = makeDynCaller();\r\n if (typeof fp !== \"function\") {\r\n throwBindingError(\"unknown function pointer with signature \" + signature + \": \" + rawFunction);\r\n }\r\n return fp;\r\n}\r\n\r\nvar UnboundTypeError = undefined;\r\n\r\nfunction getTypeName(type) {\r\n var ptr = ___getTypeName(type);\r\n var rv = readLatin1String(ptr);\r\n _free(ptr);\r\n return rv;\r\n}\r\n\r\nfunction throwUnboundTypeError(message, types) {\r\n var unboundTypes = [];\r\n var seen = {};\r\n function visit(type) {\r\n if (seen[type]) {\r\n return;\r\n }\r\n if (registeredTypes[type]) {\r\n return;\r\n }\r\n if (typeDependencies[type]) {\r\n typeDependencies[type].forEach(visit);\r\n return;\r\n }\r\n unboundTypes.push(type);\r\n seen[type] = true;\r\n }\r\n types.forEach(visit);\r\n throw new UnboundTypeError(message + \": \" + unboundTypes.map(getTypeName).join([ \", \" ]));\r\n}\r\n\r\nfunction __embind_register_class(rawType, rawPointerType, rawConstPointerType, baseClassRawType, getActualTypeSignature, getActualType, upcastSignature, upcast, downcastSignature, downcast, name, destructorSignature, rawDestructor) {\r\n name = readLatin1String(name);\r\n getActualType = embind__requireFunction(getActualTypeSignature, getActualType);\r\n if (upcast) {\r\n upcast = embind__requireFunction(upcastSignature, upcast);\r\n }\r\n if (downcast) {\r\n downcast = embind__requireFunction(downcastSignature, downcast);\r\n }\r\n rawDestructor = embind__requireFunction(destructorSignature, rawDestructor);\r\n var legalFunctionName = makeLegalFunctionName(name);\r\n exposePublicSymbol(legalFunctionName, function() {\r\n throwUnboundTypeError(\"Cannot construct \" + name + \" due to unbound types\", [ baseClassRawType ]);\r\n });\r\n whenDependentTypesAreResolved([ rawType, rawPointerType, rawConstPointerType ], baseClassRawType ? [ baseClassRawType ] : [], function(base) {\r\n base = base[0];\r\n var baseClass;\r\n var basePrototype;\r\n if (baseClassRawType) {\r\n baseClass = base.registeredClass;\r\n basePrototype = baseClass.instancePrototype;\r\n } else {\r\n basePrototype = ClassHandle.prototype;\r\n }\r\n var constructor = createNamedFunction(legalFunctionName, function() {\r\n if (Object.getPrototypeOf(this) !== instancePrototype) {\r\n throw new BindingError(\"Use 'new' to construct \" + name);\r\n }\r\n if (undefined === registeredClass.constructor_body) {\r\n throw new BindingError(name + \" has no accessible constructor\");\r\n }\r\n var body = registeredClass.constructor_body[arguments.length];\r\n if (undefined === body) {\r\n throw new BindingError(\"Tried to invoke ctor of \" + name + \" with invalid number of parameters (\" + arguments.length + \") - expected (\" + Object.keys(registeredClass.constructor_body).toString() + \") parameters instead!\");\r\n }\r\n return body.apply(this, arguments);\r\n });\r\n var instancePrototype = Object.create(basePrototype, {\r\n constructor: {\r\n value: constructor\r\n }\r\n });\r\n constructor.prototype = instancePrototype;\r\n var registeredClass = new RegisteredClass(name, constructor, instancePrototype, rawDestructor, baseClass, getActualType, upcast, downcast);\r\n var referenceConverter = new RegisteredPointer(name, registeredClass, true, false, false);\r\n var pointerConverter = new RegisteredPointer(name + \"*\", registeredClass, false, false, false);\r\n var constPointerConverter = new RegisteredPointer(name + \" const*\", registeredClass, false, true, false);\r\n registeredPointers[rawType] = {\r\n pointerType: pointerConverter,\r\n constPointerType: constPointerConverter\r\n };\r\n replacePublicSymbol(legalFunctionName, constructor);\r\n return [ referenceConverter, pointerConverter, constPointerConverter ];\r\n });\r\n}\r\n\r\nfunction heap32VectorToArray(count, firstElement) {\r\n var array = [];\r\n for (var i = 0; i < count; i++) {\r\n array.push(_asan_js_load_4((firstElement >> 2) + i));\r\n }\r\n return array;\r\n}\r\n\r\nfunction runDestructors(destructors) {\r\n while (destructors.length) {\r\n var ptr = destructors.pop();\r\n var del = destructors.pop();\r\n del(ptr);\r\n }\r\n}\r\n\r\nfunction __embind_register_class_constructor(rawClassType, argCount, rawArgTypesAddr, invokerSignature, invoker, rawConstructor) {\r\n assert(argCount > 0);\r\n var rawArgTypes = heap32VectorToArray(argCount, rawArgTypesAddr);\r\n invoker = embind__requireFunction(invokerSignature, invoker);\r\n whenDependentTypesAreResolved([], [ rawClassType ], function(classType) {\r\n classType = classType[0];\r\n var humanName = \"constructor \" + classType.name;\r\n if (undefined === classType.registeredClass.constructor_body) {\r\n classType.registeredClass.constructor_body = [];\r\n }\r\n if (undefined !== classType.registeredClass.constructor_body[argCount - 1]) {\r\n 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!\");\r\n }\r\n classType.registeredClass.constructor_body[argCount - 1] = (() => {\r\n throwUnboundTypeError(\"Cannot construct \" + classType.name + \" due to unbound types\", rawArgTypes);\r\n });\r\n whenDependentTypesAreResolved([], rawArgTypes, function(argTypes) {\r\n argTypes.splice(1, 0, null);\r\n classType.registeredClass.constructor_body[argCount - 1] = craftInvokerFunction(humanName, argTypes, null, invoker, rawConstructor);\r\n return [];\r\n });\r\n return [];\r\n });\r\n}\r\n\r\nfunction new_(constructor, argumentList) {\r\n if (!(constructor instanceof Function)) {\r\n throw new TypeError(\"new_ called with constructor type \" + typeof constructor + \" which is not a function\");\r\n }\r\n var dummy = createNamedFunction(constructor.name || \"unknownFunctionName\", function() {});\r\n dummy.prototype = constructor.prototype;\r\n var obj = new dummy();\r\n var r = constructor.apply(obj, argumentList);\r\n return r instanceof Object ? r : obj;\r\n}\r\n\r\nfunction craftInvokerFunction(humanName, argTypes, classType, cppInvokerFunc, cppTargetFunc) {\r\n var argCount = argTypes.length;\r\n if (argCount < 2) {\r\n throwBindingError(\"argTypes array size mismatch! Must at least get return value and 'this' types!\");\r\n }\r\n var isClassMethodFunc = argTypes[1] !== null && classType !== null;\r\n var needsDestructorStack = false;\r\n for (var i = 1; i < argTypes.length; ++i) {\r\n if (argTypes[i] !== null && argTypes[i].destructorFunction === undefined) {\r\n needsDestructorStack = true;\r\n break;\r\n }\r\n }\r\n var returns = argTypes[0].name !== \"void\";\r\n var argsList = \"\";\r\n var argsListWired = \"\";\r\n for (var i = 0; i < argCount - 2; ++i) {\r\n argsList += (i !== 0 ? \", \" : \"\") + \"arg\" + i;\r\n argsListWired += (i !== 0 ? \", \" : \"\") + \"arg\" + i + \"Wired\";\r\n }\r\n var invokerFnBody = \"return function \" + makeLegalFunctionName(humanName) + \"(\" + argsList + \") {\\n\" + \"if (arguments.length !== \" + (argCount - 2) + \") {\\n\" + \"throwBindingError('function \" + humanName + \" called with ' + arguments.length + ' arguments, expected \" + (argCount - 2) + \" args!');\\n\" + \"}\\n\";\r\n if (needsDestructorStack) {\r\n invokerFnBody += \"var destructors = [];\\n\";\r\n }\r\n var dtorStack = needsDestructorStack ? \"destructors\" : \"null\";\r\n var args1 = [ \"throwBindingError\", \"invoker\", \"fn\", \"runDestructors\", \"retType\", \"classParam\" ];\r\n var args2 = [ throwBindingError, cppInvokerFunc, cppTargetFunc, runDestructors, argTypes[0], argTypes[1] ];\r\n if (isClassMethodFunc) {\r\n invokerFnBody += \"var thisWired = classParam.toWireType(\" + dtorStack + \", this);\\n\";\r\n }\r\n for (var i = 0; i < argCount - 2; ++i) {\r\n invokerFnBody += \"var arg\" + i + \"Wired = argType\" + i + \".toWireType(\" + dtorStack + \", arg\" + i + \"); // \" + argTypes[i + 2].name + \"\\n\";\r\n args1.push(\"argType\" + i);\r\n args2.push(argTypes[i + 2]);\r\n }\r\n if (isClassMethodFunc) {\r\n argsListWired = \"thisWired\" + (argsListWired.length > 0 ? \", \" : \"\") + argsListWired;\r\n }\r\n invokerFnBody += (returns ? \"var rv = \" : \"\") + \"invoker(fn\" + (argsListWired.length > 0 ? \", \" : \"\") + argsListWired + \");\\n\";\r\n if (needsDestructorStack) {\r\n invokerFnBody += \"runDestructors(destructors);\\n\";\r\n } else {\r\n for (var i = isClassMethodFunc ? 1 : 2; i < argTypes.length; ++i) {\r\n var paramName = i === 1 ? \"thisWired\" : \"arg\" + (i - 2) + \"Wired\";\r\n if (argTypes[i].destructorFunction !== null) {\r\n invokerFnBody += paramName + \"_dtor(\" + paramName + \"); // \" + argTypes[i].name + \"\\n\";\r\n args1.push(paramName + \"_dtor\");\r\n args2.push(argTypes[i].destructorFunction);\r\n }\r\n }\r\n }\r\n if (returns) {\r\n invokerFnBody += \"var ret = retType.fromWireType(rv);\\n\" + \"return ret;\\n\";\r\n } else {}\r\n invokerFnBody += \"}\\n\";\r\n args1.push(invokerFnBody);\r\n var invokerFunction = new_(Function, args1).apply(null, args2);\r\n return invokerFunction;\r\n}\r\n\r\nfunction __embind_register_class_function(rawClassType, methodName, argCount, rawArgTypesAddr, invokerSignature, rawInvoker, context, isPureVirtual) {\r\n var rawArgTypes = heap32VectorToArray(argCount, rawArgTypesAddr);\r\n methodName = readLatin1String(methodName);\r\n rawInvoker = embind__requireFunction(invokerSignature, rawInvoker);\r\n whenDependentTypesAreResolved([], [ rawClassType ], function(classType) {\r\n classType = classType[0];\r\n var humanName = classType.name + \".\" + methodName;\r\n if (methodName.startsWith(\"@@\")) {\r\n methodName = Symbol[methodName.substring(2)];\r\n }\r\n if (isPureVirtual) {\r\n classType.registeredClass.pureVirtualFunctions.push(methodName);\r\n }\r\n function unboundTypesHandler() {\r\n throwUnboundTypeError(\"Cannot call \" + humanName + \" due to unbound types\", rawArgTypes);\r\n }\r\n var proto = classType.registeredClass.instancePrototype;\r\n var method = proto[methodName];\r\n if (undefined === method || undefined === method.overloadTable && method.className !== classType.name && method.argCount === argCount - 2) {\r\n unboundTypesHandler.argCount = argCount - 2;\r\n unboundTypesHandler.className = classType.name;\r\n proto[methodName] = unboundTypesHandler;\r\n } else {\r\n ensureOverloadTable(proto, methodName, humanName);\r\n proto[methodName].overloadTable[argCount - 2] = unboundTypesHandler;\r\n }\r\n whenDependentTypesAreResolved([], rawArgTypes, function(argTypes) {\r\n var memberFunction = craftInvokerFunction(humanName, argTypes, classType, rawInvoker, context);\r\n if (undefined === proto[methodName].overloadTable) {\r\n memberFunction.argCount = argCount - 2;\r\n proto[methodName] = memberFunction;\r\n } else {\r\n proto[methodName].overloadTable[argCount - 2] = memberFunction;\r\n }\r\n return [];\r\n });\r\n return [];\r\n });\r\n}\r\n\r\nvar emval_free_list = [];\r\n\r\nvar emval_handle_array = [ {}, {\r\n value: undefined\r\n}, {\r\n value: null\r\n}, {\r\n value: true\r\n}, {\r\n value: false\r\n} ];\r\n\r\nfunction __emval_decref(handle) {\r\n if (handle > 4 && 0 === --emval_handle_array[handle].refcount) {\r\n emval_handle_array[handle] = undefined;\r\n emval_free_list.push(handle);\r\n }\r\n}\r\n\r\nfunction count_emval_handles() {\r\n var count = 0;\r\n for (var i = 5; i < emval_handle_array.length; ++i) {\r\n if (emval_handle_array[i] !== undefined) {\r\n ++count;\r\n }\r\n }\r\n return count;\r\n}\r\n\r\nfunction get_first_emval() {\r\n for (var i = 5; i < emval_handle_array.length; ++i) {\r\n if (emval_handle_array[i] !== undefined) {\r\n return emval_handle_array[i];\r\n }\r\n }\r\n return null;\r\n}\r\n\r\nfunction init_emval() {\r\n Module[\"count_emval_handles\"] = count_emval_handles;\r\n Module[\"get_first_emval\"] = get_first_emval;\r\n}\r\n\r\nvar Emval = {\r\n toValue: function(handle) {\r\n if (!handle) {\r\n throwBindingError(\"Cannot use deleted val. handle = \" + handle);\r\n }\r\n return emval_handle_array[handle].value;\r\n },\r\n toHandle: function(value) {\r\n switch (value) {\r\n case undefined:\r\n {\r\n return 1;\r\n }\r\n\r\n case null:\r\n {\r\n return 2;\r\n }\r\n\r\n case true:\r\n {\r\n return 3;\r\n }\r\n\r\n case false:\r\n {\r\n return 4;\r\n }\r\n\r\n default:\r\n {\r\n var handle = emval_free_list.length ? emval_free_list.pop() : emval_handle_array.length;\r\n emval_handle_array[handle] = {\r\n refcount: 1,\r\n value: value\r\n };\r\n return handle;\r\n }\r\n }\r\n }\r\n};\r\n\r\nfunction __embind_register_emval(rawType, name) {\r\n name = readLatin1String(name);\r\n registerType(rawType, {\r\n name: name,\r\n \"fromWireType\": function(handle) {\r\n var rv = Emval.toValue(handle);\r\n __emval_decref(handle);\r\n return rv;\r\n },\r\n \"toWireType\": function(destructors, value) {\r\n return Emval.toHandle(value);\r\n },\r\n \"argPackAdvance\": 8,\r\n \"readValueFromPointer\": simpleReadValueFromPointer,\r\n destructorFunction: null\r\n });\r\n}\r\n\r\nfunction _embind_repr(v) {\r\n if (v === null) {\r\n return \"null\";\r\n }\r\n var t = typeof v;\r\n if (t === \"object\" || t === \"array\" || t === \"function\") {\r\n return v.toString();\r\n } else {\r\n return \"\" + v;\r\n }\r\n}\r\n\r\nfunction floatReadValueFromPointer(name, shift) {\r\n switch (shift) {\r\n case 2:\r\n return function(pointer) {\r\n return this[\"fromWireType\"](_asan_js_load_f(pointer >> 2));\r\n };\r\n\r\n case 3:\r\n return function(pointer) {\r\n return this[\"fromWireType\"](_asan_js_load_d(pointer >> 3));\r\n };\r\n\r\n default:\r\n throw new TypeError(\"Unknown float type: \" + name);\r\n }\r\n}\r\n\r\nfunction __embind_register_float(rawType, name, size) {\r\n var shift = getShiftFromSize(size);\r\n name = readLatin1String(name);\r\n registerType(rawType, {\r\n name: name,\r\n \"fromWireType\": function(value) {\r\n return value;\r\n },\r\n \"toWireType\": function(destructors, value) {\r\n if (typeof value !== \"number\" && typeof value !== \"boolean\") {\r\n throw new TypeError('Cannot convert \"' + _embind_repr(value) + '\" to ' + this.name);\r\n }\r\n return value;\r\n },\r\n \"argPackAdvance\": 8,\r\n \"readValueFromPointer\": floatReadValueFromPointer(name, shift),\r\n destructorFunction: null\r\n });\r\n}\r\n\r\nfunction __embind_register_function(name, argCount, rawArgTypesAddr, signature, rawInvoker, fn) {\r\n var argTypes = heap32VectorToArray(argCount, rawArgTypesAddr);\r\n name = readLatin1String(name);\r\n rawInvoker = embind__requireFunction(signature, rawInvoker);\r\n exposePublicSymbol(name, function() {\r\n throwUnboundTypeError(\"Cannot call \" + name + \" due to unbound types\", argTypes);\r\n }, argCount - 1);\r\n whenDependentTypesAreResolved([], argTypes, function(argTypes) {\r\n var invokerArgsArray = [ argTypes[0], null ].concat(argTypes.slice(1));\r\n replacePublicSymbol(name, craftInvokerFunction(name, invokerArgsArray, null, rawInvoker, fn), argCount - 1);\r\n return [];\r\n });\r\n}\r\n\r\nfunction integerReadValueFromPointer(name, shift, signed) {\r\n switch (shift) {\r\n case 0:\r\n return signed ? function readS8FromPointer(pointer) {\r\n return _asan_js_load_1(pointer);\r\n } : function readU8FromPointer(pointer) {\r\n return _asan_js_load_1u(pointer);\r\n };\r\n\r\n case 1:\r\n return signed ? function readS16FromPointer(pointer) {\r\n return _asan_js_load_2(pointer >> 1);\r\n } : function readU16FromPointer(pointer) {\r\n return _asan_js_load_2u(pointer >> 1);\r\n };\r\n\r\n case 2:\r\n return signed ? function readS32FromPointer(pointer) {\r\n return _asan_js_load_4(pointer >> 2);\r\n } : function readU32FromPointer(pointer) {\r\n return _asan_js_load_4u(pointer >> 2);\r\n };\r\n\r\n default:\r\n throw new TypeError(\"Unknown integer type: \" + name);\r\n }\r\n}\r\n\r\nfunction __embind_register_integer(primitiveType, name, size, minRange, maxRange) {\r\n name = readLatin1String(name);\r\n if (maxRange === -1) {\r\n maxRange = 4294967295;\r\n }\r\n var shift = getShiftFromSize(size);\r\n var fromWireType = value => value;\r\n if (minRange === 0) {\r\n var bitshift = 32 - 8 * size;\r\n fromWireType = (value => value << bitshift >>> bitshift);\r\n }\r\n var isUnsignedType = name.includes(\"unsigned\");\r\n var checkAssertions = (value, toTypeName) => {\r\n if (typeof value !== \"number\" && typeof value !== \"boolean\") {\r\n throw new TypeError('Cannot convert \"' + _embind_repr(value) + '\" to ' + toTypeName);\r\n }\r\n if (value < minRange || value > maxRange) {\r\n 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 + \"]!\");\r\n }\r\n };\r\n var toWireType;\r\n if (isUnsignedType) {\r\n toWireType = function(destructors, value) {\r\n checkAssertions(value, this.name);\r\n return value >>> 0;\r\n };\r\n } else {\r\n toWireType = function(destructors, value) {\r\n checkAssertions(value, this.name);\r\n return value;\r\n };\r\n }\r\n registerType(primitiveType, {\r\n name: name,\r\n \"fromWireType\": fromWireType,\r\n \"toWireType\": toWireType,\r\n \"argPackAdvance\": 8,\r\n \"readValueFromPointer\": integerReadValueFromPointer(name, shift, minRange !== 0),\r\n destructorFunction: null\r\n });\r\n}\r\n\r\nfunction __embind_register_memory_view(rawType, dataTypeIndex, name) {\r\n var typeMapping = [ Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array ];\r\n var TA = typeMapping[dataTypeIndex];\r\n function decodeMemoryView(handle) {\r\n handle = handle >> 2;\r\n var heap = HEAPU32;\r\n var size = heap[handle];\r\n var data = heap[handle + 1];\r\n return new TA(buffer, data, size);\r\n }\r\n name = readLatin1String(name);\r\n registerType(rawType, {\r\n name: name,\r\n \"fromWireType\": decodeMemoryView,\r\n \"argPackAdvance\": 8,\r\n \"readValueFromPointer\": decodeMemoryView\r\n }, {\r\n ignoreDuplicateRegistrations: true\r\n });\r\n}\r\n\r\nfunction __embind_register_std_string(rawType, name) {\r\n name = readLatin1String(name);\r\n var stdStringIsUTF8 = name === \"std::string\";\r\n registerType(rawType, {\r\n name: name,\r\n \"fromWireType\": function(value) {\r\n var length = _asan_js_load_4u(value >> 2);\r\n var str;\r\n if (stdStringIsUTF8) {\r\n var decodeStartPtr = value + 4;\r\n for (var i = 0; i <= length; ++i) {\r\n var currentBytePtr = value + 4 + i;\r\n if (i == length || _asan_js_load_1u(currentBytePtr) == 0) {\r\n var maxRead = currentBytePtr - decodeStartPtr;\r\n var stringSegment = UTF8ToString(decodeStartPtr, maxRead);\r\n if (str === undefined) {\r\n str = stringSegment;\r\n } else {\r\n str += String.fromCharCode(0);\r\n str += stringSegment;\r\n }\r\n decodeStartPtr = currentBytePtr + 1;\r\n }\r\n }\r\n } else {\r\n var a = new Array(length);\r\n for (var i = 0; i < length; ++i) {\r\n a[i] = String.fromCharCode(_asan_js_load_1u(value + 4 + i));\r\n }\r\n str = a.join(\"\");\r\n }\r\n _free(value);\r\n return str;\r\n },\r\n \"toWireType\": function(destructors, value) {\r\n if (value instanceof ArrayBuffer) {\r\n value = new Uint8Array(value);\r\n }\r\n var getLength;\r\n var valueIsOfTypeString = typeof value === \"string\";\r\n if (!(valueIsOfTypeString || value instanceof Uint8Array || value instanceof Uint8ClampedArray || value instanceof Int8Array)) {\r\n throwBindingError(\"Cannot pass non-string to std::string\");\r\n }\r\n if (stdStringIsUTF8 && valueIsOfTypeString) {\r\n getLength = (() => lengthBytesUTF8(value));\r\n } else {\r\n getLength = (() => value.length);\r\n }\r\n var length = getLength();\r\n var ptr = _malloc(4 + length + 1);\r\n _asan_js_store_4u(ptr >> 2, length);\r\n if (stdStringIsUTF8 && valueIsOfTypeString) {\r\n stringToUTF8(value, ptr + 4, length + 1);\r\n } else {\r\n if (valueIsOfTypeString) {\r\n for (var i = 0; i < length; ++i) {\r\n var charCode = value.charCodeAt(i);\r\n if (charCode > 255) {\r\n _free(ptr);\r\n throwBindingError(\"String has UTF-16 code units that do not fit in 8 bits\");\r\n }\r\n _asan_js_store_1u(ptr + 4 + i, charCode);\r\n }\r\n } else {\r\n for (var i = 0; i < length; ++i) {\r\n _asan_js_store_1u(ptr + 4 + i, value[i]);\r\n }\r\n }\r\n }\r\n if (destructors !== null) {\r\n destructors.push(_free, ptr);\r\n }\r\n return ptr;\r\n },\r\n \"argPackAdvance\": 8,\r\n \"readValueFromPointer\": simpleReadValueFromPointer,\r\n destructorFunction: function(ptr) {\r\n _free(ptr);\r\n }\r\n });\r\n}\r\n\r\nfunction __embind_register_std_wstring(rawType, charSize, name) {\r\n name = readLatin1String(name);\r\n var decodeString, encodeString, getHeap, lengthBytesUTF, shift;\r\n if (charSize === 2) {\r\n decodeString = UTF16ToString;\r\n encodeString = stringToUTF16;\r\n lengthBytesUTF = lengthBytesUTF16;\r\n getHeap = (() => HEAPU16);\r\n shift = 1;\r\n } else if (charSize === 4) {\r\n decodeString = UTF32ToString;\r\n encodeString = stringToUTF32;\r\n lengthBytesUTF = lengthBytesUTF32;\r\n getHeap = (() => HEAPU32);\r\n shift = 2;\r\n }\r\n registerType(rawType, {\r\n name: name,\r\n \"fromWireType\": function(value) {\r\n var length = _asan_js_load_4u(value >> 2);\r\n var HEAP = getHeap();\r\n var str;\r\n var decodeStartPtr = value + 4;\r\n for (var i = 0; i <= length; ++i) {\r\n var currentBytePtr = value + 4 + i * charSize;\r\n if (i == length || HEAP[currentBytePtr >> shift] == 0) {\r\n var maxReadBytes = currentBytePtr - decodeStartPtr;\r\n var stringSegment = decodeString(decodeStartPtr, maxReadBytes);\r\n if (str === undefined) {\r\n str = stringSegment;\r\n } else {\r\n str += String.fromCharCode(0);\r\n str += stringSegment;\r\n }\r\n decodeStartPtr = currentBytePtr + charSize;\r\n }\r\n }\r\n _free(value);\r\n return str;\r\n },\r\n \"toWireType\": function(destructors, value) {\r\n if (!(typeof value === \"string\")) {\r\n throwBindingError(\"Cannot pass non-string to C++ string type \" + name);\r\n }\r\n var length = lengthBytesUTF(value);\r\n var ptr = _malloc(4 + length + charSize);\r\n _asan_js_store_4u(ptr >> 2, length >> shift);\r\n encodeString(value, ptr + 4, length + charSize);\r\n if (destructors !== null) {\r\n destructors.push(_free, ptr);\r\n }\r\n return ptr;\r\n },\r\n \"argPackAdvance\": 8,\r\n \"readValueFromPointer\": simpleReadValueFromPointer,\r\n destructorFunction: function(ptr) {\r\n _free(ptr);\r\n }\r\n });\r\n}\r\n\r\nfunction __embind_register_void(rawType, name) {\r\n name = readLatin1String(name);\r\n registerType(rawType, {\r\n isVoid: true,\r\n name: name,\r\n \"argPackAdvance\": 0,\r\n \"fromWireType\": function() {\r\n return undefined;\r\n },\r\n \"toWireType\": function(destructors, o) {\r\n return undefined;\r\n }\r\n });\r\n}\r\n\r\nfunction __emval_incref(handle) {\r\n if (handle > 4) {\r\n emval_handle_array[handle].refcount += 1;\r\n }\r\n}\r\n\r\nfunction requireRegisteredType(rawType, humanName) {\r\n var impl = registeredTypes[rawType];\r\n if (undefined === impl) {\r\n throwBindingError(humanName + \" has unknown type \" + getTypeName(rawType));\r\n }\r\n return impl;\r\n}\r\n\r\nfunction __emval_take_value(type, argv) {\r\n type = requireRegisteredType(type, \"_emval_take_value\");\r\n var v = type[\"readValueFromPointer\"](argv);\r\n return Emval.toHandle(v);\r\n}\r\n\r\nfunction _abort() {\r\n abort(\"native code called abort()\");\r\n}\r\n\r\nvar readAsmConstArgsArray = [];\r\n\r\nfunction readAsmConstArgs(sigPtr, buf) {\r\n assert(Array.isArray(readAsmConstArgsArray));\r\n assert(buf % 16 == 0);\r\n readAsmConstArgsArray.length = 0;\r\n var ch;\r\n buf >>= 2;\r\n while (ch = _asan_js_load_1u(sigPtr++)) {\r\n assert(ch === 100 || ch === 102 || ch === 105);\r\n var readAsmConstArgsDouble = ch < 105;\r\n if (readAsmConstArgsDouble && buf & 1) buf++;\r\n readAsmConstArgsArray.push(readAsmConstArgsDouble ? _asan_js_load_d(buf++ >> 1) : _asan_js_load_4(buf));\r\n ++buf;\r\n }\r\n return readAsmConstArgsArray;\r\n}\r\n\r\nfunction _emscripten_asm_const_int(code, sigPtr, argbuf) {\r\n var args = readAsmConstArgs(sigPtr, argbuf);\r\n if (!ASM_CONSTS.hasOwnProperty(code)) abort(\"No EM_ASM constant found at address \" + code);\r\n return ASM_CONSTS[code].apply(null, args);\r\n}\r\n\r\nfunction _emscripten_asm_const_double(a0, a1, a2) {\r\n return _emscripten_asm_const_int(a0, a1, a2);\r\n}\r\n\r\nfunction syscallMmap2(addr, len, prot, flags, fd, off) {\r\n off <<= 12;\r\n var ptr;\r\n var allocated = false;\r\n if ((flags & 16) !== 0 && addr % 65536 !== 0) {\r\n return -28;\r\n }\r\n if ((flags & 32) !== 0) {\r\n ptr = mmapAlloc(len);\r\n if (!ptr) return -48;\r\n allocated = true;\r\n } else {\r\n var info = FS.getStream(fd);\r\n if (!info) return -8;\r\n var res = FS.mmap(info, addr, len, off, prot, flags);\r\n ptr = res.ptr;\r\n allocated = res.allocated;\r\n }\r\n SYSCALLS.mappings[ptr] = {\r\n malloc: ptr,\r\n len: len,\r\n allocated: allocated,\r\n fd: fd,\r\n prot: prot,\r\n flags: flags,\r\n offset: off\r\n };\r\n return ptr;\r\n}\r\n\r\nfunction withBuiltinMalloc(func) {\r\n var prev_malloc = typeof _malloc !== \"undefined\" ? _malloc : undefined;\r\n var prev_memalign = typeof _memalign !== \"undefined\" ? _memalign : undefined;\r\n var prev_free = typeof _free !== \"undefined\" ? _free : undefined;\r\n _malloc = _emscripten_builtin_malloc;\r\n _memalign = _emscripten_builtin_memalign;\r\n _free = _emscripten_builtin_free;\r\n try {\r\n return func();\r\n } finally {\r\n _malloc = prev_malloc;\r\n _memalign = prev_memalign;\r\n _free = prev_free;\r\n }\r\n}\r\n\r\nfunction _emscripten_builtin_mmap2(addr, len, prot, flags, fd, off) {\r\n return withBuiltinMalloc(function() {\r\n return syscallMmap2(addr, len, prot, flags, fd, off);\r\n });\r\n}\r\n\r\nfunction syscallMunmap(addr, len) {\r\n var info = SYSCALLS.mappings[addr];\r\n if (len === 0 || !info) {\r\n return -28;\r\n }\r\n if (len === info.len) {\r\n var stream = FS.getStream(info.fd);\r\n if (stream) {\r\n if (info.prot & 2) {\r\n SYSCALLS.doMsync(addr, stream, len, info.flags, info.offset);\r\n }\r\n FS.munmap(stream);\r\n }\r\n SYSCALLS.mappings[addr] = null;\r\n if (info.allocated) {\r\n _free(info.malloc);\r\n }\r\n }\r\n return 0;\r\n}\r\n\r\nfunction _emscripten_builtin_munmap(addr, len) {\r\n return withBuiltinMalloc(function() {\r\n return syscallMunmap(addr, len);\r\n });\r\n}\r\n\r\nfunction _emscripten_console_error(str) {\r\n assert(typeof str === \"number\");\r\n console.error(UTF8ToString(str));\r\n}\r\n\r\nfunction _emscripten_get_heap_max() {\r\n return HEAPU8.length;\r\n}\r\n\r\nfunction _emscripten_get_module_name(buf, length) {\r\n return stringToUTF8(wasmBinaryFile, buf, length);\r\n}\r\n\r\nvar _emscripten_get_now;\r\n\r\n_emscripten_get_now = (() => performance.now());\r\n\r\nvar UNWIND_CACHE = {};\r\n\r\nfunction convertFrameToPC(frame) {\r\n assert(wasmOffsetConverter);\r\n var match;\r\n if (match = /\\bwasm-function\\[\\d+\\]:(0x[0-9a-f]+)/.exec(frame)) {\r\n return +match[1];\r\n } else if (match = /\\bwasm-function\\[(\\d+)\\]:(\\d+)/.exec(frame)) {\r\n return wasmOffsetConverter.convert(+match[1], +match[2]);\r\n } else if (match = /:(\\d+):\\d+(?:\\)|$)/.exec(frame)) {\r\n return 2147483648 | +match[1];\r\n }\r\n return 0;\r\n}\r\n\r\nfunction convertPCtoSourceLocation(pc) {\r\n if (UNWIND_CACHE.last_get_source_pc == pc) return UNWIND_CACHE.last_source;\r\n var match;\r\n var source;\r\n if (!source) {\r\n var frame = UNWIND_CACHE[pc];\r\n if (!frame) return null;\r\n if (match = /\\((.*):(\\d+):(\\d+)\\)$/.exec(frame)) {\r\n source = {\r\n file: match[1],\r\n line: match[2],\r\n column: match[3]\r\n };\r\n } else if (match = /@(.*):(\\d+):(\\d+)/.exec(frame)) {\r\n source = {\r\n file: match[1],\r\n line: match[2],\r\n column: match[3]\r\n };\r\n }\r\n }\r\n UNWIND_CACHE.last_get_source_pc = pc;\r\n UNWIND_CACHE.last_source = source;\r\n return source;\r\n}\r\n\r\nfunction _emscripten_pc_get_column(pc) {\r\n var result = convertPCtoSourceLocation(pc);\r\n return result ? result.column || 0 : 0;\r\n}\r\n\r\nfunction _emscripten_pc_get_file(pc) {\r\n return withBuiltinMalloc(function() {\r\n var result = convertPCtoSourceLocation(pc);\r\n if (!result) return 0;\r\n if (_emscripten_pc_get_file.ret) _free(_emscripten_pc_get_file.ret);\r\n _emscripten_pc_get_file.ret = allocateUTF8(result.file);\r\n return _emscripten_pc_get_file.ret;\r\n });\r\n}\r\n\r\nfunction _emscripten_pc_get_function(pc) {\r\n return withBuiltinMalloc(function() {\r\n var name;\r\n if (pc & 2147483648) {\r\n var frame = UNWIND_CACHE[pc];\r\n if (!frame) return 0;\r\n var match;\r\n if (match = /^\\s+at (.*) \\(.*\\)$/.exec(frame)) {\r\n name = match[1];\r\n } else if (match = /^(.+?)@/.exec(frame)) {\r\n name = match[1];\r\n } else {\r\n return 0;\r\n }\r\n } else {\r\n name = wasmOffsetConverter.getName(pc);\r\n }\r\n if (_emscripten_pc_get_function.ret) _free(_emscripten_pc_get_function.ret);\r\n _emscripten_pc_get_function.ret = allocateUTF8(name);\r\n return _emscripten_pc_get_function.ret;\r\n });\r\n}\r\n\r\nfunction _emscripten_pc_get_line(pc) {\r\n var result = convertPCtoSourceLocation(pc);\r\n return result ? result.line : 0;\r\n}\r\n\r\nfunction abortOnCannotGrowMemory(requestedSize) {\r\n abort(\"Cannot enlarge memory arrays to size \" + requestedSize + \" bytes (OOM). Either (1) compile with -s INITIAL_MEMORY=X with X higher than the current value \" + HEAP8.length + \", (2) compile with -s ALLOW_MEMORY_GROWTH=1 which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 \");\r\n}\r\n\r\nfunction _emscripten_resize_heap(requestedSize) {\r\n var oldSize = HEAPU8.length;\r\n requestedSize = requestedSize >>> 0;\r\n abortOnCannotGrowMemory(requestedSize);\r\n}\r\n\r\nfunction _emscripten_return_address(level) {\r\n var callstack = new Error().stack.split(\"\\n\");\r\n if (callstack[0] == \"Error\") {\r\n callstack.shift();\r\n }\r\n return convertFrameToPC(callstack[level + 2]);\r\n}\r\n\r\nfunction saveInUnwindCache(callstack) {\r\n callstack.forEach(function(frame) {\r\n var pc = convertFrameToPC(frame);\r\n if (pc) {\r\n UNWIND_CACHE[pc] = frame;\r\n }\r\n });\r\n}\r\n\r\nfunction _emscripten_stack_snapshot() {\r\n var callstack = new Error().stack.split(\"\\n\");\r\n if (callstack[0] == \"Error\") {\r\n callstack.shift();\r\n }\r\n saveInUnwindCache(callstack);\r\n UNWIND_CACHE.last_addr = convertFrameToPC(callstack[2]);\r\n UNWIND_CACHE.last_stack = callstack;\r\n return UNWIND_CACHE.last_addr;\r\n}\r\n\r\nfunction _emscripten_stack_unwind_buffer(addr, buffer, count) {\r\n var stack;\r\n if (UNWIND_CACHE.last_addr == addr) {\r\n stack = UNWIND_CACHE.last_stack;\r\n } else {\r\n stack = new Error().stack.split(\"\\n\");\r\n if (stack[0] == \"Error\") {\r\n stack.shift();\r\n }\r\n saveInUnwindCache(stack);\r\n }\r\n var offset = 2;\r\n while (stack[offset] && convertFrameToPC(stack[offset]) != addr) {\r\n ++offset;\r\n }\r\n for (var i = 0; i < count && stack[i + offset]; ++i) {\r\n _asan_js_store_4(buffer + i * 4 >> 2, convertFrameToPC(stack[i + offset]));\r\n }\r\n return i;\r\n}\r\n\r\nvar ENV = {};\r\n\r\nfunction getExecutableName() {\r\n return thisProgram || \"./this.program\";\r\n}\r\n\r\nfunction getEnvStrings() {\r\n if (!getEnvStrings.strings) {\r\n var lang = (typeof navigator === \"object\" && navigator.languages && navigator.languages[0] || \"C\").replace(\"-\", \"_\") + \".UTF-8\";\r\n var env = {\r\n \"USER\": \"web_user\",\r\n \"LOGNAME\": \"web_user\",\r\n \"PATH\": \"/\",\r\n \"PWD\": \"/\",\r\n \"HOME\": \"/home/web_user\",\r\n \"LANG\": lang,\r\n \"_\": getExecutableName()\r\n };\r\n for (var x in ENV) {\r\n if (ENV[x] === undefined) delete env[x]; else env[x] = ENV[x];\r\n }\r\n var strings = [];\r\n for (var x in env) {\r\n strings.push(x + \"=\" + env[x]);\r\n }\r\n getEnvStrings.strings = strings;\r\n }\r\n return getEnvStrings.strings;\r\n}\r\n\r\nfunction _environ_get(__environ, environ_buf) {\r\n var bufSize = 0;\r\n getEnvStrings().forEach(function(string, i) {\r\n var ptr = environ_buf + bufSize;\r\n _asan_js_store_4(__environ + i * 4 >> 2, ptr);\r\n writeAsciiToMemory(string, ptr);\r\n bufSize += string.length + 1;\r\n });\r\n return 0;\r\n}\r\n\r\nfunction _environ_sizes_get(penviron_count, penviron_buf_size) {\r\n var strings = getEnvStrings();\r\n _asan_js_store_4(penviron_count >> 2, strings.length);\r\n var bufSize = 0;\r\n strings.forEach(function(string) {\r\n bufSize += string.length + 1;\r\n });\r\n _asan_js_store_4(penviron_buf_size >> 2, bufSize);\r\n return 0;\r\n}\r\n\r\nfunction _fd_close(fd) {\r\n try {\r\n var stream = SYSCALLS.getStreamFromFD(fd);\r\n FS.close(stream);\r\n return 0;\r\n } catch (e) {\r\n if (typeof FS === \"undefined\" || !(e instanceof FS.ErrnoError)) throw e;\r\n return e.errno;\r\n }\r\n}\r\n\r\nfunction _fd_read(fd, iov, iovcnt, pnum) {\r\n try {\r\n var stream = SYSCALLS.getStreamFromFD(fd);\r\n var num = SYSCALLS.doReadv(stream, iov, iovcnt);\r\n _asan_js_store_4(pnum >> 2, num);\r\n return 0;\r\n } catch (e) {\r\n if (typeof FS === \"undefined\" || !(e instanceof FS.ErrnoError)) throw e;\r\n return e.errno;\r\n }\r\n}\r\n\r\nfunction _fd_write(fd, iov, iovcnt, pnum) {\r\n try {\r\n var stream = SYSCALLS.getStreamFromFD(fd);\r\n var num = SYSCALLS.doWritev(stream, iov, iovcnt);\r\n _asan_js_store_4(pnum >> 2, num);\r\n return 0;\r\n } catch (e) {\r\n if (typeof FS === \"undefined\" || !(e instanceof FS.ErrnoError)) throw e;\r\n return e.errno;\r\n }\r\n}\r\n\r\nfunction _proc_exit(code) {\r\n procExit(code);\r\n}\r\n\r\nfunction _setTempRet0(val) {\r\n setTempRet0(val);\r\n}\r\n\r\nvar FSNode = function(parent, name, mode, rdev) {\r\n if (!parent) {\r\n parent = this;\r\n }\r\n this.parent = parent;\r\n this.mount = parent.mount;\r\n this.mounted = null;\r\n this.id = FS.nextInode++;\r\n this.name = name;\r\n this.mode = mode;\r\n this.node_ops = {};\r\n this.stream_ops = {};\r\n this.rdev = rdev;\r\n};\r\n\r\nvar readMode = 292 | 73;\r\n\r\nvar writeMode = 146;\r\n\r\nObject.defineProperties(FSNode.prototype, {\r\n read: {\r\n get: function() {\r\n return (this.mode & readMode) === readMode;\r\n },\r\n set: function(val) {\r\n val ? this.mode |= readMode : this.mode &= ~readMode;\r\n }\r\n },\r\n write: {\r\n get: function() {\r\n return (this.mode & writeMode) === writeMode;\r\n },\r\n set: function(val) {\r\n val ? this.mode |= writeMode : this.mode &= ~writeMode;\r\n }\r\n },\r\n isFolder: {\r\n get: function() {\r\n return FS.isDir(this.mode);\r\n }\r\n },\r\n isDevice: {\r\n get: function() {\r\n return FS.isChrdev(this.mode);\r\n }\r\n }\r\n});\r\n\r\nFS.FSNode = FSNode;\r\n\r\nFS.staticInit();\r\n\r\nERRNO_CODES = {\r\n \"EPERM\": 63,\r\n \"ENOENT\": 44,\r\n \"ESRCH\": 71,\r\n \"EINTR\": 27,\r\n \"EIO\": 29,\r\n \"ENXIO\": 60,\r\n \"E2BIG\": 1,\r\n \"ENOEXEC\": 45,\r\n \"EBADF\": 8,\r\n \"ECHILD\": 12,\r\n \"EAGAIN\": 6,\r\n \"EWOULDBLOCK\": 6,\r\n \"ENOMEM\": 48,\r\n \"EACCES\": 2,\r\n \"EFAULT\": 21,\r\n \"ENOTBLK\": 105,\r\n \"EBUSY\": 10,\r\n \"EEXIST\": 20,\r\n \"EXDEV\": 75,\r\n \"ENODEV\": 43,\r\n \"ENOTDIR\": 54,\r\n \"EISDIR\": 31,\r\n \"EINVAL\": 28,\r\n \"ENFILE\": 41,\r\n \"EMFILE\": 33,\r\n \"ENOTTY\": 59,\r\n \"ETXTBSY\": 74,\r\n \"EFBIG\": 22,\r\n \"ENOSPC\": 51,\r\n \"ESPIPE\": 70,\r\n \"EROFS\": 69,\r\n \"EMLINK\": 34,\r\n \"EPIPE\": 64,\r\n \"EDOM\": 18,\r\n \"ERANGE\": 68,\r\n \"ENOMSG\": 49,\r\n \"EIDRM\": 24,\r\n \"ECHRNG\": 106,\r\n \"EL2NSYNC\": 156,\r\n \"EL3HLT\": 107,\r\n \"EL3RST\": 108,\r\n \"ELNRNG\": 109,\r\n \"EUNATCH\": 110,\r\n \"ENOCSI\": 111,\r\n \"EL2HLT\": 112,\r\n \"EDEADLK\": 16,\r\n \"ENOLCK\": 46,\r\n \"EBADE\": 113,\r\n \"EBADR\": 114,\r\n \"EXFULL\": 115,\r\n \"ENOANO\": 104,\r\n \"EBADRQC\": 103,\r\n \"EBADSLT\": 102,\r\n \"EDEADLOCK\": 16,\r\n \"EBFONT\": 101,\r\n \"ENOSTR\": 100,\r\n \"ENODATA\": 116,\r\n \"ETIME\": 117,\r\n \"ENOSR\": 118,\r\n \"ENONET\": 119,\r\n \"ENOPKG\": 120,\r\n \"EREMOTE\": 121,\r\n \"ENOLINK\": 47,\r\n \"EADV\": 122,\r\n \"ESRMNT\": 123,\r\n \"ECOMM\": 124,\r\n \"EPROTO\": 65,\r\n \"EMULTIHOP\": 36,\r\n \"EDOTDOT\": 125,\r\n \"EBADMSG\": 9,\r\n \"ENOTUNIQ\": 126,\r\n \"EBADFD\": 127,\r\n \"EREMCHG\": 128,\r\n \"ELIBACC\": 129,\r\n \"ELIBBAD\": 130,\r\n \"ELIBSCN\": 131,\r\n \"ELIBMAX\": 132,\r\n \"ELIBEXEC\": 133,\r\n \"ENOSYS\": 52,\r\n \"ENOTEMPTY\": 55,\r\n \"ENAMETOOLONG\": 37,\r\n \"ELOOP\": 32,\r\n \"EOPNOTSUPP\": 138,\r\n \"EPFNOSUPPORT\": 139,\r\n \"ECONNRESET\": 15,\r\n \"ENOBUFS\": 42,\r\n \"EAFNOSUPPORT\": 5,\r\n \"EPROTOTYPE\": 67,\r\n \"ENOTSOCK\": 57,\r\n \"ENOPROTOOPT\": 50,\r\n \"ESHUTDOWN\": 140,\r\n \"ECONNREFUSED\": 14,\r\n \"EADDRINUSE\": 3,\r\n \"ECONNABORTED\": 13,\r\n \"ENETUNREACH\": 40,\r\n \"ENETDOWN\": 38,\r\n \"ETIMEDOUT\": 73,\r\n \"EHOSTDOWN\": 142,\r\n \"EHOSTUNREACH\": 23,\r\n \"EINPROGRESS\": 26,\r\n \"EALREADY\": 7,\r\n \"EDESTADDRREQ\": 17,\r\n \"EMSGSIZE\": 35,\r\n \"EPROTONOSUPPORT\": 66,\r\n \"ESOCKTNOSUPPORT\": 137,\r\n \"EADDRNOTAVAIL\": 4,\r\n \"ENETRESET\": 39,\r\n \"EISCONN\": 30,\r\n \"ENOTCONN\": 53,\r\n \"ETOOMANYREFS\": 141,\r\n \"EUSERS\": 136,\r\n \"EDQUOT\": 19,\r\n \"ESTALE\": 72,\r\n \"ENOTSUP\": 138,\r\n \"ENOMEDIUM\": 148,\r\n \"EILSEQ\": 25,\r\n \"EOVERFLOW\": 61,\r\n \"ECANCELED\": 11,\r\n \"ENOTRECOVERABLE\": 56,\r\n \"EOWNERDEAD\": 62,\r\n \"ESTRPIPE\": 135\r\n};\r\n\r\nembind_init_charCodes();\r\n\r\nBindingError = Module[\"BindingError\"] = extendError(Error, \"BindingError\");\r\n\r\nInternalError = Module[\"InternalError\"] = extendError(Error, \"InternalError\");\r\n\r\ninit_ClassHandle();\r\n\r\ninit_embind();\r\n\r\ninit_RegisteredPointer();\r\n\r\nUnboundTypeError = Module[\"UnboundTypeError\"] = extendError(Error, \"UnboundTypeError\");\r\n\r\ninit_emval();\r\n\r\nvar ASSERTIONS = true;\r\n\r\nfunction intArrayFromString(stringy, dontAddNull, length) {\r\n var len = length > 0 ? length : lengthBytesUTF8(stringy) + 1;\r\n var u8array = new Array(len);\r\n var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length);\r\n if (dontAddNull) u8array.length = numBytesWritten;\r\n return u8array;\r\n}\r\n\r\nvar asmLibraryArg = {\r\n \"__assert_fail\": ___assert_fail,\r\n \"__syscall_dup\": ___syscall_dup,\r\n \"__syscall_open\": ___syscall_open,\r\n \"__syscall_stat64\": ___syscall_stat64,\r\n \"_embind_register_bigint\": __embind_register_bigint,\r\n \"_embind_register_bool\": __embind_register_bool,\r\n \"_embind_register_class\": __embind_register_class,\r\n \"_embind_register_class_constructor\": __embind_register_class_constructor,\r\n \"_embind_register_class_function\": __embind_register_class_function,\r\n \"_embind_register_emval\": __embind_register_emval,\r\n \"_embind_register_float\": __embind_register_float,\r\n \"_embind_register_function\": __embind_register_function,\r\n \"_embind_register_integer\": __embind_register_integer,\r\n \"_embind_register_memory_view\": __embind_register_memory_view,\r\n \"_embind_register_std_string\": __embind_register_std_string,\r\n \"_embind_register_std_wstring\": __embind_register_std_wstring,\r\n \"_embind_register_void\": __embind_register_void,\r\n \"_emval_decref\": __emval_decref,\r\n \"_emval_incref\": __emval_incref,\r\n \"_emval_take_value\": __emval_take_value,\r\n \"abort\": _abort,\r\n \"emscripten_asm_const_double\": _emscripten_asm_const_double,\r\n \"emscripten_asm_const_int\": _emscripten_asm_const_int,\r\n \"emscripten_builtin_mmap2\": _emscripten_builtin_mmap2,\r\n \"emscripten_builtin_munmap\": _emscripten_builtin_munmap,\r\n \"emscripten_console_error\": _emscripten_console_error,\r\n \"emscripten_get_heap_max\": _emscripten_get_heap_max,\r\n \"emscripten_get_module_name\": _emscripten_get_module_name,\r\n \"emscripten_get_now\": _emscripten_get_now,\r\n \"emscripten_pc_get_column\": _emscripten_pc_get_column,\r\n \"emscripten_pc_get_file\": _emscripten_pc_get_file,\r\n \"emscripten_pc_get_function\": _emscripten_pc_get_function,\r\n \"emscripten_pc_get_line\": _emscripten_pc_get_line,\r\n \"emscripten_resize_heap\": _emscripten_resize_heap,\r\n \"emscripten_return_address\": _emscripten_return_address,\r\n \"emscripten_stack_snapshot\": _emscripten_stack_snapshot,\r\n \"emscripten_stack_unwind_buffer\": _emscripten_stack_unwind_buffer,\r\n \"environ_get\": _environ_get,\r\n \"environ_sizes_get\": _environ_sizes_get,\r\n \"fd_close\": _fd_close,\r\n \"fd_read\": _fd_read,\r\n \"fd_write\": _fd_write,\r\n \"proc_exit\": _proc_exit,\r\n \"setTempRet0\": _setTempRet0\r\n};\r\n\r\nvar asm = createWasm();\r\n\r\nvar ___wasm_call_ctors = Module[\"___wasm_call_ctors\"] = createExportWrapper(\"__wasm_call_ctors\");\r\n\r\nvar ___getTypeName = Module[\"___getTypeName\"] = createExportWrapper(\"__getTypeName\");\r\n\r\nvar ___embind_register_native_and_builtin_types = Module[\"___embind_register_native_and_builtin_types\"] = createExportWrapper(\"__embind_register_native_and_builtin_types\");\r\n\r\nvar ___errno_location = Module[\"___errno_location\"] = createExportWrapper(\"__errno_location\");\r\n\r\nvar ___stdio_exit = Module[\"___stdio_exit\"] = createExportWrapper(\"__stdio_exit\");\r\n\r\nvar ___funcs_on_exit = Module[\"___funcs_on_exit\"] = createExportWrapper(\"__funcs_on_exit\");\r\n\r\nvar _malloc = Module[\"_malloc\"] = createExportWrapper(\"malloc\");\r\n\r\nvar _free = Module[\"_free\"] = createExportWrapper(\"free\");\r\n\r\nvar _memalign = Module[\"_memalign\"] = createExportWrapper(\"memalign\");\r\n\r\nvar _emscripten_builtin_malloc = Module[\"_emscripten_builtin_malloc\"] = createExportWrapper(\"emscripten_builtin_malloc\");\r\n\r\nvar _emscripten_builtin_free = Module[\"_emscripten_builtin_free\"] = createExportWrapper(\"emscripten_builtin_free\");\r\n\r\nvar _emscripten_builtin_memalign = Module[\"_emscripten_builtin_memalign\"] = createExportWrapper(\"emscripten_builtin_memalign\");\r\n\r\nvar _emscripten_stack_init = Module[\"_emscripten_stack_init\"] = function() {\r\n return (_emscripten_stack_init = Module[\"_emscripten_stack_init\"] = Module[\"asm\"][\"emscripten_stack_init\"]).apply(null, arguments);\r\n};\r\n\r\nvar _emscripten_stack_get_free = Module[\"_emscripten_stack_get_free\"] = function() {\r\n return (_emscripten_stack_get_free = Module[\"_emscripten_stack_get_free\"] = Module[\"asm\"][\"emscripten_stack_get_free\"]).apply(null, arguments);\r\n};\r\n\r\nvar _emscripten_stack_get_base = Module[\"_emscripten_stack_get_base\"] = function() {\r\n return (_emscripten_stack_get_base = Module[\"_emscripten_stack_get_base\"] = Module[\"asm\"][\"emscripten_stack_get_base\"]).apply(null, arguments);\r\n};\r\n\r\nvar _emscripten_stack_get_end = Module[\"_emscripten_stack_get_end\"] = function() {\r\n return (_emscripten_stack_get_end = Module[\"_emscripten_stack_get_end\"] = Module[\"asm\"][\"emscripten_stack_get_end\"]).apply(null, arguments);\r\n};\r\n\r\nvar stackSave = Module[\"stackSave\"] = createExportWrapper(\"stackSave\");\r\n\r\nvar stackRestore = Module[\"stackRestore\"] = createExportWrapper(\"stackRestore\");\r\n\r\nvar stackAlloc = Module[\"stackAlloc\"] = createExportWrapper(\"stackAlloc\");\r\n\r\nvar __ZN6__asan9FakeStack17AddrIsInFakeStackEm = Module[\"__ZN6__asan9FakeStack17AddrIsInFakeStackEm\"] = createExportWrapper(\"_ZN6__asan9FakeStack17AddrIsInFakeStackEm\");\r\n\r\nvar __ZN6__asan9FakeStack8AllocateEmmm = Module[\"__ZN6__asan9FakeStack8AllocateEmmm\"] = createExportWrapper(\"_ZN6__asan9FakeStack8AllocateEmmm\");\r\n\r\nvar _asan_c_load_1 = Module[\"_asan_c_load_1\"] = createExportWrapper(\"asan_c_load_1\");\r\n\r\nvar _asan_c_load_1u = Module[\"_asan_c_load_1u\"] = createExportWrapper(\"asan_c_load_1u\");\r\n\r\nvar _asan_c_load_2 = Module[\"_asan_c_load_2\"] = createExportWrapper(\"asan_c_load_2\");\r\n\r\nvar _asan_c_load_2u = Module[\"_asan_c_load_2u\"] = createExportWrapper(\"asan_c_load_2u\");\r\n\r\nvar _asan_c_load_4 = Module[\"_asan_c_load_4\"] = createExportWrapper(\"asan_c_load_4\");\r\n\r\nvar _asan_c_load_4u = Module[\"_asan_c_load_4u\"] = createExportWrapper(\"asan_c_load_4u\");\r\n\r\nvar _asan_c_load_f = Module[\"_asan_c_load_f\"] = createExportWrapper(\"asan_c_load_f\");\r\n\r\nvar _asan_c_load_d = Module[\"_asan_c_load_d\"] = createExportWrapper(\"asan_c_load_d\");\r\n\r\nvar _asan_c_store_1 = Module[\"_asan_c_store_1\"] = createExportWrapper(\"asan_c_store_1\");\r\n\r\nvar _asan_c_store_1u = Module[\"_asan_c_store_1u\"] = createExportWrapper(\"asan_c_store_1u\");\r\n\r\nvar _asan_c_store_2 = Module[\"_asan_c_store_2\"] = createExportWrapper(\"asan_c_store_2\");\r\n\r\nvar _asan_c_store_2u = Module[\"_asan_c_store_2u\"] = createExportWrapper(\"asan_c_store_2u\");\r\n\r\nvar _asan_c_store_4 = Module[\"_asan_c_store_4\"] = createExportWrapper(\"asan_c_store_4\");\r\n\r\nvar _asan_c_store_4u = Module[\"_asan_c_store_4u\"] = createExportWrapper(\"asan_c_store_4u\");\r\n\r\nvar _asan_c_store_f = Module[\"_asan_c_store_f\"] = createExportWrapper(\"asan_c_store_f\");\r\n\r\nvar _asan_c_store_d = Module[\"_asan_c_store_d\"] = createExportWrapper(\"asan_c_store_d\");\r\n\r\nvar dynCall_jii = Module[\"dynCall_jii\"] = createExportWrapper(\"dynCall_jii\");\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"intArrayFromString\")) Module[\"intArrayFromString\"] = (() => abort(\"'intArrayFromString' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"intArrayToString\")) Module[\"intArrayToString\"] = (() => abort(\"'intArrayToString' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"ccall\")) Module[\"ccall\"] = (() => abort(\"'ccall' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"cwrap\")) Module[\"cwrap\"] = (() => abort(\"'cwrap' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"setValue\")) Module[\"setValue\"] = (() => abort(\"'setValue' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"getValue\")) Module[\"getValue\"] = (() => abort(\"'getValue' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"allocate\")) Module[\"allocate\"] = (() => abort(\"'allocate' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"UTF8ArrayToString\")) Module[\"UTF8ArrayToString\"] = (() => abort(\"'UTF8ArrayToString' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"UTF8ToString\")) Module[\"UTF8ToString\"] = (() => abort(\"'UTF8ToString' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"stringToUTF8Array\")) Module[\"stringToUTF8Array\"] = (() => abort(\"'stringToUTF8Array' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"stringToUTF8\")) Module[\"stringToUTF8\"] = (() => abort(\"'stringToUTF8' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"lengthBytesUTF8\")) Module[\"lengthBytesUTF8\"] = (() => abort(\"'lengthBytesUTF8' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"stackTrace\")) Module[\"stackTrace\"] = (() => abort(\"'stackTrace' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"addOnPreRun\")) Module[\"addOnPreRun\"] = (() => abort(\"'addOnPreRun' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"addOnInit\")) Module[\"addOnInit\"] = (() => abort(\"'addOnInit' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"addOnPreMain\")) Module[\"addOnPreMain\"] = (() => abort(\"'addOnPreMain' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"addOnExit\")) Module[\"addOnExit\"] = (() => abort(\"'addOnExit' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"addOnPostRun\")) Module[\"addOnPostRun\"] = (() => abort(\"'addOnPostRun' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"writeStringToMemory\")) Module[\"writeStringToMemory\"] = (() => abort(\"'writeStringToMemory' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"writeArrayToMemory\")) Module[\"writeArrayToMemory\"] = (() => abort(\"'writeArrayToMemory' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"writeAsciiToMemory\")) Module[\"writeAsciiToMemory\"] = (() => abort(\"'writeAsciiToMemory' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"addRunDependency\")) Module[\"addRunDependency\"] = (() => abort(\"'addRunDependency' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"removeRunDependency\")) Module[\"removeRunDependency\"] = (() => abort(\"'removeRunDependency' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"FS_createFolder\")) Module[\"FS_createFolder\"] = (() => abort(\"'FS_createFolder' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"FS_createPath\")) Module[\"FS_createPath\"] = (() => abort(\"'FS_createPath' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"FS_createDataFile\")) Module[\"FS_createDataFile\"] = (() => abort(\"'FS_createDataFile' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"FS_createPreloadedFile\")) Module[\"FS_createPreloadedFile\"] = (() => abort(\"'FS_createPreloadedFile' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"FS_createLazyFile\")) Module[\"FS_createLazyFile\"] = (() => abort(\"'FS_createLazyFile' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"FS_createLink\")) Module[\"FS_createLink\"] = (() => abort(\"'FS_createLink' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"FS_createDevice\")) Module[\"FS_createDevice\"] = (() => abort(\"'FS_createDevice' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"FS_unlink\")) Module[\"FS_unlink\"] = (() => abort(\"'FS_unlink' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"getLEB\")) Module[\"getLEB\"] = (() => abort(\"'getLEB' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"getFunctionTables\")) Module[\"getFunctionTables\"] = (() => abort(\"'getFunctionTables' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"alignFunctionTables\")) Module[\"alignFunctionTables\"] = (() => abort(\"'alignFunctionTables' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"registerFunctions\")) Module[\"registerFunctions\"] = (() => abort(\"'registerFunctions' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"addFunction\")) Module[\"addFunction\"] = (() => abort(\"'addFunction' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"removeFunction\")) Module[\"removeFunction\"] = (() => abort(\"'removeFunction' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"getFuncWrapper\")) Module[\"getFuncWrapper\"] = (() => abort(\"'getFuncWrapper' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"prettyPrint\")) Module[\"prettyPrint\"] = (() => abort(\"'prettyPrint' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"dynCall\")) Module[\"dynCall\"] = (() => abort(\"'dynCall' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"getCompilerSetting\")) Module[\"getCompilerSetting\"] = (() => abort(\"'getCompilerSetting' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"print\")) Module[\"print\"] = (() => abort(\"'print' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"printErr\")) Module[\"printErr\"] = (() => abort(\"'printErr' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"getTempRet0\")) Module[\"getTempRet0\"] = (() => abort(\"'getTempRet0' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"setTempRet0\")) Module[\"setTempRet0\"] = (() => abort(\"'setTempRet0' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"callMain\")) Module[\"callMain\"] = (() => abort(\"'callMain' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"abort\")) Module[\"abort\"] = (() => abort(\"'abort' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"keepRuntimeAlive\")) Module[\"keepRuntimeAlive\"] = (() => abort(\"'keepRuntimeAlive' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"WasmOffsetConverter\")) Module[\"WasmOffsetConverter\"] = (() => abort(\"'WasmOffsetConverter' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"zeroMemory\")) Module[\"zeroMemory\"] = (() => abort(\"'zeroMemory' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"stringToNewUTF8\")) Module[\"stringToNewUTF8\"] = (() => abort(\"'stringToNewUTF8' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"setFileTime\")) Module[\"setFileTime\"] = (() => abort(\"'setFileTime' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"abortOnCannotGrowMemory\")) Module[\"abortOnCannotGrowMemory\"] = (() => abort(\"'abortOnCannotGrowMemory' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"emscripten_realloc_buffer\")) Module[\"emscripten_realloc_buffer\"] = (() => abort(\"'emscripten_realloc_buffer' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"ENV\")) Module[\"ENV\"] = (() => abort(\"'ENV' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"withStackSave\")) Module[\"withStackSave\"] = (() => abort(\"'withStackSave' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"ERRNO_CODES\")) Module[\"ERRNO_CODES\"] = (() => abort(\"'ERRNO_CODES' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"ERRNO_MESSAGES\")) Module[\"ERRNO_MESSAGES\"] = (() => abort(\"'ERRNO_MESSAGES' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"setErrNo\")) Module[\"setErrNo\"] = (() => abort(\"'setErrNo' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"inetPton4\")) Module[\"inetPton4\"] = (() => abort(\"'inetPton4' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"inetNtop4\")) Module[\"inetNtop4\"] = (() => abort(\"'inetNtop4' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"inetPton6\")) Module[\"inetPton6\"] = (() => abort(\"'inetPton6' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"inetNtop6\")) Module[\"inetNtop6\"] = (() => abort(\"'inetNtop6' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"readSockaddr\")) Module[\"readSockaddr\"] = (() => abort(\"'readSockaddr' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"writeSockaddr\")) Module[\"writeSockaddr\"] = (() => abort(\"'writeSockaddr' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"DNS\")) Module[\"DNS\"] = (() => abort(\"'DNS' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"getHostByName\")) Module[\"getHostByName\"] = (() => abort(\"'getHostByName' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"Protocols\")) Module[\"Protocols\"] = (() => abort(\"'Protocols' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"Sockets\")) Module[\"Sockets\"] = (() => abort(\"'Sockets' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"getRandomDevice\")) Module[\"getRandomDevice\"] = (() => abort(\"'getRandomDevice' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"traverseStack\")) Module[\"traverseStack\"] = (() => abort(\"'traverseStack' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"convertFrameToPC\")) Module[\"convertFrameToPC\"] = (() => abort(\"'convertFrameToPC' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"UNWIND_CACHE\")) Module[\"UNWIND_CACHE\"] = (() => abort(\"'UNWIND_CACHE' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"saveInUnwindCache\")) Module[\"saveInUnwindCache\"] = (() => abort(\"'saveInUnwindCache' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"convertPCtoSourceLocation\")) Module[\"convertPCtoSourceLocation\"] = (() => abort(\"'convertPCtoSourceLocation' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"withBuiltinMalloc\")) Module[\"withBuiltinMalloc\"] = (() => abort(\"'withBuiltinMalloc' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"readAsmConstArgsArray\")) Module[\"readAsmConstArgsArray\"] = (() => abort(\"'readAsmConstArgsArray' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"readAsmConstArgs\")) Module[\"readAsmConstArgs\"] = (() => abort(\"'readAsmConstArgs' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"mainThreadEM_ASM\")) Module[\"mainThreadEM_ASM\"] = (() => abort(\"'mainThreadEM_ASM' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"jstoi_q\")) Module[\"jstoi_q\"] = (() => abort(\"'jstoi_q' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"jstoi_s\")) Module[\"jstoi_s\"] = (() => abort(\"'jstoi_s' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"getExecutableName\")) Module[\"getExecutableName\"] = (() => abort(\"'getExecutableName' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"listenOnce\")) Module[\"listenOnce\"] = (() => abort(\"'listenOnce' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"autoResumeAudioContext\")) Module[\"autoResumeAudioContext\"] = (() => abort(\"'autoResumeAudioContext' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"dynCallLegacy\")) Module[\"dynCallLegacy\"] = (() => abort(\"'dynCallLegacy' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"getDynCaller\")) Module[\"getDynCaller\"] = (() => abort(\"'getDynCaller' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"dynCall\")) Module[\"dynCall\"] = (() => abort(\"'dynCall' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"callRuntimeCallbacks\")) Module[\"callRuntimeCallbacks\"] = (() => abort(\"'callRuntimeCallbacks' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"wasmTableMirror\")) Module[\"wasmTableMirror\"] = (() => abort(\"'wasmTableMirror' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"setWasmTableEntry\")) Module[\"setWasmTableEntry\"] = (() => abort(\"'setWasmTableEntry' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"getWasmTableEntry\")) Module[\"getWasmTableEntry\"] = (() => abort(\"'getWasmTableEntry' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"handleException\")) Module[\"handleException\"] = (() => abort(\"'handleException' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"runtimeKeepalivePush\")) Module[\"runtimeKeepalivePush\"] = (() => abort(\"'runtimeKeepalivePush' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"runtimeKeepalivePop\")) Module[\"runtimeKeepalivePop\"] = (() => abort(\"'runtimeKeepalivePop' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"callUserCallback\")) Module[\"callUserCallback\"] = (() => abort(\"'callUserCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"maybeExit\")) Module[\"maybeExit\"] = (() => abort(\"'maybeExit' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"safeSetTimeout\")) Module[\"safeSetTimeout\"] = (() => abort(\"'safeSetTimeout' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"asmjsMangle\")) Module[\"asmjsMangle\"] = (() => abort(\"'asmjsMangle' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"asyncLoad\")) Module[\"asyncLoad\"] = (() => abort(\"'asyncLoad' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"alignMemory\")) Module[\"alignMemory\"] = (() => abort(\"'alignMemory' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"mmapAlloc\")) Module[\"mmapAlloc\"] = (() => abort(\"'mmapAlloc' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"reallyNegative\")) Module[\"reallyNegative\"] = (() => abort(\"'reallyNegative' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"unSign\")) Module[\"unSign\"] = (() => abort(\"'unSign' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"reSign\")) Module[\"reSign\"] = (() => abort(\"'reSign' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"formatString\")) Module[\"formatString\"] = (() => abort(\"'formatString' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"PATH\")) Module[\"PATH\"] = (() => abort(\"'PATH' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"PATH_FS\")) Module[\"PATH_FS\"] = (() => abort(\"'PATH_FS' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"SYSCALLS\")) Module[\"SYSCALLS\"] = (() => abort(\"'SYSCALLS' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"syscallMmap2\")) Module[\"syscallMmap2\"] = (() => abort(\"'syscallMmap2' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"syscallMunmap\")) Module[\"syscallMunmap\"] = (() => abort(\"'syscallMunmap' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"getSocketFromFD\")) Module[\"getSocketFromFD\"] = (() => abort(\"'getSocketFromFD' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"getSocketAddress\")) Module[\"getSocketAddress\"] = (() => abort(\"'getSocketAddress' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"JSEvents\")) Module[\"JSEvents\"] = (() => abort(\"'JSEvents' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"registerKeyEventCallback\")) Module[\"registerKeyEventCallback\"] = (() => abort(\"'registerKeyEventCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"specialHTMLTargets\")) Module[\"specialHTMLTargets\"] = (() => abort(\"'specialHTMLTargets' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"maybeCStringToJsString\")) Module[\"maybeCStringToJsString\"] = (() => abort(\"'maybeCStringToJsString' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"findEventTarget\")) Module[\"findEventTarget\"] = (() => abort(\"'findEventTarget' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"findCanvasEventTarget\")) Module[\"findCanvasEventTarget\"] = (() => abort(\"'findCanvasEventTarget' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"getBoundingClientRect\")) Module[\"getBoundingClientRect\"] = (() => abort(\"'getBoundingClientRect' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"fillMouseEventData\")) Module[\"fillMouseEventData\"] = (() => abort(\"'fillMouseEventData' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"registerMouseEventCallback\")) Module[\"registerMouseEventCallback\"] = (() => abort(\"'registerMouseEventCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"registerWheelEventCallback\")) Module[\"registerWheelEventCallback\"] = (() => abort(\"'registerWheelEventCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"registerUiEventCallback\")) Module[\"registerUiEventCallback\"] = (() => abort(\"'registerUiEventCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"registerFocusEventCallback\")) Module[\"registerFocusEventCallback\"] = (() => abort(\"'registerFocusEventCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"fillDeviceOrientationEventData\")) Module[\"fillDeviceOrientationEventData\"] = (() => abort(\"'fillDeviceOrientationEventData' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"registerDeviceOrientationEventCallback\")) Module[\"registerDeviceOrientationEventCallback\"] = (() => abort(\"'registerDeviceOrientationEventCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"fillDeviceMotionEventData\")) Module[\"fillDeviceMotionEventData\"] = (() => abort(\"'fillDeviceMotionEventData' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"registerDeviceMotionEventCallback\")) Module[\"registerDeviceMotionEventCallback\"] = (() => abort(\"'registerDeviceMotionEventCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"screenOrientation\")) Module[\"screenOrientation\"] = (() => abort(\"'screenOrientation' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"fillOrientationChangeEventData\")) Module[\"fillOrientationChangeEventData\"] = (() => abort(\"'fillOrientationChangeEventData' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"registerOrientationChangeEventCallback\")) Module[\"registerOrientationChangeEventCallback\"] = (() => abort(\"'registerOrientationChangeEventCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"fillFullscreenChangeEventData\")) Module[\"fillFullscreenChangeEventData\"] = (() => abort(\"'fillFullscreenChangeEventData' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"registerFullscreenChangeEventCallback\")) Module[\"registerFullscreenChangeEventCallback\"] = (() => abort(\"'registerFullscreenChangeEventCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"registerRestoreOldStyle\")) Module[\"registerRestoreOldStyle\"] = (() => abort(\"'registerRestoreOldStyle' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"hideEverythingExceptGivenElement\")) Module[\"hideEverythingExceptGivenElement\"] = (() => abort(\"'hideEverythingExceptGivenElement' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"restoreHiddenElements\")) Module[\"restoreHiddenElements\"] = (() => abort(\"'restoreHiddenElements' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"setLetterbox\")) Module[\"setLetterbox\"] = (() => abort(\"'setLetterbox' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"currentFullscreenStrategy\")) Module[\"currentFullscreenStrategy\"] = (() => abort(\"'currentFullscreenStrategy' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"restoreOldWindowedStyle\")) Module[\"restoreOldWindowedStyle\"] = (() => abort(\"'restoreOldWindowedStyle' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"softFullscreenResizeWebGLRenderTarget\")) Module[\"softFullscreenResizeWebGLRenderTarget\"] = (() => abort(\"'softFullscreenResizeWebGLRenderTarget' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"doRequestFullscreen\")) Module[\"doRequestFullscreen\"] = (() => abort(\"'doRequestFullscreen' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"fillPointerlockChangeEventData\")) Module[\"fillPointerlockChangeEventData\"] = (() => abort(\"'fillPointerlockChangeEventData' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"registerPointerlockChangeEventCallback\")) Module[\"registerPointerlockChangeEventCallback\"] = (() => abort(\"'registerPointerlockChangeEventCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"registerPointerlockErrorEventCallback\")) Module[\"registerPointerlockErrorEventCallback\"] = (() => abort(\"'registerPointerlockErrorEventCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"requestPointerLock\")) Module[\"requestPointerLock\"] = (() => abort(\"'requestPointerLock' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"fillVisibilityChangeEventData\")) Module[\"fillVisibilityChangeEventData\"] = (() => abort(\"'fillVisibilityChangeEventData' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"registerVisibilityChangeEventCallback\")) Module[\"registerVisibilityChangeEventCallback\"] = (() => abort(\"'registerVisibilityChangeEventCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"registerTouchEventCallback\")) Module[\"registerTouchEventCallback\"] = (() => abort(\"'registerTouchEventCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"fillGamepadEventData\")) Module[\"fillGamepadEventData\"] = (() => abort(\"'fillGamepadEventData' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"registerGamepadEventCallback\")) Module[\"registerGamepadEventCallback\"] = (() => abort(\"'registerGamepadEventCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"registerBeforeUnloadEventCallback\")) Module[\"registerBeforeUnloadEventCallback\"] = (() => abort(\"'registerBeforeUnloadEventCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"fillBatteryEventData\")) Module[\"fillBatteryEventData\"] = (() => abort(\"'fillBatteryEventData' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"battery\")) Module[\"battery\"] = (() => abort(\"'battery' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"registerBatteryEventCallback\")) Module[\"registerBatteryEventCallback\"] = (() => abort(\"'registerBatteryEventCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"setCanvasElementSize\")) Module[\"setCanvasElementSize\"] = (() => abort(\"'setCanvasElementSize' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"getCanvasElementSize\")) Module[\"getCanvasElementSize\"] = (() => abort(\"'getCanvasElementSize' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"demangle\")) Module[\"demangle\"] = (() => abort(\"'demangle' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"demangleAll\")) Module[\"demangleAll\"] = (() => abort(\"'demangleAll' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"jsStackTrace\")) Module[\"jsStackTrace\"] = (() => abort(\"'jsStackTrace' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"stackTrace\")) Module[\"stackTrace\"] = (() => abort(\"'stackTrace' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"getEnvStrings\")) Module[\"getEnvStrings\"] = (() => abort(\"'getEnvStrings' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"checkWasiClock\")) Module[\"checkWasiClock\"] = (() => abort(\"'checkWasiClock' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"writeI53ToI64\")) Module[\"writeI53ToI64\"] = (() => abort(\"'writeI53ToI64' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"writeI53ToI64Clamped\")) Module[\"writeI53ToI64Clamped\"] = (() => abort(\"'writeI53ToI64Clamped' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"writeI53ToI64Signaling\")) Module[\"writeI53ToI64Signaling\"] = (() => abort(\"'writeI53ToI64Signaling' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"writeI53ToU64Clamped\")) Module[\"writeI53ToU64Clamped\"] = (() => abort(\"'writeI53ToU64Clamped' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"writeI53ToU64Signaling\")) Module[\"writeI53ToU64Signaling\"] = (() => abort(\"'writeI53ToU64Signaling' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"readI53FromI64\")) Module[\"readI53FromI64\"] = (() => abort(\"'readI53FromI64' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"readI53FromU64\")) Module[\"readI53FromU64\"] = (() => abort(\"'readI53FromU64' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"convertI32PairToI53\")) Module[\"convertI32PairToI53\"] = (() => abort(\"'convertI32PairToI53' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"convertU32PairToI53\")) Module[\"convertU32PairToI53\"] = (() => abort(\"'convertU32PairToI53' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"setImmediateWrapped\")) Module[\"setImmediateWrapped\"] = (() => abort(\"'setImmediateWrapped' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"clearImmediateWrapped\")) Module[\"clearImmediateWrapped\"] = (() => abort(\"'clearImmediateWrapped' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"polyfillSetImmediate\")) Module[\"polyfillSetImmediate\"] = (() => abort(\"'polyfillSetImmediate' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"uncaughtExceptionCount\")) Module[\"uncaughtExceptionCount\"] = (() => abort(\"'uncaughtExceptionCount' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"exceptionLast\")) Module[\"exceptionLast\"] = (() => abort(\"'exceptionLast' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"exceptionCaught\")) Module[\"exceptionCaught\"] = (() => abort(\"'exceptionCaught' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"ExceptionInfo\")) Module[\"ExceptionInfo\"] = (() => abort(\"'ExceptionInfo' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"CatchInfo\")) Module[\"CatchInfo\"] = (() => abort(\"'CatchInfo' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"exception_addRef\")) Module[\"exception_addRef\"] = (() => abort(\"'exception_addRef' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"exception_decRef\")) Module[\"exception_decRef\"] = (() => abort(\"'exception_decRef' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"Browser\")) Module[\"Browser\"] = (() => abort(\"'Browser' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"funcWrappers\")) Module[\"funcWrappers\"] = (() => abort(\"'funcWrappers' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"getFuncWrapper\")) Module[\"getFuncWrapper\"] = (() => abort(\"'getFuncWrapper' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"setMainLoop\")) Module[\"setMainLoop\"] = (() => abort(\"'setMainLoop' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"wget\")) Module[\"wget\"] = (() => abort(\"'wget' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"FS\")) Module[\"FS\"] = (() => abort(\"'FS' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"MEMFS\")) Module[\"MEMFS\"] = (() => abort(\"'MEMFS' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"TTY\")) Module[\"TTY\"] = (() => abort(\"'TTY' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"PIPEFS\")) Module[\"PIPEFS\"] = (() => abort(\"'PIPEFS' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"SOCKFS\")) Module[\"SOCKFS\"] = (() => abort(\"'SOCKFS' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"_setNetworkCallback\")) Module[\"_setNetworkCallback\"] = (() => abort(\"'_setNetworkCallback' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"tempFixedLengthArray\")) Module[\"tempFixedLengthArray\"] = (() => abort(\"'tempFixedLengthArray' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"miniTempWebGLFloatBuffers\")) Module[\"miniTempWebGLFloatBuffers\"] = (() => abort(\"'miniTempWebGLFloatBuffers' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"heapObjectForWebGLType\")) Module[\"heapObjectForWebGLType\"] = (() => abort(\"'heapObjectForWebGLType' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"heapAccessShiftForWebGLHeap\")) Module[\"heapAccessShiftForWebGLHeap\"] = (() => abort(\"'heapAccessShiftForWebGLHeap' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"GL\")) Module[\"GL\"] = (() => abort(\"'GL' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"emscriptenWebGLGet\")) Module[\"emscriptenWebGLGet\"] = (() => abort(\"'emscriptenWebGLGet' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"computeUnpackAlignedImageSize\")) Module[\"computeUnpackAlignedImageSize\"] = (() => abort(\"'computeUnpackAlignedImageSize' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"emscriptenWebGLGetTexPixelData\")) Module[\"emscriptenWebGLGetTexPixelData\"] = (() => abort(\"'emscriptenWebGLGetTexPixelData' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"emscriptenWebGLGetUniform\")) Module[\"emscriptenWebGLGetUniform\"] = (() => abort(\"'emscriptenWebGLGetUniform' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"webglGetUniformLocation\")) Module[\"webglGetUniformLocation\"] = (() => abort(\"'webglGetUniformLocation' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"webglPrepareUniformLocationsBeforeFirstUse\")) Module[\"webglPrepareUniformLocationsBeforeFirstUse\"] = (() => abort(\"'webglPrepareUniformLocationsBeforeFirstUse' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"webglGetLeftBracePos\")) Module[\"webglGetLeftBracePos\"] = (() => abort(\"'webglGetLeftBracePos' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"emscriptenWebGLGetVertexAttrib\")) Module[\"emscriptenWebGLGetVertexAttrib\"] = (() => abort(\"'emscriptenWebGLGetVertexAttrib' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"writeGLArray\")) Module[\"writeGLArray\"] = (() => abort(\"'writeGLArray' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"AL\")) Module[\"AL\"] = (() => abort(\"'AL' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"SDL_unicode\")) Module[\"SDL_unicode\"] = (() => abort(\"'SDL_unicode' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"SDL_ttfContext\")) Module[\"SDL_ttfContext\"] = (() => abort(\"'SDL_ttfContext' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"SDL_audio\")) Module[\"SDL_audio\"] = (() => abort(\"'SDL_audio' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"SDL\")) Module[\"SDL\"] = (() => abort(\"'SDL' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"SDL_gfx\")) Module[\"SDL_gfx\"] = (() => abort(\"'SDL_gfx' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"GLUT\")) Module[\"GLUT\"] = (() => abort(\"'GLUT' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"EGL\")) Module[\"EGL\"] = (() => abort(\"'EGL' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"GLFW_Window\")) Module[\"GLFW_Window\"] = (() => abort(\"'GLFW_Window' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"GLFW\")) Module[\"GLFW\"] = (() => abort(\"'GLFW' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"GLEW\")) Module[\"GLEW\"] = (() => abort(\"'GLEW' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"IDBStore\")) Module[\"IDBStore\"] = (() => abort(\"'IDBStore' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"runAndAbortIfError\")) Module[\"runAndAbortIfError\"] = (() => abort(\"'runAndAbortIfError' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"InternalError\")) Module[\"InternalError\"] = (() => abort(\"'InternalError' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"BindingError\")) Module[\"BindingError\"] = (() => abort(\"'BindingError' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"UnboundTypeError\")) Module[\"UnboundTypeError\"] = (() => abort(\"'UnboundTypeError' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"PureVirtualError\")) Module[\"PureVirtualError\"] = (() => abort(\"'PureVirtualError' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"init_embind\")) Module[\"init_embind\"] = (() => abort(\"'init_embind' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"throwInternalError\")) Module[\"throwInternalError\"] = (() => abort(\"'throwInternalError' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"throwBindingError\")) Module[\"throwBindingError\"] = (() => abort(\"'throwBindingError' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"throwUnboundTypeError\")) Module[\"throwUnboundTypeError\"] = (() => abort(\"'throwUnboundTypeError' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"ensureOverloadTable\")) Module[\"ensureOverloadTable\"] = (() => abort(\"'ensureOverloadTable' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"exposePublicSymbol\")) Module[\"exposePublicSymbol\"] = (() => abort(\"'exposePublicSymbol' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"replacePublicSymbol\")) Module[\"replacePublicSymbol\"] = (() => abort(\"'replacePublicSymbol' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"extendError\")) Module[\"extendError\"] = (() => abort(\"'extendError' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"createNamedFunction\")) Module[\"createNamedFunction\"] = (() => abort(\"'createNamedFunction' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"registeredInstances\")) Module[\"registeredInstances\"] = (() => abort(\"'registeredInstances' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"getBasestPointer\")) Module[\"getBasestPointer\"] = (() => abort(\"'getBasestPointer' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"registerInheritedInstance\")) Module[\"registerInheritedInstance\"] = (() => abort(\"'registerInheritedInstance' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"unregisterInheritedInstance\")) Module[\"unregisterInheritedInstance\"] = (() => abort(\"'unregisterInheritedInstance' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"getInheritedInstance\")) Module[\"getInheritedInstance\"] = (() => abort(\"'getInheritedInstance' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"getInheritedInstanceCount\")) Module[\"getInheritedInstanceCount\"] = (() => abort(\"'getInheritedInstanceCount' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"getLiveInheritedInstances\")) Module[\"getLiveInheritedInstances\"] = (() => abort(\"'getLiveInheritedInstances' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"registeredTypes\")) Module[\"registeredTypes\"] = (() => abort(\"'registeredTypes' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"awaitingDependencies\")) Module[\"awaitingDependencies\"] = (() => abort(\"'awaitingDependencies' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"typeDependencies\")) Module[\"typeDependencies\"] = (() => abort(\"'typeDependencies' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"registeredPointers\")) Module[\"registeredPointers\"] = (() => abort(\"'registeredPointers' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"registerType\")) Module[\"registerType\"] = (() => abort(\"'registerType' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"whenDependentTypesAreResolved\")) Module[\"whenDependentTypesAreResolved\"] = (() => abort(\"'whenDependentTypesAreResolved' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"embind_charCodes\")) Module[\"embind_charCodes\"] = (() => abort(\"'embind_charCodes' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"embind_init_charCodes\")) Module[\"embind_init_charCodes\"] = (() => abort(\"'embind_init_charCodes' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"readLatin1String\")) Module[\"readLatin1String\"] = (() => abort(\"'readLatin1String' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"getTypeName\")) Module[\"getTypeName\"] = (() => abort(\"'getTypeName' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"heap32VectorToArray\")) Module[\"heap32VectorToArray\"] = (() => abort(\"'heap32VectorToArray' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"requireRegisteredType\")) Module[\"requireRegisteredType\"] = (() => abort(\"'requireRegisteredType' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"getShiftFromSize\")) Module[\"getShiftFromSize\"] = (() => abort(\"'getShiftFromSize' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"integerReadValueFromPointer\")) Module[\"integerReadValueFromPointer\"] = (() => abort(\"'integerReadValueFromPointer' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"enumReadValueFromPointer\")) Module[\"enumReadValueFromPointer\"] = (() => abort(\"'enumReadValueFromPointer' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"floatReadValueFromPointer\")) Module[\"floatReadValueFromPointer\"] = (() => abort(\"'floatReadValueFromPointer' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"simpleReadValueFromPointer\")) Module[\"simpleReadValueFromPointer\"] = (() => abort(\"'simpleReadValueFromPointer' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"runDestructors\")) Module[\"runDestructors\"] = (() => abort(\"'runDestructors' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"new_\")) Module[\"new_\"] = (() => abort(\"'new_' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"craftInvokerFunction\")) Module[\"craftInvokerFunction\"] = (() => abort(\"'craftInvokerFunction' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"embind__requireFunction\")) Module[\"embind__requireFunction\"] = (() => abort(\"'embind__requireFunction' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"tupleRegistrations\")) Module[\"tupleRegistrations\"] = (() => abort(\"'tupleRegistrations' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"structRegistrations\")) Module[\"structRegistrations\"] = (() => abort(\"'structRegistrations' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"genericPointerToWireType\")) Module[\"genericPointerToWireType\"] = (() => abort(\"'genericPointerToWireType' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"constNoSmartPtrRawPointerToWireType\")) Module[\"constNoSmartPtrRawPointerToWireType\"] = (() => abort(\"'constNoSmartPtrRawPointerToWireType' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"nonConstNoSmartPtrRawPointerToWireType\")) Module[\"nonConstNoSmartPtrRawPointerToWireType\"] = (() => abort(\"'nonConstNoSmartPtrRawPointerToWireType' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"init_RegisteredPointer\")) Module[\"init_RegisteredPointer\"] = (() => abort(\"'init_RegisteredPointer' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"RegisteredPointer\")) Module[\"RegisteredPointer\"] = (() => abort(\"'RegisteredPointer' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"RegisteredPointer_getPointee\")) Module[\"RegisteredPointer_getPointee\"] = (() => abort(\"'RegisteredPointer_getPointee' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"RegisteredPointer_destructor\")) Module[\"RegisteredPointer_destructor\"] = (() => abort(\"'RegisteredPointer_destructor' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"RegisteredPointer_deleteObject\")) Module[\"RegisteredPointer_deleteObject\"] = (() => abort(\"'RegisteredPointer_deleteObject' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"RegisteredPointer_fromWireType\")) Module[\"RegisteredPointer_fromWireType\"] = (() => abort(\"'RegisteredPointer_fromWireType' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"runDestructor\")) Module[\"runDestructor\"] = (() => abort(\"'runDestructor' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"releaseClassHandle\")) Module[\"releaseClassHandle\"] = (() => abort(\"'releaseClassHandle' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"finalizationRegistry\")) Module[\"finalizationRegistry\"] = (() => abort(\"'finalizationRegistry' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"detachFinalizer_deps\")) Module[\"detachFinalizer_deps\"] = (() => abort(\"'detachFinalizer_deps' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"detachFinalizer\")) Module[\"detachFinalizer\"] = (() => abort(\"'detachFinalizer' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"attachFinalizer\")) Module[\"attachFinalizer\"] = (() => abort(\"'attachFinalizer' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"makeClassHandle\")) Module[\"makeClassHandle\"] = (() => abort(\"'makeClassHandle' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"init_ClassHandle\")) Module[\"init_ClassHandle\"] = (() => abort(\"'init_ClassHandle' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"ClassHandle\")) Module[\"ClassHandle\"] = (() => abort(\"'ClassHandle' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"ClassHandle_isAliasOf\")) Module[\"ClassHandle_isAliasOf\"] = (() => abort(\"'ClassHandle_isAliasOf' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"throwInstanceAlreadyDeleted\")) Module[\"throwInstanceAlreadyDeleted\"] = (() => abort(\"'throwInstanceAlreadyDeleted' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"ClassHandle_clone\")) Module[\"ClassHandle_clone\"] = (() => abort(\"'ClassHandle_clone' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"ClassHandle_delete\")) Module[\"ClassHandle_delete\"] = (() => abort(\"'ClassHandle_delete' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"deletionQueue\")) Module[\"deletionQueue\"] = (() => abort(\"'deletionQueue' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"ClassHandle_isDeleted\")) Module[\"ClassHandle_isDeleted\"] = (() => abort(\"'ClassHandle_isDeleted' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"ClassHandle_deleteLater\")) Module[\"ClassHandle_deleteLater\"] = (() => abort(\"'ClassHandle_deleteLater' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"flushPendingDeletes\")) Module[\"flushPendingDeletes\"] = (() => abort(\"'flushPendingDeletes' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"delayFunction\")) Module[\"delayFunction\"] = (() => abort(\"'delayFunction' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"setDelayFunction\")) Module[\"setDelayFunction\"] = (() => abort(\"'setDelayFunction' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"RegisteredClass\")) Module[\"RegisteredClass\"] = (() => abort(\"'RegisteredClass' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"shallowCopyInternalPointer\")) Module[\"shallowCopyInternalPointer\"] = (() => abort(\"'shallowCopyInternalPointer' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"downcastPointer\")) Module[\"downcastPointer\"] = (() => abort(\"'downcastPointer' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"upcastPointer\")) Module[\"upcastPointer\"] = (() => abort(\"'upcastPointer' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"validateThis\")) Module[\"validateThis\"] = (() => abort(\"'validateThis' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"char_0\")) Module[\"char_0\"] = (() => abort(\"'char_0' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"char_9\")) Module[\"char_9\"] = (() => abort(\"'char_9' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"makeLegalFunctionName\")) Module[\"makeLegalFunctionName\"] = (() => abort(\"'makeLegalFunctionName' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"emval_handle_array\")) Module[\"emval_handle_array\"] = (() => abort(\"'emval_handle_array' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"emval_free_list\")) Module[\"emval_free_list\"] = (() => abort(\"'emval_free_list' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"emval_symbols\")) Module[\"emval_symbols\"] = (() => abort(\"'emval_symbols' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"init_emval\")) Module[\"init_emval\"] = (() => abort(\"'init_emval' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"count_emval_handles\")) Module[\"count_emval_handles\"] = (() => abort(\"'count_emval_handles' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"get_first_emval\")) Module[\"get_first_emval\"] = (() => abort(\"'get_first_emval' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"getStringOrSymbol\")) Module[\"getStringOrSymbol\"] = (() => abort(\"'getStringOrSymbol' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"Emval\")) Module[\"Emval\"] = (() => abort(\"'Emval' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"emval_newers\")) Module[\"emval_newers\"] = (() => abort(\"'emval_newers' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"craftEmvalAllocator\")) Module[\"craftEmvalAllocator\"] = (() => abort(\"'craftEmvalAllocator' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"emval_get_global\")) Module[\"emval_get_global\"] = (() => abort(\"'emval_get_global' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"emval_methodCallers\")) Module[\"emval_methodCallers\"] = (() => abort(\"'emval_methodCallers' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"emval_registeredMethods\")) Module[\"emval_registeredMethods\"] = (() => abort(\"'emval_registeredMethods' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"warnOnce\")) Module[\"warnOnce\"] = (() => abort(\"'warnOnce' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"stackSave\")) Module[\"stackSave\"] = (() => abort(\"'stackSave' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"stackRestore\")) Module[\"stackRestore\"] = (() => abort(\"'stackRestore' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"stackAlloc\")) Module[\"stackAlloc\"] = (() => abort(\"'stackAlloc' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"AsciiToString\")) Module[\"AsciiToString\"] = (() => abort(\"'AsciiToString' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"stringToAscii\")) Module[\"stringToAscii\"] = (() => abort(\"'stringToAscii' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"UTF16ToString\")) Module[\"UTF16ToString\"] = (() => abort(\"'UTF16ToString' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"stringToUTF16\")) Module[\"stringToUTF16\"] = (() => abort(\"'stringToUTF16' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"lengthBytesUTF16\")) Module[\"lengthBytesUTF16\"] = (() => abort(\"'lengthBytesUTF16' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"UTF32ToString\")) Module[\"UTF32ToString\"] = (() => abort(\"'UTF32ToString' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"stringToUTF32\")) Module[\"stringToUTF32\"] = (() => abort(\"'stringToUTF32' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"lengthBytesUTF32\")) Module[\"lengthBytesUTF32\"] = (() => abort(\"'lengthBytesUTF32' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"allocateUTF8\")) Module[\"allocateUTF8\"] = (() => abort(\"'allocateUTF8' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"allocateUTF8OnStack\")) Module[\"allocateUTF8OnStack\"] = (() => abort(\"'allocateUTF8OnStack' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\"));\r\n\r\nModule[\"writeStackCookie\"] = writeStackCookie;\r\n\r\nModule[\"checkStackCookie\"] = checkStackCookie;\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"ALLOC_NORMAL\")) Object.defineProperty(Module, \"ALLOC_NORMAL\", {\r\n configurable: true,\r\n get: function() {\r\n abort(\"'ALLOC_NORMAL' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\");\r\n }\r\n});\r\n\r\nif (!Object.getOwnPropertyDescriptor(Module, \"ALLOC_STACK\")) Object.defineProperty(Module, \"ALLOC_STACK\", {\r\n configurable: true,\r\n get: function() {\r\n abort(\"'ALLOC_STACK' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\");\r\n }\r\n});\r\n\r\nvar calledRun;\r\n\r\nfunction ExitStatus(status) {\r\n this.name = \"ExitStatus\";\r\n this.message = \"Program terminated with exit(\" + status + \")\";\r\n this.status = status;\r\n}\r\n\r\ndependenciesFulfilled = function runCaller() {\r\n if (!calledRun) run();\r\n if (!calledRun) dependenciesFulfilled = runCaller;\r\n};\r\n\r\nfunction stackCheckInit() {\r\n _emscripten_stack_init();\r\n writeStackCookie();\r\n}\r\n\r\nfunction run(args) {\r\n args = args || arguments_;\r\n if (runDependencies > 0) {\r\n return;\r\n }\r\n stackCheckInit();\r\n preRun();\r\n if (runDependencies > 0) {\r\n return;\r\n }\r\n function doRun() {\r\n if (calledRun) return;\r\n calledRun = true;\r\n Module[\"calledRun\"] = true;\r\n if (ABORT) return;\r\n initRuntime();\r\n readyPromiseResolve(Module);\r\n if (Module[\"onRuntimeInitialized\"]) Module[\"onRuntimeInitialized\"]();\r\n assert(!Module[\"_main\"], 'compiled without a main, but one is present. if you added it from JS, use Module[\"onRuntimeInitialized\"]');\r\n postRun();\r\n }\r\n if (Module[\"setStatus\"]) {\r\n Module[\"setStatus\"](\"Running...\");\r\n setTimeout(function() {\r\n setTimeout(function() {\r\n Module[\"setStatus\"](\"\");\r\n }, 1);\r\n doRun();\r\n }, 1);\r\n } else {\r\n doRun();\r\n }\r\n checkStackCookie();\r\n}\r\n\r\nModule[\"run\"] = run;\r\n\r\nfunction procExit(code) {\r\n EXITSTATUS = code;\r\n if (!keepRuntimeAlive()) {\r\n if (Module[\"onExit\"]) Module[\"onExit\"](code);\r\n ABORT = true;\r\n }\r\n quit_(code, new ExitStatus(code));\r\n}\r\n\r\nif (Module[\"preInit\"]) {\r\n if (typeof Module[\"preInit\"] == \"function\") Module[\"preInit\"] = [ Module[\"preInit\"] ];\r\n while (Module[\"preInit\"].length > 0) {\r\n Module[\"preInit\"].pop()();\r\n }\r\n}\r\n\r\nrun();\r\n\r\n\r\n return createMLSGenModule.ready\r\n}\r\n);\r\n})();\r\nif (true)\r\n module.exports = createMLSGenModule;\r\nelse {}\r\n\n\n//# sourceURL=webpack://speakerCalibrator/./dist/mlsGen.js?");
|
|
29
29
|
|
|
30
30
|
/***/ }),
|
|
31
31
|
|
|
@@ -391,7 +391,7 @@ eval("/*!\n* sweetalert2 v11.14.0\n* Released under the MIT License.\n*/\n(funct
|
|
|
391
391
|
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
392
392
|
|
|
393
393
|
"use strict";
|
|
394
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var firebase_app__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! firebase/app */ \"./node_modules/firebase/app/dist/esm/index.esm.js\");\n/* harmony import */ var firebase_database__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! firebase/database */ \"./node_modules/firebase/database/dist/esm/index.esm.js\");\n/* harmony import */ var firebase_firestore__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! firebase/firestore */ \"./node_modules/firebase/firestore/dist/esm/index.esm.js\");\n// Import the functions you need from the SDKs you need\n\n\n\n// TODO: Add SDKs for Firebase products that you want to use\n// https://firebase.google.com/docs/web/setup#available-libraries\n\n// Your web app's Firebase configuration\n// For Firebase JS SDK v7.20.0 and later, measurementId is optional\nconst firebaseConfig = {\n apiKey: 'AIzaSyDZopCl6jqND4sFYCSiB1GpCXreXd6-Q9s',\n authDomain: 'speaker-calibration.firebaseapp.com',\n databaseURL: 'https://speaker-calibration-default-rtdb.firebaseio.com',\n projectId: 'speaker-calibration',\n storageBucket: 'speaker-calibration.appspot.com',\n messagingSenderId: '322038930574',\n appId: '1:322038930574:web:d10ca9e7d60b6da9bafddf',\n measurementId: 'G-3724GD92R6',\n};\n\n// Initialize Firebase\nconst app = (0,firebase_app__WEBPACK_IMPORTED_MODULE_0__.initializeApp)(firebaseConfig);\n// const database = getDatabase();\nconst database = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_2__.getFirestore)(app);\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (database);\n\n\n//# sourceURL=webpack://speakerCalibrator/./src/config/firebase.js?");
|
|
394
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var firebase_app__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! firebase/app */ \"./node_modules/firebase/app/dist/esm/index.esm.js\");\n/* harmony import */ var firebase_database__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! firebase/database */ \"./node_modules/firebase/database/dist/esm/index.esm.js\");\n/* harmony import */ var firebase_firestore__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! firebase/firestore */ \"./node_modules/firebase/firestore/dist/esm/index.esm.js\");\n// Import the functions you need from the SDKs you need\r\n\r\n\r\n\r\n// TODO: Add SDKs for Firebase products that you want to use\r\n// https://firebase.google.com/docs/web/setup#available-libraries\r\n\r\n// Your web app's Firebase configuration\r\n// For Firebase JS SDK v7.20.0 and later, measurementId is optional\r\nconst firebaseConfig = {\r\n apiKey: 'AIzaSyDZopCl6jqND4sFYCSiB1GpCXreXd6-Q9s',\r\n authDomain: 'speaker-calibration.firebaseapp.com',\r\n databaseURL: 'https://speaker-calibration-default-rtdb.firebaseio.com',\r\n projectId: 'speaker-calibration',\r\n storageBucket: 'speaker-calibration.appspot.com',\r\n messagingSenderId: '322038930574',\r\n appId: '1:322038930574:web:d10ca9e7d60b6da9bafddf',\r\n measurementId: 'G-3724GD92R6',\r\n};\r\n\r\n// Initialize Firebase\r\nconst app = (0,firebase_app__WEBPACK_IMPORTED_MODULE_0__.initializeApp)(firebaseConfig);\r\n// const database = getDatabase();\r\nconst database = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_2__.getFirestore)(app);\r\n\r\n/* harmony default export */ __webpack_exports__[\"default\"] = (database);\r\n\n\n//# sourceURL=webpack://speakerCalibrator/./src/config/firebase.js?");
|
|
395
395
|
|
|
396
396
|
/***/ }),
|
|
397
397
|
|
|
@@ -402,7 +402,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var fire
|
|
|
402
402
|
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
403
403
|
|
|
404
404
|
"use strict";
|
|
405
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ CalibrationTimedOutError: function() { return /* reexport safe */ _peer_connection_peerErrors__WEBPACK_IMPORTED_MODULE_5__.CalibrationTimedOutError; },\n/* harmony export */ CombinationCalibration: function() { return /* reexport safe */ _tasks_combination_combination__WEBPACK_IMPORTED_MODULE_4__[\"default\"]; },\n/* harmony export */ ImpulseResponseCalibration: function() { return /* reexport safe */ _tasks_impulse_response_impulseResponse__WEBPACK_IMPORTED_MODULE_3__[\"default\"]; },\n/* harmony export */ Listener: function() { return /* reexport safe */ _peer_connection_listener__WEBPACK_IMPORTED_MODULE_0__[\"default\"]; },\n/* harmony export */ MissingSpeakerIdError: function() { return /* reexport safe */ _peer_connection_peerErrors__WEBPACK_IMPORTED_MODULE_5__.MissingSpeakerIdError; },\n/* harmony export */ Speaker: function() { return /* reexport safe */ _peer_connection_speaker__WEBPACK_IMPORTED_MODULE_1__[\"default\"]; },\n/* harmony export */ UnsupportedDeviceError: function() { return /* reexport safe */ _peer_connection_peerErrors__WEBPACK_IMPORTED_MODULE_5__.UnsupportedDeviceError; },\n/* harmony export */ VolumeCalibration: function() { return /* reexport safe */ _tasks_volume_volume__WEBPACK_IMPORTED_MODULE_2__[\"default\"]; }\n/* harmony export */ });\n/* harmony import */ var _peer_connection_listener__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./peer-connection/listener */ \"./src/peer-connection/listener.js\");\n/* harmony import */ var _peer_connection_speaker__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./peer-connection/speaker */ \"./src/peer-connection/speaker.js\");\n/* harmony import */ var _tasks_volume_volume__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./tasks/volume/volume */ \"./src/tasks/volume/volume.js\");\n/* harmony import */ var _tasks_impulse_response_impulseResponse__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./tasks/impulse-response/impulseResponse */ \"./src/tasks/impulse-response/impulseResponse.js\");\n/* harmony import */ var _tasks_combination_combination__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./tasks/combination/combination */ \"./src/tasks/combination/combination.js\");\n/* harmony import */ var _peer_connection_peerErrors__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./peer-connection/peerErrors */ \"./src/peer-connection/peerErrors.js\");\n\n\n\n\n\n\n\n\n\n\n\n\n//# sourceURL=webpack://speakerCalibrator/./src/main.js?");
|
|
405
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ CalibrationTimedOutError: function() { return /* reexport safe */ _peer_connection_peerErrors__WEBPACK_IMPORTED_MODULE_5__.CalibrationTimedOutError; },\n/* harmony export */ CombinationCalibration: function() { return /* reexport safe */ _tasks_combination_combination__WEBPACK_IMPORTED_MODULE_4__[\"default\"]; },\n/* harmony export */ ImpulseResponseCalibration: function() { return /* reexport safe */ _tasks_impulse_response_impulseResponse__WEBPACK_IMPORTED_MODULE_3__[\"default\"]; },\n/* harmony export */ Listener: function() { return /* reexport safe */ _peer_connection_listener__WEBPACK_IMPORTED_MODULE_0__[\"default\"]; },\n/* harmony export */ MissingSpeakerIdError: function() { return /* reexport safe */ _peer_connection_peerErrors__WEBPACK_IMPORTED_MODULE_5__.MissingSpeakerIdError; },\n/* harmony export */ Speaker: function() { return /* reexport safe */ _peer_connection_speaker__WEBPACK_IMPORTED_MODULE_1__[\"default\"]; },\n/* harmony export */ UnsupportedDeviceError: function() { return /* reexport safe */ _peer_connection_peerErrors__WEBPACK_IMPORTED_MODULE_5__.UnsupportedDeviceError; },\n/* harmony export */ VolumeCalibration: function() { return /* reexport safe */ _tasks_volume_volume__WEBPACK_IMPORTED_MODULE_2__[\"default\"]; }\n/* harmony export */ });\n/* harmony import */ var _peer_connection_listener__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./peer-connection/listener */ \"./src/peer-connection/listener.js\");\n/* harmony import */ var _peer_connection_speaker__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./peer-connection/speaker */ \"./src/peer-connection/speaker.js\");\n/* harmony import */ var _tasks_volume_volume__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./tasks/volume/volume */ \"./src/tasks/volume/volume.js\");\n/* harmony import */ var _tasks_impulse_response_impulseResponse__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./tasks/impulse-response/impulseResponse */ \"./src/tasks/impulse-response/impulseResponse.js\");\n/* harmony import */ var _tasks_combination_combination__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./tasks/combination/combination */ \"./src/tasks/combination/combination.js\");\n/* harmony import */ var _peer_connection_peerErrors__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./peer-connection/peerErrors */ \"./src/peer-connection/peerErrors.js\");\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\n\n//# sourceURL=webpack://speakerCalibrator/./src/main.js?");
|
|
406
406
|
|
|
407
407
|
/***/ }),
|
|
408
408
|
|
|
@@ -413,7 +413,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
413
413
|
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
414
414
|
|
|
415
415
|
"use strict";
|
|
416
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/**\n * A simple event emitter class. Objects that inheret this class or implement it can then bubble events up to the UI\n * similar to existings event emitter such as 'onChange' or 'onClick'.\n */\nclass MyEventEmitter {\n #events;\n\n /** .\n * .\n * .\n * Default constructor, intializes an empty object to store events\n *\n * @example\n */\n constructor() {\n this.#events = {};\n }\n\n /**\n * The external API for this class. Gets called with an event name and a callback function that is fired when the event is emitted.\n *\n * @param name\n * @param listener\n * @example\n */\n on(name, listener) {\n if (!this.#events[name]) {\n this.#events[name] = [];\n }\n\n this.#events[name].push(listener);\n }\n\n /** .\n * .\n * .\n * Function to remove a listener that was previously set\n *\n * @param {*} name\n * @param {*} listenerToRemove\n * @example\n */\n removeListener(name, listenerToRemove) {\n if (!this.#events[name]) {\n throw new Error(`Can't remove a listener. Event \"${name}\" doesn't exits.`);\n }\n\n /**\n *\n * @param listener\n * @example\n */\n const filterListeners = listener => listener !== listenerToRemove;\n\n this.#events[name] = this.#events[name].filter(filterListeners);\n }\n\n /**\n * The internal API for this class. Gets called with an event name and a data object.\n * Any callbacks that have been set to listen to the matching event are dispatched.\n *\n * @param name\n * @param data\n * @example\n */\n emit(name, data) {\n if (!this.#events[name]) {\n throw new Error(`Can't emit an event. Event \"${name}\" doesn't exits.`);\n }\n\n /**\n *\n * @param {*} callback\n */\n const fireCallbacks = callback => {\n callback(data);\n };\n\n this.#events[name].forEach(fireCallbacks);\n }\n}\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (MyEventEmitter);\n\n\n//# sourceURL=webpack://speakerCalibrator/./src/myEventEmitter.js?");
|
|
416
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/**\r\n * A simple event emitter class. Objects that inheret this class or implement it can then bubble events up to the UI\r\n * similar to existings event emitter such as 'onChange' or 'onClick'.\r\n */\r\nclass MyEventEmitter {\r\n #events;\r\n\r\n /** .\r\n * .\r\n * .\r\n * Default constructor, intializes an empty object to store events\r\n *\r\n * @example\r\n */\r\n constructor() {\r\n this.#events = {};\r\n }\r\n\r\n /**\r\n * The external API for this class. Gets called with an event name and a callback function that is fired when the event is emitted.\r\n *\r\n * @param name\r\n * @param listener\r\n * @example\r\n */\r\n on(name, listener) {\r\n if (!this.#events[name]) {\r\n this.#events[name] = [];\r\n }\r\n\r\n this.#events[name].push(listener);\r\n }\r\n\r\n /** .\r\n * .\r\n * .\r\n * Function to remove a listener that was previously set\r\n *\r\n * @param {*} name\r\n * @param {*} listenerToRemove\r\n * @example\r\n */\r\n removeListener(name, listenerToRemove) {\r\n if (!this.#events[name]) {\r\n throw new Error(`Can't remove a listener. Event \"${name}\" doesn't exits.`);\r\n }\r\n\r\n /**\r\n *\r\n * @param listener\r\n * @example\r\n */\r\n const filterListeners = listener => listener !== listenerToRemove;\r\n\r\n this.#events[name] = this.#events[name].filter(filterListeners);\r\n }\r\n\r\n /**\r\n * The internal API for this class. Gets called with an event name and a data object.\r\n * Any callbacks that have been set to listen to the matching event are dispatched.\r\n *\r\n * @param name\r\n * @param data\r\n * @example\r\n */\r\n emit(name, data) {\r\n if (!this.#events[name]) {\r\n throw new Error(`Can't emit an event. Event \"${name}\" doesn't exits.`);\r\n }\r\n\r\n /**\r\n *\r\n * @param {*} callback\r\n */\r\n const fireCallbacks = callback => {\r\n callback(data);\r\n };\r\n\r\n this.#events[name].forEach(fireCallbacks);\r\n }\r\n}\r\n\r\n/* harmony default export */ __webpack_exports__[\"default\"] = (MyEventEmitter);\r\n\n\n//# sourceURL=webpack://speakerCalibrator/./src/myEventEmitter.js?");
|
|
417
417
|
|
|
418
418
|
/***/ }),
|
|
419
419
|
|
|
@@ -424,7 +424,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/**\n * A simple event emitte
|
|
|
424
424
|
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
425
425
|
|
|
426
426
|
"use strict";
|
|
427
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var peerjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! peerjs */ \"./node_modules/peerjs/dist/peerjs.min.js\");\n/* harmony import */ var peerjs__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(peerjs__WEBPACK_IMPORTED_MODULE_0__);\n\n\n// TODO: this was already here before, but appears to be unused\nconst pressFeedbackURI =\n 'data:audio/mpeg;base64,//uQZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASW5mbwAAAA8AAAALAAATlgAXFxcXFxcXFxcuLi4uLi4uLi5FRUVFRUVFRUVdXV1dXV1dXV10dHR0dHR0dHSLi4uLi4uLi4uioqKioqKioqK6urq6urq6urrR0dHR0dHR0dHo6Ojo6Ojo6Oj///////////8AAAA5TEFNRTMuMTAwAaoAAAAALgYAABSAJAZbTgAAgAAAE5YfafL/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//uQZAAAA0YVyhVvQAAAAA0goAABGfWdITn6gAgAADSDAAAAAEWjAwMwMDMFBzCQsw8PMPCwUDgkNMpNzXEoSUTP3s6nJPd4z28k62JNdIwIUHj3nvynRempMmLAo/tff9/3IchyHIch/IxY3SUmG86enD4Pg+fgmfEAIQQcsP+oH//E7/+Ud/1HP/B9AAABMCFFFAAAwDgCyMCVAgQcBQmARAHw0AOGAUgFJgUoL8YKsEvqzGA1APJQAIGBNgDpoBRvQYb6EIGhIkmJg1QA0aH0H4GDBgJ4G55UBpM1AGgUG0wAgOBIUAYJGoGFQ4AkHitxzRSocGMwDYYCwJAWAICgBD8jhwlEqBNsMiAkCBpQY2FxpG61opmucDLrjKi6Fmk5oK9PWVh1DNFM2IaRH/q8mTQgTF4sk0bnv//zEuqRMjYycuuj///5wxZzIvLSMTUxYyZL////86ZBqh4D+QUIABcwBQBLMCmAeTA4wJowO8E2DAeYwQ8CWMDLBHDB1QpIxscoSMwBQJj/WZBA3O4mFMHIAGzAKAVgwmcG8OIV//uSZCIN9VQ4wgd/gAAAAA0g4AABD+S/Di5+qgAAADSAAAAEEzcNTC4yM0m41SLDHAJLSggBKwtKRwb6+IBi4ctbepDskh2KmAgA16NTNrON66ptO40mNa9ayZHVx7zmGPHktZb7vP9xLn4fr+9jeO//8P+z39///9T/////t+d6vf1+c6fP9Hv5cxg4aA4TgkGIYmLbYHGAxaCjHwlM0lwBC4zGwzVG+MFnGoTY8sn0w1MSHA09vAM8ssDCSYAykIABmeCI4AKDMDIRfGbFAjWE8h+BfIEfBoFCTQJUcA5ZIrQDjzQ+gWzxsjDLtE4s46kxjHZZom2SXfyj6uadvNvb0ee/3dX//01YAVKw/FoW3hDrwUDTAwDMVigy8rTYaRNKug2tzzBwxnAx/DOuMhFECAOxWsDO6kAwkdQFH0BiwIgYlAwCgdAwiZBBI1kCC5JcWwCQWMQ/JQnkVFkOVN8oku8yDkjbMiry+2rrLvW/MvT53q/yv+n2///dywQL8DRgOgsrBBi0LGcngZrCZgYxGEAoZ+IplUdGJ1ifHVRh5v/7kmRMDPOhJ0MTn6qAAAANIAAAARDEiQhOf0pAAAA0gAAABAdCcEnCwmbqA1JhbIFwYKEAUGAXgOJo45oXAyjT0MinMgXM2UNoNGyYeLN0ENORMgQC5EYAJlr4Z3L3lgaHG5VO0lWX1q92J3t9sWM+bu9/fe8/VT/L+zq9v+zr9/+//8r71SAAAA9tq0AA1hzXXdxmzgPWzJyU20wh4EDDUSzWI4x4rgMGBd+IImDoAiEBAMCJn2HpqAlRpDIZhbxxp2ASQcGVRJG6RC4xmaZHiYlYPKGGdEGJjIoa4YtICXGHRhGJg2QMkYJADRGfCMTZE5+4ze1gMF1k163DfQrNgh83G3zIYoMdC4wEOwcrzMxMMam0AlYxkKzOgqMDhUuUBgYIQOWiEgwYHAogAwXBAYHAKAVVm0ZW2J1Wno9taaAzuOSF34AjMUjdBOy+pjbpKCil9TG/hOWRkUkxad2pAAAGFlrIADgyUqh1syPqzGQRoUAEDDoFgKMDw7MVA2NJ1sKHaMVghBwfGAgOgJR0migMTBUODDQezBI5jGNQzXD/+5JkjYD20jDN67/kngAADSAAAAEXjN0dTv9SAAAANIAAAASwgEb7HKvHZpiFAM0Bgs8wPYBNNi8MMfMIKRGRlOETOErM6wMGpBTQHTjJEQaKEBoKmlLXGizd5Ax5W2Byh0X6R9YRJ2rQFSKzgZDB0DQDKJHDr/MoZRDsaleN+vVhpoVqzczvZYx+Hdbx1/MuWOZb///Vr1YX93I/6P9KAWAQE8pFZWkOCuFAO0EEAThJ4OYwBQMHIJgUUVrHHRwaURUkZ4YX6MYvO6EDvpgTJY6aVeR7mGcgzBgfQE2YCuA5H9adJQKBCAhAqA53/aS/bk0T1zjIhpmcjVumpqS/ZZ1v6TuOXxF1+49x5d5Knl/Luvw7ua/8P/DdWT+dOkhD5zhvqb0db/93/5AQAQsF3glyO4MAysKti2BGAAdE0L31C4EMAhEAgAu28hgMOFHwEgaYACAFHpko0GM0ia2Yx0/wmKECIhpq5poYK2CTmAQAMhgAQBKYAoARFUAhUQbKhIMAxAFG3eFpLns4drJbaY9+pDVDPZ/QKtLHKNCpsTA6//uSZIEE9GAuRhNfzIAAAA0gAAABEnjLFK588sAAADSAAAAEdTXMSKxfop3DPM5RNbal/EvU7p6/Ie/t93Z1v6OqEAzmEmBoIQcGTCwGMCghPwvOQgUwEbKMZBgNAwOPZioUiMIl/ACXRGoREDB0clmTLApMiq4x2azRlmMM7NijivBEQxUIGvMGdAsjAxgHcDSxgRZANSYAOAgYs0FXAnwaIl43xAcuEVEogHIiFKRHEuREzUfFfSOoEgRyTk8Isema00Fl0gzqujqL/ZT3Krfoq7r1H/AvWzp/yXv/3f/oA0GjFwIZS19BgKAsiCDxuUBAMZ8D6zIZAIFMChweF7GFbQAITYoiSSSvMRBoUJ5l4RGVzOa2hhmAr6mbNSaYcYlxgqAvmAaCEYDAE6yBgAFIpAsGADyaXw+/MSnONGVBjhuNW+/dbYnEQqJJNwIgainmo0TB3Ofkus/yHs5P3dnW/+ryf+QqTEFNRTMuMTAwqqqqqqqqqqqqAABjBgrdYuwIwHSioNCCFkYbBZpMaoVDIRMDhB326ByJkJgYuGdC4P/7kmSwDPT4N0MLn6SAAAANIAAAARDIpRJOePLAAAA0gAAABDAGIA0YOGJhoVGKx+YbQxu2mmHbCT5rII6wYW2ASgYFJDgHYBAIpMARM6WcpEFALUjnWoXbkbwf8AGkx+2FugJGw/l2gIK+vverzfFet8Re/kur09f/f/u6f/1GySAhOMFigxOOnJAAdLIIqmTCCa9ahACTDANMqFMLAIQjQw0EVbjH4aOuN8OAgFCBn0sS0GpU0IAjUJ3MCoPaDTTB4AwnIE7MGrBCjAcgE836g5kUx6AtCKkjKElvKarxnFzLOlKRocalMtnabKM6hpYW5TSrdLe1Kop3e+ZWtymHt445fv9Vfyy/Hn5Xv///v1bXt4M9Z7+o729b+K/4b6pMQU1FMy4xMDCqqqqqqqqqqqoAArJ2QY8DbERAFjDyZMdBUwYDwIEDHduP9KsmPhhMKGHR0ZzTg0NTB4kGhkYqgZ2MZGQRUYNHoGXBgA4HWYEoBbGCNgvJhVgV8ZJaR2GsQJb5g5gRMYD+BQmAhADQNAVRoA4EQAOXUBwAkYBsAVr/+5Jk0w/0GynDE59coAAADSAAAAEULMkADn9SAAAANIAAAATsdabY4ta/VUMV5DuqzWuVs3pSSLmoKyJqFQGpUi+IAy2PdQm57ZU/m8oR6dDu/KvzehHpx5O/KkuvNN/o39SX9fblC3lusxd7wMr2zmhS+YLExsQBmRRQGKE6HITacxM2hgy8ATH50NVDsxSlQMPDL4bNJAg7HUAIBQcOjCRbMBtAdDAAACkwB4EWMCzCGTGll+U7EVMUMoPCSjDHgWcwaECqP+mza0I1QpATkY0Sm3lwsB0q0C3xd6GWuF4jEAeiqacWb5bdVxJbap8YzlnZWta3hLq34RaGf5hj3/pZ3HveY/3ku7/5a/7Wf//9/92aGoPcO9Z3nep/9H+mTEFNRTMuMTAwqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgBOZ2IMSwdMDATGQhDC4ZXKRj8wGMxub0k5717G//uSZPaO9axfvJOfPEAAAA0gAAABFsja3g5/cEAAADSAAAAELQSBSmZKFYVCYsIjBA1MCgYxWdDkBzMRAEwgQDIIBMgFIzWQTUjgPK3c02lpDWsiqM0Ih0w6QzjB4BzMDcD4wFgEzAfAeQQs8TcsNydp+n5wlq8UapFM2auMpwfZrv475ll25Y5ll3mtzMuwCWO8Ocqe/lndv+j/b1f6/9QATU2x0wCPIAYTCoUHAxhIYX2MXBDC24mvTCAedLotPVa09tEZwuBrSZmkoXXBgkY2SmmPBjQkpGrwfaYZQGhQDcPACJNPw90xLlijCVZWUifsophFk7ww7v7fGk6gE/vB+l0VNkSFwo0bYXJC6gyQQEiwvlDzbHAhHpZLIQbJ1UxBTUUzLjEwMFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVUASWNHVvyNdkdcuCnNLhmA8HuRIHbo/1AhfJ9JZVctla8gMQwpDT96eCGcDAGg8qCCIBce3D8P35RGMZXL8gcmxBByacE9hDD09hNohydtFshlp7EeIe9aMiMe/P/7kmTNjPTPJLaLvPDwAAANIAAAAQ/obuBt+FJAAAA0gAAABEchD3bEIchgekEBmZYRmyPAM3j4DJ8fhgfmeIjtD4HTwPAiPgNGB+BAAjtCABG8AwMvgwAEo5cSIfzt69YYDMdo9RxSsKtgIcom1PMylIK9rWkMkKzctAIIkqXCTqLYAoUrBCJrAlHzJipaMuaPvWraLnsMj6ExUtGUZ0ZRnJ7Q6PrnS7VrsC55kSlRyTYjonPkkybMT2AyVMrbMrYly661bq13Fz0K2JlbEdH1zk9ocnsB09CcutLYmj71p7Q6PWDI+hMXWjJ06Mozk9odH0BkfQmLrRlGdE6M5JrhKJzZKPoSSephKVHJlGcmLhkZXJJ9CYnrRkqSmMZybKpMQU1FMy4xMDCqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqr/+5Jk7QT0dTc4kxw0ogAADSAAAAEZOaLm5+WQSAAANIAAAASqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqglFJEIRoPjA2MDYyViqViCJxDHghjyPQ4ioUiYKw4EMzYZXAooDEE1y2zRpTu00acWUWWcacaUWYeWcacJAhYgWJFCRQGIFiBZZRZRZlw7s7PG////s7M7Ozs7M5xpRZR5RRpxZRZh5RRZRbRC1NP///9PKqqq4NNNNRKqJXTTTTVVVTEFNRTMuMTAwVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//uSZIIP9BFGHYksMlIAAA0gAAABAAABpAAAACAAADSAAAAEVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVQ==';\n\n/**\n * @typedef initParameters - Parameters for initializing the AudioPeer\n * @type {object}\n * @property {string} targetElementId - Target element where new elements will be appended.\n * @property {string} siteUrl: The url of the current site.\n */\nconst initParameters = {\n targetElementId: null,\n siteUrl: null,\n};\n\n/**\n * @class The first layer of abstraction on the PeerJS library.\n * It meant to be extended by the two seperate client classes, Speaker and Listener.\n * It implements the shared methods and properties of both classes.\n */\nclass AudioPeer {\n /**\n * Creates an instance of AudioPeer\n * Takes the url of the current site and a target element where html elements will be appended.\n *\n * @param params - See type definition for initParameters.\n * @param param\n * @example\n */\n constructor(param = initParameters) {\n // PeerJS\n /* Create the Peer object for our end of the connection. */\n this.peer = new (peerjs__WEBPACK_IMPORTED_MODULE_0___default())({\n secure: true,\n host: 'easyeyes-peer-server.herokuapp.com',\n port: 443,\n config: {\n iceServers: [\n {\n urls: 'stun:stun.relay.metered.ca:80',\n },\n {\n urls: 'turn:global.relay.metered.ca:80',\n username: 'de884cfc34189cdf1a5dd616',\n credential: 'IcOpouU9/TYBmpHU',\n },\n {\n urls: 'turn:global.relay.metered.ca:80?transport=tcp',\n username: 'de884cfc34189cdf1a5dd616',\n credential: 'IcOpouU9/TYBmpHU',\n },\n {\n urls: 'turn:global.relay.metered.ca:443',\n username: 'de884cfc34189cdf1a5dd616',\n credential: 'IcOpouU9/TYBmpHU',\n },\n {\n urls: 'turns:global.relay.metered.ca:443?transport=tcp',\n username: 'de884cfc34189cdf1a5dd616',\n credential: 'IcOpouU9/TYBmpHU',\n },\n ],\n },\n });\n this.conn = null;\n this.lastPeerId = null;\n\n // Display information to HTML elem with given id\n this.targetElement = param.targetElementId;\n\n this.siteUrl = param.siteUrl;\n this.debug = false;\n // Store for all incoming data\n this.dataStore = [];\n\n // Create and play sounds using this audio context\n this.sourceAudioContext = new (window.AudioContext ||\n window.webkitAudioContext ||\n window.audioContext)();\n }\n\n /** .\n * .\n * .\n * Helper method to display information to DOM element\n *\n * @param {string} message\n * @param {boolean} append\n * @example\n */\n displayUpdate = (message, append = true) => {\n // If the specified elem exists, update that elem\n if (document.getElementById(this.targetElement)) {\n const displayElement = document.getElementById(this.targetElement);\n if (append) {\n displayElement.innerText += `\\n${message}`;\n } else {\n displayElement.innerText = message;\n }\n } else {\n console.log('MESSAGE: ', message);\n }\n };\n\n /**\n * Callback method for when a peer connection is lost\n * saves the last peer id, last server id, and attempts to reconnect.\n *\n * @example\n */\n onPeerDisconnected = () => {\n this.displayUpdate('Connection lost. Please reconnect');\n\n // Workaround for peer.reconnect deleting previous id\n this.peer.id = this.lastPeerId;\n // eslint-disable-next-line no-underscore-dangle\n this.peer._lastServerId = this.lastPeerId;\n this.peer.reconnect();\n };\n\n /** .\n * .\n * .\n * Callback method that cleans up after peer connection is closed\n *\n * @example\n */\n onPeerClose = () => {\n this.displayUpdate('Connection closed');\n this.conn = null;\n };\n\n /** .\n * .\n * .\n * Helper method for when an error occurs\n *\n * @param {*} err\n * @example\n */\n onPeerError = err => {\n this.displayUpdate(err);\n console.log(`${err}`);\n };\n\n /** .\n * .\n * .\n * Helper method that converts url paramters to an object\n *\n * @returns {object}\n * @example\n */\n parseURLSearchParams = () =>\n // SOURCE: chickens, https://stackoverflow.com/questions/8648892/how-to-convert-url-parameters-to-a-javascript-object\n // eslint-disable-next-line no-restricted-globals\n Object.fromEntries(new URLSearchParams(location.search));\n\n /** .\n * .\n * .\n * Helper method that converts an object to a query string\n *\n * @param {object} params\n * @returns {string}\n * @example\n */\n queryStringFromObject = params =>\n Object.keys(params)\n .map(key => `${key}=${params[key]}`)\n .join('&');\n\n static keypressFeedbackSound = pressFeedbackURI;\n}\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (AudioPeer);\n\n\n//# sourceURL=webpack://speakerCalibrator/./src/peer-connection/audioPeer.js?");
|
|
427
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var peerjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! peerjs */ \"./node_modules/peerjs/dist/peerjs.min.js\");\n/* harmony import */ var peerjs__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(peerjs__WEBPACK_IMPORTED_MODULE_0__);\n\r\n\r\n// TODO: this was already here before, but appears to be unused\r\nconst pressFeedbackURI =\r\n 'data:audio/mpeg;base64,//uQZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASW5mbwAAAA8AAAALAAATlgAXFxcXFxcXFxcuLi4uLi4uLi5FRUVFRUVFRUVdXV1dXV1dXV10dHR0dHR0dHSLi4uLi4uLi4uioqKioqKioqK6urq6urq6urrR0dHR0dHR0dHo6Ojo6Ojo6Oj///////////8AAAA5TEFNRTMuMTAwAaoAAAAALgYAABSAJAZbTgAAgAAAE5YfafL/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//uQZAAAA0YVyhVvQAAAAA0goAABGfWdITn6gAgAADSDAAAAAEWjAwMwMDMFBzCQsw8PMPCwUDgkNMpNzXEoSUTP3s6nJPd4z28k62JNdIwIUHj3nvynRempMmLAo/tff9/3IchyHIch/IxY3SUmG86enD4Pg+fgmfEAIQQcsP+oH//E7/+Ud/1HP/B9AAABMCFFFAAAwDgCyMCVAgQcBQmARAHw0AOGAUgFJgUoL8YKsEvqzGA1APJQAIGBNgDpoBRvQYb6EIGhIkmJg1QA0aH0H4GDBgJ4G55UBpM1AGgUG0wAgOBIUAYJGoGFQ4AkHitxzRSocGMwDYYCwJAWAICgBD8jhwlEqBNsMiAkCBpQY2FxpG61opmucDLrjKi6Fmk5oK9PWVh1DNFM2IaRH/q8mTQgTF4sk0bnv//zEuqRMjYycuuj///5wxZzIvLSMTUxYyZL////86ZBqh4D+QUIABcwBQBLMCmAeTA4wJowO8E2DAeYwQ8CWMDLBHDB1QpIxscoSMwBQJj/WZBA3O4mFMHIAGzAKAVgwmcG8OIV//uSZCIN9VQ4wgd/gAAAAA0g4AABD+S/Di5+qgAAADSAAAAEEzcNTC4yM0m41SLDHAJLSggBKwtKRwb6+IBi4ctbepDskh2KmAgA16NTNrON66ptO40mNa9ayZHVx7zmGPHktZb7vP9xLn4fr+9jeO//8P+z39///9T/////t+d6vf1+c6fP9Hv5cxg4aA4TgkGIYmLbYHGAxaCjHwlM0lwBC4zGwzVG+MFnGoTY8sn0w1MSHA09vAM8ssDCSYAykIABmeCI4AKDMDIRfGbFAjWE8h+BfIEfBoFCTQJUcA5ZIrQDjzQ+gWzxsjDLtE4s46kxjHZZom2SXfyj6uadvNvb0ee/3dX//01YAVKw/FoW3hDrwUDTAwDMVigy8rTYaRNKug2tzzBwxnAx/DOuMhFECAOxWsDO6kAwkdQFH0BiwIgYlAwCgdAwiZBBI1kCC5JcWwCQWMQ/JQnkVFkOVN8oku8yDkjbMiry+2rrLvW/MvT53q/yv+n2///dywQL8DRgOgsrBBi0LGcngZrCZgYxGEAoZ+IplUdGJ1ifHVRh5v/7kmRMDPOhJ0MTn6qAAAANIAAAARDEiQhOf0pAAAA0gAAABAdCcEnCwmbqA1JhbIFwYKEAUGAXgOJo45oXAyjT0MinMgXM2UNoNGyYeLN0ENORMgQC5EYAJlr4Z3L3lgaHG5VO0lWX1q92J3t9sWM+bu9/fe8/VT/L+zq9v+zr9/+//8r71SAAAA9tq0AA1hzXXdxmzgPWzJyU20wh4EDDUSzWI4x4rgMGBd+IImDoAiEBAMCJn2HpqAlRpDIZhbxxp2ASQcGVRJG6RC4xmaZHiYlYPKGGdEGJjIoa4YtICXGHRhGJg2QMkYJADRGfCMTZE5+4ze1gMF1k163DfQrNgh83G3zIYoMdC4wEOwcrzMxMMam0AlYxkKzOgqMDhUuUBgYIQOWiEgwYHAogAwXBAYHAKAVVm0ZW2J1Wno9taaAzuOSF34AjMUjdBOy+pjbpKCil9TG/hOWRkUkxad2pAAAGFlrIADgyUqh1syPqzGQRoUAEDDoFgKMDw7MVA2NJ1sKHaMVghBwfGAgOgJR0migMTBUODDQezBI5jGNQzXD/+5JkjYD20jDN67/kngAADSAAAAEXjN0dTv9SAAAANIAAAASwgEb7HKvHZpiFAM0Bgs8wPYBNNi8MMfMIKRGRlOETOErM6wMGpBTQHTjJEQaKEBoKmlLXGizd5Ax5W2Byh0X6R9YRJ2rQFSKzgZDB0DQDKJHDr/MoZRDsaleN+vVhpoVqzczvZYx+Hdbx1/MuWOZb///Vr1YX93I/6P9KAWAQE8pFZWkOCuFAO0EEAThJ4OYwBQMHIJgUUVrHHRwaURUkZ4YX6MYvO6EDvpgTJY6aVeR7mGcgzBgfQE2YCuA5H9adJQKBCAhAqA53/aS/bk0T1zjIhpmcjVumpqS/ZZ1v6TuOXxF1+49x5d5Knl/Luvw7ua/8P/DdWT+dOkhD5zhvqb0db/93/5AQAQsF3glyO4MAysKti2BGAAdE0L31C4EMAhEAgAu28hgMOFHwEgaYACAFHpko0GM0ia2Yx0/wmKECIhpq5poYK2CTmAQAMhgAQBKYAoARFUAhUQbKhIMAxAFG3eFpLns4drJbaY9+pDVDPZ/QKtLHKNCpsTA6//uSZIEE9GAuRhNfzIAAAA0gAAABEnjLFK588sAAADSAAAAEdTXMSKxfop3DPM5RNbal/EvU7p6/Ie/t93Z1v6OqEAzmEmBoIQcGTCwGMCghPwvOQgUwEbKMZBgNAwOPZioUiMIl/ACXRGoREDB0clmTLApMiq4x2azRlmMM7NijivBEQxUIGvMGdAsjAxgHcDSxgRZANSYAOAgYs0FXAnwaIl43xAcuEVEogHIiFKRHEuREzUfFfSOoEgRyTk8Isema00Fl0gzqujqL/ZT3Krfoq7r1H/AvWzp/yXv/3f/oA0GjFwIZS19BgKAsiCDxuUBAMZ8D6zIZAIFMChweF7GFbQAITYoiSSSvMRBoUJ5l4RGVzOa2hhmAr6mbNSaYcYlxgqAvmAaCEYDAE6yBgAFIpAsGADyaXw+/MSnONGVBjhuNW+/dbYnEQqJJNwIgainmo0TB3Ofkus/yHs5P3dnW/+ryf+QqTEFNRTMuMTAwqqqqqqqqqqqqAABjBgrdYuwIwHSioNCCFkYbBZpMaoVDIRMDhB326ByJkJgYuGdC4P/7kmSwDPT4N0MLn6SAAAANIAAAARDIpRJOePLAAAA0gAAABDAGIA0YOGJhoVGKx+YbQxu2mmHbCT5rII6wYW2ASgYFJDgHYBAIpMARM6WcpEFALUjnWoXbkbwf8AGkx+2FugJGw/l2gIK+vverzfFet8Re/kur09f/f/u6f/1GySAhOMFigxOOnJAAdLIIqmTCCa9ahACTDANMqFMLAIQjQw0EVbjH4aOuN8OAgFCBn0sS0GpU0IAjUJ3MCoPaDTTB4AwnIE7MGrBCjAcgE836g5kUx6AtCKkjKElvKarxnFzLOlKRocalMtnabKM6hpYW5TSrdLe1Kop3e+ZWtymHt445fv9Vfyy/Hn5Xv///v1bXt4M9Z7+o729b+K/4b6pMQU1FMy4xMDCqqqqqqqqqqqoAArJ2QY8DbERAFjDyZMdBUwYDwIEDHduP9KsmPhhMKGHR0ZzTg0NTB4kGhkYqgZ2MZGQRUYNHoGXBgA4HWYEoBbGCNgvJhVgV8ZJaR2GsQJb5g5gRMYD+BQmAhADQNAVRoA4EQAOXUBwAkYBsAVr/+5Jk0w/0GynDE59coAAADSAAAAEULMkADn9SAAAANIAAAATsdabY4ta/VUMV5DuqzWuVs3pSSLmoKyJqFQGpUi+IAy2PdQm57ZU/m8oR6dDu/KvzehHpx5O/KkuvNN/o39SX9fblC3lusxd7wMr2zmhS+YLExsQBmRRQGKE6HITacxM2hgy8ATH50NVDsxSlQMPDL4bNJAg7HUAIBQcOjCRbMBtAdDAAACkwB4EWMCzCGTGll+U7EVMUMoPCSjDHgWcwaECqP+mza0I1QpATkY0Sm3lwsB0q0C3xd6GWuF4jEAeiqacWb5bdVxJbap8YzlnZWta3hLq34RaGf5hj3/pZ3HveY/3ku7/5a/7Wf//9/92aGoPcO9Z3nep/9H+mTEFNRTMuMTAwqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgBOZ2IMSwdMDATGQhDC4ZXKRj8wGMxub0k5717G//uSZPaO9axfvJOfPEAAAA0gAAABFsja3g5/cEAAADSAAAAELQSBSmZKFYVCYsIjBA1MCgYxWdDkBzMRAEwgQDIIBMgFIzWQTUjgPK3c02lpDWsiqM0Ih0w6QzjB4BzMDcD4wFgEzAfAeQQs8TcsNydp+n5wlq8UapFM2auMpwfZrv475ll25Y5ll3mtzMuwCWO8Ocqe/lndv+j/b1f6/9QATU2x0wCPIAYTCoUHAxhIYX2MXBDC24mvTCAedLotPVa09tEZwuBrSZmkoXXBgkY2SmmPBjQkpGrwfaYZQGhQDcPACJNPw90xLlijCVZWUifsophFk7ww7v7fGk6gE/vB+l0VNkSFwo0bYXJC6gyQQEiwvlDzbHAhHpZLIQbJ1UxBTUUzLjEwMFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVUASWNHVvyNdkdcuCnNLhmA8HuRIHbo/1AhfJ9JZVctla8gMQwpDT96eCGcDAGg8qCCIBce3D8P35RGMZXL8gcmxBByacE9hDD09hNohydtFshlp7EeIe9aMiMe/P/7kmTNjPTPJLaLvPDwAAANIAAAAQ/obuBt+FJAAAA0gAAABEchD3bEIchgekEBmZYRmyPAM3j4DJ8fhgfmeIjtD4HTwPAiPgNGB+BAAjtCABG8AwMvgwAEo5cSIfzt69YYDMdo9RxSsKtgIcom1PMylIK9rWkMkKzctAIIkqXCTqLYAoUrBCJrAlHzJipaMuaPvWraLnsMj6ExUtGUZ0ZRnJ7Q6PrnS7VrsC55kSlRyTYjonPkkybMT2AyVMrbMrYly661bq13Fz0K2JlbEdH1zk9ocnsB09CcutLYmj71p7Q6PWDI+hMXWjJ06Mozk9odH0BkfQmLrRlGdE6M5JrhKJzZKPoSSephKVHJlGcmLhkZXJJ9CYnrRkqSmMZybKpMQU1FMy4xMDCqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqr/+5Jk7QT0dTc4kxw0ogAADSAAAAEZOaLm5+WQSAAANIAAAASqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqglFJEIRoPjA2MDYyViqViCJxDHghjyPQ4ioUiYKw4EMzYZXAooDEE1y2zRpTu00acWUWWcacaUWYeWcacJAhYgWJFCRQGIFiBZZRZRZlw7s7PG////s7M7Ozs7M5xpRZR5RRpxZRZh5RRZRbRC1NP///9PKqqq4NNNNRKqJXTTTTVVVTEFNRTMuMTAwVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//uSZIIP9BFGHYksMlIAAA0gAAABAAABpAAAACAAADSAAAAEVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVQ==';\r\n\r\n/**\r\n * @typedef initParameters - Parameters for initializing the AudioPeer\r\n * @type {object}\r\n * @property {string} targetElementId - Target element where new elements will be appended.\r\n * @property {string} siteUrl: The url of the current site.\r\n */\r\nconst initParameters = {\r\n targetElementId: null,\r\n siteUrl: null,\r\n};\r\n\r\n/**\r\n * @class The first layer of abstraction on the PeerJS library.\r\n * It meant to be extended by the two seperate client classes, Speaker and Listener.\r\n * It implements the shared methods and properties of both classes.\r\n */\r\nclass AudioPeer {\r\n /**\r\n * Creates an instance of AudioPeer\r\n * Takes the url of the current site and a target element where html elements will be appended.\r\n *\r\n * @param params - See type definition for initParameters.\r\n * @param param\r\n * @example\r\n */\r\n constructor(param = initParameters) {\r\n // PeerJS\r\n /* Create the Peer object for our end of the connection. */\r\n this.peer = new (peerjs__WEBPACK_IMPORTED_MODULE_0___default())({\r\n secure: true,\r\n host: 'easyeyes-peer-server.herokuapp.com',\r\n port: 443,\r\n config: {\r\n iceServers: [\r\n {\r\n urls: 'stun:stun.relay.metered.ca:80',\r\n },\r\n {\r\n urls: 'turn:global.relay.metered.ca:80',\r\n username: 'de884cfc34189cdf1a5dd616',\r\n credential: 'IcOpouU9/TYBmpHU',\r\n },\r\n {\r\n urls: 'turn:global.relay.metered.ca:80?transport=tcp',\r\n username: 'de884cfc34189cdf1a5dd616',\r\n credential: 'IcOpouU9/TYBmpHU',\r\n },\r\n {\r\n urls: 'turn:global.relay.metered.ca:443',\r\n username: 'de884cfc34189cdf1a5dd616',\r\n credential: 'IcOpouU9/TYBmpHU',\r\n },\r\n {\r\n urls: 'turns:global.relay.metered.ca:443?transport=tcp',\r\n username: 'de884cfc34189cdf1a5dd616',\r\n credential: 'IcOpouU9/TYBmpHU',\r\n },\r\n ],\r\n },\r\n });\r\n this.conn = null;\r\n this.lastPeerId = null;\r\n\r\n // Display information to HTML elem with given id\r\n this.targetElement = param.targetElementId;\r\n\r\n this.siteUrl = param.siteUrl;\r\n this.debug = false;\r\n // Store for all incoming data\r\n this.dataStore = [];\r\n\r\n // Create and play sounds using this audio context\r\n this.sourceAudioContext = new (window.AudioContext ||\r\n window.webkitAudioContext ||\r\n window.audioContext)();\r\n }\r\n\r\n /** .\r\n * .\r\n * .\r\n * Helper method to display information to DOM element\r\n *\r\n * @param {string} message\r\n * @param {boolean} append\r\n * @example\r\n */\r\n displayUpdate = (message, append = true) => {\r\n // If the specified elem exists, update that elem\r\n if (document.getElementById(this.targetElement)) {\r\n const displayElement = document.getElementById(this.targetElement);\r\n if (append) {\r\n displayElement.innerText += `\\n${message}`;\r\n } else {\r\n displayElement.innerText = message;\r\n }\r\n } else {\r\n console.log('MESSAGE: ', message);\r\n }\r\n };\r\n\r\n /**\r\n * Callback method for when a peer connection is lost\r\n * saves the last peer id, last server id, and attempts to reconnect.\r\n *\r\n * @example\r\n */\r\n onPeerDisconnected = () => {\r\n this.displayUpdate('Connection lost. Please reconnect');\r\n\r\n // Workaround for peer.reconnect deleting previous id\r\n this.peer.id = this.lastPeerId;\r\n // eslint-disable-next-line no-underscore-dangle\r\n this.peer._lastServerId = this.lastPeerId;\r\n this.peer.reconnect();\r\n };\r\n\r\n /** .\r\n * .\r\n * .\r\n * Callback method that cleans up after peer connection is closed\r\n *\r\n * @example\r\n */\r\n onPeerClose = () => {\r\n this.displayUpdate('Connection closed');\r\n this.conn = null;\r\n };\r\n\r\n /** .\r\n * .\r\n * .\r\n * Helper method for when an error occurs\r\n *\r\n * @param {*} err\r\n * @example\r\n */\r\n onPeerError = err => {\r\n this.displayUpdate(err);\r\n console.log(`${err}`);\r\n };\r\n\r\n /** .\r\n * .\r\n * .\r\n * Helper method that converts url paramters to an object\r\n *\r\n * @returns {object}\r\n * @example\r\n */\r\n parseURLSearchParams = () =>\r\n // SOURCE: chickens, https://stackoverflow.com/questions/8648892/how-to-convert-url-parameters-to-a-javascript-object\r\n // eslint-disable-next-line no-restricted-globals\r\n Object.fromEntries(new URLSearchParams(location.search));\r\n\r\n /** .\r\n * .\r\n * .\r\n * Helper method that converts an object to a query string\r\n *\r\n * @param {object} params\r\n * @returns {string}\r\n * @example\r\n */\r\n queryStringFromObject = params =>\r\n Object.keys(params)\r\n .map(key => `${key}=${params[key]}`)\r\n .join('&');\r\n\r\n static keypressFeedbackSound = pressFeedbackURI;\r\n}\r\n\r\n/* harmony default export */ __webpack_exports__[\"default\"] = (AudioPeer);\r\n\n\n//# sourceURL=webpack://speakerCalibrator/./src/peer-connection/audioPeer.js?");
|
|
428
428
|
|
|
429
429
|
/***/ }),
|
|
430
430
|
|
|
@@ -435,7 +435,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var peer
|
|
|
435
435
|
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
436
436
|
|
|
437
437
|
"use strict";
|
|
438
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _audioPeer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./audioPeer */ \"./src/peer-connection/audioPeer.js\");\n/* harmony import */ var _peerErrors__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./peerErrors */ \"./src/peer-connection/peerErrors.js\");\n\n\n\n\n/**\n * @class Handles the listener's side of the connection. Responsible for getting access to user's microphone,\n * and initiating a call to the Speaker.\n * @augments AudioPeer\n */\nclass Listener extends _audioPeer__WEBPACK_IMPORTED_MODULE_0__[\"default\"] {\n /**\n * Takes a target element where html elements will be appended.\n *\n * @param params - See type definition for initParameters.\n * @example\n */\n constructor(params) {\n super(params);\n this.microphoneFromAPI = params.microphoneFromAPI ? params.microphoneFromAPI : '';\n this.microphoneDeviceId = params.microphoneDeviceId ? params.microphoneDeviceId : '';\n // this.deviceInfoFromUser = params.deviceInfoFromUser\n // ? params.deviceInfoFromUser\n // : {modelNumber: '', modelName: ''};\n this.startTime = Date.now();\n this.receiverPeerId = null;\n\n const urlParameters = this.parseURLSearchParams();\n this.calibrateSoundHz =\n // previous calibrateSoundHz\n urlParameters.hz !== null && urlParameters.hz !== undefined ? urlParameters.hz : 48000;\n this.calibrateSoundSamplingDesiredBits =\n // previous calibrateSoundSamplingDesiredBits\n urlParameters.bits !== null && urlParameters.bits !== undefined ? urlParameters.bits : 24;\n this.speakerPeerId = urlParameters.speakerPeerId;\n\n this.peer.on('open', this.onPeerOpen);\n this.peer.on('connection', this.onPeerConnection);\n this.peer.on('disconnected', this.onPeerDisconnected);\n this.peer.on('close', this.onPeerClose);\n this.peer.on('error', this.onPeerError);\n }\n\n onPeerOpen = id => {\n this.displayUpdate('Listener - onPeerOpen');\n // Workaround for peer.reconnect deleting previous id\n\n if (id === null) {\n this.displayUpdate('Received null id from peer open');\n this.peer.id = this.lastPeerId;\n } else {\n this.lastPeerId = this.peer.id;\n }\n\n this.join();\n };\n\n onPeerConnection = connection => {\n this.displayUpdate('Listener - onPeerConnection');\n // Disallow incoming connections\n connection.on('open', () => {\n connection.send('Sender does not accept incoming connections');\n setTimeout(() => {\n connection.close();\n }, 500);\n });\n };\n\n onConnData = data => {\n this.displayUpdate('Listener - onConnData');\n const hasSpeakerID = Object.prototype.hasOwnProperty.call(data, 'speakerPeerId');\n if (!hasSpeakerID) {\n this.displayUpdate('Error in parsing data received! Must set \"speakerPeerId\" property');\n throw new _peerErrors__WEBPACK_IMPORTED_MODULE_1__.MissingSpeakerIdError('Must set \"speakerPeerId\" property');\n } else {\n // this.conn.close();\n this.displayUpdate(this.speakerPeerId);\n this.speakerPeerId = data.speakerPeerId;\n const newParams = {\n speakerPeerId: this.speakerPeerId,\n };\n /*\n FUTURE does this limit usable environments?\n ie does this work if internet is lost after initial page load?\n */\n window.location.search = this.queryStringFromObject(newParams); // Redirect to correctly constructed keypad page\n }\n };\n\n join = async () => {\n this.displayUpdate('Listener - join');\n /**\n * Create the connection between the two Peers.\n *\n * Sets up callbacks that handle any events related to the\n * connection and data received on it.\n */\n // Close old connection\n if (this.conn) {\n this.displayUpdate('Closing old connection');\n this.conn.close();\n }\n\n // Create connection to destination peer specified by the query param\n this.displayUpdate(`Creating connection to: ${this.speakerPeerId}`);\n this.conn = this.peer.connect(this.speakerPeerId, {\n reliable: true,\n });\n\n this.displayUpdate('Created connection');\n this.conn.on('open', async () => {\n this.displayUpdate('Listener - conn open');\n await this.getDeviceInfo();\n // this.sendSamplingRate();\n await this.openAudioStream();\n });\n\n // Handle incoming data (messages only since this is the signal sender)\n this.conn.on('data', this.onConnData);\n this.conn.on('close', () => {\n console.log('Connection closed');\n });\n };\n\n getMobileOS = () => {\n const ua = navigator.userAgent;\n if (/android/i.test(ua)) {\n return 'Android';\n }\n if (\n /iPad|iPhone|iPod/.test(ua) ||\n ((navigator?.userAgentData?.platform || navigator?.platform) === 'MacIntel' &&\n navigator.maxTouchPoints > 1)\n ) {\n return 'iOS';\n }\n return 'Other';\n };\n\n sendSamplingRate = sampleRate => {\n this.displayUpdate('Listener - sendSamplingRate');\n this.conn.send({\n name: 'samplingRate',\n payload: sampleRate,\n });\n };\n\n sendSampleSize = sampleSize => {\n this.displayUpdate('Listener - sendSampleSize');\n this.conn.send({\n name: 'sampleSize',\n payload: sampleSize,\n });\n };\n\n sendFlags = flags => {\n this.displayUpdate('Listener - sendFlags');\n this.conn.send({\n name: 'flags',\n payload: flags,\n });\n };\n\n getDeviceInfo = async () => {\n try {\n const deviceInfo = {};\n fod.complete(function (data) {\n deviceInfo['IsMobile'] = data.device['ismobile'];\n deviceInfo['HardwareName'] = data.device['hardwarename'];\n deviceInfo['HardwareFamily'] = data.device['hardwarefamily'];\n deviceInfo['HardwareModel'] = data.device['hardwaremodel'];\n deviceInfo['OEM'] = data.device['oem'];\n deviceInfo['HardwareModelVariants'] = data.device['hardwaremodelvariants'];\n deviceInfo['DeviceId'] = data.device['deviceid'];\n deviceInfo['PlatformName'] = data.device['platformname'];\n deviceInfo['PlatformVersion'] = data.device['platformversion'];\n deviceInfo['DeviceType'] = data.device['devicetype'];\n // deviceInfo['deviceInfoFromUser'] = this.deviceInfoFromUser;\n });\n // deviceInfo['deviceInfoFromUser'] = this.deviceInfoFromUser;\n deviceInfo['microphoneFromAPI'] = this.microphoneFromAPI;\n deviceInfo['microphoneDeviceId'] = this.microphoneDeviceId;\n deviceInfo['screenWidth'] = window.screen.width;\n deviceInfo['screenHeight'] = window.screen.height;\n console.log('deviceInfo Inside getDeviceInfo: ', deviceInfo);\n this.conn.send({\n name: 'deviceInfo',\n payload: deviceInfo,\n });\n return deviceInfo;\n } catch (error) {\n console.error('Error fetching or executing script:', error.message);\n return null;\n }\n };\n\n applyHQTrackConstraints = async stream => {\n // Contraint the incoming audio to the sampling rate we want\n stream.getAudioTracks().forEach(track => {\n console.log(track, track.enabled);\n });\n const track = stream.getAudioTracks()[0];\n console.log(track);\n const capabilities = track.getCapabilities();\n\n this.displayUpdate(\n `Listener Track Capabilities - ${JSON.stringify(capabilities, undefined, 2)}`\n );\n\n const constraints = track.getConstraints();\n\n if (capabilities.echoCancellation) {\n constraints.echoCancellation = false;\n }\n\n if (capabilities.sampleRate) {\n constraints.sampleRate = this.calibrateSoundHz;\n }\n\n if (capabilities.sampleSize) {\n constraints.sampleSize = this.calibrateSoundSamplingDesiredBits;\n }\n\n if (capabilities.channelCount) {\n constraints.channelCount = 1;\n }\n\n this.displayUpdate(`Listener Track Constraints - ${JSON.stringify(constraints, undefined, 2)}`);\n\n // await the promise\n try {\n await track.applyConstraints(constraints);\n } catch (err) {\n console.error(err);\n this.displayUpdate(`Error applying constraints to track: ${err}`);\n }\n\n const settings = track.getSettings();\n this.displayUpdate(`Listener Track Settings - ${JSON.stringify(settings, undefined, 2)}`);\n return settings;\n };\n\n getMediaDevicesAudioContraints = async () => {\n const availableConstraints = navigator.mediaDevices.getSupportedConstraints();\n\n const contraints = {\n // ...(availableConstraints.echoCancellation && availableConstraints.echoCancellation == true\n // ? {echoCancellation: {exact: false}}\n // : {}),\n // ...(availableConstraints.sampleRate && availableConstraints.sampleRate == true\n // ? {sampleRate: {ideal: this.calibrateSoundHz}}\n // : {}),\n // ...(availableConstraints.sampleSize && availableConstraints.sampleSize == true\n // ? {sampleSize: {ideal: this.calibrateSoundSamplingDesiredBits}}\n // : {}),\n // ...(availableConstraints.channelCount && availableConstraints.channelCount == true\n // ? {channelCount: {exact: 1}}\n // : {}),\n echoCancellation: false,\n channelCount: 1,\n };\n\n if (this.microphoneDeviceId !== '') {\n contraints.deviceId = {exact: await this.getDeviceIdByLabel(this.microphoneDeviceId)};\n }\n\n console.log(contraints);\n\n return contraints;\n };\n getDeviceIdByLabel = async targetLabel => {\n try {\n // Enumerate available media devices\n const devices = await navigator.mediaDevices.enumerateDevices();\n\n // Find the device with the matching label\n const matchingDevice = devices.find(\n device => device.kind === 'audioinput' && device.label === targetLabel\n );\n\n if (matchingDevice) {\n return matchingDevice.deviceId; // Return the deviceId if found\n } else {\n throw new Error(`No audio input device found with label: \"${targetLabel}\"`);\n }\n } catch (error) {\n console.error('Error finding device ID:', error);\n return null;\n }\n };\n\n openAudioStream = async () => {\n this.displayUpdate('Listener - openAudioStream');\n const mobileOS = this.getMobileOS();\n if (false) {}\n const constraints = await this.getMediaDevicesAudioContraints();\n console.log('Constraints right before getUserMedia:', constraints);\n navigator.mediaDevices\n .getUserMedia({\n audio: constraints,\n video: false,\n //audio: {echoCancellation: false, noiseSuppression: false, autoGainControl: false, deviceId: {exact: await this.getDeviceIdByLabel(this.microphoneDeviceId) }},\n })\n .then(stream => {\n this.displayUpdate(\n `Listener Track settings before applied constraints - ${JSON.stringify(\n stream.getAudioTracks()[0].getSettings(),\n undefined,\n 2\n )}`\n );\n this.applyHQTrackConstraints(stream)\n .then(settings => {\n console.log(settings);\n this.sendSamplingRate(settings.sampleRate);\n let sampleSize = settings.sampleSize;\n if (!sampleSize) {\n sampleSize = this.calibrateSoundSamplingDesiredBits;\n }\n this.sendSampleSize(sampleSize);\n this.sendFlags({\n autoGainControl: settings.autoGainControl,\n noiseSuppression: settings.noiseSuppression,\n echoCancellation: settings.echoCancellation,\n });\n this.peer.call(this.speakerPeerId, stream); // one-way call\n this.displayUpdate('Listener - openAudioStream');\n })\n .catch(err => {\n console.log(err);\n this.displayUpdate(\n `Listener - Error in applyHQTrackConstraints - ${JSON.stringify(err, undefined, 2)}`\n );\n });\n })\n .catch(err => {\n console.error(err);\n if (err.name === 'OverconstrainedError') {\n const constraint = err.constraint;\n const message = `The constraint \"${constraint}\" cannot be satisfied by the selected microphone. Please adjust your calibration settings or choose a different microphone.`;\n\n this.displayUpdate(`Listener - OverconstrainedError: ${message}`);\n console.error(message);\n\n alert(`Overconstrained Error: ${message}`);\n }\n this.displayUpdate(\n `Listener - Error in getUserMedia - ${JSON.stringify(err, undefined, 2)}`\n );\n });\n };\n}\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (Listener);\n\n\n//# sourceURL=webpack://speakerCalibrator/./src/peer-connection/listener.js?");
|
|
438
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _audioPeer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./audioPeer */ \"./src/peer-connection/audioPeer.js\");\n/* harmony import */ var _peerErrors__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./peerErrors */ \"./src/peer-connection/peerErrors.js\");\n\r\n\r\n\r\n\r\n/**\r\n * @class Handles the listener's side of the connection. Responsible for getting access to user's microphone,\r\n * and initiating a call to the Speaker.\r\n * @augments AudioPeer\r\n */\r\nclass Listener extends _audioPeer__WEBPACK_IMPORTED_MODULE_0__[\"default\"] {\r\n /**\r\n * Takes a target element where html elements will be appended.\r\n *\r\n * @param params - See type definition for initParameters.\r\n * @example\r\n */\r\n constructor(params) {\r\n super(params);\r\n this.microphoneFromAPI = params.microphoneFromAPI ? params.microphoneFromAPI : '';\r\n this.microphoneDeviceId = params.microphoneDeviceId ? params.microphoneDeviceId : '';\r\n // this.deviceInfoFromUser = params.deviceInfoFromUser\r\n // ? params.deviceInfoFromUser\r\n // : {modelNumber: '', modelName: ''};\r\n this.startTime = Date.now();\r\n this.receiverPeerId = null;\r\n\r\n const urlParameters = this.parseURLSearchParams();\r\n this.calibrateSoundHz =\r\n // previous calibrateSoundHz\r\n urlParameters.hz !== null && urlParameters.hz !== undefined ? urlParameters.hz : 48000;\r\n this.calibrateSoundSamplingDesiredBits =\r\n // previous calibrateSoundSamplingDesiredBits\r\n urlParameters.bits !== null && urlParameters.bits !== undefined ? urlParameters.bits : 24;\r\n this.speakerPeerId = urlParameters.speakerPeerId;\r\n\r\n this.peer.on('open', this.onPeerOpen);\r\n this.peer.on('connection', this.onPeerConnection);\r\n this.peer.on('disconnected', this.onPeerDisconnected);\r\n this.peer.on('close', this.onPeerClose);\r\n this.peer.on('error', this.onPeerError);\r\n }\r\n\r\n onPeerOpen = id => {\r\n this.displayUpdate('Listener - onPeerOpen');\r\n // Workaround for peer.reconnect deleting previous id\r\n\r\n if (id === null) {\r\n this.displayUpdate('Received null id from peer open');\r\n this.peer.id = this.lastPeerId;\r\n } else {\r\n this.lastPeerId = this.peer.id;\r\n }\r\n\r\n this.join();\r\n };\r\n\r\n onPeerConnection = connection => {\r\n this.displayUpdate('Listener - onPeerConnection');\r\n // Disallow incoming connections\r\n connection.on('open', () => {\r\n connection.send('Sender does not accept incoming connections');\r\n setTimeout(() => {\r\n connection.close();\r\n }, 500);\r\n });\r\n };\r\n\r\n onConnData = data => {\r\n this.displayUpdate('Listener - onConnData');\r\n const hasSpeakerID = Object.prototype.hasOwnProperty.call(data, 'speakerPeerId');\r\n if (!hasSpeakerID) {\r\n this.displayUpdate('Error in parsing data received! Must set \"speakerPeerId\" property');\r\n throw new _peerErrors__WEBPACK_IMPORTED_MODULE_1__.MissingSpeakerIdError('Must set \"speakerPeerId\" property');\r\n } else {\r\n // this.conn.close();\r\n this.displayUpdate(this.speakerPeerId);\r\n this.speakerPeerId = data.speakerPeerId;\r\n const newParams = {\r\n speakerPeerId: this.speakerPeerId,\r\n };\r\n /*\r\n FUTURE does this limit usable environments?\r\n ie does this work if internet is lost after initial page load?\r\n */\r\n window.location.search = this.queryStringFromObject(newParams); // Redirect to correctly constructed keypad page\r\n }\r\n };\r\n\r\n join = async () => {\r\n this.displayUpdate('Listener - join');\r\n /**\r\n * Create the connection between the two Peers.\r\n *\r\n * Sets up callbacks that handle any events related to the\r\n * connection and data received on it.\r\n */\r\n // Close old connection\r\n if (this.conn) {\r\n this.displayUpdate('Closing old connection');\r\n this.conn.close();\r\n }\r\n\r\n // Create connection to destination peer specified by the query param\r\n this.displayUpdate(`Creating connection to: ${this.speakerPeerId}`);\r\n this.conn = this.peer.connect(this.speakerPeerId, {\r\n reliable: true,\r\n });\r\n\r\n this.displayUpdate('Created connection');\r\n this.conn.on('open', async () => {\r\n this.displayUpdate('Listener - conn open');\r\n await this.getDeviceInfo();\r\n // this.sendSamplingRate();\r\n await this.openAudioStream();\r\n });\r\n\r\n // Handle incoming data (messages only since this is the signal sender)\r\n this.conn.on('data', this.onConnData);\r\n this.conn.on('close', () => {\r\n console.log('Connection closed');\r\n });\r\n };\r\n\r\n getMobileOS = () => {\r\n const ua = navigator.userAgent;\r\n if (/android/i.test(ua)) {\r\n return 'Android';\r\n }\r\n if (\r\n /iPad|iPhone|iPod/.test(ua) ||\r\n ((navigator?.userAgentData?.platform || navigator?.platform) === 'MacIntel' &&\r\n navigator.maxTouchPoints > 1)\r\n ) {\r\n return 'iOS';\r\n }\r\n return 'Other';\r\n };\r\n\r\n sendSamplingRate = sampleRate => {\r\n this.displayUpdate('Listener - sendSamplingRate');\r\n this.conn.send({\r\n name: 'samplingRate',\r\n payload: sampleRate,\r\n });\r\n };\r\n\r\n sendSampleSize = sampleSize => {\r\n this.displayUpdate('Listener - sendSampleSize');\r\n this.conn.send({\r\n name: 'sampleSize',\r\n payload: sampleSize,\r\n });\r\n };\r\n\r\n sendFlags = flags => {\r\n this.displayUpdate('Listener - sendFlags');\r\n this.conn.send({\r\n name: 'flags',\r\n payload: flags,\r\n });\r\n };\r\n\r\n getDeviceInfo = async () => {\r\n try {\r\n const deviceInfo = {};\r\n fod.complete(function (data) {\r\n deviceInfo['IsMobile'] = data.device['ismobile'];\r\n deviceInfo['HardwareName'] = data.device['hardwarename'];\r\n deviceInfo['HardwareFamily'] = data.device['hardwarefamily'];\r\n deviceInfo['HardwareModel'] = data.device['hardwaremodel'];\r\n deviceInfo['OEM'] = data.device['oem'];\r\n deviceInfo['HardwareModelVariants'] = data.device['hardwaremodelvariants'];\r\n deviceInfo['DeviceId'] = data.device['deviceid'];\r\n deviceInfo['PlatformName'] = data.device['platformname'];\r\n deviceInfo['PlatformVersion'] = data.device['platformversion'];\r\n deviceInfo['DeviceType'] = data.device['devicetype'];\r\n // deviceInfo['deviceInfoFromUser'] = this.deviceInfoFromUser;\r\n });\r\n // deviceInfo['deviceInfoFromUser'] = this.deviceInfoFromUser;\r\n deviceInfo['microphoneFromAPI'] = this.microphoneFromAPI;\r\n deviceInfo['microphoneDeviceId'] = this.microphoneDeviceId;\r\n deviceInfo['screenWidth'] = window.screen.width;\r\n deviceInfo['screenHeight'] = window.screen.height;\r\n console.log('deviceInfo Inside getDeviceInfo: ', deviceInfo);\r\n this.conn.send({\r\n name: 'deviceInfo',\r\n payload: deviceInfo,\r\n });\r\n return deviceInfo;\r\n } catch (error) {\r\n console.error('Error fetching or executing script:', error.message);\r\n return null;\r\n }\r\n };\r\n\r\n applyHQTrackConstraints = async stream => {\r\n // Contraint the incoming audio to the sampling rate we want\r\n stream.getAudioTracks().forEach(track => {\r\n console.log(track, track.enabled);\r\n });\r\n const track = stream.getAudioTracks()[0];\r\n console.log(track);\r\n const capabilities = track.getCapabilities();\r\n\r\n this.displayUpdate(\r\n `Listener Track Capabilities - ${JSON.stringify(capabilities, undefined, 2)}`\r\n );\r\n\r\n const constraints = track.getConstraints();\r\n\r\n if (capabilities.echoCancellation) {\r\n constraints.echoCancellation = false;\r\n }\r\n\r\n if (capabilities.sampleRate) {\r\n constraints.sampleRate = this.calibrateSoundHz;\r\n }\r\n\r\n if (capabilities.sampleSize) {\r\n constraints.sampleSize = this.calibrateSoundSamplingDesiredBits;\r\n }\r\n\r\n if (capabilities.channelCount) {\r\n constraints.channelCount = 1;\r\n }\r\n\r\n this.displayUpdate(`Listener Track Constraints - ${JSON.stringify(constraints, undefined, 2)}`);\r\n\r\n // await the promise\r\n try {\r\n await track.applyConstraints(constraints);\r\n } catch (err) {\r\n console.error(err);\r\n this.displayUpdate(`Error applying constraints to track: ${err}`);\r\n }\r\n\r\n const settings = track.getSettings();\r\n this.displayUpdate(`Listener Track Settings - ${JSON.stringify(settings, undefined, 2)}`);\r\n return settings;\r\n };\r\n\r\n getMediaDevicesAudioContraints = async () => {\r\n const availableConstraints = navigator.mediaDevices.getSupportedConstraints();\r\n\r\n const contraints = {\r\n // ...(availableConstraints.echoCancellation && availableConstraints.echoCancellation == true\r\n // ? {echoCancellation: {exact: false}}\r\n // : {}),\r\n // ...(availableConstraints.sampleRate && availableConstraints.sampleRate == true\r\n // ? {sampleRate: {ideal: this.calibrateSoundHz}}\r\n // : {}),\r\n // ...(availableConstraints.sampleSize && availableConstraints.sampleSize == true\r\n // ? {sampleSize: {ideal: this.calibrateSoundSamplingDesiredBits}}\r\n // : {}),\r\n // ...(availableConstraints.channelCount && availableConstraints.channelCount == true\r\n // ? {channelCount: {exact: 1}}\r\n // : {}),\r\n echoCancellation: false,\r\n channelCount: 1,\r\n };\r\n\r\n if (this.microphoneDeviceId !== '') {\r\n contraints.deviceId = {exact: await this.getDeviceIdByLabel(this.microphoneDeviceId)};\r\n }\r\n\r\n console.log(contraints);\r\n\r\n return contraints;\r\n };\r\n getDeviceIdByLabel = async targetLabel => {\r\n try {\r\n //get permission to use audio first. (Returns empty labels on some computers if not done first)\r\n await navigator.mediaDevices.getUserMedia({audio: true});\r\n // Enumerate available media devices\r\n const devices = await navigator.mediaDevices.enumerateDevices();\r\n\r\n // Find the device with the matching label\r\n const matchingDevice = devices.find(\r\n device => device.kind === 'audioinput' && device.label === targetLabel\r\n );\r\n\r\n if (matchingDevice) {\r\n return matchingDevice.deviceId; // Return the deviceId if found\r\n } else {\r\n throw new Error(`No audio input device found with label: \"${targetLabel}\"`);\r\n }\r\n } catch (error) {\r\n console.error('Error finding device ID:', error);\r\n return null;\r\n }\r\n };\r\n\r\n openAudioStream = async () => {\r\n this.displayUpdate('Listener - openAudioStream');\r\n const mobileOS = this.getMobileOS();\r\n if (false) {}\r\n const constraints = await this.getMediaDevicesAudioContraints();\r\n console.log('Constraints right before getUserMedia:', constraints);\r\n navigator.mediaDevices\r\n .getUserMedia({\r\n audio: constraints,\r\n video: false,\r\n //audio: {echoCancellation: false, noiseSuppression: false, autoGainControl: false, deviceId: {exact: await this.getDeviceIdByLabel(this.microphoneDeviceId) }},\r\n })\r\n .then(stream => {\r\n this.displayUpdate(\r\n `Listener Track settings before applied constraints - ${JSON.stringify(\r\n stream.getAudioTracks()[0].getSettings(),\r\n undefined,\r\n 2\r\n )}`\r\n );\r\n this.applyHQTrackConstraints(stream)\r\n .then(settings => {\r\n console.log(settings);\r\n this.sendSamplingRate(settings.sampleRate);\r\n let sampleSize = settings.sampleSize;\r\n if (!sampleSize) {\r\n sampleSize = this.calibrateSoundSamplingDesiredBits;\r\n }\r\n this.sendSampleSize(sampleSize);\r\n this.sendFlags({\r\n autoGainControl: settings.autoGainControl,\r\n noiseSuppression: settings.noiseSuppression,\r\n echoCancellation: settings.echoCancellation,\r\n });\r\n this.peer.call(this.speakerPeerId, stream); // one-way call\r\n this.displayUpdate('Listener - openAudioStream');\r\n })\r\n .catch(err => {\r\n console.log(err);\r\n this.displayUpdate(\r\n `Listener - Error in applyHQTrackConstraints - ${JSON.stringify(err, undefined, 2)}`\r\n );\r\n });\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n if (err.name === 'OverconstrainedError') {\r\n const constraint = err.constraint;\r\n const message = `The constraint \"${constraint}\" cannot be satisfied by the selected microphone. Please adjust your calibration settings or choose a different microphone.`;\r\n\r\n this.displayUpdate(`Listener - OverconstrainedError: ${message}`);\r\n console.error(message);\r\n\r\n alert(`Overconstrained Error: ${message}`);\r\n }\r\n this.displayUpdate(\r\n `Listener - Error in getUserMedia - ${JSON.stringify(err, undefined, 2)}`\r\n );\r\n });\r\n };\r\n}\r\n\r\n/* harmony default export */ __webpack_exports__[\"default\"] = (Listener);\r\n\n\n//# sourceURL=webpack://speakerCalibrator/./src/peer-connection/listener.js?");
|
|
439
439
|
|
|
440
440
|
/***/ }),
|
|
441
441
|
|
|
@@ -446,7 +446,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _aud
|
|
|
446
446
|
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
447
447
|
|
|
448
448
|
"use strict";
|
|
449
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ CalibrationTimedOutError: function() { return /* binding */ CalibrationTimedOutError; },\n/* harmony export */ MissingSpeakerIdError: function() { return /* binding */ MissingSpeakerIdError; },\n/* harmony export */ UnsupportedDeviceError: function() { return /* binding */ UnsupportedDeviceError; }\n/* harmony export */ });\nclass UnsupportedDeviceError extends Error {\n constructor(message) {\n super(message);\n this.name = 'UnsupportedDeviceError';\n this.message = message;\n }\n}\n\nclass MissingSpeakerIdError extends Error {\n constructor(message) {\n super(message);\n this.name = 'missingSpeakerIdError';\n this.message = message;\n }\n}\n\nclass CalibrationTimedOutError extends Error {\n constructor(message) {\n super(message);\n this.name = 'calibrationTimedOutError';\n this.message = message;\n }\n}\n\n\n\n\n//# sourceURL=webpack://speakerCalibrator/./src/peer-connection/peerErrors.js?");
|
|
449
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ CalibrationTimedOutError: function() { return /* binding */ CalibrationTimedOutError; },\n/* harmony export */ MissingSpeakerIdError: function() { return /* binding */ MissingSpeakerIdError; },\n/* harmony export */ UnsupportedDeviceError: function() { return /* binding */ UnsupportedDeviceError; }\n/* harmony export */ });\nclass UnsupportedDeviceError extends Error {\r\n constructor(message) {\r\n super(message);\r\n this.name = 'UnsupportedDeviceError';\r\n this.message = message;\r\n }\r\n}\r\n\r\nclass MissingSpeakerIdError extends Error {\r\n constructor(message) {\r\n super(message);\r\n this.name = 'missingSpeakerIdError';\r\n this.message = message;\r\n }\r\n}\r\n\r\nclass CalibrationTimedOutError extends Error {\r\n constructor(message) {\r\n super(message);\r\n this.name = 'calibrationTimedOutError';\r\n this.message = message;\r\n }\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://speakerCalibrator/./src/peer-connection/peerErrors.js?");
|
|
450
450
|
|
|
451
451
|
/***/ }),
|
|
452
452
|
|
|
@@ -457,7 +457,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
457
457
|
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
458
458
|
|
|
459
459
|
"use strict";
|
|
460
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var qrcode__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! qrcode */ \"./node_modules/qrcode/lib/browser.js\");\n/* harmony import */ var _audioPeer__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./audioPeer */ \"./src/peer-connection/audioPeer.js\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../utils */ \"./src/utils.js\");\n/* harmony import */ var _peerErrors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./peerErrors */ \"./src/peer-connection/peerErrors.js\");\n\n\n\n\n\n//import {phrases} from '../../dist/example/i18n';\n\n/**\n * @class Handles the speaker's side of the connection. Responsible for initiating the connection,\n * rendering the QRCode, and answering the call.\n * @augments AudioPeer\n */\nclass Speaker extends _audioPeer__WEBPACK_IMPORTED_MODULE_1__[\"default\"] {\n /**\n * Takes the url of the current site and a target element where html elements will be appended.\n *\n * @param params - See type definition for initParameters.\n * @param Calibrator - An instance of the AudioCalibrator class, should not use AudioCalibrator directly, instead use an extended class available in /tasks/.\n * @param CalibratorInstance\n * @example\n */\n constructor(params, CalibratorInstance) {\n super(params);\n this.language = params?.language ?? 'en-US';\n this.siteUrl += '/listener?';\n this.ac = CalibratorInstance;\n this.result = null;\n this.debug = params?.debug ?? false;\n this.isSmartPhone = params?.isSmartPhone ?? false;\n this.calibrateSoundHz = params?.calibrateSoundHz ?? 48000;\n this.calibrateSoundSamplingDesiredBits = params?.calibrateSoundSamplingDesiredBits ?? 24;\n this.instructionDisplayId = params?.instructionDisplayId ?? '';\n this.soundSubtitleId = params?.soundSubtitleId ?? '';\n this.timeToCalibrateDisplay = params?.timeToCalibrateId ?? '';\n this.soundMessageId = params?.soundMessageId ?? '';\n this.titleDisplayId = params?.titleDisplayId ?? '';\n this.timeToCalibrate = params?.timeToCalibrate ?? 10;\n this.isParticipant = params?.isParticipant ?? false;\n this.isLoudspeakerCalibration = params?.isLoudspeakerCalibration ?? false;\n this.deviceId = params?.micrpohoneIdFromWebAudioApi ?? '';\n this.buttonsContainer = params?.buttonsContainer ?? document.createElement('div');\n this.phrases = params?. phrases ?? {};\n\n /* Set up callbacks that handle any events related to our peer object. */\n }\n\n uri = '';\n qrImage;\n shortURL;\n\n initPeer = async () => {\n const id = await this.generateTimeBasedPeerID();\n this.peer = new Peer(id, {\n secure: true,\n host: 'easyeyes-peer-server.herokuapp.com',\n port: 443,\n config: {\n iceServers: [\n {\n urls: 'stun:stun.relay.metered.ca:80',\n },\n {\n urls: 'turn:global.relay.metered.ca:80',\n username: 'de884cfc34189cdf1a5dd616',\n credential: 'IcOpouU9/TYBmpHU',\n },\n {\n urls: 'turn:global.relay.metered.ca:80?transport=tcp',\n username: 'de884cfc34189cdf1a5dd616',\n credential: 'IcOpouU9/TYBmpHU',\n },\n {\n urls: 'turn:global.relay.metered.ca:443',\n username: 'de884cfc34189cdf1a5dd616',\n credential: 'IcOpouU9/TYBmpHU',\n },\n {\n urls: 'turns:global.relay.metered.ca:443?transport=tcp',\n username: 'de884cfc34189cdf1a5dd616',\n credential: 'IcOpouU9/TYBmpHU',\n },\n ],\n },\n });\n this.peer.on('open', this.#onPeerOpen);\n this.peer.on('connection', this.#onPeerConnection);\n this.peer.on('close', this.onPeerClose);\n this.peer.on('disconnected', this.#onPeerDisconnected);\n this.peer.on('error', this.#onPeerError);\n };\n generateTimeBasedPeerID = async () => {\n const now = new Date().getTime();\n const randomBuffer = new Uint8Array(10);\n crypto.getRandomValues(randomBuffer);\n const randomPart = Array.from(randomBuffer)\n .map(b => b.toString(36))\n .join('');\n const toHash = `${now}-${randomPart}`;\n const encoder = new TextEncoder();\n const data = encoder.encode(toHash);\n const hash = await crypto.subtle.digest('SHA-256', data);\n const hashArray = Array.from(new Uint8Array(hash)); // Convert buffer to byte array\n const hashString = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');\n const shortHash = hashString.substring(0, 12); // Use more of the hash for a longer ID\n // return shortHash; // Consider converting this to Base62\n return this.encodeBase62(parseInt(shortHash, 16));\n };\n\n encodeBase62 = num => {\n const base = 36;\n const characters = '0123456789abcdefghijklmnopqrstuvwxyz';\n let result = '';\n while (num > 0) {\n result = characters[num % base] + result;\n num = Math.floor(num / base);\n }\n return result;\n };\n\n /**\n * Async factory method that creates the Speaker object, and returns a promise that resolves to the result of the calibration.\n *\n * @param params - The parameters to be passed to the peer object.\n * @param Calibrator - The class that defines the calibration process.\n * @param CalibratorInstance\n * @param timeOut - The amount of time to wait before timing out the connection (in milliseconds).\n * @public\n * @example\n */\n static startCalibration = async (params, CalibratorInstance, timeOut = 180000) => {\n window.speaker = new Speaker(params, CalibratorInstance);\n const {speaker} = window;\n await speaker.initPeer();\n // wrap the calibration process in a promise so we can await it\n return new Promise((resolve, reject) => {\n // when a call is received\n speaker.peer.on('call', async call => {\n // Answer the call (one way)\n\n call.answer();\n speaker.#removeUIElems();\n speaker.#showSpinner();\n speaker.ac.createLocalAudio(document.getElementById(speaker.targetElement));\n // when we start receiving audio\n call.on('stream', async stream => {\n window.localStream = stream;\n window.localAudio.srcObject = stream;\n window.localAudio.autoplay = false;\n\n // if the sinkSamplingRate is not set sleep\n while (!speaker.ac.sampleRatesSet()) {\n console.log('SinkSamplingRate is undefined, sleeping');\n await (0,_utils__WEBPACK_IMPORTED_MODULE_2__.sleep)(1);\n }\n\n if (params.displayUpdate) {\n params.displayUpdate.style.display = '';\n }\n\n // resolve when we have a result\n speaker.result = await speaker.ac.startCalibration(\n stream,\n params.gainValues,\n params.ICalib,\n params.knownIR,\n params.microphoneName,\n params.calibrateSoundCheck,\n params.isSmartPhone,\n params.calibrateSoundBurstDb,\n params.calibrateSoundBurstFilteredExtraDb,\n params.calibrateSoundBurstLevelReTBool,\n params.calibrateSoundBurstUses1000HzGainBool,\n params.calibrateSoundBurstRepeats,\n params.calibrateSoundBurstSec,\n params._calibrateSoundBurstPreSec,\n params._calibrateSoundBurstPostSec,\n params.calibrateSoundHz,\n params.calibrateSoundIRSec,\n params.calibrateSoundIIRSec,\n params.calibrateSoundIIRPhase,\n params.calibrateSound1000HzPreSec,\n params.calibrateSound1000HzSec,\n params.calibrateSound1000HzPostSec,\n params.calibrateSoundBackgroundSecs,\n params.calibrateSoundSmoothOctaves,\n params.calibrateSoundSmoothMinBandwidthHz,\n params.calibrateSoundPowerBinDesiredSec,\n params.calibrateSoundPowerDbSDToleratedDb,\n params.calibrateSoundTaperSec,\n params.micManufacturer,\n params.micSerialNumber,\n params.micModelNumber,\n params.micModelName,\n params.calibrateMicrophonesBool,\n params.authorEmails,\n params.webAudioDeviceNames,\n params.IDsToSaveInSoundProfileLibrary,\n params.restartButton,\n params.reminder,\n params.calibrateSoundLimit,\n params.calibrateSoundBurstNormalizeBy1000HzGainBool,\n params.calibrateSoundBurstScalarDB,\n params.calibrateSound1000HzMaxSD_dB,\n params._calibrateSoundBurstMaxSD_dB,\n params.calibrateSoundSamplingDesiredBits,\n params.language,\n params.loudspeakerModelName,\n params.phrases,\n );\n speaker.#removeUIElems();\n resolve(speaker.result);\n });\n // if we do not receive a result within the timeout, reject\n setTimeout(() => {\n reject(\n new _peerErrors__WEBPACK_IMPORTED_MODULE_3__.CalibrationTimedOutError(\n `Calibration failed to produce a result after ${\n timeOut / 1000\n } seconds. Please try again.`\n )\n );\n }, timeOut);\n });\n });\n };\n\n static testIIR = async (params, CalibratorInstance, IIR, timeOut = 180000) => {\n window.speaker = new Speaker(params, CalibratorInstance);\n const {speaker} = window;\n speaker.initPeer();\n // wrap the calibration process in a promise so we can await it\n return new Promise((resolve, reject) => {\n // when a call is received\n speaker.peer.on('call', async call => {\n // Answer the call (one way)\n call.answer();\n speaker.#removeUIElems();\n speaker.#showSpinner();\n speaker.ac.createLocalAudio(document.getElementById(speaker.targetElement));\n // when we start receiving audio\n call.on('stream', async stream => {\n window.localStream = stream;\n window.localAudio.srcObject = stream;\n window.localAudio.autoplay = false;\n\n // if the sinkSamplingRate is not set sleep\n while (!speaker.ac.sampleRatesSet()) {\n console.log('SinkSamplingRate is undefined, sleeping');\n await (0,_utils__WEBPACK_IMPORTED_MODULE_2__.sleep)(1);\n }\n // resolve when we have a result\n speaker.result = await speaker.ac.playMLSwithIIR(stream, IIR);\n speaker.#removeUIElems();\n resolve(speaker.result);\n });\n // if we do not receive a result within the timeout, reject\n setTimeout(() => {\n reject(\n new _peerErrors__WEBPACK_IMPORTED_MODULE_3__.CalibrationTimedOutError(\n `Calibration failed to produce a result after ${\n timeOut / 1000\n } seconds. Please try again.`\n )\n );\n }, timeOut);\n });\n });\n };\n\n /**\n * Called after the peer conncection has been opened.\n * Generates a QR code for the connection and displays it.\n *\n * @private\n * @example\n */\n\n #showQRCode = async () => {\n // Get query string, the URL parameters to specify a Listener\n const queryStringParameters = {\n speakerPeerId: this.peer.id,\n sp: this.isSmartPhone,\n hz: this.calibrateSoundHz,\n bits: this.calibrateSoundSamplingDesiredBits,\n lang: this.language,\n deviceId: this.deviceId\n };\n const queryString = this.queryStringFromObject(queryStringParameters);\n this.uri = this.siteUrl + queryString;\n if (this.isSmartPhone) {\n // if (true) { // test smartphone QR\n // Display QR code for the participant to scan\n const qrCanvas = document.createElement('canvas');\n qrCanvas.setAttribute('id', 'qrCanvas');\n qrcode__WEBPACK_IMPORTED_MODULE_0__.toCanvas(qrCanvas, this.uri, error => {\n if (error) console.error(error);\n });\n const explanation = document.createElement('h2');\n explanation.id = 'skipQRExplanation';\n explanation.style = `\n user-select: text;\n margin-top: 9px;\n font-size: 1.1rem;\n `;\n // Define the URL and options for the request\n const url = 'https://api.short.io/links/public';\n const options = {\n method: 'POST',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n Authorization: 'pk_fysLKGj3legZz4XZ',\n },\n body: JSON.stringify({\n domain: 'listeners.link', // Ensure this domain is valid for your account\n originalURL: this.uri,\n }),\n };\n\n // Make the request using fetch\n await fetch(url, options)\n .then(response => {\n if (!response.ok) {\n throw new Error(`HTTP error! Status: ${response.status}`);\n }\n return response.json(); // Parse the JSON response\n })\n .then(data => {\n explanation.innerHTML = (0,_utils__WEBPACK_IMPORTED_MODULE_2__.formatLineBreak)(\n this.phrases.RC_skipQR_ExplanationWithoutPreferNot[this.language]\n .replace('xxx', `<b style=\"user-select: text\">${data.shortURL}</b>`)\n .replace('XXX', `<b style=\"user-select: text\">${data.shortURL}</b>`),\n this.phrases.RC_checkInternetConnection[this.language]\n );\n const checkConnection = document.createElement('a');\n checkConnection.id = 'check-connection';\n checkConnection.href = '#';\n checkConnection.innerHTML = \"check the phone's internet connection\";\n const lang = this.language;\n checkConnection.addEventListener('click', function (event) {\n console.log('clicked');\n event.preventDefault(); // Prevent the default link action\n (0,_utils__WEBPACK_IMPORTED_MODULE_2__.createAndShowPopup)(lang, this.phrases);\n });\n explanation.querySelector('a#check-connection').replaceWith(checkConnection);\n })\n .catch(error => {\n console.error('Error:', error.message); // Handle errors\n });\n\n const qrImage = new Image(400, 400);\n qrImage.setAttribute('id', 'compatibilityCheckQRImage');\n qrImage.style.zIndex = Infinity;\n qrImage.style.width = 400;\n qrImage.style.height = 400;\n qrImage.style.aspectRatio = 1;\n qrImage.src = qrCanvas.toDataURL();\n qrImage.style.maxHeight = '150px';\n qrImage.style.maxWidth = '150px';\n\n this.qrImage = qrImage;\n\n const container = document.createElement('div');\n container.style.display = 'flex';\n container.style.justifyContent = 'space-between';\n container.style.alignItems = 'top';\n container.id = 'skipQRContainer';\n container.appendChild(qrImage);\n container.appendChild(explanation);\n container.appendChild(this.buttonsContainer);\n const qrContainer = document.createElement('div');\n qrContainer.appendChild(container);\n\n document.getElementById(this.targetElement).appendChild(qrContainer);\n } else {\n // show the link to the user\n // If specified HTML Id is available, show QR code there\n if (document.getElementById(this.targetElement)) {\n // const linkTag = document.createElement('a');\n // linkTag.setAttribute('href', uri);\n // linkTag.innerHTML = 'Click here to start the calibration';\n // linkTag.target = '_blank';\n // document.getElementById(this.targetElement).appendChild(linkTag);\n // document.getElementById(this.targetElement).appendChild(qrCanvas);\n\n const proceedButton = document.createElement('button');\n proceedButton.setAttribute('id', 'calibrationProceedButton');\n proceedButton.setAttribute('class', 'btn btn-success');\n proceedButton.innerHTML = this.phrases.T_proceed[this.language];\n proceedButton.onclick = () => {\n // open the link in a new tab\n window.open(this.uri, '_blank');\n // remove the button\n document.getElementById('calibrationProceedButton').remove();\n };\n document.getElementById(this.targetElement).appendChild(proceedButton);\n }\n }\n // or just print it to console\n console.log('TEST: Peer reachable at: ', this.uri);\n };\n\n #showSpinner = () => {\n const spinner = document.createElement('div');\n spinner.className = 'spinner-border ml-auto';\n spinner.role = 'status';\n spinner.ariaHidden = 'true';\n spinner.style.marginTop = '0.8rem';\n document.getElementById(this.targetElement).appendChild(spinner);\n\n // clear instructionDisplay\n const soundMessage = document.getElementById(this.soundMessageId);\n soundMessage.innerHTML = '';\n soundMessage.style.display = 'none';\n const instructionDisplay = document.getElementById(this.instructionDisplayId);\n const background = document.getElementById('background'); // todo: get background id from params\n const subtitle = document.getElementById(this.soundSubtitleId);\n if (subtitle) {\n subtitle.innerHTML = '';\n }\n if (instructionDisplay) {\n instructionDisplay.innerHTML = '';\n instructionDisplay.style.whiteSpace = 'nowrap';\n instructionDisplay.style.fontWeight = 'bold';\n instructionDisplay.style.width = 'fit-content';\n instructionDisplay.innerHTML = this.phrases.RC_soundRecording[this.language];\n let fontSize = 100;\n instructionDisplay.style.fontSize = fontSize + 'px';\n while (instructionDisplay.scrollWidth > background.scrollWidth * 0.9 && fontSize > 10) {\n fontSize--;\n instructionDisplay.style.fontSize = fontSize + 'px';\n }\n // const p = document.createElement('p');\n // // font size\n // p.style.fontSize = '1.1rem';\n // p.style.fontWeight = 'normal';\n // p.style.paddingTop = '20px';\n // const timeToCalibrateText = phrases.RC_howLongToCalibrate['en-US'];\n // p.innerHTML = timeToCalibrateText.replace('111', this.timeToCalibrate);\n // instructionDisplay.appendChild(p);\n }\n\n const timeToCalibrateDisplay = document.getElementById(this.timeToCalibrateDisplay);\n if (timeToCalibrateDisplay) {\n const timeToCalibrateText = this.phrases.RC_howLongToCalibrate[this.language];\n timeToCalibrateDisplay.innerHTML = timeToCalibrateText.replace('111', this.timeToCalibrate);\n timeToCalibrateDisplay.style.fontWeight = 'normal';\n timeToCalibrateDisplay.style.fontSize = '1rem';\n // timeToCalibrateDisplay.style.paddingTop = '20px';\n }\n\n // Update title - titleDisplayId\n const titleDisplay = document.getElementById(this.titleDisplayId);\n if (titleDisplay) {\n // if (this.isParticipant) {\n // titleDisplay.innerHTML = titleDisplay.innerHTML.replace('3', '4');\n // } else if (this.isSmartPhone) {\n // if (this.isLoudspeakerCalibration) {\n // titleDisplay.innerHTML = titleDisplay.innerHTML.replace('6', '7');\n // } else {\n // titleDisplay.innerHTML = titleDisplay.innerHTML.replace('5', '6');\n // }\n // } else {\n // titleDisplay.innerHTML = titleDisplay.innerHTML.replace('5', '6');\n // }\n if (this.isLoudspeakerCalibration) {\n if (this.isParticipant) {\n titleDisplay.innerHTML = titleDisplay.innerHTML.replace('3', '4');\n } else if (this.isSmartPhone) {\n titleDisplay.innerHTML = titleDisplay.innerHTML.replace('6', '7');\n } else {\n titleDisplay.innerHTML = titleDisplay.innerHTML.replace('4', '5');\n }\n } else {\n if (this.isSmartPhone) {\n titleDisplay.innerHTML = titleDisplay.innerHTML.replace('5', '6');\n } else {\n titleDisplay.innerHTML = titleDisplay.innerHTML.replace('3', '4');\n }\n }\n }\n };\n\n #removeUIElems = () => {\n const parent = document.getElementById(this.targetElement);\n while (parent.firstChild) {\n parent.firstChild.remove();\n }\n };\n\n /**\n * Called when the peer connection is opened.\n * Saves the peer id and calls the QR code generator.\n *\n * @param peerId - The peer id of the peer connection.\n * @param id\n * @private\n * @example\n */\n #onPeerOpen = id => {\n // Workaround for peer.reconnect deleting previous id\n if (id === null) {\n console.error('Received null id from peer open');\n this.peer.id = this.lastPeerId;\n } else {\n this.lastPeerId = this.peer.id;\n }\n\n if (id !== this.peer.id) {\n console.warn('DEBUG Check you assumption that id === this.peer.id');\n }\n\n this.#showQRCode();\n };\n\n /**\n * Called when the peer connection is established.\n * Enforces a single connection.\n *\n * @param connection - The connection object.\n * @private\n * @example\n */\n #onPeerConnection = connection => {\n // Allow only a single connection\n if (this.conn && this.conn.open) {\n connection.on('open', () => {\n connection.send('Already connected to another client');\n setTimeout(() => {\n connection.close();\n }, 500);\n });\n return;\n }\n\n this.conn = connection;\n console.log('Connected to: ', this.conn.peer);\n this.#ready();\n };\n\n /**\n * Called when the peer connection is closed.\n *\n * @private\n * @example\n */\n onPeerClose = () => {\n this.conn = null;\n console.log('Connection destroyed');\n };\n\n static closeConnection = () => {\n this.conn = null;\n console.log('Connection destroyed');\n };\n\n /**\n * Called when the peer connection is disconnected.\n * Attempts to reconnect.\n *\n * @private\n * @example\n */\n #onPeerDisconnected = () => {\n console.log('Connection lost. Please reconnect');\n\n // Workaround for peer.reconnect deleting previous id\n this.peer.id = this.lastPeerId;\n // eslint-disable-next-line no-underscore-dangle\n this.peer._lastServerId = this.lastPeerId;\n this.peer.reconnect();\n };\n\n /**\n * Called when the peer connection encounters an error.\n *\n * @param error\n * @private\n * @example\n */\n #onPeerError = error => {\n // TODO: check if this function is needed or not\n console.error(error);\n };\n\n /**\n * Called when data is received from the peer connection.\n *\n * @param data\n * @private\n * @example\n */\n #onIncomingData = data => {\n // enforce object type\n if (\n !Object.prototype.hasOwnProperty.call(data, 'name') ||\n !Object.prototype.hasOwnProperty.call(data, 'payload')\n ) {\n console.error('Received malformed data: ', data);\n return;\n }\n\n switch (data.name) {\n case 'samplingRate':\n this.ac.setSamplingRates(data.payload);\n break;\n case 'sampleSize':\n this.ac.setSampleSize(data.payload);\n break;\n case 'deviceType':\n this.ac.setDeviceType(data.payload);\n break;\n case 'deviceName':\n this.ac.setDeviceName(data.payload);\n break;\n case 'flags':\n //this.ac.setDeviceName(data.payload);\n console.log('FLAGS');\n console.log(data.payload);\n this.ac.setFlags(data.payload);\n break;\n case 'deviceInfo':\n this.ac.setDeviceInfo(data.payload);\n console.log('Received device info from listener: ', data.payload);\n break;\n case _peerErrors__WEBPACK_IMPORTED_MODULE_3__.UnsupportedDeviceError.name:\n case _peerErrors__WEBPACK_IMPORTED_MODULE_3__.MissingSpeakerIdError.name:\n throw data.payload;\n break;\n default:\n break;\n }\n };\n\n /**\n * Called when the peer connection is #ready.\n *\n * @private\n * @example\n */\n #ready = () => {\n // Perform callback with data\n this.conn.on('data', this.#onIncomingData);\n this.conn.on('close', () => {\n console.log('Connection reset<br>Awaiting connection...');\n this.conn = null;\n });\n };\n\n /** .\n * .\n * .\n * Debug method for downloading the recorded audio\n *\n * @public\n * @example\n */\n downloadData = () => {\n this.ac.downloadData();\n };\n\n repeatCalibration = async (params, stream, CalibratorInstance) => {\n this.ac = CalibratorInstance;\n this.#removeUIElems();\n this.#showSpinner();\n\n console.log('This is a repeat');\n // wrap the calibration process in a promise so we can await it\n return new Promise(async (resolve, reject) => {\n const result = await this.ac.startCalibration(\n stream,\n params.gainValues,\n params.ICalib,\n params.knownIR,\n params.microphoneName,\n params.calibrateSoundCheck,\n params.isSmartPhone,\n params.calibrateSoundBurstDb,\n params.calibrateSoundBurstFilteredExtraDb,\n params.calibrateSoundBurstLevelReTBool,\n params.calibrateSoundBurstUses1000HzGainBool,\n params.calibrateSoundBurstRepeats,\n params.calibrateSoundBurstSec,\n params._calibrateSoundBurstPreSec,\n params._calibrateSoundBurstPostSec,\n params.calibrateSoundHz,\n params.calibrateSoundIRSec,\n params.calibrateSoundIIRSec,\n params.calibrateSoundIIRPhase,\n params.calibrateSound1000HzPreSec,\n params.calibrateSound1000HzSec,\n params.calibrateSound1000HzPostSec,\n params.calibrateSoundBackgroundSecs,\n params.calibrateSoundSmoothOctaves,\n params.calibrateSoundSmoothMinBandwidthHz,\n params.calibrateSoundPowerBinDesiredSec,\n params.calibrateSoundPowerDbSDToleratedDb,\n params.calibrateSoundTaperSec,\n params.micManufacturer,\n params.micSerialNumber,\n params.micModelNumber,\n params.micModelName,\n params.calibrateMicrophonesBool,\n params.authorEmails,\n params.webAudioDeviceNames,\n params.IDsToSaveInSoundProfileLibrary,\n params.restartButton,\n params.reminder,\n params.calibrateSoundLimit,\n params.calibrateSoundBurstNormalizeBy1000HzGainBool,\n params.calibrateSoundBurstScalarDB,\n params.calibrateSound1000HzMaxSD_dB,\n params._calibrateSoundBurstMaxSD_dB,\n params.calibrateSoundSamplingDesiredBits,\n params.language,\n params.loudspeakerModelName,\n params.phrases,\n );\n this.#removeUIElems();\n resolve(result);\n });\n };\n}\n\n/* \nReferenced links:\nhttps://stackoverflow.com/questions/28016664/when-you-pass-this-as-an-argument/28016676#28016676\nhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes\nhttps://stackoverflow.com/questions/879152/how-do-i-make-javascript-beep [3]\n*/\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (Speaker);\n\n\n//# sourceURL=webpack://speakerCalibrator/./src/peer-connection/speaker.js?");
|
|
460
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var qrcode__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! qrcode */ \"./node_modules/qrcode/lib/browser.js\");\n/* harmony import */ var _audioPeer__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./audioPeer */ \"./src/peer-connection/audioPeer.js\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../utils */ \"./src/utils.js\");\n/* harmony import */ var _peerErrors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./peerErrors */ \"./src/peer-connection/peerErrors.js\");\n\r\n\r\n\r\n\r\n\r\n//import {phrases} from '../../dist/example/i18n';\r\n\r\n/**\r\n * @class Handles the speaker's side of the connection. Responsible for initiating the connection,\r\n * rendering the QRCode, and answering the call.\r\n * @augments AudioPeer\r\n */\r\nclass Speaker extends _audioPeer__WEBPACK_IMPORTED_MODULE_1__[\"default\"] {\r\n /**\r\n * Takes the url of the current site and a target element where html elements will be appended.\r\n *\r\n * @param params - See type definition for initParameters.\r\n * @param Calibrator - An instance of the AudioCalibrator class, should not use AudioCalibrator directly, instead use an extended class available in /tasks/.\r\n * @param CalibratorInstance\r\n * @example\r\n */\r\n constructor(params, CalibratorInstance) {\r\n super(params);\r\n this.language = params?.language ?? 'en-US';\r\n this.siteUrl += '/listener?';\r\n this.ac = CalibratorInstance;\r\n this.result = null;\r\n this.debug = params?.debug ?? false;\r\n this.isSmartPhone = params?.isSmartPhone ?? false;\r\n this.calibrateSoundHz = params?.calibrateSoundHz ?? 48000;\r\n this.calibrateSoundSamplingDesiredBits = params?.calibrateSoundSamplingDesiredBits ?? 24;\r\n this.instructionDisplayId = params?.instructionDisplayId ?? '';\r\n this.soundSubtitleId = params?.soundSubtitleId ?? '';\r\n this.timeToCalibrateDisplay = params?.timeToCalibrateId ?? '';\r\n this.soundMessageId = params?.soundMessageId ?? '';\r\n this.titleDisplayId = params?.titleDisplayId ?? '';\r\n this.timeToCalibrate = params?.timeToCalibrate ?? 10;\r\n this.isParticipant = params?.isParticipant ?? false;\r\n this.isLoudspeakerCalibration = params?.isLoudspeakerCalibration ?? false;\r\n this.deviceId = params?.micrpohoneIdFromWebAudioApi ?? '';\r\n this.buttonsContainer = params?.buttonsContainer ?? document.createElement('div');\r\n this.phrases = params?. phrases ?? {};\r\n\r\n /* Set up callbacks that handle any events related to our peer object. */\r\n }\r\n\r\n uri = '';\r\n qrImage;\r\n shortURL;\r\n\r\n initPeer = async () => {\r\n const id = await this.generateTimeBasedPeerID();\r\n this.peer = new Peer(id, {\r\n secure: true,\r\n host: 'easyeyes-peer-server.herokuapp.com',\r\n port: 443,\r\n config: {\r\n iceServers: [\r\n {\r\n urls: 'stun:stun.relay.metered.ca:80',\r\n },\r\n {\r\n urls: 'turn:global.relay.metered.ca:80',\r\n username: 'de884cfc34189cdf1a5dd616',\r\n credential: 'IcOpouU9/TYBmpHU',\r\n },\r\n {\r\n urls: 'turn:global.relay.metered.ca:80?transport=tcp',\r\n username: 'de884cfc34189cdf1a5dd616',\r\n credential: 'IcOpouU9/TYBmpHU',\r\n },\r\n {\r\n urls: 'turn:global.relay.metered.ca:443',\r\n username: 'de884cfc34189cdf1a5dd616',\r\n credential: 'IcOpouU9/TYBmpHU',\r\n },\r\n {\r\n urls: 'turns:global.relay.metered.ca:443?transport=tcp',\r\n username: 'de884cfc34189cdf1a5dd616',\r\n credential: 'IcOpouU9/TYBmpHU',\r\n },\r\n ],\r\n },\r\n });\r\n this.peer.on('open', this.#onPeerOpen);\r\n this.peer.on('connection', this.#onPeerConnection);\r\n this.peer.on('close', this.onPeerClose);\r\n this.peer.on('disconnected', this.#onPeerDisconnected);\r\n this.peer.on('error', this.#onPeerError);\r\n };\r\n generateTimeBasedPeerID = async () => {\r\n const now = new Date().getTime();\r\n const randomBuffer = new Uint8Array(10);\r\n crypto.getRandomValues(randomBuffer);\r\n const randomPart = Array.from(randomBuffer)\r\n .map(b => b.toString(36))\r\n .join('');\r\n const toHash = `${now}-${randomPart}`;\r\n const encoder = new TextEncoder();\r\n const data = encoder.encode(toHash);\r\n const hash = await crypto.subtle.digest('SHA-256', data);\r\n const hashArray = Array.from(new Uint8Array(hash)); // Convert buffer to byte array\r\n const hashString = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');\r\n const shortHash = hashString.substring(0, 12); // Use more of the hash for a longer ID\r\n // return shortHash; // Consider converting this to Base62\r\n return this.encodeBase62(parseInt(shortHash, 16));\r\n };\r\n\r\n encodeBase62 = num => {\r\n const base = 36;\r\n const characters = '0123456789abcdefghijklmnopqrstuvwxyz';\r\n let result = '';\r\n while (num > 0) {\r\n result = characters[num % base] + result;\r\n num = Math.floor(num / base);\r\n }\r\n return result;\r\n };\r\n\r\n /**\r\n * Async factory method that creates the Speaker object, and returns a promise that resolves to the result of the calibration.\r\n *\r\n * @param params - The parameters to be passed to the peer object.\r\n * @param Calibrator - The class that defines the calibration process.\r\n * @param CalibratorInstance\r\n * @param timeOut - The amount of time to wait before timing out the connection (in milliseconds).\r\n * @public\r\n * @example\r\n */\r\n static startCalibration = async (params, CalibratorInstance, timeOut = 180000) => {\r\n window.speaker = new Speaker(params, CalibratorInstance);\r\n const {speaker} = window;\r\n await speaker.initPeer();\r\n // wrap the calibration process in a promise so we can await it\r\n return new Promise((resolve, reject) => {\r\n // when a call is received\r\n speaker.peer.on('call', async call => {\r\n // Answer the call (one way)\r\n\r\n call.answer();\r\n speaker.#removeUIElems();\r\n speaker.#showSpinner();\r\n speaker.ac.createLocalAudio(document.getElementById(speaker.targetElement));\r\n // when we start receiving audio\r\n call.on('stream', async stream => {\r\n window.localStream = stream;\r\n window.localAudio.srcObject = stream;\r\n window.localAudio.autoplay = false;\r\n\r\n // if the sinkSamplingRate is not set sleep\r\n while (!speaker.ac.sampleRatesSet()) {\r\n console.log('SinkSamplingRate is undefined, sleeping');\r\n await (0,_utils__WEBPACK_IMPORTED_MODULE_2__.sleep)(1);\r\n }\r\n\r\n if (params.displayUpdate) {\r\n params.displayUpdate.style.display = '';\r\n }\r\n\r\n // resolve when we have a result\r\n speaker.result = await speaker.ac.startCalibration(\r\n stream,\r\n params.gainValues,\r\n params.ICalib,\r\n params.knownIR,\r\n params.microphoneName,\r\n params.calibrateSoundCheck,\r\n params.isSmartPhone,\r\n params.calibrateSoundBurstDb,\r\n params.calibrateSoundBurstFilteredExtraDb,\r\n params.calibrateSoundBurstLevelReTBool,\r\n params.calibrateSoundBurstUses1000HzGainBool,\r\n params.calibrateSoundBurstRepeats,\r\n params.calibrateSoundBurstSec,\r\n params._calibrateSoundBurstPreSec,\r\n params._calibrateSoundBurstPostSec,\r\n params.calibrateSoundHz,\r\n params.calibrateSoundIRSec,\r\n params.calibrateSoundIIRSec,\r\n params.calibrateSoundIIRPhase,\r\n params.calibrateSound1000HzPreSec,\r\n params.calibrateSound1000HzSec,\r\n params.calibrateSound1000HzPostSec,\r\n params.calibrateSoundBackgroundSecs,\r\n params.calibrateSoundSmoothOctaves,\r\n params.calibrateSoundSmoothMinBandwidthHz,\r\n params.calibrateSoundPowerBinDesiredSec,\r\n params.calibrateSoundPowerDbSDToleratedDb,\r\n params.calibrateSoundTaperSec,\r\n params.micManufacturer,\r\n params.micSerialNumber,\r\n params.micModelNumber,\r\n params.micModelName,\r\n params.calibrateMicrophonesBool,\r\n params.authorEmails,\r\n params.webAudioDeviceNames,\r\n params.IDsToSaveInSoundProfileLibrary,\r\n params.restartButton,\r\n params.reminder,\r\n params.calibrateSoundLimit,\r\n params.calibrateSoundBurstNormalizeBy1000HzGainBool,\r\n params.calibrateSoundBurstScalarDB,\r\n params.calibrateSound1000HzMaxSD_dB,\r\n params._calibrateSoundBurstMaxSD_dB,\r\n params.calibrateSoundSamplingDesiredBits,\r\n params.language,\r\n params.loudspeakerModelName,\r\n params.phrases,\r\n );\r\n speaker.#removeUIElems();\r\n resolve(speaker.result);\r\n });\r\n // if we do not receive a result within the timeout, reject\r\n setTimeout(() => {\r\n reject(\r\n new _peerErrors__WEBPACK_IMPORTED_MODULE_3__.CalibrationTimedOutError(\r\n `Calibration failed to produce a result after ${\r\n timeOut / 1000\r\n } seconds. Please try again.`\r\n )\r\n );\r\n }, timeOut);\r\n });\r\n });\r\n };\r\n\r\n static testIIR = async (params, CalibratorInstance, IIR, timeOut = 180000) => {\r\n window.speaker = new Speaker(params, CalibratorInstance);\r\n const {speaker} = window;\r\n speaker.initPeer();\r\n // wrap the calibration process in a promise so we can await it\r\n return new Promise((resolve, reject) => {\r\n // when a call is received\r\n speaker.peer.on('call', async call => {\r\n // Answer the call (one way)\r\n call.answer();\r\n speaker.#removeUIElems();\r\n speaker.#showSpinner();\r\n speaker.ac.createLocalAudio(document.getElementById(speaker.targetElement));\r\n // when we start receiving audio\r\n call.on('stream', async stream => {\r\n window.localStream = stream;\r\n window.localAudio.srcObject = stream;\r\n window.localAudio.autoplay = false;\r\n\r\n // if the sinkSamplingRate is not set sleep\r\n while (!speaker.ac.sampleRatesSet()) {\r\n console.log('SinkSamplingRate is undefined, sleeping');\r\n await (0,_utils__WEBPACK_IMPORTED_MODULE_2__.sleep)(1);\r\n }\r\n // resolve when we have a result\r\n speaker.result = await speaker.ac.playMLSwithIIR(stream, IIR);\r\n speaker.#removeUIElems();\r\n resolve(speaker.result);\r\n });\r\n // if we do not receive a result within the timeout, reject\r\n setTimeout(() => {\r\n reject(\r\n new _peerErrors__WEBPACK_IMPORTED_MODULE_3__.CalibrationTimedOutError(\r\n `Calibration failed to produce a result after ${\r\n timeOut / 1000\r\n } seconds. Please try again.`\r\n )\r\n );\r\n }, timeOut);\r\n });\r\n });\r\n };\r\n\r\n /**\r\n * Called after the peer conncection has been opened.\r\n * Generates a QR code for the connection and displays it.\r\n *\r\n * @private\r\n * @example\r\n */\r\n\r\n #showQRCode = async () => {\r\n // Get query string, the URL parameters to specify a Listener\r\n const queryStringParameters = {\r\n speakerPeerId: this.peer.id,\r\n sp: this.isSmartPhone,\r\n hz: this.calibrateSoundHz,\r\n bits: this.calibrateSoundSamplingDesiredBits,\r\n lang: this.language,\r\n deviceId: this.deviceId\r\n };\r\n const queryString = this.queryStringFromObject(queryStringParameters);\r\n this.uri = this.siteUrl + queryString;\r\n if (this.isSmartPhone) {\r\n // if (true) { // test smartphone QR\r\n // Display QR code for the participant to scan\r\n const qrCanvas = document.createElement('canvas');\r\n qrCanvas.setAttribute('id', 'qrCanvas');\r\n qrcode__WEBPACK_IMPORTED_MODULE_0__.toCanvas(qrCanvas, this.uri, error => {\r\n if (error) console.error(error);\r\n });\r\n const explanation = document.createElement('h2');\r\n explanation.id = 'skipQRExplanation';\r\n explanation.style = `\r\n user-select: text;\r\n margin-top: 9px;\r\n font-size: 1.1rem;\r\n `;\r\n // Define the URL and options for the request\r\n const url = 'https://api.short.io/links/public';\r\n const options = {\r\n method: 'POST',\r\n headers: {\r\n Accept: 'application/json',\r\n 'Content-Type': 'application/json',\r\n Authorization: 'pk_fysLKGj3legZz4XZ',\r\n },\r\n body: JSON.stringify({\r\n domain: 'listeners.link', // Ensure this domain is valid for your account\r\n originalURL: this.uri,\r\n }),\r\n };\r\n\r\n // Make the request using fetch\r\n await fetch(url, options)\r\n .then(response => {\r\n if (!response.ok) {\r\n throw new Error(`HTTP error! Status: ${response.status}`);\r\n }\r\n return response.json(); // Parse the JSON response\r\n })\r\n .then(data => {\r\n explanation.innerHTML = (0,_utils__WEBPACK_IMPORTED_MODULE_2__.formatLineBreak)(\r\n this.phrases.RC_skipQR_ExplanationWithoutPreferNot[this.language]\r\n .replace('xxx', `<b style=\"user-select: text\">${data.shortURL}</b>`)\r\n .replace('XXX', `<b style=\"user-select: text\">${data.shortURL}</b>`),\r\n this.phrases.RC_checkInternetConnection[this.language]\r\n );\r\n const checkConnection = document.createElement('a');\r\n checkConnection.id = 'check-connection';\r\n checkConnection.href = '#';\r\n checkConnection.innerHTML = \"check the phone's internet connection\";\r\n const lang = this.language;\r\n checkConnection.addEventListener('click', function (event) {\r\n console.log('clicked');\r\n event.preventDefault(); // Prevent the default link action\r\n (0,_utils__WEBPACK_IMPORTED_MODULE_2__.createAndShowPopup)(lang, this.phrases);\r\n });\r\n explanation.querySelector('a#check-connection').replaceWith(checkConnection);\r\n })\r\n .catch(error => {\r\n console.error('Error:', error.message); // Handle errors\r\n });\r\n\r\n const qrImage = new Image(400, 400);\r\n qrImage.setAttribute('id', 'compatibilityCheckQRImage');\r\n qrImage.style.zIndex = Infinity;\r\n qrImage.style.width = 400;\r\n qrImage.style.height = 400;\r\n qrImage.style.aspectRatio = 1;\r\n qrImage.src = qrCanvas.toDataURL();\r\n qrImage.style.maxHeight = '150px';\r\n qrImage.style.maxWidth = '150px';\r\n\r\n this.qrImage = qrImage;\r\n\r\n const container = document.createElement('div');\r\n container.style.display = 'flex';\r\n container.style.justifyContent = 'space-between';\r\n container.style.alignItems = 'top';\r\n container.id = 'skipQRContainer';\r\n container.appendChild(qrImage);\r\n container.appendChild(explanation);\r\n container.appendChild(this.buttonsContainer);\r\n const qrContainer = document.createElement('div');\r\n qrContainer.appendChild(container);\r\n\r\n document.getElementById(this.targetElement).appendChild(qrContainer);\r\n } else {\r\n // show the link to the user\r\n // If specified HTML Id is available, show QR code there\r\n if (document.getElementById(this.targetElement)) {\r\n // const linkTag = document.createElement('a');\r\n // linkTag.setAttribute('href', uri);\r\n // linkTag.innerHTML = 'Click here to start the calibration';\r\n // linkTag.target = '_blank';\r\n // document.getElementById(this.targetElement).appendChild(linkTag);\r\n // document.getElementById(this.targetElement).appendChild(qrCanvas);\r\n\r\n const proceedButton = document.createElement('button');\r\n proceedButton.setAttribute('id', 'calibrationProceedButton');\r\n proceedButton.setAttribute('class', 'btn btn-success');\r\n proceedButton.innerHTML = this.phrases.T_proceed[this.language];\r\n proceedButton.onclick = () => {\r\n // open the link in a new tab\r\n window.open(this.uri, '_blank');\r\n // remove the button\r\n document.getElementById('calibrationProceedButton').remove();\r\n };\r\n document.getElementById(this.targetElement).appendChild(proceedButton);\r\n }\r\n }\r\n // or just print it to console\r\n console.log('TEST: Peer reachable at: ', this.uri);\r\n };\r\n\r\n #showSpinner = () => {\r\n const spinner = document.createElement('div');\r\n spinner.className = 'spinner-border ml-auto';\r\n spinner.role = 'status';\r\n spinner.ariaHidden = 'true';\r\n spinner.style.marginTop = '0.8rem';\r\n document.getElementById(this.targetElement).appendChild(spinner);\r\n\r\n // clear instructionDisplay\r\n const soundMessage = document.getElementById(this.soundMessageId);\r\n soundMessage.innerHTML = '';\r\n soundMessage.style.display = 'none';\r\n const instructionDisplay = document.getElementById(this.instructionDisplayId);\r\n const background = document.getElementById('background'); // todo: get background id from params\r\n const subtitle = document.getElementById(this.soundSubtitleId);\r\n if (subtitle) {\r\n subtitle.innerHTML = '';\r\n }\r\n if (instructionDisplay) {\r\n instructionDisplay.innerHTML = '';\r\n instructionDisplay.style.whiteSpace = 'nowrap';\r\n instructionDisplay.style.fontWeight = 'bold';\r\n instructionDisplay.style.width = 'fit-content';\r\n instructionDisplay.innerHTML = this.phrases.RC_soundRecording[this.language];\r\n let fontSize = 100;\r\n instructionDisplay.style.fontSize = fontSize + 'px';\r\n while (instructionDisplay.scrollWidth > background.scrollWidth * 0.9 && fontSize > 10) {\r\n fontSize--;\r\n instructionDisplay.style.fontSize = fontSize + 'px';\r\n }\r\n // const p = document.createElement('p');\r\n // // font size\r\n // p.style.fontSize = '1.1rem';\r\n // p.style.fontWeight = 'normal';\r\n // p.style.paddingTop = '20px';\r\n // const timeToCalibrateText = phrases.RC_howLongToCalibrate['en-US'];\r\n // p.innerHTML = timeToCalibrateText.replace('111', this.timeToCalibrate);\r\n // instructionDisplay.appendChild(p);\r\n }\r\n\r\n const timeToCalibrateDisplay = document.getElementById(this.timeToCalibrateDisplay);\r\n if (timeToCalibrateDisplay) {\r\n const timeToCalibrateText = this.phrases.RC_howLongToCalibrate[this.language];\r\n timeToCalibrateDisplay.innerHTML = timeToCalibrateText.replace('111', this.timeToCalibrate);\r\n timeToCalibrateDisplay.style.fontWeight = 'normal';\r\n timeToCalibrateDisplay.style.fontSize = '1rem';\r\n // timeToCalibrateDisplay.style.paddingTop = '20px';\r\n }\r\n\r\n // Update title - titleDisplayId\r\n const titleDisplay = document.getElementById(this.titleDisplayId);\r\n if (titleDisplay) {\r\n // if (this.isParticipant) {\r\n // titleDisplay.innerHTML = titleDisplay.innerHTML.replace('3', '4');\r\n // } else if (this.isSmartPhone) {\r\n // if (this.isLoudspeakerCalibration) {\r\n // titleDisplay.innerHTML = titleDisplay.innerHTML.replace('6', '7');\r\n // } else {\r\n // titleDisplay.innerHTML = titleDisplay.innerHTML.replace('5', '6');\r\n // }\r\n // } else {\r\n // titleDisplay.innerHTML = titleDisplay.innerHTML.replace('5', '6');\r\n // }\r\n if (this.isLoudspeakerCalibration) {\r\n if (this.isParticipant) {\r\n titleDisplay.innerHTML = titleDisplay.innerHTML.replace('3', '4');\r\n } else if (this.isSmartPhone) {\r\n titleDisplay.innerHTML = titleDisplay.innerHTML.replace('6', '7');\r\n } else {\r\n titleDisplay.innerHTML = titleDisplay.innerHTML.replace('4', '5');\r\n }\r\n } else {\r\n if (this.isSmartPhone) {\r\n titleDisplay.innerHTML = titleDisplay.innerHTML.replace('5', '6');\r\n } else {\r\n titleDisplay.innerHTML = titleDisplay.innerHTML.replace('3', '4');\r\n }\r\n }\r\n }\r\n };\r\n\r\n #removeUIElems = () => {\r\n const parent = document.getElementById(this.targetElement);\r\n while (parent.firstChild) {\r\n parent.firstChild.remove();\r\n }\r\n };\r\n\r\n /**\r\n * Called when the peer connection is opened.\r\n * Saves the peer id and calls the QR code generator.\r\n *\r\n * @param peerId - The peer id of the peer connection.\r\n * @param id\r\n * @private\r\n * @example\r\n */\r\n #onPeerOpen = id => {\r\n // Workaround for peer.reconnect deleting previous id\r\n if (id === null) {\r\n console.error('Received null id from peer open');\r\n this.peer.id = this.lastPeerId;\r\n } else {\r\n this.lastPeerId = this.peer.id;\r\n }\r\n\r\n if (id !== this.peer.id) {\r\n console.warn('DEBUG Check you assumption that id === this.peer.id');\r\n }\r\n\r\n this.#showQRCode();\r\n };\r\n\r\n /**\r\n * Called when the peer connection is established.\r\n * Enforces a single connection.\r\n *\r\n * @param connection - The connection object.\r\n * @private\r\n * @example\r\n */\r\n #onPeerConnection = connection => {\r\n // Allow only a single connection\r\n if (this.conn && this.conn.open) {\r\n connection.on('open', () => {\r\n connection.send('Already connected to another client');\r\n setTimeout(() => {\r\n connection.close();\r\n }, 500);\r\n });\r\n return;\r\n }\r\n\r\n this.conn = connection;\r\n console.log('Connected to: ', this.conn.peer);\r\n this.#ready();\r\n };\r\n\r\n /**\r\n * Called when the peer connection is closed.\r\n *\r\n * @private\r\n * @example\r\n */\r\n onPeerClose = () => {\r\n this.conn = null;\r\n console.log('Connection destroyed');\r\n };\r\n\r\n static closeConnection = () => {\r\n this.conn = null;\r\n console.log('Connection destroyed');\r\n };\r\n\r\n /**\r\n * Called when the peer connection is disconnected.\r\n * Attempts to reconnect.\r\n *\r\n * @private\r\n * @example\r\n */\r\n #onPeerDisconnected = () => {\r\n console.log('Connection lost. Please reconnect');\r\n\r\n // Workaround for peer.reconnect deleting previous id\r\n this.peer.id = this.lastPeerId;\r\n // eslint-disable-next-line no-underscore-dangle\r\n this.peer._lastServerId = this.lastPeerId;\r\n this.peer.reconnect();\r\n };\r\n\r\n /**\r\n * Called when the peer connection encounters an error.\r\n *\r\n * @param error\r\n * @private\r\n * @example\r\n */\r\n #onPeerError = error => {\r\n // TODO: check if this function is needed or not\r\n console.error(error);\r\n };\r\n\r\n /**\r\n * Called when data is received from the peer connection.\r\n *\r\n * @param data\r\n * @private\r\n * @example\r\n */\r\n #onIncomingData = data => {\r\n // enforce object type\r\n if (\r\n !Object.prototype.hasOwnProperty.call(data, 'name') ||\r\n !Object.prototype.hasOwnProperty.call(data, 'payload')\r\n ) {\r\n console.error('Received malformed data: ', data);\r\n return;\r\n }\r\n\r\n switch (data.name) {\r\n case 'samplingRate':\r\n this.ac.setSamplingRates(data.payload);\r\n break;\r\n case 'sampleSize':\r\n this.ac.setSampleSize(data.payload);\r\n break;\r\n case 'deviceType':\r\n this.ac.setDeviceType(data.payload);\r\n break;\r\n case 'deviceName':\r\n this.ac.setDeviceName(data.payload);\r\n break;\r\n case 'flags':\r\n //this.ac.setDeviceName(data.payload);\r\n console.log('FLAGS');\r\n console.log(data.payload);\r\n this.ac.setFlags(data.payload);\r\n break;\r\n case 'deviceInfo':\r\n this.ac.setDeviceInfo(data.payload);\r\n console.log('Received device info from listener: ', data.payload);\r\n break;\r\n case _peerErrors__WEBPACK_IMPORTED_MODULE_3__.UnsupportedDeviceError.name:\r\n case _peerErrors__WEBPACK_IMPORTED_MODULE_3__.MissingSpeakerIdError.name:\r\n throw data.payload;\r\n break;\r\n default:\r\n break;\r\n }\r\n };\r\n\r\n /**\r\n * Called when the peer connection is #ready.\r\n *\r\n * @private\r\n * @example\r\n */\r\n #ready = () => {\r\n // Perform callback with data\r\n this.conn.on('data', this.#onIncomingData);\r\n this.conn.on('close', () => {\r\n console.log('Connection reset<br>Awaiting connection...');\r\n this.conn = null;\r\n });\r\n };\r\n\r\n /** .\r\n * .\r\n * .\r\n * Debug method for downloading the recorded audio\r\n *\r\n * @public\r\n * @example\r\n */\r\n downloadData = () => {\r\n this.ac.downloadData();\r\n };\r\n\r\n repeatCalibration = async (params, stream, CalibratorInstance) => {\r\n this.ac = CalibratorInstance;\r\n this.#removeUIElems();\r\n this.#showSpinner();\r\n\r\n console.log('This is a repeat');\r\n // wrap the calibration process in a promise so we can await it\r\n return new Promise(async (resolve, reject) => {\r\n const result = await this.ac.startCalibration(\r\n stream,\r\n params.gainValues,\r\n params.ICalib,\r\n params.knownIR,\r\n params.microphoneName,\r\n params.calibrateSoundCheck,\r\n params.isSmartPhone,\r\n params.calibrateSoundBurstDb,\r\n params.calibrateSoundBurstFilteredExtraDb,\r\n params.calibrateSoundBurstLevelReTBool,\r\n params.calibrateSoundBurstUses1000HzGainBool,\r\n params.calibrateSoundBurstRepeats,\r\n params.calibrateSoundBurstSec,\r\n params._calibrateSoundBurstPreSec,\r\n params._calibrateSoundBurstPostSec,\r\n params.calibrateSoundHz,\r\n params.calibrateSoundIRSec,\r\n params.calibrateSoundIIRSec,\r\n params.calibrateSoundIIRPhase,\r\n params.calibrateSound1000HzPreSec,\r\n params.calibrateSound1000HzSec,\r\n params.calibrateSound1000HzPostSec,\r\n params.calibrateSoundBackgroundSecs,\r\n params.calibrateSoundSmoothOctaves,\r\n params.calibrateSoundSmoothMinBandwidthHz,\r\n params.calibrateSoundPowerBinDesiredSec,\r\n params.calibrateSoundPowerDbSDToleratedDb,\r\n params.calibrateSoundTaperSec,\r\n params.micManufacturer,\r\n params.micSerialNumber,\r\n params.micModelNumber,\r\n params.micModelName,\r\n params.calibrateMicrophonesBool,\r\n params.authorEmails,\r\n params.webAudioDeviceNames,\r\n params.IDsToSaveInSoundProfileLibrary,\r\n params.restartButton,\r\n params.reminder,\r\n params.calibrateSoundLimit,\r\n params.calibrateSoundBurstNormalizeBy1000HzGainBool,\r\n params.calibrateSoundBurstScalarDB,\r\n params.calibrateSound1000HzMaxSD_dB,\r\n params._calibrateSoundBurstMaxSD_dB,\r\n params.calibrateSoundSamplingDesiredBits,\r\n params.language,\r\n params.loudspeakerModelName,\r\n params.phrases,\r\n );\r\n this.#removeUIElems();\r\n resolve(result);\r\n });\r\n };\r\n}\r\n\r\n/* \r\nReferenced links:\r\nhttps://stackoverflow.com/questions/28016664/when-you-pass-this-as-an-argument/28016676#28016676\r\nhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes\r\nhttps://stackoverflow.com/questions/879152/how-do-i-make-javascript-beep [3]\r\n*/\r\n\r\n/* harmony default export */ __webpack_exports__[\"default\"] = (Speaker);\r\n\n\n//# sourceURL=webpack://speakerCalibrator/./src/peer-connection/speaker.js?");
|
|
461
461
|
|
|
462
462
|
/***/ }),
|
|
463
463
|
|
|
@@ -468,7 +468,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var qrco
|
|
|
468
468
|
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
469
469
|
|
|
470
470
|
"use strict";
|
|
471
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ getPower: function() { return /* binding */ getPower; },\n/* harmony export */ interpolate: function() { return /* binding */ interpolate; },\n/* harmony export */ standardDeviation: function() { return /* binding */ standardDeviation; },\n/* harmony export */ volumePowerCheck: function() { return /* binding */ volumePowerCheck; }\n/* harmony export */ });\nconst volumePowerCheck = (rec, fs, preSec, Sec, _calibrateSoundPowerBinDesiredSec) => {\n const coarseHz = 1 / _calibrateSoundPowerBinDesiredSec;\n const power = rec.map(x => Math.pow(x, 2)); // Squared values of the signal\n \n // Adjust coarseHz so that fs is an integer multiple of coarseHz.\n let n = Math.round(fs / coarseHz);\n \n // Sampling times for plotting\n const t = Array.from({ length: power.length }, (_, i) => i / fs);\n \n const coarseSamples = Math.ceil(power.length / n);\n const coarsePowerDb = new Array(coarseSamples).fill(0);\n const coarseT = new Array(coarseSamples).fill(0);\n\n for (let i = 0; i < coarseSamples; i++) {\n const indices = Array.from({ length: Math.min(n, power.length - i * n) }, (_, idx) => i * n + idx);\n const extremeIndices = [indices[0], indices[indices.length - 1]];\n \n const avgPower = indices.reduce((sum, idx) => sum + power[idx], 0) / indices.length;\n coarsePowerDb[i] = 10 * Math.log10(avgPower);\n \n const avgTime = (t[extremeIndices[0]] + t[extremeIndices[1]]) / 2;\n coarseT[i] = avgTime;\n }\n\n const prepSamples = Math.round(coarseHz * preSec);\n const postSamples = Math.round(coarseHz * (preSec + Sec));\n const sd = Math.round(standardDeviation(coarsePowerDb.slice(prepSamples)) * 10) / 10;\n \n const coarseTRounded = coarseT.map(t => Math.round(t * 1000) / 1000); // Round to 3 decimal places\n const coarsePowerDbRounded = coarsePowerDb.map(db => Math.round(db * 1000) / 1000); // Round to 3 decimal places\n\n const start = interpolate(coarseT, coarsePowerDb, preSec);\n const end = interpolate(coarseT, coarsePowerDb, preSec + Sec);\n \n let preT = coarseTRounded.slice(0, prepSamples);\n let preDb = coarsePowerDbRounded.slice(0, prepSamples);\n \n // Adjust starting point of preT and preDb\n if (preT[preT.length - 1] < preSec) {\n preT.push(preSec);\n preDb.push(start);\n }\n\n let recT = coarseTRounded.slice(prepSamples, postSamples);\n let recDb = coarsePowerDbRounded.slice(prepSamples, postSamples);\n \n if (recT[0] > preSec) {\n recT.unshift(preSec);\n recDb.unshift(start);\n }\n \n if (recT[recT.length - 1] < preSec + Sec) {\n recT.push(preSec + Sec);\n recDb.push(end);\n }\n\n let postT = coarseTRounded.slice(postSamples);\n let postDb = coarsePowerDbRounded.slice(postSamples);\n\n if (postT[0] > preSec + Sec) {\n postT.unshift(preSec + Sec);\n postDb.unshift(end);\n }\n\n return { preT, preDb, recT, recDb, postT, postDb, sd };\n}\n\n// Helper function for interpolation\nconst interpolate = (x, y, target) => {\n let lowIdx = 0;\n while (lowIdx < x.length - 1 && x[lowIdx] < target) {\n lowIdx++;\n }\n\n const x0 = x[lowIdx - 1];\n const y0 = y[lowIdx - 1];\n const x1 = x[lowIdx];\n const y1 = y[lowIdx];\n\n // Linear interpolation\n return y0 + ((target - x0) * (y1 - y0)) / (x1 - x0);\n}\n\n// Helper function to calculate standard deviation\nconst standardDeviation = (arr) => {\n const mean = arr.reduce((sum, val) => sum + val, 0) / arr.length;\n const variance = arr.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) / arr.length;\n return Math.sqrt(variance);\n}\n\nconst getPower = (dataArray) => {\n const squaredValues = dataArray.map(value => value * value);\n const sum_of_squares = squaredValues.reduce((total, value) => total + value, 0);\n const squared_mean = sum_of_squares / dataArray.length;\n const dbLevel = 20 * Math.log10(Math.sqrt(squared_mean));\n const roundedDbLevel = Math.round(dbLevel * 10) / 10;\n return roundedDbLevel;\n}\n\n//# sourceURL=webpack://speakerCalibrator/./src/powerCheck.js?");
|
|
471
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ getPower: function() { return /* binding */ getPower; },\n/* harmony export */ interpolate: function() { return /* binding */ interpolate; },\n/* harmony export */ standardDeviation: function() { return /* binding */ standardDeviation; },\n/* harmony export */ volumePowerCheck: function() { return /* binding */ volumePowerCheck; }\n/* harmony export */ });\nconst volumePowerCheck = (rec, fs, preSec, Sec, _calibrateSoundPowerBinDesiredSec) => {\r\n const coarseHz = 1 / _calibrateSoundPowerBinDesiredSec;\r\n const power = rec.map(x => Math.pow(x, 2)); // Squared values of the signal\r\n \r\n // Adjust coarseHz so that fs is an integer multiple of coarseHz.\r\n let n = Math.round(fs / coarseHz);\r\n \r\n // Sampling times for plotting\r\n const t = Array.from({ length: power.length }, (_, i) => i / fs);\r\n \r\n const coarseSamples = Math.ceil(power.length / n);\r\n const coarsePowerDb = new Array(coarseSamples).fill(0);\r\n const coarseT = new Array(coarseSamples).fill(0);\r\n\r\n for (let i = 0; i < coarseSamples; i++) {\r\n const indices = Array.from({ length: Math.min(n, power.length - i * n) }, (_, idx) => i * n + idx);\r\n const extremeIndices = [indices[0], indices[indices.length - 1]];\r\n \r\n const avgPower = indices.reduce((sum, idx) => sum + power[idx], 0) / indices.length;\r\n coarsePowerDb[i] = 10 * Math.log10(avgPower);\r\n \r\n const avgTime = (t[extremeIndices[0]] + t[extremeIndices[1]]) / 2;\r\n coarseT[i] = avgTime;\r\n }\r\n\r\n const prepSamples = Math.round(coarseHz * preSec);\r\n const postSamples = Math.round(coarseHz * (preSec + Sec));\r\n const sd = Math.round(standardDeviation(coarsePowerDb.slice(prepSamples)) * 10) / 10;\r\n \r\n const coarseTRounded = coarseT.map(t => Math.round(t * 1000) / 1000); // Round to 3 decimal places\r\n const coarsePowerDbRounded = coarsePowerDb.map(db => Math.round(db * 1000) / 1000); // Round to 3 decimal places\r\n\r\n const start = interpolate(coarseT, coarsePowerDb, preSec);\r\n const end = interpolate(coarseT, coarsePowerDb, preSec + Sec);\r\n \r\n let preT = coarseTRounded.slice(0, prepSamples);\r\n let preDb = coarsePowerDbRounded.slice(0, prepSamples);\r\n \r\n // Adjust starting point of preT and preDb\r\n if (preT[preT.length - 1] < preSec) {\r\n preT.push(preSec);\r\n preDb.push(start);\r\n }\r\n\r\n let recT = coarseTRounded.slice(prepSamples, postSamples);\r\n let recDb = coarsePowerDbRounded.slice(prepSamples, postSamples);\r\n \r\n if (recT[0] > preSec) {\r\n recT.unshift(preSec);\r\n recDb.unshift(start);\r\n }\r\n \r\n if (recT[recT.length - 1] < preSec + Sec) {\r\n recT.push(preSec + Sec);\r\n recDb.push(end);\r\n }\r\n\r\n let postT = coarseTRounded.slice(postSamples);\r\n let postDb = coarsePowerDbRounded.slice(postSamples);\r\n\r\n if (postT[0] > preSec + Sec) {\r\n postT.unshift(preSec + Sec);\r\n postDb.unshift(end);\r\n }\r\n\r\n return { preT, preDb, recT, recDb, postT, postDb, sd };\r\n}\r\n\r\n// Helper function for interpolation\r\nconst interpolate = (x, y, target) => {\r\n let lowIdx = 0;\r\n while (lowIdx < x.length - 1 && x[lowIdx] < target) {\r\n lowIdx++;\r\n }\r\n\r\n const x0 = x[lowIdx - 1];\r\n const y0 = y[lowIdx - 1];\r\n const x1 = x[lowIdx];\r\n const y1 = y[lowIdx];\r\n\r\n // Linear interpolation\r\n return y0 + ((target - x0) * (y1 - y0)) / (x1 - x0);\r\n}\r\n\r\n// Helper function to calculate standard deviation\r\nconst standardDeviation = (arr) => {\r\n const mean = arr.reduce((sum, val) => sum + val, 0) / arr.length;\r\n const variance = arr.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) / arr.length;\r\n return Math.sqrt(variance);\r\n}\r\n\r\nconst getPower = (dataArray) => {\r\n const squaredValues = dataArray.map(value => value * value);\r\n const sum_of_squares = squaredValues.reduce((total, value) => total + value, 0);\r\n const squared_mean = sum_of_squares / dataArray.length;\r\n const dbLevel = 20 * Math.log10(Math.sqrt(squared_mean));\r\n const roundedDbLevel = Math.round(dbLevel * 10) / 10;\r\n return roundedDbLevel;\r\n}\n\n//# sourceURL=webpack://speakerCalibrator/./src/powerCheck.js?");
|
|
472
472
|
|
|
473
473
|
/***/ }),
|
|
474
474
|
|
|
@@ -479,7 +479,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
479
479
|
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
480
480
|
|
|
481
481
|
"use strict";
|
|
482
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var axios__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! axios */ \"./node_modules/axios/lib/axios.js\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils */ \"./src/utils.js\");\n\n\n/**\n *\n */\nclass PythonServerAPI {\n static PYTHON_SERVER_URL = 'https://easyeyes-python-flask-server.herokuapp.com';\n\n static TEST_SERVER_URL = 'http://127.0.0.1:5000';\n // static PYTHON_SERVER_URL ='http://127.0.0.1:5000';\n\n /** @private */\n MAX_RETRY_COUNT = 3;\n /** @private */\n RETRY_DELAY_MS = 1000;\n /**\n * @param data- -\n * g = inverted impulse response, when convolved with the impulse\n * reponse, they cancel out.\n * @param data.payload\n * @param data.sampleRate\n * @param data.P\n * @param data-.payload\n * @param data-.sampleRate\n * @param data-.P\n * @returns\n * @example\n */\n getImpulseResponse = async ({\n mls, \n sampleRate, \n numPeriods,\n sig,\n fs2,\n L_new_n,\n dL_n\n }) => {\n const task = 'impulse-response';\n let res = null;\n\n const data = JSON.stringify({\n task,\n 'sample-rate': sampleRate,\n mls,\n numPeriods,\n sig,\n fs2,\n L_new_n,\n dL_n\n });\n\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: `/task/${task}`,\n headers: {\n 'Content-Type': 'application/json',\n },\n data,\n })\n .then(response => {\n res = response;\n })\n .catch(error => {\n throw error;\n });\n return res.data[task];\n };\n\n getAutocorrelation = async ({\n mls, \n payload, \n sampleRate, \n numPeriods\n }) => {\n const task = 'autocorrelation';\n let res = null;\n\n const data = JSON.stringify({\n task,\n 'payload': payload,\n 'sample-rate': sampleRate,\n mls,\n numPeriods,\n });\n\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: `/task/${task}`,\n headers: {\n 'Content-Type': 'application/json',\n },\n data,\n })\n .then(response => {\n res = response;\n })\n .catch(error => {\n throw error;\n });\n return res.data[task];\n };\n\n getConvolution = async ({\n mls, \n inverse_response, \n inverse_response_no_bandpass,\n attenuatorGain_dB,\n mls_amplitude\n }) => {\n const task = 'convolution';\n let res = null;\n\n const data = JSON.stringify({\n task,\n mls, \n inverse_response, \n inverse_response_no_bandpass,\n attenuatorGain_dB,\n mls_amplitude\n });\n\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: `/task/${task}`,\n headers: {\n 'Content-Type': 'application/json',\n },\n data,\n })\n .then(response => {\n res = response;\n })\n .catch(error => {\n throw error;\n });\n return res.data[task];\n };\n\n getMLS = async ({length,amplitude,calibrateSoundBurstMLSVersions}) => {\n const task = 'mls';\n let res = null;\n\n const data = JSON.stringify({\n task,\n length: length,\n amplitude: amplitude,\n calibrateSoundBurstMLSVersions: calibrateSoundBurstMLSVersions,\n });\n\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: `/task/${task}`,\n headers: {\n 'Content-Type': 'application/json',\n },\n data,\n })\n .then(response => {\n res = response;\n })\n .catch(error => {\n throw error;\n });\n\n return res.data[task];\n };\n\n getShortURL = async (originalURL) => {\n const task = 'url';\n let res = null;\n console.log(originalURL);\n const data = JSON.stringify({\n 'URL': originalURL\n });\n\n console.log(data);\n\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: `/task/${task}`,\n headers: {\n 'Content-Type': 'application/json',\n },\n data,\n })\n .then(response => {\n res = response;\n console.log(res.data[task]);\n })\n .catch(error => {\n throw error;\n });\n\n return res.data[task];\n };\n\n getMemory = async () => {\n let res;\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: `/memory`,\n headers: {\n 'Content-Type': 'application/json',\n }\n })\n .then(response => {\n console.log(\"memory used:\", Math.round(response.data['memory']), \"mb\");\n res = response.data['memory'];\n })\n .catch(error => {\n throw error;\n });\n return res;\n };\n\n\n checkMemory = async () => {\n console.log(\"wait for memory under 500 mb to continue calibration\");\n await this.getMemory();\n // let memory = await this.getMemory();\n // while (memory >= 500) {\n // console.log(\"sleep 30s\");\n // await sleep(30);\n // memory = await this.getMemory();\n // }\n \n };\n\n\n getMLSWithRetry = async ({length,amplitude,calibrateSoundBurstMLSVersions}) => {\n let retryCount = 0;\n let response = null;\n\n while (retryCount < this.MAX_RETRY_COUNT) {\n try {\n response = await this.getMLS({length,amplitude, calibrateSoundBurstMLSVersions});\n // If the request is successful, break out of the loop\n break;\n } catch (error) {\n console.error(`Error occurred. Retrying... (${retryCount + 1}/${this.MAX_RETRY_COUNT})`);\n retryCount++;\n await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS));\n }\n }\n\n if (response) {\n return response;\n } else {\n throw new Error(`Failed to get MLS after ${this.MAX_RETRY_COUNT} attempts.`);\n }\n };\n\n getPSD = async ({unconv_rec, conv_rec, sampleRate}) => {\n const task = 'psd';\n let res = null;\n\n const data = JSON.stringify({\n task,\n unconv_rec,\n conv_rec,\n sampleRate,\n });\n\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: `/task/${task}`,\n headers: {\n 'Content-Type': 'application/json',\n },\n data,\n })\n .then(response => {\n res = response;\n })\n .catch(error => {\n throw error;\n });\n return res.data[task];\n };\n\n getBackgroundNoisePSD = async ({background_rec, sampleRate}) => {\n const task = 'background-psd';\n let res = null;\n\n const data = JSON.stringify({\n task,\n background_rec,\n sampleRate,\n });\n\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: `/task/${task}`,\n headers: {\n 'Content-Type': 'application/json',\n },\n data,\n })\n .then(response => {\n res = response;\n })\n .catch(error => {\n throw error;\n });\n return res.data[task];\n };\n\n getBackgroundNoisePSDWithRetry = async ({background_rec, sampleRate}) => {\n let retryCount = 0;\n let response = null;\n\n while (retryCount < this.MAX_RETRY_COUNT) {\n try {\n response = await this.getBackgroundNoisePSD({background_rec, sampleRate});\n // If the request is successful, break out of the loop\n break;\n } catch (error) {\n console.error(`Error occurred. Retrying... (${retryCount + 1}/${this.MAX_RETRY_COUNT})`);\n retryCount++;\n await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS));\n }\n }\n\n if (response) {\n return response;\n } else {\n throw new Error(`Failed to get PSD after ${this.MAX_RETRY_COUNT} attempts.`);\n }\n };\n\n getSubtractedPSD = async (rec, knownGains, knownFrequencies, sampleRate) => {\n const task = 'subtracted-psd';\n let res = null;\n\n const data = JSON.stringify({\n task,\n rec,\n knownGains,\n knownFrequencies,\n sampleRate,\n });\n\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: `/task/${task}`,\n headers: {\n 'Content-Type': 'application/json',\n },\n data,\n })\n .then(response => {\n res = response;\n })\n .catch(error => {\n throw error;\n });\n return res.data[task];\n };\n\n getSubtractedPSDWithRetry = async (rec, knownGains, knownFrequencies, sampleRate) => {\n let retryCount = 0;\n let response = null;\n\n while (retryCount < this.MAX_RETRY_COUNT) {\n try {\n response = await this.getSubtractedPSD(rec, knownGains, knownFrequencies, sampleRate);\n // If the request is successful, break out of the loop\n break;\n } catch (error) {\n console.error(`Error occurred. Retrying... (${retryCount + 1}/${this.MAX_RETRY_COUNT})`);\n retryCount++;\n await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS));\n }\n }\n\n if (response) {\n return response;\n } else {\n throw new Error(`Failed to get PSD after ${this.MAX_RETRY_COUNT} attempts.`);\n }\n };\n\n getPSDWithRetry = async ({unconv_rec, conv_rec, sampleRate}) => {\n let retryCount = 0;\n let response = null;\n\n while (retryCount < this.MAX_RETRY_COUNT) {\n try {\n response = await this.getPSD({unconv_rec, conv_rec, sampleRate});\n // If the request is successful, break out of the loop\n break;\n } catch (error) {\n console.error(`Error occurred. Retrying... (${retryCount + 1}/${this.MAX_RETRY_COUNT})`);\n retryCount++;\n await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS));\n }\n }\n\n if (response) {\n return response;\n } else {\n throw new Error(`Failed to get PSD after ${this.MAX_RETRY_COUNT} attempts.`);\n }\n };\n\n getComponentInverseImpulseResponse = async ({\n payload,\n mls,\n lowHz,\n highHz,\n componentIRGains,\n iirLength,\n componentIRFreqs,\n sampleRate,\n mlsAmplitude,\n irLength,\n calibrateSoundSmoothOctaves,\n calibrateSoundSmoothMinBandwidthHz,\n calibrateSoundBurstFilteredExtraDb,\n calibrateSoundIIRPhase\n }) => {\n const task = 'component-inverse-impulse-response';\n let res = null;\n\n const data = JSON.stringify({\n task,\n payload,\n mls,\n lowHz,\n highHz,\n iirLength,\n componentIRGains,\n componentIRFreqs,\n sampleRate,\n mlsAmplitude,\n irLength,\n calibrateSoundSmoothOctaves,\n calibrateSoundSmoothMinBandwidthHz,\n calibrateSoundBurstFilteredExtraDb,\n calibrateSoundIIRPhase\n });\n\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: `/task/${task}`,\n headers: {\n 'Content-Type': 'application/json',\n },\n data,\n })\n .then(response => {\n res = response;\n })\n .catch(error => {\n throw error;\n });\n\n return res.data[task];\n };\n getSystemInverseImpulseResponse = async ({\n payload,\n mls,\n lowHz,\n highHz,\n iirLength,\n sampleRate,\n mlsAmplitude,\n calibrateSoundBurstFilteredExtraDb,\n calibrateSoundIIRPhase\n }) => {\n const task = 'system-inverse-impulse-response';\n let res = null;\n\n const data = JSON.stringify({\n task,\n payload,\n mls,\n lowHz,\n iirLength,\n highHz,\n sampleRate,\n mlsAmplitude,\n calibrateSoundBurstFilteredExtraDb,\n calibrateSoundIIRPhase\n });\n\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: `/task/${task}`,\n headers: {\n 'Content-Type': 'application/json',\n },\n data,\n })\n .then(response => {\n res = response;\n })\n .catch(error => {\n throw error;\n });\n\n return res.data[task];\n };\n\n getMLSPSD = async ({mls, sampleRate}) => {\n const task = 'mls-psd';\n let res = null;\n\n const data = JSON.stringify({\n task,\n mls,\n sampleRate,\n });\n\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: `/task/${task}`,\n headers: {\n 'Content-Type': 'application/json',\n },\n data,\n })\n .then(response => {\n res = response;\n })\n .catch(error => {\n throw error;\n });\n\n return res.data[task];\n };\n\n getMLSPSDWithRetry = async ({mls, sampleRate}) => {\n let retryCount = 0;\n let response = null;\n\n while (retryCount < this.MAX_RETRY_COUNT) {\n try {\n response = await this.getMLSPSD({mls, sampleRate});\n // If the request is successful, break out of the loop\n break;\n } catch (error) {\n console.error(`Error occurred. Retrying... (${retryCount + 1}/${this.MAX_RETRY_COUNT})`);\n retryCount++;\n await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS));\n }\n }\n\n if (response) {\n return response;\n } else {\n throw new Error(\n `Failed to get inverse impulse response after ${this.MAX_RETRY_COUNT} attempts.`\n );\n }\n };\n\n getComponentInverseImpulseResponseWithRetry = async ({\n payload,\n mls,\n lowHz,\n highHz,\n componentIRGains,\n iirLength,\n componentIRFreqs,\n sampleRate,\n mlsAmplitude,\n irLength,\n calibrateSoundSmoothOctaves,\n calibrateSoundSmoothMinBandwidthHz,\n calibrateSoundBurstFilteredExtraDb,\n calibrateSoundIIRPhase\n }) => {\n let retryCount = 0;\n let response = null;\n\n while (retryCount < this.MAX_RETRY_COUNT) {\n try {\n response = await this.getComponentInverseImpulseResponse({\n payload,\n mls,\n lowHz,\n highHz,\n componentIRGains,\n iirLength,\n componentIRFreqs,\n sampleRate,\n mlsAmplitude,\n irLength,\n calibrateSoundSmoothOctaves,\n calibrateSoundSmoothMinBandwidthHz,\n calibrateSoundBurstFilteredExtraDb,\n calibrateSoundIIRPhase\n });\n // If the request is successful, break out of the loop\n break;\n } catch (error) {\n console.error(`Error occurred. Retrying... (${retryCount + 1}/${this.MAX_RETRY_COUNT})`);\n retryCount++;\n await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS));\n }\n }\n\n if (response) {\n return response;\n } else {\n throw new Error(\n `Failed to get inverse impulse response after ${this.MAX_RETRY_COUNT} attempts.`\n );\n }\n };\n\n getSystemInverseImpulseResponseWithRetry = async ({\n payload,\n mls,\n lowHz,\n highHz,\n iirLength,\n sampleRate,\n mlsAmplitude,\n calibrateSoundBurstFilteredExtraDb,\n calibrateSoundIIRPhase\n }) => {\n let retryCount = 0;\n let response = null;\n\n while (retryCount < this.MAX_RETRY_COUNT) {\n try {\n response = await this.getSystemInverseImpulseResponse({\n payload,\n mls,\n lowHz,\n highHz,\n iirLength,\n sampleRate,\n mlsAmplitude,\n calibrateSoundBurstFilteredExtraDb,\n calibrateSoundIIRPhase\n });\n // If the request is successful, break out of the loop\n break;\n } catch (error) {\n console.error(`Error occurred. Retrying... (${retryCount + 1}/${this.MAX_RETRY_COUNT})`);\n retryCount++;\n await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS));\n }\n }\n\n if (response) {\n return response;\n } else {\n throw new Error(\n `Failed to get inverse impulse response after ${this.MAX_RETRY_COUNT} attempts.`\n );\n }\n };\n\n getVolumeCalibration = async ({payload, sampleRate, lCalib}) => {\n const task = 'volume';\n let res = null;\n\n console.log({payload});\n\n const data = JSON.stringify({\n task,\n payload,\n 'sample-rate': sampleRate,\n lCalib,\n });\n\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: `/task/${task}`,\n headers: {\n 'Content-Type': 'application/json',\n },\n data,\n })\n .then(response => {\n res = response;\n })\n .catch(error => {\n throw error;\n });\n\n return res.data[task];\n };\n\n getVolumeCalibrationParameters = async ({\n inDBValues,\n outDBSPLValues,\n lCalib,\n componentGainDBSPL,\n }) => {\n const task = 'volume-parameters';\n let res = null;\n\n const data = JSON.stringify({\n task,\n inDBValues,\n outDBSPLValues,\n lCalib,\n componentGainDBSPL,\n });\n\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL, //server\n url: `/task/${task}`,\n headers: {\n 'Content-Type': 'application/json',\n },\n data,\n })\n .then(response => {\n res = response;\n console.log(res.data[task]);\n })\n .catch(error => {\n throw error;\n });\n\n // console.log(res.data[task]);\n //below is an example of res.data[task]\n //{\n // R: 16.56981076554259,\n // RMSError: 1.9289162528535229\n // T: -47.79799120884434,\n // W: 61.0485247483732,\n // backgroundDBSPL: 43.88233142069752,\n // gainDBSPL: -128.24742161208985\n //}\n return res.data[task];\n };\n\n allHzPowerCheck = async ({\n payload, \n sampleRate, \n binDesiredSec,\n burstSec,\n repeats,\n warmUp\n }) => {\n const task = 'all-hz-check';\n let res = null;\n\n console.log({payload, \n sampleRate, \n binDesiredSec,\n burstSec,\n repeats,\n warmUp});\n\n const data = JSON.stringify({\n payload, \n sampleRate, \n binDesiredSec,\n burstSec,\n repeats,\n warmUp\n });\n\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL, //server\n url: `/task/${task}`,\n headers: {\n 'Content-Type': 'application/json',\n },\n data,\n })\n .then(response => {\n res = response;\n console.log(res.data[task]);\n })\n .catch(error => {\n throw error;\n });\n return res.data[task];\n };\n\n volumePowerCheck = async ({\n payload, \n sampleRate, \n preSec,\n Sec,\n binDesiredSec\n }) => {\n const task = 'volume-check';\n let res = null;\n\n const data = JSON.stringify({\n payload, \n sampleRate, \n preSec,\n Sec,\n binDesiredSec\n });\n\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL, //server\n url: `/task/${task}`,\n headers: {\n 'Content-Type': 'application/json',\n },\n data,\n })\n .then(response => {\n res = response;\n console.log(res.data[task]);\n })\n .catch(error => {\n throw error;\n });\n return res.data[task];\n };\n\n volumePowerCheckWithRetry = async ({\n payload, \n sampleRate, \n preSec,\n Sec,\n binDesiredSec\n }) => {\n let retryCount = 0;\n let response = null;\n\n while (retryCount < this.MAX_RETRY_COUNT) {\n try {\n response = await this.volumePowerCheck({\n payload, \n sampleRate, \n preSec,\n Sec,\n binDesiredSec});\n // If the request is successful, break out of the loop\n break;\n } catch (error) {\n console.error(`Error occurred. Retrying... (${retryCount + 1}/${this.MAX_RETRY_COUNT})`);\n retryCount++;\n await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS));\n }\n }\n\n if (response) {\n return response;\n } else {\n throw new Error(`Failed to get volume power check after ${this.MAX_RETRY_COUNT} attempts.`);\n }\n };\n}\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (PythonServerAPI);\n\n\n//# sourceURL=webpack://speakerCalibrator/./src/server/PythonServerAPI.js?");
|
|
482
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var axios__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! axios */ \"./node_modules/axios/lib/axios.js\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils */ \"./src/utils.js\");\n\r\n\r\n/**\r\n *\r\n */\r\nclass PythonServerAPI {\r\n static PYTHON_SERVER_URL = 'https://easyeyes-python-flask-server.herokuapp.com';\r\n\r\n static TEST_SERVER_URL = 'http://127.0.0.1:5000';\r\n // static PYTHON_SERVER_URL ='http://127.0.0.1:5000';\r\n\r\n /** @private */\r\n MAX_RETRY_COUNT = 3;\r\n /** @private */\r\n RETRY_DELAY_MS = 1000;\r\n /**\r\n * @param data- -\r\n * g = inverted impulse response, when convolved with the impulse\r\n * reponse, they cancel out.\r\n * @param data.payload\r\n * @param data.sampleRate\r\n * @param data.P\r\n * @param data-.payload\r\n * @param data-.sampleRate\r\n * @param data-.P\r\n * @returns\r\n * @example\r\n */\r\n getImpulseResponse = async ({\r\n mls, \r\n sampleRate, \r\n numPeriods,\r\n sig,\r\n fs2,\r\n L_new_n,\r\n dL_n\r\n }) => {\r\n const task = 'impulse-response';\r\n let res = null;\r\n\r\n const data = JSON.stringify({\r\n task,\r\n 'sample-rate': sampleRate,\r\n mls,\r\n numPeriods,\r\n sig,\r\n fs2,\r\n L_new_n,\r\n dL_n\r\n });\r\n\r\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\r\n method: 'post',\r\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\r\n url: `/task/${task}`,\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n data,\r\n })\r\n .then(response => {\r\n res = response;\r\n })\r\n .catch(error => {\r\n throw error;\r\n });\r\n return res.data[task];\r\n };\r\n\r\n getAutocorrelation = async ({\r\n mls, \r\n payload, \r\n sampleRate, \r\n numPeriods\r\n }) => {\r\n const task = 'autocorrelation';\r\n let res = null;\r\n\r\n const data = JSON.stringify({\r\n task,\r\n 'payload': payload,\r\n 'sample-rate': sampleRate,\r\n mls,\r\n numPeriods,\r\n });\r\n\r\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\r\n method: 'post',\r\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\r\n url: `/task/${task}`,\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n data,\r\n })\r\n .then(response => {\r\n res = response;\r\n })\r\n .catch(error => {\r\n throw error;\r\n });\r\n return res.data[task];\r\n };\r\n\r\n getConvolution = async ({\r\n mls, \r\n inverse_response, \r\n inverse_response_no_bandpass,\r\n attenuatorGain_dB,\r\n mls_amplitude\r\n }) => {\r\n const task = 'convolution';\r\n let res = null;\r\n\r\n const data = JSON.stringify({\r\n task,\r\n mls, \r\n inverse_response, \r\n inverse_response_no_bandpass,\r\n attenuatorGain_dB,\r\n mls_amplitude\r\n });\r\n\r\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\r\n method: 'post',\r\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\r\n url: `/task/${task}`,\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n data,\r\n })\r\n .then(response => {\r\n res = response;\r\n })\r\n .catch(error => {\r\n throw error;\r\n });\r\n return res.data[task];\r\n };\r\n\r\n getMLS = async ({length,amplitude,calibrateSoundBurstMLSVersions}) => {\r\n const task = 'mls';\r\n let res = null;\r\n\r\n const data = JSON.stringify({\r\n task,\r\n length: length,\r\n amplitude: amplitude,\r\n calibrateSoundBurstMLSVersions: calibrateSoundBurstMLSVersions,\r\n });\r\n\r\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\r\n method: 'post',\r\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\r\n url: `/task/${task}`,\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n data,\r\n })\r\n .then(response => {\r\n res = response;\r\n })\r\n .catch(error => {\r\n throw error;\r\n });\r\n\r\n return res.data[task];\r\n };\r\n\r\n getShortURL = async (originalURL) => {\r\n const task = 'url';\r\n let res = null;\r\n console.log(originalURL);\r\n const data = JSON.stringify({\r\n 'URL': originalURL\r\n });\r\n\r\n console.log(data);\r\n\r\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\r\n method: 'post',\r\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\r\n url: `/task/${task}`,\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n data,\r\n })\r\n .then(response => {\r\n res = response;\r\n console.log(res.data[task]);\r\n })\r\n .catch(error => {\r\n throw error;\r\n });\r\n\r\n return res.data[task];\r\n };\r\n\r\n getMemory = async () => {\r\n let res;\r\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\r\n method: 'post',\r\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\r\n url: `/memory`,\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n }\r\n })\r\n .then(response => {\r\n console.log(\"memory used:\", Math.round(response.data['memory']), \"mb\");\r\n res = response.data['memory'];\r\n })\r\n .catch(error => {\r\n throw error;\r\n });\r\n return res;\r\n };\r\n\r\n\r\n checkMemory = async () => {\r\n console.log(\"wait for memory under 500 mb to continue calibration\");\r\n await this.getMemory();\r\n // let memory = await this.getMemory();\r\n // while (memory >= 500) {\r\n // console.log(\"sleep 30s\");\r\n // await sleep(30);\r\n // memory = await this.getMemory();\r\n // }\r\n \r\n };\r\n\r\n\r\n getMLSWithRetry = async ({length,amplitude,calibrateSoundBurstMLSVersions}) => {\r\n let retryCount = 0;\r\n let response = null;\r\n\r\n while (retryCount < this.MAX_RETRY_COUNT) {\r\n try {\r\n response = await this.getMLS({length,amplitude, calibrateSoundBurstMLSVersions});\r\n // If the request is successful, break out of the loop\r\n break;\r\n } catch (error) {\r\n console.error(`Error occurred. Retrying... (${retryCount + 1}/${this.MAX_RETRY_COUNT})`);\r\n retryCount++;\r\n await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS));\r\n }\r\n }\r\n\r\n if (response) {\r\n return response;\r\n } else {\r\n throw new Error(`Failed to get MLS after ${this.MAX_RETRY_COUNT} attempts.`);\r\n }\r\n };\r\n\r\n getPSD = async ({unconv_rec, conv_rec, sampleRate}) => {\r\n const task = 'psd';\r\n let res = null;\r\n\r\n const data = JSON.stringify({\r\n task,\r\n unconv_rec,\r\n conv_rec,\r\n sampleRate,\r\n });\r\n\r\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\r\n method: 'post',\r\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\r\n url: `/task/${task}`,\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n data,\r\n })\r\n .then(response => {\r\n res = response;\r\n })\r\n .catch(error => {\r\n throw error;\r\n });\r\n return res.data[task];\r\n };\r\n\r\n getBackgroundNoisePSD = async ({background_rec, sampleRate}) => {\r\n const task = 'background-psd';\r\n let res = null;\r\n\r\n const data = JSON.stringify({\r\n task,\r\n background_rec,\r\n sampleRate,\r\n });\r\n\r\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\r\n method: 'post',\r\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\r\n url: `/task/${task}`,\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n data,\r\n })\r\n .then(response => {\r\n res = response;\r\n })\r\n .catch(error => {\r\n throw error;\r\n });\r\n return res.data[task];\r\n };\r\n\r\n getBackgroundNoisePSDWithRetry = async ({background_rec, sampleRate}) => {\r\n let retryCount = 0;\r\n let response = null;\r\n\r\n while (retryCount < this.MAX_RETRY_COUNT) {\r\n try {\r\n response = await this.getBackgroundNoisePSD({background_rec, sampleRate});\r\n // If the request is successful, break out of the loop\r\n break;\r\n } catch (error) {\r\n console.error(`Error occurred. Retrying... (${retryCount + 1}/${this.MAX_RETRY_COUNT})`);\r\n retryCount++;\r\n await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS));\r\n }\r\n }\r\n\r\n if (response) {\r\n return response;\r\n } else {\r\n throw new Error(`Failed to get PSD after ${this.MAX_RETRY_COUNT} attempts.`);\r\n }\r\n };\r\n\r\n getSubtractedPSD = async (rec, knownGains, knownFrequencies, sampleRate) => {\r\n const task = 'subtracted-psd';\r\n let res = null;\r\n\r\n const data = JSON.stringify({\r\n task,\r\n rec,\r\n knownGains,\r\n knownFrequencies,\r\n sampleRate,\r\n });\r\n\r\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\r\n method: 'post',\r\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\r\n url: `/task/${task}`,\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n data,\r\n })\r\n .then(response => {\r\n res = response;\r\n })\r\n .catch(error => {\r\n throw error;\r\n });\r\n return res.data[task];\r\n };\r\n\r\n getSubtractedPSDWithRetry = async (rec, knownGains, knownFrequencies, sampleRate) => {\r\n let retryCount = 0;\r\n let response = null;\r\n\r\n while (retryCount < this.MAX_RETRY_COUNT) {\r\n try {\r\n response = await this.getSubtractedPSD(rec, knownGains, knownFrequencies, sampleRate);\r\n // If the request is successful, break out of the loop\r\n break;\r\n } catch (error) {\r\n console.error(`Error occurred. Retrying... (${retryCount + 1}/${this.MAX_RETRY_COUNT})`);\r\n retryCount++;\r\n await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS));\r\n }\r\n }\r\n\r\n if (response) {\r\n return response;\r\n } else {\r\n throw new Error(`Failed to get PSD after ${this.MAX_RETRY_COUNT} attempts.`);\r\n }\r\n };\r\n\r\n getPSDWithRetry = async ({unconv_rec, conv_rec, sampleRate}) => {\r\n let retryCount = 0;\r\n let response = null;\r\n\r\n while (retryCount < this.MAX_RETRY_COUNT) {\r\n try {\r\n response = await this.getPSD({unconv_rec, conv_rec, sampleRate});\r\n // If the request is successful, break out of the loop\r\n break;\r\n } catch (error) {\r\n console.error(`Error occurred. Retrying... (${retryCount + 1}/${this.MAX_RETRY_COUNT})`);\r\n retryCount++;\r\n await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS));\r\n }\r\n }\r\n\r\n if (response) {\r\n return response;\r\n } else {\r\n throw new Error(`Failed to get PSD after ${this.MAX_RETRY_COUNT} attempts.`);\r\n }\r\n };\r\n\r\n getComponentInverseImpulseResponse = async ({\r\n payload,\r\n mls,\r\n lowHz,\r\n highHz,\r\n componentIRGains,\r\n iirLength,\r\n componentIRFreqs,\r\n sampleRate,\r\n mlsAmplitude,\r\n irLength,\r\n calibrateSoundSmoothOctaves,\r\n calibrateSoundSmoothMinBandwidthHz,\r\n calibrateSoundBurstFilteredExtraDb,\r\n calibrateSoundIIRPhase\r\n }) => {\r\n const task = 'component-inverse-impulse-response';\r\n let res = null;\r\n\r\n const data = JSON.stringify({\r\n task,\r\n payload,\r\n mls,\r\n lowHz,\r\n highHz,\r\n iirLength,\r\n componentIRGains,\r\n componentIRFreqs,\r\n sampleRate,\r\n mlsAmplitude,\r\n irLength,\r\n calibrateSoundSmoothOctaves,\r\n calibrateSoundSmoothMinBandwidthHz,\r\n calibrateSoundBurstFilteredExtraDb,\r\n calibrateSoundIIRPhase\r\n });\r\n\r\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\r\n method: 'post',\r\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\r\n url: `/task/${task}`,\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n data,\r\n })\r\n .then(response => {\r\n res = response;\r\n })\r\n .catch(error => {\r\n throw error;\r\n });\r\n\r\n return res.data[task];\r\n };\r\n getSystemInverseImpulseResponse = async ({\r\n payload,\r\n mls,\r\n lowHz,\r\n highHz,\r\n iirLength,\r\n sampleRate,\r\n mlsAmplitude,\r\n calibrateSoundBurstFilteredExtraDb,\r\n calibrateSoundIIRPhase\r\n }) => {\r\n const task = 'system-inverse-impulse-response';\r\n let res = null;\r\n\r\n const data = JSON.stringify({\r\n task,\r\n payload,\r\n mls,\r\n lowHz,\r\n iirLength,\r\n highHz,\r\n sampleRate,\r\n mlsAmplitude,\r\n calibrateSoundBurstFilteredExtraDb,\r\n calibrateSoundIIRPhase\r\n });\r\n\r\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\r\n method: 'post',\r\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\r\n url: `/task/${task}`,\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n data,\r\n })\r\n .then(response => {\r\n res = response;\r\n })\r\n .catch(error => {\r\n throw error;\r\n });\r\n\r\n return res.data[task];\r\n };\r\n\r\n getMLSPSD = async ({mls, sampleRate}) => {\r\n const task = 'mls-psd';\r\n let res = null;\r\n\r\n const data = JSON.stringify({\r\n task,\r\n mls,\r\n sampleRate,\r\n });\r\n\r\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\r\n method: 'post',\r\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\r\n url: `/task/${task}`,\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n data,\r\n })\r\n .then(response => {\r\n res = response;\r\n })\r\n .catch(error => {\r\n throw error;\r\n });\r\n\r\n return res.data[task];\r\n };\r\n\r\n getMLSPSDWithRetry = async ({mls, sampleRate}) => {\r\n let retryCount = 0;\r\n let response = null;\r\n\r\n while (retryCount < this.MAX_RETRY_COUNT) {\r\n try {\r\n response = await this.getMLSPSD({mls, sampleRate});\r\n // If the request is successful, break out of the loop\r\n break;\r\n } catch (error) {\r\n console.error(`Error occurred. Retrying... (${retryCount + 1}/${this.MAX_RETRY_COUNT})`);\r\n retryCount++;\r\n await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS));\r\n }\r\n }\r\n\r\n if (response) {\r\n return response;\r\n } else {\r\n throw new Error(\r\n `Failed to get inverse impulse response after ${this.MAX_RETRY_COUNT} attempts.`\r\n );\r\n }\r\n };\r\n\r\n getComponentInverseImpulseResponseWithRetry = async ({\r\n payload,\r\n mls,\r\n lowHz,\r\n highHz,\r\n componentIRGains,\r\n iirLength,\r\n componentIRFreqs,\r\n sampleRate,\r\n mlsAmplitude,\r\n irLength,\r\n calibrateSoundSmoothOctaves,\r\n calibrateSoundSmoothMinBandwidthHz,\r\n calibrateSoundBurstFilteredExtraDb,\r\n calibrateSoundIIRPhase\r\n }) => {\r\n let retryCount = 0;\r\n let response = null;\r\n\r\n while (retryCount < this.MAX_RETRY_COUNT) {\r\n try {\r\n response = await this.getComponentInverseImpulseResponse({\r\n payload,\r\n mls,\r\n lowHz,\r\n highHz,\r\n componentIRGains,\r\n iirLength,\r\n componentIRFreqs,\r\n sampleRate,\r\n mlsAmplitude,\r\n irLength,\r\n calibrateSoundSmoothOctaves,\r\n calibrateSoundSmoothMinBandwidthHz,\r\n calibrateSoundBurstFilteredExtraDb,\r\n calibrateSoundIIRPhase\r\n });\r\n // If the request is successful, break out of the loop\r\n break;\r\n } catch (error) {\r\n console.error(`Error occurred. Retrying... (${retryCount + 1}/${this.MAX_RETRY_COUNT})`);\r\n retryCount++;\r\n await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS));\r\n }\r\n }\r\n\r\n if (response) {\r\n return response;\r\n } else {\r\n throw new Error(\r\n `Failed to get inverse impulse response after ${this.MAX_RETRY_COUNT} attempts.`\r\n );\r\n }\r\n };\r\n\r\n getSystemInverseImpulseResponseWithRetry = async ({\r\n payload,\r\n mls,\r\n lowHz,\r\n highHz,\r\n iirLength,\r\n sampleRate,\r\n mlsAmplitude,\r\n calibrateSoundBurstFilteredExtraDb,\r\n calibrateSoundIIRPhase\r\n }) => {\r\n let retryCount = 0;\r\n let response = null;\r\n\r\n while (retryCount < this.MAX_RETRY_COUNT) {\r\n try {\r\n response = await this.getSystemInverseImpulseResponse({\r\n payload,\r\n mls,\r\n lowHz,\r\n highHz,\r\n iirLength,\r\n sampleRate,\r\n mlsAmplitude,\r\n calibrateSoundBurstFilteredExtraDb,\r\n calibrateSoundIIRPhase\r\n });\r\n // If the request is successful, break out of the loop\r\n break;\r\n } catch (error) {\r\n console.error(`Error occurred. Retrying... (${retryCount + 1}/${this.MAX_RETRY_COUNT})`);\r\n retryCount++;\r\n await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS));\r\n }\r\n }\r\n\r\n if (response) {\r\n return response;\r\n } else {\r\n throw new Error(\r\n `Failed to get inverse impulse response after ${this.MAX_RETRY_COUNT} attempts.`\r\n );\r\n }\r\n };\r\n\r\n getVolumeCalibration = async ({payload, sampleRate, lCalib}) => {\r\n const task = 'volume';\r\n let res = null;\r\n\r\n console.log({payload});\r\n\r\n const data = JSON.stringify({\r\n task,\r\n payload,\r\n 'sample-rate': sampleRate,\r\n lCalib,\r\n });\r\n\r\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\r\n method: 'post',\r\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\r\n url: `/task/${task}`,\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n data,\r\n })\r\n .then(response => {\r\n res = response;\r\n })\r\n .catch(error => {\r\n throw error;\r\n });\r\n\r\n return res.data[task];\r\n };\r\n\r\n getVolumeCalibrationParameters = async ({\r\n inDBValues,\r\n outDBSPLValues,\r\n lCalib,\r\n componentGainDBSPL,\r\n }) => {\r\n const task = 'volume-parameters';\r\n let res = null;\r\n\r\n const data = JSON.stringify({\r\n task,\r\n inDBValues,\r\n outDBSPLValues,\r\n lCalib,\r\n componentGainDBSPL,\r\n });\r\n\r\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\r\n method: 'post',\r\n baseURL: PythonServerAPI.PYTHON_SERVER_URL, //server\r\n url: `/task/${task}`,\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n data,\r\n })\r\n .then(response => {\r\n res = response;\r\n console.log(res.data[task]);\r\n })\r\n .catch(error => {\r\n throw error;\r\n });\r\n\r\n // console.log(res.data[task]);\r\n //below is an example of res.data[task]\r\n //{\r\n // R: 16.56981076554259,\r\n // RMSError: 1.9289162528535229\r\n // T: -47.79799120884434,\r\n // W: 61.0485247483732,\r\n // backgroundDBSPL: 43.88233142069752,\r\n // gainDBSPL: -128.24742161208985\r\n //}\r\n return res.data[task];\r\n };\r\n\r\n allHzPowerCheck = async ({\r\n payload, \r\n sampleRate, \r\n binDesiredSec,\r\n burstSec,\r\n repeats,\r\n warmUp\r\n }) => {\r\n const task = 'all-hz-check';\r\n let res = null;\r\n\r\n console.log({payload, \r\n sampleRate, \r\n binDesiredSec,\r\n burstSec,\r\n repeats,\r\n warmUp});\r\n\r\n const data = JSON.stringify({\r\n payload, \r\n sampleRate, \r\n binDesiredSec,\r\n burstSec,\r\n repeats,\r\n warmUp\r\n });\r\n\r\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\r\n method: 'post',\r\n baseURL: PythonServerAPI.PYTHON_SERVER_URL, //server\r\n url: `/task/${task}`,\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n data,\r\n })\r\n .then(response => {\r\n res = response;\r\n console.log(res.data[task]);\r\n })\r\n .catch(error => {\r\n throw error;\r\n });\r\n return res.data[task];\r\n };\r\n\r\n volumePowerCheck = async ({\r\n payload, \r\n sampleRate, \r\n preSec,\r\n Sec,\r\n binDesiredSec\r\n }) => {\r\n const task = 'volume-check';\r\n let res = null;\r\n\r\n const data = JSON.stringify({\r\n payload, \r\n sampleRate, \r\n preSec,\r\n Sec,\r\n binDesiredSec\r\n });\r\n\r\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\r\n method: 'post',\r\n baseURL: PythonServerAPI.PYTHON_SERVER_URL, //server\r\n url: `/task/${task}`,\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n data,\r\n })\r\n .then(response => {\r\n res = response;\r\n console.log(res.data[task]);\r\n })\r\n .catch(error => {\r\n throw error;\r\n });\r\n return res.data[task];\r\n };\r\n\r\n volumePowerCheckWithRetry = async ({\r\n payload, \r\n sampleRate, \r\n preSec,\r\n Sec,\r\n binDesiredSec\r\n }) => {\r\n let retryCount = 0;\r\n let response = null;\r\n\r\n while (retryCount < this.MAX_RETRY_COUNT) {\r\n try {\r\n response = await this.volumePowerCheck({\r\n payload, \r\n sampleRate, \r\n preSec,\r\n Sec,\r\n binDesiredSec});\r\n // If the request is successful, break out of the loop\r\n break;\r\n } catch (error) {\r\n console.error(`Error occurred. Retrying... (${retryCount + 1}/${this.MAX_RETRY_COUNT})`);\r\n retryCount++;\r\n await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS));\r\n }\r\n }\r\n\r\n if (response) {\r\n return response;\r\n } else {\r\n throw new Error(`Failed to get volume power check after ${this.MAX_RETRY_COUNT} attempts.`);\r\n }\r\n };\r\n}\r\n\r\n/* harmony default export */ __webpack_exports__[\"default\"] = (PythonServerAPI);\r\n\n\n//# sourceURL=webpack://speakerCalibrator/./src/server/PythonServerAPI.js?");
|
|
483
483
|
|
|
484
484
|
/***/ }),
|
|
485
485
|
|
|
@@ -490,7 +490,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var axio
|
|
|
490
490
|
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
491
491
|
|
|
492
492
|
"use strict";
|
|
493
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _audioRecorder__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./audioRecorder */ \"./src/tasks/audioRecorder.js\");\n/* harmony import */ var _server_PythonServerAPI__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../server/PythonServerAPI */ \"./src/server/PythonServerAPI.js\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../utils */ \"./src/utils.js\");\n/* eslint-disable no-await-in-loop */\n\n\n\n\n/**\n * .\n * .\n * .\n * Provides methods for calibrating the user's speakers\n *\n * @extends AudioRecorder\n */\nclass AudioCalibrator extends _audioRecorder__WEBPACK_IMPORTED_MODULE_0__[\"default\"] {\n /**\n *\n * @param numCaptures\n * @param numMLSPerCapture\n * @example\n */\n constructor(numCaptures = 1, numMLSPerCapture = 1) {\n super();\n this.numCaptures = numCaptures;\n this.numMLSPerCapture = numMLSPerCapture;\n this.pyServerAPI = new _server_PythonServerAPI__WEBPACK_IMPORTED_MODULE_1__[\"default\"]();\n }\n\n /** @private */\n isCalibrating = false;\n\n /** @private */\n sourceAudioContext;\n\n /** @private */\n sourceAudioContextConvolved;\n\n /** @protected */\n numCalibratingRounds = 1;\n\n /** @protected */\n numSuccessfulCaptured = 0;\n\n /** @private */\n sourceSamplingRate;\n\n /** @protected */\n calibrationNodes = [];\n\n /** @protected */\n calibrationNodesConvolved = [];\n\n /** @protected */\n localAudio;\n\n /** @private */\n startTime;\n\n numCalibratingRoundsCompleted=0;\n /**\n * Called when a call is received.\n * Creates a local audio DOM element and attaches it to the page.\n *\n * @param targetElement\n * @example\n */\n createLocalAudio = targetElement => {\n this.localAudio = document.createElement('audio');\n this.localAudio.setAttribute('id', 'localAudio');\n targetElement.appendChild(this.localAudio);\n };\n\n addTimeStamp = taskName => {\n let startTaskTime = (new Date().getTime() - this.startTime) / 1000;\n this.timeStamp.push(`SOUND ${Number(startTaskTime.toFixed(1))} s. ${taskName}`);\n };\n\n recordBackground = async (\n stream,\n loopCondition = () => false,\n duringRecord = async () => {},\n afterRecord = async () => {},\n mode,\n checkRec\n ) => {\n console.warn('before recording background noise');\n // calibration loop\n while (loopCondition()) {\n // start recording\n console.warn('startRecording');\n await this.startRecording(stream);\n\n // do something during the recording such as sleep n amount of time\n console.warn('duringRecord');\n await duringRecord();\n\n // when done, stop recording\n console.warn('stopRecording');\n await this.stopRecording(mode, checkRec);\n\n // do something after recording such as start processing values\n console.warn('afterRecord');\n await afterRecord();\n\n // eslint-disable-next-line no-await-in-loop\n await (0,_utils__WEBPACK_IMPORTED_MODULE_2__.sleep)(1);\n }\n };\n\n /**\n *\n * @param {MediaStream} stream\n * @param {Function} playCalibrationAudio - (async) function that plays the calibration audio\n * @param {*} beforePlay - (async) function that is called before playing the audio\n * @param {*} beforeRecord - (async) function that is called before recording\n * @param {*} duringRecord - (async) function that is called while recording\n * @param {*} afterRecord - (async) function that is called after recording\n * @example\n */\n calibrationSteps = async (\n stream,\n playCalibrationAudio,\n beforePlay = async () => {},\n beforeRecord = async () => {},\n loopCondition = () => false,\n duringRecord = async () => {},\n afterRecord = async () => {},\n mode,\n checkRec\n ) => {\n // if it finished 2 attempts, it move to next iteration so reset numSuccessfulCaptured\n if (this.numSuccessfulCaptured >=2) {\n this.numSuccessfulCaptured = 0;\n }\n\n // do something before playing such as using the MLS to fill the buffers\n console.warn('beforePlay');\n await beforePlay();\n\n // play calibration audio\n console.warn('playCalibrationAudio');\n playCalibrationAudio();\n\n // do something before recording such as awaiting a certain amount of time\n console.warn('beforeRecord');\n await beforeRecord();\n const totalSec = this._calibrateSoundBurstPreSec + (this.numMLSPerCapture - this.num_mls_to_skip) * this._calibrateSoundBurstSec + this._calibrateSoundBurstPostSec;\n this.addTimeStamp(`Record ${totalSec.toFixed(1)} s of MLS with speaker+microphone IIR.`);\n\n // calibration loop\n while (loopCondition()) {\n if (this.isCalibrating) break;\n // start recording\n console.warn('startRecording');\n await this.startRecording(stream);\n\n if (this.isCalibrating) break;\n // do something during the recording such as sleep n amount of time\n console.warn('duringRecord');\n await duringRecord();\n\n if (this.isCalibrating) break;\n // when done, stop recording\n console.warn('stopRecording');\n await this.stopRecording(mode, checkRec);\n\n if (this.isCalibrating) break;\n // do something after recording such as start processing values\n console.warn('afterRecord');\n await afterRecord();\n\n // eslint-disable-next-line no-await-in-loop\n await (0,_utils__WEBPACK_IMPORTED_MODULE_2__.sleep)(1);\n }\n };\n\n /**\n *\n * @param {MediaStream} stream\n * @param {Function} playCalibrationAudio - (async) function that plays the calibration audio\n * @param {*} beforeRecord - (async) function that is called before recording\n * @param {*} afterRecord - (async) function that is called after recording\n * @param {Number} gainValue - the gain value to set the gain node to\n */\n volumeCalibrationSteps = async (\n stream,\n playCalibrationAudio,\n beforeRecord = () => {},\n afterRecord = () => {},\n gainValue,\n lCalib = 104.92978421490648,\n checkRec,\n checkSD,\n maxSD\n ) => {\n this.numCalibratingRoundsCompleted = 0;\n this.numCalibratingRounds = 2;\n // calibration loop\n while (!this.isCalibrating && this.numCalibratingRoundsCompleted < this.numCalibratingRounds) {\n if (this.isCalibrating) break;\n // before recording\n await beforeRecord(gainValue);\n if (this.isCalibrating) break;\n // start recording\n await this.startRecording(stream);\n if (this.isCalibrating) break;\n // play calibration audio\n console.log(`Calibration Round ${this.numCalibratingRoundsCompleted}`);\n await playCalibrationAudio();\n if (this.isCalibrating) break;\n // when done, stop recording\n console.log('Calibration Round Complete');\n await this.stopRecording('volume', checkRec);\n if (this.isCalibrating) break;\n // after recording\n await afterRecord(lCalib);\n const sd = await checkSD() || Infinity;\n if (sd <= maxSD) {\n console.log(`SD =${sd}, less than calibrateSound1000HzMaxSD_dB=${maxSD}`);\n this.numCalibratingRoundsCompleted += 2;\n } else {\n // if exist the maxSD do it one more time and only one more time\n console.log(`SD =${sd}, greater than calibrateSound1000HzMaxSD_dB=${maxSD}`);\n this.numCalibratingRoundsCompleted += 1;\n }\n this.calibrationNodes = [];\n\n // eslint-disable-next-line no-await-in-loop\n await (0,_utils__WEBPACK_IMPORTED_MODULE_2__.sleep)(2);\n }\n };\n\n /**\n * Getter for the isCalibrating property.\n *\n * @public\n * @returns - True if the audio is being calibrated, false otherwise.\n * @example\n */\n getCalibrationStatus = () => this.isCalibrating;\n\n /** .\n * .\n * .\n * Set the sampling rate to the value received from the listener\n *\n * @param {*} sinkSamplingRate\n * @param samplingRate\n * @example\n */\n setSamplingRates = samplingRate => {\n this.sinkSamplingRate = samplingRate;\n this.sourceSamplingRate = samplingRate;\n\n // this.emit('update', {message: `sampling at ${samplingRate}Hz...`});\n };\n\n setSampleSize = sampleSize => {\n this.sampleSize = sampleSize;\n };\n\n setFlags = flags => {\n this.flags = flags;\n }\n\n sampleRatesSet = () => this.sourceSamplingRate && this.sinkSamplingRate;\n\n addCalibrationNode = node => {\n this.calibrationNodes.push(node);\n };\n\n addCalibrationNodeConvolved = node => {\n this.calibrationNodesConvolved.push(node);\n };\n\n makeNewSourceAudioContext = () => {\n const options = {\n sampleRate: this.sourceSamplingRate,\n };\n\n this.sourceAudioContext = new (window.AudioContext ||\n window.webkitAudioContext ||\n window.audioContext)(options);\n\n return this.sourceAudioContext;\n };\n\n makeNewSourceAudioContextConvolved = () => {\n const options = {\n sampleRate: this.sourceSamplingRate,\n };\n\n this.sourceAudioContextConvolved = new (window.AudioContext ||\n window.webkitAudioContext ||\n window.audioContext)(options);\n\n return this.sourceAudioContextConvolved;\n };\n\n /** .\n * .\n * .\n * Download the result of the calibration roudns\n *\n * @example\n */\n downloadData = () => {\n const recordings = this.getAllRecordedSignals();\n const i = recordings.length - 1;\n (0,_utils__WEBPACK_IMPORTED_MODULE_2__.saveToCSV)(recordings[i], `recordedMLSignal_${i}_unconvolved.csv`);\n };\n downloadSingleUnfilteredRecording = () => {\n const recordings = this.getAllUnfilteredRecordedSignals();\n (0,_utils__WEBPACK_IMPORTED_MODULE_2__.saveToCSV)(recordings[recordings.length - 1], `recordedMLSignal_unconvolved.csv`);\n };\n downloadSingleFilteredRecording = () => {\n const recordings = this.getAllFilteredRecordedSignals();\n console.log('Single filtered recording should be of length: ' + recordings[0].length);\n (0,_utils__WEBPACK_IMPORTED_MODULE_2__.saveToCSV)(recordings[0], `recordedMLSignal_convolved.csv`);\n };\n downloadUnfilteredRecordings = () => {\n const recordings = this.getAllRecordedSignals();\n console.log('unfilterd download?');\n for (let i = 0; i < recordings.length; i++) {\n console.log(i);\n (0,_utils__WEBPACK_IMPORTED_MODULE_2__.saveToCSV)(recordings[i], `recordedMLSignal_${i}_unconvolved.csv`);\n }\n };\n downloadFilteredRecordings = () => {\n const recordings = this.getAllFilteredRecordedSignals();\n for (let i = 0; i < recordings.length; i++) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_2__.saveToCSV)(recordings[i], `recordedMLSignal_${i}_convolved.csv`);\n }\n };\n}\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (AudioCalibrator);\n\n\n//# sourceURL=webpack://speakerCalibrator/./src/tasks/audioCalibrator.js?");
|
|
493
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _audioRecorder__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./audioRecorder */ \"./src/tasks/audioRecorder.js\");\n/* harmony import */ var _server_PythonServerAPI__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../server/PythonServerAPI */ \"./src/server/PythonServerAPI.js\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../utils */ \"./src/utils.js\");\n/* eslint-disable no-await-in-loop */\r\n\r\n\r\n\r\n\r\n/**\r\n * .\r\n * .\r\n * .\r\n * Provides methods for calibrating the user's speakers\r\n *\r\n * @extends AudioRecorder\r\n */\r\nclass AudioCalibrator extends _audioRecorder__WEBPACK_IMPORTED_MODULE_0__[\"default\"] {\r\n /**\r\n *\r\n * @param numCaptures\r\n * @param numMLSPerCapture\r\n * @example\r\n */\r\n constructor(numCaptures = 1, numMLSPerCapture = 1) {\r\n super();\r\n this.numCaptures = numCaptures;\r\n this.numMLSPerCapture = numMLSPerCapture;\r\n this.pyServerAPI = new _server_PythonServerAPI__WEBPACK_IMPORTED_MODULE_1__[\"default\"]();\r\n }\r\n\r\n /** @private */\r\n isCalibrating = false;\r\n\r\n /** @private */\r\n sourceAudioContext;\r\n\r\n /** @private */\r\n sourceAudioContextConvolved;\r\n\r\n /** @protected */\r\n numCalibratingRounds = 1;\r\n\r\n /** @protected */\r\n numSuccessfulCaptured = 0;\r\n\r\n /** @private */\r\n sourceSamplingRate;\r\n\r\n /** @protected */\r\n calibrationNodes = [];\r\n\r\n /** @protected */\r\n calibrationNodesConvolved = [];\r\n\r\n /** @protected */\r\n localAudio;\r\n\r\n /** @private */\r\n startTime;\r\n\r\n numCalibratingRoundsCompleted=0;\r\n /**\r\n * Called when a call is received.\r\n * Creates a local audio DOM element and attaches it to the page.\r\n *\r\n * @param targetElement\r\n * @example\r\n */\r\n createLocalAudio = targetElement => {\r\n this.localAudio = document.createElement('audio');\r\n this.localAudio.setAttribute('id', 'localAudio');\r\n targetElement.appendChild(this.localAudio);\r\n };\r\n\r\n addTimeStamp = taskName => {\r\n let startTaskTime = (new Date().getTime() - this.startTime) / 1000;\r\n this.timeStamp.push(`SOUND ${Number(startTaskTime.toFixed(1))} s. ${taskName}`);\r\n };\r\n\r\n recordBackground = async (\r\n stream,\r\n loopCondition = () => false,\r\n duringRecord = async () => {},\r\n afterRecord = async () => {},\r\n mode,\r\n checkRec\r\n ) => {\r\n console.warn('before recording background noise');\r\n // calibration loop\r\n while (loopCondition()) {\r\n // start recording\r\n console.warn('startRecording');\r\n await this.startRecording(stream);\r\n\r\n // do something during the recording such as sleep n amount of time\r\n console.warn('duringRecord');\r\n await duringRecord();\r\n\r\n // when done, stop recording\r\n console.warn('stopRecording');\r\n await this.stopRecording(mode, checkRec);\r\n\r\n // do something after recording such as start processing values\r\n console.warn('afterRecord');\r\n await afterRecord();\r\n\r\n // eslint-disable-next-line no-await-in-loop\r\n await (0,_utils__WEBPACK_IMPORTED_MODULE_2__.sleep)(1);\r\n }\r\n };\r\n\r\n /**\r\n *\r\n * @param {MediaStream} stream\r\n * @param {Function} playCalibrationAudio - (async) function that plays the calibration audio\r\n * @param {*} beforePlay - (async) function that is called before playing the audio\r\n * @param {*} beforeRecord - (async) function that is called before recording\r\n * @param {*} duringRecord - (async) function that is called while recording\r\n * @param {*} afterRecord - (async) function that is called after recording\r\n * @example\r\n */\r\n calibrationSteps = async (\r\n stream,\r\n playCalibrationAudio,\r\n beforePlay = async () => {},\r\n beforeRecord = async () => {},\r\n loopCondition = () => false,\r\n duringRecord = async () => {},\r\n afterRecord = async () => {},\r\n mode,\r\n checkRec\r\n ) => {\r\n // if it finished 2 attempts, it move to next iteration so reset numSuccessfulCaptured\r\n if (this.numSuccessfulCaptured >=2) {\r\n this.numSuccessfulCaptured = 0;\r\n }\r\n\r\n // do something before playing such as using the MLS to fill the buffers\r\n console.warn('beforePlay');\r\n await beforePlay();\r\n\r\n // play calibration audio\r\n console.warn('playCalibrationAudio');\r\n playCalibrationAudio();\r\n\r\n // do something before recording such as awaiting a certain amount of time\r\n console.warn('beforeRecord');\r\n await beforeRecord();\r\n const totalSec = this._calibrateSoundBurstPreSec + (this.numMLSPerCapture - this.num_mls_to_skip) * this._calibrateSoundBurstSec + this._calibrateSoundBurstPostSec;\r\n this.addTimeStamp(`Record ${totalSec.toFixed(1)} s of MLS with speaker+microphone IIR.`);\r\n\r\n // calibration loop\r\n while (loopCondition()) {\r\n if (this.isCalibrating) break;\r\n // start recording\r\n console.warn('startRecording');\r\n await this.startRecording(stream);\r\n\r\n if (this.isCalibrating) break;\r\n // do something during the recording such as sleep n amount of time\r\n console.warn('duringRecord');\r\n await duringRecord();\r\n\r\n if (this.isCalibrating) break;\r\n // when done, stop recording\r\n console.warn('stopRecording');\r\n await this.stopRecording(mode, checkRec);\r\n\r\n if (this.isCalibrating) break;\r\n // do something after recording such as start processing values\r\n console.warn('afterRecord');\r\n await afterRecord();\r\n\r\n // eslint-disable-next-line no-await-in-loop\r\n await (0,_utils__WEBPACK_IMPORTED_MODULE_2__.sleep)(1);\r\n }\r\n };\r\n\r\n /**\r\n *\r\n * @param {MediaStream} stream\r\n * @param {Function} playCalibrationAudio - (async) function that plays the calibration audio\r\n * @param {*} beforeRecord - (async) function that is called before recording\r\n * @param {*} afterRecord - (async) function that is called after recording\r\n * @param {Number} gainValue - the gain value to set the gain node to\r\n */\r\n volumeCalibrationSteps = async (\r\n stream,\r\n playCalibrationAudio,\r\n beforeRecord = () => {},\r\n afterRecord = () => {},\r\n gainValue,\r\n lCalib = 104.92978421490648,\r\n checkRec,\r\n checkSD,\r\n maxSD\r\n ) => {\r\n this.numCalibratingRoundsCompleted = 0;\r\n this.numCalibratingRounds = 2;\r\n // calibration loop\r\n while (!this.isCalibrating && this.numCalibratingRoundsCompleted < this.numCalibratingRounds) {\r\n if (this.isCalibrating) break;\r\n // before recording\r\n await beforeRecord(gainValue);\r\n if (this.isCalibrating) break;\r\n // start recording\r\n await this.startRecording(stream);\r\n if (this.isCalibrating) break;\r\n // play calibration audio\r\n console.log(`Calibration Round ${this.numCalibratingRoundsCompleted}`);\r\n await playCalibrationAudio();\r\n if (this.isCalibrating) break;\r\n // when done, stop recording\r\n console.log('Calibration Round Complete');\r\n await this.stopRecording('volume', checkRec);\r\n if (this.isCalibrating) break;\r\n // after recording\r\n await afterRecord(lCalib);\r\n const sd = await checkSD() || Infinity;\r\n if (sd <= maxSD) {\r\n console.log(`SD =${sd}, less than calibrateSound1000HzMaxSD_dB=${maxSD}`);\r\n this.numCalibratingRoundsCompleted += 2;\r\n } else {\r\n // if exist the maxSD do it one more time and only one more time\r\n console.log(`SD =${sd}, greater than calibrateSound1000HzMaxSD_dB=${maxSD}`);\r\n this.numCalibratingRoundsCompleted += 1;\r\n }\r\n this.calibrationNodes = [];\r\n\r\n // eslint-disable-next-line no-await-in-loop\r\n await (0,_utils__WEBPACK_IMPORTED_MODULE_2__.sleep)(2);\r\n }\r\n };\r\n\r\n /**\r\n * Getter for the isCalibrating property.\r\n *\r\n * @public\r\n * @returns - True if the audio is being calibrated, false otherwise.\r\n * @example\r\n */\r\n getCalibrationStatus = () => this.isCalibrating;\r\n\r\n /** .\r\n * .\r\n * .\r\n * Set the sampling rate to the value received from the listener\r\n *\r\n * @param {*} sinkSamplingRate\r\n * @param samplingRate\r\n * @example\r\n */\r\n setSamplingRates = samplingRate => {\r\n this.sinkSamplingRate = samplingRate;\r\n this.sourceSamplingRate = samplingRate;\r\n\r\n // this.emit('update', {message: `sampling at ${samplingRate}Hz...`});\r\n };\r\n\r\n setSampleSize = sampleSize => {\r\n this.sampleSize = sampleSize;\r\n };\r\n\r\n setFlags = flags => {\r\n this.flags = flags;\r\n }\r\n\r\n sampleRatesSet = () => this.sourceSamplingRate && this.sinkSamplingRate;\r\n\r\n addCalibrationNode = node => {\r\n this.calibrationNodes.push(node);\r\n };\r\n\r\n addCalibrationNodeConvolved = node => {\r\n this.calibrationNodesConvolved.push(node);\r\n };\r\n\r\n makeNewSourceAudioContext = () => {\r\n const options = {\r\n sampleRate: this.sourceSamplingRate,\r\n };\r\n\r\n this.sourceAudioContext = new (window.AudioContext ||\r\n window.webkitAudioContext ||\r\n window.audioContext)(options);\r\n\r\n return this.sourceAudioContext;\r\n };\r\n\r\n makeNewSourceAudioContextConvolved = () => {\r\n const options = {\r\n sampleRate: this.sourceSamplingRate,\r\n };\r\n\r\n this.sourceAudioContextConvolved = new (window.AudioContext ||\r\n window.webkitAudioContext ||\r\n window.audioContext)(options);\r\n\r\n return this.sourceAudioContextConvolved;\r\n };\r\n\r\n /** .\r\n * .\r\n * .\r\n * Download the result of the calibration roudns\r\n *\r\n * @example\r\n */\r\n downloadData = () => {\r\n const recordings = this.getAllRecordedSignals();\r\n const i = recordings.length - 1;\r\n (0,_utils__WEBPACK_IMPORTED_MODULE_2__.saveToCSV)(recordings[i], `recordedMLSignal_${i}_unconvolved.csv`);\r\n };\r\n downloadSingleUnfilteredRecording = () => {\r\n const recordings = this.getAllUnfilteredRecordedSignals();\r\n (0,_utils__WEBPACK_IMPORTED_MODULE_2__.saveToCSV)(recordings[recordings.length - 1], `recordedMLSignal_unconvolved.csv`);\r\n };\r\n downloadSingleFilteredRecording = () => {\r\n const recordings = this.getAllFilteredRecordedSignals();\r\n console.log('Single filtered recording should be of length: ' + recordings[0].length);\r\n (0,_utils__WEBPACK_IMPORTED_MODULE_2__.saveToCSV)(recordings[0], `recordedMLSignal_convolved.csv`);\r\n };\r\n downloadUnfilteredRecordings = () => {\r\n const recordings = this.getAllRecordedSignals();\r\n console.log('unfilterd download?');\r\n for (let i = 0; i < recordings.length; i++) {\r\n console.log(i);\r\n (0,_utils__WEBPACK_IMPORTED_MODULE_2__.saveToCSV)(recordings[i], `recordedMLSignal_${i}_unconvolved.csv`);\r\n }\r\n };\r\n downloadFilteredRecordings = () => {\r\n const recordings = this.getAllFilteredRecordedSignals();\r\n for (let i = 0; i < recordings.length; i++) {\r\n (0,_utils__WEBPACK_IMPORTED_MODULE_2__.saveToCSV)(recordings[i], `recordedMLSignal_${i}_convolved.csv`);\r\n }\r\n };\r\n}\r\n\r\n/* harmony default export */ __webpack_exports__[\"default\"] = (AudioCalibrator);\r\n\n\n//# sourceURL=webpack://speakerCalibrator/./src/tasks/audioCalibrator.js?");
|
|
494
494
|
|
|
495
495
|
/***/ }),
|
|
496
496
|
|
|
@@ -501,7 +501,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _aud
|
|
|
501
501
|
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
502
502
|
|
|
503
503
|
"use strict";
|
|
504
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _myEventEmitter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../myEventEmitter */ \"./src/myEventEmitter.js\");\n\n\n/**\n * @class provides a simple interface for recording audio from a microphone\n * using the Media Recorder API.\n */\nclass AudioRecorder extends _myEventEmitter__WEBPACK_IMPORTED_MODULE_0__[\"default\"] {\n /** @private */\n #mediaRecorder;\n\n /** @private */\n #recordedChunks = [];\n\n /** @private */\n #audioBlob;\n\n /** @private */\n #audioContext;\n\n /** @private */\n #recordedSignals = [];\n\n /**@private */\n #allHzUnfilteredRecordings = [];\n\n /**@private */\n #allBackgroundRecordings = [];\n\n /** @private */\n #allHzFilteredRecordings = [];\n\n /** @private */\n sinkSamplingRate;\n\n /** @private */\n sampleSize;\n\n /** @private */\n #allVolumeRecordings = [];\n\n /** @private */\n flags = {};\n\n /**\n * Decode the audio data from the recorded audio blob.\n *\n * @private\n * @example\n */\n #saveRecording = async (mode, checkRec) => {\n const arrayBuffer = await this.#audioBlob.arrayBuffer();\n const audioBuffer = await this.#audioContext.decodeAudioData(arrayBuffer);\n console.log(audioBuffer);\n const data = audioBuffer.getChannelData(0);\n const dataArray = Array.from(data);\n\n console.log(`Decoded audio buffer with ${data.length} samples`);\n console.log(`Unfiltered recording should be of length: ${data.length}`);\n if (checkRec == 'loudest') {\n const uniqueSet = new Set(dataArray);\n const numberOfUniqueValues = uniqueSet.size;\n const squaredValues = dataArray.map(value => value * value);\n const sum_of_squares = squaredValues.reduce((total, value) => total + value, 0);\n const squared_mean = sum_of_squares / dataArray.length;\n const dbLevel = 20 * Math.log10(Math.sqrt(squared_mean));\n const roundedDbLevel = Math.round(dbLevel * 10) / 10;\n console.log(\n 'Loudest 1000-Hz recording: ' +\n roundedDbLevel +\n ' dB with ' +\n numberOfUniqueValues +\n ' unique values.'\n );\n } else if (checkRec == 'allhz') {\n const uniqueSet = new Set(dataArray);\n const numberOfUniqueValues = uniqueSet.size;\n const squaredValues = dataArray.map(value => value * value);\n const sum_of_squares = squaredValues.reduce((total, value) => total + value, 0);\n const squared_mean = sum_of_squares / dataArray.length;\n const dbLevel = 20 * Math.log10(Math.sqrt(squared_mean));\n const roundedDbLevel = Math.round(dbLevel * 10) / 10;\n console.log(\n 'All Hz Recording: ' +\n roundedDbLevel +\n ' dB with ' +\n numberOfUniqueValues +\n ' unique values.'\n );\n }\n if (mode === 'volume'){\n console.log('Saving 1000 Hz Recording to #allVolumeRecordings')\n this.#allVolumeRecordings.push(dataArray);\n }else if (mode ==='unfiltered'){\n console.log('Saving unfiltered all Hz recording to #allHzUnfilteredRecordings')\n this.#allHzUnfilteredRecordings.push(dataArray);\n }else if (mode ==='filtered'){\n console.log('Saving filtered all hz recording to #allHzFilteredRecordings')\n this.#allHzFilteredRecordings.push(dataArray);\n }else if (mode ==='background'){\n console.log('Saving background recording to #allBackgroundRecordings')\n this.#allBackgroundRecordings.push(dataArray);\n }\n\n };\n\n #saveFilteredRecording = async () => {\n const arrayBuffer = await this.#audioBlob.arrayBuffer();\n const audioBuffer = await this.#audioContext.decodeAudioData(arrayBuffer);\n const data = audioBuffer.getChannelData(0);\n\n console.log(`Decoded audio buffer with ${data.length} samples`);\n console.log(`Filtered recording should be of length: ${data.length}`);\n this.#allHzFilteredRecordings.push(Array.from(data));\n };\n\n /**\n * Event listener triggered when data is available in the media recorder.\n *\n * @private\n * @param e - The event object.\n * @example\n */\n #onRecorderDataAvailable = e => {\n if (e.data && e.data.size > 0) this.#recordedChunks.push(e.data);\n };\n\n /**\n * Method to create a media recorder object and set up event listeners.\n *\n * @private\n * @param stream - The stream of audio from the Listener.\n * @example\n */\n #setMediaRecorder = stream => {\n // Create a new MediaRecorder object\n this.#mediaRecorder = new MediaRecorder(stream);\n\n // Add event listeners\n this.#mediaRecorder.ondataavailable = e => this.#onRecorderDataAvailable(e);\n };\n\n #setAudioContext = () => {\n this.#audioContext = new (window.AudioContext ||\n window.webkitAudioContext ||\n window.audioContext)({\n sampleRate: this.sinkSamplingRate,\n sampleSize: this.sampleSize,\n //sampleRate: 96000\n });\n };\n\n /**\n * Public method to start the recording process.\n *\n * @param stream - The stream of audio from the Listener.\n * @example\n */\n startRecording = async stream => {\n try {\n // Create a fresh audio context\n this.#setAudioContext();\n // Set up media recorder if needed\n if (!this.#mediaRecorder) this.#setMediaRecorder(stream);\n // clear recorded chunks\n this.#recordedChunks = [];\n // start recording\n this.#mediaRecorder.start();\n } catch (error) {\n console.error('Error in startRecording:', error);\n // Handle the error as needed, e.g., throw it or perform error-specific actions\n }\n };\n\n /**\n * Method to stop the recording process.\n *\n * @public\n * @example\n */\n stopRecording = async (mode, checkRec) => {\n try {\n // Stop the media recorder, and wait for the data to be available\n await new Promise(resolve => {\n this.#mediaRecorder.onstop = () => {\n // when the stop event is triggered, resolve the promise\n this.#audioBlob = new Blob(this.#recordedChunks, {\n type: 'audio/wav; codecs=opus',\n });\n resolve(this.#audioBlob);\n };\n // call stop\n this.#mediaRecorder.stop();\n });\n // Now that we have data, save it\n await this.#saveRecording(mode, checkRec);\n } catch (error) {\n console.error('Error in stopRecording:', error);\n // Handle the error as needed, e.g., throw it or perform error-specific actions\n }\n };\n\n /** .\n * .\n * .\n * Public method to get the last recorded audio signal\n *\n * @returns\n * @example\n */\n getLastRecordedSignal = () => this.#recordedSignals[this.#recordedSignals.length - 1];\n\n /** .\n * .\n * .\n * Public method to get the last 1000hz recorded audio signal\n *\n * @returns\n * @example\n */\n getLastVolumeRecordedSignal = () => Array.from(this.#allVolumeRecordings[this.#allVolumeRecordings.length - 1]);\n\n /** .\n * .\n * .\n * Public method to get all the recorded audio signals\n *\n * @returns\n * @example\n */\n getAllRecordedSignals = () => this.#recordedSignals;\n\n /** .\n * .\n * .\n * Public method to get all the recorded audio signals\n *\n * @returns\n * @example\n */\n getAllVolumeRecordedSignals = () => this.#allVolumeRecordings;\n\n /** .\n * .\n * .\n * Public method to get all the recorded audio signals\n *\n * @returns\n * @example\n */\n getAllFilteredRecordedSignals = () => this.#allHzFilteredRecordings;\n\n /** .\n * .\n * .\n * Public method to get all the recorded audio signals\n *\n * @returns\n * @example\n */\n clearAllFilteredRecordedSignals = () => this.#allHzFilteredRecordings = [];\n\n /** .\n * .\n * .\n * Public method to clear last the recorded audio signals\n *\n * @returns\n * @example\n */\n clearLastFilteredRecordedSignals = () => this.#allHzFilteredRecordings.pop();\n\n /** .\n * .\n * .\n * Public method to get all the recorded audio signals for psd\n *\n * @returns\n * @example\n */\n getAllUnfilteredRecordedSignals = () => this.#allHzUnfilteredRecordings;\n\n /** .\n * .\n * .\n * Public method to get all the recorded audio signals\n *\n * @returns\n * @example\n */\n clearLastUnfilteredRecordedSignals = () => this.#allHzUnfilteredRecordings.pop();\n\n /** .\n * .\n * .\n * Public method to get all the recorded audio signals for psd\n *\n * @returns\n * @example\n */\n getAllBackgroundRecordings = () => this.#allBackgroundRecordings;\n\n /** .\n * .\n * .\n * Public method to set the sampling rate used by the capture device\n *\n * @param {Number} sinkSamplingRate - The sampling rate of the capture device\n * @example\n */\n setSinkSamplingRate = sinkSamplingRate => {\n this.sinkSamplingRate = sinkSamplingRate;\n };\n}\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (AudioRecorder);\n\n\n//# sourceURL=webpack://speakerCalibrator/./src/tasks/audioRecorder.js?");
|
|
504
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _myEventEmitter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../myEventEmitter */ \"./src/myEventEmitter.js\");\n\r\n\r\n/**\r\n * @class provides a simple interface for recording audio from a microphone\r\n * using the Media Recorder API.\r\n */\r\nclass AudioRecorder extends _myEventEmitter__WEBPACK_IMPORTED_MODULE_0__[\"default\"] {\r\n /** @private */\r\n #mediaRecorder;\r\n\r\n /** @private */\r\n #recordedChunks = [];\r\n\r\n /** @private */\r\n #audioBlob;\r\n\r\n /** @private */\r\n #audioContext;\r\n\r\n /** @private */\r\n #recordedSignals = [];\r\n\r\n /**@private */\r\n #allHzUnfilteredRecordings = [];\r\n\r\n /**@private */\r\n #allBackgroundRecordings = [];\r\n\r\n /** @private */\r\n #allHzFilteredRecordings = [];\r\n\r\n /** @private */\r\n sinkSamplingRate;\r\n\r\n /** @private */\r\n sampleSize;\r\n\r\n /** @private */\r\n #allVolumeRecordings = [];\r\n\r\n /** @private */\r\n flags = {};\r\n\r\n /**\r\n * Decode the audio data from the recorded audio blob.\r\n *\r\n * @private\r\n * @example\r\n */\r\n #saveRecording = async (mode, checkRec) => {\r\n const arrayBuffer = await this.#audioBlob.arrayBuffer();\r\n const audioBuffer = await this.#audioContext.decodeAudioData(arrayBuffer);\r\n console.log(audioBuffer);\r\n const data = audioBuffer.getChannelData(0);\r\n const dataArray = Array.from(data);\r\n\r\n console.log(`Decoded audio buffer with ${data.length} samples`);\r\n console.log(`Unfiltered recording should be of length: ${data.length}`);\r\n if (checkRec == 'loudest') {\r\n const uniqueSet = new Set(dataArray);\r\n const numberOfUniqueValues = uniqueSet.size;\r\n const squaredValues = dataArray.map(value => value * value);\r\n const sum_of_squares = squaredValues.reduce((total, value) => total + value, 0);\r\n const squared_mean = sum_of_squares / dataArray.length;\r\n const dbLevel = 20 * Math.log10(Math.sqrt(squared_mean));\r\n const roundedDbLevel = Math.round(dbLevel * 10) / 10;\r\n console.log(\r\n 'Loudest 1000-Hz recording: ' +\r\n roundedDbLevel +\r\n ' dB with ' +\r\n numberOfUniqueValues +\r\n ' unique values.'\r\n );\r\n } else if (checkRec == 'allhz') {\r\n const uniqueSet = new Set(dataArray);\r\n const numberOfUniqueValues = uniqueSet.size;\r\n const squaredValues = dataArray.map(value => value * value);\r\n const sum_of_squares = squaredValues.reduce((total, value) => total + value, 0);\r\n const squared_mean = sum_of_squares / dataArray.length;\r\n const dbLevel = 20 * Math.log10(Math.sqrt(squared_mean));\r\n const roundedDbLevel = Math.round(dbLevel * 10) / 10;\r\n console.log(\r\n 'All Hz Recording: ' +\r\n roundedDbLevel +\r\n ' dB with ' +\r\n numberOfUniqueValues +\r\n ' unique values.'\r\n );\r\n }\r\n if (mode === 'volume'){\r\n console.log('Saving 1000 Hz Recording to #allVolumeRecordings')\r\n this.#allVolumeRecordings.push(dataArray);\r\n }else if (mode ==='unfiltered'){\r\n console.log('Saving unfiltered all Hz recording to #allHzUnfilteredRecordings')\r\n this.#allHzUnfilteredRecordings.push(dataArray);\r\n }else if (mode ==='filtered'){\r\n console.log('Saving filtered all hz recording to #allHzFilteredRecordings')\r\n this.#allHzFilteredRecordings.push(dataArray);\r\n }else if (mode ==='background'){\r\n console.log('Saving background recording to #allBackgroundRecordings')\r\n this.#allBackgroundRecordings.push(dataArray);\r\n }\r\n\r\n };\r\n\r\n #saveFilteredRecording = async () => {\r\n const arrayBuffer = await this.#audioBlob.arrayBuffer();\r\n const audioBuffer = await this.#audioContext.decodeAudioData(arrayBuffer);\r\n const data = audioBuffer.getChannelData(0);\r\n\r\n console.log(`Decoded audio buffer with ${data.length} samples`);\r\n console.log(`Filtered recording should be of length: ${data.length}`);\r\n this.#allHzFilteredRecordings.push(Array.from(data));\r\n };\r\n\r\n /**\r\n * Event listener triggered when data is available in the media recorder.\r\n *\r\n * @private\r\n * @param e - The event object.\r\n * @example\r\n */\r\n #onRecorderDataAvailable = e => {\r\n if (e.data && e.data.size > 0) this.#recordedChunks.push(e.data);\r\n };\r\n\r\n /**\r\n * Method to create a media recorder object and set up event listeners.\r\n *\r\n * @private\r\n * @param stream - The stream of audio from the Listener.\r\n * @example\r\n */\r\n #setMediaRecorder = stream => {\r\n // Create a new MediaRecorder object\r\n this.#mediaRecorder = new MediaRecorder(stream);\r\n\r\n // Add event listeners\r\n this.#mediaRecorder.ondataavailable = e => this.#onRecorderDataAvailable(e);\r\n };\r\n\r\n #setAudioContext = () => {\r\n this.#audioContext = new (window.AudioContext ||\r\n window.webkitAudioContext ||\r\n window.audioContext)({\r\n sampleRate: this.sinkSamplingRate,\r\n sampleSize: this.sampleSize,\r\n //sampleRate: 96000\r\n });\r\n };\r\n\r\n /**\r\n * Public method to start the recording process.\r\n *\r\n * @param stream - The stream of audio from the Listener.\r\n * @example\r\n */\r\n startRecording = async stream => {\r\n try {\r\n // Create a fresh audio context\r\n this.#setAudioContext();\r\n // Set up media recorder if needed\r\n if (!this.#mediaRecorder) this.#setMediaRecorder(stream);\r\n // clear recorded chunks\r\n this.#recordedChunks = [];\r\n // start recording\r\n this.#mediaRecorder.start();\r\n } catch (error) {\r\n console.error('Error in startRecording:', error);\r\n // Handle the error as needed, e.g., throw it or perform error-specific actions\r\n }\r\n };\r\n\r\n /**\r\n * Method to stop the recording process.\r\n *\r\n * @public\r\n * @example\r\n */\r\n stopRecording = async (mode, checkRec) => {\r\n try {\r\n // Stop the media recorder, and wait for the data to be available\r\n await new Promise(resolve => {\r\n this.#mediaRecorder.onstop = () => {\r\n // when the stop event is triggered, resolve the promise\r\n this.#audioBlob = new Blob(this.#recordedChunks, {\r\n type: 'audio/wav; codecs=opus',\r\n });\r\n resolve(this.#audioBlob);\r\n };\r\n // call stop\r\n this.#mediaRecorder.stop();\r\n });\r\n // Now that we have data, save it\r\n await this.#saveRecording(mode, checkRec);\r\n } catch (error) {\r\n console.error('Error in stopRecording:', error);\r\n // Handle the error as needed, e.g., throw it or perform error-specific actions\r\n }\r\n };\r\n\r\n /** .\r\n * .\r\n * .\r\n * Public method to get the last recorded audio signal\r\n *\r\n * @returns\r\n * @example\r\n */\r\n getLastRecordedSignal = () => this.#recordedSignals[this.#recordedSignals.length - 1];\r\n\r\n /** .\r\n * .\r\n * .\r\n * Public method to get the last 1000hz recorded audio signal\r\n *\r\n * @returns\r\n * @example\r\n */\r\n getLastVolumeRecordedSignal = () => Array.from(this.#allVolumeRecordings[this.#allVolumeRecordings.length - 1]);\r\n\r\n /** .\r\n * .\r\n * .\r\n * Public method to get all the recorded audio signals\r\n *\r\n * @returns\r\n * @example\r\n */\r\n getAllRecordedSignals = () => this.#recordedSignals;\r\n\r\n /** .\r\n * .\r\n * .\r\n * Public method to get all the recorded audio signals\r\n *\r\n * @returns\r\n * @example\r\n */\r\n getAllVolumeRecordedSignals = () => this.#allVolumeRecordings;\r\n\r\n /** .\r\n * .\r\n * .\r\n * Public method to get all the recorded audio signals\r\n *\r\n * @returns\r\n * @example\r\n */\r\n getAllFilteredRecordedSignals = () => this.#allHzFilteredRecordings;\r\n\r\n /** .\r\n * .\r\n * .\r\n * Public method to get all the recorded audio signals\r\n *\r\n * @returns\r\n * @example\r\n */\r\n clearAllFilteredRecordedSignals = () => this.#allHzFilteredRecordings = [];\r\n\r\n /** .\r\n * .\r\n * .\r\n * Public method to clear last the recorded audio signals\r\n *\r\n * @returns\r\n * @example\r\n */\r\n clearLastFilteredRecordedSignals = () => this.#allHzFilteredRecordings.pop();\r\n\r\n /** .\r\n * .\r\n * .\r\n * Public method to get all the recorded audio signals for psd\r\n *\r\n * @returns\r\n * @example\r\n */\r\n getAllUnfilteredRecordedSignals = () => this.#allHzUnfilteredRecordings;\r\n\r\n /** .\r\n * .\r\n * .\r\n * Public method to get all the recorded audio signals\r\n *\r\n * @returns\r\n * @example\r\n */\r\n clearLastUnfilteredRecordedSignals = () => this.#allHzUnfilteredRecordings.pop();\r\n\r\n /** .\r\n * .\r\n * .\r\n * Public method to get all the recorded audio signals for psd\r\n *\r\n * @returns\r\n * @example\r\n */\r\n getAllBackgroundRecordings = () => this.#allBackgroundRecordings;\r\n\r\n /** .\r\n * .\r\n * .\r\n * Public method to set the sampling rate used by the capture device\r\n *\r\n * @param {Number} sinkSamplingRate - The sampling rate of the capture device\r\n * @example\r\n */\r\n setSinkSamplingRate = sinkSamplingRate => {\r\n this.sinkSamplingRate = sinkSamplingRate;\r\n };\r\n}\r\n\r\n/* harmony default export */ __webpack_exports__[\"default\"] = (AudioRecorder);\r\n\n\n//# sourceURL=webpack://speakerCalibrator/./src/tasks/audioRecorder.js?");
|
|
505
505
|
|
|
506
506
|
/***/ }),
|
|
507
507
|
|
|
@@ -512,7 +512,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _myE
|
|
|
512
512
|
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
513
513
|
|
|
514
514
|
"use strict";
|
|
515
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _audioCalibrator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../audioCalibrator */ \"./src/tasks/audioCalibrator.js\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../utils */ \"./src/utils.js\");\n/* harmony import */ var _powerCheck__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../powerCheck */ \"./src/powerCheck.js\");\n/* harmony import */ var _config_firebase__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../config/firebase */ \"./src/config/firebase.js\");\n/* harmony import */ var firebase_database__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! firebase/database */ \"./node_modules/firebase/database/dist/esm/index.esm.js\");\n/* harmony import */ var firebase_firestore__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! firebase/firestore */ \"./node_modules/firebase/firestore/dist/esm/index.esm.js\");\n\n\n\n\n\n\n\n\n\n//import { phrases } from '../../../dist/example/i18n';\n\n/**\n *\n */\nclass Combination extends _audioCalibrator__WEBPACK_IMPORTED_MODULE_0__[\"default\"] {\n /**\n * Default constructor. Creates an instance with any number of paramters passed or the default parameters defined here.\n *\n * @param {Object<boolean, number, number, number>} calibratorParams - paramter object\n * @param {boolean} [calibratorParams.download = false] - boolean flag to download captures\n * @param {number} [calibratorParams.mlsOrder = 18] - order of the MLS to be generated\n * @param {number} [calibratorParams.numCaptures = 5] - number of captures to perform\n * @param {number} [calibratorParams.numMLSPerCapture = 2] - number of bursts of MLS per capture\n */\n constructor({\n download = false,\n mlsOrder = 18,\n numCaptures = 3,\n numMLSPerCapture = 2,\n lowHz = 20,\n highHz = 10000,\n }) {\n super(numCaptures, numMLSPerCapture);\n this.#mlsOrder = parseInt(mlsOrder, 10);\n this.#P = 2 ** mlsOrder - 1;\n this.#download = download;\n this.#mls = [];\n this.#lowHz = lowHz;\n this.#highHz = highHz;\n }\n\n /** @private */\n stepNum = 0;\n\n /** @private */\n totalSteps = 25;\n\n /** @private */\n #download;\n\n /** @private */\n #mlsGenInterface;\n\n /** @private */\n #mlsBufferView;\n\n /** @private */\n componentInvertedImpulseResponse = null;\n\n /** @private */\n systemInvertedImpulseResponse = null;\n\n //averaged and subtracted ir returned from calibration used to calculated iir\n /** @private */\n ir = null;\n\n /** @private */\n impulseResponses = [];\n\n /** @private */\n #mlsOrder;\n\n /** @private */\n #lowHz;\n\n /** @private */\n #highHz;\n\n /** @private */\n #mls;\n\n /** @private */\n #P;\n\n /** @private */\n #audioContext;\n\n /** @private */\n offsetGainNode;\n\n /** @private */\n componentConvolution;\n\n /** @private */\n componentConvolutionNoBandpass;\n\n /** @private */\n componentIROrigin = {\n Freq: [],\n Gain: [],\n };\n\n /** @private */\n systemConvolution;\n\n /** @private */\n systemConvolutionNoBandpass;\n\n ////////////////////////volume\n /** @private */\n #CALIBRATION_TONE_FREQUENCY = 1000; // Hz\n\n /** @private */\n #CALIBRATION_TONE_TYPE = 'sine';\n\n CALIBRATION_TONE_DURATION = 5; // seconds\n calibrateSound1000HzPreSec = 3.5;\n calibrateSound1000HzSec = 1.0;\n calibrateSound1000HzPostSec = 0.5;\n\n /** @private */\n outDBSPL = null;\n THD = null;\n outDBSPL1000 = null;\n\n /** @private */\n TAPER_SECS = 0.01; // seconds\n\n /** @private */\n status_denominator = 8;\n\n /** @private */\n status_numerator = 0;\n\n /** @private */\n percent_complete = 0;\n\n /** @private */\n status = ``;\n\n /**@private */\n status_literal = `<div style=\"display: flex; justify-content: center;\"><div style=\"width: 200px; height: 20px; border: 2px solid #000; border-radius: 10px;\"><div style=\"width: ${this.percent_complete}%; height: 100%; background-color: #00aaff; border-radius: 8px;\"></div></div></div>`;\n\n /**@private */\n componentIR = null;\n\n /**@private */\n oldComponentIR = null;\n\n /**@private */\n systemIR = null;\n\n /**@private */\n _calibrateSoundCheck = '';\n\n deviceType = null;\n\n deviceName = null;\n\n deviceInfo = null;\n\n desired_time_per_mls = 0;\n\n num_mls_to_skip = 0;\n\n desired_sampling_rate = 0;\n\n #currentConvolution = [];\n\n mode = 'unfiltered';\n\n sourceNode;\n\n autocorrelations = [];\n\n iirLength = 0;\n\n irLength = 0;\n\n calibrateSoundIIRPhase = 'linear';\n\n componentInvertedImpulseResponseNoBandpass = [];\n\n componentIRInTimeDomain = [];\n\n systemInvertedImpulseResponseNoBandpass = [];\n\n _calibrateSoundBackgroundSecs;\n\n _calibrateSoundSmoothOctaves;\n\n background_noise = {};\n\n numSuccessfulBackgroundCaptured;\n\n _calibrateSoundBurstDb;\n\n _calibrateSoundBurstFilteredExtraDb;\n\n _calibrateSoundBurstLevelReTBool;\n\n SDofFilteredRange = {\n mls: undefined,\n component: undefined,\n system: undefined,\n };\n\n transducerType = 'Loudspeaker';\n\n componentIRPhase = [];\n\n systemIRPhase = [];\n\n webAudioDeviceNames = {loudspeaker: '', microphone: '', loudspeakerText: '', microphoneText: ''};\n\n waveforms = {\n volume: {},\n };\n\n recordingChecks = {\n volume: {},\n unfiltered: [],\n system: [],\n component: [],\n warnings:[]\n };\n\n inDB;\n\n soundCheck = '';\n\n filteredMLSRange = {\n component: {\n Min: null,\n Max: null,\n },\n system: {\n Min: null,\n Max: null,\n },\n };\n\n /** @private */\n timeStamp = [];\n\n restartCalibration = false;\n\n calibrateSoundLimit = 1;\n\n filteredMLSAttenuation = {\n component: 1,\n system: 1,\n maxAbsSystem: 1,\n maxAbsComponent: 1,\n };\n\n //parameter result from volume calibration\n T = 0;\n //gainDBSPL result from volume calibration\n gainDBSPL = 0;\n //not always just using _calibrateSoundBurstDb for MLS so created a new parameter\n power_dB = 0;\n\n //system\n systemAttenuatorGainDB = 0;\n systemFMaxHz = 0;\n\n //component\n componentAttentuatorGainDB = 0;\n componentFMaxHz = 0;\n\n dL_n;\n L_new_n;\n fs2;\n icapture = 0;\n\n /**generate string template that gets reevaluated as variable increases */\n generateTemplate = (status) => {\n if (this.isCalibrating) {\n return '';\n }\n if (this.percent_complete > 100) {\n this.percent_complete = 100;\n }\n let MLSsd = '';\n let componentSD = '';\n let systemSD = '';\n let flags = '';\n const reportWebAudioNames = `<strong>${this.webAudioDeviceNames.loudspeakerText} </strong> <strong>${this.webAudioDeviceNames.microphoneText} </strong>`;\n const samplingParamText = this.phrases.RC_SamplingHzBits[this.language].replace('111', this.sourceSamplingRate).replace('222',this.sinkSamplingRate).replace('333', this.calibrateSoundSamplingDesiredBits);\n const reportParameters = `${samplingParamText}`;\n if (this.flags) {\n flags = `<br> autoGainControl: ${this.flags.autoGainControl}; \n echoCancellation: ${this.flags.echoCancellation};\n noiseSuppression: ${this.flags.noiseSuppression}`;\n }\n if (this.SDofFilteredRange['mls']) {\n MLSsd = `<br> Recorded MLS power SD: ${this.SDofFilteredRange['mls']} dB`;\n }\n if (this.SDofFilteredRange['system']) {\n systemSD = `<br> Loudspeaker+Microphone correction SD: ${this.SDofFilteredRange['system']} dB`;\n }\n if (this.SDofFilteredRange['component']) {\n componentSD = `<br> ${this.transducerType} correction SD: ${this.SDofFilteredRange['component']} dB`;\n }\n const template = `<div style=\"display: flex; justify-content: flex-start; margin-top: 0.4rem;\"><div style=\"width: 100%; height: 20px; border: 2px solid #000; border-radius: 10px;\"><div style=\"width: ${this.percent_complete}%; height: 100%; background-color: #00aaff; border-radius: 8px;\"></div></div></div>`;\n return `\n ${reportWebAudioNames}\n ${reportParameters} \n ${MLSsd}\n ${systemSD}\n ${componentSD}\n ${flags}\n <br>${status}\n ${template }`;\n };\n\n /** increment numerator and percent for status bar */\n incrementStatusBar = () => {\n this.status_numerator += 1;\n this.percent_complete = (this.status_numerator / this.status_denominator) * 100;\n };\n\n setDeviceType = deviceType => {\n this.deviceType = deviceType;\n };\n\n setDeviceName = deviceName => {\n this.deviceName = deviceName;\n };\n\n setDeviceInfo = deviceInfo => {\n this.deviceInfo = deviceInfo;\n };\n\n /** .\n * .\n * .\n * Sends all the computed impulse responses to the backend server for processing\n *\n * @returns sets the resulting inverted impulse response to the class property\n * @example\n */\n sendSystemImpulseResponsesToServerForProcessing = async () => {\n this.addTimeStamp('Compute system IIR');\n const computedIRs = await Promise.all(this.impulseResponses);\n const filteredComputedIRs = computedIRs.filter(element => {\n return element != undefined;\n }); //log any errors that are found in this step\n console.log('filteredComputedIRs', filteredComputedIRs);\n const mls = this.#mls[this.icapture];\n const lowHz = this.#lowHz; //gain of 1 below cutoff, need gain of 0\n const highHz = this.#highHz; //check error for anything other than 10 kHz\n const iirLength = this.iirLength;\n this.stepNum += 1;\n console.log('send impulse responses to server: ' + this.stepNum);\n this.status = this.generateTemplate(`All Hz Calibration: computing the IIR...`.toString()).toString();\n this.emit('update', {message: this.status});\n return await this.pyServerAPI\n .getSystemInverseImpulseResponseWithRetry({\n payload: filteredComputedIRs.slice(0, this.numCaptures),\n mls,\n lowHz,\n highHz,\n iirLength,\n sampleRate: this.sourceSamplingRate || 96000,\n mlsAmplitude: Math.pow(10, this.power_dB / 20),\n calibrateSoundBurstFilteredExtraDb: this._calibrateSoundBurstFilteredExtraDb,\n calibrateSoundIIRPhase: this.calibrateSoundIIRPhase,\n })\n .then(async res => {\n this.stepNum += 1;\n console.log('got impulse response ' + this.stepNum);\n this.incrementStatusBar();\n this.status = this.generateTemplate(`All Hz Calibration: done computing the IIR...`.toString()).toString();\n this.emit('update', {message: this.status});\n this.systemInvertedImpulseResponse = res['iir'];\n this.systemIR = res['ir'];\n this.systemInvertedImpulseResponseNoBandpass = res['iirNoBandpass'];\n this.systemAttenuatorGainDB = res['attenuatorGain_dB'];\n this.systemFMaxHz = res['fMaxHz'];\n await this.pyServerAPI.checkMemory();\n await this.pyServerAPI\n .getConvolution({\n mls,\n inverse_response: this.systemInvertedImpulseResponse,\n inverse_response_no_bandpass: this.systemInvertedImpulseResponseNoBandpass,\n attenuatorGain_dB: this.systemAttenuatorGainDB,\n mls_amplitude: Math.pow(10, this.power_dB / 20),\n })\n .then(result => {\n console.log(result);\n this.systemConvolution = result['convolution'];\n this.systemConvolutionNoBandpass = result['convolution_no_bandpass'];\n });\n\n // attenuate the system convolution if the amplitude is greater than this.calibrateSoundLimit\n // find max of absolute value of system convolution\n\n const max = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.findMaxValue)(this.systemConvolution);\n this.filteredMLSAttenuation.system =\n this.systemConvolution.reduce((a, b) => a + b ** 2, 0) / this.systemConvolution.length;\n this.filteredMLSAttenuation.maxAbsSystem = max;\n })\n .catch(err => {\n console.error(err);\n });\n };\n\n /** .\n * .\n * .\n * Sends all the computed impulse responses to the backend server for processing\n *\n * @returns sets the resulting inverted impulse response to the class property\n * @example\n */\n sendComponentImpulseResponsesToServerForProcessing = async () => {\n this.addTimeStamp('Compute component IIR');\n const computedIRs = await Promise.all(this.impulseResponses);\n const filteredComputedIRs = computedIRs.filter(element => {\n return element != undefined;\n });\n let componentIRGains = this.componentIR['Gain'];\n const componentIRFreqs = this.componentIR['Freq'];\n //normalize the component IR gains\n componentIRGains = componentIRGains.map(value => {\n return value + this._calibrateSoundBurstScalarDB - this._calibrateSoundBurstDb;\n });\n if (this._calibrateSoundBurstNormalizeBy1000HzGainBool) {\n const sineGainAt1000Hz_dB = this.gainDBSPL;\n componentIRGains = componentIRGains.map(value => {\n return value - sineGainAt1000Hz_dB;\n });\n }\n const mls = this.#mls[this.icapture];\n const lowHz = this.#lowHz;\n const iirLength = this.iirLength;\n const irLength = this.irLength;\n const highHz = this.#highHz;\n this.stepNum += 1;\n console.log('send impulse responses to server: ' + this.stepNum);\n this.status = this.generateTemplate(`All Hz Calibration: computing the IIR...`.toString()).toString();\n this.emit('update', {message: this.status});\n console.log()\n return this.pyServerAPI\n .getComponentInverseImpulseResponseWithRetry({\n payload: filteredComputedIRs.slice(0, this.numCaptures),\n mls,\n lowHz,\n highHz,\n iirLength,\n componentIRGains,\n componentIRFreqs,\n sampleRate: this.sourceSamplingRate || 96000,\n mlsAmplitude: Math.pow(10, this.power_dB / 20),\n irLength,\n calibrateSoundSmoothOctaves: this._calibrateSoundSmoothOctaves,\n calibrateSoundSmoothMinBandwidthHz: this._calibrateSoundSmoothMinBandwidthHz,\n calibrateSoundBurstFilteredExtraDb: this._calibrateSoundBurstFilteredExtraDb,\n calibrateSoundIIRPhase: this.calibrateSoundIIRPhase,\n })\n .then(async res => {\n this.stepNum += 1;\n console.log('got impulse response ' + this.stepNum);\n this.incrementStatusBar();\n this.status = this.generateTemplate(`All Hz Calibration: done computing the IIR...`.toString()).toString();\n this.emit('update', {message: this.status});\n this.componentInvertedImpulseResponse = res['iir'];\n this.componentInvertedImpulseResponseNoBandpass = res['iirNoBandpass'];\n this.componentIR['Gain'] = res['ir'];\n this.componentIR['Freq'] = res['frequencies'];\n this.componentIRPhase = res['component_angle'];\n this.systemIRPhase = res['system_angle'];\n this.componentIROrigin['Freq'] = res['frequencies'];\n this.componentIROrigin['Gain'] = res['irOrigin'];\n this.componentIRInTimeDomain = res['irTime'];\n this.componentAttenuatorGainDB = res['attenuatorGain_dB'];\n this.componentFMaxHz = res['fMaxHz'];\n await this.pyServerAPI.checkMemory();\n await this.pyServerAPI\n .getConvolution({\n mls,\n inverse_response: this.componentInvertedImpulseResponse,\n inverse_response_no_bandpass: this.componentInvertedImpulseResponseNoBandpass,\n attenuatorGain_dB: this.componentAttenuatorGainDB,\n mls_amplitude: Math.pow(10, this.power_dB / 20),\n })\n .then(result => {\n console.log(result);\n this.componentConvolution = result['convolution'];\n this.componentConvolutionNoBandpass = result['convolution_no_bandpass'];\n });\n // attenuate the component convolution if the amplitude is greater than this.calibrateSoundLimit\n // find max of absolute value of component convolution\n const max = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.findMaxValue)(this.componentConvolution);\n // if (max > this.calibrateSoundLimit) {\n // const gain = this.calibrateSoundLimit / max;\n // // apply gain to component convolution\n // this.componentConvolution = this.componentConvolution.map(value => value * gain);\n // this.filteredMLSAttenuation.component = gain;\n // }\n this.filteredMLSAttenuation.component =\n this.componentConvolution.reduce((a, b) => a + b ** 2, 0) /\n this.componentConvolution.length;\n this.filteredMLSAttenuation.maxAbsComponent = max;\n })\n .catch(err => {\n // this.emit('InvertedImpulseResponse', {res: false});\n console.error(err);\n });\n };\n\n sendBackgroundRecording = () => {\n const allSignals = this.getAllBackgroundRecordings();\n const numSignals = allSignals.length;\n const background_rec_whole = allSignals[numSignals - 1];\n const fraction = 0.5 / (this._calibrateSoundBackgroundSecs + 0.5);\n // Calculate the starting index for slicing the array\n const startIndex = Math.round(fraction * background_rec_whole.length);\n // Slice the array from the calculated start index to the end of the array\n const background_rec = background_rec_whole.slice(startIndex);\n console.log('Sending background recording to server for processing');\n this.addTimeStamp('Compute background PSD');\n this.pyServerAPI\n .getBackgroundNoisePSDWithRetry({\n background_rec,\n sampleRate: this.sourceSamplingRate || 96000,\n })\n .then(res => {\n if (this.numSuccessfulBackgroundCaptured < 1) {\n this.numSuccessfulBackgroundCaptured += 1;\n //storing all background data in background_psd object\n this.background_noise['x_background'] = res['x_background'];\n this.background_noise['y_background'] = res['y_background'];\n this.background_noise['recording'] = background_rec;\n }\n })\n .catch(err => {\n console.error(err);\n });\n };\n\n /** .\n * .\n * .\n * Sends the recorded signal, or a given csv string of a signal, to the back end server for processing\n *\n * @param {<array>String} signalCsv - Optional csv string of a previously recorded signal, if given, this signal will be processed\n * @example\n */\n sendRecordingToServerForProcessing = async signalCsv => {\n const allSignals = this.getAllUnfilteredRecordedSignals();\n console.log(\n 'Obtaining last all hz unfiltered recording from #allHzUnfilteredRecordings to send to server for processing'\n );\n const numSignals = allSignals.length;\n const mls = this.#mlsBufferView[this.icapture];\n const payload =\n signalCsv && signalCsv.length > 0 ? (0,_utils__WEBPACK_IMPORTED_MODULE_1__.csvToArray)(signalCsv) : allSignals[numSignals - 1];\n console.log('sending rec');\n this.stepNum += 1;\n console.log('send rec ' + this.stepNum);\n this.status = this.generateTemplate(`All Hz Calibration Step: computing the IR of the last recording...`.toString()).toString();\n this.emit('update', {message: this.status});\n if (this.isCalibrating) return null;\n await this.pyServerAPI\n .allHzPowerCheck({\n payload,\n sampleRate: this.sourceSamplingRate || 96000,\n binDesiredSec: this._calibrateSoundPowerBinDesiredSec,\n burstSec: this.desired_time_per_mls,\n repeats: this.numMLSPerCapture - this.num_mls_to_skip,\n warmUp: this.num_mls_to_skip \n })\n .then(async result => {\n if (result) {\n if (result['sd'] > this._calibrateSoundBurstMaxSD_dB && \n this.numSuccessfulCaptured == 0) {\n console.log('SD: ' + result['sd'] + ', greater than _calibrateSoundBurstMaxSD_dB: ' + this._calibrateSoundBurstMaxSD_dB);\n this.recordingChecks['unfiltered'].push(result);\n this.clearLastUnfilteredRecordedSignals();\n this.numSuccessfulCaptured +=1;\n } else {\n if (result['sd'] <= this._calibrateSoundBurstMaxSD_dB) {\n console.log('SD: ' + result['sd'] + ', less than _calibrateSoundBurstMaxSD_dB: ' + this._calibrateSoundBurstMaxSD_dB);\n } else {\n console.log('SD: ' + result['sd'] + ', greater than _calibrateSoundBurstMaxSD_dB: ' + this._calibrateSoundBurstMaxSD_dB);\n this.recordingChecks['warnings'].push(`All Hz. Re-recorded ${this.inDB} dB because SD ${result['sd']} > ${this._calibrateSoundBurstMaxSD_dB} dB`);\n this.status = this.generateTemplate(`All Hz: Re-recording at ${this.inDB} dB because SD ${result['sd']} > ${this._calibrateSoundBurstMaxSD_dB} dB`.toString()).toString();\n this.emit('update', {\n message: this.status,\n });\n }\n if (this.numSuccessfulCaptured == 1) {\n console.log('pop last unfiltered mls volume check');\n this.recordingChecks['unfiltered'].pop();\n }\n this.recordingChecks['unfiltered'].push(result);\n // let start = new Date().getTime() / 1000;\n // const payloadT = tf.tensor1d(payload);\n // payloadT.print();\n // const xfft = payloadT.rfft(); // tf.spe\n // xfft.array().then(array => {\n // console.log(\"fft:\", array);\n // let setItem = new Set(array);\n // console.log(\"all zero\", setItem.size === 1 && setItem.has(0));\n // });\n // console.log(\"dimention:\", xfft.shape);\n // let end = new Date().getTime() / 1000;\n // console.log(\"Time taken:\", end - start, \"seconds\");\n console.log('start calculate impulse response');\n const usedPeriodStart = this.num_mls_to_skip * this.sourceSamplingRate;\n const payload_skipped_warmUp = payload.slice(usedPeriodStart);\n await this.pyServerAPI\n .getAutocorrelation({\n mls:mls,\n payload: payload_skipped_warmUp,\n sampleRate: this.sourceSamplingRate || 96000,\n numPeriods: this.numMLSPerCapture - this.num_mls_to_skip,\n })\n .then(async res => {\n this.autocorrelations.push(res['autocorrelation']);\n this.fs2 = res['fs2'];\n this.L_new_n = res['L_new_n'];\n this.dL_n = res['dL_n'];\n this.impulseResponses.push(\n await this.pyServerAPI\n .getImpulseResponse({\n mls,\n sampleRate: this.sourceSamplingRate || 96000,\n numPeriods: this.numMLSPerCapture - this.num_mls_to_skip,\n sig: payload_skipped_warmUp,\n fs2: this.fs2,\n L_new_n: this.L_new_n,\n dL_n: this.dL_n,\n })\n .then(res => {\n this.numSuccessfulCaptured += 2;\n this.stepNum += 1;\n console.log('got impulse response ' + this.stepNum);\n this.incrementStatusBar();\n this.status = this.generateTemplate(`All Hz Calibration: ${this.numSuccessfulCaptured}/${this.numCaptures} IRs computed...`.toString()).toString();\n this.emit('update', {\n message: this.status,\n });\n return res['ir'];\n })\n .catch(err => {\n console.error(err);\n })\n );\n });\n }\n console.log('number of unfiltered recording checks:' + this.recordingChecks['unfiltered'].length);\n }\n })\n .catch(err => {\n console.error(err);\n });\n };\n\n /**\n * Passed to the calibration steps function, awaits the desired amount of seconds to capture the desired number\n * of MLS periods defined in the constructor.\n *\n * @example\n */\n #awaitDesiredMLSLength = async () => {\n // seconds per MLS = P / SR\n // await N * P / SR\n this.stepNum += 1;\n console.log('await desired length ' + this.stepNum);\n this.status = this.generateTemplate(`All Hz Calibration: sampling the calibration signal...`.toString() +\n `\\niteration ${this.stepNum}`);\n this.emit('update', {\n message: this.status,\n });\n let time_to_wait = 0;\n if (this.mode === 'unfiltered') {\n //unfiltered\n time_to_wait = (this.#mls[0].length / this.sourceSamplingRate) * this.numMLSPerCapture;\n time_to_wait = time_to_wait + this._calibrateSoundBurstPostSec;\n } else if (this.mode === 'filtered') {\n //filtered\n // time_to_wait =\n // (this.#currentConvolution.length / this.sourceSamplingRate) *\n // (this.numMLSPerCapture / (this.num_mls_to_skip + this.numMLSPerCapture));\n time_to_wait =\n (this.#currentConvolution.length / this.sourceSamplingRate) * this.numMLSPerCapture;\n time_to_wait = time_to_wait + this._calibrateSoundBurstPostSec;\n } else {\n throw new Error('Mode broke in awaitDesiredMLSLength');\n }\n\n await (0,_utils__WEBPACK_IMPORTED_MODULE_1__.sleep)(time_to_wait);\n };\n\n /**\n * Passed to the background noise recording function, awaits the desired amount of seconds to capture the desired number\n * of seconds of background noise\n *\n * @example\n */\n #awaitBackgroundNoiseRecording = async () => {\n console.log(\n 'Waiting ' + this._calibrateSoundBackgroundSecs + ' second(s) to record background noise'\n );\n let time_to_wait = this._calibrateSoundBackgroundSecs + 0.5;\n this.addTimeStamp(`Record ${time_to_wait.toFixed(1)} s of background.`)\n await (0,_utils__WEBPACK_IMPORTED_MODULE_1__.sleep)(time_to_wait);\n };\n\n /** .\n * .\n * .\n * Passed to the calibration steps function, awaits the onset of the signal to ensure a steady state\n *\n * @example\n */\n #awaitSignalOnset = async () => {\n this.stepNum += 1;\n console.log('await signal onset ' + this.stepNum);\n this.status = this.generateTemplate(`All Hz Calibration: waiting for the signal to stabilize...`.toString());\n this.emit('update', {\n message: this.status,\n });\n let number_of_bursts_to_skip = 0;\n let time_to_sleep = 0;\n if (this.mode === 'unfiltered') {\n time_to_sleep = (this.#mls[0].length / this.sourceSamplingRate) * number_of_bursts_to_skip;\n } else if (this.mode === 'filtered') {\n console.log(this.#currentConvolution.length);\n // time_to_sleep =\n // (this.#currentConvolution.length / this.sourceSamplingRate) *\n // (number_of_bursts_to_skip / (number_of_bursts_to_skip + this.numMLSPerCapture));\n time_to_sleep =\n (this.#currentConvolution.length / this.sourceSamplingRate) * number_of_bursts_to_skip;\n } else {\n throw new Error('Mode broke in awaitSignalOnset');\n }\n await (0,_utils__WEBPACK_IMPORTED_MODULE_1__.sleep)(time_to_sleep);\n };\n\n /**\n * Called immediately after a recording is captured. Used to process the resulting signal\n * whether by sending the result to a server or by computing a result locally.\n *\n * @example\n */\n #afterMLSRecord = async () => {\n console.log('after record');\n this.addTimeStamp(`Send unfiltered MLS to the server`);\n await this.sendRecordingToServerForProcessing();\n };\n\n #afterMLSwIIRRecord = async () => {\n await this.checkPowerVariation();\n };\n\n /** .\n * .\n * .\n * Created an S Curver Buffer to taper the signal onset\n *\n * @param {*} onSetBool\n * @returns\n * @example\n */\n createSCurveBuffer = (onSetBool = true) => {\n const curve = new Float32Array(this.TAPER_SECS * this.sourceSamplingRate + 1);\n const frequency = 1 / (4 * this.TAPER_SECS);\n let j = 0;\n for (let i = 0; i < this.TAPER_SECS * this.sourceSamplingRate + 1; i += 1) {\n const phase = 2 * Math.PI * frequency * j;\n const onsetTaper = Math.pow(Math.sin(phase), 2);\n const offsetTaper = Math.pow(Math.cos(phase), 2);\n curve[i] = onSetBool ? onsetTaper : offsetTaper;\n j += 1 / this.sourceSamplingRate;\n }\n return curve;\n };\n\n static createInverseSCurveBuffer = (length, phase) => {\n const curve = new Float32Array(length);\n let i;\n let j = length - 1;\n for (i = 0; i < length; i += 1) {\n // scale the curve to be between 0-1\n curve[i] = Math.sin((Math.PI * j) / length - phase) / 2 + 0.5;\n j -= 1;\n }\n return curve;\n };\n\n /**\n * Construct a Calibration Node with the calibration parameters.\n *\n * @param dataBuffer\n * @private\n * @example\n */\n #createCalibrationNodeFromBuffer = dataBuffer => {\n console.log('length databuffer');\n console.log(dataBuffer.length);\n if (!this.sourceAudioContext) {\n this.makeNewSourceAudioContext();\n }\n\n const buffer = this.sourceAudioContext.createBuffer(\n 1, // number of channels\n dataBuffer.length,\n this.sourceAudioContext.sampleRate // sample rate\n );\n\n const data = buffer.getChannelData(0); // get data\n\n // fill the buffer with our data\n try {\n for (let i = 0; i < dataBuffer.length; i += 1) {\n data[i] = dataBuffer[i];\n }\n } catch (error) {\n console.error(error);\n }\n\n this.sourceNode = this.sourceAudioContext.createBufferSource();\n\n this.sourceNode.buffer = buffer;\n\n if (this.mode === 'filtered') {\n //used to not loop filtered\n this.sourceNode.loop = true;\n } else {\n this.sourceNode.loop = true;\n }\n\n this.sourceNode.connect(this.sourceAudioContext.destination);\n\n this.addCalibrationNode(this.sourceNode);\n };\n\n /**\n * Given a data buffer, creates the required calibration node\n *\n * @param {*} dataBufferArray\n * @example\n */\n #setCalibrationNodesFromBuffer = (dataBufferArray = [this.#mlsBufferView[this.icapture]]) => {\n if (dataBufferArray.length === 1) {\n this.#createCalibrationNodeFromBuffer(dataBufferArray[0]);\n } else {\n throw new Error('The length of the data buffer array must be 1');\n }\n };\n\n /**\n * Creates an audio context and plays it for a few seconds.\n *\n * @private\n * @returns - Resolves when the audio is done playing.\n * @example\n */\n #playCalibrationAudio = () => {\n this.calibrationNodes[0].start(0);\n this.status = ``;\n if (this.mode === 'unfiltered') {\n console.log('play calibration audio ' + this.stepNum);\n\n const pre = this._calibrateSoundBurstPreSec; \n const repeats = this._calibrateSoundBurstRepeats; \n const burst = this._calibrateSoundBurstSec; \n const post = this._calibrateSoundBurstPostSec; \n const total_dur = pre + repeats * burst + post;\n this.addTimeStamp(\n `Record ${total_dur.toFixed(1)} s of MLS ver. ${this.icapture}, unfiltered. ` +\n `(${pre.toFixed(1)} s pre + ${repeats}×${burst.toFixed(1)} s used + ${post.toFixed(1)} s post).`\n );\n this.status = this.generateTemplate(`All Hz Calibration: playing the calibration tone...`.toString()).toString();\n } else if (this.mode === 'filtered') {\n console.log('play convolved audio ' + this.stepNum);\n this.status = this.generateTemplate().toString( `All Hz Calibration: playing the convolved calibration tone...`.toString());\n } else {\n throw new Error('Mode is incorrect');\n }\n this.emit('update', {message: this.status});\n this.stepNum += 1;\n console.log('sink sampling rate');\n console.log(this.sinkSamplingRate);\n console.log('source sampling rate');\n console.log(this.sourceSamplingRate);\n console.log('sample size');\n console.log(this.sampleSize);\n };\n\n /** .\n * .\n * .\n * Stops the audio with tapered offset\n *\n * @example\n */\n stopCalibrationAudio = () => {\n if (this.calibrationNodes.length === 0) {\n return;\n }\n this.calibrationNodes[0].stop(0);\n this.calibrationNodes = [];\n if (this.sourceNode) this.sourceNode.disconnect();\n this.stepNum += 1;\n console.log('stop calibration audio ' + this.stepNum);\n this.status = this.generateTemplate(`All Hz Calibration: stopping the calibration tone...`.toString()).toString();\n this.emit('update', {message: this.status});\n };\n\n playMLSwithIIR = async (stream, convolution) => {\n let checkRec = false;\n this.mode = 'filtered';\n console.log('play mls with iir');\n //this.invertedImpulseResponse = iir\n\n await this.calibrationSteps(\n stream,\n this.#playCalibrationAudio, // play audio func (required)\n this.#createCalibrationNodeFromBuffer(convolution), // before play func\n this.#awaitSignalOnset, // before record\n () => this.numSuccessfulCaptured < 2,\n this.#awaitDesiredMLSLength, // during record\n this.#afterMLSwIIRRecord, // after record\n this.mode,\n checkRec\n );\n };\n\n bothSoundCheck = async stream => {\n let iir_ir_and_plots;\n this.#currentConvolution = this.componentConvolution;\n this.filteredMLSRange.component.Min = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.findMinValue)(this.#currentConvolution);\n this.filteredMLSRange.component.Max = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.findMaxValue)(this.#currentConvolution);\n const pre = this._calibrateSoundBurstPreSec; \n const repeats = this._calibrateSoundBurstRepeats; \n const burst = this._calibrateSoundBurstSec; \n const post = this._calibrateSoundBurstPostSec; \n const total_dur = pre + repeats * burst + post;\n this.soundCheck = 'component';\n this.addTimeStamp(`Record ${total_dur} s of MLS with ${this.soundCheck} IIR.”`)\n \n if (this.isCalibrating) return null;\n await this.playMLSwithIIR(stream, this.#currentConvolution);\n this.stopCalibrationAudio();\n let component_conv_recs = this.getAllFilteredRecordedSignals();\n\n if (this.componentAttentuatorGainDB != 0) {\n let linearScaleAttenuation = Math.pow(10, this.componentAttentuatorGainDB / 20);\n component_conv_recs = component_conv_recs.map(rec => {\n return rec.map(value => value / this.linearScaleAttenuation);\n });\n }\n\n let return_component_conv_rec = component_conv_recs[component_conv_recs.length - 1];\n this.clearAllFilteredRecordedSignals();\n\n this.numSuccessfulCaptured = 0;\n this.#currentConvolution = this.systemConvolution;\n this.filteredMLSRange.system.Min = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.findMinValue)(this.#currentConvolution);\n this.filteredMLSRange.system.Max = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.findMaxValue)(this.#currentConvolution);\n this.soundCheck = 'system';\n\n this.addTimeStamp(`Record ${total_dur} s of MLS with ${this.soundCheck} IIR.”`)\n\n\n if (this.isCalibrating) return null;\n await this.playMLSwithIIR(stream, this.#currentConvolution);\n\n this.stopCalibrationAudio();\n\n let system_conv_recs = this.getAllFilteredRecordedSignals();\n\n if (this.systemAttenuatorGainDB != 0) {\n let linearScaleAttenuation = Math.pow(10, this.systemAttenuatorGainDB / 20);\n system_conv_recs = system_conv_recs.map(rec => {\n return rec.map(value => value / linearScaleAttenuation);\n });\n }\n\n let return_system_conv_rec = system_conv_recs[system_conv_recs.length - 1];\n // await this.checkPowerVariation(return_system_conv_rec);\n\n this.clearAllFilteredRecordedSignals();\n\n this.sourceAudioContext.close();\n let recs = this.getAllUnfilteredRecordedSignals();\n if (this.componentAttentuatorGainDB != 0) {\n let linearScaleAttenuation = Math.pow(10, this.componentAttentuatorGainDB / 20);\n recs = recs.map(rec => {\n return rec.map(value => value / this.linearScaleAttenuation);\n });\n }\n let unconv_rec = recs[0];\n let return_unconv_rec = unconv_rec;\n let conv_rec = component_conv_recs[component_conv_recs.length - 1];\n\n //psd of component\n let knownGain = this.oldComponentIR.Gain;\n let knownFreq = this.oldComponentIR.Freq;\n let sampleRate = this.sourceSamplingRate || 96000;\n this.addTimeStamp('Compute PSD of MLS recording');\n if (this.isCalibrating) return null;\n let component_unconv_rec_psd = await this.pyServerAPI\n .getSubtractedPSDWithRetry(unconv_rec, knownGain, knownFreq, sampleRate)\n .then(res => {\n this.incrementStatusBar();\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\n this.emit('update', {message: this.status});\n return res;\n })\n .catch(err => {\n console.error(err);\n });\n\n this.addTimeStamp('Compute PSD of filtered recording (component)');\n if (this.isCalibrating) return null;\n let component_conv_rec_psd = await this.pyServerAPI\n .getSubtractedPSDWithRetry(conv_rec, knownGain, knownFreq, sampleRate)\n .then(res => {\n let interpolatedGain = res.x.map((freq, index) => {\n let i = 0;\n while (i < knownFreq.length && knownFreq[i] < freq) {\n i++;\n }\n if (i === 0 || i === knownFreq.length) {\n return knownGain[i];\n }\n return (0,_utils__WEBPACK_IMPORTED_MODULE_1__.interpolate)(freq, knownFreq[i - 1], knownFreq[i], knownGain[i - 1], knownGain[i]);\n });\n\n let correctedGain = res.y.map(\n (gain, index) => 10 * Math.log10(gain) - interpolatedGain[index]\n );\n\n let filtered_psd = correctedGain.filter(\n (value, index) => res.x[index] >= this.#lowHz && res.x[index] <= this.componentFMaxHz\n );\n\n this.SDofFilteredRange['component'] = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.standardDeviation)(filtered_psd);\n this.incrementStatusBar();\n this.status =this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\n this.emit('update', {message: this.status});\n return res;\n })\n .catch(err => {\n console.error(err);\n });\n\n conv_rec = system_conv_recs[system_conv_recs.length - 1];\n //psd of system\n this.addTimeStamp('Compute PSD of filtered recording (system) and unfiltered recording');\n if (this.isCalibrating) return null;\n let system_recs_psd = await this.pyServerAPI\n .getPSDWithRetry({\n unconv_rec,\n conv_rec,\n sampleRate: this.sourceSamplingRate || 96000,\n })\n .then(res => {\n let filtered_psd = res.y_conv\n .filter(\n (value, index) => res.x_conv[index] >= this.#lowHz && res.x_conv[index] <= this.#highHz\n )\n .map(value => 10 * Math.log10(value));\n\n let mls_psd = res.y_unconv\n .filter(\n (value, index) =>\n res.x_unconv[index] >= this.#lowHz && res.x_conv[index] <= this.#highHz\n )\n .map(value => 10 * Math.log10(value));\n\n this.SDofFilteredRange['mls'] = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.standardDeviation)(mls_psd);\n console.log('mls_psd', this.SDofFilteredRange['mls']);\n this.SDofFilteredRange['system'] = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.standardDeviation)(filtered_psd);\n this.incrementStatusBar();\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\n this.emit('update', {message: this.status});\n return res;\n })\n .catch(err => {\n console.error(err);\n });\n\n //iir w/ and without bandpass psd. done\n unconv_rec = this.componentInvertedImpulseResponseNoBandpass;\n conv_rec = this.componentInvertedImpulseResponse;\n this.addTimeStamp('Compute PSD of component IIR and component IIR no band pass');\n if (this.isCalibrating) return null;\n let component_iir_psd = await this.pyServerAPI\n .getPSDWithRetry({\n unconv_rec,\n conv_rec,\n sampleRate: this.sourceSamplingRate || 96000,\n })\n .then(res => {\n this.incrementStatusBar();\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\n this.emit('update', {message: this.status});\n return res;\n })\n .catch(err => {\n console.error(err);\n });\n unconv_rec = this.systemInvertedImpulseResponseNoBandpass;\n conv_rec = this.systemInvertedImpulseResponse;\n this.addTimeStamp('Compute PSD of system IIR and system IIR no band pass');\n if (this.isCalibrating) return null;\n let system_iir_psd = await this.pyServerAPI\n .getPSDWithRetry({\n unconv_rec,\n conv_rec,\n sampleRate: this.sourceSamplingRate || 96000,\n })\n .then(res => {\n this.incrementStatusBar();\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString() ).toString();\n this.emit('update', {message: this.status});\n return res;\n })\n .catch(err => {\n console.error(err);\n });\n\n this.addTimeStamp('Compute PSD of MLS sequence');\n if (this.isCalibrating) return null;\n let mls_psd = await this.pyServerAPI\n .getMLSPSDWithRetry({\n mls: this.#mlsBufferView[0],\n sampleRate: this.sourceSamplingRate || 96000,\n })\n .then(res => {\n this.incrementStatusBar();\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\n this.emit('update', {message: this.status});\n return res;\n })\n .catch(err => {\n console.error(err);\n });\n\n this.addTimeStamp('Compute PSD of filtered MLS (system)');\n if (this.isCalibrating) return null;\n let system_filtered_mls_psd = await this.pyServerAPI\n .getMLSPSDWithRetry({\n mls: this.systemConvolution,\n sampleRate: this.sourceSamplingRate || 96000,\n })\n .then(res => {\n this.incrementStatusBar();\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString() ).toString();\n this.emit('update', {message: this.status});\n return res;\n })\n .catch(err => {\n console.error(err);\n });\n\n let system_no_bandpass_filtered_mls_psd = await this.pyServerAPI\n .getMLSPSDWithRetry({\n mls: this.systemConvolution,\n sampleRate: this.sourceSamplingRate || 96000,\n })\n .then(res => {\n this.incrementStatusBar();\n this.status =this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\n this.emit('update', {message: this.status});\n return res;\n })\n .catch(err => {\n console.error(err);\n });\n\n this.addTimeStamp('Compute PSD of filtered MLS (component)');\n if (this.isCalibrating) return null;\n let component_filtered_mls_psd = await this.pyServerAPI\n .getMLSPSDWithRetry({\n mls: this.componentConvolution,\n sampleRate: this.sourceSamplingRate || 96000,\n })\n .then(res => {\n this.incrementStatusBar();\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString() ).toString();\n this.emit('update', {message: this.status});\n return res;\n })\n .catch(err => {\n console.error(err);\n });\n\n let component_no_bandpass_filtered_mls_psd = await this.pyServerAPI\n .getMLSPSDWithRetry({\n mls: this.componentConvolutionNoBandpass,\n sampleRate: this.sourceSamplingRate || 96000,\n })\n .then(res => {\n this.incrementStatusBar();\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString() ).toString();\n this.emit('update', {message: this.status});\n return res;\n })\n .catch(err => {\n console.error(err);\n });\n\n let gainValue = this.getGainDBSPL();\n\n iir_ir_and_plots = {\n filtered_recording: {\n component: return_component_conv_rec,\n system: return_system_conv_rec,\n },\n unfiltered_recording: this.getAllUnfilteredRecordedSignals()[0],\n system: {\n iir: this.systemInvertedImpulseResponse,\n iir_no_bandpass: this.systemInvertedImpulseResponseNoBandpass,\n ir: this.systemIR,\n iir_psd: {\n y: system_iir_psd['y_conv'],\n x: system_iir_psd['x_conv'],\n y_no_bandpass: system_iir_psd['y_unconv'],\n x_no_bandpass: system_iir_psd['x_unconv'],\n },\n filtered_mls_psd: {\n x: system_filtered_mls_psd['x_mls'],\n y: system_filtered_mls_psd['y_mls'],\n },\n filtered_no_bandpass_mls_psd: {\n x: system_no_bandpass_filtered_mls_psd['x_mls'],\n y: system_no_bandpass_filtered_mls_psd['y_mls'],\n },\n convolution: this.systemConvolution,\n convolutionNoBandpass: this.systemConvolutionNoBandpass,\n psd: {\n unconv: {\n x: system_recs_psd['x_unconv'],\n y: system_recs_psd['y_unconv'],\n },\n conv: {\n x: system_recs_psd['x_conv'],\n y: system_recs_psd['y_conv'],\n },\n },\n },\n component: {\n iir: this.componentInvertedImpulseResponse,\n iir_no_bandpass: this.componentInvertedImpulseResponseNoBandpass,\n ir: this.componentIR,\n ir_origin: this.componentIROrigin,\n ir_in_time_domain: this.componentIRInTimeDomain,\n iir_psd: {\n y: component_iir_psd['y_conv'],\n x: component_iir_psd['x_conv'],\n y_no_bandpass: component_iir_psd['y_unconv'],\n x_no_bandpass: component_iir_psd['x_unconv'],\n },\n filtered_mls_psd: {\n x: component_filtered_mls_psd['x_mls'],\n y: component_filtered_mls_psd['y_mls'],\n },\n filtered_no_bandpass_mls_psd: {\n x: component_no_bandpass_filtered_mls_psd['x_mls'],\n y: component_no_bandpass_filtered_mls_psd['y_mls'],\n },\n convolution: this.componentConvolution,\n convolutionNoBandpass: this.componentConvolutionNoBandpass,\n psd: {\n unconv: {\n x: component_unconv_rec_psd['x'],\n y: component_unconv_rec_psd['y'],\n },\n conv: {\n x: component_conv_rec_psd['x'],\n y: component_conv_rec_psd['y'],\n },\n },\n gainDBSPL: gainValue,\n },\n mls: this.#mlsBufferView,\n mls_psd: {\n x: mls_psd['x_mls'],\n y: mls_psd['y_mls'],\n },\n autocorrelations: this.autocorrelations,\n impulseResponses: [],\n };\n\n return iir_ir_and_plots;\n };\n\n singleSoundCheck = async stream => {\n let iir_ir_and_plots;\n const pre = this._calibrateSoundBurstPreSec; \n const repeats = this._calibrateSoundBurstRepeats; \n const burst = this._calibrateSoundBurstSec; \n const post = this._calibrateSoundBurstPostSec; \n const total_dur = pre + repeats * burst + post;\n if (this._calibrateSoundCheck != 'system') {\n this.#currentConvolution = this.componentConvolution;\n this.filteredMLSRange.component.Min = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.findMinValue)(this.#currentConvolution);\n this.filteredMLSRange.component.Max = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.findMaxValue)(this.#currentConvolution);\n this.soundCheck = 'component';\n this.addTimeStamp(`Record ${total_dur} s of MLS with ${this.soundCheck} IIR.`)\n this.addTimeStamp(`Record ${total_dur} s of MLS with speaker or microphone IIR.`);\n if (this.isCalibrating) return null;\n await this.playMLSwithIIR(stream, this.#currentConvolution);\n this.stopCalibrationAudio();\n } else {\n this.#currentConvolution = this.systemConvolution;\n this.filteredMLSRange.system.Min = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.findMinValue)(this.#currentConvolution);\n this.filteredMLSRange.system.Max = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.findMaxValue)(this.#currentConvolution);\n this.soundCheck = 'system';\n this.addTimeStamp(`Record ${total_dur} s of MLS with ${this.soundCheck} IIR.`)\n this.addTimeStamp(`Record ${total_dur} s of MLS with speaker or microphone IIR.`);\n if (this.isCalibrating) return null;\n await this.playMLSwithIIR(stream, this.#currentConvolution);\n this.stopCalibrationAudio();\n }\n let conv_recs = this.getAllFilteredRecordedSignals();\n if (this._calibrateSoundCheck == 'goal') {\n if (this.componentAttentuatorGainDB != 0) {\n let linearScaleAttenuation = Math.pow(10, this.componentAttentuatorGainDB / 20);\n conv_recs = conv_recs.map(rec => {\n return rec.map(value => value / this.linearScaleAttenuation);\n });\n }\n } else if (this._calibrateSoundCheck == 'system') {\n if (this.systemAttentuatorGainDB != 0) {\n let linearScaleAttenuation = Math.pow(10, this.systemAttentuatorGainDB / 20);\n conv_recs = conv_recs.map(rec => {\n return rec.map(value => value / this.linearScaleAttenuation);\n });\n }\n }\n\n //remove the filteredMLSAttenuation from the recorded signals\n // conv_recs = conv_recs.map(rec => {\n // if (this.soundCheck === 'component') {\n // return rec.map(value => value / this.filteredMLSAttenuation.component);\n // }\n // return rec.map(value => value / this.filteredMLSAttenuation.system);\n // });\n\n let recs = this.getAllUnfilteredRecordedSignals();\n if (this._calibrateSoundCheck == 'goal') {\n if (this.componentAttentuatorGainDB != 0) {\n let linearScaleAttenuation = Math.pow(10, this.componentAttentuatorGainDB / 20);\n recs = recs.map(rec => {\n return rec.map(value => value / this.linearScaleAttenuation);\n });\n }\n } else if (this._calibrateSoundCheck == 'system') {\n if (this.systemAttentuatorGainDB != 0) {\n let linearScaleAttenuation = Math.pow(10, this.systemAttentuatorGainDB / 20);\n recs = recs.map(rec => {\n return rec.map(value => value / this.linearScaleAttenuation);\n });\n }\n }\n this.clearAllFilteredRecordedSignals();\n console.log('Obtaining unfiltered recording from #allHzUnfilteredRecordings to calculate PSD');\n console.log('Obtaining filtered recording from #allHzFilteredRecordings to calculate PSD');\n let unconv_rec = recs[0];\n let return_unconv_rec = unconv_rec;\n let conv_rec = conv_recs[conv_recs.length - 1];\n let return_conv_rec = conv_rec;\n this.sourceAudioContext.close();\n if (this._calibrateSoundCheck != 'system') {\n let knownGain = this.oldComponentIR.Gain;\n let knownFreq = this.oldComponentIR.Freq;\n let sampleRate = this.sourceSamplingRate || 96000;\n this.addTimeStamp('Compute PSD of MLS recording');\n if (this.isCalibrating) return null;\n let unconv_results = await this.pyServerAPI\n .getSubtractedPSDWithRetry(unconv_rec, knownGain, knownFreq, sampleRate)\n .then(res => {\n console.log(res);\n let mls_psd = res.y\n .filter(\n (value, index) => res.x[index] >= this.#lowHz && res.x[index] <= this.systemFMaxHz\n )\n .map(value => 10 * Math.log10(value));\n this.SDofFilteredRange['mls'] = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.standardDeviation)(mls_psd);\n console.log('mls sd', this.SDofFilteredRange['mls']);\n this.incrementStatusBar();\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\n this.emit('update', {message: this.status});\n return res;\n })\n .catch(err => {\n console.error(err);\n });\n\n this.addTimeStamp('Compute PSD recording of filtered recording (component)');\n if (this.isCalibrating) return null;\n let conv_results = await this.pyServerAPI\n .getSubtractedPSDWithRetry(conv_rec, knownGain, knownFreq, sampleRate)\n .then(res => {\n let interpolatedGain = res.x.map((freq, index) => {\n let i = 0;\n while (i < knownFreq.length && knownFreq[i] < freq) {\n i++;\n }\n if (i === 0 || i === knownFreq.length) {\n return knownGain[i];\n }\n return (0,_utils__WEBPACK_IMPORTED_MODULE_1__.interpolate)(\n freq,\n knownFreq[i - 1],\n knownFreq[i],\n knownGain[i - 1],\n knownGain[i]\n );\n });\n\n let correctedGain = res.y.map(\n (gain, index) => 10 * Math.log10(gain) - interpolatedGain[index]\n );\n let filtered_psd = correctedGain.filter(\n (value, index) => res.x[index] >= this.#lowHz && res.x[index] <= this.#highHz\n );\n\n this.SDofFilteredRange['component'] = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.standardDeviation)(filtered_psd);\n this.incrementStatusBar();\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\n this.emit('update', {message: this.status});\n return res;\n })\n .catch(err => {\n console.error(err);\n });\n\n unconv_rec = this.componentInvertedImpulseResponseNoBandpass;\n conv_rec = this.componentInvertedImpulseResponse;\n this.addTimeStamp('Compute PSD of component IIR and component IIR no bandpass');\n if (this.isCalibrating) return null;\n let component_iir_psd = await this.pyServerAPI\n .getPSDWithRetry({\n unconv_rec,\n conv_rec,\n sampleRate: this.sourceSamplingRate || 96000,\n })\n .then(res => {\n this.incrementStatusBar();\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\n this.emit('update', {message: this.status});\n return res;\n })\n .catch(err => {\n console.error(err);\n });\n unconv_rec = this.systemInvertedImpulseResponseNoBandpass;\n conv_rec = this.systemInvertedImpulseResponse;\n this.addTimeStamp('Compute PSD of system IIR and system IIR no bandpass');\n if (this.isCalibrating) return null;\n let system_iir_psd = await this.pyServerAPI\n .getPSDWithRetry({\n unconv_rec,\n conv_rec,\n sampleRate: this.sourceSamplingRate || 96000,\n })\n .then(res => {\n this.incrementStatusBar();\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\n this.emit('update', {message: this.status});\n return res;\n })\n .catch(err => {\n console.error(err);\n });\n\n this.addTimeStamp('Compute PSD of MLS sequence');\n if (this.isCalibrating) return null;\n let mls_psd = await this.pyServerAPI\n .getMLSPSDWithRetry({\n mls: this.#mlsBufferView[this.icapture],\n sampleRate: this.sourceSamplingRate || 96000,\n })\n .then(res => {\n this.incrementStatusBar();\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\n this.emit('update', {message: this.status});\n return res;\n })\n .catch(err => {\n console.error(err);\n });\n\n this.addTimeStamp('Compute PSD of filtered MLS (component)');\n if (this.isCalibrating) return null;\n let filtered_mls_psd = await this.pyServerAPI\n .getMLSPSDWithRetry({\n mls: this.componentConvolution,\n sampleRate: this.sourceSamplingRate || 96000,\n })\n .then(res => {\n this.incrementStatusBar();\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\n this.emit('update', {message: this.status});\n return res;\n })\n .catch(err => {\n console.error(err);\n });\n\n let filtered_no_bandpass_mls_psd = await this.pyServerAPI\n .getMLSPSDWithRetry({\n mls: this.componentConvolutionNoBandpass,\n sampleRate: this.sourceSamplingRate || 96000,\n })\n .then(res => {\n this.incrementStatusBar();\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\n this.emit('update', {message: this.status});\n return res;\n })\n .catch(err => {\n console.error(err);\n });\n\n let gainValue = this.getGainDBSPL();\n iir_ir_and_plots = {\n unfiltered_recording: return_unconv_rec,\n filtered_recording: return_conv_rec,\n system: {\n iir: this.systemInvertedImpulseResponse,\n iir_no_bandpass: this.systemInvertedImpulseResponseNoBandpass,\n ir: this.systemIR,\n iir_psd: {\n y: system_iir_psd['y_conv'],\n x: system_iir_psd['y_conv'],\n y_no_bandpass: system_iir_psd['y_unconv'],\n x_no_bandpass: system_iir_psd['x_unconv'],\n },\n filtered_recording: [],\n filtered_mls_psd: {},\n filtered_no_bandpass_mls_psd: {},\n convolution: this.systemConvolution,\n convolutionNoBandpass: this.systemConvolutionNoBandpass,\n psd: {\n unconv: {\n x: [],\n y: [],\n },\n conv: {\n x: [],\n y: [],\n },\n },\n },\n component: {\n iir: this.componentInvertedImpulseResponse,\n iir_no_bandpass: this.componentInvertedImpulseResponseNoBandpass,\n ir: this.componentIR,\n ir_origin: this.componentIROrigin,\n ir_in_time_domain: this.componentIRInTimeDomain,\n iir_psd: {\n y: component_iir_psd['y_conv'],\n x: component_iir_psd['x_conv'],\n y_no_bandpass: component_iir_psd['y_unconv'],\n x_no_bandpass: component_iir_psd['x_unconv'],\n },\n filtered_mls_psd: {\n x: filtered_mls_psd['x_mls'],\n y: filtered_mls_psd['y_mls'],\n },\n filtered_no_bandpass_mls_psd: {\n x: filtered_no_bandpass_mls_psd['x_mls'],\n y: filtered_no_bandpass_mls_psd['y_mls'],\n },\n convolution: this.componentConvolution,\n convolutionNoBandpass: this.componentConvolutionNoBandpass,\n psd: {\n unconv: {\n x: unconv_results['x'],\n y: unconv_results['y'],\n },\n conv: {\n x: conv_results['x'],\n y: conv_results['y'],\n },\n },\n gainDBSPL: gainValue,\n },\n mls: this.#mlsBufferView,\n mls_psd: {\n x: mls_psd['x_mls'],\n y: mls_psd['y_mls'],\n },\n autocorrelations: this.autocorrelations,\n impulseResponses: [],\n };\n } else {\n this.addTimeStamp('Compute PSD of filtered recording (system) and unfiltered recording');\n if (this.isCalibrating) return null;\n let results = await this.pyServerAPI\n .getPSDWithRetry({\n unconv_rec,\n conv_rec,\n sampleRate: this.sourceSamplingRate || 96000,\n })\n .then(res => {\n let filtered_psd = res.y_conv\n .filter(\n (value, index) =>\n res.x_conv[index] >= this.#lowHz && res.x_conv[index] <= this.systemFMaxHz\n )\n .map(value => 10 * Math.log10(value));\n\n let mls_psd = res.y_unconv\n .filter(\n (value, index) =>\n res.x_unconv[index] >= this.#lowHz && res.x_conv[index] <= this.systemFMaxHz\n )\n .map(value => 10 * Math.log10(value));\n this.SDofFilteredRange['mls'] = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.standardDeviation)(mls_psd);\n this.SDofFilteredRange['system'] = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.standardDeviation)(filtered_psd);\n this.incrementStatusBar();\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\n this.emit('update', {message: this.status});\n return res;\n })\n .catch(err => {\n console.error(err);\n });\n\n //iir w/ and without bandpass psd\n unconv_rec = this.componentInvertedImpulseResponseNoBandpass;\n conv_rec = this.componentInvertedImpulseResponse;\n this.addTimeStamp('Compute PSD of component IIR and component IIR no band pass');\n if (this.isCalibrating) return null;\n let component_iir_psd = await this.pyServerAPI\n .getPSDWithRetry({\n unconv_rec,\n conv_rec,\n sampleRate: this.sourceSamplingRate || 96000,\n })\n .then(res => {\n this.incrementStatusBar();\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\n this.emit('update', {message: this.status});\n return res;\n })\n .catch(err => {\n console.error(err);\n });\n unconv_rec = this.systemInvertedImpulseResponseNoBandpass;\n conv_rec = this.systemInvertedImpulseResponse;\n this.addTimeStamp('Compute PSD of system IIR and system IIR no band pass');\n if (this.isCalibrating) return null;\n let system_iir_psd = await this.pyServerAPI\n .getPSDWithRetry({\n unconv_rec,\n conv_rec,\n sampleRate: this.sourceSamplingRate || 96000,\n })\n .then(res => {\n this.incrementStatusBar();\n this.status = this.generateTemplate( `All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\n this.emit('update', {message: this.status});\n return res;\n })\n .catch(err => {\n console.error(err);\n });\n\n this.addTimeStamp('Compute PSD of MLS sequence');\n if (this.isCalibrating) return null;\n let mls_psd = await this.pyServerAPI\n .getMLSPSDWithRetry({\n mls: this.#mlsBufferView[this.icapture],\n sampleRate: this.sourceSamplingRate || 96000,\n })\n .then(res => {\n this.incrementStatusBar();\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\n this.emit('update', {message: this.status});\n return res;\n })\n .catch(err => {\n console.error(err);\n });\n\n this.addTimeStamp('Compute PSD of filtered MLS (system)');\n if (this.isCalibrating) return null;\n let filtered_mls_psd = await this.pyServerAPI\n .getMLSPSDWithRetry({\n mls: this.systemConvolution,\n sampleRate: this.sourceSamplingRate || 96000,\n })\n .then(res => {\n this.incrementStatusBar();\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\n this.emit('update', {message: this.status});\n return res;\n })\n .catch(err => {\n console.error(err);\n });\n\n let filtered_no_bandpass_mls_psd = await this.pyServerAPI\n .getMLSPSDWithRetry({\n mls: this.systemConvolutionNoBandpass,\n sampleRate: this.sourceSamplingRate || 96000,\n })\n .then(res => {\n this.incrementStatusBar();\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\n this.emit('update', {message: this.status});\n return res;\n })\n .catch(err => {\n console.error(err);\n });\n\n let gainValue = this.getGainDBSPL();\n iir_ir_and_plots = {\n unfiltered_recording: return_unconv_rec,\n filtered_recording: return_conv_rec,\n system: {\n iir: this.systemInvertedImpulseResponse,\n iir_no_bandpass: this.systemInvertedImpulseResponseNoBandpass,\n ir: this.systemIR,\n iir_psd: {\n y: system_iir_psd['y_conv'],\n x: system_iir_psd['y_conv'],\n y_no_bandpass: system_iir_psd['y_unconv'],\n x_no_bandpass: system_iir_psd['x_unconv'],\n },\n filtered_recording: [],\n filtered_mls_psd: {\n x: filtered_mls_psd['x_mls'],\n y: filtered_mls_psd['y_mls'],\n },\n filtered_no_bandpass_mls_psd: {\n x: filtered_no_bandpass_mls_psd['x_mls'],\n y: filtered_no_bandpass_mls_psd['y_mls'],\n },\n convolution: this.systemConvolution,\n convolutionNoBandpass: this.systemConvolutionNoBandpass,\n psd: {\n unconv: {\n x: results['x_unconv'],\n y: results['y_unconv'],\n },\n conv: {\n x: results['x_conv'],\n y: results['y_conv'],\n },\n },\n },\n component: {\n iir: this.componentInvertedImpulseResponse,\n iir_no_bandpass: this.componentInvertedImpulseResponseNoBandpass,\n ir: this.componentIR,\n ir_origin: this.componentIROrigin,\n ir_in_time_domain: this.componentIRInTimeDomain,\n iir_psd: {\n y: component_iir_psd['y_conv'],\n x: component_iir_psd['x_conv'],\n y_no_bandpass: component_iir_psd['y_unconv'],\n x_no_bandpass: component_iir_psd['x_unconv'],\n },\n filtered_mls_psd: {},\n filtered_no_bandpass_mls_psd: {},\n convolution: this.componentConvolution,\n convolutionNoBandpass: this.componentConvolutionNoBandpass,\n psd: {\n unconv: {\n x: [],\n y: [],\n },\n conv: {\n x: [],\n y: [],\n },\n },\n gainDBSPL: gainValue,\n },\n mls: this.#mlsBufferView,\n mls_psd: {\n x: mls_psd['x_mls'],\n y: mls_psd['y_mls'],\n },\n autocorrelations: this.autocorrelations,\n impulseResponses: [],\n };\n }\n if (this.isCalibrating) return null;\n await Promise.all(this.impulseResponses).then(res => {\n for (let i = 0; i < res.length; i++) {\n if (res[i] != undefined) {\n iir_ir_and_plots['impulseResponses'].push(res[i]);\n }\n }\n });\n\n if (this.#download) {\n this.downloadSingleUnfilteredRecording();\n this.downloadSingleFilteredRecording();\n (0,_utils__WEBPACK_IMPORTED_MODULE_1__.saveToCSV)(this.#mls, 'MLS.csv');\n (0,_utils__WEBPACK_IMPORTED_MODULE_1__.saveToCSV)(this.componentConvolution, 'python_component_convolution_mls_iir.csv');\n (0,_utils__WEBPACK_IMPORTED_MODULE_1__.saveToCSV)(this.systemConvolution, 'python_system_convolution_mls_iir.csv');\n (0,_utils__WEBPACK_IMPORTED_MODULE_1__.saveToCSV)(this.componentInvertedImpulseResponse, 'componentIIR.csv');\n (0,_utils__WEBPACK_IMPORTED_MODULE_1__.saveToCSV)(this.systemInvertedImpulseResponse, 'systemIIR.csv');\n for (let i = 0; i < this.autocorrelations.length; i++) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_1__.saveToCSV)(this.autocorrelations[i], `autocorrelation_${i}`);\n }\n const computedIRagain = await Promise.all(this.impulseResponses).then(res => {\n for (let i = 0; i < res.length; i++) {\n if (res[i] != undefined) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_1__.saveToCSV)(res[i], `IR_${i}`);\n }\n }\n });\n }\n\n return iir_ir_and_plots;\n };\n\n /**\n * Public method to start the calibration process. Objects intialized from webassembly allocate new memory\n * and must be manually freed. This function is responsible for intializing the MlsGenInterface,\n * and wrapping the calibration steps with a garbage collection safe gaurd.\n *\n * @public\n * @param stream - The stream of audio from the Listener.\n * @example\n */\n startCalibrationImpulseResponse = async stream => {\n console.log('JS used memory:', performance.memory.usedJSHeapSize / 1024 / 1024, 'mb');\n let desired_time = this.desired_time_per_mls;\n let checkRec = 'allhz';\n\n console.log('MLS sequence should be of length: ' + this.sourceSamplingRate * desired_time);\n\n length = this.sourceSamplingRate * desired_time;\n //get mls here\n // const calibrateSoundBurstDb = Math.pow(10, this._calibrateSoundBurstDb / 20);\n\n this.power_dB = 0;\n\n if (!this._calibrateSoundBurstLevelReTBool) {\n this.power_dB = this._calibrateSoundBurstDb;\n } else {\n this.power_dB = this._calibrateSoundBurstDb + (this.T - this.gainDBSPL);\n }\n\n const amplitude = Math.pow(10, this.power_dB / 20);\n //MLSpower = Math.pow(10,this.power_dB/20);\n this.addTimeStamp('Compute MLS sequence');\n if (this.isCalibrating) return null;\n await this.pyServerAPI\n .getMLSWithRetry({\n length,\n amplitude,\n calibrateSoundBurstMLSVersions: this.numCaptures,\n })\n .then(res => {\n console.log(res);\n this.#mlsBufferView = res['mls'];\n this.#mls = res['unscaledMLS'];\n })\n .catch(err => {\n // this.emit('InvertedImpulseResponse', {res: false});\n console.error(err);\n });\n this.numSuccessfulBackgroundCaptured = 0;\n if (this._calibrateSoundBackgroundSecs > 0) {\n this.mode = 'background';\n this.status = this.generateTemplate(`All Hz Calibration: sampling the background noise...`.toString()).toString();\n this.emit('update', {message: this.status});\n if (this.isCalibrating) return null;\n await this.recordBackground(\n stream, //stream\n () => this.numSuccessfulBackgroundCaptured < 1, //loop condition\n this.#awaitBackgroundNoiseRecording, //sleep to record\n this.sendBackgroundRecording, //send to get PSD\n this.mode,\n checkRec\n );\n this.incrementStatusBar();\n }\n this.mode = 'unfiltered';\n this.numSuccessfulCaptured = 0;\n\n if (this.isCalibrating) return null;\n for (var i = 0; i < this.numCaptures; i++) {\n this.icapture = i;\n await this.calibrationSteps(\n stream,\n this.#playCalibrationAudio, // play audio func (required)\n this.#createCalibrationNodeFromBuffer(this.#mlsBufferView[this.icapture]), // before play func\n this.#awaitSignalOnset, // before record\n () => this.numSuccessfulCaptured < 2, // loop while true\n this.#awaitDesiredMLSLength, // during record\n this.#afterMLSRecord, // after record\n this.mode,\n checkRec\n );\n this.stopCalibrationAudio();\n }\n checkRec = false;\n\n // at this stage we've captured all the required signals,\n // and have received IRs for each one\n // so let's send all the IRs to the server to be converted to a single IIR\n if (this.isCalibrating) return null;\n await this.sendSystemImpulseResponsesToServerForProcessing();\n await this.pyServerAPI.checkMemory();\n if (this.isCalibrating) return null;\n await this.sendComponentImpulseResponsesToServerForProcessing();\n\n this.numSuccessfulCaptured = 0;\n\n let iir_ir_and_plots;\n if (this._calibrateSoundCheck != 'none') {\n //do single check\n if (this._calibrateSoundCheck == 'goal' || this._calibrateSoundCheck == 'system') {\n if (this.isCalibrating) return null;\n iir_ir_and_plots = await this.singleSoundCheck(stream);\n if (this.isCalibrating) return null;\n } else {\n //both\n if (this.isCalibrating) return null;\n iir_ir_and_plots = await this.bothSoundCheck(stream);\n if (this.isCalibrating) return null;\n }\n } else {\n let unconv_rec = this.componentInvertedImpulseResponseNoBandpass;\n let conv_rec = this.componentInvertedImpulseResponse;\n if (this.isCalibrating) return null;\n let component_iir_psd = await this.pyServerAPI\n .getPSDWithRetry({\n unconv_rec,\n conv_rec,\n sampleRate: this.sourceSamplingRate || 96000,\n })\n .then(res => {\n this.incrementStatusBar();\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\n this.emit('update', {message: this.status});\n return res;\n })\n .catch(err => {\n console.error(err);\n });\n unconv_rec = this.systemInvertedImpulseResponseNoBandpass;\n conv_rec = this.systemInvertedImpulseResponse;\n if (this.isCalibrating) return null;\n let system_iir_psd = await this.pyServerAPI\n .getPSDWithRetry({\n unconv_rec,\n conv_rec,\n sampleRate: this.sourceSamplingRate || 96000,\n })\n .then(res => {\n this.incrementStatusBar();\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\n this.emit('update', {message: this.status});\n return res;\n })\n .catch(err => {\n console.error(err);\n });\n\n let gainValue = this.getGainDBSPL();\n iir_ir_and_plots = {\n unfiltered_recording: return_unconv_rec,\n filtered_recording: return_conv_rec,\n system: {\n iir: this.systemInvertedImpulseResponse,\n iir_no_bandpass: this.systemInvertedImpulseResponseNoBandpass,\n ir: this.systemIR,\n iir_psd: {\n y: system_iir_psd['y_conv'],\n x: system_iir_psd['y_conv'],\n y_no_bandpass: system_iir_psd['y_unconv'],\n x_no_bandpass: system_iir_psd['x_unconv'],\n },\n filtered_recording: [],\n convolution: this.systemConvolution,\n convolutionNoBandpass: this.systemConvolutionNoBandpass,\n psd: {\n unconv: {\n x: [],\n y: [],\n },\n conv: {\n x: [],\n y: [],\n },\n },\n },\n component: {\n iir: this.componentInvertedImpulseResponse,\n iir_no_bandpass: this.componentInvertedImpulseResponseNoBandpass,\n ir: this.componentIR,\n ir_in_time_domain: this.componentIRInTimeDomain,\n iir_psd: {\n y: component_iir_psd['y_conv'],\n x: component_iir_psd['x_conv'],\n y_no_bandpass: component_iir_psd['y_unconv'],\n x_no_bandpass: component_iir_psd['x_unconv'],\n },\n convolution: this.componentConvolution,\n convolutionNoBandpass: this.componentConvolutionNoBandpass,\n psd: {\n unconv: {\n x: [],\n y: [],\n },\n conv: {\n x: [],\n y: [],\n },\n },\n gainDBSPL: gainValue,\n },\n mls: this.#mlsBufferView,\n autocorrelations: this.autocorrelations,\n impulseResponses: [],\n };\n if (this.isCalibrating) return null;\n await Promise.all(this.impulseResponses).then(res => {\n for (let i = 0; i < res.length; i++) {\n if (res[i] != undefined) {\n iir_ir_and_plots['impulseResponses'].push(res[i]);\n }\n }\n });\n\n if (this.#download) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_1__.saveToCSV)(this.#mls, 'MLS.csv');\n (0,_utils__WEBPACK_IMPORTED_MODULE_1__.saveToCSV)(this.componentConvolution, 'python_component_convolution_mls_iir.csv');\n (0,_utils__WEBPACK_IMPORTED_MODULE_1__.saveToCSV)(this.systemConvolution, 'python_system_convolution_mls_iir.csv');\n (0,_utils__WEBPACK_IMPORTED_MODULE_1__.saveToCSV)(this.componentInvertedImpulseResponse, 'componentIIR.csv');\n (0,_utils__WEBPACK_IMPORTED_MODULE_1__.saveToCSV)(this.systemInvertedImpulseResponse, 'systemIIR.csv');\n for (let i = 0; i < this.autocorrelations.length; i++) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_1__.saveToCSV)(this.autocorrelations[i], `autocorrelation_${i}`);\n }\n const computedIRagain = await Promise.all(this.impulseResponses).then(res => {\n for (let i = 0; i < res.length; i++) {\n if (res[i] != undefined) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_1__.saveToCSV)(res[i], `IR_${i}`);\n }\n }\n });\n }\n }\n if (this.isCalibrating) return null;\n this.percent_complete = 100;\n this.status = this.generateTemplate(`All Hz Calibration: Finished`.toString()).toString();\n this.emit('update', {message: this.status});\n\n //here after calibration we have the component calibration (either loudspeaker or microphone) in the same form as the componentIR\n //that was used to calibrate\n // saveToJSON(iir_ir_and_plots);\n return iir_ir_and_plots;\n };\n\n //////////////////////volume\n\n handleIncomingData = data => {\n console.log('Received data: ', data);\n if (data.type === 'soundGainDBSPL') {\n this.soundGainDBSPL = data.value;\n } else {\n throw new Error(`Unknown data type: ${data.type}`);\n }\n };\n\n #getTruncatedSignal = (left = 3.5, right = 4.5) => {\n const start = Math.floor(left * this.sourceSamplingRate);\n const end = Math.floor(right * this.sourceSamplingRate);\n const result = Array.from(this.getLastVolumeRecordedSignal().slice(start, end));\n console.log(\n 'Obtaining last 1000 hz recording from #allVolumeRecordings to send for processing'\n );\n /**\n * function to check that capture was properly made\n * @param {*} list\n */\n const checkResult = list => {\n const setItem = new Set(list);\n if (setItem.size === 1 && setItem.has(0)) {\n console.warn(\n 'The last capture failed, all recorded signal is zero',\n this.getAllVolumeRecordedSignals()\n );\n this.stopCalibrationAudio();\n this.isCalibrating = true;\n // restartButton.style.display = 'none';\n this.emit('update', {message: 'Connection failed, hit restart button to reconnect'});\n }\n if (setItem.size === 0) {\n console.warn('The last capture failed, no recorded signal');\n this.stopCalibrationAudio();\n this.isCalibrating = true;\n // restartButton.style.display = 'none';\n this.emit('update', {message: 'Connection failed, hit restart button to reconnect'});\n }\n };\n checkResult(result);\n return result;\n };\n\n /** \n * \n * \n Construct a calibration Node with the calibration parameters and given gain value\n * @param {*} gainValue\n * */\n #createCalibrationToneWithGainValue = gainValue => {\n const audioContext = this.makeNewSourceAudioContext();\n const oscilator = audioContext.createOscillator();\n const gainNode = audioContext.createGain();\n const taperGainNode = audioContext.createGain();\n const offsetGainNode = audioContext.createGain();\n const totalDuration = this.CALIBRATION_TONE_DURATION * 1.2;\n\n oscilator.frequency.value = this.#CALIBRATION_TONE_FREQUENCY;\n oscilator.type = this.#CALIBRATION_TONE_TYPE;\n gainNode.gain.value = gainValue;\n\n oscilator.connect(gainNode);\n gainNode.connect(taperGainNode);\n const onsetCurve = this.createSCurveBuffer();\n taperGainNode.gain.setValueCurveAtTime(onsetCurve, 0, this.TAPER_SECS);\n taperGainNode.connect(offsetGainNode);\n const offsetCurve = this.createSCurveBuffer(false);\n offsetGainNode.gain.setValueCurveAtTime(\n offsetCurve,\n totalDuration - this.TAPER_SECS,\n this.TAPER_SECS\n );\n offsetGainNode.connect(audioContext.destination);\n\n const gainValuesOverTime = [];\n const sampleRate = this.#CALIBRATION_TONE_FREQUENCY; // Number of samples per second\n const interval = 1 / sampleRate; // Time between samples\n\n for (let t = 0; t <= totalDuration; t += interval) {\n let gainValueAtTime = gainValue;\n\n // Apply the onset curve\n if (t < this.TAPER_SECS) {\n const onsetIndex = Math.floor((t / this.TAPER_SECS) * onsetCurve.length);\n gainValueAtTime *= onsetCurve[onsetIndex];\n }\n\n // Apply the offset curve\n if (t > totalDuration - this.TAPER_SECS) {\n const offsetTime = t - (totalDuration - this.TAPER_SECS);\n const offsetIndex = Math.floor((offsetTime / this.TAPER_SECS) * offsetCurve.length);\n gainValueAtTime *= offsetCurve[offsetIndex];\n }\n\n gainValuesOverTime.push(gainValueAtTime);\n }\n\n this.waveforms['volume'][this.inDB] = gainValuesOverTime;\n\n this.addCalibrationNode(oscilator);\n };\n\n /**\n * Construct a Calibration Node with the calibration parameters.\n *\n * @private\n * @example\n */\n #createCalibrationNode = () => {\n const audioContext = this.makeNewSourceAudioContext();\n const oscilator = audioContext.createOscillator();\n const gainNode = audioContext.createGain();\n\n oscilator.frequency.value = this.#CALIBRATION_TONE_FREQUENCY;\n oscilator.type = this.#CALIBRATION_TONE_TYPE;\n gainNode.gain.value = 0.04;\n\n oscilator.connect(gainNode);\n gainNode.connect(audioContext.destination);\n\n this.addCalibrationNode(oscilator);\n };\n\n #playCalibrationAudioVolume = async () => {\n if (this.numCalibratingRoundsCompleted==1) {\n this.recordingChecks['warnings'].push(`1000Hz. Re-recorded ${this.inDB} dB because SD ${(this.recordingChecks['volume'][this.inDB]['sd'])} > ${this.calibrateSound1000HzMaxSD_dB} dB`);\n const currentStatus = `1000 Hz: Re-recording at ${this.inDB} dB because SD \n ${this.recordingChecks['volume'][this.inDB]['sd']} > \n ${this.calibrateSound1000HzMaxSD_dB} dB`.toString();\n this.status = this.generateTemplate(currentStatus).toString();\n this.emit('update', {\n message: this.status,\n });\n }\n const totalDuration = this.CALIBRATION_TONE_DURATION * 1.2;\n\n this.calibrationNodes[0].start(0);\n this.calibrationNodes[0].stop(totalDuration);\n console.log(`Playing a buffer of ${this.CALIBRATION_TONE_DURATION} seconds of audio`);\n console.log(`Waiting a total of ${totalDuration} seconds`);\n await (0,_utils__WEBPACK_IMPORTED_MODULE_1__.sleep)(totalDuration);\n };\n\n stopCalibrationAudioVolume = () => {\n if (this.calibrationNodes.length > 0) {\n this.calibrationNodes[0].stop();\n }\n };\n\n #sendToServerForProcessing = async lCalib => {\n console.log('Sending data to server');\n const total_dur = this.calibrateSound1000HzPreSec + this.calibrateSound1000HzSec + this.calibrateSound1000HzPostSec;\n this.addTimeStamp(\n \"1000 Hz: recorded at \" + this.inDB + \n \" dB (\" + this.calibrateSound1000HzPreSec.toFixed(1) + \n \" s pre + \" + this.calibrateSound1000HzSec.toFixed(1) + \n \" s used + \" + this.calibrateSound1000HzPostSec.toFixed(1) + \n \" s post)\"\n );\n let left = this.calibrateSound1000HzPreSec;\n let right = this.calibrateSound1000HzPreSec + this.calibrateSound1000HzSec;\n if (this.isCalibrating) return null;\n this.pyServerAPI\n .getVolumeCalibration({\n sampleRate: this.sourceSamplingRate,\n payload: this.#getTruncatedSignal(left, right),\n lCalib: lCalib,\n })\n .then(res => {\n if (this.outDBSPL === null) {\n this.incrementStatusBar();\n this.outDBSPL = res['outDbSPL'];\n this.outDBSPL1000 = res['outDbSPL1000'];\n this.THD = res['thd'];\n }\n })\n .catch(err => {\n console.warn(err);\n });\n const rec = this.getLastVolumeRecordedSignal();\n console.log('pre period power: ', (0,_powerCheck__WEBPACK_IMPORTED_MODULE_2__.getPower)(rec.slice(0,this.calibrateSound1000HzPreSec * this.sourceSamplingRate)).toFixed(1));\n console.log('pre period power: ', \n (0,_powerCheck__WEBPACK_IMPORTED_MODULE_2__.getPower)(rec.slice(\n this.calibrateSound1000HzPreSec * this.sourceSamplingRate,\n (this.calibrateSound1000HzPreSec + this.calibrateSound1000HzSec)* this.sourceSamplingRate)).toFixed(1));\n console.log('pre period power: ', (0,_powerCheck__WEBPACK_IMPORTED_MODULE_2__.getPower)(rec.slice(\n (this.calibrateSound1000HzPreSec + this.calibrateSound1000HzSec)* this.sourceSamplingRate)).toFixed(1));\n const res = (0,_powerCheck__WEBPACK_IMPORTED_MODULE_2__.volumePowerCheck)(\n rec,\n this.sourceSamplingRate || 96000,\n this.calibrateSound1000HzPreSec,\n this.calibrateSound1000HzSec, \n this._calibrateSoundPowerBinDesiredSec);\n console.log(res);\n this.recordingChecks['volume'][this.inDB] = res;\n };\n\n startCalibrationVolume = async (stream, gainValues, lCalib, componentGainDBSPL) => {\n if (this.isCalibrating) return null;\n const trialIterations = gainValues.length;\n this.status_denominator += trialIterations;\n const thdValues = [];\n const inDBValues = [];\n let inDB = 0;\n const outDBSPLValues = [];\n const outDBSPL1000Values = [];\n let checkRec = 'loudest';\n // do one calibration that will be discarded\n const soundLevelToDiscard = -60;\n const gainToDiscard = Math.pow(10, soundLevelToDiscard / 20);\n this.inDB = soundLevelToDiscard;\n this.status = this.generateTemplate(`1000 Hz Calibration: Sound Level ${soundLevelToDiscard} dB`.toString()).toString();\n //this.emit('update', {message: `1000 Hz Calibration: Sound Level ${soundLevelToDiscard} dB`});\n this.emit('update', {message: this.status});\n this.startTime = new Date().getTime();\n\n do {\n console.log('while loop');\n if (this.isCalibrating) {\n console.log('restart calibration');\n return null;\n }\n // eslint-disable-next-line no-await-in-loop\n await this.volumeCalibrationSteps(\n stream,\n this.#playCalibrationAudioVolume,\n this.#createCalibrationToneWithGainValue,\n this.#sendToServerForProcessing,\n gainToDiscard,\n lCalib, //todo make this a class parameter\n checkRec,\n () => {return this.recordingChecks['volume'][this.inDB]['sd']},\n this.calibrateSound1000HzMaxSD_dB\n );\n } while (this.outDBSPL === null);\n //reset the values\n //this.incrementStatusBar();\n\n this.outDBSPL = null;\n this.outDBSPL = null;\n this.outDBSPL1000 = null;\n this.THD = null;\n\n // run the calibration at different gain values provided by the user\n for (let i = 0; i < trialIterations; i++) {\n //convert gain to DB and add to inDB\n if (i == trialIterations - 1) {\n checkRec = 'loudest';\n }\n inDB = Math.log10(gainValues[i]) * 20;\n // precision to 1 decimal place\n inDB = Math.round(inDB * 10) / 10;\n this.inDB = inDB;\n inDBValues.push(inDB);\n console.log('next update');\n this.status = this.generateTemplate(`1000 Hz Calibration: Sound Level ${inDB} dB`.toString()).toString();\n this.emit('update', {message: this.status});\n do {\n if (this.isCalibrating) {\n console.log('restart calibration');\n return null;\n }\n // eslint-disable-next-line no-await-in-loop\n await this.volumeCalibrationSteps(\n stream,\n this.#playCalibrationAudioVolume,\n this.#createCalibrationToneWithGainValue,\n this.#sendToServerForProcessing,\n gainValues[i],\n lCalib, //todo make this a class parameter\n checkRec,\n () => {return this.recordingChecks?.['volume']?.[this.inDB]?.['sd'] || 0},\n this.calibrateSound1000HzMaxSD_dB\n );\n } while (this.outDBSPL === null);\n outDBSPL1000Values.push(this.outDBSPL1000);\n thdValues.push(this.THD);\n outDBSPLValues.push(this.outDBSPL);\n\n this.outDBSPL = null;\n this.outDBSPL1000 = null;\n this.THD = null;\n }\n if (this.isCalibrating) return null;\n // get the volume calibration parameters from the server\n this.addTimeStamp('Compute sound calibration parameters');\n\n const parameters = await this.pyServerAPI\n .getVolumeCalibrationParameters({\n inDBValues: inDBValues,\n outDBSPLValues: outDBSPL1000Values,\n lCalib: lCalib,\n componentGainDBSPL,\n })\n .then(res => {\n this.incrementStatusBar();\n return res;\n });\n if (this.isCalibrating) return null;\n const result = {\n parameters: parameters,\n inDBValues: inDBValues,\n outDBSPLValues: outDBSPLValues,\n outDBSPL1000Values: outDBSPL1000Values,\n thdValues: thdValues,\n };\n\n return result;\n };\n\n writeFrqGainToFirestore = async (speakerID, frq, gain, OEM, documentID) => {\n // freq and gain are too large to take samples 1 in every 100 samples\n // const sampledFrq = [];\n // const sampledGain = [];\n // for (let i = 0; i < frq.length; i += 100) {\n // sampledFrq.push(frq[i]);\n // sampledGain.push(gain[i]);\n // }\n\n const data = {Freq: frq, Gain: gain};\n\n const docRef = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.doc)(_config_firebase__WEBPACK_IMPORTED_MODULE_3__[\"default\"], 'Microphones', documentID);\n await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.updateDoc)(docRef, {\n linear: data,\n });\n\n // divide frq and gain into smaller chunks and write to firestore one chunk at a time\n // use arrayUnion to append to the array\n // const chunkSize = 600;\n // const chunkedFrq = [];\n // const chunkedGain = [];\n // for (let i = 0; i < frq.length; i += chunkSize) {\n // chunkedFrq.push(frq.slice(i, i + chunkSize));\n // chunkedGain.push(gain.slice(i, i + chunkSize));\n // }\n // const docRef = doc(database, 'Microphones', documentID);\n // for (let i = 0; i < chunkedFrq.length; i++) {\n // await updateDoc(docRef, {\n // linear: {\n // Freq: arrayUnion(...chunkedFrq[i]),\n // Gain: arrayUnion(...chunkedGain[i]),\n // },\n // });\n // }\n };\n // function to write frq and gain to firebase database given speakerID\n writeFrqGain = async (speakerID, frq, gain, OEM) => {\n // freq and gain are too large to take samples 1 in every 100 samples\n\n const sampledFrq = [];\n const sampledGain = [];\n for (let i = 0; i < frq.length; i += 100) {\n sampledFrq.push(frq[i]);\n sampledGain.push(gain[i]);\n }\n\n const data = {Freq: sampledFrq, Gain: sampledGain};\n\n await (0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.set)((0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_3__[\"default\"], `Microphone2/${OEM}/${speakerID}/linear`), data);\n };\n\n // Function to Read frq and gain from firebase database given speakerID\n // returns an array of frq and gain if speakerID exists, returns null otherwise\n readFrqGainFromFirestore = async (speakerID, OEM, isDefault) => {\n const collectionRef = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.collection)(_config_firebase__WEBPACK_IMPORTED_MODULE_3__[\"default\"], 'Microphones');\n const q = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.query)(\n collectionRef,\n (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.where)('ID', '==', speakerID),\n (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.where)('lowercaseOEM', '==', OEM),\n (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.where)('isDefault', '==', isDefault)\n );\n const querySnapshot = await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.getDocs)(q);\n // if exists return the linear field of the first document\n if (querySnapshot.size > 0) {\n const timestamp = new firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.Timestamp(\n querySnapshot.docs[0].data().createDate.seconds,\n querySnapshot.docs[0].data().createDate.nanoseconds\n );\n return {\n ir: querySnapshot.docs[0].data().linear,\n createDate: timestamp.toDate(),\n jsonFileName: querySnapshot.docs[0].data().jsonFileName,\n };\n }\n return null;\n };\n readFrqGain = async (speakerID, OEM) => {\n const dbRef = (0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_3__[\"default\"]);\n const snapshot = await (0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.get)((0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.child)(dbRef, `Microphone2/${OEM}/${speakerID}/linear`));\n if (snapshot.exists()) {\n return snapshot.val();\n }\n return null;\n };\n readGainat1000HzFromFirestore = async (speakerID, OEM, isDefault) => {\n const collectionRef = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.collection)(_config_firebase__WEBPACK_IMPORTED_MODULE_3__[\"default\"], 'Microphones');\n const q = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.query)(\n collectionRef,\n (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.where)('ID', '==', speakerID),\n (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.where)('lowercaseOEM', '==', OEM),\n (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.where)('isDefault', '==', isDefault)\n );\n const querySnapshot = await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.getDocs)(q);\n // if exists return the Gain1000 field of the first document\n if (querySnapshot.size > 0) {\n return querySnapshot.docs[0].data().Gain1000;\n }\n return null;\n };\n\n readGainat1000Hz = async (speakerID, OEM) => {\n const dbRef = (0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_3__[\"default\"]);\n const snapshot = await (0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.get)((0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.child)(dbRef, `Microphone2/${OEM}/${speakerID}/Gain1000`));\n if (snapshot.exists()) {\n return snapshot.val();\n }\n return null;\n };\n\n writeGainat1000HzToFirestore = async (speakerID, gain, OEM, documentID) => {\n const docRef = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.doc)(_config_firebase__WEBPACK_IMPORTED_MODULE_3__[\"default\"], 'Microphones', documentID);\n await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.updateDoc)(docRef, {\n Gain1000: gain,\n });\n };\n\n writeGainat1000Hz = async (speakerID, gain, OEM) => {\n await (0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.set)((0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_3__[\"default\"], `Microphone2/${OEM}/${speakerID}/Gain1000`), gain);\n };\n\n writeIsSmartPhoneToFirestore = async (speakerID, isSmartPhone, OEM) => {\n const collectionRef = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.collection)(_config_firebase__WEBPACK_IMPORTED_MODULE_3__[\"default\"], 'Microphones');\n const q = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.query)(\n collectionRef,\n (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.where)('ID', '==', speakerID),\n (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.where)('lowercaseOEM', '==', OEM),\n (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.where)('isDefault', '==', true)\n );\n const querySnapshot = await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.getDocs)(q);\n if (querySnapshot.size > 0) {\n const docRef = await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.addDoc)(collectionRef, {isSmartPhone: isSmartPhone, isDefault: false});\n return docRef.id;\n } else {\n const docRef = await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.addDoc)(collectionRef, {isSmartPhone: isSmartPhone, isDefault: true});\n return docRef.id;\n }\n };\n\n writeIsSmartPhone = async (speakerID, isSmartPhone, OEM) => {\n const data = {isSmartPhone: isSmartPhone};\n await (0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.set)((0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_3__[\"default\"], `Microphone2/${OEM}/${speakerID}/isSmartPhone`), isSmartPhone);\n };\n\n writeMicrophoneInfoToFirestore = async (speakerID, micInfo, OEM, documentID) => {\n const docRef = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.doc)(_config_firebase__WEBPACK_IMPORTED_MODULE_3__[\"default\"], 'Microphones', documentID);\n await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.setDoc)(docRef, micInfo, {merge: true});\n };\n\n doesMicrophoneExistInFirestore = async (speakerID, OEM, documentID) => {\n const docRef = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.doc)(_config_firebase__WEBPACK_IMPORTED_MODULE_3__[\"default\"], 'Microphone', OEM, speakerID, documentID);\n const docSnap = await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.getDoc)(docRef);\n if (docSnap.exists()) {\n return true;\n }\n return false;\n };\n\n doesMicrophoneExist = async (speakerID, OEM) => {\n const dbRef = (0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_3__[\"default\"]);\n const snapshot = await (0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.get)((0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.child)(dbRef, `Microphone2/${OEM}/${speakerID}`));\n if (snapshot.exists()) {\n return true;\n }\n return false;\n };\n\n addMicrophoneInfo = async (speakerID, OEM, micInfo) => {\n // add to database if /info does not exist\n const dbRef = (0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_3__[\"default\"]);\n const snapshot = await (0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.get)((0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.child)(dbRef, `Microphone2/${OEM}/${speakerID}/info`));\n if (!snapshot.exists()) {\n await (0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.set)((0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_3__[\"default\"], `Microphone2/${OEM}/${speakerID}/info`), micInfo);\n }\n };\n\n convertToDB = gain => {\n return Math.log10(gain) * 20;\n };\n\n // Function to perform linear interpolation between two points\n interpolate(x, x0, y0, x1, y1) {\n return y0 + ((x - x0) * (y1 - y0)) / (x1 - x0);\n }\n\n findGainatFrequency = (frequencies, gains, targetFrequency) => {\n // Find the index of the first frequency in the array greater than the target frequency\n let index = 0;\n while (index < frequencies.length && frequencies[index] < targetFrequency) {\n index++;\n }\n\n // Handle cases when the target frequency is outside the range of the given data\n if (index === 0) {\n return gains[0];\n } else if (index === frequencies.length) {\n return gains[gains.length - 1];\n } else {\n // Interpolate the gain based on the surrounding frequencies\n const x0 = frequencies[index - 1];\n const y0 = gains[index - 1];\n const x1 = frequencies[index];\n const y1 = gains[index];\n return this.interpolate(targetFrequency, x0, y0, x1, y1);\n }\n };\n\n checkPowerVariation = async () => {\n let recordings = this.getAllFilteredRecordedSignals();\n // remove filteredMLSAttenuation from the recordings\n\n // recordings = recordings.map(recording => {\n // if (this.soundCheck == 'component') {\n // return recording.map(value => value / this.filteredMLSAttenuation.component);\n // }\n // return recording.map(value => value / this.filteredMLSAttenuation.system);\n // });\n\n const rec = recordings[recordings.length - 1];\n\n await this.pyServerAPI\n .allHzPowerCheck({\n payload: rec,\n sampleRate: this.sourceSamplingRate || 96000,\n binDesiredSec: this._calibrateSoundPowerBinDesiredSec,\n burstSec: this.desired_time_per_mls,\n repeats: this.numMLSPerCapture - this.num_mls_to_skip ,\n warmUp: this.num_mls_to_skip \n })\n .then(result => {\n if (result) {\n if (result['sd'] > this._calibrateSoundBurstMaxSD_dB && this.numSuccessfulCaptured == 0) {\n console.log('filtered recording sd too high');\n this.recordingChecks['warnings'].push(`All Hz. Re-recorded ${this.inDB} because SD ${result['sd']} > ${this._calibrateSoundBurstMaxSD_dB} dB`);\n this.status = this.generateTemplate(`All Hz: Re-recording at ${this.inDB} dB because SD ${result['sd']} > ${this._calibrateSoundBurstMaxSD_dB} dB`.toString()).toString();\n this.emit('update', {\n message: this.status,\n });\n // numSuccessfulCaptured no longer to count number of successful capture but count attemps\n // is sd below _calibrateSoundBurstMaxSD_dB then count two attemps\n // else count one attemp\n this.numSuccessfulCaptured += 1;\n } else {\n this.recordingChecks[this.soundCheck].push(result);\n // Now we do at most 2 attempts if sd > _calibrateSoundBurstMaxSD_dB\n // Second attempt is the final\n if (this.numSuccessfulCaptured < 2) {\n this.numSuccessfulCaptured += 2;\n this.stepNum += 1;\n this.incrementStatusBar();\n console.log(\n 'after mls w iir record for some reason add numSucc capt ' + this.stepNum\n );\n this.status = this.generateTemplate(`All Hz Calibration: ${this.numSuccessfulCaptured} recording of convolved MLS captured`.toString()).toString();\n this.emit('update', {\n message: this.status,\n });\n }\n }\n }\n });\n };\n\n getGainDBSPL = () => {\n var freqIndex = this.componentIR.Freq.indexOf(1000);\n\n // If freqIndex is not -1 (meaning 1000 is found in the freq array)\n if (freqIndex !== -1) {\n // Get the corresponding gain value using the index\n var gainValue = this.componentIR.Gain[freqIndex];\n return gainValue;\n } else {\n console.log('Freq 1000 not found in the array.');\n return null;\n }\n };\n // Example of how to use the writeFrqGain and readFrqGain functions\n // writeFrqGain('speaker1', [1, 2, 3], [4, 5, 6]);\n // Speaker1 is the speakerID you want to write to in the database\n // readFrqGain('MiniDSPUMIK_1').then(data => console.log(data));\n // MiniDSPUMIK_1 is the speakerID with some Data in the database\n //adding gainDBSPL\n startCalibration = async (\n stream,\n gainValues,\n lCalib = 104.92978421490648,\n componentIR = null,\n microphoneName = 'MiniDSP-UMIK1-711-4754-vertical',\n _calibrateSoundCheck = 'goal', //GOAL PASSed in by default\n isSmartPhone = false,\n _calibrateSoundBurstDb = -18,\n _calibrateSoundBurstFilteredExtraDb = 6,\n _calibrateSoundBurstLevelReTBool = false,\n _calibrateSoundBurstUses1000HzGainBool = false,\n _calibrateSoundBurstRepeats = 3,\n _calibrateSoundBurstSec = 1,\n _calibrateSoundBurstPreSec = 1,\n _calibrateSoundBurstPostSec = 1,\n _calibrateSoundHz = 48000,\n _calibrateSoundIRSec = 0.2,\n _calibrateSoundIIRSec = 0.2,\n _calibrateSoundIIRPhase = 'linear',\n calibrateSound1000HzPreSec = 0.5,\n calibrateSound1000HzSec = 0.5,\n calibrateSound1000HzPostSec = 0.5,\n _calibrateSoundBackgroundSecs = 0,\n _calibrateSoundSmoothOctaves = 0.33,\n _calibrateSoundSmoothMinBandwidthHz = 200,\n _calibrateSoundPowerBinDesiredSec = 0.2,\n _calibrateSoundPowerDbSDToleratedDb = 1,\n _calibrateSoundTaperSec = 0.01,\n micManufacturer = '',\n micSerialNumber = '',\n micModelNumber = '',\n micModelName = '',\n calibrateMicrophonesBool,\n authorEmails,\n webAudioDeviceNames = {\n loudspeaker: 'loudspeaker',\n microphone: 'microphone',\n microphoneText: 'xxx XXX',\n },\n userIDs,\n restartButton,\n reminder,\n calibrateSoundLimit,\n _calibrateSoundBurstNormalizeBy1000HzGainBool = false,\n _calibrateSoundBurstScalarDB = 71,\n calibrateSound1000HzMaxSD_dB = 4,\n _calibrateSoundBurstMaxSD_dB = 4,\n calibrateSoundSamplingDesiredBits = 24,\n language,\n loudspeakerModelName='',\n phrases,\n\n ) => {\n this._calibrateSoundBurstPreSec = _calibrateSoundBurstPreSec;\n this._calibrateSoundBurstRepeats = _calibrateSoundBurstRepeats;\n this._calibrateSoundBurstSec = _calibrateSoundBurstSec;\n this.micModelName = micModelName;\n this.loudspeakerModelName = loudspeakerModelName;\n this.language = language;\n this.TAPER_SECS = _calibrateSoundTaperSec;\n this.calibrateSoundLimit = calibrateSoundLimit;\n this._calibrateSoundBurstDb = _calibrateSoundBurstDb;\n this._calibrateSoundBurstFilteredExtraDb = _calibrateSoundBurstFilteredExtraDb;\n this._calibrateSoundBurstLevelReTBool = _calibrateSoundBurstLevelReTBool;\n this.CALIBRATION_TONE_DURATION =\n calibrateSound1000HzPreSec + calibrateSound1000HzSec + calibrateSound1000HzPostSec;\n this.calibrateSound1000HzPreSec = calibrateSound1000HzPreSec;\n this.calibrateSound1000HzSec = calibrateSound1000HzSec;\n this.calibrateSound1000HzPostSec = calibrateSound1000HzPostSec;\n this.iirLength = Math.floor(_calibrateSoundIIRSec * this.sourceSamplingRate);\n this.irLength = Math.floor(_calibrateSoundIRSec * this.sourceSamplingRate);\n this.calibrateSoundIIRPhase = _calibrateSoundIIRPhase;\n this.num_mls_to_skip = Math.ceil(_calibrateSoundBurstPreSec / _calibrateSoundBurstSec);\n this._calibrateSoundBurstPostSec = _calibrateSoundBurstPostSec;\n this.numMLSPerCapture = _calibrateSoundBurstRepeats + this.num_mls_to_skip;\n this.desired_time_per_mls = _calibrateSoundBurstSec;\n this.desired_sampling_rate = _calibrateSoundHz;\n this._calibrateSoundBackgroundSecs = _calibrateSoundBackgroundSecs;\n this._calibrateSoundSmoothOctaves = _calibrateSoundSmoothOctaves;\n this._calibrateSoundSmoothMinBandwidthHz = _calibrateSoundSmoothMinBandwidthHz;\n this._calibrateSoundPowerBinDesiredSec = _calibrateSoundPowerBinDesiredSec;\n this._calibrateSoundBurstUses1000HzGainBool = _calibrateSoundBurstUses1000HzGainBool;\n this._calibrateSoundPowerDbSDToleratedDb = _calibrateSoundPowerDbSDToleratedDb;\n this._calibrateSoundBurstNormalizeBy1000HzGainBool =\n _calibrateSoundBurstNormalizeBy1000HzGainBool;\n this._calibrateSoundBurstScalarDB = _calibrateSoundBurstScalarDB;\n this.webAudioDeviceNames = webAudioDeviceNames;\n this.calibrateSoundSamplingDesiredBits = calibrateSoundSamplingDesiredBits;\n this.phrases = phrases;\n if (isSmartPhone) {\n const leftQuote = \"\\u201C\"; // “\n const rightQuote = \"\\u201D\"; // ”\n this.webAudioDeviceNames.microphone = this.deviceInfo.microphoneFromAPI;\n const quotedWebAudioMic = leftQuote + this.webAudioDeviceNames.microphone + rightQuote;\n const combinedMicText = this.micModelName + \" \" + quotedWebAudioMic;\n webAudioDeviceNames.microphoneText = this.phrases.RC_nameMicrophone[this.language]\n .replace(\"“xxx”\", combinedMicText)\n .replace(\"“XXX”\", combinedMicText);\n }\n // this.webAudioDeviceNames.microphoneText = this.webAudioDeviceNames.microphoneText\n // .replace('xxx', this.webAudioDeviceNames.microphone)\n // .replace('XXX', this.webAudioDeviceNames.microphone);\n //feed calibration goal here\n this._calibrateSoundCheck = _calibrateSoundCheck;\n this.calibrateSound1000HzMaxSD_dB = calibrateSound1000HzMaxSD_dB;\n this._calibrateSoundBurstMaxSD_dB = _calibrateSoundBurstMaxSD_dB;\n //check if a componentIR was given to the system, if it isn't check for the microphone. using dummy data here bc we need to\n //check the db based on the microphone currently connected\n\n //new lCalib found at top of calibration files *1000hz, make sure to correct\n //based on zeroing of 1000hz, search for \"*1000Hz\"\n const ID = isSmartPhone ? micModelNumber : micSerialNumber;\n const OEM = isSmartPhone\n ? micModelName === 'UMIK-1' || micModelName === 'UMIK-2'\n ? 'minidsp'\n : this.deviceInfo.OEM.toLowerCase().split(' ').join('')\n : micManufacturer.toLowerCase().split(' ').join('');\n // const ID = \"712-5669\";\n // const OEM = \"minidsp\";\n const micInfo = {\n micModelName: isSmartPhone ? micModelName : microphoneName,\n OEM: isSmartPhone\n ? micModelName === 'UMIK-1' || micModelName === 'UMIK-2'\n ? 'miniDSP'\n : this.deviceInfo.OEM\n : micManufacturer,\n ID: ID,\n createDate: new Date(),\n DateText: (0,_utils__WEBPACK_IMPORTED_MODULE_1__.getCurrentTimeString)(),\n HardwareName: isSmartPhone ? this.deviceInfo.hardwarename : microphoneName,\n hardwareFamily: isSmartPhone ? this.deviceInfo.hardwarefamily : microphoneName,\n HardwareModel: isSmartPhone ? this.deviceInfo.hardwaremodel : microphoneName,\n PlatformName: isSmartPhone ? this.deviceInfo.platformname : 'N/A',\n PlatformVersion: isSmartPhone ? this.deviceInfo.platformversion : 'N/A',\n DeviceType: isSmartPhone ? this.deviceInfo.devicetype : 'N/A',\n ID_from_51Degrees: isSmartPhone ? this.deviceInfo.DeviceId : 'N/A',\n calibrateMicrophonesBool: calibrateMicrophonesBool,\n screenHeight: this.deviceInfo.screenHeight,\n screenWidth: this.deviceInfo.screenWidth,\n webAudioDeviceNames: {\n loudspeaker: this.webAudioDeviceNames.loudspeaker,\n microphone: this.webAudioDeviceNames.microphone,\n },\n userIDs: userIDs,\n lowercaseOEM: OEM.toLowerCase().split(' ').join(''),\n };\n if (calibrateMicrophonesBool) {\n micInfo['authorEmails'] = authorEmails;\n }\n // if undefined in micInfo, set to empty string\n for (const [key, value] of Object.entries(micInfo)) {\n if (value === undefined) {\n micInfo[key] = '';\n }\n }\n\n // this.writeMicrophoneInfoToFirestore(ID, micInfo, OEM, 'default');\n // this.addMicrophoneInfo(ID, OEM, micInfo);\n if (componentIR == null) {\n //mode 'ir'\n //global variable this.componentIR must be set\n await this.readFrqGainFromFirestore(ID, OEM, true).then(data => {\n if (data !== null) {\n this.componentIR = data.ir;\n micInfo['parentTimestamp'] = data.createDate ? data.createDate : new Date();\n micInfo['parentFilenameJSON'] = data.jsonFileName ? data.jsonFileName : '';\n }\n });\n\n // await this.readFrqGain(ID, OEM).then(data => {\n // return data;\n // });\n\n // lCalib = await this.readGainat1000Hz(ID, OEM);\n lCalib = await this.readGainat1000HzFromFirestore(ID, OEM, true);\n micInfo['gainDBSPL'] = lCalib;\n // this.componentGainDBSPL = this.convertToDB(lCalib);\n this.componentGainDBSPL = lCalib;\n //TODO: if this call to database is unknown, cannot perform experiment => return false\n if (this.componentIR == null) {\n this.status =\n `Microphone (${OEM},${ID}) is not found in the database. Please add it to the database.`.toString();\n this.emit('update', {message: this.status});\n return false;\n }\n } else {\n this.transducerType = 'Microphone';\n this.componentIR = componentIR;\n lCalib = this.findGainatFrequency(this.componentIR.Freq, this.componentIR.Gain, 1000);\n // this.componentGainDBSPL = this.convertToDB(lCalib);\n this.componentGainDBSPL = lCalib;\n // await this.writeIsSmartPhone(ID, isSmartPhone, OEM);\n }\n\n this.oldComponentIR = JSON.parse(JSON.stringify(this.componentIR));\n\n return await new Promise(async (resolve, reject) => {\n // add event listner to params.restartButton to resolve the promise with a string: 'restart'\n\n if (reminder) {\n reminder.style.display = '';\n }\n if (restartButton) {\n restartButton.style.display = '';\n restartButton.addEventListener('click', () => {\n this.stopCalibrationAudio();\n this.isCalibrating = true;\n restartButton.style.display = 'none';\n if (reminder) {\n reminder.style.display = 'none';\n }\n this.emit('update', {message: 'Restarting calibration...'});\n resolve('restart');\n });\n }\n await this.pyServerAPI.checkMemory();\n // calibrate volume\n\n let volumeResults = await this.startCalibrationVolume(\n stream,\n gainValues,\n lCalib,\n this.componentGainDBSPL\n );\n if (!volumeResults) return;\n this.T = volumeResults['parameters']['T'];\n this.gainDBSPL = volumeResults['parameters']['gainDBSPL'];\n\n // end calibrate volume\n\n let impulseResponseResults = await this.startCalibrationImpulseResponse(stream);\n if (!impulseResponseResults) return;\n impulseResponseResults['background_noise'] = this.background_noise;\n impulseResponseResults['system']['background_noise'] = this.background_noise;\n impulseResponseResults['component']['background_noise'] = this.background_noise;\n\n //attenuate system background noise\n if (this.systemAttenuatorGainDB != 0) {\n let linearScaleAttenuation = Math.pow(10, this.systemAttenuatorGainDB / 20);\n let linearScalePowerAttenuation = Math.pow(10, this.systemAttenuatorGainDB / 10);\n impulseResponseResults['system']['background_noise']['recording'] = impulseResponseResults[\n 'background_noise'\n ]['recording'].map(value => value / linearScaleAttenuation);\n impulseResponseResults['system']['background_noise']['x_background'] =\n impulseResponseResults['background_noise']['x_background'];\n impulseResponseResults['system']['background_noise']['y_background'] =\n impulseResponseResults['background_noise']['y_background'].map(\n value => value / linearScalePowerAttenuation\n );\n }\n //attenuate component background noise\n if (this.componentAttentuatorGainDB != 0) {\n let linearScaleAttenuation = Math.pow(10, this.componentAttenuatorGainDB / 20);\n let linearScalePowerAttenuation = Math.pow(10, this.componentAttenuatorGainDB / 10);\n impulseResponseResults['component']['background_noise']['recording'] =\n impulseResponseResults['background_noise']['recording'].map(\n value => value / linearScaleAttenuation\n );\n impulseResponseResults['component']['background_noise']['x_background'] =\n impulseResponseResults['background_noise']['x_background'];\n impulseResponseResults['component']['background_noise']['y_background'] =\n impulseResponseResults['background_noise']['y_background'].map(\n value => value / linearScalePowerAttenuation\n );\n }\n impulseResponseResults['system']['attenuatorGainDB'] = this.systemAttenuatorGainDB;\n impulseResponseResults['component']['attenuatorGainDB'] = this.componentAttenuatorGainDB;\n impulseResponseResults['system']['fMaxHz'] = this.systemFMaxHz;\n impulseResponseResults['component']['fMaxHz'] = this.componentFMaxHz;\n impulseResponseResults['L_new_n'] = this.L_new_n;\n impulseResponseResults['fs2'] = this.fs2;\n\n if (componentIR != null) {\n // I corrected microphone/loudpeaker IR scale in easyeyes,\n // but since we write microphone IR to firestore here\n // we need to correct microphone IR here\n let correctGain =\n Math.round((volumeResults.parameters.gainDBSPL - this.componentGainDBSPL) * 10) / 10;\n\n let IrFreq = impulseResponseResults?.component.ir.Freq.map(freq => Math.round(freq));\n let IrGain = impulseResponseResults?.component?.ir.Gain;\n const IrGainAt1000Hz = IrGain[IrFreq.findIndex(freq => freq === 1000)];\n const difference = Math.round(10 * (IrGainAt1000Hz - correctGain)) / 10;\n IrGain = IrGain.map(gain => gain - difference);\n micInfo['mls'] = Number(this.SDofFilteredRange['mls']);\n micInfo['systemCorrectionSD'] = Number(this.SDofFilteredRange['system']);\n micInfo['componentCorrectionSD'] = Number(this.SDofFilteredRange['component']);\n console.log(typeof micInfo['componentCorrectionSD']);\n // const id = await this.writeIsSmartPhoneToFirestore(ID, isSmartPhone, OEM);\n // await this.writeMicrophoneInfoToFirestore(ID, micInfo, OEM, id);\n // await this.writeFrqGainToFirestore(ID, IrFreq, IrGain, OEM, id);\n // micInfo['gainDBSPL'] = impulseResponseResults.component.gainDBSPL;\n // await this.writeGainat1000HzToFirestore(ID, micInfo['gainDBSPL'], OEM, id);\n // await this.writeGainat1000Hz(ID, micInfo['gainDBSPL'], OEM);\n }\n const total_results = {...volumeResults, ...impulseResponseResults};\n total_results['filteredMLSRange'] = this.filteredMLSRange;\n total_results['filteredMLSAttenuation'] = this.filteredMLSAttenuation;\n total_results['micInfo'] = micInfo;\n total_results['audioInfo'] = {};\n total_results['audioInfo']['sinkSampleRate'] = this.sinkSamplingRate;\n total_results['audioInfo']['sourceSampleRate'] = this.sourceSamplingRate;\n total_results['audioInfo']['bitsPerSample'] = this.sampleSize;\n const timeStampresult = [...this.timeStamp].join('\\n');\n total_results['timeStamps'] = timeStampresult;\n total_results['recordingChecks'] = this.recordingChecks;\n total_results['waveforms'] = this.waveforms;\n total_results['component']['phase'] = this.componentIRPhase;\n total_results['system']['phase'] = this.systemIRPhase;\n total_results['qualityMetrics'] = this.SDofFilteredRange;\n total_results['flags'] = this.flags;\n console.log('total results');\n console.log(total_results);\n console.log('Time Stamps');\n console.log(timeStampresult);\n\n resolve(total_results);\n });\n };\n}\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (Combination);\n\n//# sourceURL=webpack://speakerCalibrator/./src/tasks/combination/combination.js?");
|
|
515
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _audioCalibrator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../audioCalibrator */ \"./src/tasks/audioCalibrator.js\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../utils */ \"./src/utils.js\");\n/* harmony import */ var _powerCheck__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../powerCheck */ \"./src/powerCheck.js\");\n/* harmony import */ var _config_firebase__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../config/firebase */ \"./src/config/firebase.js\");\n/* harmony import */ var firebase_database__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! firebase/database */ \"./node_modules/firebase/database/dist/esm/index.esm.js\");\n/* harmony import */ var firebase_firestore__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! firebase/firestore */ \"./node_modules/firebase/firestore/dist/esm/index.esm.js\");\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n//import { phrases } from '../../../dist/example/i18n';\r\n\r\n/**\r\n *\r\n */\r\nclass Combination extends _audioCalibrator__WEBPACK_IMPORTED_MODULE_0__[\"default\"] {\r\n /**\r\n * Default constructor. Creates an instance with any number of paramters passed or the default parameters defined here.\r\n *\r\n * @param {Object<boolean, number, number, number>} calibratorParams - paramter object\r\n * @param {boolean} [calibratorParams.download = false] - boolean flag to download captures\r\n * @param {number} [calibratorParams.mlsOrder = 18] - order of the MLS to be generated\r\n * @param {number} [calibratorParams.numCaptures = 5] - number of captures to perform\r\n * @param {number} [calibratorParams.numMLSPerCapture = 2] - number of bursts of MLS per capture\r\n */\r\n constructor({\r\n download = false,\r\n mlsOrder = 18,\r\n numCaptures = 3,\r\n numMLSPerCapture = 2,\r\n lowHz = 20,\r\n highHz = 10000,\r\n }) {\r\n super(numCaptures, numMLSPerCapture);\r\n this.#mlsOrder = parseInt(mlsOrder, 10);\r\n this.#P = 2 ** mlsOrder - 1;\r\n this.#download = download;\r\n this.#mls = [];\r\n this.#lowHz = lowHz;\r\n this.#highHz = highHz;\r\n }\r\n\r\n /** @private */\r\n stepNum = 0;\r\n\r\n /** @private */\r\n totalSteps = 25;\r\n\r\n /** @private */\r\n #download;\r\n\r\n /** @private */\r\n #mlsGenInterface;\r\n\r\n /** @private */\r\n #mlsBufferView;\r\n\r\n /** @private */\r\n componentInvertedImpulseResponse = null;\r\n\r\n /** @private */\r\n systemInvertedImpulseResponse = null;\r\n\r\n //averaged and subtracted ir returned from calibration used to calculated iir\r\n /** @private */\r\n ir = null;\r\n\r\n /** @private */\r\n impulseResponses = [];\r\n\r\n /** @private */\r\n #mlsOrder;\r\n\r\n /** @private */\r\n #lowHz;\r\n\r\n /** @private */\r\n #highHz;\r\n\r\n /** @private */\r\n #mls;\r\n\r\n /** @private */\r\n #P;\r\n\r\n /** @private */\r\n #audioContext;\r\n\r\n /** @private */\r\n offsetGainNode;\r\n\r\n /** @private */\r\n componentConvolution;\r\n\r\n /** @private */\r\n componentConvolutionNoBandpass;\r\n\r\n /** @private */\r\n componentIROrigin = {\r\n Freq: [],\r\n Gain: [],\r\n };\r\n\r\n /** @private */\r\n systemConvolution;\r\n\r\n /** @private */\r\n systemConvolutionNoBandpass;\r\n\r\n ////////////////////////volume\r\n /** @private */\r\n #CALIBRATION_TONE_FREQUENCY = 1000; // Hz\r\n\r\n /** @private */\r\n #CALIBRATION_TONE_TYPE = 'sine';\r\n\r\n CALIBRATION_TONE_DURATION = 5; // seconds\r\n calibrateSound1000HzPreSec = 3.5;\r\n calibrateSound1000HzSec = 1.0;\r\n calibrateSound1000HzPostSec = 0.5;\r\n\r\n /** @private */\r\n outDBSPL = null;\r\n THD = null;\r\n outDBSPL1000 = null;\r\n\r\n /** @private */\r\n TAPER_SECS = 0.01; // seconds\r\n\r\n /** @private */\r\n status_denominator = 8;\r\n\r\n /** @private */\r\n status_numerator = 0;\r\n\r\n /** @private */\r\n percent_complete = 0;\r\n\r\n /** @private */\r\n status = ``;\r\n\r\n /**@private */\r\n status_literal = `<div style=\"display: flex; justify-content: center;\"><div style=\"width: 200px; height: 20px; border: 2px solid #000; border-radius: 10px;\"><div style=\"width: ${this.percent_complete}%; height: 100%; background-color: #00aaff; border-radius: 8px;\"></div></div></div>`;\r\n\r\n /**@private */\r\n componentIR = null;\r\n\r\n /**@private */\r\n oldComponentIR = null;\r\n\r\n /**@private */\r\n systemIR = null;\r\n\r\n /**@private */\r\n _calibrateSoundCheck = '';\r\n\r\n deviceType = null;\r\n\r\n deviceName = null;\r\n\r\n deviceInfo = null;\r\n\r\n desired_time_per_mls = 0;\r\n\r\n num_mls_to_skip = 0;\r\n\r\n desired_sampling_rate = 0;\r\n\r\n #currentConvolution = [];\r\n\r\n mode = 'unfiltered';\r\n\r\n sourceNode;\r\n\r\n autocorrelations = [];\r\n\r\n iirLength = 0;\r\n\r\n irLength = 0;\r\n\r\n calibrateSoundIIRPhase = 'linear';\r\n\r\n componentInvertedImpulseResponseNoBandpass = [];\r\n\r\n componentIRInTimeDomain = [];\r\n\r\n systemInvertedImpulseResponseNoBandpass = [];\r\n\r\n _calibrateSoundBackgroundSecs;\r\n\r\n _calibrateSoundSmoothOctaves;\r\n\r\n background_noise = {};\r\n\r\n numSuccessfulBackgroundCaptured;\r\n\r\n _calibrateSoundBurstDb;\r\n\r\n _calibrateSoundBurstFilteredExtraDb;\r\n\r\n _calibrateSoundBurstLevelReTBool;\r\n\r\n SDofFilteredRange = {\r\n mls: undefined,\r\n component: undefined,\r\n system: undefined,\r\n };\r\n\r\n transducerType = 'Loudspeaker';\r\n\r\n componentIRPhase = [];\r\n\r\n systemIRPhase = [];\r\n\r\n webAudioDeviceNames = {loudspeaker: '', microphone: '', loudspeakerText: '', microphoneText: ''};\r\n\r\n waveforms = {\r\n volume: {},\r\n };\r\n\r\n recordingChecks = {\r\n volume: {},\r\n unfiltered: [],\r\n system: [],\r\n component: [],\r\n warnings:[]\r\n };\r\n\r\n inDB;\r\n\r\n soundCheck = '';\r\n\r\n filteredMLSRange = {\r\n component: {\r\n Min: null,\r\n Max: null,\r\n },\r\n system: {\r\n Min: null,\r\n Max: null,\r\n },\r\n };\r\n\r\n /** @private */\r\n timeStamp = [];\r\n\r\n restartCalibration = false;\r\n\r\n calibrateSoundLimit = 1;\r\n\r\n filteredMLSAttenuation = {\r\n component: 1,\r\n system: 1,\r\n maxAbsSystem: 1,\r\n maxAbsComponent: 1,\r\n };\r\n\r\n //parameter result from volume calibration\r\n T = 0;\r\n //gainDBSPL result from volume calibration\r\n gainDBSPL = 0;\r\n //not always just using _calibrateSoundBurstDb for MLS so created a new parameter\r\n power_dB = 0;\r\n\r\n //system\r\n systemAttenuatorGainDB = 0;\r\n systemFMaxHz = 0;\r\n\r\n //component\r\n componentAttentuatorGainDB = 0;\r\n componentFMaxHz = 0;\r\n\r\n dL_n;\r\n L_new_n;\r\n fs2;\r\n icapture = 0;\r\n\r\n /**generate string template that gets reevaluated as variable increases */\r\n generateTemplate = (status) => {\r\n if (this.isCalibrating) {\r\n return '';\r\n }\r\n if (this.percent_complete > 100) {\r\n this.percent_complete = 100;\r\n }\r\n let MLSsd = '';\r\n let componentSD = '';\r\n let systemSD = '';\r\n let flags = '';\r\n const reportWebAudioNames = `<strong>${this.webAudioDeviceNames.loudspeakerText} </strong> <strong>${this.webAudioDeviceNames.microphoneText} </strong>`;\r\n const samplingParamText = this.phrases.RC_SamplingHzBits[this.language].replace('111', this.sourceSamplingRate).replace('222',this.sinkSamplingRate).replace('333', this.calibrateSoundSamplingDesiredBits);\r\n const reportParameters = `${samplingParamText}`;\r\n if (this.flags) {\r\n flags = `<br> autoGainControl: ${this.flags.autoGainControl}; \r\n echoCancellation: ${this.flags.echoCancellation};\r\n noiseSuppression: ${this.flags.noiseSuppression}`;\r\n }\r\n if (this.SDofFilteredRange['mls']) {\r\n MLSsd = `<br> Recorded MLS power SD: ${this.SDofFilteredRange['mls']} dB`;\r\n }\r\n if (this.SDofFilteredRange['system']) {\r\n systemSD = `<br> Loudspeaker+Microphone correction SD: ${this.SDofFilteredRange['system']} dB`;\r\n }\r\n if (this.SDofFilteredRange['component']) {\r\n componentSD = `<br> ${this.transducerType} correction SD: ${this.SDofFilteredRange['component']} dB`;\r\n }\r\n const template = `<div style=\"display: flex; justify-content: flex-start; margin-top: 0.4rem;\"><div style=\"width: 100%; height: 20px; border: 2px solid #000; border-radius: 10px;\"><div style=\"width: ${this.percent_complete}%; height: 100%; background-color: #00aaff; border-radius: 8px;\"></div></div></div>`;\r\n return `\r\n ${reportWebAudioNames}\r\n ${reportParameters} \r\n ${MLSsd}\r\n ${systemSD}\r\n ${componentSD}\r\n ${flags}\r\n <br>${status}\r\n ${template }`;\r\n };\r\n\r\n /** increment numerator and percent for status bar */\r\n incrementStatusBar = () => {\r\n this.status_numerator += 1;\r\n this.percent_complete = (this.status_numerator / this.status_denominator) * 100;\r\n };\r\n\r\n setDeviceType = deviceType => {\r\n this.deviceType = deviceType;\r\n };\r\n\r\n setDeviceName = deviceName => {\r\n this.deviceName = deviceName;\r\n };\r\n\r\n setDeviceInfo = deviceInfo => {\r\n this.deviceInfo = deviceInfo;\r\n };\r\n\r\n /** .\r\n * .\r\n * .\r\n * Sends all the computed impulse responses to the backend server for processing\r\n *\r\n * @returns sets the resulting inverted impulse response to the class property\r\n * @example\r\n */\r\n sendSystemImpulseResponsesToServerForProcessing = async () => {\r\n this.addTimeStamp('Compute system IIR');\r\n const computedIRs = await Promise.all(this.impulseResponses);\r\n const filteredComputedIRs = computedIRs.filter(element => {\r\n return element != undefined;\r\n }); //log any errors that are found in this step\r\n console.log('filteredComputedIRs', filteredComputedIRs);\r\n const mls = this.#mls[this.icapture];\r\n const lowHz = this.#lowHz; //gain of 1 below cutoff, need gain of 0\r\n const highHz = this.#highHz; //check error for anything other than 10 kHz\r\n const iirLength = this.iirLength;\r\n this.stepNum += 1;\r\n console.log('send impulse responses to server: ' + this.stepNum);\r\n this.status = this.generateTemplate(`All Hz Calibration: computing the IIR...`.toString()).toString();\r\n this.emit('update', {message: this.status});\r\n return await this.pyServerAPI\r\n .getSystemInverseImpulseResponseWithRetry({\r\n payload: filteredComputedIRs.slice(0, this.numCaptures),\r\n mls,\r\n lowHz,\r\n highHz,\r\n iirLength,\r\n sampleRate: this.sourceSamplingRate || 96000,\r\n mlsAmplitude: Math.pow(10, this.power_dB / 20),\r\n calibrateSoundBurstFilteredExtraDb: this._calibrateSoundBurstFilteredExtraDb,\r\n calibrateSoundIIRPhase: this.calibrateSoundIIRPhase,\r\n })\r\n .then(async res => {\r\n this.stepNum += 1;\r\n console.log('got impulse response ' + this.stepNum);\r\n this.incrementStatusBar();\r\n this.status = this.generateTemplate(`All Hz Calibration: done computing the IIR...`.toString()).toString();\r\n this.emit('update', {message: this.status});\r\n this.systemInvertedImpulseResponse = res['iir'];\r\n this.systemIR = res['ir'];\r\n this.systemInvertedImpulseResponseNoBandpass = res['iirNoBandpass'];\r\n this.systemAttenuatorGainDB = res['attenuatorGain_dB'];\r\n this.systemFMaxHz = res['fMaxHz'];\r\n await this.pyServerAPI.checkMemory();\r\n await this.pyServerAPI\r\n .getConvolution({\r\n mls,\r\n inverse_response: this.systemInvertedImpulseResponse,\r\n inverse_response_no_bandpass: this.systemInvertedImpulseResponseNoBandpass,\r\n attenuatorGain_dB: this.systemAttenuatorGainDB,\r\n mls_amplitude: Math.pow(10, this.power_dB / 20),\r\n })\r\n .then(result => {\r\n console.log(result);\r\n this.systemConvolution = result['convolution'];\r\n this.systemConvolutionNoBandpass = result['convolution_no_bandpass'];\r\n });\r\n\r\n // attenuate the system convolution if the amplitude is greater than this.calibrateSoundLimit\r\n // find max of absolute value of system convolution\r\n\r\n const max = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.findMaxValue)(this.systemConvolution);\r\n this.filteredMLSAttenuation.system =\r\n this.systemConvolution.reduce((a, b) => a + b ** 2, 0) / this.systemConvolution.length;\r\n this.filteredMLSAttenuation.maxAbsSystem = max;\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n });\r\n };\r\n\r\n /** .\r\n * .\r\n * .\r\n * Sends all the computed impulse responses to the backend server for processing\r\n *\r\n * @returns sets the resulting inverted impulse response to the class property\r\n * @example\r\n */\r\n sendComponentImpulseResponsesToServerForProcessing = async () => {\r\n this.addTimeStamp('Compute component IIR');\r\n const computedIRs = await Promise.all(this.impulseResponses);\r\n const filteredComputedIRs = computedIRs.filter(element => {\r\n return element != undefined;\r\n });\r\n let componentIRGains = this.componentIR['Gain'];\r\n const componentIRFreqs = this.componentIR['Freq'];\r\n //normalize the component IR gains\r\n componentIRGains = componentIRGains.map(value => {\r\n return value + this._calibrateSoundBurstScalarDB - this._calibrateSoundBurstDb;\r\n });\r\n if (this._calibrateSoundBurstNormalizeBy1000HzGainBool) {\r\n const sineGainAt1000Hz_dB = this.gainDBSPL;\r\n componentIRGains = componentIRGains.map(value => {\r\n return value - sineGainAt1000Hz_dB;\r\n });\r\n }\r\n const mls = this.#mls[this.icapture];\r\n const lowHz = this.#lowHz;\r\n const iirLength = this.iirLength;\r\n const irLength = this.irLength;\r\n const highHz = this.#highHz;\r\n this.stepNum += 1;\r\n console.log('send impulse responses to server: ' + this.stepNum);\r\n this.status = this.generateTemplate(`All Hz Calibration: computing the IIR...`.toString()).toString();\r\n this.emit('update', {message: this.status});\r\n console.log()\r\n return this.pyServerAPI\r\n .getComponentInverseImpulseResponseWithRetry({\r\n payload: filteredComputedIRs.slice(0, this.numCaptures),\r\n mls,\r\n lowHz,\r\n highHz,\r\n iirLength,\r\n componentIRGains,\r\n componentIRFreqs,\r\n sampleRate: this.sourceSamplingRate || 96000,\r\n mlsAmplitude: Math.pow(10, this.power_dB / 20),\r\n irLength,\r\n calibrateSoundSmoothOctaves: this._calibrateSoundSmoothOctaves,\r\n calibrateSoundSmoothMinBandwidthHz: this._calibrateSoundSmoothMinBandwidthHz,\r\n calibrateSoundBurstFilteredExtraDb: this._calibrateSoundBurstFilteredExtraDb,\r\n calibrateSoundIIRPhase: this.calibrateSoundIIRPhase,\r\n })\r\n .then(async res => {\r\n this.stepNum += 1;\r\n console.log('got impulse response ' + this.stepNum);\r\n this.incrementStatusBar();\r\n this.status = this.generateTemplate(`All Hz Calibration: done computing the IIR...`.toString()).toString();\r\n this.emit('update', {message: this.status});\r\n this.componentInvertedImpulseResponse = res['iir'];\r\n this.componentInvertedImpulseResponseNoBandpass = res['iirNoBandpass'];\r\n this.componentIR['Gain'] = res['ir'];\r\n this.componentIR['Freq'] = res['frequencies'];\r\n this.componentIRPhase = res['component_angle'];\r\n this.systemIRPhase = res['system_angle'];\r\n this.componentIROrigin['Freq'] = res['frequencies'];\r\n this.componentIROrigin['Gain'] = res['irOrigin'];\r\n this.componentIRInTimeDomain = res['irTime'];\r\n this.componentAttenuatorGainDB = res['attenuatorGain_dB'];\r\n this.componentFMaxHz = res['fMaxHz'];\r\n await this.pyServerAPI.checkMemory();\r\n await this.pyServerAPI\r\n .getConvolution({\r\n mls,\r\n inverse_response: this.componentInvertedImpulseResponse,\r\n inverse_response_no_bandpass: this.componentInvertedImpulseResponseNoBandpass,\r\n attenuatorGain_dB: this.componentAttenuatorGainDB,\r\n mls_amplitude: Math.pow(10, this.power_dB / 20),\r\n })\r\n .then(result => {\r\n console.log(result);\r\n this.componentConvolution = result['convolution'];\r\n this.componentConvolutionNoBandpass = result['convolution_no_bandpass'];\r\n });\r\n // attenuate the component convolution if the amplitude is greater than this.calibrateSoundLimit\r\n // find max of absolute value of component convolution\r\n const max = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.findMaxValue)(this.componentConvolution);\r\n // if (max > this.calibrateSoundLimit) {\r\n // const gain = this.calibrateSoundLimit / max;\r\n // // apply gain to component convolution\r\n // this.componentConvolution = this.componentConvolution.map(value => value * gain);\r\n // this.filteredMLSAttenuation.component = gain;\r\n // }\r\n this.filteredMLSAttenuation.component =\r\n this.componentConvolution.reduce((a, b) => a + b ** 2, 0) /\r\n this.componentConvolution.length;\r\n this.filteredMLSAttenuation.maxAbsComponent = max;\r\n })\r\n .catch(err => {\r\n // this.emit('InvertedImpulseResponse', {res: false});\r\n console.error(err);\r\n });\r\n };\r\n\r\n sendBackgroundRecording = () => {\r\n const allSignals = this.getAllBackgroundRecordings();\r\n const numSignals = allSignals.length;\r\n const background_rec_whole = allSignals[numSignals - 1];\r\n const fraction = 0.5 / (this._calibrateSoundBackgroundSecs + 0.5);\r\n // Calculate the starting index for slicing the array\r\n const startIndex = Math.round(fraction * background_rec_whole.length);\r\n // Slice the array from the calculated start index to the end of the array\r\n const background_rec = background_rec_whole.slice(startIndex);\r\n console.log('Sending background recording to server for processing');\r\n this.addTimeStamp('Compute background PSD');\r\n this.pyServerAPI\r\n .getBackgroundNoisePSDWithRetry({\r\n background_rec,\r\n sampleRate: this.sourceSamplingRate || 96000,\r\n })\r\n .then(res => {\r\n if (this.numSuccessfulBackgroundCaptured < 1) {\r\n this.numSuccessfulBackgroundCaptured += 1;\r\n //storing all background data in background_psd object\r\n this.background_noise['x_background'] = res['x_background'];\r\n this.background_noise['y_background'] = res['y_background'];\r\n this.background_noise['recording'] = background_rec;\r\n }\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n });\r\n };\r\n\r\n /** .\r\n * .\r\n * .\r\n * Sends the recorded signal, or a given csv string of a signal, to the back end server for processing\r\n *\r\n * @param {<array>String} signalCsv - Optional csv string of a previously recorded signal, if given, this signal will be processed\r\n * @example\r\n */\r\n sendRecordingToServerForProcessing = async signalCsv => {\r\n const allSignals = this.getAllUnfilteredRecordedSignals();\r\n console.log(\r\n 'Obtaining last all hz unfiltered recording from #allHzUnfilteredRecordings to send to server for processing'\r\n );\r\n const numSignals = allSignals.length;\r\n const mls = this.#mlsBufferView[this.icapture];\r\n const payload =\r\n signalCsv && signalCsv.length > 0 ? (0,_utils__WEBPACK_IMPORTED_MODULE_1__.csvToArray)(signalCsv) : allSignals[numSignals - 1];\r\n console.log('sending rec');\r\n this.stepNum += 1;\r\n console.log('send rec ' + this.stepNum);\r\n this.status = this.generateTemplate(`All Hz Calibration Step: computing the IR of the last recording...`.toString()).toString();\r\n this.emit('update', {message: this.status});\r\n if (this.isCalibrating) return null;\r\n await this.pyServerAPI\r\n .allHzPowerCheck({\r\n payload,\r\n sampleRate: this.sourceSamplingRate || 96000,\r\n binDesiredSec: this._calibrateSoundPowerBinDesiredSec,\r\n burstSec: this.desired_time_per_mls,\r\n repeats: this.numMLSPerCapture - this.num_mls_to_skip,\r\n warmUp: this.num_mls_to_skip \r\n })\r\n .then(async result => {\r\n if (result) {\r\n if (result['sd'] > this._calibrateSoundBurstMaxSD_dB && \r\n this.numSuccessfulCaptured == 0) {\r\n console.log('SD: ' + result['sd'] + ', greater than _calibrateSoundBurstMaxSD_dB: ' + this._calibrateSoundBurstMaxSD_dB);\r\n this.recordingChecks['unfiltered'].push(result);\r\n this.clearLastUnfilteredRecordedSignals();\r\n this.numSuccessfulCaptured +=1;\r\n } else {\r\n if (result['sd'] <= this._calibrateSoundBurstMaxSD_dB) {\r\n console.log('SD: ' + result['sd'] + ', less than _calibrateSoundBurstMaxSD_dB: ' + this._calibrateSoundBurstMaxSD_dB);\r\n } else {\r\n console.log('SD: ' + result['sd'] + ', greater than _calibrateSoundBurstMaxSD_dB: ' + this._calibrateSoundBurstMaxSD_dB);\r\n this.recordingChecks['warnings'].push(`All Hz. Re-recorded ${this.inDB} dB because SD ${result['sd']} > ${this._calibrateSoundBurstMaxSD_dB} dB`);\r\n this.status = this.generateTemplate(`All Hz: Re-recording at ${this.inDB} dB because SD ${result['sd']} > ${this._calibrateSoundBurstMaxSD_dB} dB`.toString()).toString();\r\n this.emit('update', {\r\n message: this.status,\r\n });\r\n }\r\n if (this.numSuccessfulCaptured == 1) {\r\n console.log('pop last unfiltered mls volume check');\r\n this.recordingChecks['unfiltered'].pop();\r\n }\r\n this.recordingChecks['unfiltered'].push(result);\r\n // let start = new Date().getTime() / 1000;\r\n // const payloadT = tf.tensor1d(payload);\r\n // payloadT.print();\r\n // const xfft = payloadT.rfft(); // tf.spe\r\n // xfft.array().then(array => {\r\n // console.log(\"fft:\", array);\r\n // let setItem = new Set(array);\r\n // console.log(\"all zero\", setItem.size === 1 && setItem.has(0));\r\n // });\r\n // console.log(\"dimention:\", xfft.shape);\r\n // let end = new Date().getTime() / 1000;\r\n // console.log(\"Time taken:\", end - start, \"seconds\");\r\n console.log('start calculate impulse response');\r\n const usedPeriodStart = this.num_mls_to_skip * this.sourceSamplingRate;\r\n const payload_skipped_warmUp = payload.slice(usedPeriodStart);\r\n await this.pyServerAPI\r\n .getAutocorrelation({\r\n mls:mls,\r\n payload: payload_skipped_warmUp,\r\n sampleRate: this.sourceSamplingRate || 96000,\r\n numPeriods: this.numMLSPerCapture - this.num_mls_to_skip,\r\n })\r\n .then(async res => {\r\n this.autocorrelations.push(res['autocorrelation']);\r\n this.fs2 = res['fs2'];\r\n this.L_new_n = res['L_new_n'];\r\n this.dL_n = res['dL_n'];\r\n this.impulseResponses.push(\r\n await this.pyServerAPI\r\n .getImpulseResponse({\r\n mls,\r\n sampleRate: this.sourceSamplingRate || 96000,\r\n numPeriods: this.numMLSPerCapture - this.num_mls_to_skip,\r\n sig: payload_skipped_warmUp,\r\n fs2: this.fs2,\r\n L_new_n: this.L_new_n,\r\n dL_n: this.dL_n,\r\n })\r\n .then(res => {\r\n this.numSuccessfulCaptured += 2;\r\n this.stepNum += 1;\r\n console.log('got impulse response ' + this.stepNum);\r\n this.incrementStatusBar();\r\n this.status = this.generateTemplate(`All Hz Calibration: ${this.numSuccessfulCaptured}/${this.numCaptures} IRs computed...`.toString()).toString();\r\n this.emit('update', {\r\n message: this.status,\r\n });\r\n return res['ir'];\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n })\r\n );\r\n });\r\n }\r\n console.log('number of unfiltered recording checks:' + this.recordingChecks['unfiltered'].length);\r\n }\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n });\r\n };\r\n\r\n /**\r\n * Passed to the calibration steps function, awaits the desired amount of seconds to capture the desired number\r\n * of MLS periods defined in the constructor.\r\n *\r\n * @example\r\n */\r\n #awaitDesiredMLSLength = async () => {\r\n // seconds per MLS = P / SR\r\n // await N * P / SR\r\n this.stepNum += 1;\r\n console.log('await desired length ' + this.stepNum);\r\n this.status = this.generateTemplate(`All Hz Calibration: sampling the calibration signal...`.toString() +\r\n `\\niteration ${this.stepNum}`);\r\n this.emit('update', {\r\n message: this.status,\r\n });\r\n let time_to_wait = 0;\r\n if (this.mode === 'unfiltered') {\r\n //unfiltered\r\n time_to_wait = (this.#mls[0].length / this.sourceSamplingRate) * this.numMLSPerCapture;\r\n time_to_wait = time_to_wait + this._calibrateSoundBurstPostSec;\r\n } else if (this.mode === 'filtered') {\r\n //filtered\r\n // time_to_wait =\r\n // (this.#currentConvolution.length / this.sourceSamplingRate) *\r\n // (this.numMLSPerCapture / (this.num_mls_to_skip + this.numMLSPerCapture));\r\n time_to_wait =\r\n (this.#currentConvolution.length / this.sourceSamplingRate) * this.numMLSPerCapture;\r\n time_to_wait = time_to_wait + this._calibrateSoundBurstPostSec;\r\n } else {\r\n throw new Error('Mode broke in awaitDesiredMLSLength');\r\n }\r\n\r\n await (0,_utils__WEBPACK_IMPORTED_MODULE_1__.sleep)(time_to_wait);\r\n };\r\n\r\n /**\r\n * Passed to the background noise recording function, awaits the desired amount of seconds to capture the desired number\r\n * of seconds of background noise\r\n *\r\n * @example\r\n */\r\n #awaitBackgroundNoiseRecording = async () => {\r\n console.log(\r\n 'Waiting ' + this._calibrateSoundBackgroundSecs + ' second(s) to record background noise'\r\n );\r\n let time_to_wait = this._calibrateSoundBackgroundSecs + 0.5;\r\n this.addTimeStamp(`Record ${time_to_wait.toFixed(1)} s of background.`)\r\n await (0,_utils__WEBPACK_IMPORTED_MODULE_1__.sleep)(time_to_wait);\r\n };\r\n\r\n /** .\r\n * .\r\n * .\r\n * Passed to the calibration steps function, awaits the onset of the signal to ensure a steady state\r\n *\r\n * @example\r\n */\r\n #awaitSignalOnset = async () => {\r\n this.stepNum += 1;\r\n console.log('await signal onset ' + this.stepNum);\r\n this.status = this.generateTemplate(`All Hz Calibration: waiting for the signal to stabilize...`.toString());\r\n this.emit('update', {\r\n message: this.status,\r\n });\r\n let number_of_bursts_to_skip = 0;\r\n let time_to_sleep = 0;\r\n if (this.mode === 'unfiltered') {\r\n time_to_sleep = (this.#mls[0].length / this.sourceSamplingRate) * number_of_bursts_to_skip;\r\n } else if (this.mode === 'filtered') {\r\n console.log(this.#currentConvolution.length);\r\n // time_to_sleep =\r\n // (this.#currentConvolution.length / this.sourceSamplingRate) *\r\n // (number_of_bursts_to_skip / (number_of_bursts_to_skip + this.numMLSPerCapture));\r\n time_to_sleep =\r\n (this.#currentConvolution.length / this.sourceSamplingRate) * number_of_bursts_to_skip;\r\n } else {\r\n throw new Error('Mode broke in awaitSignalOnset');\r\n }\r\n await (0,_utils__WEBPACK_IMPORTED_MODULE_1__.sleep)(time_to_sleep);\r\n };\r\n\r\n /**\r\n * Called immediately after a recording is captured. Used to process the resulting signal\r\n * whether by sending the result to a server or by computing a result locally.\r\n *\r\n * @example\r\n */\r\n #afterMLSRecord = async () => {\r\n console.log('after record');\r\n this.addTimeStamp(`Send unfiltered MLS to the server`);\r\n await this.sendRecordingToServerForProcessing();\r\n };\r\n\r\n #afterMLSwIIRRecord = async () => {\r\n await this.checkPowerVariation();\r\n };\r\n\r\n /** .\r\n * .\r\n * .\r\n * Created an S Curver Buffer to taper the signal onset\r\n *\r\n * @param {*} onSetBool\r\n * @returns\r\n * @example\r\n */\r\n createSCurveBuffer = (onSetBool = true) => {\r\n const curve = new Float32Array(this.TAPER_SECS * this.sourceSamplingRate + 1);\r\n const frequency = 1 / (4 * this.TAPER_SECS);\r\n let j = 0;\r\n for (let i = 0; i < this.TAPER_SECS * this.sourceSamplingRate + 1; i += 1) {\r\n const phase = 2 * Math.PI * frequency * j;\r\n const onsetTaper = Math.pow(Math.sin(phase), 2);\r\n const offsetTaper = Math.pow(Math.cos(phase), 2);\r\n curve[i] = onSetBool ? onsetTaper : offsetTaper;\r\n j += 1 / this.sourceSamplingRate;\r\n }\r\n return curve;\r\n };\r\n\r\n static createInverseSCurveBuffer = (length, phase) => {\r\n const curve = new Float32Array(length);\r\n let i;\r\n let j = length - 1;\r\n for (i = 0; i < length; i += 1) {\r\n // scale the curve to be between 0-1\r\n curve[i] = Math.sin((Math.PI * j) / length - phase) / 2 + 0.5;\r\n j -= 1;\r\n }\r\n return curve;\r\n };\r\n\r\n /**\r\n * Construct a Calibration Node with the calibration parameters.\r\n *\r\n * @param dataBuffer\r\n * @private\r\n * @example\r\n */\r\n #createCalibrationNodeFromBuffer = dataBuffer => {\r\n console.log('length databuffer');\r\n console.log(dataBuffer.length);\r\n if (!this.sourceAudioContext) {\r\n this.makeNewSourceAudioContext();\r\n }\r\n\r\n const buffer = this.sourceAudioContext.createBuffer(\r\n 1, // number of channels\r\n dataBuffer.length,\r\n this.sourceAudioContext.sampleRate // sample rate\r\n );\r\n\r\n const data = buffer.getChannelData(0); // get data\r\n\r\n // fill the buffer with our data\r\n try {\r\n for (let i = 0; i < dataBuffer.length; i += 1) {\r\n data[i] = dataBuffer[i];\r\n }\r\n } catch (error) {\r\n console.error(error);\r\n }\r\n\r\n this.sourceNode = this.sourceAudioContext.createBufferSource();\r\n\r\n this.sourceNode.buffer = buffer;\r\n\r\n if (this.mode === 'filtered') {\r\n //used to not loop filtered\r\n this.sourceNode.loop = true;\r\n } else {\r\n this.sourceNode.loop = true;\r\n }\r\n\r\n this.sourceNode.connect(this.sourceAudioContext.destination);\r\n\r\n this.addCalibrationNode(this.sourceNode);\r\n };\r\n\r\n /**\r\n * Given a data buffer, creates the required calibration node\r\n *\r\n * @param {*} dataBufferArray\r\n * @example\r\n */\r\n #setCalibrationNodesFromBuffer = (dataBufferArray = [this.#mlsBufferView[this.icapture]]) => {\r\n if (dataBufferArray.length === 1) {\r\n this.#createCalibrationNodeFromBuffer(dataBufferArray[0]);\r\n } else {\r\n throw new Error('The length of the data buffer array must be 1');\r\n }\r\n };\r\n\r\n /**\r\n * Creates an audio context and plays it for a few seconds.\r\n *\r\n * @private\r\n * @returns - Resolves when the audio is done playing.\r\n * @example\r\n */\r\n #playCalibrationAudio = () => {\r\n this.calibrationNodes[0].start(0);\r\n this.status = ``;\r\n if (this.mode === 'unfiltered') {\r\n console.log('play calibration audio ' + this.stepNum);\r\n\r\n const pre = this._calibrateSoundBurstPreSec; \r\n const repeats = this._calibrateSoundBurstRepeats; \r\n const burst = this._calibrateSoundBurstSec; \r\n const post = this._calibrateSoundBurstPostSec; \r\n const total_dur = pre + repeats * burst + post;\r\n this.addTimeStamp(\r\n `Record ${total_dur.toFixed(1)} s of MLS ver. ${this.icapture}, unfiltered. ` +\r\n `(${pre.toFixed(1)} s pre + ${repeats}×${burst.toFixed(1)} s used + ${post.toFixed(1)} s post).`\r\n );\r\n this.status = this.generateTemplate(`All Hz Calibration: playing the calibration tone...`.toString()).toString();\r\n } else if (this.mode === 'filtered') {\r\n console.log('play convolved audio ' + this.stepNum);\r\n this.status = this.generateTemplate().toString( `All Hz Calibration: playing the convolved calibration tone...`.toString());\r\n } else {\r\n throw new Error('Mode is incorrect');\r\n }\r\n this.emit('update', {message: this.status});\r\n this.stepNum += 1;\r\n console.log('sink sampling rate');\r\n console.log(this.sinkSamplingRate);\r\n console.log('source sampling rate');\r\n console.log(this.sourceSamplingRate);\r\n console.log('sample size');\r\n console.log(this.sampleSize);\r\n };\r\n\r\n /** .\r\n * .\r\n * .\r\n * Stops the audio with tapered offset\r\n *\r\n * @example\r\n */\r\n stopCalibrationAudio = () => {\r\n if (this.calibrationNodes.length === 0) {\r\n return;\r\n }\r\n this.calibrationNodes[0].stop(0);\r\n this.calibrationNodes = [];\r\n if (this.sourceNode) this.sourceNode.disconnect();\r\n this.stepNum += 1;\r\n console.log('stop calibration audio ' + this.stepNum);\r\n this.status = this.generateTemplate(`All Hz Calibration: stopping the calibration tone...`.toString()).toString();\r\n this.emit('update', {message: this.status});\r\n };\r\n\r\n playMLSwithIIR = async (stream, convolution) => {\r\n let checkRec = false;\r\n this.mode = 'filtered';\r\n console.log('play mls with iir');\r\n //this.invertedImpulseResponse = iir\r\n\r\n await this.calibrationSteps(\r\n stream,\r\n this.#playCalibrationAudio, // play audio func (required)\r\n this.#createCalibrationNodeFromBuffer(convolution), // before play func\r\n this.#awaitSignalOnset, // before record\r\n () => this.numSuccessfulCaptured < 2,\r\n this.#awaitDesiredMLSLength, // during record\r\n this.#afterMLSwIIRRecord, // after record\r\n this.mode,\r\n checkRec\r\n );\r\n };\r\n\r\n bothSoundCheck = async stream => {\r\n let iir_ir_and_plots;\r\n this.#currentConvolution = this.componentConvolution;\r\n this.filteredMLSRange.component.Min = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.findMinValue)(this.#currentConvolution);\r\n this.filteredMLSRange.component.Max = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.findMaxValue)(this.#currentConvolution);\r\n const pre = this._calibrateSoundBurstPreSec; \r\n const repeats = this._calibrateSoundBurstRepeats; \r\n const burst = this._calibrateSoundBurstSec; \r\n const post = this._calibrateSoundBurstPostSec; \r\n const total_dur = pre + repeats * burst + post;\r\n this.soundCheck = 'component';\r\n this.addTimeStamp(`Record ${total_dur} s of MLS with ${this.soundCheck} IIR.”`)\r\n \r\n if (this.isCalibrating) return null;\r\n await this.playMLSwithIIR(stream, this.#currentConvolution);\r\n this.stopCalibrationAudio();\r\n let component_conv_recs = this.getAllFilteredRecordedSignals();\r\n\r\n if (this.componentAttentuatorGainDB != 0) {\r\n let linearScaleAttenuation = Math.pow(10, this.componentAttentuatorGainDB / 20);\r\n component_conv_recs = component_conv_recs.map(rec => {\r\n return rec.map(value => value / this.linearScaleAttenuation);\r\n });\r\n }\r\n\r\n let return_component_conv_rec = component_conv_recs[component_conv_recs.length - 1];\r\n this.clearAllFilteredRecordedSignals();\r\n\r\n this.numSuccessfulCaptured = 0;\r\n this.#currentConvolution = this.systemConvolution;\r\n this.filteredMLSRange.system.Min = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.findMinValue)(this.#currentConvolution);\r\n this.filteredMLSRange.system.Max = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.findMaxValue)(this.#currentConvolution);\r\n this.soundCheck = 'system';\r\n\r\n this.addTimeStamp(`Record ${total_dur} s of MLS with ${this.soundCheck} IIR.”`)\r\n\r\n\r\n if (this.isCalibrating) return null;\r\n await this.playMLSwithIIR(stream, this.#currentConvolution);\r\n\r\n this.stopCalibrationAudio();\r\n\r\n let system_conv_recs = this.getAllFilteredRecordedSignals();\r\n\r\n if (this.systemAttenuatorGainDB != 0) {\r\n let linearScaleAttenuation = Math.pow(10, this.systemAttenuatorGainDB / 20);\r\n system_conv_recs = system_conv_recs.map(rec => {\r\n return rec.map(value => value / linearScaleAttenuation);\r\n });\r\n }\r\n\r\n let return_system_conv_rec = system_conv_recs[system_conv_recs.length - 1];\r\n // await this.checkPowerVariation(return_system_conv_rec);\r\n\r\n this.clearAllFilteredRecordedSignals();\r\n\r\n this.sourceAudioContext.close();\r\n let recs = this.getAllUnfilteredRecordedSignals();\r\n if (this.componentAttentuatorGainDB != 0) {\r\n let linearScaleAttenuation = Math.pow(10, this.componentAttentuatorGainDB / 20);\r\n recs = recs.map(rec => {\r\n return rec.map(value => value / this.linearScaleAttenuation);\r\n });\r\n }\r\n let unconv_rec = recs[0];\r\n let return_unconv_rec = unconv_rec;\r\n let conv_rec = component_conv_recs[component_conv_recs.length - 1];\r\n\r\n //psd of component\r\n let knownGain = this.oldComponentIR.Gain;\r\n let knownFreq = this.oldComponentIR.Freq;\r\n let sampleRate = this.sourceSamplingRate || 96000;\r\n this.addTimeStamp('Compute PSD of MLS recording');\r\n if (this.isCalibrating) return null;\r\n let component_unconv_rec_psd = await this.pyServerAPI\r\n .getSubtractedPSDWithRetry(unconv_rec, knownGain, knownFreq, sampleRate)\r\n .then(res => {\r\n this.incrementStatusBar();\r\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\r\n this.emit('update', {message: this.status});\r\n return res;\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n });\r\n\r\n this.addTimeStamp('Compute PSD of filtered recording (component)');\r\n if (this.isCalibrating) return null;\r\n let component_conv_rec_psd = await this.pyServerAPI\r\n .getSubtractedPSDWithRetry(conv_rec, knownGain, knownFreq, sampleRate)\r\n .then(res => {\r\n let interpolatedGain = res.x.map((freq, index) => {\r\n let i = 0;\r\n while (i < knownFreq.length && knownFreq[i] < freq) {\r\n i++;\r\n }\r\n if (i === 0 || i === knownFreq.length) {\r\n return knownGain[i];\r\n }\r\n return (0,_utils__WEBPACK_IMPORTED_MODULE_1__.interpolate)(freq, knownFreq[i - 1], knownFreq[i], knownGain[i - 1], knownGain[i]);\r\n });\r\n\r\n let correctedGain = res.y.map(\r\n (gain, index) => 10 * Math.log10(gain) - interpolatedGain[index]\r\n );\r\n\r\n let filtered_psd = correctedGain.filter(\r\n (value, index) => res.x[index] >= this.#lowHz && res.x[index] <= this.componentFMaxHz\r\n );\r\n\r\n this.SDofFilteredRange['component'] = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.standardDeviation)(filtered_psd);\r\n this.incrementStatusBar();\r\n this.status =this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\r\n this.emit('update', {message: this.status});\r\n return res;\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n });\r\n\r\n conv_rec = system_conv_recs[system_conv_recs.length - 1];\r\n //psd of system\r\n this.addTimeStamp('Compute PSD of filtered recording (system) and unfiltered recording');\r\n if (this.isCalibrating) return null;\r\n let system_recs_psd = await this.pyServerAPI\r\n .getPSDWithRetry({\r\n unconv_rec,\r\n conv_rec,\r\n sampleRate: this.sourceSamplingRate || 96000,\r\n })\r\n .then(res => {\r\n let filtered_psd = res.y_conv\r\n .filter(\r\n (value, index) => res.x_conv[index] >= this.#lowHz && res.x_conv[index] <= this.#highHz\r\n )\r\n .map(value => 10 * Math.log10(value));\r\n\r\n let mls_psd = res.y_unconv\r\n .filter(\r\n (value, index) =>\r\n res.x_unconv[index] >= this.#lowHz && res.x_conv[index] <= this.#highHz\r\n )\r\n .map(value => 10 * Math.log10(value));\r\n\r\n this.SDofFilteredRange['mls'] = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.standardDeviation)(mls_psd);\r\n console.log('mls_psd', this.SDofFilteredRange['mls']);\r\n this.SDofFilteredRange['system'] = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.standardDeviation)(filtered_psd);\r\n this.incrementStatusBar();\r\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\r\n this.emit('update', {message: this.status});\r\n return res;\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n });\r\n\r\n //iir w/ and without bandpass psd. done\r\n unconv_rec = this.componentInvertedImpulseResponseNoBandpass;\r\n conv_rec = this.componentInvertedImpulseResponse;\r\n this.addTimeStamp('Compute PSD of component IIR and component IIR no band pass');\r\n if (this.isCalibrating) return null;\r\n let component_iir_psd = await this.pyServerAPI\r\n .getPSDWithRetry({\r\n unconv_rec,\r\n conv_rec,\r\n sampleRate: this.sourceSamplingRate || 96000,\r\n })\r\n .then(res => {\r\n this.incrementStatusBar();\r\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\r\n this.emit('update', {message: this.status});\r\n return res;\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n });\r\n unconv_rec = this.systemInvertedImpulseResponseNoBandpass;\r\n conv_rec = this.systemInvertedImpulseResponse;\r\n this.addTimeStamp('Compute PSD of system IIR and system IIR no band pass');\r\n if (this.isCalibrating) return null;\r\n let system_iir_psd = await this.pyServerAPI\r\n .getPSDWithRetry({\r\n unconv_rec,\r\n conv_rec,\r\n sampleRate: this.sourceSamplingRate || 96000,\r\n })\r\n .then(res => {\r\n this.incrementStatusBar();\r\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString() ).toString();\r\n this.emit('update', {message: this.status});\r\n return res;\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n });\r\n\r\n this.addTimeStamp('Compute PSD of MLS sequence');\r\n if (this.isCalibrating) return null;\r\n let mls_psd = await this.pyServerAPI\r\n .getMLSPSDWithRetry({\r\n mls: this.#mlsBufferView[0],\r\n sampleRate: this.sourceSamplingRate || 96000,\r\n })\r\n .then(res => {\r\n this.incrementStatusBar();\r\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\r\n this.emit('update', {message: this.status});\r\n return res;\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n });\r\n\r\n this.addTimeStamp('Compute PSD of filtered MLS (system)');\r\n if (this.isCalibrating) return null;\r\n let system_filtered_mls_psd = await this.pyServerAPI\r\n .getMLSPSDWithRetry({\r\n mls: this.systemConvolution,\r\n sampleRate: this.sourceSamplingRate || 96000,\r\n })\r\n .then(res => {\r\n this.incrementStatusBar();\r\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString() ).toString();\r\n this.emit('update', {message: this.status});\r\n return res;\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n });\r\n\r\n let system_no_bandpass_filtered_mls_psd = await this.pyServerAPI\r\n .getMLSPSDWithRetry({\r\n mls: this.systemConvolution,\r\n sampleRate: this.sourceSamplingRate || 96000,\r\n })\r\n .then(res => {\r\n this.incrementStatusBar();\r\n this.status =this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\r\n this.emit('update', {message: this.status});\r\n return res;\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n });\r\n\r\n this.addTimeStamp('Compute PSD of filtered MLS (component)');\r\n if (this.isCalibrating) return null;\r\n let component_filtered_mls_psd = await this.pyServerAPI\r\n .getMLSPSDWithRetry({\r\n mls: this.componentConvolution,\r\n sampleRate: this.sourceSamplingRate || 96000,\r\n })\r\n .then(res => {\r\n this.incrementStatusBar();\r\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString() ).toString();\r\n this.emit('update', {message: this.status});\r\n return res;\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n });\r\n\r\n let component_no_bandpass_filtered_mls_psd = await this.pyServerAPI\r\n .getMLSPSDWithRetry({\r\n mls: this.componentConvolutionNoBandpass,\r\n sampleRate: this.sourceSamplingRate || 96000,\r\n })\r\n .then(res => {\r\n this.incrementStatusBar();\r\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString() ).toString();\r\n this.emit('update', {message: this.status});\r\n return res;\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n });\r\n\r\n let gainValue = this.getGainDBSPL();\r\n\r\n iir_ir_and_plots = {\r\n filtered_recording: {\r\n component: return_component_conv_rec,\r\n system: return_system_conv_rec,\r\n },\r\n unfiltered_recording: this.getAllUnfilteredRecordedSignals()[0],\r\n system: {\r\n iir: this.systemInvertedImpulseResponse,\r\n iir_no_bandpass: this.systemInvertedImpulseResponseNoBandpass,\r\n ir: this.systemIR,\r\n iir_psd: {\r\n y: system_iir_psd['y_conv'],\r\n x: system_iir_psd['x_conv'],\r\n y_no_bandpass: system_iir_psd['y_unconv'],\r\n x_no_bandpass: system_iir_psd['x_unconv'],\r\n },\r\n filtered_mls_psd: {\r\n x: system_filtered_mls_psd['x_mls'],\r\n y: system_filtered_mls_psd['y_mls'],\r\n },\r\n filtered_no_bandpass_mls_psd: {\r\n x: system_no_bandpass_filtered_mls_psd['x_mls'],\r\n y: system_no_bandpass_filtered_mls_psd['y_mls'],\r\n },\r\n convolution: this.systemConvolution,\r\n convolutionNoBandpass: this.systemConvolutionNoBandpass,\r\n psd: {\r\n unconv: {\r\n x: system_recs_psd['x_unconv'],\r\n y: system_recs_psd['y_unconv'],\r\n },\r\n conv: {\r\n x: system_recs_psd['x_conv'],\r\n y: system_recs_psd['y_conv'],\r\n },\r\n },\r\n },\r\n component: {\r\n iir: this.componentInvertedImpulseResponse,\r\n iir_no_bandpass: this.componentInvertedImpulseResponseNoBandpass,\r\n ir: this.componentIR,\r\n ir_origin: this.componentIROrigin,\r\n ir_in_time_domain: this.componentIRInTimeDomain,\r\n iir_psd: {\r\n y: component_iir_psd['y_conv'],\r\n x: component_iir_psd['x_conv'],\r\n y_no_bandpass: component_iir_psd['y_unconv'],\r\n x_no_bandpass: component_iir_psd['x_unconv'],\r\n },\r\n filtered_mls_psd: {\r\n x: component_filtered_mls_psd['x_mls'],\r\n y: component_filtered_mls_psd['y_mls'],\r\n },\r\n filtered_no_bandpass_mls_psd: {\r\n x: component_no_bandpass_filtered_mls_psd['x_mls'],\r\n y: component_no_bandpass_filtered_mls_psd['y_mls'],\r\n },\r\n convolution: this.componentConvolution,\r\n convolutionNoBandpass: this.componentConvolutionNoBandpass,\r\n psd: {\r\n unconv: {\r\n x: component_unconv_rec_psd['x'],\r\n y: component_unconv_rec_psd['y'],\r\n },\r\n conv: {\r\n x: component_conv_rec_psd['x'],\r\n y: component_conv_rec_psd['y'],\r\n },\r\n },\r\n gainDBSPL: gainValue,\r\n },\r\n mls: this.#mlsBufferView,\r\n mls_psd: {\r\n x: mls_psd['x_mls'],\r\n y: mls_psd['y_mls'],\r\n },\r\n autocorrelations: this.autocorrelations,\r\n impulseResponses: [],\r\n };\r\n\r\n return iir_ir_and_plots;\r\n };\r\n\r\n singleSoundCheck = async stream => {\r\n let iir_ir_and_plots;\r\n const pre = this._calibrateSoundBurstPreSec; \r\n const repeats = this._calibrateSoundBurstRepeats; \r\n const burst = this._calibrateSoundBurstSec; \r\n const post = this._calibrateSoundBurstPostSec; \r\n const total_dur = pre + repeats * burst + post;\r\n if (this._calibrateSoundCheck != 'system') {\r\n this.#currentConvolution = this.componentConvolution;\r\n this.filteredMLSRange.component.Min = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.findMinValue)(this.#currentConvolution);\r\n this.filteredMLSRange.component.Max = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.findMaxValue)(this.#currentConvolution);\r\n this.soundCheck = 'component';\r\n this.addTimeStamp(`Record ${total_dur} s of MLS with ${this.soundCheck} IIR.`)\r\n this.addTimeStamp(`Record ${total_dur} s of MLS with speaker or microphone IIR.`);\r\n if (this.isCalibrating) return null;\r\n await this.playMLSwithIIR(stream, this.#currentConvolution);\r\n this.stopCalibrationAudio();\r\n } else {\r\n this.#currentConvolution = this.systemConvolution;\r\n this.filteredMLSRange.system.Min = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.findMinValue)(this.#currentConvolution);\r\n this.filteredMLSRange.system.Max = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.findMaxValue)(this.#currentConvolution);\r\n this.soundCheck = 'system';\r\n this.addTimeStamp(`Record ${total_dur} s of MLS with ${this.soundCheck} IIR.`)\r\n this.addTimeStamp(`Record ${total_dur} s of MLS with speaker or microphone IIR.`);\r\n if (this.isCalibrating) return null;\r\n await this.playMLSwithIIR(stream, this.#currentConvolution);\r\n this.stopCalibrationAudio();\r\n }\r\n let conv_recs = this.getAllFilteredRecordedSignals();\r\n if (this._calibrateSoundCheck == 'goal') {\r\n if (this.componentAttentuatorGainDB != 0) {\r\n let linearScaleAttenuation = Math.pow(10, this.componentAttentuatorGainDB / 20);\r\n conv_recs = conv_recs.map(rec => {\r\n return rec.map(value => value / this.linearScaleAttenuation);\r\n });\r\n }\r\n } else if (this._calibrateSoundCheck == 'system') {\r\n if (this.systemAttentuatorGainDB != 0) {\r\n let linearScaleAttenuation = Math.pow(10, this.systemAttentuatorGainDB / 20);\r\n conv_recs = conv_recs.map(rec => {\r\n return rec.map(value => value / this.linearScaleAttenuation);\r\n });\r\n }\r\n }\r\n\r\n //remove the filteredMLSAttenuation from the recorded signals\r\n // conv_recs = conv_recs.map(rec => {\r\n // if (this.soundCheck === 'component') {\r\n // return rec.map(value => value / this.filteredMLSAttenuation.component);\r\n // }\r\n // return rec.map(value => value / this.filteredMLSAttenuation.system);\r\n // });\r\n\r\n let recs = this.getAllUnfilteredRecordedSignals();\r\n if (this._calibrateSoundCheck == 'goal') {\r\n if (this.componentAttentuatorGainDB != 0) {\r\n let linearScaleAttenuation = Math.pow(10, this.componentAttentuatorGainDB / 20);\r\n recs = recs.map(rec => {\r\n return rec.map(value => value / this.linearScaleAttenuation);\r\n });\r\n }\r\n } else if (this._calibrateSoundCheck == 'system') {\r\n if (this.systemAttentuatorGainDB != 0) {\r\n let linearScaleAttenuation = Math.pow(10, this.systemAttentuatorGainDB / 20);\r\n recs = recs.map(rec => {\r\n return rec.map(value => value / this.linearScaleAttenuation);\r\n });\r\n }\r\n }\r\n this.clearAllFilteredRecordedSignals();\r\n console.log('Obtaining unfiltered recording from #allHzUnfilteredRecordings to calculate PSD');\r\n console.log('Obtaining filtered recording from #allHzFilteredRecordings to calculate PSD');\r\n let unconv_rec = recs[0];\r\n let return_unconv_rec = unconv_rec;\r\n let conv_rec = conv_recs[conv_recs.length - 1];\r\n let return_conv_rec = conv_rec;\r\n this.sourceAudioContext.close();\r\n if (this._calibrateSoundCheck != 'system') {\r\n let knownGain = this.oldComponentIR.Gain;\r\n let knownFreq = this.oldComponentIR.Freq;\r\n let sampleRate = this.sourceSamplingRate || 96000;\r\n this.addTimeStamp('Compute PSD of MLS recording');\r\n if (this.isCalibrating) return null;\r\n let unconv_results = await this.pyServerAPI\r\n .getSubtractedPSDWithRetry(unconv_rec, knownGain, knownFreq, sampleRate)\r\n .then(res => {\r\n console.log(res);\r\n let mls_psd = res.y\r\n .filter(\r\n (value, index) => res.x[index] >= this.#lowHz && res.x[index] <= this.systemFMaxHz\r\n )\r\n .map(value => 10 * Math.log10(value));\r\n this.SDofFilteredRange['mls'] = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.standardDeviation)(mls_psd);\r\n console.log('mls sd', this.SDofFilteredRange['mls']);\r\n this.incrementStatusBar();\r\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\r\n this.emit('update', {message: this.status});\r\n return res;\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n });\r\n\r\n this.addTimeStamp('Compute PSD recording of filtered recording (component)');\r\n if (this.isCalibrating) return null;\r\n let conv_results = await this.pyServerAPI\r\n .getSubtractedPSDWithRetry(conv_rec, knownGain, knownFreq, sampleRate)\r\n .then(res => {\r\n let interpolatedGain = res.x.map((freq, index) => {\r\n let i = 0;\r\n while (i < knownFreq.length && knownFreq[i] < freq) {\r\n i++;\r\n }\r\n if (i === 0 || i === knownFreq.length) {\r\n return knownGain[i];\r\n }\r\n return (0,_utils__WEBPACK_IMPORTED_MODULE_1__.interpolate)(\r\n freq,\r\n knownFreq[i - 1],\r\n knownFreq[i],\r\n knownGain[i - 1],\r\n knownGain[i]\r\n );\r\n });\r\n\r\n let correctedGain = res.y.map(\r\n (gain, index) => 10 * Math.log10(gain) - interpolatedGain[index]\r\n );\r\n let filtered_psd = correctedGain.filter(\r\n (value, index) => res.x[index] >= this.#lowHz && res.x[index] <= this.#highHz\r\n );\r\n\r\n this.SDofFilteredRange['component'] = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.standardDeviation)(filtered_psd);\r\n this.incrementStatusBar();\r\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\r\n this.emit('update', {message: this.status});\r\n return res;\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n });\r\n\r\n unconv_rec = this.componentInvertedImpulseResponseNoBandpass;\r\n conv_rec = this.componentInvertedImpulseResponse;\r\n this.addTimeStamp('Compute PSD of component IIR and component IIR no bandpass');\r\n if (this.isCalibrating) return null;\r\n let component_iir_psd = await this.pyServerAPI\r\n .getPSDWithRetry({\r\n unconv_rec,\r\n conv_rec,\r\n sampleRate: this.sourceSamplingRate || 96000,\r\n })\r\n .then(res => {\r\n this.incrementStatusBar();\r\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\r\n this.emit('update', {message: this.status});\r\n return res;\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n });\r\n unconv_rec = this.systemInvertedImpulseResponseNoBandpass;\r\n conv_rec = this.systemInvertedImpulseResponse;\r\n this.addTimeStamp('Compute PSD of system IIR and system IIR no bandpass');\r\n if (this.isCalibrating) return null;\r\n let system_iir_psd = await this.pyServerAPI\r\n .getPSDWithRetry({\r\n unconv_rec,\r\n conv_rec,\r\n sampleRate: this.sourceSamplingRate || 96000,\r\n })\r\n .then(res => {\r\n this.incrementStatusBar();\r\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\r\n this.emit('update', {message: this.status});\r\n return res;\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n });\r\n\r\n this.addTimeStamp('Compute PSD of MLS sequence');\r\n if (this.isCalibrating) return null;\r\n let mls_psd = await this.pyServerAPI\r\n .getMLSPSDWithRetry({\r\n mls: this.#mlsBufferView[this.icapture],\r\n sampleRate: this.sourceSamplingRate || 96000,\r\n })\r\n .then(res => {\r\n this.incrementStatusBar();\r\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\r\n this.emit('update', {message: this.status});\r\n return res;\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n });\r\n\r\n this.addTimeStamp('Compute PSD of filtered MLS (component)');\r\n if (this.isCalibrating) return null;\r\n let filtered_mls_psd = await this.pyServerAPI\r\n .getMLSPSDWithRetry({\r\n mls: this.componentConvolution,\r\n sampleRate: this.sourceSamplingRate || 96000,\r\n })\r\n .then(res => {\r\n this.incrementStatusBar();\r\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\r\n this.emit('update', {message: this.status});\r\n return res;\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n });\r\n\r\n let filtered_no_bandpass_mls_psd = await this.pyServerAPI\r\n .getMLSPSDWithRetry({\r\n mls: this.componentConvolutionNoBandpass,\r\n sampleRate: this.sourceSamplingRate || 96000,\r\n })\r\n .then(res => {\r\n this.incrementStatusBar();\r\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\r\n this.emit('update', {message: this.status});\r\n return res;\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n });\r\n\r\n let gainValue = this.getGainDBSPL();\r\n iir_ir_and_plots = {\r\n unfiltered_recording: return_unconv_rec,\r\n filtered_recording: return_conv_rec,\r\n system: {\r\n iir: this.systemInvertedImpulseResponse,\r\n iir_no_bandpass: this.systemInvertedImpulseResponseNoBandpass,\r\n ir: this.systemIR,\r\n iir_psd: {\r\n y: system_iir_psd['y_conv'],\r\n x: system_iir_psd['y_conv'],\r\n y_no_bandpass: system_iir_psd['y_unconv'],\r\n x_no_bandpass: system_iir_psd['x_unconv'],\r\n },\r\n filtered_recording: [],\r\n filtered_mls_psd: {},\r\n filtered_no_bandpass_mls_psd: {},\r\n convolution: this.systemConvolution,\r\n convolutionNoBandpass: this.systemConvolutionNoBandpass,\r\n psd: {\r\n unconv: {\r\n x: [],\r\n y: [],\r\n },\r\n conv: {\r\n x: [],\r\n y: [],\r\n },\r\n },\r\n },\r\n component: {\r\n iir: this.componentInvertedImpulseResponse,\r\n iir_no_bandpass: this.componentInvertedImpulseResponseNoBandpass,\r\n ir: this.componentIR,\r\n ir_origin: this.componentIROrigin,\r\n ir_in_time_domain: this.componentIRInTimeDomain,\r\n iir_psd: {\r\n y: component_iir_psd['y_conv'],\r\n x: component_iir_psd['x_conv'],\r\n y_no_bandpass: component_iir_psd['y_unconv'],\r\n x_no_bandpass: component_iir_psd['x_unconv'],\r\n },\r\n filtered_mls_psd: {\r\n x: filtered_mls_psd['x_mls'],\r\n y: filtered_mls_psd['y_mls'],\r\n },\r\n filtered_no_bandpass_mls_psd: {\r\n x: filtered_no_bandpass_mls_psd['x_mls'],\r\n y: filtered_no_bandpass_mls_psd['y_mls'],\r\n },\r\n convolution: this.componentConvolution,\r\n convolutionNoBandpass: this.componentConvolutionNoBandpass,\r\n psd: {\r\n unconv: {\r\n x: unconv_results['x'],\r\n y: unconv_results['y'],\r\n },\r\n conv: {\r\n x: conv_results['x'],\r\n y: conv_results['y'],\r\n },\r\n },\r\n gainDBSPL: gainValue,\r\n },\r\n mls: this.#mlsBufferView,\r\n mls_psd: {\r\n x: mls_psd['x_mls'],\r\n y: mls_psd['y_mls'],\r\n },\r\n autocorrelations: this.autocorrelations,\r\n impulseResponses: [],\r\n };\r\n } else {\r\n this.addTimeStamp('Compute PSD of filtered recording (system) and unfiltered recording');\r\n if (this.isCalibrating) return null;\r\n let results = await this.pyServerAPI\r\n .getPSDWithRetry({\r\n unconv_rec,\r\n conv_rec,\r\n sampleRate: this.sourceSamplingRate || 96000,\r\n })\r\n .then(res => {\r\n let filtered_psd = res.y_conv\r\n .filter(\r\n (value, index) =>\r\n res.x_conv[index] >= this.#lowHz && res.x_conv[index] <= this.systemFMaxHz\r\n )\r\n .map(value => 10 * Math.log10(value));\r\n\r\n let mls_psd = res.y_unconv\r\n .filter(\r\n (value, index) =>\r\n res.x_unconv[index] >= this.#lowHz && res.x_conv[index] <= this.systemFMaxHz\r\n )\r\n .map(value => 10 * Math.log10(value));\r\n this.SDofFilteredRange['mls'] = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.standardDeviation)(mls_psd);\r\n this.SDofFilteredRange['system'] = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.standardDeviation)(filtered_psd);\r\n this.incrementStatusBar();\r\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\r\n this.emit('update', {message: this.status});\r\n return res;\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n });\r\n\r\n //iir w/ and without bandpass psd\r\n unconv_rec = this.componentInvertedImpulseResponseNoBandpass;\r\n conv_rec = this.componentInvertedImpulseResponse;\r\n this.addTimeStamp('Compute PSD of component IIR and component IIR no band pass');\r\n if (this.isCalibrating) return null;\r\n let component_iir_psd = await this.pyServerAPI\r\n .getPSDWithRetry({\r\n unconv_rec,\r\n conv_rec,\r\n sampleRate: this.sourceSamplingRate || 96000,\r\n })\r\n .then(res => {\r\n this.incrementStatusBar();\r\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\r\n this.emit('update', {message: this.status});\r\n return res;\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n });\r\n unconv_rec = this.systemInvertedImpulseResponseNoBandpass;\r\n conv_rec = this.systemInvertedImpulseResponse;\r\n this.addTimeStamp('Compute PSD of system IIR and system IIR no band pass');\r\n if (this.isCalibrating) return null;\r\n let system_iir_psd = await this.pyServerAPI\r\n .getPSDWithRetry({\r\n unconv_rec,\r\n conv_rec,\r\n sampleRate: this.sourceSamplingRate || 96000,\r\n })\r\n .then(res => {\r\n this.incrementStatusBar();\r\n this.status = this.generateTemplate( `All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\r\n this.emit('update', {message: this.status});\r\n return res;\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n });\r\n\r\n this.addTimeStamp('Compute PSD of MLS sequence');\r\n if (this.isCalibrating) return null;\r\n let mls_psd = await this.pyServerAPI\r\n .getMLSPSDWithRetry({\r\n mls: this.#mlsBufferView[this.icapture],\r\n sampleRate: this.sourceSamplingRate || 96000,\r\n })\r\n .then(res => {\r\n this.incrementStatusBar();\r\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\r\n this.emit('update', {message: this.status});\r\n return res;\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n });\r\n\r\n this.addTimeStamp('Compute PSD of filtered MLS (system)');\r\n if (this.isCalibrating) return null;\r\n let filtered_mls_psd = await this.pyServerAPI\r\n .getMLSPSDWithRetry({\r\n mls: this.systemConvolution,\r\n sampleRate: this.sourceSamplingRate || 96000,\r\n })\r\n .then(res => {\r\n this.incrementStatusBar();\r\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\r\n this.emit('update', {message: this.status});\r\n return res;\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n });\r\n\r\n let filtered_no_bandpass_mls_psd = await this.pyServerAPI\r\n .getMLSPSDWithRetry({\r\n mls: this.systemConvolutionNoBandpass,\r\n sampleRate: this.sourceSamplingRate || 96000,\r\n })\r\n .then(res => {\r\n this.incrementStatusBar();\r\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\r\n this.emit('update', {message: this.status});\r\n return res;\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n });\r\n\r\n let gainValue = this.getGainDBSPL();\r\n iir_ir_and_plots = {\r\n unfiltered_recording: return_unconv_rec,\r\n filtered_recording: return_conv_rec,\r\n system: {\r\n iir: this.systemInvertedImpulseResponse,\r\n iir_no_bandpass: this.systemInvertedImpulseResponseNoBandpass,\r\n ir: this.systemIR,\r\n iir_psd: {\r\n y: system_iir_psd['y_conv'],\r\n x: system_iir_psd['y_conv'],\r\n y_no_bandpass: system_iir_psd['y_unconv'],\r\n x_no_bandpass: system_iir_psd['x_unconv'],\r\n },\r\n filtered_recording: [],\r\n filtered_mls_psd: {\r\n x: filtered_mls_psd['x_mls'],\r\n y: filtered_mls_psd['y_mls'],\r\n },\r\n filtered_no_bandpass_mls_psd: {\r\n x: filtered_no_bandpass_mls_psd['x_mls'],\r\n y: filtered_no_bandpass_mls_psd['y_mls'],\r\n },\r\n convolution: this.systemConvolution,\r\n convolutionNoBandpass: this.systemConvolutionNoBandpass,\r\n psd: {\r\n unconv: {\r\n x: results['x_unconv'],\r\n y: results['y_unconv'],\r\n },\r\n conv: {\r\n x: results['x_conv'],\r\n y: results['y_conv'],\r\n },\r\n },\r\n },\r\n component: {\r\n iir: this.componentInvertedImpulseResponse,\r\n iir_no_bandpass: this.componentInvertedImpulseResponseNoBandpass,\r\n ir: this.componentIR,\r\n ir_origin: this.componentIROrigin,\r\n ir_in_time_domain: this.componentIRInTimeDomain,\r\n iir_psd: {\r\n y: component_iir_psd['y_conv'],\r\n x: component_iir_psd['x_conv'],\r\n y_no_bandpass: component_iir_psd['y_unconv'],\r\n x_no_bandpass: component_iir_psd['x_unconv'],\r\n },\r\n filtered_mls_psd: {},\r\n filtered_no_bandpass_mls_psd: {},\r\n convolution: this.componentConvolution,\r\n convolutionNoBandpass: this.componentConvolutionNoBandpass,\r\n psd: {\r\n unconv: {\r\n x: [],\r\n y: [],\r\n },\r\n conv: {\r\n x: [],\r\n y: [],\r\n },\r\n },\r\n gainDBSPL: gainValue,\r\n },\r\n mls: this.#mlsBufferView,\r\n mls_psd: {\r\n x: mls_psd['x_mls'],\r\n y: mls_psd['y_mls'],\r\n },\r\n autocorrelations: this.autocorrelations,\r\n impulseResponses: [],\r\n };\r\n }\r\n if (this.isCalibrating) return null;\r\n await Promise.all(this.impulseResponses).then(res => {\r\n for (let i = 0; i < res.length; i++) {\r\n if (res[i] != undefined) {\r\n iir_ir_and_plots['impulseResponses'].push(res[i]);\r\n }\r\n }\r\n });\r\n\r\n if (this.#download) {\r\n this.downloadSingleUnfilteredRecording();\r\n this.downloadSingleFilteredRecording();\r\n (0,_utils__WEBPACK_IMPORTED_MODULE_1__.saveToCSV)(this.#mls, 'MLS.csv');\r\n (0,_utils__WEBPACK_IMPORTED_MODULE_1__.saveToCSV)(this.componentConvolution, 'python_component_convolution_mls_iir.csv');\r\n (0,_utils__WEBPACK_IMPORTED_MODULE_1__.saveToCSV)(this.systemConvolution, 'python_system_convolution_mls_iir.csv');\r\n (0,_utils__WEBPACK_IMPORTED_MODULE_1__.saveToCSV)(this.componentInvertedImpulseResponse, 'componentIIR.csv');\r\n (0,_utils__WEBPACK_IMPORTED_MODULE_1__.saveToCSV)(this.systemInvertedImpulseResponse, 'systemIIR.csv');\r\n for (let i = 0; i < this.autocorrelations.length; i++) {\r\n (0,_utils__WEBPACK_IMPORTED_MODULE_1__.saveToCSV)(this.autocorrelations[i], `autocorrelation_${i}`);\r\n }\r\n const computedIRagain = await Promise.all(this.impulseResponses).then(res => {\r\n for (let i = 0; i < res.length; i++) {\r\n if (res[i] != undefined) {\r\n (0,_utils__WEBPACK_IMPORTED_MODULE_1__.saveToCSV)(res[i], `IR_${i}`);\r\n }\r\n }\r\n });\r\n }\r\n\r\n return iir_ir_and_plots;\r\n };\r\n\r\n /**\r\n * Public method to start the calibration process. Objects intialized from webassembly allocate new memory\r\n * and must be manually freed. This function is responsible for intializing the MlsGenInterface,\r\n * and wrapping the calibration steps with a garbage collection safe gaurd.\r\n *\r\n * @public\r\n * @param stream - The stream of audio from the Listener.\r\n * @example\r\n */\r\n startCalibrationImpulseResponse = async stream => {\r\n console.log('JS used memory:', performance.memory.usedJSHeapSize / 1024 / 1024, 'mb');\r\n let desired_time = this.desired_time_per_mls;\r\n let checkRec = 'allhz';\r\n\r\n console.log('MLS sequence should be of length: ' + this.sourceSamplingRate * desired_time);\r\n\r\n length = this.sourceSamplingRate * desired_time;\r\n //get mls here\r\n // const calibrateSoundBurstDb = Math.pow(10, this._calibrateSoundBurstDb / 20);\r\n\r\n this.power_dB = 0;\r\n\r\n if (!this._calibrateSoundBurstLevelReTBool) {\r\n this.power_dB = this._calibrateSoundBurstDb;\r\n } else {\r\n this.power_dB = this._calibrateSoundBurstDb + (this.T - this.gainDBSPL);\r\n }\r\n\r\n const amplitude = Math.pow(10, this.power_dB / 20);\r\n //MLSpower = Math.pow(10,this.power_dB/20);\r\n this.addTimeStamp('Compute MLS sequence');\r\n if (this.isCalibrating) return null;\r\n await this.pyServerAPI\r\n .getMLSWithRetry({\r\n length,\r\n amplitude,\r\n calibrateSoundBurstMLSVersions: this.numCaptures,\r\n })\r\n .then(res => {\r\n console.log(res);\r\n this.#mlsBufferView = res['mls'];\r\n this.#mls = res['unscaledMLS'];\r\n })\r\n .catch(err => {\r\n // this.emit('InvertedImpulseResponse', {res: false});\r\n console.error(err);\r\n });\r\n this.numSuccessfulBackgroundCaptured = 0;\r\n if (this._calibrateSoundBackgroundSecs > 0) {\r\n this.mode = 'background';\r\n this.status = this.generateTemplate(`All Hz Calibration: sampling the background noise...`.toString()).toString();\r\n this.emit('update', {message: this.status});\r\n if (this.isCalibrating) return null;\r\n await this.recordBackground(\r\n stream, //stream\r\n () => this.numSuccessfulBackgroundCaptured < 1, //loop condition\r\n this.#awaitBackgroundNoiseRecording, //sleep to record\r\n this.sendBackgroundRecording, //send to get PSD\r\n this.mode,\r\n checkRec\r\n );\r\n this.incrementStatusBar();\r\n }\r\n this.mode = 'unfiltered';\r\n this.numSuccessfulCaptured = 0;\r\n\r\n if (this.isCalibrating) return null;\r\n for (var i = 0; i < this.numCaptures; i++) {\r\n this.icapture = i;\r\n await this.calibrationSteps(\r\n stream,\r\n this.#playCalibrationAudio, // play audio func (required)\r\n this.#createCalibrationNodeFromBuffer(this.#mlsBufferView[this.icapture]), // before play func\r\n this.#awaitSignalOnset, // before record\r\n () => this.numSuccessfulCaptured < 2, // loop while true\r\n this.#awaitDesiredMLSLength, // during record\r\n this.#afterMLSRecord, // after record\r\n this.mode,\r\n checkRec\r\n );\r\n this.stopCalibrationAudio();\r\n }\r\n checkRec = false;\r\n\r\n // at this stage we've captured all the required signals,\r\n // and have received IRs for each one\r\n // so let's send all the IRs to the server to be converted to a single IIR\r\n if (this.isCalibrating) return null;\r\n await this.sendSystemImpulseResponsesToServerForProcessing();\r\n await this.pyServerAPI.checkMemory();\r\n if (this.isCalibrating) return null;\r\n await this.sendComponentImpulseResponsesToServerForProcessing();\r\n\r\n this.numSuccessfulCaptured = 0;\r\n\r\n let iir_ir_and_plots;\r\n if (this._calibrateSoundCheck != 'none') {\r\n //do single check\r\n if (this._calibrateSoundCheck == 'goal' || this._calibrateSoundCheck == 'system') {\r\n if (this.isCalibrating) return null;\r\n iir_ir_and_plots = await this.singleSoundCheck(stream);\r\n if (this.isCalibrating) return null;\r\n } else {\r\n //both\r\n if (this.isCalibrating) return null;\r\n iir_ir_and_plots = await this.bothSoundCheck(stream);\r\n if (this.isCalibrating) return null;\r\n }\r\n } else {\r\n let unconv_rec = this.componentInvertedImpulseResponseNoBandpass;\r\n let conv_rec = this.componentInvertedImpulseResponse;\r\n if (this.isCalibrating) return null;\r\n let component_iir_psd = await this.pyServerAPI\r\n .getPSDWithRetry({\r\n unconv_rec,\r\n conv_rec,\r\n sampleRate: this.sourceSamplingRate || 96000,\r\n })\r\n .then(res => {\r\n this.incrementStatusBar();\r\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\r\n this.emit('update', {message: this.status});\r\n return res;\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n });\r\n unconv_rec = this.systemInvertedImpulseResponseNoBandpass;\r\n conv_rec = this.systemInvertedImpulseResponse;\r\n if (this.isCalibrating) return null;\r\n let system_iir_psd = await this.pyServerAPI\r\n .getPSDWithRetry({\r\n unconv_rec,\r\n conv_rec,\r\n sampleRate: this.sourceSamplingRate || 96000,\r\n })\r\n .then(res => {\r\n this.incrementStatusBar();\r\n this.status = this.generateTemplate(`All Hz Calibration: done computing the PSD graphs...`.toString()).toString();\r\n this.emit('update', {message: this.status});\r\n return res;\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n });\r\n\r\n let gainValue = this.getGainDBSPL();\r\n iir_ir_and_plots = {\r\n unfiltered_recording: return_unconv_rec,\r\n filtered_recording: return_conv_rec,\r\n system: {\r\n iir: this.systemInvertedImpulseResponse,\r\n iir_no_bandpass: this.systemInvertedImpulseResponseNoBandpass,\r\n ir: this.systemIR,\r\n iir_psd: {\r\n y: system_iir_psd['y_conv'],\r\n x: system_iir_psd['y_conv'],\r\n y_no_bandpass: system_iir_psd['y_unconv'],\r\n x_no_bandpass: system_iir_psd['x_unconv'],\r\n },\r\n filtered_recording: [],\r\n convolution: this.systemConvolution,\r\n convolutionNoBandpass: this.systemConvolutionNoBandpass,\r\n psd: {\r\n unconv: {\r\n x: [],\r\n y: [],\r\n },\r\n conv: {\r\n x: [],\r\n y: [],\r\n },\r\n },\r\n },\r\n component: {\r\n iir: this.componentInvertedImpulseResponse,\r\n iir_no_bandpass: this.componentInvertedImpulseResponseNoBandpass,\r\n ir: this.componentIR,\r\n ir_in_time_domain: this.componentIRInTimeDomain,\r\n iir_psd: {\r\n y: component_iir_psd['y_conv'],\r\n x: component_iir_psd['x_conv'],\r\n y_no_bandpass: component_iir_psd['y_unconv'],\r\n x_no_bandpass: component_iir_psd['x_unconv'],\r\n },\r\n convolution: this.componentConvolution,\r\n convolutionNoBandpass: this.componentConvolutionNoBandpass,\r\n psd: {\r\n unconv: {\r\n x: [],\r\n y: [],\r\n },\r\n conv: {\r\n x: [],\r\n y: [],\r\n },\r\n },\r\n gainDBSPL: gainValue,\r\n },\r\n mls: this.#mlsBufferView,\r\n autocorrelations: this.autocorrelations,\r\n impulseResponses: [],\r\n };\r\n if (this.isCalibrating) return null;\r\n await Promise.all(this.impulseResponses).then(res => {\r\n for (let i = 0; i < res.length; i++) {\r\n if (res[i] != undefined) {\r\n iir_ir_and_plots['impulseResponses'].push(res[i]);\r\n }\r\n }\r\n });\r\n\r\n if (this.#download) {\r\n (0,_utils__WEBPACK_IMPORTED_MODULE_1__.saveToCSV)(this.#mls, 'MLS.csv');\r\n (0,_utils__WEBPACK_IMPORTED_MODULE_1__.saveToCSV)(this.componentConvolution, 'python_component_convolution_mls_iir.csv');\r\n (0,_utils__WEBPACK_IMPORTED_MODULE_1__.saveToCSV)(this.systemConvolution, 'python_system_convolution_mls_iir.csv');\r\n (0,_utils__WEBPACK_IMPORTED_MODULE_1__.saveToCSV)(this.componentInvertedImpulseResponse, 'componentIIR.csv');\r\n (0,_utils__WEBPACK_IMPORTED_MODULE_1__.saveToCSV)(this.systemInvertedImpulseResponse, 'systemIIR.csv');\r\n for (let i = 0; i < this.autocorrelations.length; i++) {\r\n (0,_utils__WEBPACK_IMPORTED_MODULE_1__.saveToCSV)(this.autocorrelations[i], `autocorrelation_${i}`);\r\n }\r\n const computedIRagain = await Promise.all(this.impulseResponses).then(res => {\r\n for (let i = 0; i < res.length; i++) {\r\n if (res[i] != undefined) {\r\n (0,_utils__WEBPACK_IMPORTED_MODULE_1__.saveToCSV)(res[i], `IR_${i}`);\r\n }\r\n }\r\n });\r\n }\r\n }\r\n if (this.isCalibrating) return null;\r\n this.percent_complete = 100;\r\n this.status = this.generateTemplate(`All Hz Calibration: Finished`.toString()).toString();\r\n this.emit('update', {message: this.status});\r\n\r\n //here after calibration we have the component calibration (either loudspeaker or microphone) in the same form as the componentIR\r\n //that was used to calibrate\r\n // saveToJSON(iir_ir_and_plots);\r\n return iir_ir_and_plots;\r\n };\r\n\r\n //////////////////////volume\r\n\r\n handleIncomingData = data => {\r\n console.log('Received data: ', data);\r\n if (data.type === 'soundGainDBSPL') {\r\n this.soundGainDBSPL = data.value;\r\n } else {\r\n throw new Error(`Unknown data type: ${data.type}`);\r\n }\r\n };\r\n\r\n #getTruncatedSignal = (left = 3.5, right = 4.5) => {\r\n const start = Math.floor(left * this.sourceSamplingRate);\r\n const end = Math.floor(right * this.sourceSamplingRate);\r\n const result = Array.from(this.getLastVolumeRecordedSignal().slice(start, end));\r\n console.log(\r\n 'Obtaining last 1000 hz recording from #allVolumeRecordings to send for processing'\r\n );\r\n /**\r\n * function to check that capture was properly made\r\n * @param {*} list\r\n */\r\n const checkResult = list => {\r\n const setItem = new Set(list);\r\n if (setItem.size === 1 && setItem.has(0)) {\r\n console.warn(\r\n 'The last capture failed, all recorded signal is zero',\r\n this.getAllVolumeRecordedSignals()\r\n );\r\n this.stopCalibrationAudio();\r\n this.isCalibrating = true;\r\n // restartButton.style.display = 'none';\r\n this.emit('update', {message: 'Connection failed, hit restart button to reconnect'});\r\n }\r\n if (setItem.size === 0) {\r\n console.warn('The last capture failed, no recorded signal');\r\n this.stopCalibrationAudio();\r\n this.isCalibrating = true;\r\n // restartButton.style.display = 'none';\r\n this.emit('update', {message: 'Connection failed, hit restart button to reconnect'});\r\n }\r\n };\r\n checkResult(result);\r\n return result;\r\n };\r\n\r\n /** \r\n * \r\n * \r\n Construct a calibration Node with the calibration parameters and given gain value\r\n * @param {*} gainValue\r\n * */\r\n #createCalibrationToneWithGainValue = gainValue => {\r\n const audioContext = this.makeNewSourceAudioContext();\r\n const oscilator = audioContext.createOscillator();\r\n const gainNode = audioContext.createGain();\r\n const taperGainNode = audioContext.createGain();\r\n const offsetGainNode = audioContext.createGain();\r\n const totalDuration = this.CALIBRATION_TONE_DURATION * 1.2;\r\n\r\n oscilator.frequency.value = this.#CALIBRATION_TONE_FREQUENCY;\r\n oscilator.type = this.#CALIBRATION_TONE_TYPE;\r\n gainNode.gain.value = gainValue;\r\n\r\n oscilator.connect(gainNode);\r\n gainNode.connect(taperGainNode);\r\n const onsetCurve = this.createSCurveBuffer();\r\n taperGainNode.gain.setValueCurveAtTime(onsetCurve, 0, this.TAPER_SECS);\r\n taperGainNode.connect(offsetGainNode);\r\n const offsetCurve = this.createSCurveBuffer(false);\r\n offsetGainNode.gain.setValueCurveAtTime(\r\n offsetCurve,\r\n totalDuration - this.TAPER_SECS,\r\n this.TAPER_SECS\r\n );\r\n offsetGainNode.connect(audioContext.destination);\r\n\r\n const gainValuesOverTime = [];\r\n const sampleRate = this.#CALIBRATION_TONE_FREQUENCY; // Number of samples per second\r\n const interval = 1 / sampleRate; // Time between samples\r\n\r\n for (let t = 0; t <= totalDuration; t += interval) {\r\n let gainValueAtTime = gainValue;\r\n\r\n // Apply the onset curve\r\n if (t < this.TAPER_SECS) {\r\n const onsetIndex = Math.floor((t / this.TAPER_SECS) * onsetCurve.length);\r\n gainValueAtTime *= onsetCurve[onsetIndex];\r\n }\r\n\r\n // Apply the offset curve\r\n if (t > totalDuration - this.TAPER_SECS) {\r\n const offsetTime = t - (totalDuration - this.TAPER_SECS);\r\n const offsetIndex = Math.floor((offsetTime / this.TAPER_SECS) * offsetCurve.length);\r\n gainValueAtTime *= offsetCurve[offsetIndex];\r\n }\r\n\r\n gainValuesOverTime.push(gainValueAtTime);\r\n }\r\n\r\n this.waveforms['volume'][this.inDB] = gainValuesOverTime;\r\n\r\n this.addCalibrationNode(oscilator);\r\n };\r\n\r\n /**\r\n * Construct a Calibration Node with the calibration parameters.\r\n *\r\n * @private\r\n * @example\r\n */\r\n #createCalibrationNode = () => {\r\n const audioContext = this.makeNewSourceAudioContext();\r\n const oscilator = audioContext.createOscillator();\r\n const gainNode = audioContext.createGain();\r\n\r\n oscilator.frequency.value = this.#CALIBRATION_TONE_FREQUENCY;\r\n oscilator.type = this.#CALIBRATION_TONE_TYPE;\r\n gainNode.gain.value = 0.04;\r\n\r\n oscilator.connect(gainNode);\r\n gainNode.connect(audioContext.destination);\r\n\r\n this.addCalibrationNode(oscilator);\r\n };\r\n\r\n #playCalibrationAudioVolume = async () => {\r\n if (this.numCalibratingRoundsCompleted==1) {\r\n this.recordingChecks['warnings'].push(`1000Hz. Re-recorded ${this.inDB} dB because SD ${(this.recordingChecks['volume'][this.inDB]['sd'])} > ${this.calibrateSound1000HzMaxSD_dB} dB`);\r\n const currentStatus = `1000 Hz: Re-recording at ${this.inDB} dB because SD \r\n ${this.recordingChecks['volume'][this.inDB]['sd']} > \r\n ${this.calibrateSound1000HzMaxSD_dB} dB`.toString();\r\n this.status = this.generateTemplate(currentStatus).toString();\r\n this.emit('update', {\r\n message: this.status,\r\n });\r\n }\r\n const totalDuration = this.CALIBRATION_TONE_DURATION * 1.2;\r\n\r\n this.calibrationNodes[0].start(0);\r\n this.calibrationNodes[0].stop(totalDuration);\r\n console.log(`Playing a buffer of ${this.CALIBRATION_TONE_DURATION} seconds of audio`);\r\n console.log(`Waiting a total of ${totalDuration} seconds`);\r\n await (0,_utils__WEBPACK_IMPORTED_MODULE_1__.sleep)(totalDuration);\r\n };\r\n\r\n stopCalibrationAudioVolume = () => {\r\n if (this.calibrationNodes.length > 0) {\r\n this.calibrationNodes[0].stop();\r\n }\r\n };\r\n\r\n #sendToServerForProcessing = async lCalib => {\r\n console.log('Sending data to server');\r\n const total_dur = this.calibrateSound1000HzPreSec + this.calibrateSound1000HzSec + this.calibrateSound1000HzPostSec;\r\n this.addTimeStamp(\r\n \"1000 Hz: recorded at \" + this.inDB + \r\n \" dB (\" + this.calibrateSound1000HzPreSec.toFixed(1) + \r\n \" s pre + \" + this.calibrateSound1000HzSec.toFixed(1) + \r\n \" s used + \" + this.calibrateSound1000HzPostSec.toFixed(1) + \r\n \" s post)\"\r\n );\r\n let left = this.calibrateSound1000HzPreSec;\r\n let right = this.calibrateSound1000HzPreSec + this.calibrateSound1000HzSec;\r\n if (this.isCalibrating) return null;\r\n this.pyServerAPI\r\n .getVolumeCalibration({\r\n sampleRate: this.sourceSamplingRate,\r\n payload: this.#getTruncatedSignal(left, right),\r\n lCalib: lCalib,\r\n })\r\n .then(res => {\r\n if (this.outDBSPL === null) {\r\n this.incrementStatusBar();\r\n this.outDBSPL = res['outDbSPL'];\r\n this.outDBSPL1000 = res['outDbSPL1000'];\r\n this.THD = res['thd'];\r\n }\r\n })\r\n .catch(err => {\r\n console.warn(err);\r\n });\r\n const rec = this.getLastVolumeRecordedSignal();\r\n console.log('pre period power: ', (0,_powerCheck__WEBPACK_IMPORTED_MODULE_2__.getPower)(rec.slice(0,this.calibrateSound1000HzPreSec * this.sourceSamplingRate)).toFixed(1));\r\n console.log('pre period power: ', \r\n (0,_powerCheck__WEBPACK_IMPORTED_MODULE_2__.getPower)(rec.slice(\r\n this.calibrateSound1000HzPreSec * this.sourceSamplingRate,\r\n (this.calibrateSound1000HzPreSec + this.calibrateSound1000HzSec)* this.sourceSamplingRate)).toFixed(1));\r\n console.log('pre period power: ', (0,_powerCheck__WEBPACK_IMPORTED_MODULE_2__.getPower)(rec.slice(\r\n (this.calibrateSound1000HzPreSec + this.calibrateSound1000HzSec)* this.sourceSamplingRate)).toFixed(1));\r\n const res = (0,_powerCheck__WEBPACK_IMPORTED_MODULE_2__.volumePowerCheck)(\r\n rec,\r\n this.sourceSamplingRate || 96000,\r\n this.calibrateSound1000HzPreSec,\r\n this.calibrateSound1000HzSec, \r\n this._calibrateSoundPowerBinDesiredSec);\r\n console.log(res);\r\n this.recordingChecks['volume'][this.inDB] = res;\r\n };\r\n\r\n startCalibrationVolume = async (stream, gainValues, lCalib, componentGainDBSPL) => {\r\n if (this.isCalibrating) return null;\r\n const trialIterations = gainValues.length;\r\n this.status_denominator += trialIterations;\r\n const thdValues = [];\r\n const inDBValues = [];\r\n let inDB = 0;\r\n const outDBSPLValues = [];\r\n const outDBSPL1000Values = [];\r\n let checkRec = 'loudest';\r\n // do one calibration that will be discarded\r\n const soundLevelToDiscard = -60;\r\n const gainToDiscard = Math.pow(10, soundLevelToDiscard / 20);\r\n this.inDB = soundLevelToDiscard;\r\n this.status = this.generateTemplate(`1000 Hz Calibration: Sound Level ${soundLevelToDiscard} dB`.toString()).toString();\r\n //this.emit('update', {message: `1000 Hz Calibration: Sound Level ${soundLevelToDiscard} dB`});\r\n this.emit('update', {message: this.status});\r\n this.startTime = new Date().getTime();\r\n\r\n do {\r\n console.log('while loop');\r\n if (this.isCalibrating) {\r\n console.log('restart calibration');\r\n return null;\r\n }\r\n // eslint-disable-next-line no-await-in-loop\r\n await this.volumeCalibrationSteps(\r\n stream,\r\n this.#playCalibrationAudioVolume,\r\n this.#createCalibrationToneWithGainValue,\r\n this.#sendToServerForProcessing,\r\n gainToDiscard,\r\n lCalib, //todo make this a class parameter\r\n checkRec,\r\n () => {return this.recordingChecks['volume'][this.inDB]['sd']},\r\n this.calibrateSound1000HzMaxSD_dB\r\n );\r\n } while (this.outDBSPL === null);\r\n //reset the values\r\n //this.incrementStatusBar();\r\n\r\n this.outDBSPL = null;\r\n this.outDBSPL = null;\r\n this.outDBSPL1000 = null;\r\n this.THD = null;\r\n\r\n // run the calibration at different gain values provided by the user\r\n for (let i = 0; i < trialIterations; i++) {\r\n //convert gain to DB and add to inDB\r\n if (i == trialIterations - 1) {\r\n checkRec = 'loudest';\r\n }\r\n inDB = Math.log10(gainValues[i]) * 20;\r\n // precision to 1 decimal place\r\n inDB = Math.round(inDB * 10) / 10;\r\n this.inDB = inDB;\r\n inDBValues.push(inDB);\r\n console.log('next update');\r\n this.status = this.generateTemplate(`1000 Hz Calibration: Sound Level ${inDB} dB`.toString()).toString();\r\n this.emit('update', {message: this.status});\r\n do {\r\n if (this.isCalibrating) {\r\n console.log('restart calibration');\r\n return null;\r\n }\r\n // eslint-disable-next-line no-await-in-loop\r\n await this.volumeCalibrationSteps(\r\n stream,\r\n this.#playCalibrationAudioVolume,\r\n this.#createCalibrationToneWithGainValue,\r\n this.#sendToServerForProcessing,\r\n gainValues[i],\r\n lCalib, //todo make this a class parameter\r\n checkRec,\r\n () => {return this.recordingChecks?.['volume']?.[this.inDB]?.['sd'] || 0},\r\n this.calibrateSound1000HzMaxSD_dB\r\n );\r\n } while (this.outDBSPL === null);\r\n outDBSPL1000Values.push(this.outDBSPL1000);\r\n thdValues.push(this.THD);\r\n outDBSPLValues.push(this.outDBSPL);\r\n\r\n this.outDBSPL = null;\r\n this.outDBSPL1000 = null;\r\n this.THD = null;\r\n }\r\n if (this.isCalibrating) return null;\r\n // get the volume calibration parameters from the server\r\n this.addTimeStamp('Compute sound calibration parameters');\r\n\r\n const parameters = await this.pyServerAPI\r\n .getVolumeCalibrationParameters({\r\n inDBValues: inDBValues,\r\n outDBSPLValues: outDBSPL1000Values,\r\n lCalib: lCalib,\r\n componentGainDBSPL,\r\n })\r\n .then(res => {\r\n this.incrementStatusBar();\r\n return res;\r\n });\r\n if (this.isCalibrating) return null;\r\n const result = {\r\n parameters: parameters,\r\n inDBValues: inDBValues,\r\n outDBSPLValues: outDBSPLValues,\r\n outDBSPL1000Values: outDBSPL1000Values,\r\n thdValues: thdValues,\r\n };\r\n\r\n return result;\r\n };\r\n\r\n writeFrqGainToFirestore = async (speakerID, frq, gain, OEM, documentID) => {\r\n // freq and gain are too large to take samples 1 in every 100 samples\r\n // const sampledFrq = [];\r\n // const sampledGain = [];\r\n // for (let i = 0; i < frq.length; i += 100) {\r\n // sampledFrq.push(frq[i]);\r\n // sampledGain.push(gain[i]);\r\n // }\r\n\r\n const data = {Freq: frq, Gain: gain};\r\n\r\n const docRef = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.doc)(_config_firebase__WEBPACK_IMPORTED_MODULE_3__[\"default\"], 'Microphones', documentID);\r\n await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.updateDoc)(docRef, {\r\n linear: data,\r\n });\r\n\r\n // divide frq and gain into smaller chunks and write to firestore one chunk at a time\r\n // use arrayUnion to append to the array\r\n // const chunkSize = 600;\r\n // const chunkedFrq = [];\r\n // const chunkedGain = [];\r\n // for (let i = 0; i < frq.length; i += chunkSize) {\r\n // chunkedFrq.push(frq.slice(i, i + chunkSize));\r\n // chunkedGain.push(gain.slice(i, i + chunkSize));\r\n // }\r\n // const docRef = doc(database, 'Microphones', documentID);\r\n // for (let i = 0; i < chunkedFrq.length; i++) {\r\n // await updateDoc(docRef, {\r\n // linear: {\r\n // Freq: arrayUnion(...chunkedFrq[i]),\r\n // Gain: arrayUnion(...chunkedGain[i]),\r\n // },\r\n // });\r\n // }\r\n };\r\n // function to write frq and gain to firebase database given speakerID\r\n writeFrqGain = async (speakerID, frq, gain, OEM) => {\r\n // freq and gain are too large to take samples 1 in every 100 samples\r\n\r\n const sampledFrq = [];\r\n const sampledGain = [];\r\n for (let i = 0; i < frq.length; i += 100) {\r\n sampledFrq.push(frq[i]);\r\n sampledGain.push(gain[i]);\r\n }\r\n\r\n const data = {Freq: sampledFrq, Gain: sampledGain};\r\n\r\n await (0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.set)((0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_3__[\"default\"], `Microphone2/${OEM}/${speakerID}/linear`), data);\r\n };\r\n\r\n // Function to Read frq and gain from firebase database given speakerID\r\n // returns an array of frq and gain if speakerID exists, returns null otherwise\r\n readFrqGainFromFirestore = async (speakerID, OEM, isDefault) => {\r\n const collectionRef = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.collection)(_config_firebase__WEBPACK_IMPORTED_MODULE_3__[\"default\"], 'Microphones');\r\n const q = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.query)(\r\n collectionRef,\r\n (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.where)('ID', '==', speakerID),\r\n (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.where)('lowercaseOEM', '==', OEM),\r\n (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.where)('isDefault', '==', isDefault)\r\n );\r\n const querySnapshot = await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.getDocs)(q);\r\n // if exists return the linear field of the first document\r\n if (querySnapshot.size > 0) {\r\n const timestamp = new firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.Timestamp(\r\n querySnapshot.docs[0].data().createDate.seconds,\r\n querySnapshot.docs[0].data().createDate.nanoseconds\r\n );\r\n return {\r\n ir: querySnapshot.docs[0].data().linear,\r\n createDate: timestamp.toDate(),\r\n jsonFileName: querySnapshot.docs[0].data().jsonFileName,\r\n };\r\n }\r\n return null;\r\n };\r\n readFrqGain = async (speakerID, OEM) => {\r\n const dbRef = (0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_3__[\"default\"]);\r\n const snapshot = await (0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.get)((0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.child)(dbRef, `Microphone2/${OEM}/${speakerID}/linear`));\r\n if (snapshot.exists()) {\r\n return snapshot.val();\r\n }\r\n return null;\r\n };\r\n readGainat1000HzFromFirestore = async (speakerID, OEM, isDefault) => {\r\n const collectionRef = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.collection)(_config_firebase__WEBPACK_IMPORTED_MODULE_3__[\"default\"], 'Microphones');\r\n const q = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.query)(\r\n collectionRef,\r\n (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.where)('ID', '==', speakerID),\r\n (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.where)('lowercaseOEM', '==', OEM),\r\n (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.where)('isDefault', '==', isDefault)\r\n );\r\n const querySnapshot = await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.getDocs)(q);\r\n // if exists return the Gain1000 field of the first document\r\n if (querySnapshot.size > 0) {\r\n return querySnapshot.docs[0].data().Gain1000;\r\n }\r\n return null;\r\n };\r\n\r\n readGainat1000Hz = async (speakerID, OEM) => {\r\n const dbRef = (0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_3__[\"default\"]);\r\n const snapshot = await (0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.get)((0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.child)(dbRef, `Microphone2/${OEM}/${speakerID}/Gain1000`));\r\n if (snapshot.exists()) {\r\n return snapshot.val();\r\n }\r\n return null;\r\n };\r\n\r\n writeGainat1000HzToFirestore = async (speakerID, gain, OEM, documentID) => {\r\n const docRef = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.doc)(_config_firebase__WEBPACK_IMPORTED_MODULE_3__[\"default\"], 'Microphones', documentID);\r\n await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.updateDoc)(docRef, {\r\n Gain1000: gain,\r\n });\r\n };\r\n\r\n writeGainat1000Hz = async (speakerID, gain, OEM) => {\r\n await (0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.set)((0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_3__[\"default\"], `Microphone2/${OEM}/${speakerID}/Gain1000`), gain);\r\n };\r\n\r\n writeIsSmartPhoneToFirestore = async (speakerID, isSmartPhone, OEM) => {\r\n const collectionRef = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.collection)(_config_firebase__WEBPACK_IMPORTED_MODULE_3__[\"default\"], 'Microphones');\r\n const q = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.query)(\r\n collectionRef,\r\n (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.where)('ID', '==', speakerID),\r\n (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.where)('lowercaseOEM', '==', OEM),\r\n (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.where)('isDefault', '==', true)\r\n );\r\n const querySnapshot = await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.getDocs)(q);\r\n if (querySnapshot.size > 0) {\r\n const docRef = await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.addDoc)(collectionRef, {isSmartPhone: isSmartPhone, isDefault: false});\r\n return docRef.id;\r\n } else {\r\n const docRef = await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.addDoc)(collectionRef, {isSmartPhone: isSmartPhone, isDefault: true});\r\n return docRef.id;\r\n }\r\n };\r\n\r\n writeIsSmartPhone = async (speakerID, isSmartPhone, OEM) => {\r\n const data = {isSmartPhone: isSmartPhone};\r\n await (0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.set)((0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_3__[\"default\"], `Microphone2/${OEM}/${speakerID}/isSmartPhone`), isSmartPhone);\r\n };\r\n\r\n writeMicrophoneInfoToFirestore = async (speakerID, micInfo, OEM, documentID) => {\r\n const docRef = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.doc)(_config_firebase__WEBPACK_IMPORTED_MODULE_3__[\"default\"], 'Microphones', documentID);\r\n await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.setDoc)(docRef, micInfo, {merge: true});\r\n };\r\n\r\n doesMicrophoneExistInFirestore = async (speakerID, OEM, documentID) => {\r\n const docRef = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.doc)(_config_firebase__WEBPACK_IMPORTED_MODULE_3__[\"default\"], 'Microphone', OEM, speakerID, documentID);\r\n const docSnap = await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_5__.getDoc)(docRef);\r\n if (docSnap.exists()) {\r\n return true;\r\n }\r\n return false;\r\n };\r\n\r\n doesMicrophoneExist = async (speakerID, OEM) => {\r\n const dbRef = (0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_3__[\"default\"]);\r\n const snapshot = await (0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.get)((0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.child)(dbRef, `Microphone2/${OEM}/${speakerID}`));\r\n if (snapshot.exists()) {\r\n return true;\r\n }\r\n return false;\r\n };\r\n\r\n addMicrophoneInfo = async (speakerID, OEM, micInfo) => {\r\n // add to database if /info does not exist\r\n const dbRef = (0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_3__[\"default\"]);\r\n const snapshot = await (0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.get)((0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.child)(dbRef, `Microphone2/${OEM}/${speakerID}/info`));\r\n if (!snapshot.exists()) {\r\n await (0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.set)((0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_3__[\"default\"], `Microphone2/${OEM}/${speakerID}/info`), micInfo);\r\n }\r\n };\r\n\r\n convertToDB = gain => {\r\n return Math.log10(gain) * 20;\r\n };\r\n\r\n // Function to perform linear interpolation between two points\r\n interpolate(x, x0, y0, x1, y1) {\r\n return y0 + ((x - x0) * (y1 - y0)) / (x1 - x0);\r\n }\r\n\r\n findGainatFrequency = (frequencies, gains, targetFrequency) => {\r\n // Find the index of the first frequency in the array greater than the target frequency\r\n let index = 0;\r\n while (index < frequencies.length && frequencies[index] < targetFrequency) {\r\n index++;\r\n }\r\n\r\n // Handle cases when the target frequency is outside the range of the given data\r\n if (index === 0) {\r\n return gains[0];\r\n } else if (index === frequencies.length) {\r\n return gains[gains.length - 1];\r\n } else {\r\n // Interpolate the gain based on the surrounding frequencies\r\n const x0 = frequencies[index - 1];\r\n const y0 = gains[index - 1];\r\n const x1 = frequencies[index];\r\n const y1 = gains[index];\r\n return this.interpolate(targetFrequency, x0, y0, x1, y1);\r\n }\r\n };\r\n\r\n checkPowerVariation = async () => {\r\n let recordings = this.getAllFilteredRecordedSignals();\r\n // remove filteredMLSAttenuation from the recordings\r\n\r\n // recordings = recordings.map(recording => {\r\n // if (this.soundCheck == 'component') {\r\n // return recording.map(value => value / this.filteredMLSAttenuation.component);\r\n // }\r\n // return recording.map(value => value / this.filteredMLSAttenuation.system);\r\n // });\r\n\r\n const rec = recordings[recordings.length - 1];\r\n\r\n await this.pyServerAPI\r\n .allHzPowerCheck({\r\n payload: rec,\r\n sampleRate: this.sourceSamplingRate || 96000,\r\n binDesiredSec: this._calibrateSoundPowerBinDesiredSec,\r\n burstSec: this.desired_time_per_mls,\r\n repeats: this.numMLSPerCapture - this.num_mls_to_skip ,\r\n warmUp: this.num_mls_to_skip \r\n })\r\n .then(result => {\r\n if (result) {\r\n if (result['sd'] > this._calibrateSoundBurstMaxSD_dB && this.numSuccessfulCaptured == 0) {\r\n console.log('filtered recording sd too high');\r\n this.recordingChecks['warnings'].push(`All Hz. Re-recorded ${this.inDB} because SD ${result['sd']} > ${this._calibrateSoundBurstMaxSD_dB} dB`);\r\n this.status = this.generateTemplate(`All Hz: Re-recording at ${this.inDB} dB because SD ${result['sd']} > ${this._calibrateSoundBurstMaxSD_dB} dB`.toString()).toString();\r\n this.emit('update', {\r\n message: this.status,\r\n });\r\n // numSuccessfulCaptured no longer to count number of successful capture but count attemps\r\n // is sd below _calibrateSoundBurstMaxSD_dB then count two attemps\r\n // else count one attemp\r\n this.numSuccessfulCaptured += 1;\r\n } else {\r\n this.recordingChecks[this.soundCheck].push(result);\r\n // Now we do at most 2 attempts if sd > _calibrateSoundBurstMaxSD_dB\r\n // Second attempt is the final\r\n if (this.numSuccessfulCaptured < 2) {\r\n this.numSuccessfulCaptured += 2;\r\n this.stepNum += 1;\r\n this.incrementStatusBar();\r\n console.log(\r\n 'after mls w iir record for some reason add numSucc capt ' + this.stepNum\r\n );\r\n this.status = this.generateTemplate(`All Hz Calibration: ${this.numSuccessfulCaptured} recording of convolved MLS captured`.toString()).toString();\r\n this.emit('update', {\r\n message: this.status,\r\n });\r\n }\r\n }\r\n }\r\n });\r\n };\r\n\r\n getGainDBSPL = () => {\r\n var freqIndex = this.componentIR.Freq.indexOf(1000);\r\n\r\n // If freqIndex is not -1 (meaning 1000 is found in the freq array)\r\n if (freqIndex !== -1) {\r\n // Get the corresponding gain value using the index\r\n var gainValue = this.componentIR.Gain[freqIndex];\r\n return gainValue;\r\n } else {\r\n console.log('Freq 1000 not found in the array.');\r\n return null;\r\n }\r\n };\r\n // Example of how to use the writeFrqGain and readFrqGain functions\r\n // writeFrqGain('speaker1', [1, 2, 3], [4, 5, 6]);\r\n // Speaker1 is the speakerID you want to write to in the database\r\n // readFrqGain('MiniDSPUMIK_1').then(data => console.log(data));\r\n // MiniDSPUMIK_1 is the speakerID with some Data in the database\r\n //adding gainDBSPL\r\n startCalibration = async (\r\n stream,\r\n gainValues,\r\n lCalib = 104.92978421490648,\r\n componentIR = null,\r\n microphoneName = 'MiniDSP-UMIK1-711-4754-vertical',\r\n _calibrateSoundCheck = 'goal', //GOAL PASSed in by default\r\n isSmartPhone = false,\r\n _calibrateSoundBurstDb = -18,\r\n _calibrateSoundBurstFilteredExtraDb = 6,\r\n _calibrateSoundBurstLevelReTBool = false,\r\n _calibrateSoundBurstUses1000HzGainBool = false,\r\n _calibrateSoundBurstRepeats = 3,\r\n _calibrateSoundBurstSec = 1,\r\n _calibrateSoundBurstPreSec = 1,\r\n _calibrateSoundBurstPostSec = 1,\r\n _calibrateSoundHz = 48000,\r\n _calibrateSoundIRSec = 0.2,\r\n _calibrateSoundIIRSec = 0.2,\r\n _calibrateSoundIIRPhase = 'linear',\r\n calibrateSound1000HzPreSec = 0.5,\r\n calibrateSound1000HzSec = 0.5,\r\n calibrateSound1000HzPostSec = 0.5,\r\n _calibrateSoundBackgroundSecs = 0,\r\n _calibrateSoundSmoothOctaves = 0.33,\r\n _calibrateSoundSmoothMinBandwidthHz = 200,\r\n _calibrateSoundPowerBinDesiredSec = 0.2,\r\n _calibrateSoundPowerDbSDToleratedDb = 1,\r\n _calibrateSoundTaperSec = 0.01,\r\n micManufacturer = '',\r\n micSerialNumber = '',\r\n micModelNumber = '',\r\n micModelName = '',\r\n calibrateMicrophonesBool,\r\n authorEmails,\r\n webAudioDeviceNames = {\r\n loudspeaker: 'loudspeaker',\r\n microphone: 'microphone',\r\n microphoneText: 'xxx XXX',\r\n },\r\n userIDs,\r\n restartButton,\r\n reminder,\r\n calibrateSoundLimit,\r\n _calibrateSoundBurstNormalizeBy1000HzGainBool = false,\r\n _calibrateSoundBurstScalarDB = 71,\r\n calibrateSound1000HzMaxSD_dB = 4,\r\n _calibrateSoundBurstMaxSD_dB = 4,\r\n calibrateSoundSamplingDesiredBits = 24,\r\n language,\r\n loudspeakerModelName='',\r\n phrases,\r\n\r\n ) => {\r\n this._calibrateSoundBurstPreSec = _calibrateSoundBurstPreSec;\r\n this._calibrateSoundBurstRepeats = _calibrateSoundBurstRepeats;\r\n this._calibrateSoundBurstSec = _calibrateSoundBurstSec;\r\n this.micModelName = micModelName;\r\n this.loudspeakerModelName = loudspeakerModelName;\r\n this.language = language;\r\n this.TAPER_SECS = _calibrateSoundTaperSec;\r\n this.calibrateSoundLimit = calibrateSoundLimit;\r\n this._calibrateSoundBurstDb = _calibrateSoundBurstDb;\r\n this._calibrateSoundBurstFilteredExtraDb = _calibrateSoundBurstFilteredExtraDb;\r\n this._calibrateSoundBurstLevelReTBool = _calibrateSoundBurstLevelReTBool;\r\n this.CALIBRATION_TONE_DURATION =\r\n calibrateSound1000HzPreSec + calibrateSound1000HzSec + calibrateSound1000HzPostSec;\r\n this.calibrateSound1000HzPreSec = calibrateSound1000HzPreSec;\r\n this.calibrateSound1000HzSec = calibrateSound1000HzSec;\r\n this.calibrateSound1000HzPostSec = calibrateSound1000HzPostSec;\r\n this.iirLength = Math.floor(_calibrateSoundIIRSec * this.sourceSamplingRate);\r\n this.irLength = Math.floor(_calibrateSoundIRSec * this.sourceSamplingRate);\r\n this.calibrateSoundIIRPhase = _calibrateSoundIIRPhase;\r\n this.num_mls_to_skip = Math.ceil(_calibrateSoundBurstPreSec / _calibrateSoundBurstSec);\r\n this._calibrateSoundBurstPostSec = _calibrateSoundBurstPostSec;\r\n this.numMLSPerCapture = _calibrateSoundBurstRepeats + this.num_mls_to_skip;\r\n this.desired_time_per_mls = _calibrateSoundBurstSec;\r\n this.desired_sampling_rate = _calibrateSoundHz;\r\n this._calibrateSoundBackgroundSecs = _calibrateSoundBackgroundSecs;\r\n this._calibrateSoundSmoothOctaves = _calibrateSoundSmoothOctaves;\r\n this._calibrateSoundSmoothMinBandwidthHz = _calibrateSoundSmoothMinBandwidthHz;\r\n this._calibrateSoundPowerBinDesiredSec = _calibrateSoundPowerBinDesiredSec;\r\n this._calibrateSoundBurstUses1000HzGainBool = _calibrateSoundBurstUses1000HzGainBool;\r\n this._calibrateSoundPowerDbSDToleratedDb = _calibrateSoundPowerDbSDToleratedDb;\r\n this._calibrateSoundBurstNormalizeBy1000HzGainBool =\r\n _calibrateSoundBurstNormalizeBy1000HzGainBool;\r\n this._calibrateSoundBurstScalarDB = _calibrateSoundBurstScalarDB;\r\n this.webAudioDeviceNames = webAudioDeviceNames;\r\n this.calibrateSoundSamplingDesiredBits = calibrateSoundSamplingDesiredBits;\r\n this.phrases = phrases;\r\n if (isSmartPhone) {\r\n const leftQuote = \"\\u201C\"; // “\r\n const rightQuote = \"\\u201D\"; // ”\r\n this.webAudioDeviceNames.microphone = this.deviceInfo.microphoneFromAPI;\r\n const quotedWebAudioMic = leftQuote + this.webAudioDeviceNames.microphone + rightQuote;\r\n const combinedMicText = this.micModelName + \" \" + quotedWebAudioMic;\r\n webAudioDeviceNames.microphoneText = this.phrases.RC_nameMicrophone[this.language]\r\n .replace(\"“xxx”\", combinedMicText)\r\n .replace(\"“XXX”\", combinedMicText);\r\n }\r\n // this.webAudioDeviceNames.microphoneText = this.webAudioDeviceNames.microphoneText\r\n // .replace('xxx', this.webAudioDeviceNames.microphone)\r\n // .replace('XXX', this.webAudioDeviceNames.microphone);\r\n //feed calibration goal here\r\n this._calibrateSoundCheck = _calibrateSoundCheck;\r\n this.calibrateSound1000HzMaxSD_dB = calibrateSound1000HzMaxSD_dB;\r\n this._calibrateSoundBurstMaxSD_dB = _calibrateSoundBurstMaxSD_dB;\r\n //check if a componentIR was given to the system, if it isn't check for the microphone. using dummy data here bc we need to\r\n //check the db based on the microphone currently connected\r\n\r\n //new lCalib found at top of calibration files *1000hz, make sure to correct\r\n //based on zeroing of 1000hz, search for \"*1000Hz\"\r\n const ID = isSmartPhone ? micModelNumber : micSerialNumber;\r\n const OEM = isSmartPhone\r\n ? micModelName === 'UMIK-1' || micModelName === 'UMIK-2'\r\n ? 'minidsp'\r\n : this.deviceInfo.OEM.toLowerCase().split(' ').join('')\r\n : micManufacturer.toLowerCase().split(' ').join('');\r\n // const ID = \"712-5669\";\r\n // const OEM = \"minidsp\";\r\n const micInfo = {\r\n micModelName: isSmartPhone ? micModelName : microphoneName,\r\n OEM: isSmartPhone\r\n ? micModelName === 'UMIK-1' || micModelName === 'UMIK-2'\r\n ? 'miniDSP'\r\n : this.deviceInfo.OEM\r\n : micManufacturer,\r\n ID: ID,\r\n createDate: new Date(),\r\n DateText: (0,_utils__WEBPACK_IMPORTED_MODULE_1__.getCurrentTimeString)(),\r\n HardwareName: isSmartPhone ? this.deviceInfo.hardwarename : microphoneName,\r\n hardwareFamily: isSmartPhone ? this.deviceInfo.hardwarefamily : microphoneName,\r\n HardwareModel: isSmartPhone ? this.deviceInfo.hardwaremodel : microphoneName,\r\n PlatformName: isSmartPhone ? this.deviceInfo.platformname : 'N/A',\r\n PlatformVersion: isSmartPhone ? this.deviceInfo.platformversion : 'N/A',\r\n DeviceType: isSmartPhone ? this.deviceInfo.devicetype : 'N/A',\r\n ID_from_51Degrees: isSmartPhone ? this.deviceInfo.DeviceId : 'N/A',\r\n calibrateMicrophonesBool: calibrateMicrophonesBool,\r\n screenHeight: this.deviceInfo.screenHeight,\r\n screenWidth: this.deviceInfo.screenWidth,\r\n webAudioDeviceNames: {\r\n loudspeaker: this.webAudioDeviceNames.loudspeaker,\r\n microphone: this.webAudioDeviceNames.microphone,\r\n },\r\n userIDs: userIDs,\r\n lowercaseOEM: OEM.toLowerCase().split(' ').join(''),\r\n };\r\n if (calibrateMicrophonesBool) {\r\n micInfo['authorEmails'] = authorEmails;\r\n }\r\n // if undefined in micInfo, set to empty string\r\n for (const [key, value] of Object.entries(micInfo)) {\r\n if (value === undefined) {\r\n micInfo[key] = '';\r\n }\r\n }\r\n\r\n // this.writeMicrophoneInfoToFirestore(ID, micInfo, OEM, 'default');\r\n // this.addMicrophoneInfo(ID, OEM, micInfo);\r\n if (componentIR == null) {\r\n //mode 'ir'\r\n //global variable this.componentIR must be set\r\n await this.readFrqGainFromFirestore(ID, OEM, true).then(data => {\r\n if (data !== null) {\r\n this.componentIR = data.ir;\r\n micInfo['parentTimestamp'] = data.createDate ? data.createDate : new Date();\r\n micInfo['parentFilenameJSON'] = data.jsonFileName ? data.jsonFileName : '';\r\n }\r\n });\r\n\r\n // await this.readFrqGain(ID, OEM).then(data => {\r\n // return data;\r\n // });\r\n\r\n // lCalib = await this.readGainat1000Hz(ID, OEM);\r\n lCalib = await this.readGainat1000HzFromFirestore(ID, OEM, true);\r\n micInfo['gainDBSPL'] = lCalib;\r\n // this.componentGainDBSPL = this.convertToDB(lCalib);\r\n this.componentGainDBSPL = lCalib;\r\n //TODO: if this call to database is unknown, cannot perform experiment => return false\r\n if (this.componentIR == null) {\r\n this.status =\r\n `Microphone (${OEM},${ID}) is not found in the database. Please add it to the database.`.toString();\r\n this.emit('update', {message: this.status});\r\n return false;\r\n }\r\n } else {\r\n this.transducerType = 'Microphone';\r\n this.componentIR = componentIR;\r\n lCalib = this.findGainatFrequency(this.componentIR.Freq, this.componentIR.Gain, 1000);\r\n // this.componentGainDBSPL = this.convertToDB(lCalib);\r\n this.componentGainDBSPL = lCalib;\r\n // await this.writeIsSmartPhone(ID, isSmartPhone, OEM);\r\n }\r\n\r\n this.oldComponentIR = JSON.parse(JSON.stringify(this.componentIR));\r\n\r\n return await new Promise(async (resolve, reject) => {\r\n // add event listner to params.restartButton to resolve the promise with a string: 'restart'\r\n\r\n if (reminder) {\r\n reminder.style.display = '';\r\n }\r\n if (restartButton) {\r\n restartButton.style.display = '';\r\n restartButton.addEventListener('click', () => {\r\n this.stopCalibrationAudio();\r\n this.isCalibrating = true;\r\n restartButton.style.display = 'none';\r\n if (reminder) {\r\n reminder.style.display = 'none';\r\n }\r\n this.emit('update', {message: 'Restarting calibration...'});\r\n resolve('restart');\r\n });\r\n }\r\n await this.pyServerAPI.checkMemory();\r\n // calibrate volume\r\n\r\n let volumeResults = await this.startCalibrationVolume(\r\n stream,\r\n gainValues,\r\n lCalib,\r\n this.componentGainDBSPL\r\n );\r\n if (!volumeResults) return;\r\n this.T = volumeResults['parameters']['T'];\r\n this.gainDBSPL = volumeResults['parameters']['gainDBSPL'];\r\n\r\n // end calibrate volume\r\n\r\n let impulseResponseResults = await this.startCalibrationImpulseResponse(stream);\r\n if (!impulseResponseResults) return;\r\n impulseResponseResults['background_noise'] = this.background_noise;\r\n impulseResponseResults['system']['background_noise'] = this.background_noise;\r\n impulseResponseResults['component']['background_noise'] = this.background_noise;\r\n\r\n //attenuate system background noise\r\n if (this.systemAttenuatorGainDB != 0) {\r\n let linearScaleAttenuation = Math.pow(10, this.systemAttenuatorGainDB / 20);\r\n let linearScalePowerAttenuation = Math.pow(10, this.systemAttenuatorGainDB / 10);\r\n impulseResponseResults['system']['background_noise']['recording'] = impulseResponseResults[\r\n 'background_noise'\r\n ]['recording'].map(value => value / linearScaleAttenuation);\r\n impulseResponseResults['system']['background_noise']['x_background'] =\r\n impulseResponseResults['background_noise']['x_background'];\r\n impulseResponseResults['system']['background_noise']['y_background'] =\r\n impulseResponseResults['background_noise']['y_background'].map(\r\n value => value / linearScalePowerAttenuation\r\n );\r\n }\r\n //attenuate component background noise\r\n if (this.componentAttentuatorGainDB != 0) {\r\n let linearScaleAttenuation = Math.pow(10, this.componentAttenuatorGainDB / 20);\r\n let linearScalePowerAttenuation = Math.pow(10, this.componentAttenuatorGainDB / 10);\r\n impulseResponseResults['component']['background_noise']['recording'] =\r\n impulseResponseResults['background_noise']['recording'].map(\r\n value => value / linearScaleAttenuation\r\n );\r\n impulseResponseResults['component']['background_noise']['x_background'] =\r\n impulseResponseResults['background_noise']['x_background'];\r\n impulseResponseResults['component']['background_noise']['y_background'] =\r\n impulseResponseResults['background_noise']['y_background'].map(\r\n value => value / linearScalePowerAttenuation\r\n );\r\n }\r\n impulseResponseResults['system']['attenuatorGainDB'] = this.systemAttenuatorGainDB;\r\n impulseResponseResults['component']['attenuatorGainDB'] = this.componentAttenuatorGainDB;\r\n impulseResponseResults['system']['fMaxHz'] = this.systemFMaxHz;\r\n impulseResponseResults['component']['fMaxHz'] = this.componentFMaxHz;\r\n impulseResponseResults['L_new_n'] = this.L_new_n;\r\n impulseResponseResults['fs2'] = this.fs2;\r\n\r\n if (componentIR != null) {\r\n // I corrected microphone/loudpeaker IR scale in easyeyes,\r\n // but since we write microphone IR to firestore here\r\n // we need to correct microphone IR here\r\n let correctGain =\r\n Math.round((volumeResults.parameters.gainDBSPL - this.componentGainDBSPL) * 10) / 10;\r\n\r\n let IrFreq = impulseResponseResults?.component.ir.Freq.map(freq => Math.round(freq));\r\n let IrGain = impulseResponseResults?.component?.ir.Gain;\r\n const IrGainAt1000Hz = IrGain[IrFreq.findIndex(freq => freq === 1000)];\r\n const difference = Math.round(10 * (IrGainAt1000Hz - correctGain)) / 10;\r\n IrGain = IrGain.map(gain => gain - difference);\r\n micInfo['mls'] = Number(this.SDofFilteredRange['mls']);\r\n micInfo['systemCorrectionSD'] = Number(this.SDofFilteredRange['system']);\r\n micInfo['componentCorrectionSD'] = Number(this.SDofFilteredRange['component']);\r\n console.log(typeof micInfo['componentCorrectionSD']);\r\n // const id = await this.writeIsSmartPhoneToFirestore(ID, isSmartPhone, OEM);\r\n // await this.writeMicrophoneInfoToFirestore(ID, micInfo, OEM, id);\r\n // await this.writeFrqGainToFirestore(ID, IrFreq, IrGain, OEM, id);\r\n // micInfo['gainDBSPL'] = impulseResponseResults.component.gainDBSPL;\r\n // await this.writeGainat1000HzToFirestore(ID, micInfo['gainDBSPL'], OEM, id);\r\n // await this.writeGainat1000Hz(ID, micInfo['gainDBSPL'], OEM);\r\n }\r\n const total_results = {...volumeResults, ...impulseResponseResults};\r\n total_results['filteredMLSRange'] = this.filteredMLSRange;\r\n total_results['filteredMLSAttenuation'] = this.filteredMLSAttenuation;\r\n total_results['micInfo'] = micInfo;\r\n total_results['audioInfo'] = {};\r\n total_results['audioInfo']['sinkSampleRate'] = this.sinkSamplingRate;\r\n total_results['audioInfo']['sourceSampleRate'] = this.sourceSamplingRate;\r\n total_results['audioInfo']['bitsPerSample'] = this.sampleSize;\r\n const timeStampresult = [...this.timeStamp].join('\\n');\r\n total_results['timeStamps'] = timeStampresult;\r\n total_results['recordingChecks'] = this.recordingChecks;\r\n total_results['waveforms'] = this.waveforms;\r\n total_results['component']['phase'] = this.componentIRPhase;\r\n total_results['system']['phase'] = this.systemIRPhase;\r\n total_results['qualityMetrics'] = this.SDofFilteredRange;\r\n total_results['flags'] = this.flags;\r\n console.log('total results');\r\n console.log(total_results);\r\n console.log('Time Stamps');\r\n console.log(timeStampresult);\r\n\r\n resolve(total_results);\r\n });\r\n };\r\n}\r\n\r\n/* harmony default export */ __webpack_exports__[\"default\"] = (Combination);\n\n//# sourceURL=webpack://speakerCalibrator/./src/tasks/combination/combination.js?");
|
|
516
516
|
|
|
517
517
|
/***/ }),
|
|
518
518
|
|
|
@@ -523,7 +523,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _aud
|
|
|
523
523
|
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
524
524
|
|
|
525
525
|
"use strict";
|
|
526
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _audioCalibrator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../audioCalibrator */ \"./src/tasks/audioCalibrator.js\");\n/* harmony import */ var _mlsGen_mlsGenInterface__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./mlsGen/mlsGenInterface */ \"./src/tasks/impulse-response/mlsGen/mlsGenInterface.js\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../utils */ \"./src/utils.js\");\n/* harmony import */ var _config_firebase__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../config/firebase */ \"./src/config/firebase.js\");\n/* harmony import */ var firebase_database__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! firebase/database */ \"./node_modules/firebase/database/dist/esm/index.esm.js\");\n\n\n\n\n\n\n\n/**\n *\n */\nclass ImpulseResponse extends _audioCalibrator__WEBPACK_IMPORTED_MODULE_0__[\"default\"] {\n /**\n * Default constructor. Creates an instance with any number of paramters passed or the default parameters defined here.\n *\n * @param {Object<boolean, number, number, number>} calibratorParams - paramter object\n * @param {boolean} [calibratorParams.download = false] - boolean flag to download captures\n * @param {number} [calibratorParams.mlsOrder = 18] - order of the MLS to be generated\n * @param {number} [calibratorParams.numCaptures = 5] - number of captures to perform\n * @param {number} [calibratorParams.numMLSPerCapture = 4] - number of bursts of MLS per capture\n */\n constructor({\n download = false,\n mlsOrder = 18,\n numCaptures = 3,\n numMLSPerCapture = 4,\n lowHz = 20,\n highHz = 10000,\n loudSpeakerIr = null,\n }) {\n super(numCaptures, numMLSPerCapture);\n this.#mlsOrder = parseInt(mlsOrder, 10);\n this.#P = 2 ** mlsOrder - 1;\n this.#download = download;\n this.#mls = [];\n this.#lowHz = lowHz;\n this.#highHz = highHz;\n }\n\n /** @private */\n stepNum = 0;\n\n /** @private */\n totalSteps = 25;\n\n /** @private */\n #download;\n\n /** @private */\n #mlsGenInterface;\n\n /** @private */\n #mlsBufferView;\n\n /** @private */\n invertedImpulseResponse = null;\n\n /** @private */\n impulseResponses = [];\n\n /** @private */\n #mlsOrder;\n\n /** @private */\n #lowHz;\n\n /** @private */\n #highHz;\n\n /** @private */\n #mls;\n\n /** @private */\n #P;\n\n /** @private */\n #audioContext;\n\n /** @private */\n TAPER_SECS = 5;\n\n /** @private */\n offsetGainNode;\n\n /** @private */\n convolution;\n\n /** @private */\n status_denominator = 6;\n\n /** @private */\n status_numerator = 0;\n\n /** @private */\n percent_complete = 0;\n\n /** @private */\n status = ``;\n\n /**generate string template that gets reevaluated as variable increases */\n generateTemplate = () => {\n if (this.percent_complete > 100) {\n this.percent_complete = 100;\n }\n const template = `<div style=\"display: flex; justify-content: center;\"><div style=\"width: 200px; height: 20px; border: 2px solid #000; border-radius: 10px;\"><div style=\"width: ${this.percent_complete}%; height: 100%; background-color: #00aaff; border-radius: 8px;\"></div></div></div>`;\n return template;\n };\n\n /** increment numerator and percent for status bar */\n incrementStatusBar = () => {\n this.status_numerator += 1;\n this.percent_complete = (this.status_numerator / this.status_denominator) * 100;\n };\n\n /** .\n * .\n * .\n * Sends all the computed impulse responses to the backend server for processing\n *\n * @returns sets the resulting inverted impulse response to the class property\n * @example\n */\n sendImpulseResponsesToServerForProcessing = async () => {\n const computedIRs = await Promise.all(this.impulseResponses);\n const filteredComputedIRs = computedIRs.filter(element => {\n return element != undefined;\n });\n const mls = this.#mls;\n const lowHz = this.#lowHz;\n const highHz = this.#highHz;\n this.stepNum += 1;\n this.status = `computing the IIR...`.toString() + this.generateTemplate().toString();\n this.emit('update', {message: this.status});\n return this.pyServerAPI\n .getInverseImpulseResponseWithRetry({\n payload: filteredComputedIRs.slice(0, this.numCaptures),\n mls,\n lowHz,\n highHz,\n })\n .then(res => {\n console.log(res);\n this.stepNum += 1;\n this.incrementStatusBar();\n this.status = `done computing the IIR...`.toString() + this.generateTemplate().toString();\n this.emit('update', {message: this.status});\n this.invertedImpulseResponse = res['iir'];\n this.convolution = res['convolution'];\n })\n .catch(err => {\n // this.emit('InvertedImpulseResponse', {res: false});\n console.error(err);\n });\n };\n\n /** .\n * .\n * .\n * Sends the recorded signal, or a given csv string of a signal, to the back end server for processing\n *\n * @param {<array>String} signalCsv - Optional csv string of a previously recorded signal, if given, this signal will be processed\n * @example\n */\n sendRecordingToServerForProcessing = signalCsv => {\n const allSignals = this.getAllRecordedSignals();\n const numSignals = allSignals.length;\n const mls = this.#mls;\n const payload =\n signalCsv && signalCsv.length > 0 ? (0,_utils__WEBPACK_IMPORTED_MODULE_2__.csvToArray)(signalCsv) : allSignals[numSignals - 1];\n console.log('sending rec');\n this.stepNum += 1;\n this.status =\n `computing the IR of the last recording...`.toString() + this.generateTemplate().toString();\n this.emit('update', {message: this.status});\n this.impulseResponses.push(\n this.pyServerAPI\n .getImpulseResponse({\n sampleRate: this.sourceSamplingRate || 96000,\n payload,\n mls,\n P: this.#P,\n })\n .then(res => {\n if (this.numSuccessfulCaptured < this.numCaptures) {\n this.numSuccessfulCaptured += 1;\n console.log('num succ capt: ' + this.numSuccessfulCaptured);\n this.stepNum += 1;\n this.incrementStatusBar();\n this.status =\n `${this.numSuccessfulCaptured}/${this.numCaptures} IRs computed...`.toString() +\n this.generateTemplate().toString();\n this.emit('update', {message: this.status});\n return res;\n }\n })\n .catch(err => {\n console.error(err);\n })\n );\n };\n\n /**\n * Passed to the calibration steps function, awaits the desired amount of seconds to capture the desired number\n * of MLS periods defined in the constructor.\n *\n * @example\n */\n #awaitDesiredMLSLength = async () => {\n // seconds per MLS = P / SR\n // await N * P / SR\n this.stepNum += 1;\n this.status =\n `sampling the calibration signal...`.toString() + this.generateTemplate().toString();\n this.emit('update', {message: this.status});\n await (0,_utils__WEBPACK_IMPORTED_MODULE_2__.sleep)((this.#P / this.sourceSamplingRate) * this.numMLSPerCapture);\n };\n\n /** .\n * .\n * .\n * Passed to the calibration steps function, awaits the onset of the signal to ensure a steady state\n *\n * @example\n */\n #awaitSignalOnset = async () => {\n this.stepNum += 1;\n this.status =\n `waiting for the signal to stabilize...`.toString() + this.generateTemplate().toString();\n this.emit('update', {message: this.status});\n await (0,_utils__WEBPACK_IMPORTED_MODULE_2__.sleep)(this.TAPER_SECS);\n };\n\n /**\n * Called immediately after a recording is captured. Used to process the resulting signal\n * whether by sending the result to a server or by computing a result locally.\n *\n * @example\n */\n #afterMLSRecord = () => {\n console.log('after record');\n this.sendRecordingToServerForProcessing();\n };\n\n #afterMLSwIIRRecord = () => {\n if (this.numSuccessfulCaptured < 1) {\n this.numSuccessfulCaptured += 1;\n this.stepNum += 1;\n this.incrementStatusBar();\n this.status =\n `${this.numSuccessfulCaptured} recording of convolved MLS captured`.toString() +\n this.generateTemplate().toString();\n this.emit('update', {message: this.status});\n }\n };\n\n /** .\n * .\n * .\n * Created an S Curver Buffer to taper the signal onset\n *\n * @param {*} length\n * @param {*} phase\n * @returns\n * @example\n */\n static createSCurveBuffer = (length, phase) => {\n const curve = new Float32Array(length);\n let i;\n for (i = 0; i < length; i += 1) {\n // scale the curve to be between 0-1\n curve[i] = Math.sin((Math.PI * i) / length - phase) / 2 + 0.5;\n }\n return curve;\n };\n\n static createInverseSCurveBuffer = (length, phase) => {\n const curve = new Float32Array(length);\n let i;\n let j = length - 1;\n for (i = 0; i < length; i += 1) {\n // scale the curve to be between 0-1\n curve[i] = Math.sin((Math.PI * j) / length - phase) / 2 + 0.5;\n j -= 1;\n }\n return curve;\n };\n\n /**\n * Construct a Calibration Node with the calibration parameters.\n *\n * @param CALIBRATION_TONE_FREQUENCY\n * @private\n * @example\n */\n #createPureTonenNode = CALIBRATION_TONE_FREQUENCY => {\n const audioContext = this.makeNewSourceAudioContext();\n const oscilator = audioContext.createOscillator();\n const gainNode = audioContext.createGain();\n\n oscilator.frequency.value = CALIBRATION_TONE_FREQUENCY;\n oscilator.type = 'sine';\n gainNode.gain.value = 0.04;\n\n oscilator.connect(gainNode);\n gainNode.connect(audioContext.destination);\n\n this.addCalibrationNode(oscilator);\n };\n\n /**\n * Construct a Calibration Node with the calibration parameters.\n *\n * @param dataBuffer\n * @private\n * @example\n */\n #createCalibrationNodeFromBuffer = dataBuffer => {\n const audioContext = this.makeNewSourceAudioContext();\n const buffer = audioContext.createBuffer(\n 1, // number of channels\n dataBuffer.length,\n audioContext.sampleRate // sample rate\n );\n\n const data = buffer.getChannelData(0); // get data\n // fill the buffer with our data\n try {\n for (let i = 0; i < dataBuffer.length; i += 1) {\n data[i] = dataBuffer[i] * 0.1;\n }\n } catch (error) {\n console.error(error);\n }\n console.log('mls second, same?');\n console.log(data);\n const onsetGainNode = audioContext.createGain();\n this.offsetGainNode = audioContext.createGain();\n const source = audioContext.createBufferSource();\n\n source.buffer = buffer;\n source.loop = true;\n source.connect(onsetGainNode);\n onsetGainNode.connect(this.offsetGainNode);\n this.offsetGainNode.connect(audioContext.destination);\n\n const onsetCurve = ImpulseResponse.createSCurveBuffer(this.sourceSamplingRate, Math.PI / 2);\n onsetGainNode.gain.setValueCurveAtTime(onsetCurve, 0, this.TAPER_SECS);\n this.addCalibrationNode(source);\n };\n\n /**\n * Given a data buffer, creates the required calibration node\n *\n * @param {*} dataBufferArray\n * @example\n */\n #setCalibrationNodesFromBuffer = (dataBufferArray = [this.#mlsBufferView]) => {\n if (dataBufferArray.length === 1) {\n this.#createCalibrationNodeFromBuffer(dataBufferArray[0]);\n } else {\n throw new Error('The length of the data buffer array must be 1');\n }\n };\n\n /**\n * function to put MLS filtered IIR data obtained from\n * python server into our audio buffer to be played aloud\n */\n #putInPythonConv = () => {\n const audioCtx = this.makeNewSourceAudioContextConvolved();\n const buffer = audioCtx.createBuffer(\n 1, // number of channels\n this.convolution.length,\n audioCtx.sampleRate // sample rate\n );\n\n const data = buffer.getChannelData(0); // get data\n // fill the buffer with our data\n try {\n for (let i = 0; i < this.convolution.length; i += 1) {\n data[i] = this.convolution[i];\n }\n } catch (error) {\n console.error(error);\n }\n\n const source = audioCtx.createBufferSource();\n\n source.buffer = buffer;\n source.loop = true;\n source.connect(audioCtx.destination);\n\n this.addCalibrationNodeConvolved(source);\n };\n\n /**\n * Creates an audio context and plays it for a few seconds.\n *\n * @private\n * @returns - Resolves when the audio is done playing.\n * @example\n */\n #playCalibrationAudio = () => {\n this.calibrationNodes[0].start(0);\n this.#mls = this.calibrationNodes[0].buffer.getChannelData(0);\n this.stepNum += 1;\n this.status = `playing the calibration tone...`.toString() + this.generateTemplate().toString();\n this.emit('update', {message: this.status});\n };\n\n #playCalibrationAudioConvolved = () => {\n this.calibrationNodesConvolved[0].start(0);\n this.stepNum += 1;\n this.status =\n `playing the convolved calibration tone...`.toString() + this.generateTemplate().toString();\n this.emit('update', {message: this.status});\n };\n\n /** .\n * .\n * .\n * Stops the audio with tapered offset\n *\n * @example\n */\n #stopCalibrationAudio = () => {\n this.offsetGainNode.gain.setValueAtTime(\n this.offsetGainNode.gain.value,\n this.sourceAudioContext.currentTime\n );\n\n this.offsetGainNode.gain.setTargetAtTime(0, this.sourceAudioContext.currentTime, 0.5);\n this.calibrationNodes[0].stop(0);\n this.sourceAudioContext.close();\n this.stepNum += 1;\n this.status =\n `stopping the calibration tone...`.toString() + this.generateTemplate().toString();\n this.emit('update', {message: this.status});\n };\n\n #stopCalibrationAudioConvolved = () => {\n this.offsetGainNode.gain.setValueAtTime(\n this.offsetGainNode.gain.value,\n this.sourceAudioContextConvolved.currentTime\n );\n\n this.offsetGainNode.gain.setTargetAtTime(0, this.sourceAudioContextConvolved.currentTime, 0.5);\n this.sourceAudioContextConvolved.close();\n this.stepNum += 1;\n this.status =\n `stopping the convolved calibration tone...`.toString() + this.generateTemplate().toString();\n this.emit('update', {message: this.status});\n };\n\n playMLSwithIIR = async (stream, iir) => {\n this.invertedImpulseResponse = iir;\n // initialize the MLSGenInterface object with it's factory method\n\n await _mlsGen_mlsGenInterface__WEBPACK_IMPORTED_MODULE_1__[\"default\"].factory(\n this.#mlsOrder,\n this.sinkSamplingRate,\n this.sourceSamplingRate\n ).then(mlsGenInterface => {\n this.#mlsGenInterface = mlsGenInterface;\n this.#mlsBufferView = this.#mlsGenInterface.getMLS();\n });\n\n // after intializating, start the calibration steps with garbage collection\n await this.#mlsGenInterface.withGarbageCollection([\n () =>\n this.calibrationSteps(\n stream,\n this.#playCalibrationAudioConvolved, // play audio func (required)\n this.#putInPythonConv, // before play func\n this.#awaitSignalOnset, // before record\n () => this.numSuccessfulCaptured < 1, // < this.numCaptures\n this.#awaitDesiredMLSLength, // during record\n this.#afterMLSwIIRRecord, // after record\n 'filtered'\n ),\n ]);\n };\n\n // function to write frq and gain to firebase database given speakerID\n writeFrqGain = async (speakerID, frq, gain) => {\n const data = {\n frq,\n gain,\n };\n await (0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.set)((0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_3__[\"default\"], `${speakerID}/linear`), data);\n };\n\n // Function to Read frq and gain from firebase database given speakerID\n // returns an array of frq and gain if speakerID exists, returns null otherwise\n\n readFrqGain = async speakerID => {\n const dbRef = (0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_3__[\"default\"]);\n const snapshot = await (0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.get)((0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.child)(dbRef, `${speakerID}/linear`));\n if (snapshot.exists()) {\n return snapshot.val();\n }\n return null;\n };\n\n // Example of how to use the writeFrqGain and readFrqGain functions\n // writeFrqGain('speaker1', [1, 2, 3], [4, 5, 6]);\n // Speaker1 is the speakerID you want to write to in the database\n // readFrqGain('MiniDSPUMIK_1').then(data => console.log(data));\n // MiniDSPUMIK_1 is the speakerID with some Data in the database\n\n /**\n * Public method to start the calibration process. Objects intialized from webassembly allocate new memory\n * and must be manually freed. This function is responsible for intializing the MlsGenInterface,\n * and wrapping the calibration steps with a garbage collection safe gaurd.\n *\n * @public\n * @param stream - The stream of audio from the Listener.\n * @example\n */\n\n startCalibration = async stream => {\n // initialize the MLSGenInterface object with it's factory method\n await _mlsGen_mlsGenInterface__WEBPACK_IMPORTED_MODULE_1__[\"default\"].factory(\n this.#mlsOrder,\n this.sinkSamplingRate,\n this.sourceSamplingRate\n ).then(mlsGenInterface => {\n this.#mlsGenInterface = mlsGenInterface;\n this.#mlsBufferView = this.#mlsGenInterface.getMLS();\n });\n\n // after intializating, start the calibration steps with garbage collection\n await this.#mlsGenInterface.withGarbageCollection([\n () =>\n this.calibrationSteps(\n stream,\n this.#playCalibrationAudio, // play audio func (required)\n this.#setCalibrationNodesFromBuffer, // before play func\n this.#awaitSignalOnset, // before record\n () => this.numSuccessfulCaptured < this.numCaptures, // loop while true\n this.#awaitDesiredMLSLength, // during record\n this.#afterMLSRecord, // after record\n 'unfiltered'\n ),\n ]);\n\n this.#stopCalibrationAudio();\n\n // at this stage we've captured all the required signals,\n // and have received IRs for each one\n // so let's send all the IRs to the server to be converted to a single IIR\n\n await this.sendImpulseResponsesToServerForProcessing();\n\n this.numSuccessfulCaptured = 0;\n // debugging function, use to test the result of the IIR\n await this.playMLSwithIIR(stream, this.invertedImpulseResponse);\n this.#stopCalibrationAudioConvolved();\n\n let recs = this.getAllRecordedSignals();\n let conv_recs = this.getAllFilteredRecordedSignals();\n let unconv_rec = recs[0];\n let conv_rec = conv_recs[0];\n\n this.status = `computing the PSD graphs...`.toString() + this.generateTemplate().toString();\n this.emit('update', {message: this.status});\n\n let results = await this.pyServerAPI\n .getPSDWithRetry({\n unconv_rec,\n conv_rec,\n })\n .then(res => {\n this.incrementStatusBar();\n this.status =\n `done computing the PSD graphs`.toString() + this.generateTemplate().toString();\n this.emit('update', {message: this.status});\n return res;\n })\n .catch(err => {\n console.error(err);\n });\n\n let iir_and_plots = {\n iir: this.invertedImpulseResponse,\n x_unconv: results['x_unconv'],\n y_unconv: results['y_unconv'],\n x_conv: results['x_conv'],\n y_conv: results['y_conv'],\n };\n\n if (this.#download) {\n this.downloadSingleUnfilteredRecording();\n this.downloadSingleFilteredRecording();\n (0,_utils__WEBPACK_IMPORTED_MODULE_2__.saveToCSV)(this.#mls, 'MLS.csv');\n (0,_utils__WEBPACK_IMPORTED_MODULE_2__.saveToCSV)(this.convolution, 'python_convolution_mls_iir.csv');\n (0,_utils__WEBPACK_IMPORTED_MODULE_2__.saveToCSV)(this.invertedImpulseResponse, 'IIR.csv');\n const computedIRagain = await Promise.all(this.impulseResponses).then(res => {\n for (let i = 0; i < res.length; i++) {\n if (res[i] != undefined) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_2__.saveToCSV)(res[i], `IR_${i}`);\n }\n }\n });\n }\n\n return iir_and_plots;\n };\n}\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (ImpulseResponse);\n\n\n//# sourceURL=webpack://speakerCalibrator/./src/tasks/impulse-response/impulseResponse.js?");
|
|
526
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _audioCalibrator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../audioCalibrator */ \"./src/tasks/audioCalibrator.js\");\n/* harmony import */ var _mlsGen_mlsGenInterface__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./mlsGen/mlsGenInterface */ \"./src/tasks/impulse-response/mlsGen/mlsGenInterface.js\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../utils */ \"./src/utils.js\");\n/* harmony import */ var _config_firebase__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../config/firebase */ \"./src/config/firebase.js\");\n/* harmony import */ var firebase_database__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! firebase/database */ \"./node_modules/firebase/database/dist/esm/index.esm.js\");\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n/**\r\n *\r\n */\r\nclass ImpulseResponse extends _audioCalibrator__WEBPACK_IMPORTED_MODULE_0__[\"default\"] {\r\n /**\r\n * Default constructor. Creates an instance with any number of paramters passed or the default parameters defined here.\r\n *\r\n * @param {Object<boolean, number, number, number>} calibratorParams - paramter object\r\n * @param {boolean} [calibratorParams.download = false] - boolean flag to download captures\r\n * @param {number} [calibratorParams.mlsOrder = 18] - order of the MLS to be generated\r\n * @param {number} [calibratorParams.numCaptures = 5] - number of captures to perform\r\n * @param {number} [calibratorParams.numMLSPerCapture = 4] - number of bursts of MLS per capture\r\n */\r\n constructor({\r\n download = false,\r\n mlsOrder = 18,\r\n numCaptures = 3,\r\n numMLSPerCapture = 4,\r\n lowHz = 20,\r\n highHz = 10000,\r\n loudSpeakerIr = null,\r\n }) {\r\n super(numCaptures, numMLSPerCapture);\r\n this.#mlsOrder = parseInt(mlsOrder, 10);\r\n this.#P = 2 ** mlsOrder - 1;\r\n this.#download = download;\r\n this.#mls = [];\r\n this.#lowHz = lowHz;\r\n this.#highHz = highHz;\r\n }\r\n\r\n /** @private */\r\n stepNum = 0;\r\n\r\n /** @private */\r\n totalSteps = 25;\r\n\r\n /** @private */\r\n #download;\r\n\r\n /** @private */\r\n #mlsGenInterface;\r\n\r\n /** @private */\r\n #mlsBufferView;\r\n\r\n /** @private */\r\n invertedImpulseResponse = null;\r\n\r\n /** @private */\r\n impulseResponses = [];\r\n\r\n /** @private */\r\n #mlsOrder;\r\n\r\n /** @private */\r\n #lowHz;\r\n\r\n /** @private */\r\n #highHz;\r\n\r\n /** @private */\r\n #mls;\r\n\r\n /** @private */\r\n #P;\r\n\r\n /** @private */\r\n #audioContext;\r\n\r\n /** @private */\r\n TAPER_SECS = 5;\r\n\r\n /** @private */\r\n offsetGainNode;\r\n\r\n /** @private */\r\n convolution;\r\n\r\n /** @private */\r\n status_denominator = 6;\r\n\r\n /** @private */\r\n status_numerator = 0;\r\n\r\n /** @private */\r\n percent_complete = 0;\r\n\r\n /** @private */\r\n status = ``;\r\n\r\n /**generate string template that gets reevaluated as variable increases */\r\n generateTemplate = () => {\r\n if (this.percent_complete > 100) {\r\n this.percent_complete = 100;\r\n }\r\n const template = `<div style=\"display: flex; justify-content: center;\"><div style=\"width: 200px; height: 20px; border: 2px solid #000; border-radius: 10px;\"><div style=\"width: ${this.percent_complete}%; height: 100%; background-color: #00aaff; border-radius: 8px;\"></div></div></div>`;\r\n return template;\r\n };\r\n\r\n /** increment numerator and percent for status bar */\r\n incrementStatusBar = () => {\r\n this.status_numerator += 1;\r\n this.percent_complete = (this.status_numerator / this.status_denominator) * 100;\r\n };\r\n\r\n /** .\r\n * .\r\n * .\r\n * Sends all the computed impulse responses to the backend server for processing\r\n *\r\n * @returns sets the resulting inverted impulse response to the class property\r\n * @example\r\n */\r\n sendImpulseResponsesToServerForProcessing = async () => {\r\n const computedIRs = await Promise.all(this.impulseResponses);\r\n const filteredComputedIRs = computedIRs.filter(element => {\r\n return element != undefined;\r\n });\r\n const mls = this.#mls;\r\n const lowHz = this.#lowHz;\r\n const highHz = this.#highHz;\r\n this.stepNum += 1;\r\n this.status = `computing the IIR...`.toString() + this.generateTemplate().toString();\r\n this.emit('update', {message: this.status});\r\n return this.pyServerAPI\r\n .getInverseImpulseResponseWithRetry({\r\n payload: filteredComputedIRs.slice(0, this.numCaptures),\r\n mls,\r\n lowHz,\r\n highHz,\r\n })\r\n .then(res => {\r\n console.log(res);\r\n this.stepNum += 1;\r\n this.incrementStatusBar();\r\n this.status = `done computing the IIR...`.toString() + this.generateTemplate().toString();\r\n this.emit('update', {message: this.status});\r\n this.invertedImpulseResponse = res['iir'];\r\n this.convolution = res['convolution'];\r\n })\r\n .catch(err => {\r\n // this.emit('InvertedImpulseResponse', {res: false});\r\n console.error(err);\r\n });\r\n };\r\n\r\n /** .\r\n * .\r\n * .\r\n * Sends the recorded signal, or a given csv string of a signal, to the back end server for processing\r\n *\r\n * @param {<array>String} signalCsv - Optional csv string of a previously recorded signal, if given, this signal will be processed\r\n * @example\r\n */\r\n sendRecordingToServerForProcessing = signalCsv => {\r\n const allSignals = this.getAllRecordedSignals();\r\n const numSignals = allSignals.length;\r\n const mls = this.#mls;\r\n const payload =\r\n signalCsv && signalCsv.length > 0 ? (0,_utils__WEBPACK_IMPORTED_MODULE_2__.csvToArray)(signalCsv) : allSignals[numSignals - 1];\r\n console.log('sending rec');\r\n this.stepNum += 1;\r\n this.status =\r\n `computing the IR of the last recording...`.toString() + this.generateTemplate().toString();\r\n this.emit('update', {message: this.status});\r\n this.impulseResponses.push(\r\n this.pyServerAPI\r\n .getImpulseResponse({\r\n sampleRate: this.sourceSamplingRate || 96000,\r\n payload,\r\n mls,\r\n P: this.#P,\r\n })\r\n .then(res => {\r\n if (this.numSuccessfulCaptured < this.numCaptures) {\r\n this.numSuccessfulCaptured += 1;\r\n console.log('num succ capt: ' + this.numSuccessfulCaptured);\r\n this.stepNum += 1;\r\n this.incrementStatusBar();\r\n this.status =\r\n `${this.numSuccessfulCaptured}/${this.numCaptures} IRs computed...`.toString() +\r\n this.generateTemplate().toString();\r\n this.emit('update', {message: this.status});\r\n return res;\r\n }\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n })\r\n );\r\n };\r\n\r\n /**\r\n * Passed to the calibration steps function, awaits the desired amount of seconds to capture the desired number\r\n * of MLS periods defined in the constructor.\r\n *\r\n * @example\r\n */\r\n #awaitDesiredMLSLength = async () => {\r\n // seconds per MLS = P / SR\r\n // await N * P / SR\r\n this.stepNum += 1;\r\n this.status =\r\n `sampling the calibration signal...`.toString() + this.generateTemplate().toString();\r\n this.emit('update', {message: this.status});\r\n await (0,_utils__WEBPACK_IMPORTED_MODULE_2__.sleep)((this.#P / this.sourceSamplingRate) * this.numMLSPerCapture);\r\n };\r\n\r\n /** .\r\n * .\r\n * .\r\n * Passed to the calibration steps function, awaits the onset of the signal to ensure a steady state\r\n *\r\n * @example\r\n */\r\n #awaitSignalOnset = async () => {\r\n this.stepNum += 1;\r\n this.status =\r\n `waiting for the signal to stabilize...`.toString() + this.generateTemplate().toString();\r\n this.emit('update', {message: this.status});\r\n await (0,_utils__WEBPACK_IMPORTED_MODULE_2__.sleep)(this.TAPER_SECS);\r\n };\r\n\r\n /**\r\n * Called immediately after a recording is captured. Used to process the resulting signal\r\n * whether by sending the result to a server or by computing a result locally.\r\n *\r\n * @example\r\n */\r\n #afterMLSRecord = () => {\r\n console.log('after record');\r\n this.sendRecordingToServerForProcessing();\r\n };\r\n\r\n #afterMLSwIIRRecord = () => {\r\n if (this.numSuccessfulCaptured < 1) {\r\n this.numSuccessfulCaptured += 1;\r\n this.stepNum += 1;\r\n this.incrementStatusBar();\r\n this.status =\r\n `${this.numSuccessfulCaptured} recording of convolved MLS captured`.toString() +\r\n this.generateTemplate().toString();\r\n this.emit('update', {message: this.status});\r\n }\r\n };\r\n\r\n /** .\r\n * .\r\n * .\r\n * Created an S Curver Buffer to taper the signal onset\r\n *\r\n * @param {*} length\r\n * @param {*} phase\r\n * @returns\r\n * @example\r\n */\r\n static createSCurveBuffer = (length, phase) => {\r\n const curve = new Float32Array(length);\r\n let i;\r\n for (i = 0; i < length; i += 1) {\r\n // scale the curve to be between 0-1\r\n curve[i] = Math.sin((Math.PI * i) / length - phase) / 2 + 0.5;\r\n }\r\n return curve;\r\n };\r\n\r\n static createInverseSCurveBuffer = (length, phase) => {\r\n const curve = new Float32Array(length);\r\n let i;\r\n let j = length - 1;\r\n for (i = 0; i < length; i += 1) {\r\n // scale the curve to be between 0-1\r\n curve[i] = Math.sin((Math.PI * j) / length - phase) / 2 + 0.5;\r\n j -= 1;\r\n }\r\n return curve;\r\n };\r\n\r\n /**\r\n * Construct a Calibration Node with the calibration parameters.\r\n *\r\n * @param CALIBRATION_TONE_FREQUENCY\r\n * @private\r\n * @example\r\n */\r\n #createPureTonenNode = CALIBRATION_TONE_FREQUENCY => {\r\n const audioContext = this.makeNewSourceAudioContext();\r\n const oscilator = audioContext.createOscillator();\r\n const gainNode = audioContext.createGain();\r\n\r\n oscilator.frequency.value = CALIBRATION_TONE_FREQUENCY;\r\n oscilator.type = 'sine';\r\n gainNode.gain.value = 0.04;\r\n\r\n oscilator.connect(gainNode);\r\n gainNode.connect(audioContext.destination);\r\n\r\n this.addCalibrationNode(oscilator);\r\n };\r\n\r\n /**\r\n * Construct a Calibration Node with the calibration parameters.\r\n *\r\n * @param dataBuffer\r\n * @private\r\n * @example\r\n */\r\n #createCalibrationNodeFromBuffer = dataBuffer => {\r\n const audioContext = this.makeNewSourceAudioContext();\r\n const buffer = audioContext.createBuffer(\r\n 1, // number of channels\r\n dataBuffer.length,\r\n audioContext.sampleRate // sample rate\r\n );\r\n\r\n const data = buffer.getChannelData(0); // get data\r\n // fill the buffer with our data\r\n try {\r\n for (let i = 0; i < dataBuffer.length; i += 1) {\r\n data[i] = dataBuffer[i] * 0.1;\r\n }\r\n } catch (error) {\r\n console.error(error);\r\n }\r\n console.log('mls second, same?');\r\n console.log(data);\r\n const onsetGainNode = audioContext.createGain();\r\n this.offsetGainNode = audioContext.createGain();\r\n const source = audioContext.createBufferSource();\r\n\r\n source.buffer = buffer;\r\n source.loop = true;\r\n source.connect(onsetGainNode);\r\n onsetGainNode.connect(this.offsetGainNode);\r\n this.offsetGainNode.connect(audioContext.destination);\r\n\r\n const onsetCurve = ImpulseResponse.createSCurveBuffer(this.sourceSamplingRate, Math.PI / 2);\r\n onsetGainNode.gain.setValueCurveAtTime(onsetCurve, 0, this.TAPER_SECS);\r\n this.addCalibrationNode(source);\r\n };\r\n\r\n /**\r\n * Given a data buffer, creates the required calibration node\r\n *\r\n * @param {*} dataBufferArray\r\n * @example\r\n */\r\n #setCalibrationNodesFromBuffer = (dataBufferArray = [this.#mlsBufferView]) => {\r\n if (dataBufferArray.length === 1) {\r\n this.#createCalibrationNodeFromBuffer(dataBufferArray[0]);\r\n } else {\r\n throw new Error('The length of the data buffer array must be 1');\r\n }\r\n };\r\n\r\n /**\r\n * function to put MLS filtered IIR data obtained from\r\n * python server into our audio buffer to be played aloud\r\n */\r\n #putInPythonConv = () => {\r\n const audioCtx = this.makeNewSourceAudioContextConvolved();\r\n const buffer = audioCtx.createBuffer(\r\n 1, // number of channels\r\n this.convolution.length,\r\n audioCtx.sampleRate // sample rate\r\n );\r\n\r\n const data = buffer.getChannelData(0); // get data\r\n // fill the buffer with our data\r\n try {\r\n for (let i = 0; i < this.convolution.length; i += 1) {\r\n data[i] = this.convolution[i];\r\n }\r\n } catch (error) {\r\n console.error(error);\r\n }\r\n\r\n const source = audioCtx.createBufferSource();\r\n\r\n source.buffer = buffer;\r\n source.loop = true;\r\n source.connect(audioCtx.destination);\r\n\r\n this.addCalibrationNodeConvolved(source);\r\n };\r\n\r\n /**\r\n * Creates an audio context and plays it for a few seconds.\r\n *\r\n * @private\r\n * @returns - Resolves when the audio is done playing.\r\n * @example\r\n */\r\n #playCalibrationAudio = () => {\r\n this.calibrationNodes[0].start(0);\r\n this.#mls = this.calibrationNodes[0].buffer.getChannelData(0);\r\n this.stepNum += 1;\r\n this.status = `playing the calibration tone...`.toString() + this.generateTemplate().toString();\r\n this.emit('update', {message: this.status});\r\n };\r\n\r\n #playCalibrationAudioConvolved = () => {\r\n this.calibrationNodesConvolved[0].start(0);\r\n this.stepNum += 1;\r\n this.status =\r\n `playing the convolved calibration tone...`.toString() + this.generateTemplate().toString();\r\n this.emit('update', {message: this.status});\r\n };\r\n\r\n /** .\r\n * .\r\n * .\r\n * Stops the audio with tapered offset\r\n *\r\n * @example\r\n */\r\n #stopCalibrationAudio = () => {\r\n this.offsetGainNode.gain.setValueAtTime(\r\n this.offsetGainNode.gain.value,\r\n this.sourceAudioContext.currentTime\r\n );\r\n\r\n this.offsetGainNode.gain.setTargetAtTime(0, this.sourceAudioContext.currentTime, 0.5);\r\n this.calibrationNodes[0].stop(0);\r\n this.sourceAudioContext.close();\r\n this.stepNum += 1;\r\n this.status =\r\n `stopping the calibration tone...`.toString() + this.generateTemplate().toString();\r\n this.emit('update', {message: this.status});\r\n };\r\n\r\n #stopCalibrationAudioConvolved = () => {\r\n this.offsetGainNode.gain.setValueAtTime(\r\n this.offsetGainNode.gain.value,\r\n this.sourceAudioContextConvolved.currentTime\r\n );\r\n\r\n this.offsetGainNode.gain.setTargetAtTime(0, this.sourceAudioContextConvolved.currentTime, 0.5);\r\n this.sourceAudioContextConvolved.close();\r\n this.stepNum += 1;\r\n this.status =\r\n `stopping the convolved calibration tone...`.toString() + this.generateTemplate().toString();\r\n this.emit('update', {message: this.status});\r\n };\r\n\r\n playMLSwithIIR = async (stream, iir) => {\r\n this.invertedImpulseResponse = iir;\r\n // initialize the MLSGenInterface object with it's factory method\r\n\r\n await _mlsGen_mlsGenInterface__WEBPACK_IMPORTED_MODULE_1__[\"default\"].factory(\r\n this.#mlsOrder,\r\n this.sinkSamplingRate,\r\n this.sourceSamplingRate\r\n ).then(mlsGenInterface => {\r\n this.#mlsGenInterface = mlsGenInterface;\r\n this.#mlsBufferView = this.#mlsGenInterface.getMLS();\r\n });\r\n\r\n // after intializating, start the calibration steps with garbage collection\r\n await this.#mlsGenInterface.withGarbageCollection([\r\n () =>\r\n this.calibrationSteps(\r\n stream,\r\n this.#playCalibrationAudioConvolved, // play audio func (required)\r\n this.#putInPythonConv, // before play func\r\n this.#awaitSignalOnset, // before record\r\n () => this.numSuccessfulCaptured < 1, // < this.numCaptures\r\n this.#awaitDesiredMLSLength, // during record\r\n this.#afterMLSwIIRRecord, // after record\r\n 'filtered'\r\n ),\r\n ]);\r\n };\r\n\r\n // function to write frq and gain to firebase database given speakerID\r\n writeFrqGain = async (speakerID, frq, gain) => {\r\n const data = {\r\n frq,\r\n gain,\r\n };\r\n await (0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.set)((0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_3__[\"default\"], `${speakerID}/linear`), data);\r\n };\r\n\r\n // Function to Read frq and gain from firebase database given speakerID\r\n // returns an array of frq and gain if speakerID exists, returns null otherwise\r\n\r\n readFrqGain = async speakerID => {\r\n const dbRef = (0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_3__[\"default\"]);\r\n const snapshot = await (0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.get)((0,firebase_database__WEBPACK_IMPORTED_MODULE_4__.child)(dbRef, `${speakerID}/linear`));\r\n if (snapshot.exists()) {\r\n return snapshot.val();\r\n }\r\n return null;\r\n };\r\n\r\n // Example of how to use the writeFrqGain and readFrqGain functions\r\n // writeFrqGain('speaker1', [1, 2, 3], [4, 5, 6]);\r\n // Speaker1 is the speakerID you want to write to in the database\r\n // readFrqGain('MiniDSPUMIK_1').then(data => console.log(data));\r\n // MiniDSPUMIK_1 is the speakerID with some Data in the database\r\n\r\n /**\r\n * Public method to start the calibration process. Objects intialized from webassembly allocate new memory\r\n * and must be manually freed. This function is responsible for intializing the MlsGenInterface,\r\n * and wrapping the calibration steps with a garbage collection safe gaurd.\r\n *\r\n * @public\r\n * @param stream - The stream of audio from the Listener.\r\n * @example\r\n */\r\n\r\n startCalibration = async stream => {\r\n // initialize the MLSGenInterface object with it's factory method\r\n await _mlsGen_mlsGenInterface__WEBPACK_IMPORTED_MODULE_1__[\"default\"].factory(\r\n this.#mlsOrder,\r\n this.sinkSamplingRate,\r\n this.sourceSamplingRate\r\n ).then(mlsGenInterface => {\r\n this.#mlsGenInterface = mlsGenInterface;\r\n this.#mlsBufferView = this.#mlsGenInterface.getMLS();\r\n });\r\n\r\n // after intializating, start the calibration steps with garbage collection\r\n await this.#mlsGenInterface.withGarbageCollection([\r\n () =>\r\n this.calibrationSteps(\r\n stream,\r\n this.#playCalibrationAudio, // play audio func (required)\r\n this.#setCalibrationNodesFromBuffer, // before play func\r\n this.#awaitSignalOnset, // before record\r\n () => this.numSuccessfulCaptured < this.numCaptures, // loop while true\r\n this.#awaitDesiredMLSLength, // during record\r\n this.#afterMLSRecord, // after record\r\n 'unfiltered'\r\n ),\r\n ]);\r\n\r\n this.#stopCalibrationAudio();\r\n\r\n // at this stage we've captured all the required signals,\r\n // and have received IRs for each one\r\n // so let's send all the IRs to the server to be converted to a single IIR\r\n\r\n await this.sendImpulseResponsesToServerForProcessing();\r\n\r\n this.numSuccessfulCaptured = 0;\r\n // debugging function, use to test the result of the IIR\r\n await this.playMLSwithIIR(stream, this.invertedImpulseResponse);\r\n this.#stopCalibrationAudioConvolved();\r\n\r\n let recs = this.getAllRecordedSignals();\r\n let conv_recs = this.getAllFilteredRecordedSignals();\r\n let unconv_rec = recs[0];\r\n let conv_rec = conv_recs[0];\r\n\r\n this.status = `computing the PSD graphs...`.toString() + this.generateTemplate().toString();\r\n this.emit('update', {message: this.status});\r\n\r\n let results = await this.pyServerAPI\r\n .getPSDWithRetry({\r\n unconv_rec,\r\n conv_rec,\r\n })\r\n .then(res => {\r\n this.incrementStatusBar();\r\n this.status =\r\n `done computing the PSD graphs`.toString() + this.generateTemplate().toString();\r\n this.emit('update', {message: this.status});\r\n return res;\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n });\r\n\r\n let iir_and_plots = {\r\n iir: this.invertedImpulseResponse,\r\n x_unconv: results['x_unconv'],\r\n y_unconv: results['y_unconv'],\r\n x_conv: results['x_conv'],\r\n y_conv: results['y_conv'],\r\n };\r\n\r\n if (this.#download) {\r\n this.downloadSingleUnfilteredRecording();\r\n this.downloadSingleFilteredRecording();\r\n (0,_utils__WEBPACK_IMPORTED_MODULE_2__.saveToCSV)(this.#mls, 'MLS.csv');\r\n (0,_utils__WEBPACK_IMPORTED_MODULE_2__.saveToCSV)(this.convolution, 'python_convolution_mls_iir.csv');\r\n (0,_utils__WEBPACK_IMPORTED_MODULE_2__.saveToCSV)(this.invertedImpulseResponse, 'IIR.csv');\r\n const computedIRagain = await Promise.all(this.impulseResponses).then(res => {\r\n for (let i = 0; i < res.length; i++) {\r\n if (res[i] != undefined) {\r\n (0,_utils__WEBPACK_IMPORTED_MODULE_2__.saveToCSV)(res[i], `IR_${i}`);\r\n }\r\n }\r\n });\r\n }\r\n\r\n return iir_and_plots;\r\n };\r\n}\r\n\r\n/* harmony default export */ __webpack_exports__[\"default\"] = (ImpulseResponse);\r\n\n\n//# sourceURL=webpack://speakerCalibrator/./src/tasks/impulse-response/impulseResponse.js?");
|
|
527
527
|
|
|
528
528
|
/***/ }),
|
|
529
529
|
|
|
@@ -534,7 +534,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _aud
|
|
|
534
534
|
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
535
535
|
|
|
536
536
|
"use strict";
|
|
537
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* eslint-disable prefer-destructuring */\n/* eslint-disable dot-notation */\n// eslint-disable-next-line import/extensions\nconst createMLSGenModule = __webpack_require__(/*! ../../../../dist/mlsGen.js */ \"./dist/mlsGen.js\");\n\n/**\n * MLSGenInterface provides a class for interfacing with the MLSGen WASM module.\n */\nclass MlsGenInterface {\n /** @private */\n #mlsOrder;\n\n /** @private */\n #WASMInstance; // the WASM module instance\n\n /** @private */\n #MLSGenInstance; // the MLSGen object instance\n\n /**\n * Creates an instance of MlsGenInterface.\n * Makes a call to the WASM glue code to load the WASM module.\n *\n * @param WASMInstance\n * @param mlsOrder\n * @param sourceSamplingRate\n * @param sinkSamplingRate\n * @example\n */\n constructor(WASMInstance, mlsOrder, sourceSamplingRate, sinkSamplingRate) {\n this.#mlsOrder = mlsOrder;\n this.#WASMInstance = WASMInstance;\n\n console.warn('initializing MLSGen, need to manually garbage collect');\n this.#MLSGenInstance = new this.#WASMInstance['MLSGen'](\n mlsOrder,\n sourceSamplingRate,\n sinkSamplingRate\n );\n }\n\n /**\n * Factory function that provide an asynchronous function that fetches the WASM module\n * and returns a promise that resolves when the module is loaded.\n *\n * @param mlsOrder\n * @param sourceSamplingRate - The sampling rate of the source audio.\n * @param sinkSamplingRate - The sampling rate of the sink audio.\n * @returns MlsGenInterface.\n * @example\n */\n static factory = async (mlsOrder, sourceSamplingRate, sinkSamplingRate) => {\n if (sourceSamplingRate === undefined || sinkSamplingRate === undefined) {\n throw new Error('sourceSamplingRate and sinkSamplingRate must be defined');\n }\n return new MlsGenInterface(\n await createMLSGenModule().then(instance => instance),\n mlsOrder,\n sourceSamplingRate,\n sinkSamplingRate\n );\n };\n\n /**\n * A Higher-Order function that takes an async callback function that access the MLSGen object,\n * providing safe garbage collection.\n *\n * @param func\n * @param args\n * @param funcsWithParams\n * @example\n */\n withGarbageCollection = async funcsWithParams => {\n try {\n for (let i = 0; i < funcsWithParams.length; i += 1) {\n const funcWithParams = funcsWithParams[i];\n // eslint-disable-next-line no-await-in-loop\n await funcWithParams();\n }\n } catch (error) {\n console.error(error);\n } finally {\n // garbage collect\n if (\n this !== undefined &&\n this !== null &&\n this.#MLSGenInstance !== undefined &&\n this.#MLSGenInstance !== null\n ) {\n this.#MLSGenInstance['Destruct'](); // Call the destructor\n this.#MLSGenInstance['delete'](); // Delete the object\n console.warn(`GARBAGE COLLECTION: deleted MLSGen`);\n this.#WASMInstance['doLeakCheck'](); // Check for memory leaks\n }\n }\n };\n\n /**\n * Calculate and return the Impulse Response of the recorded signal.\n *\n * @returns\n * @example\n */\n getImpulseResponse = () => this.#MLSGenInstance['getImpulseResponse']();\n\n /**\n * Given a recorded MLS signal, this function sets the recordedSignal property of the MLSGen object.\n *\n * @param signals\n * @example\n */\n setRecordedSignals = signals => {\n // get memory view\n const averagedSignals = this.average(signals);\n const recordedSignalsMemoryView = this.#MLSGenInstance['setRecordedSignalsMemoryView'](\n averagedSignals.byteLength\n );\n for (let i = 0; i < averagedSignals.length; i += 1) {\n recordedSignalsMemoryView[i] = averagedSignals[i];\n }\n };\n\n /**\n * Calculate the Maximum Length Sequence (MLS) with period P = 2^N - 1\n * using the MLSGen WASM module.\n *\n * @example\n */\n getMLS = () => this.#MLSGenInstance['getMLS']();\n}\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (MlsGenInterface);\n\n\n//# sourceURL=webpack://speakerCalibrator/./src/tasks/impulse-response/mlsGen/mlsGenInterface.js?");
|
|
537
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* eslint-disable prefer-destructuring */\r\n/* eslint-disable dot-notation */\r\n// eslint-disable-next-line import/extensions\r\nconst createMLSGenModule = __webpack_require__(/*! ../../../../dist/mlsGen.js */ \"./dist/mlsGen.js\");\r\n\r\n/**\r\n * MLSGenInterface provides a class for interfacing with the MLSGen WASM module.\r\n */\r\nclass MlsGenInterface {\r\n /** @private */\r\n #mlsOrder;\r\n\r\n /** @private */\r\n #WASMInstance; // the WASM module instance\r\n\r\n /** @private */\r\n #MLSGenInstance; // the MLSGen object instance\r\n\r\n /**\r\n * Creates an instance of MlsGenInterface.\r\n * Makes a call to the WASM glue code to load the WASM module.\r\n *\r\n * @param WASMInstance\r\n * @param mlsOrder\r\n * @param sourceSamplingRate\r\n * @param sinkSamplingRate\r\n * @example\r\n */\r\n constructor(WASMInstance, mlsOrder, sourceSamplingRate, sinkSamplingRate) {\r\n this.#mlsOrder = mlsOrder;\r\n this.#WASMInstance = WASMInstance;\r\n\r\n console.warn('initializing MLSGen, need to manually garbage collect');\r\n this.#MLSGenInstance = new this.#WASMInstance['MLSGen'](\r\n mlsOrder,\r\n sourceSamplingRate,\r\n sinkSamplingRate\r\n );\r\n }\r\n\r\n /**\r\n * Factory function that provide an asynchronous function that fetches the WASM module\r\n * and returns a promise that resolves when the module is loaded.\r\n *\r\n * @param mlsOrder\r\n * @param sourceSamplingRate - The sampling rate of the source audio.\r\n * @param sinkSamplingRate - The sampling rate of the sink audio.\r\n * @returns MlsGenInterface.\r\n * @example\r\n */\r\n static factory = async (mlsOrder, sourceSamplingRate, sinkSamplingRate) => {\r\n if (sourceSamplingRate === undefined || sinkSamplingRate === undefined) {\r\n throw new Error('sourceSamplingRate and sinkSamplingRate must be defined');\r\n }\r\n return new MlsGenInterface(\r\n await createMLSGenModule().then(instance => instance),\r\n mlsOrder,\r\n sourceSamplingRate,\r\n sinkSamplingRate\r\n );\r\n };\r\n\r\n /**\r\n * A Higher-Order function that takes an async callback function that access the MLSGen object,\r\n * providing safe garbage collection.\r\n *\r\n * @param func\r\n * @param args\r\n * @param funcsWithParams\r\n * @example\r\n */\r\n withGarbageCollection = async funcsWithParams => {\r\n try {\r\n for (let i = 0; i < funcsWithParams.length; i += 1) {\r\n const funcWithParams = funcsWithParams[i];\r\n // eslint-disable-next-line no-await-in-loop\r\n await funcWithParams();\r\n }\r\n } catch (error) {\r\n console.error(error);\r\n } finally {\r\n // garbage collect\r\n if (\r\n this !== undefined &&\r\n this !== null &&\r\n this.#MLSGenInstance !== undefined &&\r\n this.#MLSGenInstance !== null\r\n ) {\r\n this.#MLSGenInstance['Destruct'](); // Call the destructor\r\n this.#MLSGenInstance['delete'](); // Delete the object\r\n console.warn(`GARBAGE COLLECTION: deleted MLSGen`);\r\n this.#WASMInstance['doLeakCheck'](); // Check for memory leaks\r\n }\r\n }\r\n };\r\n\r\n /**\r\n * Calculate and return the Impulse Response of the recorded signal.\r\n *\r\n * @returns\r\n * @example\r\n */\r\n getImpulseResponse = () => this.#MLSGenInstance['getImpulseResponse']();\r\n\r\n /**\r\n * Given a recorded MLS signal, this function sets the recordedSignal property of the MLSGen object.\r\n *\r\n * @param signals\r\n * @example\r\n */\r\n setRecordedSignals = signals => {\r\n // get memory view\r\n const averagedSignals = this.average(signals);\r\n const recordedSignalsMemoryView = this.#MLSGenInstance['setRecordedSignalsMemoryView'](\r\n averagedSignals.byteLength\r\n );\r\n for (let i = 0; i < averagedSignals.length; i += 1) {\r\n recordedSignalsMemoryView[i] = averagedSignals[i];\r\n }\r\n };\r\n\r\n /**\r\n * Calculate the Maximum Length Sequence (MLS) with period P = 2^N - 1\r\n * using the MLSGen WASM module.\r\n *\r\n * @example\r\n */\r\n getMLS = () => this.#MLSGenInstance['getMLS']();\r\n}\r\n\r\n/* harmony default export */ __webpack_exports__[\"default\"] = (MlsGenInterface);\r\n\n\n//# sourceURL=webpack://speakerCalibrator/./src/tasks/impulse-response/mlsGen/mlsGenInterface.js?");
|
|
538
538
|
|
|
539
539
|
/***/ }),
|
|
540
540
|
|
|
@@ -545,7 +545,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* eslint-disable prefer-dest
|
|
|
545
545
|
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
546
546
|
|
|
547
547
|
"use strict";
|
|
548
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _audioCalibrator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../audioCalibrator */ \"./src/tasks/audioCalibrator.js\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../utils */ \"./src/utils.js\");\n\n\n\n\n/**\n *\n */\nclass Volume extends _audioCalibrator__WEBPACK_IMPORTED_MODULE_0__[\"default\"] {\n /**\n *\n * @param root0\n * @param root0.download\n * @param root0.numCalibrationRounds\n * @param root0.numCalibrationNodes\n * @example\n */\n\n /** @private */\n #CALIBRATION_TONE_FREQUENCY = 1000; // Hz\n\n /** @private */\n #CALIBRATION_TONE_TYPE = 'sine';\n\n /** @private */\n #CALIBRATION_TONE_DURATION = 5; // seconds\n\n /** @private */\n outDBSPL = null;\n THD = null;\n outDBSPL1000 = null;\n\n /** @private */\n TAPER_SECS = 0.010; // seconds\n\n /** @private */\n status_denominator = 2; \n\n /** @private */\n status_numerator = 0; \n\n /** @private */\n percent_complete = 0; \n\n /** @private */\n status = ``;\n\n /**generate string template that gets reevaluated as variable increases */\n generateTemplate = () => {\n if (this.percent_complete > 100){\n this.percent_complete = 100;\n }\n const template = `<div style=\"display: flex; justify-content: center;\"><div style=\"width: 200px; height: 20px; border: 2px solid #000; border-radius: 10px;\"><div style=\"width: ${this.percent_complete}%; height: 100%; background-color: #00aaff; border-radius: 8px;\"></div></div></div>`;\n return template;\n }\n\n /** increment numerator and percent for status bar */\n incrementStatusBar = () => {\n this.status_numerator += 1;\n this.percent_complete = (this.status_numerator/this.status_denominator)*100;\n }\n\n handleIncomingData = data => {\n console.log('Received data: ', data);\n if (data.type === 'soundGainDBSPL') {\n this.soundGainDBSPL = data.value;\n } else {\n throw new Error(`Unknown data type: ${data.type}`);\n }\n };\n\n createSCurveBuffer = (onSetBool=true) => {\n\n const curve = new Float32Array(this.TAPER_SECS*this.sourceSamplingRate+1);\n const frequency = 1 / (4 * this.TAPER_SECS);\n let j = 0;\n for (let i = 0; i < this.TAPER_SECS*this.sourceSamplingRate+1; i += 1) {\n const phase = 2 * Math.PI * frequency * j;\n const onsetTaper = Math.pow(Math.sin(phase) , 2);\n const offsetTaper = Math.pow(Math.cos(phase) , 2);\n curve[i] = onSetBool? onsetTaper : offsetTaper;\n j += (1 / this.sourceSamplingRate);\n } \n return curve;\n };\n\n #getTruncatedSignal = (left = 3.5, right = 4.5) => {\n const start = Math.floor(left * this.sourceSamplingRate);\n const end = Math.floor(right * this.sourceSamplingRate);\n const result = Array.from(this.getLastRecordedSignal().slice(start, end));\n\n /**\n * function to check that capture was properly made\n * @param {*} list\n */\n const checkResult = list => {\n const setItem = new Set(list);\n if (setItem.size === 1 && setItem.has(0)) {\n console.warn(\n 'The last capture failed, all recorded signal is zero',\n this.getAllRecordedSignals()\n );\n }\n if (setItem.size === 0) {\n console.warn('The last capture failed, no recorded signal');\n }\n };\n checkResult(result);\n return result;\n };\n\n /** \n * \n * \n Construct a calibration Node with the calibration parameters and given gain value\n * @param {*} gainValue\n * */\n #createCalibrationToneWithGainValue = gainValue => {\n const audioContext = this.makeNewSourceAudioContext();\n const oscilator = audioContext.createOscillator();\n const gainNode = audioContext.createGain();\n const taperGainNode = audioContext.createGain();\n const offsetGainNode = audioContext.createGain();\n const totalDuration = this.#CALIBRATION_TONE_DURATION * 1.2;\n\n oscilator.frequency.value = this.#CALIBRATION_TONE_FREQUENCY;\n oscilator.type = this.#CALIBRATION_TONE_TYPE;\n gainNode.gain.value = gainValue;\n\n oscilator.connect(gainNode);\n gainNode.connect(taperGainNode);\n const onsetCurve = this.createSCurveBuffer();\n taperGainNode.gain.setValueCurveAtTime(onsetCurve, 0, this.TAPER_SECS);\n taperGainNode.connect(offsetGainNode);\n const offsetCurve = this.createSCurveBuffer(false);\n offsetGainNode.gain.setValueCurveAtTime(offsetCurve, (totalDuration-this.TAPER_SECS), this.TAPER_SECS);\n offsetGainNode.connect(audioContext.destination);\n\n this.addCalibrationNode(oscilator);\n };\n\n /**\n * Construct a Calibration Node with the calibration parameters.\n *\n * @private\n * @example\n */\n #createCalibrationNode = () => {\n const audioContext = this.makeNewSourceAudioContext();\n const oscilator = audioContext.createOscillator();\n const gainNode = audioContext.createGain();\n\n oscilator.frequency.value = this.#CALIBRATION_TONE_FREQUENCY;\n oscilator.type = this.#CALIBRATION_TONE_TYPE;\n gainNode.gain.value = 0.04;\n\n oscilator.connect(gainNode);\n gainNode.connect(audioContext.destination);\n\n this.addCalibrationNode(oscilator);\n };\n\n #playCalibrationAudio = async () => {\n const totalDuration = this.#CALIBRATION_TONE_DURATION * 1.2;\n\n this.calibrationNodes[0].start(0);\n this.calibrationNodes[0].stop(totalDuration);\n console.log(`Playing a buffer of ${this.#CALIBRATION_TONE_DURATION} seconds of audio`);\n console.log(`Waiting a total of ${totalDuration} seconds`);\n await (0,_utils__WEBPACK_IMPORTED_MODULE_1__.sleep)(totalDuration);\n };\n\n #sendToServerForProcessing = (lCalib = 104.92978421490648) => {\n console.log('Sending data to server');\n this.pyServerAPI\n .getVolumeCalibration({\n sampleRate: this.sourceSamplingRate,\n payload: this.#getTruncatedSignal(),\n lCalib: lCalib,\n })\n .then(res => {\n if (this.outDBSPL === null) {\n this.incrementStatusBar();\n this.outDBSPL = res['outDbSPL'];\n this.outDBSPL1000 = res['outDbSPL1000'];\n this.THD = res['thd'];\n }\n })\n .catch(err => {\n console.warn(err);\n });\n };\n\n startCalibration = async (stream, gainValues, lCalib = 104.92978421490648) => {\n const trialIterations = gainValues.length;\n this.status_denominator += trialIterations;\n const thdValues = [];\n const inDBValues = [];\n let inDB = 0;\n const outDBSPLValues = [];\n const outDBSPL1000Values = [];\n\n // do one calibration that will be discarded\n const soundLevelToDiscard = -60;\n const gainToDiscard = Math.pow(10, soundLevelToDiscard / 20);\n this.status = `Sound Level: ${soundLevelToDiscard} dB`.toString() + this.generateTemplate().toString();\n this.emit('update', {message: this.status});\n do {\n // eslint-disable-next-line no-await-in-loop\n await this.volumeCalibrationSteps(\n stream,\n this.#playCalibrationAudio,\n this.#createCalibrationToneWithGainValue,\n this.#sendToServerForProcessing,\n gainToDiscard,\n lCalib //todo make this a class parameter\n );\n } while (this.outDBSPL === null);\n //reset the values\n this.outDBSPL = null;\n this.outDBSPL = null;\n this.outDBSPL1000 = null;\n this.THD = null;\n\n // run the calibration at different gain values provided by the user\n for (let i = 0; i < trialIterations; i++) {\n //convert gain to DB and add to inDB\n inDB = Math.log10(gainValues[i]) * 20;\n // precision to 1 decimal place\n inDB = Math.round(inDB * 10) / 10;\n inDBValues.push(inDB);\n this.status = `Sound Level: ${inDB} dB`.toString() + this.generateTemplate().toString();\n this.emit('update', {message: this.status});\n do {\n // eslint-disable-next-line no-await-in-loop\n await this.volumeCalibrationSteps(\n stream,\n this.#playCalibrationAudio,\n this.#createCalibrationToneWithGainValue,\n this.#sendToServerForProcessing,\n gainValues[i],\n lCalib //todo make this a class parameter\n );\n } while (this.outDBSPL === null);\n outDBSPL1000Values.push(this.outDBSPL1000);\n thdValues.push(this.THD);\n outDBSPLValues.push(this.outDBSPL);\n\n this.outDBSPL = null;\n this.outDBSPL1000 = null;\n this.THD = null;\n }\n\n // get the volume calibration parameters from the server\n \n const parameters = await this.pyServerAPI\n .getVolumeCalibrationParameters({\n inDBValues: inDBValues,\n outDBSPLValues: outDBSPL1000Values,\n lCalib: lCalib,\n })\n .then(res => {\n this.incrementStatusBar();\n this.status = `done with 1000 Hz calibration`.toString() + this.generateTemplate().toString();\n this.emit('update', {message: this.status});\n return res;\n });\n const result = {\n parameters: parameters,\n inDBValues: inDBValues,\n outDBSPLValues: outDBSPLValues,\n outDBSPL1000Values: outDBSPL1000Values,\n thdValues: thdValues,\n };\n\n return result;\n };\n}\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (Volume);\n\n\n//# sourceURL=webpack://speakerCalibrator/./src/tasks/volume/volume.js?");
|
|
548
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _audioCalibrator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../audioCalibrator */ \"./src/tasks/audioCalibrator.js\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../utils */ \"./src/utils.js\");\n\r\n\r\n\r\n\r\n/**\r\n *\r\n */\r\nclass Volume extends _audioCalibrator__WEBPACK_IMPORTED_MODULE_0__[\"default\"] {\r\n /**\r\n *\r\n * @param root0\r\n * @param root0.download\r\n * @param root0.numCalibrationRounds\r\n * @param root0.numCalibrationNodes\r\n * @example\r\n */\r\n\r\n /** @private */\r\n #CALIBRATION_TONE_FREQUENCY = 1000; // Hz\r\n\r\n /** @private */\r\n #CALIBRATION_TONE_TYPE = 'sine';\r\n\r\n /** @private */\r\n #CALIBRATION_TONE_DURATION = 5; // seconds\r\n\r\n /** @private */\r\n outDBSPL = null;\r\n THD = null;\r\n outDBSPL1000 = null;\r\n\r\n /** @private */\r\n TAPER_SECS = 0.010; // seconds\r\n\r\n /** @private */\r\n status_denominator = 2; \r\n\r\n /** @private */\r\n status_numerator = 0; \r\n\r\n /** @private */\r\n percent_complete = 0; \r\n\r\n /** @private */\r\n status = ``;\r\n\r\n /**generate string template that gets reevaluated as variable increases */\r\n generateTemplate = () => {\r\n if (this.percent_complete > 100){\r\n this.percent_complete = 100;\r\n }\r\n const template = `<div style=\"display: flex; justify-content: center;\"><div style=\"width: 200px; height: 20px; border: 2px solid #000; border-radius: 10px;\"><div style=\"width: ${this.percent_complete}%; height: 100%; background-color: #00aaff; border-radius: 8px;\"></div></div></div>`;\r\n return template;\r\n }\r\n\r\n /** increment numerator and percent for status bar */\r\n incrementStatusBar = () => {\r\n this.status_numerator += 1;\r\n this.percent_complete = (this.status_numerator/this.status_denominator)*100;\r\n }\r\n\r\n handleIncomingData = data => {\r\n console.log('Received data: ', data);\r\n if (data.type === 'soundGainDBSPL') {\r\n this.soundGainDBSPL = data.value;\r\n } else {\r\n throw new Error(`Unknown data type: ${data.type}`);\r\n }\r\n };\r\n\r\n createSCurveBuffer = (onSetBool=true) => {\r\n\r\n const curve = new Float32Array(this.TAPER_SECS*this.sourceSamplingRate+1);\r\n const frequency = 1 / (4 * this.TAPER_SECS);\r\n let j = 0;\r\n for (let i = 0; i < this.TAPER_SECS*this.sourceSamplingRate+1; i += 1) {\r\n const phase = 2 * Math.PI * frequency * j;\r\n const onsetTaper = Math.pow(Math.sin(phase) , 2);\r\n const offsetTaper = Math.pow(Math.cos(phase) , 2);\r\n curve[i] = onSetBool? onsetTaper : offsetTaper;\r\n j += (1 / this.sourceSamplingRate);\r\n } \r\n return curve;\r\n };\r\n\r\n #getTruncatedSignal = (left = 3.5, right = 4.5) => {\r\n const start = Math.floor(left * this.sourceSamplingRate);\r\n const end = Math.floor(right * this.sourceSamplingRate);\r\n const result = Array.from(this.getLastRecordedSignal().slice(start, end));\r\n\r\n /**\r\n * function to check that capture was properly made\r\n * @param {*} list\r\n */\r\n const checkResult = list => {\r\n const setItem = new Set(list);\r\n if (setItem.size === 1 && setItem.has(0)) {\r\n console.warn(\r\n 'The last capture failed, all recorded signal is zero',\r\n this.getAllRecordedSignals()\r\n );\r\n }\r\n if (setItem.size === 0) {\r\n console.warn('The last capture failed, no recorded signal');\r\n }\r\n };\r\n checkResult(result);\r\n return result;\r\n };\r\n\r\n /** \r\n * \r\n * \r\n Construct a calibration Node with the calibration parameters and given gain value\r\n * @param {*} gainValue\r\n * */\r\n #createCalibrationToneWithGainValue = gainValue => {\r\n const audioContext = this.makeNewSourceAudioContext();\r\n const oscilator = audioContext.createOscillator();\r\n const gainNode = audioContext.createGain();\r\n const taperGainNode = audioContext.createGain();\r\n const offsetGainNode = audioContext.createGain();\r\n const totalDuration = this.#CALIBRATION_TONE_DURATION * 1.2;\r\n\r\n oscilator.frequency.value = this.#CALIBRATION_TONE_FREQUENCY;\r\n oscilator.type = this.#CALIBRATION_TONE_TYPE;\r\n gainNode.gain.value = gainValue;\r\n\r\n oscilator.connect(gainNode);\r\n gainNode.connect(taperGainNode);\r\n const onsetCurve = this.createSCurveBuffer();\r\n taperGainNode.gain.setValueCurveAtTime(onsetCurve, 0, this.TAPER_SECS);\r\n taperGainNode.connect(offsetGainNode);\r\n const offsetCurve = this.createSCurveBuffer(false);\r\n offsetGainNode.gain.setValueCurveAtTime(offsetCurve, (totalDuration-this.TAPER_SECS), this.TAPER_SECS);\r\n offsetGainNode.connect(audioContext.destination);\r\n\r\n this.addCalibrationNode(oscilator);\r\n };\r\n\r\n /**\r\n * Construct a Calibration Node with the calibration parameters.\r\n *\r\n * @private\r\n * @example\r\n */\r\n #createCalibrationNode = () => {\r\n const audioContext = this.makeNewSourceAudioContext();\r\n const oscilator = audioContext.createOscillator();\r\n const gainNode = audioContext.createGain();\r\n\r\n oscilator.frequency.value = this.#CALIBRATION_TONE_FREQUENCY;\r\n oscilator.type = this.#CALIBRATION_TONE_TYPE;\r\n gainNode.gain.value = 0.04;\r\n\r\n oscilator.connect(gainNode);\r\n gainNode.connect(audioContext.destination);\r\n\r\n this.addCalibrationNode(oscilator);\r\n };\r\n\r\n #playCalibrationAudio = async () => {\r\n const totalDuration = this.#CALIBRATION_TONE_DURATION * 1.2;\r\n\r\n this.calibrationNodes[0].start(0);\r\n this.calibrationNodes[0].stop(totalDuration);\r\n console.log(`Playing a buffer of ${this.#CALIBRATION_TONE_DURATION} seconds of audio`);\r\n console.log(`Waiting a total of ${totalDuration} seconds`);\r\n await (0,_utils__WEBPACK_IMPORTED_MODULE_1__.sleep)(totalDuration);\r\n };\r\n\r\n #sendToServerForProcessing = (lCalib = 104.92978421490648) => {\r\n console.log('Sending data to server');\r\n this.pyServerAPI\r\n .getVolumeCalibration({\r\n sampleRate: this.sourceSamplingRate,\r\n payload: this.#getTruncatedSignal(),\r\n lCalib: lCalib,\r\n })\r\n .then(res => {\r\n if (this.outDBSPL === null) {\r\n this.incrementStatusBar();\r\n this.outDBSPL = res['outDbSPL'];\r\n this.outDBSPL1000 = res['outDbSPL1000'];\r\n this.THD = res['thd'];\r\n }\r\n })\r\n .catch(err => {\r\n console.warn(err);\r\n });\r\n };\r\n\r\n startCalibration = async (stream, gainValues, lCalib = 104.92978421490648) => {\r\n const trialIterations = gainValues.length;\r\n this.status_denominator += trialIterations;\r\n const thdValues = [];\r\n const inDBValues = [];\r\n let inDB = 0;\r\n const outDBSPLValues = [];\r\n const outDBSPL1000Values = [];\r\n\r\n // do one calibration that will be discarded\r\n const soundLevelToDiscard = -60;\r\n const gainToDiscard = Math.pow(10, soundLevelToDiscard / 20);\r\n this.status = `Sound Level: ${soundLevelToDiscard} dB`.toString() + this.generateTemplate().toString();\r\n this.emit('update', {message: this.status});\r\n do {\r\n // eslint-disable-next-line no-await-in-loop\r\n await this.volumeCalibrationSteps(\r\n stream,\r\n this.#playCalibrationAudio,\r\n this.#createCalibrationToneWithGainValue,\r\n this.#sendToServerForProcessing,\r\n gainToDiscard,\r\n lCalib //todo make this a class parameter\r\n );\r\n } while (this.outDBSPL === null);\r\n //reset the values\r\n this.outDBSPL = null;\r\n this.outDBSPL = null;\r\n this.outDBSPL1000 = null;\r\n this.THD = null;\r\n\r\n // run the calibration at different gain values provided by the user\r\n for (let i = 0; i < trialIterations; i++) {\r\n //convert gain to DB and add to inDB\r\n inDB = Math.log10(gainValues[i]) * 20;\r\n // precision to 1 decimal place\r\n inDB = Math.round(inDB * 10) / 10;\r\n inDBValues.push(inDB);\r\n this.status = `Sound Level: ${inDB} dB`.toString() + this.generateTemplate().toString();\r\n this.emit('update', {message: this.status});\r\n do {\r\n // eslint-disable-next-line no-await-in-loop\r\n await this.volumeCalibrationSteps(\r\n stream,\r\n this.#playCalibrationAudio,\r\n this.#createCalibrationToneWithGainValue,\r\n this.#sendToServerForProcessing,\r\n gainValues[i],\r\n lCalib //todo make this a class parameter\r\n );\r\n } while (this.outDBSPL === null);\r\n outDBSPL1000Values.push(this.outDBSPL1000);\r\n thdValues.push(this.THD);\r\n outDBSPLValues.push(this.outDBSPL);\r\n\r\n this.outDBSPL = null;\r\n this.outDBSPL1000 = null;\r\n this.THD = null;\r\n }\r\n\r\n // get the volume calibration parameters from the server\r\n \r\n const parameters = await this.pyServerAPI\r\n .getVolumeCalibrationParameters({\r\n inDBValues: inDBValues,\r\n outDBSPLValues: outDBSPL1000Values,\r\n lCalib: lCalib,\r\n })\r\n .then(res => {\r\n this.incrementStatusBar();\r\n this.status = `done with 1000 Hz calibration`.toString() + this.generateTemplate().toString();\r\n this.emit('update', {message: this.status});\r\n return res;\r\n });\r\n const result = {\r\n parameters: parameters,\r\n inDBValues: inDBValues,\r\n outDBSPLValues: outDBSPLValues,\r\n outDBSPL1000Values: outDBSPL1000Values,\r\n thdValues: thdValues,\r\n };\r\n\r\n return result;\r\n };\r\n}\r\n\r\n/* harmony default export */ __webpack_exports__[\"default\"] = (Volume);\r\n\n\n//# sourceURL=webpack://speakerCalibrator/./src/tasks/volume/volume.js?");
|
|
549
549
|
|
|
550
550
|
/***/ }),
|
|
551
551
|
|
|
@@ -556,7 +556,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _aud
|
|
|
556
556
|
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
557
557
|
|
|
558
558
|
"use strict";
|
|
559
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ convertAsterisksToList: function() { return /* binding */ convertAsterisksToList; },\n/* harmony export */ createAndShowPopup: function() { return /* binding */ createAndShowPopup; },\n/* harmony export */ csvToArray: function() { return /* binding */ csvToArray; },\n/* harmony export */ findMaxValue: function() { return /* binding */ findMaxValue; },\n/* harmony export */ findMinValue: function() { return /* binding */ findMinValue; },\n/* harmony export */ formatLineBreak: function() { return /* binding */ formatLineBreak; },\n/* harmony export */ getCurrentTimeString: function() { return /* binding */ getCurrentTimeString; },\n/* harmony export */ interpolate: function() { return /* binding */ interpolate; },\n/* harmony export */ saveToCSV: function() { return /* binding */ saveToCSV; },\n/* harmony export */ saveToJSON: function() { return /* binding */ saveToJSON; },\n/* harmony export */ sleep: function() { return /* binding */ sleep; },\n/* harmony export */ standardDeviation: function() { return /* binding */ standardDeviation; }\n/* harmony export */ });\n/* harmony import */ var sweetalert2__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! sweetalert2 */ \"./node_modules/sweetalert2/dist/sweetalert2.all.js\");\n/* harmony import */ var sweetalert2__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(sweetalert2__WEBPACK_IMPORTED_MODULE_0__);\n\n//import {phrases} from '../dist/example/i18n.js';\n/** .\n * .\n * .\n * Utlity function to pause execution for a given time\n *\n * @param {number} seconds\n * @returns {Promise}\n * @example\n */\nconst sleep = seconds =>\n new Promise(resolve => {\n setTimeout(resolve, seconds * 1000);\n });\n\n/** .\n * .\n * .\n * Uiltity function to create and save a CSV file from a buffer\n *\n * @param {*} data\n * @param {*} filename\n * @example\n */\nconst saveToCSV = (data, filename = 'recordedMLSignal.csv') => {\n // console.log(data)\n let csvContent = 'data:text/csv;charset=utf-8,';\n\n data.forEach((val, idx) => {\n csvContent += `${idx},${val}\\r\\n`;\n });\n const encodedUri = encodeURI(csvContent);\n const link = document.createElement('a');\n link.setAttribute('href', encodedUri);\n link.setAttribute('download', filename);\n document.body.appendChild(link);\n link.click();\n};\n\nconst saveToJSON = (data, filename = 'recordedMLSignal.json') => {\n const jsonData = JSON.stringify(data, null, 2);\n const blob = new Blob([jsonData], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.setAttribute('href', url);\n link.setAttribute('download', filename);\n document.body.appendChild(link);\n link.click();\n URL.revokeObjectURL(url);\n};\n\n\n/** .\n * .\n * .\n * Utility function to create a buffer from a CSV file\n *\n * @param {*} csvString\n * @param {*} delimiter\n * @returns\n * @example\n */\nconst csvToArray = (csvString, delimiter = ',') =>\n csvString\n .trim()\n .split('\\n')\n .map(row => parseFloat(row.trim().split(delimiter)[1]));\n\nconst findMinValue = (array) => {\n let minValue = array[0];\n for (let i = 1; i < array.length; i++) {\n if (array[i] < minValue) {\n minValue = array[i];\n }\n }\n return minValue;\n};\n\nconst findMaxValue = (array) => {\n let maxValue = array[0];\n for (let i = 1; i < array.length; i++) {\n if (array[i] > maxValue) {\n maxValue = array[i];\n }\n }\n return maxValue;\n};\n\nconst getCurrentTimeString = () => {\n const date = new Date();\n\n // Get the date string in the user's locale\n const dateOptions = {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n timeZoneName: \"longOffset\",\n hour: \"numeric\",\n minute: \"numeric\",\n };\n const dateString = date.toLocaleDateString(undefined, dateOptions);\n\n return dateString.replace(\"at \", \"\");\n};\n\nconst standardDeviation = (values) => {\n const avg = average(values);\n\n const squareDiffs = values.map((value) => {\n const diff = value - avg;\n const sqrDiff = diff * diff;\n return sqrDiff;\n });\n\n const avgSquareDiff = average(squareDiffs);\n\n const stdDev = Math.sqrt(avgSquareDiff);\n // only 1 digit after the decimal place\n const std = Math.round(stdDev * 10) / 10;\n return std.toFixed(1);\n};\n\nconst average = (data) => {\n const sum = data.reduce((sum, value) => {\n return sum + value;\n }, 0);\n\n const avg = sum / data.length;\n return avg;\n};\n\nfunction interpolate(x, x0, x1, y0, y1) {\n return y0 + (y1 - y0) * (x - x0) / (x1 - x0);\n}\n\nconst formatLineBreak =(inputStr,checkInternetConnection) => {\n let finalStr = inputStr\n .replace(/\\n/g, '<br>')\n .replace('LLL',\n `<a href=\"#\" id=\"check-connection\">${checkInternetConnection}</a>`);\n \n console.log(finalStr);\n\n return finalStr;\n}\n\n\n \nconst createAndShowPopup = (lang, phrases) => {\n console.log(`\n <div style=\"text-align: left;\"> \n ${convertAsterisksToList(phrases.RC_NeedInternetConnectedPhone[lang].replace(/\\n/g, '<br>'))}\n </div>\n <div class=\"col-3\" style=\"margin-top:10px;\">\n <button id=\"okaybtn\" class=\"btn btn-lg btn-dark\">\n ${phrases.EE_ok[lang]}\n </button>\n </div>`);\n sweetalert2__WEBPACK_IMPORTED_MODULE_0___default().fire({\n html: `\n <div style=\"text-align: left;\"> \n ${convertAsterisksToList(phrases.RC_NeedInternetConnectedPhone[lang].replace(/\\n/g, '<br>'))}\n </div>\n <div class=\"col-3\" style=\"margin-top:10px;\">\n <button id=\"okaybtn\" class=\"btn btn-lg btn-dark\">\n ${phrases.EE_ok[lang]}\n </button>\n </div>`,\n showConfirmButton: false,\n position: 'bottom',\n width: \"40%\",\n customClass: {\n container:'no-background',\n },\n showClass: {\n popup: \"fade-in\",\n },\n hideClass: {\n popup: \"\",\n },\n didOpen: () => {\n const okayBtn = document.getElementById(\"okaybtn\");\n okayBtn.style.display = \"flex\"; \n okayBtn.addEventListener('click', () => {\n sweetalert2__WEBPACK_IMPORTED_MODULE_0___default().close(); // Close the Swal popup\n });\n }\n });\n};\n\nfunction convertAsterisksToList(content) {\n // Replace * with <li> and convert line breaks to </li><li>\n console.log(content);\n let result = content\n .replace(/\\* (.*?)(<br>|$)/g, '<li>$1</li>')\n .replace(/(<li>)(<\\/li>)\\s*$/, '') // Remove trailing </li>\n .replace('<li>', '<ul style=\"padding-left:40px\"> <br> <li>');\n result = result.replace('</li>5', '</li></ul>5');\n return result;\n}\n\n\n\n\n\n\n//# sourceURL=webpack://speakerCalibrator/./src/utils.js?");
|
|
559
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ convertAsterisksToList: function() { return /* binding */ convertAsterisksToList; },\n/* harmony export */ createAndShowPopup: function() { return /* binding */ createAndShowPopup; },\n/* harmony export */ csvToArray: function() { return /* binding */ csvToArray; },\n/* harmony export */ findMaxValue: function() { return /* binding */ findMaxValue; },\n/* harmony export */ findMinValue: function() { return /* binding */ findMinValue; },\n/* harmony export */ formatLineBreak: function() { return /* binding */ formatLineBreak; },\n/* harmony export */ getCurrentTimeString: function() { return /* binding */ getCurrentTimeString; },\n/* harmony export */ interpolate: function() { return /* binding */ interpolate; },\n/* harmony export */ saveToCSV: function() { return /* binding */ saveToCSV; },\n/* harmony export */ saveToJSON: function() { return /* binding */ saveToJSON; },\n/* harmony export */ sleep: function() { return /* binding */ sleep; },\n/* harmony export */ standardDeviation: function() { return /* binding */ standardDeviation; }\n/* harmony export */ });\n/* harmony import */ var sweetalert2__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! sweetalert2 */ \"./node_modules/sweetalert2/dist/sweetalert2.all.js\");\n/* harmony import */ var sweetalert2__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(sweetalert2__WEBPACK_IMPORTED_MODULE_0__);\n\r\n//import {phrases} from '../dist/example/i18n.js';\r\n/** .\r\n * .\r\n * .\r\n * Utlity function to pause execution for a given time\r\n *\r\n * @param {number} seconds\r\n * @returns {Promise}\r\n * @example\r\n */\r\nconst sleep = seconds =>\r\n new Promise(resolve => {\r\n setTimeout(resolve, seconds * 1000);\r\n });\r\n\r\n/** .\r\n * .\r\n * .\r\n * Uiltity function to create and save a CSV file from a buffer\r\n *\r\n * @param {*} data\r\n * @param {*} filename\r\n * @example\r\n */\r\nconst saveToCSV = (data, filename = 'recordedMLSignal.csv') => {\r\n // console.log(data)\r\n let csvContent = 'data:text/csv;charset=utf-8,';\r\n\r\n data.forEach((val, idx) => {\r\n csvContent += `${idx},${val}\\r\\n`;\r\n });\r\n const encodedUri = encodeURI(csvContent);\r\n const link = document.createElement('a');\r\n link.setAttribute('href', encodedUri);\r\n link.setAttribute('download', filename);\r\n document.body.appendChild(link);\r\n link.click();\r\n};\r\n\r\nconst saveToJSON = (data, filename = 'recordedMLSignal.json') => {\r\n const jsonData = JSON.stringify(data, null, 2);\r\n const blob = new Blob([jsonData], { type: 'application/json' });\r\n const url = URL.createObjectURL(blob);\r\n const link = document.createElement('a');\r\n link.setAttribute('href', url);\r\n link.setAttribute('download', filename);\r\n document.body.appendChild(link);\r\n link.click();\r\n URL.revokeObjectURL(url);\r\n};\r\n\r\n\r\n/** .\r\n * .\r\n * .\r\n * Utility function to create a buffer from a CSV file\r\n *\r\n * @param {*} csvString\r\n * @param {*} delimiter\r\n * @returns\r\n * @example\r\n */\r\nconst csvToArray = (csvString, delimiter = ',') =>\r\n csvString\r\n .trim()\r\n .split('\\n')\r\n .map(row => parseFloat(row.trim().split(delimiter)[1]));\r\n\r\nconst findMinValue = (array) => {\r\n let minValue = array[0];\r\n for (let i = 1; i < array.length; i++) {\r\n if (array[i] < minValue) {\r\n minValue = array[i];\r\n }\r\n }\r\n return minValue;\r\n};\r\n\r\nconst findMaxValue = (array) => {\r\n let maxValue = array[0];\r\n for (let i = 1; i < array.length; i++) {\r\n if (array[i] > maxValue) {\r\n maxValue = array[i];\r\n }\r\n }\r\n return maxValue;\r\n};\r\n\r\nconst getCurrentTimeString = () => {\r\n const date = new Date();\r\n\r\n // Get the date string in the user's locale\r\n const dateOptions = {\r\n year: \"numeric\",\r\n month: \"long\",\r\n day: \"numeric\",\r\n timeZoneName: \"longOffset\",\r\n hour: \"numeric\",\r\n minute: \"numeric\",\r\n };\r\n const dateString = date.toLocaleDateString(undefined, dateOptions);\r\n\r\n return dateString.replace(\"at \", \"\");\r\n};\r\n\r\nconst standardDeviation = (values) => {\r\n const avg = average(values);\r\n\r\n const squareDiffs = values.map((value) => {\r\n const diff = value - avg;\r\n const sqrDiff = diff * diff;\r\n return sqrDiff;\r\n });\r\n\r\n const avgSquareDiff = average(squareDiffs);\r\n\r\n const stdDev = Math.sqrt(avgSquareDiff);\r\n // only 1 digit after the decimal place\r\n const std = Math.round(stdDev * 10) / 10;\r\n return std.toFixed(1);\r\n};\r\n\r\nconst average = (data) => {\r\n const sum = data.reduce((sum, value) => {\r\n return sum + value;\r\n }, 0);\r\n\r\n const avg = sum / data.length;\r\n return avg;\r\n};\r\n\r\nfunction interpolate(x, x0, x1, y0, y1) {\r\n return y0 + (y1 - y0) * (x - x0) / (x1 - x0);\r\n}\r\n\r\nconst formatLineBreak =(inputStr,checkInternetConnection) => {\r\n let finalStr = inputStr\r\n .replace(/\\n/g, '<br>')\r\n .replace('LLL',\r\n `<a href=\"#\" id=\"check-connection\">${checkInternetConnection}</a>`);\r\n \r\n console.log(finalStr);\r\n\r\n return finalStr;\r\n}\r\n\r\n\r\n \r\nconst createAndShowPopup = (lang, phrases) => {\r\n console.log(`\r\n <div style=\"text-align: left;\"> \r\n ${convertAsterisksToList(phrases.RC_NeedInternetConnectedPhone[lang].replace(/\\n/g, '<br>'))}\r\n </div>\r\n <div class=\"col-3\" style=\"margin-top:10px;\">\r\n <button id=\"okaybtn\" class=\"btn btn-lg btn-dark\">\r\n ${phrases.EE_ok[lang]}\r\n </button>\r\n </div>`);\r\n sweetalert2__WEBPACK_IMPORTED_MODULE_0___default().fire({\r\n html: `\r\n <div style=\"text-align: left;\"> \r\n ${convertAsterisksToList(phrases.RC_NeedInternetConnectedPhone[lang].replace(/\\n/g, '<br>'))}\r\n </div>\r\n <div class=\"col-3\" style=\"margin-top:10px;\">\r\n <button id=\"okaybtn\" class=\"btn btn-lg btn-dark\">\r\n ${phrases.EE_ok[lang]}\r\n </button>\r\n </div>`,\r\n showConfirmButton: false,\r\n position: 'bottom',\r\n width: \"40%\",\r\n customClass: {\r\n container:'no-background',\r\n },\r\n showClass: {\r\n popup: \"fade-in\",\r\n },\r\n hideClass: {\r\n popup: \"\",\r\n },\r\n didOpen: () => {\r\n const okayBtn = document.getElementById(\"okaybtn\");\r\n okayBtn.style.display = \"flex\"; \r\n okayBtn.addEventListener('click', () => {\r\n sweetalert2__WEBPACK_IMPORTED_MODULE_0___default().close(); // Close the Swal popup\r\n });\r\n }\r\n });\r\n};\r\n\r\nfunction convertAsterisksToList(content) {\r\n // Replace * with <li> and convert line breaks to </li><li>\r\n console.log(content);\r\n let result = content\r\n .replace(/\\* (.*?)(<br>|$)/g, '<li>$1</li>')\r\n .replace(/(<li>)(<\\/li>)\\s*$/, '') // Remove trailing </li>\r\n .replace('<li>', '<ul style=\"padding-left:40px\"> <br> <li>');\r\n result = result.replace('</li>5', '</li></ul>5');\r\n return result;\r\n}\r\n\r\n\r\n\r\n\r\n\n\n//# sourceURL=webpack://speakerCalibrator/./src/utils.js?");
|
|
560
560
|
|
|
561
561
|
/***/ }),
|
|
562
562
|
|