speaker-calibration 2.2.220 → 2.2.221
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/.gitignore +81 -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/index.html +123 -123
- package/coverage/lcov-report/prettify.css +101 -101
- package/coverage/lcov-report/prettify.js +937 -937
- 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/example/NoSleep.min.js +1 -1
- package/dist/example/fetch-languages-sheets.js +77 -77
- package/dist/example/i18n.js +29082 -28914
- package/dist/example/index.html +47 -47
- package/dist/example/listener.html +81 -79
- 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 +152 -152
- package/dist/listener.js +4 -4
- package/dist/main.js +11 -11
- 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.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.svg +1829 -1829
- package/doc/fonts/OpenSans-BoldItalic-webfont.svg +1829 -1829
- package/doc/fonts/OpenSans-Italic-webfont.svg +1829 -1829
- package/doc/fonts/OpenSans-Light-webfont.svg +1830 -1830
- package/doc/fonts/OpenSans-LightItalic-webfont.svg +1834 -1834
- package/doc/fonts/OpenSans-Regular-webfont.svg +1830 -1830
- 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/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/netlify.toml +26 -26
- package/package.json +78 -78
- package/src/config/firebase.js +26 -26
- package/src/index.html +21 -21
- package/src/listener-app/listener.js +377 -344
- package/src/main.js +22 -22
- package/src/myEventEmitter.js +83 -83
- package/src/peer-connection/audioPeer.js +148 -148
- package/src/peer-connection/listener.js +467 -467
- package/src/peer-connection/peerErrors.js +25 -25
- package/src/peer-connection/speaker.js +812 -810
- package/src/powerCheck.js +98 -98
- package/src/server/PythonServerAPI.js +869 -869
- package/src/tasks/audioCalibrator.js +360 -360
- package/src/tasks/audioRecorder.js +315 -315
- package/src/tasks/combination/combination.js +3171 -3167
- 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 +64 -64
- package/.github/workflows/update-phrases.yml +0 -37
- package/makefile +0 -74
package/dist/main.js
CHANGED
|
@@ -92,7 +92,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
92
92
|
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
93
93
|
|
|
94
94
|
"use strict";
|
|
95
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/web.dom-collections.iterator.js */ \"./node_modules/core-js/modules/web.dom-collections.iterator.js\");\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_0__);\n\nfunction _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }\nfunction _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError(\"Cannot initialize the same private elements twice on an object\"); }\nfunction _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }\nfunction _classPrivateFieldSet(s, a, r) { return s.set(_assertClassBrand(s, a), r), r; }\nfunction _assertClassBrand(e, t, n) { if (\"function\" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError(\"Private element is not present on this object\"); }\nvar _events = /*#__PURE__*/new WeakMap();\n/**\
|
|
95
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/web.dom-collections.iterator.js */ \"./node_modules/core-js/modules/web.dom-collections.iterator.js\");\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_0__);\n\nfunction _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }\nfunction _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError(\"Cannot initialize the same private elements twice on an object\"); }\nfunction _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }\nfunction _classPrivateFieldSet(s, a, r) { return s.set(_assertClassBrand(s, a), r), r; }\nfunction _assertClassBrand(e, t, n) { if (\"function\" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError(\"Private element is not present on this object\"); }\nvar _events = /*#__PURE__*/new WeakMap();\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 /** .\n * .\n * .\n * Default constructor, intializes an empty object to store events\n *\n * @example\n */\n constructor() {\n _classPrivateFieldInitSpec(this, _events, void 0);\n _classPrivateFieldSet(_events, this, {});\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 (!_classPrivateFieldGet(_events, this)[name]) {\n _classPrivateFieldGet(_events, this)[name] = [];\n }\n _classPrivateFieldGet(_events, this)[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 (!_classPrivateFieldGet(_events, this)[name]) {\n throw new Error(\"Can't remove a listener. Event \\\"\".concat(name, \"\\\" doesn't exits.\"));\n }\n\n /**\n *\n * @param listener\n * @example\n */\n const filterListeners = listener => listener !== listenerToRemove;\n _classPrivateFieldGet(_events, this)[name] = _classPrivateFieldGet(_events, this)[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 (!_classPrivateFieldGet(_events, this)[name]) {\n throw new Error(\"Can't emit an event. Event \\\"\".concat(name, \"\\\" doesn't exits.\"));\n }\n\n /**\n *\n * @param {*} callback\n */\n const fireCallbacks = callback => {\n callback(data);\n };\n _classPrivateFieldGet(_events, this)[name].forEach(fireCallbacks);\n }\n}\n/* harmony default export */ __webpack_exports__[\"default\"] = (MyEventEmitter);\n\n//# sourceURL=webpack://speakerCalibrator/./src/myEventEmitter.js?");
|
|
96
96
|
|
|
97
97
|
/***/ }),
|
|
98
98
|
|
|
@@ -103,7 +103,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core
|
|
|
103
103
|
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
104
104
|
|
|
105
105
|
"use strict";
|
|
106
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_object_from_entries_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.object.from-entries.js */ \"./node_modules/core-js/modules/es.object.from-entries.js\");\n/* harmony import */ var core_js_modules_es_object_from_entries_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_object_from_entries_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/web.dom-collections.iterator.js */ \"./node_modules/core-js/modules/web.dom-collections.iterator.js\");\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_web_url_search_params_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/web.url-search-params.js */ \"./node_modules/core-js/modules/web.url-search-params.js\");\n/* harmony import */ var core_js_modules_web_url_search_params_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_url_search_params_js__WEBPACK_IMPORTED_MODULE_2__);\n\n\n\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n// TODO: this was already here before, but appears to be unused\nconst pressFeedbackURI = '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/**\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 */\nconst initParameters = {\n targetElementId: null,\n siteUrl: null\n};\n\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 */\nclass AudioPeer {\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 */\n constructor() {\n var _this = this;\n let param = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initParameters;\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 */\n _defineProperty(this, \"displayUpdate\", function (message) {\n let append = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 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\".concat(message);\n } else {\n displayElement.innerText = message;\n }\n } else {\n console.log('MESSAGE: ', message);\n }\n });\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 */\n _defineProperty(this, \"onPeerDisconnected\", () => {\n this.displayUpdate('Connection lost. Please reconnect');\n\n // Workaround for peer.reconnect deleting previous id\n try {\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 } catch (e) {\n console.log(e);\n }\n });\n /** .\r\n * .\r\n * .\r\n * Callback method that cleans up after peer connection is closed\r\n *\r\n * @example\r\n */\n _defineProperty(this, \"onPeerClose\", () => {\n this.displayUpdate('Connection closed');\n this.conn = null;\n });\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 */\n _defineProperty(this, \"onPeerError\", err => {\n this.displayUpdate(err);\n console.log(\"\".concat(err));\n });\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 */\n _defineProperty(this, \"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 /** .\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 */\n _defineProperty(this, \"queryStringFromObject\", params => Object.keys(params).map(key => \"\".concat(key, \"=\").concat(params[key])).join('&'));\n this.conn = null;\n this.lastPeerId = null;\n\n // Display information to HTML elem with given id\n this.targetElement = param.targetElementId;\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 || window.webkitAudioContext || window.audioContext)();\n }\n}\n_defineProperty(AudioPeer, \"keypressFeedbackSound\", pressFeedbackURI);\n/* harmony default export */ __webpack_exports__[\"default\"] = (AudioPeer);\n\n//# sourceURL=webpack://speakerCalibrator/./src/peer-connection/audioPeer.js?");
|
|
106
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_object_from_entries_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.object.from-entries.js */ \"./node_modules/core-js/modules/es.object.from-entries.js\");\n/* harmony import */ var core_js_modules_es_object_from_entries_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_object_from_entries_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/web.dom-collections.iterator.js */ \"./node_modules/core-js/modules/web.dom-collections.iterator.js\");\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_web_url_search_params_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/web.url-search-params.js */ \"./node_modules/core-js/modules/web.url-search-params.js\");\n/* harmony import */ var core_js_modules_web_url_search_params_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_url_search_params_js__WEBPACK_IMPORTED_MODULE_2__);\n\n\n\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n// TODO: this was already here before, but appears to be unused\nconst pressFeedbackURI = '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() {\n var _this = this;\n let param = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initParameters;\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 _defineProperty(this, \"displayUpdate\", function (message) {\n let append = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 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\".concat(message);\n } else {\n displayElement.innerText = message;\n }\n } else {\n console.log('MESSAGE: ', message);\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 _defineProperty(this, \"onPeerDisconnected\", () => {\n this.displayUpdate('Connection lost. Please reconnect');\n\n // Workaround for peer.reconnect deleting previous id\n try {\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 } catch (e) {\n console.log(e);\n }\n });\n /** .\n * .\n * .\n * Callback method that cleans up after peer connection is closed\n *\n * @example\n */\n _defineProperty(this, \"onPeerClose\", () => {\n this.displayUpdate('Connection closed');\n this.conn = null;\n });\n /** .\n * .\n * .\n * Helper method for when an error occurs\n *\n * @param {*} err\n * @example\n */\n _defineProperty(this, \"onPeerError\", err => {\n this.displayUpdate(err);\n console.log(\"\".concat(err));\n });\n /** .\n * .\n * .\n * Helper method that converts url paramters to an object\n *\n * @returns {object}\n * @example\n */\n _defineProperty(this, \"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 * Helper method that converts an object to a query string\n *\n * @param {object} params\n * @returns {string}\n * @example\n */\n _defineProperty(this, \"queryStringFromObject\", params => Object.keys(params).map(key => \"\".concat(key, \"=\").concat(params[key])).join('&'));\n this.conn = null;\n this.lastPeerId = null;\n\n // Display information to HTML elem with given id\n this.targetElement = param.targetElementId;\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 || window.webkitAudioContext || window.audioContext)();\n }\n}\n_defineProperty(AudioPeer, \"keypressFeedbackSound\", pressFeedbackURI);\n/* harmony default export */ __webpack_exports__[\"default\"] = (AudioPeer);\n\n//# sourceURL=webpack://speakerCalibrator/./src/peer-connection/audioPeer.js?");
|
|
107
107
|
|
|
108
108
|
/***/ }),
|
|
109
109
|
|
|
@@ -125,7 +125,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
125
125
|
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
126
126
|
|
|
127
127
|
"use strict";
|
|
128
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_array_buffer_slice_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array-buffer.slice.js */ \"./node_modules/core-js/modules/es.array-buffer.slice.js\");\n/* harmony import */ var core_js_modules_es_array_buffer_slice_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_buffer_slice_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_es_string_replace_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/es.string.replace.js */ \"./node_modules/core-js/modules/es.string.replace.js\");\n/* harmony import */ var core_js_modules_es_string_replace_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_string_replace_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_es_typed_array_uint8_array_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/es.typed-array.uint8-array.js */ \"./node_modules/core-js/modules/es.typed-array.uint8-array.js\");\n/* harmony import */ var core_js_modules_es_typed_array_uint8_array_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_typed_array_uint8_array_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var core_js_modules_es_typed_array_fill_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! core-js/modules/es.typed-array.fill.js */ \"./node_modules/core-js/modules/es.typed-array.fill.js\");\n/* harmony import */ var core_js_modules_es_typed_array_fill_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_typed_array_fill_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var core_js_modules_es_typed_array_set_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! core-js/modules/es.typed-array.set.js */ \"./node_modules/core-js/modules/es.typed-array.set.js\");\n/* harmony import */ var core_js_modules_es_typed_array_set_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_typed_array_set_js__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var core_js_modules_es_typed_array_sort_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! core-js/modules/es.typed-array.sort.js */ \"./node_modules/core-js/modules/es.typed-array.sort.js\");\n/* harmony import */ var core_js_modules_es_typed_array_sort_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_typed_array_sort_js__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! core-js/modules/web.dom-collections.iterator.js */ \"./node_modules/core-js/modules/web.dom-collections.iterator.js\");\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_6__);\n/* harmony import */ var qrcode__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! qrcode */ \"./node_modules/qrcode/lib/browser.js\");\n/* harmony import */ var _audioPeer__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./audioPeer */ \"./src/peer-connection/audioPeer.js\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../utils */ \"./src/utils.js\");\n/* harmony import */ var _peerErrors__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./peerErrors */ \"./src/peer-connection/peerErrors.js\");\n/* harmony import */ var peerjs__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! peerjs */ \"./node_modules/peerjs/dist/bundler.mjs\");\nvar _Speaker;\n\n\n\n\n\n\n\nfunction _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }\nfunction _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError(\"Cannot initialize the same private elements twice on an object\"); }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }\nfunction _assertClassBrand(e, t, n) { if (\"function\" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError(\"Private element is not present on this object\"); }\n\n\n\n\n\n\n//import {phrases} from '../../dist/example/i18n';\n\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 */\nvar _showQRCode = /*#__PURE__*/new WeakMap();\nvar _showSpinner = /*#__PURE__*/new WeakMap();\nvar _removeUIElems = /*#__PURE__*/new WeakMap();\nvar _onPeerOpen = /*#__PURE__*/new WeakMap();\nvar _onPeerConnection = /*#__PURE__*/new WeakMap();\nvar _onPeerDisconnected = /*#__PURE__*/new WeakMap();\nvar _onPeerError = /*#__PURE__*/new WeakMap();\nvar _onIncomingData = /*#__PURE__*/new WeakMap();\nvar _ready = /*#__PURE__*/new WeakMap();\nclass Speaker extends _audioPeer__WEBPACK_IMPORTED_MODULE_8__[\"default\"] {\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 */\n constructor(_params, _CalibratorInstance) {\n var _params$language, _params$debug, _params$isSmartPhone, _params$calibrateSoun, _params$calibrateSoun2, _params$instructionDi, _params$soundSubtitle, _params$timeToCalibra, _params$soundMessageI, _params$titleDisplayI, _params$timeToCalibra2, _params$isParticipant, _params$isLoudspeaker, _params$micrpohoneIdF, _params$buttonsContai, _params$phrases;\n super(_params);\n _defineProperty(this, \"uri\", '');\n _defineProperty(this, \"qrImage\", void 0);\n _defineProperty(this, \"shortURL\", void 0);\n _defineProperty(this, \"initPeer\", async () => {\n const id = await this.generateTimeBasedPeerID();\n this.peer = new peerjs__WEBPACK_IMPORTED_MODULE_11__[\"default\"](id, {\n secure: true,\n host: 'easyeyes-peer-server.herokuapp.com',\n port: 443,\n config: {\n iceServers: [{\n urls: 'stun:stun.relay.metered.ca:80'\n }, {\n urls: 'turn:global.relay.metered.ca:80',\n username: 'de884cfc34189cdf1a5dd616',\n credential: 'IcOpouU9/TYBmpHU'\n }, {\n urls: 'turn:global.relay.metered.ca:80?transport=tcp',\n username: 'de884cfc34189cdf1a5dd616',\n credential: 'IcOpouU9/TYBmpHU'\n }, {\n urls: 'turn:global.relay.metered.ca:443',\n username: 'de884cfc34189cdf1a5dd616',\n credential: 'IcOpouU9/TYBmpHU'\n }, {\n urls: 'turns:global.relay.metered.ca:443?transport=tcp',\n username: 'de884cfc34189cdf1a5dd616',\n credential: 'IcOpouU9/TYBmpHU'\n }]\n }\n });\n this.peer.on('open', _classPrivateFieldGet(_onPeerOpen, this));\n this.peer.on('connection', _classPrivateFieldGet(_onPeerConnection, this));\n this.peer.on('close', this.onPeerClose);\n this.peer.on('disconnected', _classPrivateFieldGet(_onPeerDisconnected, this));\n this.peer.on('error', _classPrivateFieldGet(_onPeerError, this));\n });\n _defineProperty(this, \"generateTimeBasedPeerID\", async () => {\n const now = new Date().getTime();\n const randomBuffer = new Uint8Array(10);\n crypto.getRandomValues(randomBuffer);\n const randomPart = Array.from(randomBuffer).map(b => b.toString(36)).join('');\n const toHash = \"\".concat(now, \"-\").concat(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 _defineProperty(this, \"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 /**\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 */\n\n _classPrivateFieldInitSpec(this, _showQRCode, async () => {\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 // Generate QR code\n const qrCanvas = document.createElement('canvas');\n qrCanvas.setAttribute('id', 'qrCanvas');\n qrcode__WEBPACK_IMPORTED_MODULE_7__.toCanvas(qrCanvas, this.uri, error => {\n if (error) console.error(error);\n });\n\n // Create QR image\n const qrImage = new Image();\n qrImage.setAttribute('id', 'compatibilityCheckQRImage');\n qrImage.style.zIndex = Infinity;\n qrImage.style.height = '150px';\n qrImage.style.width = '150px';\n qrImage.style.margin = '-10px';\n qrImage.style.aspectRatio = 1;\n qrImage.src = qrCanvas.toDataURL();\n this.qrImage = qrImage;\n\n // Get shortened URL\n let shortURL = this.uri;\n try {\n const response = await fetch('https://api.short.io/links/public', {\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',\n originalURL: this.uri\n })\n });\n if (!response.ok) {\n throw new Error(\"HTTP error! Status: \".concat(response.status));\n }\n const data = await response.json();\n shortURL = data.shortURL;\n } catch (error) {\n console.error('Error:', error.message);\n }\n\n // Main container with 3 columns\n const container = document.createElement('div');\n container.style.display = 'flex';\n container.style.alignItems = 'flex-start';\n container.style.paddingTop = '0';\n container.id = 'skipQRContainer';\n\n // Column 1: QR Code\n const qrColumn = document.createElement('div');\n qrColumn.style.flex = '0 0 auto';\n qrColumn.appendChild(qrImage);\n\n // Column 2: Explanation Text\n const textColumn = document.createElement('div');\n textColumn.style.flex = '1';\n textColumn.style.padding = '0 20px';\n textColumn.style.maxWidth = '560px';\n const explanation = document.createElement('h2');\n explanation.style.fontSize = '1.1rem';\n explanation.id = 'skipQRExplanation';\n explanation.style.margin = '0';\n explanation.style.textAlign = 'left';\n explanation.innerHTML = (0,_utils__WEBPACK_IMPORTED_MODULE_9__.formatLineBreak)(this.phrases.RC_skipQR_ExplanationWithoutPreferNot[this.language].replace('xxx', \"<b style=\\\"user-select: text\\\">\".concat(shortURL, \"</b>\")).replace('XXX', \"<b style=\\\"user-select: text\\\">\".concat(shortURL, \"</b>\")), this.phrases.RC_checkInternetConnection[this.language]);\n const language = this.language;\n const phrases = this.phrases;\n const checkConnection = document.createElement('a');\n checkConnection.id = 'check-connection';\n checkConnection.href = '#';\n checkConnection.innerHTML = \"check the phone's internet connection\";\n checkConnection.addEventListener('click', function (event) {\n event.preventDefault();\n (0,_utils__WEBPACK_IMPORTED_MODULE_9__.createAndShowPopup)(language, phrases);\n });\n explanation.querySelector('a#check-connection').replaceWith(checkConnection);\n textColumn.appendChild(explanation);\n\n // Column 3: Buttons\n const buttonColumn = document.createElement('div');\n buttonColumn.style.display = 'flex';\n buttonColumn.style.flexDirection = 'column';\n buttonColumn.style.gap = '10px';\n buttonColumn.style.flex = '0 0 auto';\n buttonColumn.style.alignItems = 'flex-end';\n buttonColumn.appendChild(this.buttonsContainer);\n\n // Assemble the columns\n container.appendChild(qrColumn);\n container.appendChild(textColumn);\n container.appendChild(buttonColumn);\n document.getElementById(this.targetElement).appendChild(container);\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 _classPrivateFieldInitSpec(this, _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 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 _classPrivateFieldInitSpec(this, _removeUIElems, () => {\n const parent = document.getElementById(this.targetElement);\n while (parent.firstChild) {\n parent.firstChild.remove();\n }\n });\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 */\n _classPrivateFieldInitSpec(this, _onPeerOpen, id => {\n // Workaround for peer.reconnect deleting previous id\n try {\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 if (id !== this.peer.id) {\n console.warn('DEBUG Check you assumption that id === this.peer.id');\n }\n } catch (error) {\n console.error('Error in #onPeerOpen: ', error);\n }\n _classPrivateFieldGet(_showQRCode, this).call(this);\n });\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 */\n _classPrivateFieldInitSpec(this, _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 this.conn = connection;\n console.log('Connected to: ', this.conn.peer);\n _classPrivateFieldGet(_ready, this).call(this);\n });\n /**\r\n * Called when the peer connection is closed.\r\n *\r\n * @private\r\n * @example\r\n */\n _defineProperty(this, \"onPeerClose\", () => {\n this.conn = null;\n console.log('Connection destroyed');\n });\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 */\n _classPrivateFieldInitSpec(this, _onPeerDisconnected, () => {\n console.log('Connection lost. Please reconnect');\n try {\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 } catch (error) {\n console.error('Error in #onPeerDisconnected: ', error);\n }\n });\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 */\n _classPrivateFieldInitSpec(this, _onPeerError, error => {\n // TODO: check if this function is needed or not\n console.error(error);\n });\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 */\n _classPrivateFieldInitSpec(this, _onIncomingData, data => {\n // enforce object type\n if (!Object.prototype.hasOwnProperty.call(data, 'name') || !Object.prototype.hasOwnProperty.call(data, 'payload')) {\n console.error('Received malformed data: ', data);\n return;\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 'permissionStatus':\n console.log('Received permission status from listener: ', data.payload);\n if (data.payload.type === 'error') {\n this.permissionStatus = 'error';\n this.ac.setPermissionStatus('error');\n } else if (data.payload.type === 'denied') {\n this.permissionStatus = 'denied';\n this.ac.setPermissionStatus('denied');\n } else if (data.payload.type === 'granted') {\n this.permissionStatus = 'granted';\n this.ac.setPermissionStatus('granted');\n console.log('Permission granted');\n }\n break;\n case _peerErrors__WEBPACK_IMPORTED_MODULE_10__.UnsupportedDeviceError.name:\n case _peerErrors__WEBPACK_IMPORTED_MODULE_10__.MissingSpeakerIdError.name:\n throw data.payload;\n break;\n default:\n break;\n }\n });\n /**\r\n * Called when the peer connection is #ready.\r\n *\r\n * @private\r\n * @example\r\n */\n _classPrivateFieldInitSpec(this, _ready, () => {\n // Perform callback with data\n this.conn.on('data', _classPrivateFieldGet(_onIncomingData, this));\n this.conn.on('close', () => {\n console.log('Connection reset<br>Awaiting connection...');\n this.conn = null;\n });\n });\n /** .\r\n * .\r\n * .\r\n * Debug method for downloading the recorded audio\r\n *\r\n * @public\r\n * @example\r\n */\n _defineProperty(this, \"downloadData\", () => {\n this.ac.downloadData();\n });\n _defineProperty(this, \"repeatCalibration\", async (params, stream, CalibratorInstance) => {\n this.ac = CalibratorInstance;\n _classPrivateFieldGet(_removeUIElems, this).call(this);\n _classPrivateFieldGet(_showSpinner, this).call(this);\n console.log('This is a repeat');\n // wrap the calibration process in a promise so we can await it\n return new Promise((resolve, reject) => {\n // Add a permission check handler\n const permissionCheckInterval = setInterval(() => {\n if (this.permissionStatus === 'error' || this.permissionStatus === 'denied') {\n clearInterval(permissionCheckInterval);\n _classPrivateFieldGet(_removeUIElems, this).call(this);\n resolve('permission denied');\n }\n }, 100);\n\n // Start calibration process\n (async () => {\n try {\n const result = await this.ac.startCalibration(stream, params.gainValues, params.ICalib, params.knownIR, params.microphoneName, params.calibrateSoundCheck, params.isSmartPhone, params.calibrateSoundBurstDb, params.calibrateSoundBurstFilteredExtraDb, params.calibrateSoundBurstLevelReTBool, params.calibrateSoundBurstUses1000HzGainBool, params.calibrateSoundBurstRepeats, params.calibrateSoundBurstSec, params._calibrateSoundBurstPreSec, params._calibrateSoundBurstPostSec, params.calibrateSoundHz, params.calibrateSoundIRSec, params.calibrateSoundIIRSec, params.calibrateSoundIIRPhase, params.calibrateSound1000HzPreSec, params.calibrateSound1000HzSec, params.calibrateSound1000HzPostSec, params.calibrateSoundBackgroundSecs, params.calibrateSoundSmoothOctaves, params.calibrateSoundSmoothMinBandwidthHz, params.calibrateSoundPowerBinDesiredSec, params.calibrateSoundPowerDbSDToleratedDb, params.calibrateSoundTaperSec, params.micManufacturer, params.micSerialNumber, params.micModelNumber, params.micModelName, params.calibrateMicrophonesBool, params.authorEmails, params.webAudioDeviceNames, params.IDsToSaveInSoundProfileLibrary, params.restartButton, params.reminder, params.calibrateSoundLimit, params.calibrateSoundBurstNormalizeBy1000HzGainBool, params.calibrateSoundBurstScalarDB, params.calibrateSound1000HzMaxSD_dB, params._calibrateSoundBurstMaxSD_dB, params.calibrateSoundSamplingDesiredBits, params.language, params.loudspeakerModelName, params.phrases, params.soundSubtitleId);\n clearInterval(permissionCheckInterval);\n _classPrivateFieldGet(_removeUIElems, this).call(this);\n resolve(result);\n } catch (error) {\n clearInterval(permissionCheckInterval);\n reject(error);\n }\n })();\n });\n });\n this.language = (_params$language = _params === null || _params === void 0 ? void 0 : _params.language) !== null && _params$language !== void 0 ? _params$language : 'en-US';\n this.siteUrl += '/listener?';\n this.ac = _CalibratorInstance;\n this.result = null;\n this.debug = (_params$debug = _params === null || _params === void 0 ? void 0 : _params.debug) !== null && _params$debug !== void 0 ? _params$debug : false;\n this.isSmartPhone = (_params$isSmartPhone = _params === null || _params === void 0 ? void 0 : _params.isSmartPhone) !== null && _params$isSmartPhone !== void 0 ? _params$isSmartPhone : false;\n this.calibrateSoundHz = (_params$calibrateSoun = _params === null || _params === void 0 ? void 0 : _params.calibrateSoundHz) !== null && _params$calibrateSoun !== void 0 ? _params$calibrateSoun : 48000;\n this.calibrateSoundSamplingDesiredBits = (_params$calibrateSoun2 = _params === null || _params === void 0 ? void 0 : _params.calibrateSoundSamplingDesiredBits) !== null && _params$calibrateSoun2 !== void 0 ? _params$calibrateSoun2 : 24;\n this.instructionDisplayId = (_params$instructionDi = _params === null || _params === void 0 ? void 0 : _params.instructionDisplayId) !== null && _params$instructionDi !== void 0 ? _params$instructionDi : '';\n this.soundSubtitleId = (_params$soundSubtitle = _params === null || _params === void 0 ? void 0 : _params.soundSubtitleId) !== null && _params$soundSubtitle !== void 0 ? _params$soundSubtitle : '';\n this.timeToCalibrateDisplay = (_params$timeToCalibra = _params === null || _params === void 0 ? void 0 : _params.timeToCalibrateId) !== null && _params$timeToCalibra !== void 0 ? _params$timeToCalibra : '';\n this.soundMessageId = (_params$soundMessageI = _params === null || _params === void 0 ? void 0 : _params.soundMessageId) !== null && _params$soundMessageI !== void 0 ? _params$soundMessageI : '';\n this.titleDisplayId = (_params$titleDisplayI = _params === null || _params === void 0 ? void 0 : _params.titleDisplayId) !== null && _params$titleDisplayI !== void 0 ? _params$titleDisplayI : '';\n this.timeToCalibrate = (_params$timeToCalibra2 = _params === null || _params === void 0 ? void 0 : _params.timeToCalibrate) !== null && _params$timeToCalibra2 !== void 0 ? _params$timeToCalibra2 : 10;\n this.isParticipant = (_params$isParticipant = _params === null || _params === void 0 ? void 0 : _params.isParticipant) !== null && _params$isParticipant !== void 0 ? _params$isParticipant : false;\n this.isLoudspeakerCalibration = (_params$isLoudspeaker = _params === null || _params === void 0 ? void 0 : _params.isLoudspeakerCalibration) !== null && _params$isLoudspeaker !== void 0 ? _params$isLoudspeaker : false;\n this.deviceId = (_params$micrpohoneIdF = _params === null || _params === void 0 ? void 0 : _params.micrpohoneIdFromWebAudioApi) !== null && _params$micrpohoneIdF !== void 0 ? _params$micrpohoneIdF : '';\n this.buttonsContainer = (_params$buttonsContai = _params === null || _params === void 0 ? void 0 : _params.buttonsContainer) !== null && _params$buttonsContai !== void 0 ? _params$buttonsContai : document.createElement('div');\n this.phrases = (_params$phrases = _params === null || _params === void 0 ? void 0 : _params.phrases) !== null && _params$phrases !== void 0 ? _params$phrases : {};\n this.permissionStatus = 'pending';\n\n /* Set up callbacks that handle any events related to our peer object. */\n }\n}\n\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*/\n_Speaker = Speaker;\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 */\n_defineProperty(Speaker, \"startCalibration\", async function (params, CalibratorInstance) {\n let timeOut = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 180000;\n window.speaker = new _Speaker(params, CalibratorInstance);\n const {\n speaker\n } = 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 // Add a permission check handler\n const permissionCheckInterval = setInterval(() => {\n if (speaker.permissionStatus === 'error' || speaker.permissionStatus === 'denied') {\n clearInterval(permissionCheckInterval);\n _classPrivateFieldGet(_removeUIElems, speaker).call(speaker);\n resolve('permission denied');\n }\n }, 100);\n\n // when a call is received\n speaker.peer.on('call', async call => {\n clearInterval(permissionCheckInterval); // Clear interval when call is received\n // Rest of the existing call handling code...\n call.answer();\n _classPrivateFieldGet(_removeUIElems, speaker).call(speaker);\n _classPrivateFieldGet(_showSpinner, speaker).call(speaker);\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_9__.sleep)(1);\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(stream, params.gainValues, params.ICalib, params.knownIR, params.microphoneName, params.calibrateSoundCheck, params.isSmartPhone, params.calibrateSoundBurstDb, params.calibrateSoundBurstFilteredExtraDb, params.calibrateSoundBurstLevelReTBool, params.calibrateSoundBurstUses1000HzGainBool, params.calibrateSoundBurstRepeats, params.calibrateSoundBurstSec, params._calibrateSoundBurstPreSec, params._calibrateSoundBurstPostSec, params.calibrateSoundHz, params.calibrateSoundIRSec, params.calibrateSoundIIRSec, params.calibrateSoundIIRPhase, params.calibrateSound1000HzPreSec, params.calibrateSound1000HzSec, params.calibrateSound1000HzPostSec, params.calibrateSoundBackgroundSecs, params.calibrateSoundSmoothOctaves, params.calibrateSoundSmoothMinBandwidthHz, params.calibrateSoundPowerBinDesiredSec, params.calibrateSoundPowerDbSDToleratedDb, params.calibrateSoundTaperSec, params.micManufacturer, params.micSerialNumber, params.micModelNumber, params.micModelName, params.calibrateMicrophonesBool, params.authorEmails, params.webAudioDeviceNames, params.IDsToSaveInSoundProfileLibrary, params.restartButton, params.reminder, params.calibrateSoundLimit, params.calibrateSoundBurstNormalizeBy1000HzGainBool, params.calibrateSoundBurstScalarDB, params.calibrateSound1000HzMaxSD_dB, params._calibrateSoundBurstMaxSD_dB, params.calibrateSoundSamplingDesiredBits, params.language, params.loudspeakerModelName, params.phrases, params.soundSubtitleId);\n _classPrivateFieldGet(_removeUIElems, speaker).call(speaker);\n resolve(speaker.result);\n });\n // if we do not receive a result within the timeout, reject\n setTimeout(() => {\n clearInterval(permissionCheckInterval);\n reject(new _peerErrors__WEBPACK_IMPORTED_MODULE_10__.CalibrationTimedOutError(\"Calibration failed to produce a result after \".concat(timeOut / 1000, \" seconds. Try increasing \\\"_timeoutSec\\\", which is currently \").concat(timeOut / 1000, \" seconds.\")));\n }, timeOut);\n });\n });\n});\n_defineProperty(Speaker, \"testIIR\", async function (params, CalibratorInstance, IIR) {\n let timeOut = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 180000;\n window.speaker = new _Speaker(params, CalibratorInstance);\n const {\n speaker\n } = 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 _classPrivateFieldGet(_removeUIElems, speaker).call(speaker);\n _classPrivateFieldGet(_showSpinner, speaker).call(speaker);\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_9__.sleep)(1);\n }\n // resolve when we have a result\n speaker.result = await speaker.ac.playMLSwithIIR(stream, IIR);\n _classPrivateFieldGet(_removeUIElems, speaker).call(speaker);\n resolve(speaker.result);\n });\n // if we do not receive a result within the timeout, reject\n setTimeout(() => {\n reject(new _peerErrors__WEBPACK_IMPORTED_MODULE_10__.CalibrationTimedOutError(\"Calibration failed to produce a result after \".concat(timeOut / 1000, \" seconds. Try increasing \\\"_timeoutSec\\\", which is currently \").concat(timeOut / 1000, \" seconds.\")));\n }, timeOut);\n });\n });\n});\n_defineProperty(Speaker, \"closeConnection\", () => {\n _Speaker.conn = null;\n console.log('Connection destroyed');\n});\n/* harmony default export */ __webpack_exports__[\"default\"] = (Speaker);\n\n//# sourceURL=webpack://speakerCalibrator/./src/peer-connection/speaker.js?");
|
|
128
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_array_buffer_slice_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array-buffer.slice.js */ \"./node_modules/core-js/modules/es.array-buffer.slice.js\");\n/* harmony import */ var core_js_modules_es_array_buffer_slice_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_buffer_slice_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_es_string_replace_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/es.string.replace.js */ \"./node_modules/core-js/modules/es.string.replace.js\");\n/* harmony import */ var core_js_modules_es_string_replace_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_string_replace_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_es_typed_array_uint8_array_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/es.typed-array.uint8-array.js */ \"./node_modules/core-js/modules/es.typed-array.uint8-array.js\");\n/* harmony import */ var core_js_modules_es_typed_array_uint8_array_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_typed_array_uint8_array_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var core_js_modules_es_typed_array_fill_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! core-js/modules/es.typed-array.fill.js */ \"./node_modules/core-js/modules/es.typed-array.fill.js\");\n/* harmony import */ var core_js_modules_es_typed_array_fill_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_typed_array_fill_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var core_js_modules_es_typed_array_set_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! core-js/modules/es.typed-array.set.js */ \"./node_modules/core-js/modules/es.typed-array.set.js\");\n/* harmony import */ var core_js_modules_es_typed_array_set_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_typed_array_set_js__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var core_js_modules_es_typed_array_sort_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! core-js/modules/es.typed-array.sort.js */ \"./node_modules/core-js/modules/es.typed-array.sort.js\");\n/* harmony import */ var core_js_modules_es_typed_array_sort_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_typed_array_sort_js__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! core-js/modules/web.dom-collections.iterator.js */ \"./node_modules/core-js/modules/web.dom-collections.iterator.js\");\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_6__);\n/* harmony import */ var qrcode__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! qrcode */ \"./node_modules/qrcode/lib/browser.js\");\n/* harmony import */ var _audioPeer__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./audioPeer */ \"./src/peer-connection/audioPeer.js\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../utils */ \"./src/utils.js\");\n/* harmony import */ var _peerErrors__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./peerErrors */ \"./src/peer-connection/peerErrors.js\");\n/* harmony import */ var peerjs__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! peerjs */ \"./node_modules/peerjs/dist/bundler.mjs\");\nvar _Speaker;\n\n\n\n\n\n\n\nfunction _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }\nfunction _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError(\"Cannot initialize the same private elements twice on an object\"); }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }\nfunction _assertClassBrand(e, t, n) { if (\"function\" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError(\"Private element is not present on this object\"); }\n\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 */\nvar _showQRCode = /*#__PURE__*/new WeakMap();\nvar _showSpinner = /*#__PURE__*/new WeakMap();\nvar _removeUIElems = /*#__PURE__*/new WeakMap();\nvar _onPeerOpen = /*#__PURE__*/new WeakMap();\nvar _onPeerConnection = /*#__PURE__*/new WeakMap();\nvar _onPeerDisconnected = /*#__PURE__*/new WeakMap();\nvar _onPeerError = /*#__PURE__*/new WeakMap();\nvar _onIncomingData = /*#__PURE__*/new WeakMap();\nvar _ready = /*#__PURE__*/new WeakMap();\nclass Speaker extends _audioPeer__WEBPACK_IMPORTED_MODULE_8__[\"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 var _params$language, _params$debug, _params$isSmartPhone, _params$calibrateSoun, _params$calibrateSoun2, _params$instructionDi, _params$soundSubtitle, _params$timeToCalibra, _params$soundMessageI, _params$titleDisplayI, _params$timeToCalibra2, _params$isParticipant, _params$isLoudspeaker, _params$micrpohoneIdF, _params$buttonsContai, _params$phrases;\n super(_params);\n _defineProperty(this, \"uri\", '');\n _defineProperty(this, \"qrImage\", void 0);\n _defineProperty(this, \"shortURL\", void 0);\n _defineProperty(this, \"initPeer\", async () => {\n const id = await this.generateTimeBasedPeerID();\n this.peer = new peerjs__WEBPACK_IMPORTED_MODULE_11__[\"default\"](id, {\n secure: true,\n host: 'easyeyes-peer-server.herokuapp.com',\n port: 443,\n config: {\n iceServers: [{\n urls: 'stun:stun.relay.metered.ca:80'\n }, {\n urls: 'turn:global.relay.metered.ca:80',\n username: 'de884cfc34189cdf1a5dd616',\n credential: 'IcOpouU9/TYBmpHU'\n }, {\n urls: 'turn:global.relay.metered.ca:80?transport=tcp',\n username: 'de884cfc34189cdf1a5dd616',\n credential: 'IcOpouU9/TYBmpHU'\n }, {\n urls: 'turn:global.relay.metered.ca:443',\n username: 'de884cfc34189cdf1a5dd616',\n credential: 'IcOpouU9/TYBmpHU'\n }, {\n urls: 'turns:global.relay.metered.ca:443?transport=tcp',\n username: 'de884cfc34189cdf1a5dd616',\n credential: 'IcOpouU9/TYBmpHU'\n }]\n }\n });\n this.peer.on('open', _classPrivateFieldGet(_onPeerOpen, this));\n this.peer.on('connection', _classPrivateFieldGet(_onPeerConnection, this));\n this.peer.on('close', this.onPeerClose);\n this.peer.on('disconnected', _classPrivateFieldGet(_onPeerDisconnected, this));\n this.peer.on('error', _classPrivateFieldGet(_onPeerError, this));\n });\n _defineProperty(this, \"generateTimeBasedPeerID\", async () => {\n const now = new Date().getTime();\n const randomBuffer = new Uint8Array(10);\n crypto.getRandomValues(randomBuffer);\n const randomPart = Array.from(randomBuffer).map(b => b.toString(36)).join('');\n const toHash = \"\".concat(now, \"-\").concat(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 _defineProperty(this, \"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 * 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 _classPrivateFieldInitSpec(this, _showQRCode, async () => {\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 // Generate QR code\n const qrCanvas = document.createElement('canvas');\n qrCanvas.setAttribute('id', 'qrCanvas');\n qrcode__WEBPACK_IMPORTED_MODULE_7__.toCanvas(qrCanvas, this.uri, error => {\n if (error) console.error(error);\n });\n\n // Create QR image\n const qrImage = new Image();\n qrImage.setAttribute('id', 'compatibilityCheckQRImage');\n qrImage.style.zIndex = Infinity;\n qrImage.style.height = '150px';\n qrImage.style.width = '150px';\n qrImage.style.margin = '-10px';\n qrImage.style.aspectRatio = 1;\n qrImage.src = qrCanvas.toDataURL();\n this.qrImage = qrImage;\n\n // Get shortened URL\n let shortURL = this.uri;\n try {\n const response = await fetch('https://api.short.io/links/public', {\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',\n originalURL: this.uri\n })\n });\n if (!response.ok) {\n throw new Error(\"HTTP error! Status: \".concat(response.status));\n }\n const data = await response.json();\n shortURL = data.shortURL;\n } catch (error) {\n console.error('Error:', error.message);\n }\n\n // Main container with 3 columns\n const container = document.createElement('div');\n container.style.display = 'flex';\n container.style.alignItems = 'flex-start';\n container.style.paddingTop = '0';\n container.id = 'skipQRContainer';\n\n // Column 1: QR Code\n const qrColumn = document.createElement('div');\n qrColumn.style.flex = '0 0 auto';\n qrColumn.appendChild(qrImage);\n\n // Column 2: Explanation Text\n const textColumn = document.createElement('div');\n textColumn.style.flex = '1';\n textColumn.style.padding = '0 20px';\n textColumn.style.maxWidth = '560px';\n const explanation = document.createElement('h2');\n explanation.style.fontSize = '1.1rem';\n explanation.id = 'skipQRExplanation';\n explanation.style.margin = '0';\n explanation.style.textAlign = 'left';\n explanation.innerHTML = (0,_utils__WEBPACK_IMPORTED_MODULE_9__.formatLineBreak)(this.phrases.RC_skipQR_ExplanationWithoutPreferNot[this.language].replace('xxx', \"<b style=\\\"user-select: text\\\">\".concat(shortURL, \"</b>\")).replace('XXX', \"<b style=\\\"user-select: text\\\">\".concat(shortURL, \"</b>\")), this.phrases.RC_checkInternetConnection[this.language]);\n const language = this.language;\n const phrases = this.phrases;\n const checkConnection = document.createElement('a');\n checkConnection.id = 'check-connection';\n checkConnection.href = '#';\n checkConnection.innerHTML = \"check the phone's internet connection\";\n checkConnection.addEventListener('click', function (event) {\n event.preventDefault();\n (0,_utils__WEBPACK_IMPORTED_MODULE_9__.createAndShowPopup)(language, phrases);\n });\n explanation.querySelector('a#check-connection').replaceWith(checkConnection);\n textColumn.appendChild(explanation);\n\n // Column 3: Buttons\n const buttonColumn = document.createElement('div');\n buttonColumn.style.display = 'flex';\n buttonColumn.style.flexDirection = 'column';\n buttonColumn.style.gap = '10px';\n buttonColumn.style.flex = '0 0 auto';\n buttonColumn.style.alignItems = 'flex-end';\n buttonColumn.appendChild(this.buttonsContainer);\n\n // Assemble the columns\n container.appendChild(qrColumn);\n container.appendChild(textColumn);\n container.appendChild(buttonColumn);\n document.getElementById(this.targetElement).appendChild(container);\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 _classPrivateFieldInitSpec(this, _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 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 _classPrivateFieldInitSpec(this, _removeUIElems, () => {\n const parent = document.getElementById(this.targetElement);\n while (parent.firstChild) {\n parent.firstChild.remove();\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 _classPrivateFieldInitSpec(this, _onPeerOpen, id => {\n // Workaround for peer.reconnect deleting previous id\n try {\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 if (id !== this.peer.id) {\n console.warn('DEBUG Check you assumption that id === this.peer.id');\n }\n } catch (error) {\n console.error('Error in #onPeerOpen: ', error);\n }\n _classPrivateFieldGet(_showQRCode, this).call(this);\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 _classPrivateFieldInitSpec(this, _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 this.conn = connection;\n console.log('Connected to: ', this.conn.peer);\n _classPrivateFieldGet(_ready, this).call(this);\n });\n /**\n * Called when the peer connection is closed.\n *\n * @private\n * @example\n */\n _defineProperty(this, \"onPeerClose\", () => {\n this.conn = null;\n console.log('Connection destroyed');\n });\n /**\n * Called when the peer connection is disconnected.\n * Attempts to reconnect.\n *\n * @private\n * @example\n */\n _classPrivateFieldInitSpec(this, _onPeerDisconnected, () => {\n console.log('Connection lost. Please reconnect');\n try {\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 } catch (error) {\n console.error('Error in #onPeerDisconnected: ', error);\n }\n });\n /**\n * Called when the peer connection encounters an error.\n *\n * @param error\n * @private\n * @example\n */\n _classPrivateFieldInitSpec(this, _onPeerError, error => {\n // TODO: check if this function is needed or not\n console.error(error);\n });\n /**\n * Called when data is received from the peer connection.\n *\n * @param data\n * @private\n * @example\n */\n _classPrivateFieldInitSpec(this, _onIncomingData, data => {\n // enforce object type\n if (!Object.prototype.hasOwnProperty.call(data, 'name') || !Object.prototype.hasOwnProperty.call(data, 'payload')) {\n console.error('Received malformed data: ', data);\n return;\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 'permissionStatus':\n console.log('Received permission status from listener: ', data.payload);\n if (data.payload.type === 'error') {\n this.permissionStatus = 'error';\n this.ac.setPermissionStatus('error');\n } else if (data.payload.type === 'denied') {\n this.permissionStatus = 'denied';\n this.ac.setPermissionStatus('denied');\n } else if (data.payload.type === 'granted') {\n this.permissionStatus = 'granted';\n this.ac.setPermissionStatus('granted');\n console.log('Permission granted');\n }\n break;\n case _peerErrors__WEBPACK_IMPORTED_MODULE_10__.UnsupportedDeviceError.name:\n case _peerErrors__WEBPACK_IMPORTED_MODULE_10__.MissingSpeakerIdError.name:\n throw data.payload;\n break;\n default:\n break;\n }\n });\n /**\n * Called when the peer connection is #ready.\n *\n * @private\n * @example\n */\n _classPrivateFieldInitSpec(this, _ready, () => {\n // Perform callback with data\n this.conn.on('data', _classPrivateFieldGet(_onIncomingData, this));\n this.conn.on('close', () => {\n console.log('Connection reset<br>Awaiting connection...');\n this.conn = null;\n });\n });\n /** .\n * .\n * .\n * Debug method for downloading the recorded audio\n *\n * @public\n * @example\n */\n _defineProperty(this, \"downloadData\", () => {\n this.ac.downloadData();\n });\n _defineProperty(this, \"repeatCalibration\", async (params, stream, CalibratorInstance) => {\n this.ac = CalibratorInstance;\n _classPrivateFieldGet(_removeUIElems, this).call(this);\n _classPrivateFieldGet(_showSpinner, this).call(this);\n console.log('This is a repeat');\n // wrap the calibration process in a promise so we can await it\n return new Promise((resolve, reject) => {\n // Add a permission check handler\n const permissionCheckInterval = setInterval(() => {\n if (this.permissionStatus === 'error' || this.permissionStatus === 'denied') {\n clearInterval(permissionCheckInterval);\n _classPrivateFieldGet(_removeUIElems, this).call(this);\n resolve('permission denied');\n }\n }, 100);\n\n // Start calibration process\n (async () => {\n try {\n const result = await this.ac.startCalibration(stream, params.gainValues, params.ICalib, params.knownIR, params.microphoneName, params.calibrateSoundCheck, params.isSmartPhone, params.calibrateSoundBurstDb, params.calibrateSoundBurstFilteredExtraDb, params.calibrateSoundBurstLevelReTBool, params.calibrateSoundBurstUses1000HzGainBool, params.calibrateSoundBurstRepeats, params.calibrateSoundBurstSec, params._calibrateSoundBurstPreSec, params._calibrateSoundBurstPostSec, params.calibrateSoundHz, params.calibrateSoundIRSec, params.calibrateSoundIIRSec, params.calibrateSoundIIRPhase, params.calibrateSound1000HzPreSec, params.calibrateSound1000HzSec, params.calibrateSound1000HzPostSec, params.calibrateSoundBackgroundSecs, params.calibrateSoundSmoothOctaves, params.calibrateSoundSmoothMinBandwidthHz, params.calibrateSoundPowerBinDesiredSec, params.calibrateSoundPowerDbSDToleratedDb, params.calibrateSoundTaperSec, params.micManufacturer, params.micSerialNumber, params.micModelNumber, params.micModelName, params.calibrateMicrophonesBool, params.authorEmails, params.webAudioDeviceNames, params.IDsToSaveInSoundProfileLibrary, params.restartButton, params.reminder, params.calibrateSoundLimit, params.calibrateSoundBurstNormalizeBy1000HzGainBool, params.calibrateSoundBurstScalarDB, params.calibrateSound1000HzMaxSD_dB, params.calibrateSound1000HzMaxTries, params._calibrateSoundBurstMaxSD_dB, params.calibrateSoundSamplingDesiredBits, params.language, params.loudspeakerModelName, params.phrases, params.soundSubtitleId);\n clearInterval(permissionCheckInterval);\n _classPrivateFieldGet(_removeUIElems, this).call(this);\n resolve(result);\n } catch (error) {\n clearInterval(permissionCheckInterval);\n reject(error);\n }\n })();\n });\n });\n this.language = (_params$language = _params === null || _params === void 0 ? void 0 : _params.language) !== null && _params$language !== void 0 ? _params$language : 'en-US';\n this.siteUrl += '/listener?';\n this.ac = _CalibratorInstance;\n this.result = null;\n this.debug = (_params$debug = _params === null || _params === void 0 ? void 0 : _params.debug) !== null && _params$debug !== void 0 ? _params$debug : false;\n this.isSmartPhone = (_params$isSmartPhone = _params === null || _params === void 0 ? void 0 : _params.isSmartPhone) !== null && _params$isSmartPhone !== void 0 ? _params$isSmartPhone : false;\n this.calibrateSoundHz = (_params$calibrateSoun = _params === null || _params === void 0 ? void 0 : _params.calibrateSoundHz) !== null && _params$calibrateSoun !== void 0 ? _params$calibrateSoun : 48000;\n this.calibrateSoundSamplingDesiredBits = (_params$calibrateSoun2 = _params === null || _params === void 0 ? void 0 : _params.calibrateSoundSamplingDesiredBits) !== null && _params$calibrateSoun2 !== void 0 ? _params$calibrateSoun2 : 24;\n this.instructionDisplayId = (_params$instructionDi = _params === null || _params === void 0 ? void 0 : _params.instructionDisplayId) !== null && _params$instructionDi !== void 0 ? _params$instructionDi : '';\n this.soundSubtitleId = (_params$soundSubtitle = _params === null || _params === void 0 ? void 0 : _params.soundSubtitleId) !== null && _params$soundSubtitle !== void 0 ? _params$soundSubtitle : '';\n this.timeToCalibrateDisplay = (_params$timeToCalibra = _params === null || _params === void 0 ? void 0 : _params.timeToCalibrateId) !== null && _params$timeToCalibra !== void 0 ? _params$timeToCalibra : '';\n this.soundMessageId = (_params$soundMessageI = _params === null || _params === void 0 ? void 0 : _params.soundMessageId) !== null && _params$soundMessageI !== void 0 ? _params$soundMessageI : '';\n this.titleDisplayId = (_params$titleDisplayI = _params === null || _params === void 0 ? void 0 : _params.titleDisplayId) !== null && _params$titleDisplayI !== void 0 ? _params$titleDisplayI : '';\n this.timeToCalibrate = (_params$timeToCalibra2 = _params === null || _params === void 0 ? void 0 : _params.timeToCalibrate) !== null && _params$timeToCalibra2 !== void 0 ? _params$timeToCalibra2 : 10;\n this.isParticipant = (_params$isParticipant = _params === null || _params === void 0 ? void 0 : _params.isParticipant) !== null && _params$isParticipant !== void 0 ? _params$isParticipant : false;\n this.isLoudspeakerCalibration = (_params$isLoudspeaker = _params === null || _params === void 0 ? void 0 : _params.isLoudspeakerCalibration) !== null && _params$isLoudspeaker !== void 0 ? _params$isLoudspeaker : false;\n this.deviceId = (_params$micrpohoneIdF = _params === null || _params === void 0 ? void 0 : _params.micrpohoneIdFromWebAudioApi) !== null && _params$micrpohoneIdF !== void 0 ? _params$micrpohoneIdF : '';\n this.buttonsContainer = (_params$buttonsContai = _params === null || _params === void 0 ? void 0 : _params.buttonsContainer) !== null && _params$buttonsContai !== void 0 ? _params$buttonsContai : document.createElement('div');\n this.phrases = (_params$phrases = _params === null || _params === void 0 ? void 0 : _params.phrases) !== null && _params$phrases !== void 0 ? _params$phrases : {};\n this.permissionStatus = 'pending';\n\n /* Set up callbacks that handle any events related to our peer object. */\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_Speaker = Speaker;\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_defineProperty(Speaker, \"startCalibration\", async function (params, CalibratorInstance) {\n let timeOut = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 180000;\n window.speaker = new _Speaker(params, CalibratorInstance);\n const {\n speaker\n } = 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 // Add a permission check handler\n const permissionCheckInterval = setInterval(() => {\n if (speaker.permissionStatus === 'error' || speaker.permissionStatus === 'denied') {\n clearInterval(permissionCheckInterval);\n _classPrivateFieldGet(_removeUIElems, speaker).call(speaker);\n resolve('permission denied');\n }\n }, 100);\n\n // when a call is received\n speaker.peer.on('call', async call => {\n clearInterval(permissionCheckInterval); // Clear interval when call is received\n // Rest of the existing call handling code...\n call.answer();\n _classPrivateFieldGet(_removeUIElems, speaker).call(speaker);\n _classPrivateFieldGet(_showSpinner, speaker).call(speaker);\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_9__.sleep)(1);\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(stream, params.gainValues, params.ICalib, params.knownIR, params.microphoneName, params.calibrateSoundCheck, params.isSmartPhone, params.calibrateSoundBurstDb, params.calibrateSoundBurstFilteredExtraDb, params.calibrateSoundBurstLevelReTBool, params.calibrateSoundBurstUses1000HzGainBool, params.calibrateSoundBurstRepeats, params.calibrateSoundBurstSec, params._calibrateSoundBurstPreSec, params._calibrateSoundBurstPostSec, params.calibrateSoundHz, params.calibrateSoundIRSec, params.calibrateSoundIIRSec, params.calibrateSoundIIRPhase, params.calibrateSound1000HzPreSec, params.calibrateSound1000HzSec, params.calibrateSound1000HzPostSec, params.calibrateSoundBackgroundSecs, params.calibrateSoundSmoothOctaves, params.calibrateSoundSmoothMinBandwidthHz, params.calibrateSoundPowerBinDesiredSec, params.calibrateSoundPowerDbSDToleratedDb, params.calibrateSoundTaperSec, params.micManufacturer, params.micSerialNumber, params.micModelNumber, params.micModelName, params.calibrateMicrophonesBool, params.authorEmails, params.webAudioDeviceNames, params.IDsToSaveInSoundProfileLibrary, params.restartButton, params.reminder, params.calibrateSoundLimit, params.calibrateSoundBurstNormalizeBy1000HzGainBool, params.calibrateSoundBurstScalarDB, params.calibrateSound1000HzMaxSD_dB, params.calibrateSound1000HzMaxTries, params._calibrateSoundBurstMaxSD_dB, params.calibrateSoundSamplingDesiredBits, params.language, params.loudspeakerModelName, params.phrases, params.soundSubtitleId);\n _classPrivateFieldGet(_removeUIElems, speaker).call(speaker);\n resolve(speaker.result);\n });\n // if we do not receive a result within the timeout, reject\n setTimeout(() => {\n clearInterval(permissionCheckInterval);\n reject(new _peerErrors__WEBPACK_IMPORTED_MODULE_10__.CalibrationTimedOutError(\"Calibration failed to produce a result after \".concat(timeOut / 1000, \" seconds. Try increasing \\\"_timeoutSec\\\", which is currently \").concat(timeOut / 1000, \" seconds.\")));\n }, timeOut);\n });\n });\n});\n_defineProperty(Speaker, \"testIIR\", async function (params, CalibratorInstance, IIR) {\n let timeOut = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 180000;\n window.speaker = new _Speaker(params, CalibratorInstance);\n const {\n speaker\n } = 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 _classPrivateFieldGet(_removeUIElems, speaker).call(speaker);\n _classPrivateFieldGet(_showSpinner, speaker).call(speaker);\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_9__.sleep)(1);\n }\n // resolve when we have a result\n speaker.result = await speaker.ac.playMLSwithIIR(stream, IIR);\n _classPrivateFieldGet(_removeUIElems, speaker).call(speaker);\n resolve(speaker.result);\n });\n // if we do not receive a result within the timeout, reject\n setTimeout(() => {\n reject(new _peerErrors__WEBPACK_IMPORTED_MODULE_10__.CalibrationTimedOutError(\"Calibration failed to produce a result after \".concat(timeOut / 1000, \" seconds. Try increasing \\\"_timeoutSec\\\", which is currently \").concat(timeOut / 1000, \" seconds.\")));\n }, timeOut);\n });\n });\n});\n_defineProperty(Speaker, \"closeConnection\", () => {\n _Speaker.conn = null;\n console.log('Connection destroyed');\n});\n/* harmony default export */ __webpack_exports__[\"default\"] = (Speaker);\n\n//# sourceURL=webpack://speakerCalibrator/./src/peer-connection/speaker.js?");
|
|
129
129
|
|
|
130
130
|
/***/ }),
|
|
131
131
|
|
|
@@ -147,7 +147,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
147
147
|
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
148
148
|
|
|
149
149
|
"use strict";
|
|
150
|
-
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\");\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n/**\r\n *\r\n */\nclass PythonServerAPI {\n constructor() {\n // static PYTHON_SERVER_URL ='http://127.0.0.1:5000';\n /** @private */\n _defineProperty(this, \"MAX_RETRY_COUNT\", 3);\n /** @private */\n _defineProperty(this, \"RETRY_DELAY_MS\", 1000);\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 */\n _defineProperty(this, \"getImpulseResponse\", async _ref => {\n let {\n mls,\n sampleRate,\n numPeriods,\n sig,\n fs2,\n L_new_n,\n dL_n\n } = _ref;\n const task = 'impulse-response';\n let res = null;\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 await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: \"/task/\".concat(task),\n headers: {\n 'Content-Type': 'application/json'\n },\n data\n }).then(response => {\n res = response;\n }).catch(error => {\n throw error;\n });\n return res.data[task];\n });\n _defineProperty(this, \"getAutocorrelation\", async _ref2 => {\n let {\n mls,\n payload,\n sampleRate,\n numPeriods\n } = _ref2;\n const task = 'autocorrelation';\n let res = null;\n const data = JSON.stringify({\n task,\n 'payload': payload,\n 'sample-rate': sampleRate,\n mls,\n numPeriods\n });\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: \"/task/\".concat(task),\n headers: {\n 'Content-Type': 'application/json'\n },\n data\n }).then(response => {\n res = response;\n }).catch(error => {\n throw error;\n });\n return res.data[task];\n });\n _defineProperty(this, \"getConvolution\", async _ref3 => {\n let {\n mls,\n inverse_response,\n inverse_response_no_bandpass,\n attenuatorGain_dB,\n mls_amplitude\n } = _ref3;\n const task = 'convolution';\n let res = null;\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 await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: \"/task/\".concat(task),\n headers: {\n 'Content-Type': 'application/json'\n },\n data\n }).then(response => {\n res = response;\n }).catch(error => {\n throw error;\n });\n return res.data[task];\n });\n _defineProperty(this, \"getMLS\", async _ref4 => {\n let {\n length,\n amplitude,\n calibrateSoundBurstMLSVersions\n } = _ref4;\n const task = 'mls';\n let res = null;\n const data = JSON.stringify({\n task,\n length: length,\n amplitude: amplitude,\n calibrateSoundBurstMLSVersions: calibrateSoundBurstMLSVersions\n });\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: \"/task/\".concat(task),\n headers: {\n 'Content-Type': 'application/json'\n },\n data\n }).then(response => {\n res = response;\n }).catch(error => {\n throw error;\n });\n return res.data[task];\n });\n _defineProperty(this, \"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 console.log(data);\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: \"/task/\".concat(task),\n headers: {\n 'Content-Type': 'application/json'\n },\n data\n }).then(response => {\n res = response;\n console.log(res.data[task]);\n }).catch(error => {\n throw error;\n });\n return res.data[task];\n });\n _defineProperty(this, \"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 }).then(response => {\n console.log(\"memory used:\", Math.round(response.data['memory']), \"mb\");\n res = response.data['memory'];\n }).catch(error => {\n throw error;\n });\n return res;\n });\n _defineProperty(this, \"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 _defineProperty(this, \"getMLSWithRetry\", async _ref5 => {\n let {\n length,\n amplitude,\n calibrateSoundBurstMLSVersions\n } = _ref5;\n let retryCount = 0;\n let response = null;\n while (retryCount < this.MAX_RETRY_COUNT) {\n try {\n response = await this.getMLS({\n length,\n amplitude,\n calibrateSoundBurstMLSVersions\n });\n // If the request is successful, break out of the loop\n break;\n } catch (error) {\n console.error(\"Error occurred. Retrying... (\".concat(retryCount + 1, \"/\").concat(this.MAX_RETRY_COUNT, \")\"));\n retryCount++;\n await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS));\n }\n }\n if (response) {\n return response;\n } else {\n throw new Error(\"Failed to get MLS after \".concat(this.MAX_RETRY_COUNT, \" attempts.\"));\n }\n });\n _defineProperty(this, \"getPSD\", async _ref6 => {\n let {\n unconv_rec,\n conv_rec,\n sampleRate\n } = _ref6;\n const task = 'psd';\n let res = null;\n const data = JSON.stringify({\n task,\n unconv_rec,\n conv_rec,\n sampleRate\n });\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: \"/task/\".concat(task),\n headers: {\n 'Content-Type': 'application/json'\n },\n data\n }).then(response => {\n res = response;\n }).catch(error => {\n throw error;\n });\n return res.data[task];\n });\n _defineProperty(this, \"getBackgroundNoisePSD\", async _ref7 => {\n let {\n background_rec,\n sampleRate\n } = _ref7;\n const task = 'background-psd';\n let res = null;\n const data = JSON.stringify({\n task,\n background_rec,\n sampleRate\n });\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: \"/task/\".concat(task),\n headers: {\n 'Content-Type': 'application/json'\n },\n data\n }).then(response => {\n res = response;\n }).catch(error => {\n throw error;\n });\n return res.data[task];\n });\n _defineProperty(this, \"getBackgroundNoisePSDWithRetry\", async _ref8 => {\n let {\n background_rec,\n sampleRate\n } = _ref8;\n let retryCount = 0;\n let response = null;\n while (retryCount < this.MAX_RETRY_COUNT) {\n try {\n response = await this.getBackgroundNoisePSD({\n background_rec,\n sampleRate\n });\n // If the request is successful, break out of the loop\n break;\n } catch (error) {\n console.error(\"Error occurred. Retrying... (\".concat(retryCount + 1, \"/\").concat(this.MAX_RETRY_COUNT, \")\"));\n retryCount++;\n await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS));\n }\n }\n if (response) {\n return response;\n } else {\n throw new Error(\"Failed to get PSD after \".concat(this.MAX_RETRY_COUNT, \" attempts.\"));\n }\n });\n _defineProperty(this, \"getSubtractedPSD\", async (rec, knownGains, knownFrequencies, sampleRate) => {\n const task = 'subtracted-psd';\n let res = null;\n const data = JSON.stringify({\n task,\n rec,\n knownGains,\n knownFrequencies,\n sampleRate\n });\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: \"/task/\".concat(task),\n headers: {\n 'Content-Type': 'application/json'\n },\n data\n }).then(response => {\n res = response;\n }).catch(error => {\n throw error;\n });\n return res.data[task];\n });\n _defineProperty(this, \"getSubtractedPSDWithRetry\", async (rec, knownGains, knownFrequencies, sampleRate) => {\n let retryCount = 0;\n let response = null;\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... (\".concat(retryCount + 1, \"/\").concat(this.MAX_RETRY_COUNT, \")\"));\n retryCount++;\n await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS));\n }\n }\n if (response) {\n return response;\n } else {\n throw new Error(\"Failed to get PSD after \".concat(this.MAX_RETRY_COUNT, \" attempts.\"));\n }\n });\n _defineProperty(this, \"getPSDWithRetry\", async _ref9 => {\n let {\n unconv_rec,\n conv_rec,\n sampleRate\n } = _ref9;\n let retryCount = 0;\n let response = null;\n while (retryCount < this.MAX_RETRY_COUNT) {\n try {\n response = await this.getPSD({\n unconv_rec,\n conv_rec,\n sampleRate\n });\n // If the request is successful, break out of the loop\n break;\n } catch (error) {\n console.error(\"Error occurred. Retrying... (\".concat(retryCount + 1, \"/\").concat(this.MAX_RETRY_COUNT, \")\"));\n retryCount++;\n await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS));\n }\n }\n if (response) {\n return response;\n } else {\n throw new Error(\"Failed to get PSD after \".concat(this.MAX_RETRY_COUNT, \" attempts.\"));\n }\n });\n _defineProperty(this, \"getComponentInverseImpulseResponse\", async _ref10 => {\n let {\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 } = _ref10;\n const task = 'component-inverse-impulse-response';\n let res = null;\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 await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: \"/task/\".concat(task),\n headers: {\n 'Content-Type': 'application/json'\n },\n data\n }).then(response => {\n res = response;\n }).catch(error => {\n throw error;\n });\n return res.data[task];\n });\n _defineProperty(this, \"getSystemInverseImpulseResponse\", async _ref11 => {\n let {\n payload,\n mls,\n lowHz,\n highHz,\n iirLength,\n sampleRate,\n mlsAmplitude,\n calibrateSoundBurstFilteredExtraDb,\n calibrateSoundIIRPhase\n } = _ref11;\n const task = 'system-inverse-impulse-response';\n let res = null;\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 await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: \"/task/\".concat(task),\n headers: {\n 'Content-Type': 'application/json'\n },\n data\n }).then(response => {\n res = response;\n }).catch(error => {\n throw error;\n });\n return res.data[task];\n });\n _defineProperty(this, \"getMLSPSD\", async _ref12 => {\n let {\n mls,\n sampleRate\n } = _ref12;\n const task = 'mls-psd';\n let res = null;\n const data = JSON.stringify({\n task,\n mls,\n sampleRate\n });\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: \"/task/\".concat(task),\n headers: {\n 'Content-Type': 'application/json'\n },\n data\n }).then(response => {\n res = response;\n }).catch(error => {\n throw error;\n });\n return res.data[task];\n });\n _defineProperty(this, \"getMLSPSDWithRetry\", async _ref13 => {\n let {\n mls,\n sampleRate\n } = _ref13;\n let retryCount = 0;\n let response = null;\n while (retryCount < this.MAX_RETRY_COUNT) {\n try {\n response = await this.getMLSPSD({\n mls,\n sampleRate\n });\n // If the request is successful, break out of the loop\n break;\n } catch (error) {\n console.error(\"Error occurred. Retrying... (\".concat(retryCount + 1, \"/\").concat(this.MAX_RETRY_COUNT, \")\"));\n retryCount++;\n await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS));\n }\n }\n if (response) {\n return response;\n } else {\n throw new Error(\"Failed to get inverse impulse response after \".concat(this.MAX_RETRY_COUNT, \" attempts.\"));\n }\n });\n _defineProperty(this, \"getComponentInverseImpulseResponseWithRetry\", async _ref14 => {\n let {\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 } = _ref14;\n let retryCount = 0;\n let response = null;\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... (\".concat(retryCount + 1, \"/\").concat(this.MAX_RETRY_COUNT, \")\"));\n retryCount++;\n await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS));\n }\n }\n if (response) {\n return response;\n } else {\n throw new Error(\"Failed to get inverse impulse response after \".concat(this.MAX_RETRY_COUNT, \" attempts.\"));\n }\n });\n _defineProperty(this, \"getSystemInverseImpulseResponseWithRetry\", async _ref15 => {\n let {\n payload,\n mls,\n lowHz,\n highHz,\n iirLength,\n sampleRate,\n mlsAmplitude,\n calibrateSoundBurstFilteredExtraDb,\n calibrateSoundIIRPhase\n } = _ref15;\n let retryCount = 0;\n let response = null;\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... (\".concat(retryCount + 1, \"/\").concat(this.MAX_RETRY_COUNT, \")\"));\n retryCount++;\n await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS));\n }\n }\n if (response) {\n return response;\n } else {\n throw new Error(\"Failed to get inverse impulse response after \".concat(this.MAX_RETRY_COUNT, \" attempts.\"));\n }\n });\n _defineProperty(this, \"getVolumeCalibration\", async _ref16 => {\n let {\n payload,\n sampleRate,\n lCalib\n } = _ref16;\n const task = 'volume';\n let res = null;\n console.log({\n payload\n });\n const data = JSON.stringify({\n task,\n payload,\n 'sample-rate': sampleRate,\n lCalib\n });\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: \"/task/\".concat(task),\n headers: {\n 'Content-Type': 'application/json'\n },\n data\n }).then(response => {\n res = response;\n }).catch(error => {\n throw error;\n });\n return res.data[task];\n });\n _defineProperty(this, \"getVolumeCalibrationParameters\", async _ref17 => {\n let {\n inDBValues,\n outDBSPLValues,\n lCalib,\n componentGainDBSPL\n } = _ref17;\n const task = 'volume-parameters';\n let res = null;\n const data = JSON.stringify({\n task,\n inDBValues,\n outDBSPLValues,\n lCalib,\n componentGainDBSPL\n });\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n //server\n url: \"/task/\".concat(task),\n headers: {\n 'Content-Type': 'application/json'\n },\n data\n }).then(response => {\n res = response;\n console.log(res.data[task]);\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 _defineProperty(this, \"allHzPowerCheck\", async _ref18 => {\n let {\n payload,\n sampleRate,\n binDesiredSec,\n burstSec,\n repeats,\n warmUp\n } = _ref18;\n const task = 'all-hz-check';\n let res = null;\n console.log({\n 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 await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n //server\n url: \"/task/\".concat(task),\n headers: {\n 'Content-Type': 'application/json'\n },\n data\n }).then(response => {\n res = response;\n console.log(res.data[task]);\n }).catch(error => {\n throw error;\n });\n return res.data[task];\n });\n _defineProperty(this, \"volumePowerCheck\", async _ref19 => {\n let {\n payload,\n sampleRate,\n preSec,\n Sec,\n binDesiredSec\n } = _ref19;\n const task = 'volume-check';\n let res = null;\n const data = JSON.stringify({\n payload,\n sampleRate,\n preSec,\n Sec,\n binDesiredSec\n });\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n //server\n url: \"/task/\".concat(task),\n headers: {\n 'Content-Type': 'application/json'\n },\n data\n }).then(response => {\n res = response;\n console.log(res.data[task]);\n }).catch(error => {\n throw error;\n });\n return res.data[task];\n });\n _defineProperty(this, \"volumePowerCheckWithRetry\", async _ref20 => {\n let {\n payload,\n sampleRate,\n preSec,\n Sec,\n binDesiredSec\n } = _ref20;\n let retryCount = 0;\n let response = null;\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 });\n // If the request is successful, break out of the loop\n break;\n } catch (error) {\n console.error(\"Error occurred. Retrying... (\".concat(retryCount + 1, \"/\").concat(this.MAX_RETRY_COUNT, \")\"));\n retryCount++;\n await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS));\n }\n }\n if (response) {\n return response;\n } else {\n throw new Error(\"Failed to get volume power check after \".concat(this.MAX_RETRY_COUNT, \" attempts.\"));\n }\n });\n }\n}\n_defineProperty(PythonServerAPI, \"PYTHON_SERVER_URL\", 'https://easyeyes-python-flask-server.herokuapp.com');\n_defineProperty(PythonServerAPI, \"TEST_SERVER_URL\", 'http://127.0.0.1:5000');\n/* harmony default export */ __webpack_exports__[\"default\"] = (PythonServerAPI);\n\n//# sourceURL=webpack://speakerCalibrator/./src/server/PythonServerAPI.js?");
|
|
150
|
+
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\");\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n/**\n *\n */\nclass PythonServerAPI {\n constructor() {\n // static PYTHON_SERVER_URL ='http://127.0.0.1:5000';\n /** @private */\n _defineProperty(this, \"MAX_RETRY_COUNT\", 3);\n /** @private */\n _defineProperty(this, \"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 _defineProperty(this, \"getImpulseResponse\", async _ref => {\n let {\n mls,\n sampleRate,\n numPeriods,\n sig,\n fs2,\n L_new_n,\n dL_n\n } = _ref;\n const task = 'impulse-response';\n let res = null;\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 await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: \"/task/\".concat(task),\n headers: {\n 'Content-Type': 'application/json'\n },\n data\n }).then(response => {\n res = response;\n }).catch(error => {\n throw error;\n });\n return res.data[task];\n });\n _defineProperty(this, \"getAutocorrelation\", async _ref2 => {\n let {\n mls,\n payload,\n sampleRate,\n numPeriods\n } = _ref2;\n const task = 'autocorrelation';\n let res = null;\n const data = JSON.stringify({\n task,\n 'payload': payload,\n 'sample-rate': sampleRate,\n mls,\n numPeriods\n });\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: \"/task/\".concat(task),\n headers: {\n 'Content-Type': 'application/json'\n },\n data\n }).then(response => {\n res = response;\n }).catch(error => {\n throw error;\n });\n return res.data[task];\n });\n _defineProperty(this, \"getConvolution\", async _ref3 => {\n let {\n mls,\n inverse_response,\n inverse_response_no_bandpass,\n attenuatorGain_dB,\n mls_amplitude\n } = _ref3;\n const task = 'convolution';\n let res = null;\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 await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: \"/task/\".concat(task),\n headers: {\n 'Content-Type': 'application/json'\n },\n data\n }).then(response => {\n res = response;\n }).catch(error => {\n throw error;\n });\n return res.data[task];\n });\n _defineProperty(this, \"getMLS\", async _ref4 => {\n let {\n length,\n amplitude,\n calibrateSoundBurstMLSVersions\n } = _ref4;\n const task = 'mls';\n let res = null;\n const data = JSON.stringify({\n task,\n length: length,\n amplitude: amplitude,\n calibrateSoundBurstMLSVersions: calibrateSoundBurstMLSVersions\n });\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: \"/task/\".concat(task),\n headers: {\n 'Content-Type': 'application/json'\n },\n data\n }).then(response => {\n res = response;\n }).catch(error => {\n throw error;\n });\n return res.data[task];\n });\n _defineProperty(this, \"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 console.log(data);\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: \"/task/\".concat(task),\n headers: {\n 'Content-Type': 'application/json'\n },\n data\n }).then(response => {\n res = response;\n console.log(res.data[task]);\n }).catch(error => {\n throw error;\n });\n return res.data[task];\n });\n _defineProperty(this, \"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 }).then(response => {\n console.log(\"memory used:\", Math.round(response.data['memory']), \"mb\");\n res = response.data['memory'];\n }).catch(error => {\n throw error;\n });\n return res;\n });\n _defineProperty(this, \"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 _defineProperty(this, \"getMLSWithRetry\", async _ref5 => {\n let {\n length,\n amplitude,\n calibrateSoundBurstMLSVersions\n } = _ref5;\n let retryCount = 0;\n let response = null;\n while (retryCount < this.MAX_RETRY_COUNT) {\n try {\n response = await this.getMLS({\n length,\n amplitude,\n calibrateSoundBurstMLSVersions\n });\n // If the request is successful, break out of the loop\n break;\n } catch (error) {\n console.error(\"Error occurred. Retrying... (\".concat(retryCount + 1, \"/\").concat(this.MAX_RETRY_COUNT, \")\"));\n retryCount++;\n await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS));\n }\n }\n if (response) {\n return response;\n } else {\n throw new Error(\"Failed to get MLS after \".concat(this.MAX_RETRY_COUNT, \" attempts.\"));\n }\n });\n _defineProperty(this, \"getPSD\", async _ref6 => {\n let {\n unconv_rec,\n conv_rec,\n sampleRate\n } = _ref6;\n const task = 'psd';\n let res = null;\n const data = JSON.stringify({\n task,\n unconv_rec,\n conv_rec,\n sampleRate\n });\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: \"/task/\".concat(task),\n headers: {\n 'Content-Type': 'application/json'\n },\n data\n }).then(response => {\n res = response;\n }).catch(error => {\n throw error;\n });\n return res.data[task];\n });\n _defineProperty(this, \"getBackgroundNoisePSD\", async _ref7 => {\n let {\n background_rec,\n sampleRate\n } = _ref7;\n const task = 'background-psd';\n let res = null;\n const data = JSON.stringify({\n task,\n background_rec,\n sampleRate\n });\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: \"/task/\".concat(task),\n headers: {\n 'Content-Type': 'application/json'\n },\n data\n }).then(response => {\n res = response;\n }).catch(error => {\n throw error;\n });\n return res.data[task];\n });\n _defineProperty(this, \"getBackgroundNoisePSDWithRetry\", async _ref8 => {\n let {\n background_rec,\n sampleRate\n } = _ref8;\n let retryCount = 0;\n let response = null;\n while (retryCount < this.MAX_RETRY_COUNT) {\n try {\n response = await this.getBackgroundNoisePSD({\n background_rec,\n sampleRate\n });\n // If the request is successful, break out of the loop\n break;\n } catch (error) {\n console.error(\"Error occurred. Retrying... (\".concat(retryCount + 1, \"/\").concat(this.MAX_RETRY_COUNT, \")\"));\n retryCount++;\n await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS));\n }\n }\n if (response) {\n return response;\n } else {\n throw new Error(\"Failed to get PSD after \".concat(this.MAX_RETRY_COUNT, \" attempts.\"));\n }\n });\n _defineProperty(this, \"getSubtractedPSD\", async (rec, knownGains, knownFrequencies, sampleRate) => {\n const task = 'subtracted-psd';\n let res = null;\n const data = JSON.stringify({\n task,\n rec,\n knownGains,\n knownFrequencies,\n sampleRate\n });\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: \"/task/\".concat(task),\n headers: {\n 'Content-Type': 'application/json'\n },\n data\n }).then(response => {\n res = response;\n }).catch(error => {\n throw error;\n });\n return res.data[task];\n });\n _defineProperty(this, \"getSubtractedPSDWithRetry\", async (rec, knownGains, knownFrequencies, sampleRate) => {\n let retryCount = 0;\n let response = null;\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... (\".concat(retryCount + 1, \"/\").concat(this.MAX_RETRY_COUNT, \")\"));\n retryCount++;\n await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS));\n }\n }\n if (response) {\n return response;\n } else {\n throw new Error(\"Failed to get PSD after \".concat(this.MAX_RETRY_COUNT, \" attempts.\"));\n }\n });\n _defineProperty(this, \"getPSDWithRetry\", async _ref9 => {\n let {\n unconv_rec,\n conv_rec,\n sampleRate\n } = _ref9;\n let retryCount = 0;\n let response = null;\n while (retryCount < this.MAX_RETRY_COUNT) {\n try {\n response = await this.getPSD({\n unconv_rec,\n conv_rec,\n sampleRate\n });\n // If the request is successful, break out of the loop\n break;\n } catch (error) {\n console.error(\"Error occurred. Retrying... (\".concat(retryCount + 1, \"/\").concat(this.MAX_RETRY_COUNT, \")\"));\n retryCount++;\n await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS));\n }\n }\n if (response) {\n return response;\n } else {\n throw new Error(\"Failed to get PSD after \".concat(this.MAX_RETRY_COUNT, \" attempts.\"));\n }\n });\n _defineProperty(this, \"getComponentInverseImpulseResponse\", async _ref10 => {\n let {\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 } = _ref10;\n const task = 'component-inverse-impulse-response';\n let res = null;\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 await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: \"/task/\".concat(task),\n headers: {\n 'Content-Type': 'application/json'\n },\n data\n }).then(response => {\n res = response;\n }).catch(error => {\n throw error;\n });\n return res.data[task];\n });\n _defineProperty(this, \"getSystemInverseImpulseResponse\", async _ref11 => {\n let {\n payload,\n mls,\n lowHz,\n highHz,\n iirLength,\n sampleRate,\n mlsAmplitude,\n calibrateSoundBurstFilteredExtraDb,\n calibrateSoundIIRPhase\n } = _ref11;\n const task = 'system-inverse-impulse-response';\n let res = null;\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 await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: \"/task/\".concat(task),\n headers: {\n 'Content-Type': 'application/json'\n },\n data\n }).then(response => {\n res = response;\n }).catch(error => {\n throw error;\n });\n return res.data[task];\n });\n _defineProperty(this, \"getMLSPSD\", async _ref12 => {\n let {\n mls,\n sampleRate\n } = _ref12;\n const task = 'mls-psd';\n let res = null;\n const data = JSON.stringify({\n task,\n mls,\n sampleRate\n });\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: \"/task/\".concat(task),\n headers: {\n 'Content-Type': 'application/json'\n },\n data\n }).then(response => {\n res = response;\n }).catch(error => {\n throw error;\n });\n return res.data[task];\n });\n _defineProperty(this, \"getMLSPSDWithRetry\", async _ref13 => {\n let {\n mls,\n sampleRate\n } = _ref13;\n let retryCount = 0;\n let response = null;\n while (retryCount < this.MAX_RETRY_COUNT) {\n try {\n response = await this.getMLSPSD({\n mls,\n sampleRate\n });\n // If the request is successful, break out of the loop\n break;\n } catch (error) {\n console.error(\"Error occurred. Retrying... (\".concat(retryCount + 1, \"/\").concat(this.MAX_RETRY_COUNT, \")\"));\n retryCount++;\n await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS));\n }\n }\n if (response) {\n return response;\n } else {\n throw new Error(\"Failed to get inverse impulse response after \".concat(this.MAX_RETRY_COUNT, \" attempts.\"));\n }\n });\n _defineProperty(this, \"getComponentInverseImpulseResponseWithRetry\", async _ref14 => {\n let {\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 } = _ref14;\n let retryCount = 0;\n let response = null;\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... (\".concat(retryCount + 1, \"/\").concat(this.MAX_RETRY_COUNT, \")\"));\n retryCount++;\n await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS));\n }\n }\n if (response) {\n return response;\n } else {\n throw new Error(\"Failed to get inverse impulse response after \".concat(this.MAX_RETRY_COUNT, \" attempts.\"));\n }\n });\n _defineProperty(this, \"getSystemInverseImpulseResponseWithRetry\", async _ref15 => {\n let {\n payload,\n mls,\n lowHz,\n highHz,\n iirLength,\n sampleRate,\n mlsAmplitude,\n calibrateSoundBurstFilteredExtraDb,\n calibrateSoundIIRPhase\n } = _ref15;\n let retryCount = 0;\n let response = null;\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... (\".concat(retryCount + 1, \"/\").concat(this.MAX_RETRY_COUNT, \")\"));\n retryCount++;\n await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS));\n }\n }\n if (response) {\n return response;\n } else {\n throw new Error(\"Failed to get inverse impulse response after \".concat(this.MAX_RETRY_COUNT, \" attempts.\"));\n }\n });\n _defineProperty(this, \"getVolumeCalibration\", async _ref16 => {\n let {\n payload,\n sampleRate,\n lCalib\n } = _ref16;\n const task = 'volume';\n let res = null;\n console.log({\n payload\n });\n const data = JSON.stringify({\n task,\n payload,\n 'sample-rate': sampleRate,\n lCalib\n });\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n url: \"/task/\".concat(task),\n headers: {\n 'Content-Type': 'application/json'\n },\n data\n }).then(response => {\n res = response;\n }).catch(error => {\n throw error;\n });\n return res.data[task];\n });\n _defineProperty(this, \"getVolumeCalibrationParameters\", async _ref17 => {\n let {\n inDBValues,\n outDBSPLValues,\n lCalib,\n componentGainDBSPL\n } = _ref17;\n const task = 'volume-parameters';\n let res = null;\n const data = JSON.stringify({\n task,\n inDBValues,\n outDBSPLValues,\n lCalib,\n componentGainDBSPL\n });\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n //server\n url: \"/task/\".concat(task),\n headers: {\n 'Content-Type': 'application/json'\n },\n data\n }).then(response => {\n res = response;\n console.log(res.data[task]);\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 _defineProperty(this, \"allHzPowerCheck\", async _ref18 => {\n let {\n payload,\n sampleRate,\n binDesiredSec,\n burstSec,\n repeats,\n warmUp\n } = _ref18;\n const task = 'all-hz-check';\n let res = null;\n console.log({\n 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 await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n //server\n url: \"/task/\".concat(task),\n headers: {\n 'Content-Type': 'application/json'\n },\n data\n }).then(response => {\n res = response;\n console.log(res.data[task]);\n }).catch(error => {\n throw error;\n });\n return res.data[task];\n });\n _defineProperty(this, \"volumePowerCheck\", async _ref19 => {\n let {\n payload,\n sampleRate,\n preSec,\n Sec,\n binDesiredSec\n } = _ref19;\n const task = 'volume-check';\n let res = null;\n const data = JSON.stringify({\n payload,\n sampleRate,\n preSec,\n Sec,\n binDesiredSec\n });\n await (0,axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"])({\n method: 'post',\n baseURL: PythonServerAPI.PYTHON_SERVER_URL,\n //server\n url: \"/task/\".concat(task),\n headers: {\n 'Content-Type': 'application/json'\n },\n data\n }).then(response => {\n res = response;\n console.log(res.data[task]);\n }).catch(error => {\n throw error;\n });\n return res.data[task];\n });\n _defineProperty(this, \"volumePowerCheckWithRetry\", async _ref20 => {\n let {\n payload,\n sampleRate,\n preSec,\n Sec,\n binDesiredSec\n } = _ref20;\n let retryCount = 0;\n let response = null;\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 });\n // If the request is successful, break out of the loop\n break;\n } catch (error) {\n console.error(\"Error occurred. Retrying... (\".concat(retryCount + 1, \"/\").concat(this.MAX_RETRY_COUNT, \")\"));\n retryCount++;\n await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS));\n }\n }\n if (response) {\n return response;\n } else {\n throw new Error(\"Failed to get volume power check after \".concat(this.MAX_RETRY_COUNT, \" attempts.\"));\n }\n });\n }\n}\n_defineProperty(PythonServerAPI, \"PYTHON_SERVER_URL\", 'https://easyeyes-python-flask-server.herokuapp.com');\n_defineProperty(PythonServerAPI, \"TEST_SERVER_URL\", 'http://127.0.0.1:5000');\n/* harmony default export */ __webpack_exports__[\"default\"] = (PythonServerAPI);\n\n//# sourceURL=webpack://speakerCalibrator/./src/server/PythonServerAPI.js?");
|
|
151
151
|
|
|
152
152
|
/***/ }),
|
|
153
153
|
|
|
@@ -158,7 +158,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var axio
|
|
|
158
158
|
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
159
159
|
|
|
160
160
|
"use strict";
|
|
161
|
-
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\");\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/* eslint-disable no-await-in-loop */\n\n\n\n\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 */\nclass AudioCalibrator extends _audioRecorder__WEBPACK_IMPORTED_MODULE_0__[\"default\"] {\n /**\r\n *\r\n * @param numCaptures\r\n * @param numMLSPerCapture\r\n * @example\r\n */\n constructor() {\n var _this;\n let numCaptures = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;\n let numMLSPerCapture = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;\n super();\n _this = this;\n /** @private */\n _defineProperty(this, \"isCalibrating\", false);\n /** @private */\n _defineProperty(this, \"sourceAudioContext\", void 0);\n /** @private */\n _defineProperty(this, \"sourceAudioContextConvolved\", void 0);\n /** @protected */\n _defineProperty(this, \"numCalibratingRounds\", 1);\n /** @protected */\n _defineProperty(this, \"numSuccessfulCaptured\", 0);\n /** @private */\n _defineProperty(this, \"sourceSamplingRate\", void 0);\n /** @protected */\n _defineProperty(this, \"calibrationNodes\", []);\n /** @protected */\n _defineProperty(this, \"calibrationNodesConvolved\", []);\n /** @protected */\n _defineProperty(this, \"localAudio\", void 0);\n /** @private */\n _defineProperty(this, \"startTime\", void 0);\n _defineProperty(this, \"numCalibratingRoundsCompleted\", 0);\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 */\n _defineProperty(this, \"createLocalAudio\", targetElement => {\n this.localAudio = document.createElement('audio');\n this.localAudio.setAttribute('id', 'localAudio');\n targetElement.appendChild(this.localAudio);\n });\n _defineProperty(this, \"addTimeStamp\", taskName => {\n const currentTime = new Date().getTime(); // Current time in ms\n const elapsedTime = (currentTime - this.startTime) / 1000; // Convert to seconds\n const stepDuration = elapsedTime - this.currentTime;\n this.currentTime = elapsedTime; // Update for next step\n\n // Format numbers to 1 decimal place without padding\n const elapsedStr = elapsedTime.toFixed(1);\n const stepStr = stepDuration.toFixed(1);\n\n // Push timestamp string (without padding)\n this.timeStamp.push(\"\".concat(elapsedStr, \" s. \\u2206 \").concat(stepStr, \" s. \").concat(taskName));\n });\n _defineProperty(this, \"recordBackground\", async function (stream) {\n let loopCondition = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : () => false;\n let duringRecord = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : async () => {};\n let afterRecord = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : async () => {};\n let mode = arguments.length > 4 ? arguments[4] : undefined;\n let checkRec = arguments.length > 5 ? arguments[5] : undefined;\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 /**\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 */\n _defineProperty(this, \"calibrationSteps\", async function (stream, playCalibrationAudio) {\n let beforePlay = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : async () => {};\n let beforeRecord = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : async () => {};\n let loopCondition = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : () => false;\n let duringRecord = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : async () => {};\n let afterRecord = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : async () => {};\n let mode = arguments.length > 7 ? arguments[7] : undefined;\n let checkRec = arguments.length > 8 ? arguments[8] : undefined;\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\n // calibration loop\n while (loopCondition()) {\n if (_this.isCalibrating) break;\n // start recording\n console.warn('startRecording');\n await _this.startRecording(stream);\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 if (_this.isCalibrating) break;\n // when done, stop recording\n console.warn('stopRecording');\n await _this.stopRecording(mode, checkRec);\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 /**\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 */\n _defineProperty(this, \"volumeCalibrationSteps\", async function (stream, playCalibrationAudio) {\n let beforeRecord = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : () => {};\n let afterRecord = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : () => {};\n let gainValue = arguments.length > 4 ? arguments[4] : undefined;\n let lCalib = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 104.92978421490648;\n let checkRec = arguments.length > 6 ? arguments[6] : undefined;\n let checkSD = arguments.length > 7 ? arguments[7] : undefined;\n let maxSD = arguments.length > 8 ? arguments[8] : undefined;\n _this.numCalibratingRoundsCompleted = 0;\n _this.numCalibratingRounds = 2;\n console.log(\"maxSD in VolumeCaibrationSteps: \", maxSD, '0' >= maxSD);\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 \".concat(_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();\n let sdMessage;\n if (sd <= maxSD) {\n console.log(\"SD =\".concat(sd, \", less than calibrateSound1000HzMaxSD_dB=\").concat(maxSD));\n _this.numCalibratingRoundsCompleted += 2;\n sdMessage = \". SD = \".concat(sd, \" dB\");\n } else {\n // if exist the maxSD do it one more time and only one more time\n console.log(\"SD =\".concat(sd, \", greater than calibrateSound1000HzMaxSD_dB=\").concat(maxSD));\n _this.numCalibratingRoundsCompleted += 1;\n sdMessage = \". SD = \".concat(sd, \" > \").concat(_this.calibrateSound1000HzMaxSD_dB, \" dB.\");\n }\n _this.addTimeStamp(\"\".concat(_this.calibrateSound1000HzPreSec.toFixed(1)) + \"+\".concat(_this.calibrateSound1000HzSec.toFixed(1)) + \"+\".concat(_this.calibrateSound1000HzPostSec.toFixed(1), \" s. \") + \"1000 Hz at \".concat(_this.inDB, \" dB\").concat(sdMessage));\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 /**\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 */\n _defineProperty(this, \"getCalibrationStatus\", () => this.isCalibrating);\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 */\n _defineProperty(this, \"setSamplingRates\", samplingRate => {\n this.sinkSamplingRate = samplingRate;\n this.sourceSamplingRate = samplingRate;\n\n // this.emit('update', {message: `sampling at ${samplingRate}Hz...`});\n });\n _defineProperty(this, \"setSampleSize\", sampleSize => {\n this.sampleSize = sampleSize;\n });\n _defineProperty(this, \"setFlags\", flags => {\n this.flags = flags;\n });\n _defineProperty(this, \"sampleRatesSet\", () => this.sourceSamplingRate && this.sinkSamplingRate);\n _defineProperty(this, \"addCalibrationNode\", node => {\n this.calibrationNodes.push(node);\n });\n _defineProperty(this, \"addCalibrationNodeConvolved\", node => {\n this.calibrationNodesConvolved.push(node);\n });\n _defineProperty(this, \"makeNewSourceAudioContext\", () => {\n const options = {\n sampleRate: this.sourceSamplingRate\n };\n this.sourceAudioContext = new (window.AudioContext || window.webkitAudioContext || window.audioContext)(options);\n return this.sourceAudioContext;\n });\n _defineProperty(this, \"makeNewSourceAudioContextConvolved\", () => {\n const options = {\n sampleRate: this.sourceSamplingRate\n };\n this.sourceAudioContextConvolved = new (window.AudioContext || window.webkitAudioContext || window.audioContext)(options);\n return this.sourceAudioContextConvolved;\n });\n /** .\r\n * .\r\n * .\r\n * Download the result of the calibration roudns\r\n *\r\n * @example\r\n */\n _defineProperty(this, \"downloadData\", () => {\n const recordings = this.getAllRecordedSignals();\n const i = recordings.length - 1;\n (0,_utils__WEBPACK_IMPORTED_MODULE_2__.saveToCSV)(recordings[i], \"recordedMLSignal_\".concat(i, \"_unconvolved.csv\"));\n });\n _defineProperty(this, \"downloadSingleUnfilteredRecording\", () => {\n const recordings = this.getAllUnfilteredRecordedSignals();\n (0,_utils__WEBPACK_IMPORTED_MODULE_2__.saveToCSV)(recordings[recordings.length - 1], \"recordedMLSignal_unconvolved.csv\");\n });\n _defineProperty(this, \"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 _defineProperty(this, \"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_\".concat(i, \"_unconvolved.csv\"));\n }\n });\n _defineProperty(this, \"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_\".concat(i, \"_convolved.csv\"));\n }\n });\n this.numCaptures = numCaptures;\n this.numMLSPerCapture = numMLSPerCapture;\n this.pyServerAPI = new _server_PythonServerAPI__WEBPACK_IMPORTED_MODULE_1__[\"default\"]();\n this.currentTime = 0;\n }\n}\n/* harmony default export */ __webpack_exports__[\"default\"] = (AudioCalibrator);\n\n//# sourceURL=webpack://speakerCalibrator/./src/tasks/audioCalibrator.js?");
|
|
161
|
+
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\");\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\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() {\n var _this;\n let numCaptures = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;\n let numMLSPerCapture = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;\n super();\n _this = this;\n /** @private */\n _defineProperty(this, \"isCalibrating\", false);\n /** @private */\n _defineProperty(this, \"sourceAudioContext\", void 0);\n /** @private */\n _defineProperty(this, \"sourceAudioContextConvolved\", void 0);\n /** @protected */\n _defineProperty(this, \"numCalibratingRounds\", 1);\n /** @protected */\n _defineProperty(this, \"numSuccessfulCaptured\", 0);\n /** @private */\n _defineProperty(this, \"sourceSamplingRate\", void 0);\n /** @protected */\n _defineProperty(this, \"calibrationNodes\", []);\n /** @protected */\n _defineProperty(this, \"calibrationNodesConvolved\", []);\n /** @protected */\n _defineProperty(this, \"localAudio\", void 0);\n /** @private */\n _defineProperty(this, \"startTime\", void 0);\n _defineProperty(this, \"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 _defineProperty(this, \"createLocalAudio\", targetElement => {\n this.localAudio = document.createElement('audio');\n this.localAudio.setAttribute('id', 'localAudio');\n targetElement.appendChild(this.localAudio);\n });\n _defineProperty(this, \"addTimeStamp\", taskName => {\n const currentTime = new Date().getTime(); // Current time in ms\n const elapsedTime = (currentTime - this.startTime) / 1000; // Convert to seconds\n const stepDuration = elapsedTime - this.currentTime;\n this.currentTime = elapsedTime; // Update for next step\n\n // Format numbers to 1 decimal place without padding\n const elapsedStr = elapsedTime.toFixed(1);\n const stepStr = stepDuration.toFixed(1);\n\n // Push timestamp string (without padding)\n this.timeStamp.push(\"\".concat(elapsedStr, \" s. \\u2206 \").concat(stepStr, \" s. \").concat(taskName));\n });\n _defineProperty(this, \"recordBackground\", async function (stream) {\n let loopCondition = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : () => false;\n let duringRecord = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : async () => {};\n let afterRecord = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : async () => {};\n let mode = arguments.length > 4 ? arguments[4] : undefined;\n let checkRec = arguments.length > 5 ? arguments[5] : undefined;\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 * @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 _defineProperty(this, \"calibrationSteps\", async function (stream, playCalibrationAudio) {\n let beforePlay = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : async () => {};\n let beforeRecord = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : async () => {};\n let loopCondition = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : () => false;\n let duringRecord = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : async () => {};\n let afterRecord = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : async () => {};\n let mode = arguments.length > 7 ? arguments[7] : undefined;\n let checkRec = arguments.length > 8 ? arguments[8] : undefined;\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\n // calibration loop\n while (loopCondition()) {\n if (_this.isCalibrating) break;\n // start recording\n console.warn('startRecording');\n await _this.startRecording(stream);\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 if (_this.isCalibrating) break;\n // when done, stop recording\n console.warn('stopRecording');\n await _this.stopRecording(mode, checkRec);\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 * @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 _defineProperty(this, \"volumeCalibrationSteps\", async function (stream, playCalibrationAudio) {\n let beforeRecord = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : () => {};\n let afterRecord = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : () => {};\n let gainValue = arguments.length > 4 ? arguments[4] : undefined;\n let lCalib = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 104.92978421490648;\n let checkRec = arguments.length > 6 ? arguments[6] : undefined;\n let checkSD = arguments.length > 7 ? arguments[7] : undefined;\n let maxSD = arguments.length > 8 ? arguments[8] : undefined;\n let maxRetry = arguments.length > 9 ? arguments[9] : undefined;\n _this.numCalibratingRoundsCompleted = 0;\n console.log(\"maxSD in VolumeCaibrationSteps: \", maxSD, '0' >= maxSD);\n // calibration loop\n while (!_this.isCalibrating && _this.numCalibratingRoundsCompleted < maxRetry) {\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 \".concat(_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();\n let sdMessage;\n if (sd <= maxSD) {\n console.log(\"SD =\".concat(sd, \", less than calibrateSound1000HzMaxSD_dB=\").concat(maxSD));\n _this.numCalibratingRoundsCompleted += maxRetry;\n sdMessage = \". SD = \".concat(sd, \" dB\");\n } else {\n // if exist the maxSD do it one more time and only one more time\n console.log(\"SD =\".concat(sd, \", greater than calibrateSound1000HzMaxSD_dB=\").concat(maxSD));\n _this.numCalibratingRoundsCompleted += 1;\n sdMessage = \". SD = \".concat(sd, \" > \").concat(_this.calibrateSound1000HzMaxSD_dB, \" dB.\");\n }\n _this.addTimeStamp(\"\".concat(_this.calibrateSound1000HzPreSec.toFixed(1)) + \"+\".concat(_this.calibrateSound1000HzSec.toFixed(1)) + \"+\".concat(_this.calibrateSound1000HzPostSec.toFixed(1), \" s. \") + \"1000 Hz at \".concat(_this.inDB, \" dB\").concat(sdMessage));\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 * Getter for the isCalibrating property.\n *\n * @public\n * @returns - True if the audio is being calibrated, false otherwise.\n * @example\n */\n _defineProperty(this, \"getCalibrationStatus\", () => this.isCalibrating);\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 _defineProperty(this, \"setSamplingRates\", samplingRate => {\n this.sinkSamplingRate = samplingRate;\n this.sourceSamplingRate = samplingRate;\n\n // this.emit('update', {message: `sampling at ${samplingRate}Hz...`});\n });\n _defineProperty(this, \"setSampleSize\", sampleSize => {\n this.sampleSize = sampleSize;\n });\n _defineProperty(this, \"setFlags\", flags => {\n this.flags = flags;\n });\n _defineProperty(this, \"sampleRatesSet\", () => this.sourceSamplingRate && this.sinkSamplingRate);\n _defineProperty(this, \"addCalibrationNode\", node => {\n this.calibrationNodes.push(node);\n });\n _defineProperty(this, \"addCalibrationNodeConvolved\", node => {\n this.calibrationNodesConvolved.push(node);\n });\n _defineProperty(this, \"makeNewSourceAudioContext\", () => {\n const options = {\n sampleRate: this.sourceSamplingRate\n };\n this.sourceAudioContext = new (window.AudioContext || window.webkitAudioContext || window.audioContext)(options);\n return this.sourceAudioContext;\n });\n _defineProperty(this, \"makeNewSourceAudioContextConvolved\", () => {\n const options = {\n sampleRate: this.sourceSamplingRate\n };\n this.sourceAudioContextConvolved = new (window.AudioContext || window.webkitAudioContext || window.audioContext)(options);\n return this.sourceAudioContextConvolved;\n });\n /** .\n * .\n * .\n * Download the result of the calibration roudns\n *\n * @example\n */\n _defineProperty(this, \"downloadData\", () => {\n const recordings = this.getAllRecordedSignals();\n const i = recordings.length - 1;\n (0,_utils__WEBPACK_IMPORTED_MODULE_2__.saveToCSV)(recordings[i], \"recordedMLSignal_\".concat(i, \"_unconvolved.csv\"));\n });\n _defineProperty(this, \"downloadSingleUnfilteredRecording\", () => {\n const recordings = this.getAllUnfilteredRecordedSignals();\n (0,_utils__WEBPACK_IMPORTED_MODULE_2__.saveToCSV)(recordings[recordings.length - 1], \"recordedMLSignal_unconvolved.csv\");\n });\n _defineProperty(this, \"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 _defineProperty(this, \"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_\".concat(i, \"_unconvolved.csv\"));\n }\n });\n _defineProperty(this, \"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_\".concat(i, \"_convolved.csv\"));\n }\n });\n this.numCaptures = numCaptures;\n this.numMLSPerCapture = numMLSPerCapture;\n this.pyServerAPI = new _server_PythonServerAPI__WEBPACK_IMPORTED_MODULE_1__[\"default\"]();\n this.currentTime = 0;\n }\n}\n/* harmony default export */ __webpack_exports__[\"default\"] = (AudioCalibrator);\n\n//# sourceURL=webpack://speakerCalibrator/./src/tasks/audioCalibrator.js?");
|
|
162
162
|
|
|
163
163
|
/***/ }),
|
|
164
164
|
|
|
@@ -169,7 +169,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _aud
|
|
|
169
169
|
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
170
170
|
|
|
171
171
|
"use strict";
|
|
172
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/web.dom-collections.iterator.js */ \"./node_modules/core-js/modules/web.dom-collections.iterator.js\");\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _myEventEmitter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../myEventEmitter */ \"./src/myEventEmitter.js\");\n\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }\nfunction _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError(\"Cannot initialize the same private elements twice on an object\"); }\nfunction _classPrivateFieldSet(s, a, r) { return s.set(_assertClassBrand(s, a), r), r; }\nfunction _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }\nfunction _assertClassBrand(e, t, n) { if (\"function\" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError(\"Private element is not present on this object\"); }\n\n\n/**\r\n * @class provides a simple interface for recording audio from a microphone\r\n * using the Media Recorder API.\r\n */\nvar _mediaRecorder = /*#__PURE__*/new WeakMap();\nvar _recordedChunks = /*#__PURE__*/new WeakMap();\nvar _audioBlob = /*#__PURE__*/new WeakMap();\nvar _audioContext = /*#__PURE__*/new WeakMap();\nvar _recordedSignals = /*#__PURE__*/new WeakMap();\nvar _allHzUnfilteredRecordings = /*#__PURE__*/new WeakMap();\nvar _allBackgroundRecordings = /*#__PURE__*/new WeakMap();\nvar _allHzFilteredRecordings = /*#__PURE__*/new WeakMap();\nvar _allVolumeRecordings = /*#__PURE__*/new WeakMap();\nvar _saveRecording = /*#__PURE__*/new WeakMap();\nvar _saveFilteredRecording = /*#__PURE__*/new WeakMap();\nvar _onRecorderDataAvailable = /*#__PURE__*/new WeakMap();\nvar _setMediaRecorder = /*#__PURE__*/new WeakMap();\nvar _setAudioContext = /*#__PURE__*/new WeakMap();\nclass AudioRecorder extends _myEventEmitter__WEBPACK_IMPORTED_MODULE_1__[\"default\"] {\n constructor() {\n super(...arguments);\n /** @private */\n _classPrivateFieldInitSpec(this, _mediaRecorder, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _recordedChunks, []);\n /** @private */\n _classPrivateFieldInitSpec(this, _audioBlob, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _audioContext, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _recordedSignals, []);\n /**@private */\n _classPrivateFieldInitSpec(this, _allHzUnfilteredRecordings, []);\n /**@private */\n _classPrivateFieldInitSpec(this, _allBackgroundRecordings, []);\n /** @private */\n _classPrivateFieldInitSpec(this, _allHzFilteredRecordings, []);\n /** @private */\n _defineProperty(this, \"sinkSamplingRate\", void 0);\n /** @private */\n _defineProperty(this, \"sampleSize\", void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _allVolumeRecordings, []);\n /** @private */\n _defineProperty(this, \"flags\", {});\n /**\r\n * Decode the audio data from the recorded audio blob.\r\n *\r\n * @private\r\n * @example\r\n */\n _classPrivateFieldInitSpec(this, _saveRecording, async (mode, checkRec) => {\n const arrayBuffer = await _classPrivateFieldGet(_audioBlob, this).arrayBuffer();\n const audioBuffer = await _classPrivateFieldGet(_audioContext, this).decodeAudioData(arrayBuffer);\n console.log(audioBuffer);\n const data = audioBuffer.getChannelData(0);\n const dataArray = Array.from(data);\n console.log(\"Decoded audio buffer with \".concat(data.length, \" samples\"));\n console.log(\"Unfiltered recording should be of length: \".concat(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('Loudest 1000-Hz recording: ' + roundedDbLevel + ' dB with ' + numberOfUniqueValues + ' unique values.');\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('All Hz Recording: ' + roundedDbLevel + ' dB with ' + numberOfUniqueValues + ' unique values.');\n }\n if (mode === 'volume') {\n console.log('Saving 1000 Hz Recording to #allVolumeRecordings');\n _classPrivateFieldGet(_allVolumeRecordings, this).push(dataArray);\n } else if (mode === 'unfiltered') {\n console.log('Saving unfiltered all Hz recording to #allHzUnfilteredRecordings');\n _classPrivateFieldGet(_allHzUnfilteredRecordings, this).push(dataArray);\n } else if (mode === 'filtered') {\n console.log('Saving filtered all hz recording to #allHzFilteredRecordings');\n _classPrivateFieldGet(_allHzFilteredRecordings, this).push(dataArray);\n } else if (mode === 'background') {\n console.log('Saving background recording to #allBackgroundRecordings');\n _classPrivateFieldGet(_allBackgroundRecordings, this).push(dataArray);\n }\n });\n _classPrivateFieldInitSpec(this, _saveFilteredRecording, async () => {\n const arrayBuffer = await _classPrivateFieldGet(_audioBlob, this).arrayBuffer();\n const audioBuffer = await _classPrivateFieldGet(_audioContext, this).decodeAudioData(arrayBuffer);\n const data = audioBuffer.getChannelData(0);\n console.log(\"Decoded audio buffer with \".concat(data.length, \" samples\"));\n console.log(\"Filtered recording should be of length: \".concat(data.length));\n _classPrivateFieldGet(_allHzFilteredRecordings, this).push(Array.from(data));\n });\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 */\n _classPrivateFieldInitSpec(this, _onRecorderDataAvailable, e => {\n if (e.data && e.data.size > 0) _classPrivateFieldGet(_recordedChunks, this).push(e.data);\n });\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 */\n _classPrivateFieldInitSpec(this, _setMediaRecorder, stream => {\n // Create a new MediaRecorder object\n _classPrivateFieldSet(_mediaRecorder, this, new MediaRecorder(stream));\n\n // Add event listeners\n _classPrivateFieldGet(_mediaRecorder, this).ondataavailable = e => _classPrivateFieldGet(_onRecorderDataAvailable, this).call(this, e);\n });\n _classPrivateFieldInitSpec(this, _setAudioContext, () => {\n _classPrivateFieldSet(_audioContext, this, new (window.AudioContext || window.webkitAudioContext || window.audioContext)({\n sampleRate: this.sinkSamplingRate,\n sampleSize: this.sampleSize\n //sampleRate: 96000\n }));\n });\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 */\n _defineProperty(this, \"startRecording\", async stream => {\n try {\n // Create a fresh audio context\n _classPrivateFieldGet(_setAudioContext, this).call(this);\n // Set up media recorder if needed\n if (!_classPrivateFieldGet(_mediaRecorder, this)) _classPrivateFieldGet(_setMediaRecorder, this).call(this, stream);\n // clear recorded chunks\n _classPrivateFieldSet(_recordedChunks, this, []);\n // start recording\n _classPrivateFieldGet(_mediaRecorder, this).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 /**\r\n * Method to stop the recording process.\r\n *\r\n * @public\r\n * @example\r\n */\n _defineProperty(this, \"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 _classPrivateFieldGet(_mediaRecorder, this).onstop = () => {\n // when the stop event is triggered, resolve the promise\n _classPrivateFieldSet(_audioBlob, this, new Blob(_classPrivateFieldGet(_recordedChunks, this), {\n type: 'audio/wav; codecs=opus'\n }));\n resolve(_classPrivateFieldGet(_audioBlob, this));\n };\n // call stop\n _classPrivateFieldGet(_mediaRecorder, this).stop();\n });\n // Now that we have data, save it\n await _classPrivateFieldGet(_saveRecording, this).call(this, 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 /** .\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 */\n _defineProperty(this, \"getLastRecordedSignal\", () => _classPrivateFieldGet(_recordedSignals, this)[_classPrivateFieldGet(_recordedSignals, this).length - 1]);\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 */\n _defineProperty(this, \"getLastVolumeRecordedSignal\", () => Array.from(_classPrivateFieldGet(_allVolumeRecordings, this)[_classPrivateFieldGet(_allVolumeRecordings, this).length - 1]));\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 */\n _defineProperty(this, \"getAllRecordedSignals\", () => _classPrivateFieldGet(_recordedSignals, this));\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 */\n _defineProperty(this, \"getAllVolumeRecordedSignals\", () => _classPrivateFieldGet(_allVolumeRecordings, this));\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 */\n _defineProperty(this, \"getAllFilteredRecordedSignals\", () => _classPrivateFieldGet(_allHzFilteredRecordings, this));\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 */\n _defineProperty(this, \"clearAllFilteredRecordedSignals\", () => _classPrivateFieldSet(_allHzFilteredRecordings, this, []));\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 */\n _defineProperty(this, \"clearLastFilteredRecordedSignals\", () => _classPrivateFieldGet(_allHzFilteredRecordings, this).pop());\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 */\n _defineProperty(this, \"getAllUnfilteredRecordedSignals\", () => _classPrivateFieldGet(_allHzUnfilteredRecordings, this));\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 */\n _defineProperty(this, \"clearLastUnfilteredRecordedSignals\", () => _classPrivateFieldGet(_allHzUnfilteredRecordings, this).pop());\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 */\n _defineProperty(this, \"getAllBackgroundRecordings\", () => _classPrivateFieldGet(_allBackgroundRecordings, this));\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 */\n _defineProperty(this, \"setSinkSamplingRate\", sinkSamplingRate => {\n this.sinkSamplingRate = sinkSamplingRate;\n });\n }\n}\n/* harmony default export */ __webpack_exports__[\"default\"] = (AudioRecorder);\n\n//# sourceURL=webpack://speakerCalibrator/./src/tasks/audioRecorder.js?");
|
|
172
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/web.dom-collections.iterator.js */ \"./node_modules/core-js/modules/web.dom-collections.iterator.js\");\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _myEventEmitter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../myEventEmitter */ \"./src/myEventEmitter.js\");\n\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }\nfunction _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError(\"Cannot initialize the same private elements twice on an object\"); }\nfunction _classPrivateFieldSet(s, a, r) { return s.set(_assertClassBrand(s, a), r), r; }\nfunction _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }\nfunction _assertClassBrand(e, t, n) { if (\"function\" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError(\"Private element is not present on this object\"); }\n\n\n/**\n * @class provides a simple interface for recording audio from a microphone\n * using the Media Recorder API.\n */\nvar _mediaRecorder = /*#__PURE__*/new WeakMap();\nvar _recordedChunks = /*#__PURE__*/new WeakMap();\nvar _audioBlob = /*#__PURE__*/new WeakMap();\nvar _audioContext = /*#__PURE__*/new WeakMap();\nvar _recordedSignals = /*#__PURE__*/new WeakMap();\nvar _allHzUnfilteredRecordings = /*#__PURE__*/new WeakMap();\nvar _allBackgroundRecordings = /*#__PURE__*/new WeakMap();\nvar _allHzFilteredRecordings = /*#__PURE__*/new WeakMap();\nvar _allVolumeRecordings = /*#__PURE__*/new WeakMap();\nvar _saveRecording = /*#__PURE__*/new WeakMap();\nvar _saveFilteredRecording = /*#__PURE__*/new WeakMap();\nvar _onRecorderDataAvailable = /*#__PURE__*/new WeakMap();\nvar _setMediaRecorder = /*#__PURE__*/new WeakMap();\nvar _setAudioContext = /*#__PURE__*/new WeakMap();\nclass AudioRecorder extends _myEventEmitter__WEBPACK_IMPORTED_MODULE_1__[\"default\"] {\n constructor() {\n super(...arguments);\n /** @private */\n _classPrivateFieldInitSpec(this, _mediaRecorder, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _recordedChunks, []);\n /** @private */\n _classPrivateFieldInitSpec(this, _audioBlob, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _audioContext, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _recordedSignals, []);\n /**@private */\n _classPrivateFieldInitSpec(this, _allHzUnfilteredRecordings, []);\n /**@private */\n _classPrivateFieldInitSpec(this, _allBackgroundRecordings, []);\n /** @private */\n _classPrivateFieldInitSpec(this, _allHzFilteredRecordings, []);\n /** @private */\n _defineProperty(this, \"sinkSamplingRate\", void 0);\n /** @private */\n _defineProperty(this, \"sampleSize\", void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _allVolumeRecordings, []);\n /** @private */\n _defineProperty(this, \"flags\", {});\n /**\n * Decode the audio data from the recorded audio blob.\n *\n * @private\n * @example\n */\n _classPrivateFieldInitSpec(this, _saveRecording, async (mode, checkRec) => {\n const arrayBuffer = await _classPrivateFieldGet(_audioBlob, this).arrayBuffer();\n const audioBuffer = await _classPrivateFieldGet(_audioContext, this).decodeAudioData(arrayBuffer);\n console.log(audioBuffer);\n const data = audioBuffer.getChannelData(0);\n const dataArray = Array.from(data);\n console.log(\"Decoded audio buffer with \".concat(data.length, \" samples\"));\n console.log(\"Unfiltered recording should be of length: \".concat(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('Loudest 1000-Hz recording: ' + roundedDbLevel + ' dB with ' + numberOfUniqueValues + ' unique values.');\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('All Hz Recording: ' + roundedDbLevel + ' dB with ' + numberOfUniqueValues + ' unique values.');\n }\n if (mode === 'volume') {\n console.log('Saving 1000 Hz Recording to #allVolumeRecordings');\n _classPrivateFieldGet(_allVolumeRecordings, this).push(dataArray);\n } else if (mode === 'unfiltered') {\n console.log('Saving unfiltered all Hz recording to #allHzUnfilteredRecordings');\n _classPrivateFieldGet(_allHzUnfilteredRecordings, this).push(dataArray);\n } else if (mode === 'filtered') {\n console.log('Saving filtered all hz recording to #allHzFilteredRecordings');\n _classPrivateFieldGet(_allHzFilteredRecordings, this).push(dataArray);\n } else if (mode === 'background') {\n console.log('Saving background recording to #allBackgroundRecordings');\n _classPrivateFieldGet(_allBackgroundRecordings, this).push(dataArray);\n }\n });\n _classPrivateFieldInitSpec(this, _saveFilteredRecording, async () => {\n const arrayBuffer = await _classPrivateFieldGet(_audioBlob, this).arrayBuffer();\n const audioBuffer = await _classPrivateFieldGet(_audioContext, this).decodeAudioData(arrayBuffer);\n const data = audioBuffer.getChannelData(0);\n console.log(\"Decoded audio buffer with \".concat(data.length, \" samples\"));\n console.log(\"Filtered recording should be of length: \".concat(data.length));\n _classPrivateFieldGet(_allHzFilteredRecordings, this).push(Array.from(data));\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 _classPrivateFieldInitSpec(this, _onRecorderDataAvailable, e => {\n if (e.data && e.data.size > 0) _classPrivateFieldGet(_recordedChunks, this).push(e.data);\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 _classPrivateFieldInitSpec(this, _setMediaRecorder, stream => {\n // Create a new MediaRecorder object\n _classPrivateFieldSet(_mediaRecorder, this, new MediaRecorder(stream));\n\n // Add event listeners\n _classPrivateFieldGet(_mediaRecorder, this).ondataavailable = e => _classPrivateFieldGet(_onRecorderDataAvailable, this).call(this, e);\n });\n _classPrivateFieldInitSpec(this, _setAudioContext, () => {\n _classPrivateFieldSet(_audioContext, this, new (window.AudioContext || window.webkitAudioContext || window.audioContext)({\n sampleRate: this.sinkSamplingRate,\n sampleSize: this.sampleSize\n //sampleRate: 96000\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 _defineProperty(this, \"startRecording\", async stream => {\n try {\n // Create a fresh audio context\n _classPrivateFieldGet(_setAudioContext, this).call(this);\n // Set up media recorder if needed\n if (!_classPrivateFieldGet(_mediaRecorder, this)) _classPrivateFieldGet(_setMediaRecorder, this).call(this, stream);\n // clear recorded chunks\n _classPrivateFieldSet(_recordedChunks, this, []);\n // start recording\n _classPrivateFieldGet(_mediaRecorder, this).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 * Method to stop the recording process.\n *\n * @public\n * @example\n */\n _defineProperty(this, \"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 _classPrivateFieldGet(_mediaRecorder, this).onstop = () => {\n // when the stop event is triggered, resolve the promise\n _classPrivateFieldSet(_audioBlob, this, new Blob(_classPrivateFieldGet(_recordedChunks, this), {\n type: 'audio/wav; codecs=opus'\n }));\n resolve(_classPrivateFieldGet(_audioBlob, this));\n };\n // call stop\n _classPrivateFieldGet(_mediaRecorder, this).stop();\n });\n // Now that we have data, save it\n await _classPrivateFieldGet(_saveRecording, this).call(this, 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 * Public method to get the last recorded audio signal\n *\n * @returns\n * @example\n */\n _defineProperty(this, \"getLastRecordedSignal\", () => _classPrivateFieldGet(_recordedSignals, this)[_classPrivateFieldGet(_recordedSignals, this).length - 1]);\n /** .\n * .\n * .\n * Public method to get the last 1000hz recorded audio signal\n *\n * @returns\n * @example\n */\n _defineProperty(this, \"getLastVolumeRecordedSignal\", () => Array.from(_classPrivateFieldGet(_allVolumeRecordings, this)[_classPrivateFieldGet(_allVolumeRecordings, this).length - 1]));\n /** .\n * .\n * .\n * Public method to get all the recorded audio signals\n *\n * @returns\n * @example\n */\n _defineProperty(this, \"getAllRecordedSignals\", () => _classPrivateFieldGet(_recordedSignals, this));\n /** .\n * .\n * .\n * Public method to get all the recorded audio signals\n *\n * @returns\n * @example\n */\n _defineProperty(this, \"getAllVolumeRecordedSignals\", () => _classPrivateFieldGet(_allVolumeRecordings, this));\n /** .\n * .\n * .\n * Public method to get all the recorded audio signals\n *\n * @returns\n * @example\n */\n _defineProperty(this, \"getAllFilteredRecordedSignals\", () => _classPrivateFieldGet(_allHzFilteredRecordings, this));\n /** .\n * .\n * .\n * Public method to get all the recorded audio signals\n *\n * @returns\n * @example\n */\n _defineProperty(this, \"clearAllFilteredRecordedSignals\", () => _classPrivateFieldSet(_allHzFilteredRecordings, this, []));\n /** .\n * .\n * .\n * Public method to clear last the recorded audio signals\n *\n * @returns\n * @example\n */\n _defineProperty(this, \"clearLastFilteredRecordedSignals\", () => _classPrivateFieldGet(_allHzFilteredRecordings, this).pop());\n /** .\n * .\n * .\n * Public method to get all the recorded audio signals for psd\n *\n * @returns\n * @example\n */\n _defineProperty(this, \"getAllUnfilteredRecordedSignals\", () => _classPrivateFieldGet(_allHzUnfilteredRecordings, this));\n /** .\n * .\n * .\n * Public method to get all the recorded audio signals\n *\n * @returns\n * @example\n */\n _defineProperty(this, \"clearLastUnfilteredRecordedSignals\", () => _classPrivateFieldGet(_allHzUnfilteredRecordings, this).pop());\n /** .\n * .\n * .\n * Public method to get all the recorded audio signals for psd\n *\n * @returns\n * @example\n */\n _defineProperty(this, \"getAllBackgroundRecordings\", () => _classPrivateFieldGet(_allBackgroundRecordings, this));\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 _defineProperty(this, \"setSinkSamplingRate\", sinkSamplingRate => {\n this.sinkSamplingRate = sinkSamplingRate;\n });\n }\n}\n/* harmony default export */ __webpack_exports__[\"default\"] = (AudioRecorder);\n\n//# sourceURL=webpack://speakerCalibrator/./src/tasks/audioRecorder.js?");
|
|
173
173
|
|
|
174
174
|
/***/ }),
|
|
175
175
|
|
|
@@ -180,7 +180,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core
|
|
|
180
180
|
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
181
181
|
|
|
182
182
|
"use strict";
|
|
183
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_array_buffer_slice_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array-buffer.slice.js */ \"./node_modules/core-js/modules/es.array-buffer.slice.js\");\n/* harmony import */ var core_js_modules_es_array_buffer_slice_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_buffer_slice_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_es_string_replace_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/es.string.replace.js */ \"./node_modules/core-js/modules/es.string.replace.js\");\n/* harmony import */ var core_js_modules_es_string_replace_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_string_replace_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_es_typed_array_float32_array_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/es.typed-array.float32-array.js */ \"./node_modules/core-js/modules/es.typed-array.float32-array.js\");\n/* harmony import */ var core_js_modules_es_typed_array_float32_array_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_typed_array_float32_array_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var core_js_modules_es_typed_array_fill_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! core-js/modules/es.typed-array.fill.js */ \"./node_modules/core-js/modules/es.typed-array.fill.js\");\n/* harmony import */ var core_js_modules_es_typed_array_fill_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_typed_array_fill_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var core_js_modules_es_typed_array_set_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! core-js/modules/es.typed-array.set.js */ \"./node_modules/core-js/modules/es.typed-array.set.js\");\n/* harmony import */ var core_js_modules_es_typed_array_set_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_typed_array_set_js__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var core_js_modules_es_typed_array_sort_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! core-js/modules/es.typed-array.sort.js */ \"./node_modules/core-js/modules/es.typed-array.sort.js\");\n/* harmony import */ var core_js_modules_es_typed_array_sort_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_typed_array_sort_js__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! core-js/modules/web.dom-collections.iterator.js */ \"./node_modules/core-js/modules/web.dom-collections.iterator.js\");\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_6__);\n/* harmony import */ var _audioCalibrator__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../audioCalibrator */ \"./src/tasks/audioCalibrator.js\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../utils */ \"./src/utils.js\");\n/* harmony import */ var _powerCheck__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../powerCheck */ \"./src/powerCheck.js\");\n/* harmony import */ var _config_firebase__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../../config/firebase */ \"./src/config/firebase.js\");\n/* harmony import */ var firebase_database__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! firebase/database */ \"./node_modules/firebase/database/dist/esm/index.esm.js\");\n/* harmony import */ var firebase_firestore__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! firebase/firestore */ \"./node_modules/firebase/firestore/dist/esm/index.esm.js\");\n\n\n\n\n\n\n\nfunction _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }\nfunction _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError(\"Cannot initialize the same private elements twice on an object\"); }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }\nfunction _classPrivateFieldSet(s, a, r) { return s.set(_assertClassBrand(s, a), r), r; }\nfunction _assertClassBrand(e, t, n) { if (\"function\" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError(\"Private element is not present on this object\"); }\n\n\n\n\n\n\n//import { phrases } from '../../../dist/example/i18n';\n\n/**\r\n *\r\n */\nvar _download = /*#__PURE__*/new WeakMap();\nvar _mlsGenInterface = /*#__PURE__*/new WeakMap();\nvar _mlsBufferView = /*#__PURE__*/new WeakMap();\nvar _mlsOrder = /*#__PURE__*/new WeakMap();\nvar _lowHz = /*#__PURE__*/new WeakMap();\nvar _highHz = /*#__PURE__*/new WeakMap();\nvar _mls = /*#__PURE__*/new WeakMap();\nvar _P = /*#__PURE__*/new WeakMap();\nvar _audioContext = /*#__PURE__*/new WeakMap();\nvar _CALIBRATION_TONE_FREQUENCY = /*#__PURE__*/new WeakMap();\nvar _CALIBRATION_TONE_TYPE = /*#__PURE__*/new WeakMap();\nvar _currentConvolution = /*#__PURE__*/new WeakMap();\nvar _awaitDesiredMLSLength = /*#__PURE__*/new WeakMap();\nvar _awaitBackgroundNoiseRecording = /*#__PURE__*/new WeakMap();\nvar _awaitSignalOnset = /*#__PURE__*/new WeakMap();\nvar _afterMLSRecord = /*#__PURE__*/new WeakMap();\nvar _afterMLSwIIRRecord = /*#__PURE__*/new WeakMap();\nvar _createCalibrationNodeFromBuffer = /*#__PURE__*/new WeakMap();\nvar _setCalibrationNodesFromBuffer = /*#__PURE__*/new WeakMap();\nvar _playCalibrationAudio = /*#__PURE__*/new WeakMap();\nvar _getTruncatedSignal = /*#__PURE__*/new WeakMap();\nvar _createCalibrationToneWithGainValue = /*#__PURE__*/new WeakMap();\nvar _createCalibrationNode = /*#__PURE__*/new WeakMap();\nvar _playCalibrationAudioVolume = /*#__PURE__*/new WeakMap();\nvar _sendToServerForProcessing = /*#__PURE__*/new WeakMap();\nclass Combination extends _audioCalibrator__WEBPACK_IMPORTED_MODULE_7__[\"default\"] {\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 */\n constructor(_ref) {\n var _this;\n let {\n download = false,\n mlsOrder = 18,\n numCaptures = 3,\n numMLSPerCapture = 2,\n lowHz: _lowHz2 = 20,\n highHz: _highHz2 = 10000\n } = _ref;\n super(numCaptures, numMLSPerCapture);\n _this = this;\n /** @private */\n _defineProperty(this, \"stepNum\", 0);\n /** @private */\n _defineProperty(this, \"totalSteps\", 25);\n /** @private */\n _classPrivateFieldInitSpec(this, _download, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _mlsGenInterface, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _mlsBufferView, void 0);\n /** @private */\n _defineProperty(this, \"componentInvertedImpulseResponse\", null);\n /** @private */\n _defineProperty(this, \"systemInvertedImpulseResponse\", null);\n //averaged and subtracted ir returned from calibration used to calculated iir\n /** @private */\n _defineProperty(this, \"ir\", null);\n /** @private */\n _defineProperty(this, \"impulseResponses\", []);\n /** @private */\n _classPrivateFieldInitSpec(this, _mlsOrder, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _lowHz, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _highHz, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _mls, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _P, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _audioContext, void 0);\n /** @private */\n _defineProperty(this, \"offsetGainNode\", void 0);\n /** @private */\n _defineProperty(this, \"componentConvolution\", void 0);\n /** @private */\n _defineProperty(this, \"componentConvolutionNoBandpass\", void 0);\n /** @private */\n _defineProperty(this, \"componentIROrigin\", {\n Freq: [],\n Gain: []\n });\n /** @private */\n _defineProperty(this, \"systemConvolution\", void 0);\n /** @private */\n _defineProperty(this, \"systemConvolutionNoBandpass\", void 0);\n ////////////////////////volume\n /** @private */\n _classPrivateFieldInitSpec(this, _CALIBRATION_TONE_FREQUENCY, 1000);\n // Hz\n\n /** @private */\n _classPrivateFieldInitSpec(this, _CALIBRATION_TONE_TYPE, 'sine');\n _defineProperty(this, \"CALIBRATION_TONE_DURATION\", 5);\n // seconds\n _defineProperty(this, \"calibrateSound1000HzPreSec\", 3.5);\n _defineProperty(this, \"calibrateSound1000HzSec\", 1.0);\n _defineProperty(this, \"calibrateSound1000HzPostSec\", 0.5);\n /** @private */\n _defineProperty(this, \"outDBSPL\", null);\n _defineProperty(this, \"THD\", null);\n _defineProperty(this, \"outDBSPL1000\", null);\n /** @private */\n _defineProperty(this, \"TAPER_SECS\", 0.01);\n // seconds\n /** @private */\n _defineProperty(this, \"status_denominator\", 8);\n /** @private */\n _defineProperty(this, \"status_numerator\", 0);\n /** @private */\n _defineProperty(this, \"percent_complete\", 0);\n /** @private */\n _defineProperty(this, \"status\", \"\");\n /**@private */\n _defineProperty(this, \"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: \".concat(this.percent_complete, \"%; height: 100%; background-color: #00aaff; border-radius: 8px;\\\"></div></div></div>\"));\n /**@private */\n _defineProperty(this, \"componentIR\", null);\n /**@private */\n _defineProperty(this, \"oldComponentIR\", null);\n /**@private */\n _defineProperty(this, \"systemIR\", null);\n /**@private */\n _defineProperty(this, \"_calibrateSoundCheck\", '');\n _defineProperty(this, \"deviceType\", null);\n _defineProperty(this, \"deviceName\", null);\n _defineProperty(this, \"deviceInfo\", null);\n _defineProperty(this, \"desired_time_per_mls\", 0);\n _defineProperty(this, \"num_mls_to_skip\", 0);\n _defineProperty(this, \"desired_sampling_rate\", 0);\n _classPrivateFieldInitSpec(this, _currentConvolution, []);\n _defineProperty(this, \"mode\", 'unfiltered');\n _defineProperty(this, \"sourceNode\", void 0);\n _defineProperty(this, \"autocorrelations\", []);\n _defineProperty(this, \"iirLength\", 0);\n _defineProperty(this, \"irLength\", 0);\n _defineProperty(this, \"calibrateSoundIIRPhase\", 'linear');\n _defineProperty(this, \"componentInvertedImpulseResponseNoBandpass\", []);\n _defineProperty(this, \"componentIRInTimeDomain\", []);\n _defineProperty(this, \"systemInvertedImpulseResponseNoBandpass\", []);\n _defineProperty(this, \"_calibrateSoundBackgroundSecs\", void 0);\n _defineProperty(this, \"_calibrateSoundSmoothOctaves\", void 0);\n _defineProperty(this, \"background_noise\", {});\n _defineProperty(this, \"numSuccessfulBackgroundCaptured\", void 0);\n _defineProperty(this, \"_calibrateSoundBurstDb\", void 0);\n _defineProperty(this, \"_calibrateSoundBurstFilteredExtraDb\", void 0);\n _defineProperty(this, \"_calibrateSoundBurstLevelReTBool\", void 0);\n _defineProperty(this, \"SDofFilteredRange\", {\n mls: undefined,\n component: undefined,\n system: undefined\n });\n _defineProperty(this, \"transducerType\", 'Loudspeaker');\n _defineProperty(this, \"componentIRPhase\", []);\n _defineProperty(this, \"systemIRPhase\", []);\n _defineProperty(this, \"webAudioDeviceNames\", {\n loudspeaker: '',\n microphone: '',\n loudspeakerText: '',\n microphoneText: ''\n });\n _defineProperty(this, \"waveforms\", {\n volume: {}\n });\n _defineProperty(this, \"recordingChecks\", {\n volume: {},\n unfiltered: [],\n system: [],\n component: [],\n warnings: []\n });\n _defineProperty(this, \"inDB\", void 0);\n _defineProperty(this, \"soundCheck\", '');\n _defineProperty(this, \"filteredMLSRange\", {\n component: {\n Min: null,\n Max: null\n },\n system: {\n Min: null,\n Max: null\n }\n });\n /** @private */\n _defineProperty(this, \"timeStamp\", []);\n _defineProperty(this, \"restartCalibration\", false);\n _defineProperty(this, \"calibrateSoundLimit\", 1);\n _defineProperty(this, \"filteredMLSAttenuation\", {\n component: 1,\n system: 1,\n maxAbsSystem: 1,\n maxAbsComponent: 1\n });\n //parameter result from volume calibration\n _defineProperty(this, \"T\", 0);\n //gainDBSPL result from volume calibration\n _defineProperty(this, \"gainDBSPL\", 0);\n //not always just using _calibrateSoundBurstDb for MLS so created a new parameter\n _defineProperty(this, \"power_dB\", 0);\n //system\n _defineProperty(this, \"systemAttenuatorGainDB\", 0);\n _defineProperty(this, \"systemFMaxHz\", 0);\n //component\n _defineProperty(this, \"componentAttentuatorGainDB\", 0);\n _defineProperty(this, \"componentFMaxHz\", 0);\n _defineProperty(this, \"dL_n\", void 0);\n _defineProperty(this, \"L_new_n\", void 0);\n _defineProperty(this, \"fs2\", void 0);\n _defineProperty(this, \"icapture\", 0);\n _defineProperty(this, \"permissionStatus\", null);\n /**generate string template that gets reevaluated as variable increases */\n _defineProperty(this, \"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 soundSubtitle = document.getElementById(this.soundSubtitleId);\n if (soundSubtitle) {\n const reportWebAudioNames = \"\".concat(this.webAudioDeviceNames.loudspeakerText, \"<br/> \").concat(this.webAudioDeviceNames.microphoneText);\n soundSubtitle.innerHTML = reportWebAudioNames;\n }\n const samplingParamText = this.phrases.RC_SamplingHzBits[this.language].replace('111', this.sourceSamplingRate).replace('222', this.sinkSamplingRate).replace('333', this.calibrateSoundSamplingDesiredBits);\n const reportParameters = \"\".concat(samplingParamText);\n if (this.flags) {\n flags = \"<br> autoGainControl: \".concat(this.flags.autoGainControl, \"; \\n echoCancellation: \").concat(this.flags.echoCancellation, \";\\n noiseSuppression: \").concat(this.flags.noiseSuppression);\n }\n if (this.SDofFilteredRange['mls']) {\n MLSsd = \"<br> Recorded MLS power SD: \".concat(this.SDofFilteredRange['mls'], \" dB\");\n }\n if (this.SDofFilteredRange['system']) {\n systemSD = \"<br> Loudspeaker+Microphone correction SD: \".concat(this.SDofFilteredRange['system'], \" dB\");\n }\n if (this.SDofFilteredRange['component']) {\n componentSD = \"<br> \".concat(this.transducerType, \" correction SD: \").concat(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: \".concat(this.percent_complete, \"%; height: 100%; background-color: #00aaff; border-radius: 8px;\\\"></div></div></div>\");\n return \"\\n \".concat(reportParameters, \" \\n \").concat(MLSsd, \"\\n \").concat(systemSD, \"\\n \").concat(componentSD, \"\\n \").concat(flags, \"\\n <br>\").concat(status, \"\\n \").concat(template);\n });\n /** increment numerator and percent for status bar */\n _defineProperty(this, \"incrementStatusBar\", () => {\n this.status_numerator += 1;\n this.percent_complete = this.status_numerator / this.status_denominator * 100;\n });\n _defineProperty(this, \"setDeviceType\", deviceType => {\n this.deviceType = deviceType;\n });\n _defineProperty(this, \"setDeviceName\", deviceName => {\n this.deviceName = deviceName;\n });\n _defineProperty(this, \"setDeviceInfo\", deviceInfo => {\n this.deviceInfo = deviceInfo;\n });\n _defineProperty(this, \"setPermissionStatus\", permissionStatus => {\n this.permissionStatus = permissionStatus;\n });\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 */\n _defineProperty(this, \"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 = _classPrivateFieldGet(_mls, this)[this.icapture];\n const lowHz = _classPrivateFieldGet(_lowHz, this); //gain of 1 below cutoff, need gain of 0\n const highHz = _classPrivateFieldGet(_highHz, this); //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', {\n message: this.status\n });\n return await this.pyServerAPI.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 }).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', {\n message: this.status\n });\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.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 }).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_8__.findMaxValue)(this.systemConvolution);\n this.filteredMLSAttenuation.system = this.systemConvolution.reduce((a, b) => a + b ** 2, 0) / this.systemConvolution.length;\n this.filteredMLSAttenuation.maxAbsSystem = max;\n }).catch(err => {\n console.error(err);\n });\n });\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 */\n _defineProperty(this, \"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 = _classPrivateFieldGet(_mls, this)[this.icapture];\n const lowHz = _classPrivateFieldGet(_lowHz, this);\n const iirLength = this.iirLength;\n const irLength = this.irLength;\n const highHz = _classPrivateFieldGet(_highHz, this);\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', {\n message: this.status\n });\n console.log();\n return this.pyServerAPI.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 }).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', {\n message: this.status\n });\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.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 }).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_8__.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 = this.componentConvolution.reduce((a, b) => a + b ** 2, 0) / this.componentConvolution.length;\n this.filteredMLSAttenuation.maxAbsComponent = max;\n }).catch(err => {\n // this.emit('InvertedImpulseResponse', {res: false});\n console.error(err);\n });\n });\n _defineProperty(this, \"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 PSD of background');\n this.pyServerAPI.getBackgroundNoisePSDWithRetry({\n background_rec,\n sampleRate: this.sourceSamplingRate || 96000\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 }).catch(err => {\n console.error(err);\n });\n });\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 */\n _defineProperty(this, \"sendRecordingToServerForProcessing\", async signalCsv => {\n const allSignals = this.getAllUnfilteredRecordedSignals();\n console.log('Obtaining last all hz unfiltered recording from #allHzUnfilteredRecordings to send to server for processing');\n const numSignals = allSignals.length;\n const mls = _classPrivateFieldGet(_mlsBufferView, this)[this.icapture];\n const payload = signalCsv && signalCsv.length > 0 ? (0,_utils__WEBPACK_IMPORTED_MODULE_8__.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', {\n message: this.status\n });\n if (this.isCalibrating) return null;\n await this.pyServerAPI.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 }).then(async result => {\n if (result) {\n if (result['sd'] > this._calibrateSoundBurstMaxSD_dB && 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 \".concat(this.inDB, \" dB because SD \").concat(result['sd'], \" > \").concat(this._calibrateSoundBurstMaxSD_dB, \" dB\"));\n this.status = this.generateTemplate(\"All Hz: Re-recording at \".concat(this.inDB, \" dB because SD \").concat(result['sd'], \" > \").concat(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.getAutocorrelation({\n mls: mls,\n payload: payload_skipped_warmUp,\n sampleRate: this.sourceSamplingRate || 96000,\n numPeriods: this.numMLSPerCapture - this.num_mls_to_skip\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(await this.pyServerAPI.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 }).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: \".concat(this.numSuccessfulCaptured, \"/\").concat(this.numCaptures, \" IRs computed...\").toString()).toString();\n this.emit('update', {\n message: this.status\n });\n return res['ir'];\n }).catch(err => {\n console.error(err);\n }));\n });\n }\n console.log('number of unfiltered recording checks:' + this.recordingChecks['unfiltered'].length);\n }\n }).catch(err => {\n console.error(err);\n });\n });\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 */\n _classPrivateFieldInitSpec(this, _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() + \"\\niteration \".concat(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 = _classPrivateFieldGet(_mls, this)[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 = _classPrivateFieldGet(_currentConvolution, this).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 await (0,_utils__WEBPACK_IMPORTED_MODULE_8__.sleep)(time_to_wait);\n });\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 */\n _classPrivateFieldInitSpec(this, _awaitBackgroundNoiseRecording, async () => {\n console.log('Waiting ' + this._calibrateSoundBackgroundSecs + ' second(s) to record background noise');\n let time_to_wait = this._calibrateSoundBackgroundSecs + 0.5;\n this.addTimeStamp(\"Record \".concat(time_to_wait.toFixed(1), \" s of background.\"));\n await (0,_utils__WEBPACK_IMPORTED_MODULE_8__.sleep)(time_to_wait);\n });\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 */\n _classPrivateFieldInitSpec(this, _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 = _classPrivateFieldGet(_mls, this)[0].length / this.sourceSamplingRate * number_of_bursts_to_skip;\n } else if (this.mode === 'filtered') {\n console.log(_classPrivateFieldGet(_currentConvolution, this).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 = _classPrivateFieldGet(_currentConvolution, this).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_8__.sleep)(time_to_sleep);\n });\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 */\n _classPrivateFieldInitSpec(this, _afterMLSRecord, async () => {\n console.log('after record');\n this.addTimeStamp(\"Send MLS to the server\");\n await this.sendRecordingToServerForProcessing();\n });\n _classPrivateFieldInitSpec(this, _afterMLSwIIRRecord, async () => {\n await this.checkPowerVariation();\n });\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 */\n _defineProperty(this, \"createSCurveBuffer\", function () {\n let onSetBool = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 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 /**\r\n * Construct a Calibration Node with the calibration parameters.\r\n *\r\n * @param dataBuffer\r\n * @private\r\n * @example\r\n */\n _classPrivateFieldInitSpec(this, _createCalibrationNodeFromBuffer, dataBuffer => {\n console.log('length databuffer');\n console.log(dataBuffer.length);\n if (!this.sourceAudioContext) {\n this.makeNewSourceAudioContext();\n }\n const buffer = this.sourceAudioContext.createBuffer(1,\n // number of channels\n dataBuffer.length, this.sourceAudioContext.sampleRate // sample rate\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 this.sourceNode = this.sourceAudioContext.createBufferSource();\n this.sourceNode.buffer = buffer;\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 this.sourceNode.connect(this.sourceAudioContext.destination);\n this.addCalibrationNode(this.sourceNode);\n });\n /**\r\n * Given a data buffer, creates the required calibration node\r\n *\r\n * @param {*} dataBufferArray\r\n * @example\r\n */\n _classPrivateFieldInitSpec(this, _setCalibrationNodesFromBuffer, function () {\n let dataBufferArray = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [_classPrivateFieldGet(_mlsBufferView, _this)[_this.icapture]];\n if (dataBufferArray.length === 1) {\n _classPrivateFieldGet(_createCalibrationNodeFromBuffer, _this).call(_this, dataBufferArray[0]);\n } else {\n throw new Error('The length of the data buffer array must be 1');\n }\n });\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 */\n _classPrivateFieldInitSpec(this, _playCalibrationAudio, () => {\n this.calibrationNodes[0].start(0);\n this.status = \"\";\n if (this.mode === 'unfiltered') {\n console.log('play calibration audio ' + this.stepNum);\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(\"Record \".concat(total_dur.toFixed(1), \" s \") + \"(\".concat(pre.toFixed(1), \" + \").concat(repeats, \"\\xD7\").concat(burst.toFixed(1), \" + \").concat(post.toFixed(1), \" s) of MLS ver. \").concat(this.icapture));\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', {\n message: this.status\n });\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 /** .\r\n * .\r\n * .\r\n * Stops the audio with tapered offset\r\n *\r\n * @example\r\n */\n _defineProperty(this, \"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', {\n message: this.status\n });\n });\n _defineProperty(this, \"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(stream, _classPrivateFieldGet(_playCalibrationAudio, this), // play audio func (required)\n _classPrivateFieldGet(_createCalibrationNodeFromBuffer, this).call(this, convolution),\n // before play func\n _classPrivateFieldGet(_awaitSignalOnset, this),\n // before record\n () => this.numSuccessfulCaptured < 2, _classPrivateFieldGet(_awaitDesiredMLSLength, this),\n // during record\n _classPrivateFieldGet(_afterMLSwIIRRecord, this),\n // after record\n this.mode, checkRec);\n });\n _defineProperty(this, \"bothSoundCheck\", async stream => {\n let iir_ir_and_plots;\n _classPrivateFieldSet(_currentConvolution, this, this.componentConvolution);\n this.filteredMLSRange.component.Min = (0,_utils__WEBPACK_IMPORTED_MODULE_8__.findMinValue)(_classPrivateFieldGet(_currentConvolution, this));\n this.filteredMLSRange.component.Max = (0,_utils__WEBPACK_IMPORTED_MODULE_8__.findMaxValue)(_classPrivateFieldGet(_currentConvolution, this));\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 \".concat(total_dur, \" s of MLS with \").concat(this.soundCheck, \" IIR.\\u201D\"));\n if (this.isCalibrating) return null;\n await this.playMLSwithIIR(stream, _classPrivateFieldGet(_currentConvolution, this));\n this.stopCalibrationAudio();\n let component_conv_recs = this.getAllFilteredRecordedSignals();\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 let return_component_conv_rec = component_conv_recs[component_conv_recs.length - 1];\n this.clearAllFilteredRecordedSignals();\n this.numSuccessfulCaptured = 0;\n _classPrivateFieldSet(_currentConvolution, this, this.systemConvolution);\n this.filteredMLSRange.system.Min = (0,_utils__WEBPACK_IMPORTED_MODULE_8__.findMinValue)(_classPrivateFieldGet(_currentConvolution, this));\n this.filteredMLSRange.system.Max = (0,_utils__WEBPACK_IMPORTED_MODULE_8__.findMaxValue)(_classPrivateFieldGet(_currentConvolution, this));\n this.soundCheck = 'system';\n this.addTimeStamp(\"Record \".concat(total_dur, \" s of MLS with \").concat(this.soundCheck, \" IIR.\\u201D\"));\n if (this.isCalibrating) return null;\n await this.playMLSwithIIR(stream, _classPrivateFieldGet(_currentConvolution, this));\n this.stopCalibrationAudio();\n let system_conv_recs = this.getAllFilteredRecordedSignals();\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 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 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.getSubtractedPSDWithRetry(unconv_rec, knownGain, knownFreq, sampleRate).then(res => {\n this.incrementStatusBar();\n this.status = this.generateTemplate(\"All Hz Calibration: done computing the PSD graphs...\".toString()).toString();\n this.emit('update', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\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.getSubtractedPSDWithRetry(conv_rec, knownGain, knownFreq, sampleRate).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_8__.interpolate)(freq, knownFreq[i - 1], knownFreq[i], knownGain[i - 1], knownGain[i]);\n });\n let correctedGain = res.y.map((gain, index) => 10 * Math.log10(gain) - interpolatedGain[index]);\n let filtered_psd = correctedGain.filter((value, index) => res.x[index] >= _classPrivateFieldGet(_lowHz, this) && res.x[index] <= this.componentFMaxHz);\n this.SDofFilteredRange['component'] = (0,_utils__WEBPACK_IMPORTED_MODULE_8__.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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\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.getPSDWithRetry({\n unconv_rec,\n conv_rec,\n sampleRate: this.sourceSamplingRate || 96000\n }).then(res => {\n let filtered_psd = res.y_conv.filter((value, index) => res.x_conv[index] >= _classPrivateFieldGet(_lowHz, this) && res.x_conv[index] <= _classPrivateFieldGet(_highHz, this)).map(value => 10 * Math.log10(value));\n let mls_psd = res.y_unconv.filter((value, index) => res.x_unconv[index] >= _classPrivateFieldGet(_lowHz, this) && res.x_conv[index] <= _classPrivateFieldGet(_highHz, this)).map(value => 10 * Math.log10(value));\n this.SDofFilteredRange['mls'] = (0,_utils__WEBPACK_IMPORTED_MODULE_8__.standardDeviation)(mls_psd);\n console.log('mls_psd', this.SDofFilteredRange['mls']);\n this.SDofFilteredRange['system'] = (0,_utils__WEBPACK_IMPORTED_MODULE_8__.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', {\n message: this.status\n });\n return res;\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.getPSDWithRetry({\n unconv_rec,\n conv_rec,\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\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.getPSDWithRetry({\n unconv_rec,\n conv_rec,\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\n });\n this.addTimeStamp('Compute PSD of MLS sequence');\n if (this.isCalibrating) return null;\n let mls_psd = await this.pyServerAPI.getMLSPSDWithRetry({\n mls: _classPrivateFieldGet(_mlsBufferView, this)[0],\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\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.getMLSPSDWithRetry({\n mls: this.systemConvolution,\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\n });\n let system_no_bandpass_filtered_mls_psd = await this.pyServerAPI.getMLSPSDWithRetry({\n mls: this.systemConvolution,\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\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.getMLSPSDWithRetry({\n mls: this.componentConvolution,\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\n });\n let component_no_bandpass_filtered_mls_psd = await this.pyServerAPI.getMLSPSDWithRetry({\n mls: this.componentConvolutionNoBandpass,\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\n });\n let gainValue = this.getGainDBSPL();\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: _classPrivateFieldGet(_mlsBufferView, this),\n mls_psd: {\n x: mls_psd['x_mls'],\n y: mls_psd['y_mls']\n },\n autocorrelations: this.autocorrelations,\n impulseResponses: []\n };\n return iir_ir_and_plots;\n });\n _defineProperty(this, \"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 _classPrivateFieldSet(_currentConvolution, this, this.componentConvolution);\n this.filteredMLSRange.component.Min = (0,_utils__WEBPACK_IMPORTED_MODULE_8__.findMinValue)(_classPrivateFieldGet(_currentConvolution, this));\n this.filteredMLSRange.component.Max = (0,_utils__WEBPACK_IMPORTED_MODULE_8__.findMaxValue)(_classPrivateFieldGet(_currentConvolution, this));\n this.soundCheck = 'component';\n this.addTimeStamp(\"Record \".concat(total_dur, \" s of MLS with \").concat(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, _classPrivateFieldGet(_currentConvolution, this));\n this.stopCalibrationAudio();\n } else {\n _classPrivateFieldSet(_currentConvolution, this, this.systemConvolution);\n this.filteredMLSRange.system.Min = (0,_utils__WEBPACK_IMPORTED_MODULE_8__.findMinValue)(_classPrivateFieldGet(_currentConvolution, this));\n this.filteredMLSRange.system.Max = (0,_utils__WEBPACK_IMPORTED_MODULE_8__.findMaxValue)(_classPrivateFieldGet(_currentConvolution, this));\n this.soundCheck = 'system';\n this.addTimeStamp(\"Record \".concat(total_dur, \" s of MLS with \").concat(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, _classPrivateFieldGet(_currentConvolution, this));\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.getSubtractedPSDWithRetry(unconv_rec, knownGain, knownFreq, sampleRate).then(res => {\n console.log(res);\n let mls_psd = res.y.filter((value, index) => res.x[index] >= _classPrivateFieldGet(_lowHz, this) && res.x[index] <= this.systemFMaxHz).map(value => 10 * Math.log10(value));\n this.SDofFilteredRange['mls'] = (0,_utils__WEBPACK_IMPORTED_MODULE_8__.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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\n });\n this.addTimeStamp('Compute PSD recording of speaker+ mic IIR-filtered MLS recording');\n if (this.isCalibrating) return null;\n let conv_results = await this.pyServerAPI.getSubtractedPSDWithRetry(conv_rec, knownGain, knownFreq, sampleRate).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_8__.interpolate)(freq, knownFreq[i - 1], knownFreq[i], knownGain[i - 1], knownGain[i]);\n });\n let correctedGain = res.y.map((gain, index) => 10 * Math.log10(gain) - interpolatedGain[index]);\n let filtered_psd = correctedGain.filter((value, index) => res.x[index] >= _classPrivateFieldGet(_lowHz, this) && res.x[index] <= _classPrivateFieldGet(_highHz, this));\n this.SDofFilteredRange['component'] = (0,_utils__WEBPACK_IMPORTED_MODULE_8__.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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\n });\n unconv_rec = this.componentInvertedImpulseResponseNoBandpass;\n conv_rec = this.componentInvertedImpulseResponse;\n this.addTimeStamp('Compute PSD of speaker or mic IIR, with and without bandpass');\n if (this.isCalibrating) return null;\n let component_iir_psd = await this.pyServerAPI.getPSDWithRetry({\n unconv_rec,\n conv_rec,\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\n });\n unconv_rec = this.systemInvertedImpulseResponseNoBandpass;\n conv_rec = this.systemInvertedImpulseResponse;\n this.addTimeStamp('Compute PSD of speaker +mic IIR, with and without bandpass');\n if (this.isCalibrating) return null;\n let system_iir_psd = await this.pyServerAPI.getPSDWithRetry({\n unconv_rec,\n conv_rec,\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\n });\n this.addTimeStamp('Compute PSD of MLS');\n if (this.isCalibrating) return null;\n let mls_psd = await this.pyServerAPI.getMLSPSDWithRetry({\n mls: _classPrivateFieldGet(_mlsBufferView, this)[this.icapture],\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\n });\n this.addTimeStamp('Compute PSD of speaker or mic');\n if (this.isCalibrating) return null;\n let filtered_mls_psd = await this.pyServerAPI.getMLSPSDWithRetry({\n mls: this.componentConvolution,\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\n });\n let filtered_no_bandpass_mls_psd = await this.pyServerAPI.getMLSPSDWithRetry({\n mls: this.componentConvolutionNoBandpass,\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\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: _classPrivateFieldGet(_mlsBufferView, this),\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.getPSDWithRetry({\n unconv_rec,\n conv_rec,\n sampleRate: this.sourceSamplingRate || 96000\n }).then(res => {\n let filtered_psd = res.y_conv.filter((value, index) => res.x_conv[index] >= _classPrivateFieldGet(_lowHz, this) && res.x_conv[index] <= this.systemFMaxHz).map(value => 10 * Math.log10(value));\n let mls_psd = res.y_unconv.filter((value, index) => res.x_unconv[index] >= _classPrivateFieldGet(_lowHz, this) && res.x_conv[index] <= this.systemFMaxHz).map(value => 10 * Math.log10(value));\n this.SDofFilteredRange['mls'] = (0,_utils__WEBPACK_IMPORTED_MODULE_8__.standardDeviation)(mls_psd);\n this.SDofFilteredRange['system'] = (0,_utils__WEBPACK_IMPORTED_MODULE_8__.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', {\n message: this.status\n });\n return res;\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.getPSDWithRetry({\n unconv_rec,\n conv_rec,\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\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.getPSDWithRetry({\n unconv_rec,\n conv_rec,\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\n });\n this.addTimeStamp('Compute PSD of MLS sequence');\n if (this.isCalibrating) return null;\n let mls_psd = await this.pyServerAPI.getMLSPSDWithRetry({\n mls: _classPrivateFieldGet(_mlsBufferView, this)[this.icapture],\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\n });\n this.addTimeStamp('Compute PSD of filtered MLS (system)');\n if (this.isCalibrating) return null;\n let filtered_mls_psd = await this.pyServerAPI.getMLSPSDWithRetry({\n mls: this.systemConvolution,\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\n });\n let filtered_no_bandpass_mls_psd = await this.pyServerAPI.getMLSPSDWithRetry({\n mls: this.systemConvolutionNoBandpass,\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\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: _classPrivateFieldGet(_mlsBufferView, this),\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 if (_classPrivateFieldGet(_download, this)) {\n this.downloadSingleUnfilteredRecording();\n this.downloadSingleFilteredRecording();\n (0,_utils__WEBPACK_IMPORTED_MODULE_8__.saveToCSV)(_classPrivateFieldGet(_mls, this), 'MLS.csv');\n (0,_utils__WEBPACK_IMPORTED_MODULE_8__.saveToCSV)(this.componentConvolution, 'python_component_convolution_mls_iir.csv');\n (0,_utils__WEBPACK_IMPORTED_MODULE_8__.saveToCSV)(this.systemConvolution, 'python_system_convolution_mls_iir.csv');\n (0,_utils__WEBPACK_IMPORTED_MODULE_8__.saveToCSV)(this.componentInvertedImpulseResponse, 'componentIIR.csv');\n (0,_utils__WEBPACK_IMPORTED_MODULE_8__.saveToCSV)(this.systemInvertedImpulseResponse, 'systemIIR.csv');\n for (let i = 0; i < this.autocorrelations.length; i++) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_8__.saveToCSV)(this.autocorrelations[i], \"autocorrelation_\".concat(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_8__.saveToCSV)(res[i], \"IR_\".concat(i));\n }\n }\n });\n }\n return iir_ir_and_plots;\n });\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 */\n _defineProperty(this, \"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 console.log('MLS sequence should be of length: ' + this.sourceSamplingRate * desired_time);\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 if (!this._calibrateSoundBurstLevelReTBool) {\n this.power_dB = this._calibrateSoundBurstDb;\n } else {\n this.power_dB = this._calibrateSoundBurstDb + (this.T - this.gainDBSPL);\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.getMLSWithRetry({\n length,\n amplitude,\n calibrateSoundBurstMLSVersions: this.numCaptures\n }).then(res => {\n console.log(res);\n _classPrivateFieldSet(_mlsBufferView, this, res['mls']);\n _classPrivateFieldSet(_mls, this, res['unscaledMLS']);\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', {\n message: this.status\n });\n if (this.isCalibrating) return null;\n await this.recordBackground(stream,\n //stream\n () => this.numSuccessfulBackgroundCaptured < 1,\n //loop condition\n _classPrivateFieldGet(_awaitBackgroundNoiseRecording, this),\n //sleep to record\n this.sendBackgroundRecording,\n //send to get PSD\n this.mode, checkRec);\n this.incrementStatusBar();\n }\n this.mode = 'unfiltered';\n this.numSuccessfulCaptured = 0;\n if (this.isCalibrating) return null;\n for (var i = 0; i < this.numCaptures; i++) {\n this.icapture = i;\n await this.calibrationSteps(stream, _classPrivateFieldGet(_playCalibrationAudio, this), // play audio func (required)\n _classPrivateFieldGet(_createCalibrationNodeFromBuffer, this).call(this, _classPrivateFieldGet(_mlsBufferView, this)[this.icapture]),\n // before play func\n _classPrivateFieldGet(_awaitSignalOnset, this),\n // before record\n () => this.numSuccessfulCaptured < 2,\n // loop while true\n _classPrivateFieldGet(_awaitDesiredMLSLength, this),\n // during record\n _classPrivateFieldGet(_afterMLSRecord, this),\n // after record\n this.mode, checkRec);\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 this.numSuccessfulCaptured = 0;\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.getPSDWithRetry({\n unconv_rec,\n conv_rec,\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\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.getPSDWithRetry({\n unconv_rec,\n conv_rec,\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\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: _classPrivateFieldGet(_mlsBufferView, this),\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 if (_classPrivateFieldGet(_download, this)) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_8__.saveToCSV)(_classPrivateFieldGet(_mls, this), 'MLS.csv');\n (0,_utils__WEBPACK_IMPORTED_MODULE_8__.saveToCSV)(this.componentConvolution, 'python_component_convolution_mls_iir.csv');\n (0,_utils__WEBPACK_IMPORTED_MODULE_8__.saveToCSV)(this.systemConvolution, 'python_system_convolution_mls_iir.csv');\n (0,_utils__WEBPACK_IMPORTED_MODULE_8__.saveToCSV)(this.componentInvertedImpulseResponse, 'componentIIR.csv');\n (0,_utils__WEBPACK_IMPORTED_MODULE_8__.saveToCSV)(this.systemInvertedImpulseResponse, 'systemIIR.csv');\n for (let i = 0; i < this.autocorrelations.length; i++) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_8__.saveToCSV)(this.autocorrelations[i], \"autocorrelation_\".concat(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_8__.saveToCSV)(res[i], \"IR_\".concat(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.addTimeStamp('Done');\n this.emit('update', {\n message: this.status\n });\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 //////////////////////volume\n _defineProperty(this, \"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: \".concat(data.type));\n }\n });\n _classPrivateFieldInitSpec(this, _getTruncatedSignal, function () {\n let left = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 3.5;\n let right = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 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('Obtaining last 1000 hz recording from #allVolumeRecordings to send for processing');\n /**\r\n * function to check that capture was properly made\r\n * @param {*} list\r\n */\n const checkResult = list => {\n const setItem = new Set(list);\n if (setItem.size === 1 && setItem.has(0)) {\n console.warn('The last capture failed, all recorded signal is zero', _this.getAllVolumeRecordedSignals());\n _this.stopCalibrationAudio();\n _this.isCalibrating = true;\n // restartButton.style.display = 'none';\n _this.emit('update', {\n message: 'Connection failed, hit restart button to reconnect'\n });\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', {\n message: 'Connection failed, hit restart button to reconnect'\n });\n }\n };\n checkResult(result);\n return result;\n });\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 * */\n _classPrivateFieldInitSpec(this, _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 oscilator.frequency.value = _classPrivateFieldGet(_CALIBRATION_TONE_FREQUENCY, this);\n oscilator.type = _classPrivateFieldGet(_CALIBRATION_TONE_TYPE, this);\n gainNode.gain.value = gainValue;\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 const gainValuesOverTime = [];\n const sampleRate = _classPrivateFieldGet(_CALIBRATION_TONE_FREQUENCY, this); // 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 gainValuesOverTime.push(gainValueAtTime);\n }\n this.waveforms['volume'][this.inDB] = gainValuesOverTime;\n this.addCalibrationNode(oscilator);\n });\n /**\r\n * Construct a Calibration Node with the calibration parameters.\r\n *\r\n * @private\r\n * @example\r\n */\n _classPrivateFieldInitSpec(this, _createCalibrationNode, () => {\n const audioContext = this.makeNewSourceAudioContext();\n const oscilator = audioContext.createOscillator();\n const gainNode = audioContext.createGain();\n oscilator.frequency.value = _classPrivateFieldGet(_CALIBRATION_TONE_FREQUENCY, this);\n oscilator.type = _classPrivateFieldGet(_CALIBRATION_TONE_TYPE, this);\n gainNode.gain.value = 0.04;\n oscilator.connect(gainNode);\n gainNode.connect(audioContext.destination);\n this.addCalibrationNode(oscilator);\n });\n _classPrivateFieldInitSpec(this, _playCalibrationAudioVolume, async () => {\n if (this.numCalibratingRoundsCompleted == 1) {\n this.recordingChecks['warnings'].push(\"1000Hz. Re-recorded \".concat(this.inDB, \" dB because SD \").concat(this.recordingChecks['volume'][this.inDB]['sd'], \" > \").concat(this.calibrateSound1000HzMaxSD_dB, \" dB\"));\n const currentStatus = \"1000 Hz: Re-recording at \".concat(this.inDB, \" dB because SD \\n \").concat(this.recordingChecks['volume'][this.inDB]['sd'], \" > \\n \").concat(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 this.calibrationNodes[0].start(0);\n this.calibrationNodes[0].stop(totalDuration);\n console.log(\"Playing a buffer of \".concat(this.CALIBRATION_TONE_DURATION, \" seconds of audio\"));\n console.log(\"Waiting a total of \".concat(totalDuration, \" seconds\"));\n await (0,_utils__WEBPACK_IMPORTED_MODULE_8__.sleep)(totalDuration);\n });\n _defineProperty(this, \"stopCalibrationAudioVolume\", () => {\n if (this.calibrationNodes.length > 0) {\n this.calibrationNodes[0].stop();\n }\n });\n _classPrivateFieldInitSpec(this, _sendToServerForProcessing, async lCalib => {\n console.log('Sending data to server');\n let left = this.calibrateSound1000HzPreSec;\n let right = this.calibrateSound1000HzPreSec + this.calibrateSound1000HzSec;\n if (this.isCalibrating) return null;\n this.pyServerAPI.getVolumeCalibration({\n sampleRate: this.sourceSamplingRate,\n payload: _classPrivateFieldGet(_getTruncatedSignal, this).call(this, left, right),\n lCalib: lCalib\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 }).catch(err => {\n console.warn(err);\n });\n const rec = this.getLastVolumeRecordedSignal();\n console.log('pre period power: ', (0,_powerCheck__WEBPACK_IMPORTED_MODULE_9__.getPower)(rec.slice(0, this.calibrateSound1000HzPreSec * this.sourceSamplingRate)).toFixed(1));\n console.log('pre period power: ', (0,_powerCheck__WEBPACK_IMPORTED_MODULE_9__.getPower)(rec.slice(this.calibrateSound1000HzPreSec * this.sourceSamplingRate, (this.calibrateSound1000HzPreSec + this.calibrateSound1000HzSec) * this.sourceSamplingRate)).toFixed(1));\n console.log('pre period power: ', (0,_powerCheck__WEBPACK_IMPORTED_MODULE_9__.getPower)(rec.slice((this.calibrateSound1000HzPreSec + this.calibrateSound1000HzSec) * this.sourceSamplingRate)).toFixed(1));\n const res = (0,_powerCheck__WEBPACK_IMPORTED_MODULE_9__.volumePowerCheck)(rec, this.sourceSamplingRate || 96000, this.calibrateSound1000HzPreSec, this.calibrateSound1000HzSec, this._calibrateSoundPowerBinDesiredSec);\n console.log(res);\n this.recordingChecks['volume'][this.inDB] = res;\n console.log('Recording checks in sendToServer', this.recordingChecks['volume']);\n const getSD = () => this.recordingChecks['volume'][this.inDB]['sd'];\n // const getSDMessage = () => {\n // //SOUND 6.7 s. 2.5+2.5+0.5 s. 1000 Hz at -60 dB. SD = 1.3 dB\n // // And reporting each rejected recording as\n // // SOUND 6.7 s. 2.5+2.5+0.5 s. 1000 Hz at -60 dB, SD = 19.7 > 4 dB.\n\n // if (this.numCalibratingRoundsCompleted == 1)\n // return `. SD = ${getSD()} > ${this.calibrateSound1000HzMaxSD_dB} dB.`;\n // return `. SD = ${getSD()} dB`;\n // };\n // const total_dur =\n // this.calibrateSound1000HzPreSec +\n // this.calibrateSound1000HzSec +\n // this.calibrateSound1000HzPostSec;\n\n // this.addTimeStamp(\n // `${this.calibrateSound1000HzPreSec.toFixed(1)}` +\n // `+${this.calibrateSound1000HzSec.toFixed(1)}` +\n // `+${this.calibrateSound1000HzPostSec.toFixed(1)} s.` +\n // `1000 Hz at ${this.inDB} dB${getSDMessage()}`\n // );\n });\n _defineProperty(this, \"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 \".concat(soundLevelToDiscard, \" dB\").toString()).toString();\n //this.emit('update', {message: `1000 Hz Calibration: Sound Level ${soundLevelToDiscard} dB`});\n this.emit('update', {\n message: this.status\n });\n this.startTime = new Date().getTime();\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(stream, _classPrivateFieldGet(_playCalibrationAudioVolume, this), _classPrivateFieldGet(_createCalibrationToneWithGainValue, this), _classPrivateFieldGet(_sendToServerForProcessing, this), gainToDiscard, lCalib,\n //todo make this a class parameter\n checkRec, () => {\n return this.recordingChecks['volume'][this.inDB]['sd'];\n }, this.calibrateSound1000HzMaxSD_dB);\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 \".concat(inDB, \" dB\").toString()).toString();\n this.emit('update', {\n message: this.status\n });\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(stream, _classPrivateFieldGet(_playCalibrationAudioVolume, this), _classPrivateFieldGet(_createCalibrationToneWithGainValue, this), _classPrivateFieldGet(_sendToServerForProcessing, this), gainValues[i], lCalib,\n //todo make this a class parameter\n checkRec, () => {\n var _this$recordingChecks;\n return ((_this$recordingChecks = this.recordingChecks) === null || _this$recordingChecks === void 0 || (_this$recordingChecks = _this$recordingChecks['volume']) === null || _this$recordingChecks === void 0 || (_this$recordingChecks = _this$recordingChecks[this.inDB]) === null || _this$recordingChecks === void 0 ? void 0 : _this$recordingChecks['sd']) || 0;\n }, this.calibrateSound1000HzMaxSD_dB);\n } while (this.outDBSPL === null);\n outDBSPL1000Values.push(this.outDBSPL1000);\n thdValues.push(this.THD);\n outDBSPLValues.push(this.outDBSPL);\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 const parameters = await this.pyServerAPI.getVolumeCalibrationParameters({\n inDBValues: inDBValues,\n outDBSPLValues: outDBSPL1000Values,\n lCalib: lCalib,\n componentGainDBSPL\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 return result;\n });\n _defineProperty(this, \"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 = {\n Freq: frq,\n Gain: gain\n };\n const docRef = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.doc)(_config_firebase__WEBPACK_IMPORTED_MODULE_10__[\"default\"], 'Microphones', documentID);\n await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.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 _defineProperty(this, \"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 const data = {\n Freq: sampledFrq,\n Gain: sampledGain\n };\n await (0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.set)((0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_10__[\"default\"], \"Microphone2/\".concat(OEM, \"/\").concat(speakerID, \"/linear\")), data);\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 _defineProperty(this, \"readFrqGainFromFirestore\", async (speakerID, OEM, isDefault) => {\n const collectionRef = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.collection)(_config_firebase__WEBPACK_IMPORTED_MODULE_10__[\"default\"], 'Microphones');\n const q = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.query)(collectionRef, (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.where)('ID', '==', speakerID), (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.where)('lowercaseOEM', '==', OEM), (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.where)('isDefault', '==', isDefault));\n const querySnapshot = await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.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_12__.Timestamp(querySnapshot.docs[0].data().createDate.seconds, querySnapshot.docs[0].data().createDate.nanoseconds);\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 _defineProperty(this, \"readFrqGain\", async (speakerID, OEM) => {\n const dbRef = (0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_10__[\"default\"]);\n const snapshot = await (0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.get)((0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.child)(dbRef, \"Microphone2/\".concat(OEM, \"/\").concat(speakerID, \"/linear\")));\n if (snapshot.exists()) {\n return snapshot.val();\n }\n return null;\n });\n _defineProperty(this, \"readGainat1000HzFromFirestore\", async (speakerID, OEM, isDefault) => {\n const collectionRef = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.collection)(_config_firebase__WEBPACK_IMPORTED_MODULE_10__[\"default\"], 'Microphones');\n const q = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.query)(collectionRef, (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.where)('ID', '==', speakerID), (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.where)('lowercaseOEM', '==', OEM), (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.where)('isDefault', '==', isDefault));\n const querySnapshot = await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.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 _defineProperty(this, \"readGainat1000Hz\", async (speakerID, OEM) => {\n const dbRef = (0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_10__[\"default\"]);\n const snapshot = await (0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.get)((0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.child)(dbRef, \"Microphone2/\".concat(OEM, \"/\").concat(speakerID, \"/Gain1000\")));\n if (snapshot.exists()) {\n return snapshot.val();\n }\n return null;\n });\n _defineProperty(this, \"writeGainat1000HzToFirestore\", async (speakerID, gain, OEM, documentID) => {\n const docRef = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.doc)(_config_firebase__WEBPACK_IMPORTED_MODULE_10__[\"default\"], 'Microphones', documentID);\n await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.updateDoc)(docRef, {\n Gain1000: gain\n });\n });\n _defineProperty(this, \"writeGainat1000Hz\", async (speakerID, gain, OEM) => {\n await (0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.set)((0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_10__[\"default\"], \"Microphone2/\".concat(OEM, \"/\").concat(speakerID, \"/Gain1000\")), gain);\n });\n _defineProperty(this, \"writeIsSmartPhoneToFirestore\", async (speakerID, isSmartPhone, OEM) => {\n const collectionRef = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.collection)(_config_firebase__WEBPACK_IMPORTED_MODULE_10__[\"default\"], 'Microphones');\n const q = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.query)(collectionRef, (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.where)('ID', '==', speakerID), (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.where)('lowercaseOEM', '==', OEM), (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.where)('isDefault', '==', true));\n const querySnapshot = await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.getDocs)(q);\n if (querySnapshot.size > 0) {\n const docRef = await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.addDoc)(collectionRef, {\n isSmartPhone: isSmartPhone,\n isDefault: false\n });\n return docRef.id;\n } else {\n const docRef = await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.addDoc)(collectionRef, {\n isSmartPhone: isSmartPhone,\n isDefault: true\n });\n return docRef.id;\n }\n });\n _defineProperty(this, \"writeIsSmartPhone\", async (speakerID, isSmartPhone, OEM) => {\n const data = {\n isSmartPhone: isSmartPhone\n };\n await (0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.set)((0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_10__[\"default\"], \"Microphone2/\".concat(OEM, \"/\").concat(speakerID, \"/isSmartPhone\")), isSmartPhone);\n });\n _defineProperty(this, \"writeMicrophoneInfoToFirestore\", async (speakerID, micInfo, OEM, documentID) => {\n const docRef = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.doc)(_config_firebase__WEBPACK_IMPORTED_MODULE_10__[\"default\"], 'Microphones', documentID);\n await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.setDoc)(docRef, micInfo, {\n merge: true\n });\n });\n _defineProperty(this, \"doesMicrophoneExistInFirestore\", async (speakerID, OEM, documentID) => {\n const docRef = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.doc)(_config_firebase__WEBPACK_IMPORTED_MODULE_10__[\"default\"], 'Microphone', OEM, speakerID, documentID);\n const docSnap = await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.getDoc)(docRef);\n if (docSnap.exists()) {\n return true;\n }\n return false;\n });\n _defineProperty(this, \"doesMicrophoneExist\", async (speakerID, OEM) => {\n const dbRef = (0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_10__[\"default\"]);\n const snapshot = await (0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.get)((0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.child)(dbRef, \"Microphone2/\".concat(OEM, \"/\").concat(speakerID)));\n if (snapshot.exists()) {\n return true;\n }\n return false;\n });\n _defineProperty(this, \"addMicrophoneInfo\", async (speakerID, OEM, micInfo) => {\n // add to database if /info does not exist\n const dbRef = (0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_10__[\"default\"]);\n const snapshot = await (0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.get)((0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.child)(dbRef, \"Microphone2/\".concat(OEM, \"/\").concat(speakerID, \"/info\")));\n if (!snapshot.exists()) {\n await (0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.set)((0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_10__[\"default\"], \"Microphone2/\".concat(OEM, \"/\").concat(speakerID, \"/info\")), micInfo);\n }\n });\n _defineProperty(this, \"convertToDB\", gain => {\n return Math.log10(gain) * 20;\n });\n _defineProperty(this, \"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 _defineProperty(this, \"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 await this.pyServerAPI.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 }).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 \".concat(this.inDB, \" because SD \").concat(result['sd'], \" > \").concat(this._calibrateSoundBurstMaxSD_dB, \" dB\"));\n this.status = this.generateTemplate(\"All Hz: Re-recording at \".concat(this.inDB, \" dB because SD \").concat(result['sd'], \" > \").concat(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('after mls w iir record for some reason add numSucc capt ' + this.stepNum);\n this.status = this.generateTemplate(\"All Hz Calibration: \".concat(this.numSuccessfulCaptured, \" recording of convolved MLS captured\").toString()).toString();\n this.emit('update', {\n message: this.status\n });\n }\n }\n }\n });\n });\n _defineProperty(this, \"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 _defineProperty(this, \"startCalibration\", async function (stream, gainValues) {\n let lCalib = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 104.92978421490648;\n let componentIR = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;\n let microphoneName = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 'MiniDSP-UMIK1-711-4754-vertical';\n let _calibrateSoundCheck = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 'goal';\n let isSmartPhone = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : false;\n let _calibrateSoundBurstDb = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : -18;\n let _calibrateSoundBurstFilteredExtraDb = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : 6;\n let _calibrateSoundBurstLevelReTBool = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : false;\n let _calibrateSoundBurstUses1000HzGainBool = arguments.length > 10 && arguments[10] !== undefined ? arguments[10] : false;\n let _calibrateSoundBurstRepeats = arguments.length > 11 && arguments[11] !== undefined ? arguments[11] : 3;\n let _calibrateSoundBurstSec = arguments.length > 12 && arguments[12] !== undefined ? arguments[12] : 1;\n let _calibrateSoundBurstPreSec = arguments.length > 13 && arguments[13] !== undefined ? arguments[13] : 1;\n let _calibrateSoundBurstPostSec = arguments.length > 14 && arguments[14] !== undefined ? arguments[14] : 1;\n let _calibrateSoundHz = arguments.length > 15 && arguments[15] !== undefined ? arguments[15] : 48000;\n let _calibrateSoundIRSec = arguments.length > 16 && arguments[16] !== undefined ? arguments[16] : 0.2;\n let _calibrateSoundIIRSec = arguments.length > 17 && arguments[17] !== undefined ? arguments[17] : 0.2;\n let _calibrateSoundIIRPhase = arguments.length > 18 && arguments[18] !== undefined ? arguments[18] : 'linear';\n let calibrateSound1000HzPreSec = arguments.length > 19 && arguments[19] !== undefined ? arguments[19] : 0.5;\n let calibrateSound1000HzSec = arguments.length > 20 && arguments[20] !== undefined ? arguments[20] : 0.5;\n let calibrateSound1000HzPostSec = arguments.length > 21 && arguments[21] !== undefined ? arguments[21] : 0.5;\n let _calibrateSoundBackgroundSecs = arguments.length > 22 && arguments[22] !== undefined ? arguments[22] : 0;\n let _calibrateSoundSmoothOctaves = arguments.length > 23 && arguments[23] !== undefined ? arguments[23] : 0.33;\n let _calibrateSoundSmoothMinBandwidthHz = arguments.length > 24 && arguments[24] !== undefined ? arguments[24] : 200;\n let _calibrateSoundPowerBinDesiredSec = arguments.length > 25 && arguments[25] !== undefined ? arguments[25] : 0.2;\n let _calibrateSoundPowerDbSDToleratedDb = arguments.length > 26 && arguments[26] !== undefined ? arguments[26] : 1;\n let _calibrateSoundTaperSec = arguments.length > 27 && arguments[27] !== undefined ? arguments[27] : 0.01;\n let micManufacturer = arguments.length > 28 && arguments[28] !== undefined ? arguments[28] : '';\n let micSerialNumber = arguments.length > 29 && arguments[29] !== undefined ? arguments[29] : '';\n let micModelNumber = arguments.length > 30 && arguments[30] !== undefined ? arguments[30] : '';\n let micModelName = arguments.length > 31 && arguments[31] !== undefined ? arguments[31] : '';\n let calibrateMicrophonesBool = arguments.length > 32 ? arguments[32] : undefined;\n let authorEmails = arguments.length > 33 ? arguments[33] : undefined;\n let webAudioDeviceNames = arguments.length > 34 && arguments[34] !== undefined ? arguments[34] : {\n loudspeaker: 'loudspeaker',\n microphone: 'microphone',\n microphoneText: 'xxx XXX'\n };\n let userIDs = arguments.length > 35 ? arguments[35] : undefined;\n let restartButton = arguments.length > 36 ? arguments[36] : undefined;\n let reminder = arguments.length > 37 ? arguments[37] : undefined;\n let calibrateSoundLimit = arguments.length > 38 ? arguments[38] : undefined;\n let _calibrateSoundBurstNormalizeBy1000HzGainBool = arguments.length > 39 && arguments[39] !== undefined ? arguments[39] : false;\n let _calibrateSoundBurstScalarDB = arguments.length > 40 && arguments[40] !== undefined ? arguments[40] : 71;\n let calibrateSound1000HzMaxSD_dB = arguments.length > 41 && arguments[41] !== undefined ? arguments[41] : 4;\n let _calibrateSoundBurstMaxSD_dB = arguments.length > 42 && arguments[42] !== undefined ? arguments[42] : 4;\n let calibrateSoundSamplingDesiredBits = arguments.length > 43 && arguments[43] !== undefined ? arguments[43] : 24;\n let language = arguments.length > 44 ? arguments[44] : undefined;\n let loudspeakerModelName = arguments.length > 45 && arguments[45] !== undefined ? arguments[45] : '';\n let phrases = arguments.length > 46 ? arguments[46] : undefined;\n let soundSubtitleId = arguments.length > 47 ? arguments[47] : undefined;\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 = 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 = _calibrateSoundBurstNormalizeBy1000HzGainBool;\n _this._calibrateSoundBurstScalarDB = _calibrateSoundBurstScalarDB;\n _this.webAudioDeviceNames = webAudioDeviceNames;\n _this.calibrateSoundSamplingDesiredBits = calibrateSoundSamplingDesiredBits;\n _this.phrases = phrases;\n _this.soundSubtitleId = soundSubtitleId;\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].replace('“xxx”', combinedMicText).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 ? micModelName === 'UMIK-1' || micModelName === 'UMIK-2' ? 'minidsp' : _this.deviceInfo.OEM ? _this.deviceInfo.OEM.toLowerCase().split(' ').join('') : micManufacturer.toLowerCase().split(' ').join('') : micManufacturer.toLowerCase().split(' ').join('');\n // const ID = \"712-5669\";\n // const OEM = \"minidsp\";\n const micInfo = {\n micModelName: isSmartPhone ? micModelName : microphoneName,\n OEM: isSmartPhone ? micModelName === 'UMIK-1' || micModelName === 'UMIK-2' ? 'miniDSP' : _this.deviceInfo.OEM : micManufacturer,\n ID: ID,\n createDate: new Date(),\n DateText: (0,_utils__WEBPACK_IMPORTED_MODULE_8__.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 ? 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 = \"Microphone (\".concat(OEM, \",\").concat(ID, \") is not found in the database. Please add it to the database.\").toString();\n _this.emit('update', {\n message: _this.status\n });\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 _this.oldComponentIR = JSON.parse(JSON.stringify(_this.componentIR));\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', {\n message: 'Restarting calibration...'\n });\n resolve('restart');\n });\n }\n await _this.pyServerAPI.checkMemory();\n // calibrate volume\n\n let volumeResults = await _this.startCalibrationVolume(stream, gainValues, lCalib, _this.componentGainDBSPL);\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['background_noise']['recording'].map(value => value / linearScaleAttenuation);\n impulseResponseResults['system']['background_noise']['x_background'] = impulseResponseResults['background_noise']['x_background'];\n impulseResponseResults['system']['background_noise']['y_background'] = impulseResponseResults['background_noise']['y_background'].map(value => value / linearScalePowerAttenuation);\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'] = impulseResponseResults['background_noise']['recording'].map(value => value / linearScaleAttenuation);\n impulseResponseResults['component']['background_noise']['x_background'] = impulseResponseResults['background_noise']['x_background'];\n impulseResponseResults['component']['background_noise']['y_background'] = impulseResponseResults['background_noise']['y_background'].map(value => value / linearScalePowerAttenuation);\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 if (componentIR != null) {\n var _impulseResponseResul;\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 = Math.round((volumeResults.parameters.gainDBSPL - _this.componentGainDBSPL) * 10) / 10;\n let IrFreq = impulseResponseResults === null || impulseResponseResults === void 0 ? void 0 : impulseResponseResults.component.ir.Freq.map(freq => Math.round(freq));\n let IrGain = impulseResponseResults === null || impulseResponseResults === void 0 || (_impulseResponseResul = impulseResponseResults.component) === null || _impulseResponseResul === void 0 ? void 0 : _impulseResponseResul.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 = {\n ...volumeResults,\n ...impulseResponseResults\n };\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 total_results['permissionStatus'] = _this.permissionStatus;\n console.log('total results');\n console.log(total_results);\n console.log('Time Stamps');\n console.log(timeStampresult);\n resolve(total_results);\n });\n });\n _classPrivateFieldSet(_mlsOrder, this, parseInt(mlsOrder, 10));\n _classPrivateFieldSet(_P, this, 2 ** mlsOrder - 1);\n _classPrivateFieldSet(_download, this, download);\n _classPrivateFieldSet(_mls, this, []);\n _classPrivateFieldSet(_lowHz, this, _lowHz2);\n _classPrivateFieldSet(_highHz, this, _highHz2);\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_defineProperty(Combination, \"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/* harmony default export */ __webpack_exports__[\"default\"] = (Combination);\n\n//# sourceURL=webpack://speakerCalibrator/./src/tasks/combination/combination.js?");
|
|
183
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_array_buffer_slice_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array-buffer.slice.js */ \"./node_modules/core-js/modules/es.array-buffer.slice.js\");\n/* harmony import */ var core_js_modules_es_array_buffer_slice_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_buffer_slice_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_es_string_replace_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/es.string.replace.js */ \"./node_modules/core-js/modules/es.string.replace.js\");\n/* harmony import */ var core_js_modules_es_string_replace_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_string_replace_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_es_typed_array_float32_array_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/es.typed-array.float32-array.js */ \"./node_modules/core-js/modules/es.typed-array.float32-array.js\");\n/* harmony import */ var core_js_modules_es_typed_array_float32_array_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_typed_array_float32_array_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var core_js_modules_es_typed_array_fill_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! core-js/modules/es.typed-array.fill.js */ \"./node_modules/core-js/modules/es.typed-array.fill.js\");\n/* harmony import */ var core_js_modules_es_typed_array_fill_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_typed_array_fill_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var core_js_modules_es_typed_array_set_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! core-js/modules/es.typed-array.set.js */ \"./node_modules/core-js/modules/es.typed-array.set.js\");\n/* harmony import */ var core_js_modules_es_typed_array_set_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_typed_array_set_js__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var core_js_modules_es_typed_array_sort_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! core-js/modules/es.typed-array.sort.js */ \"./node_modules/core-js/modules/es.typed-array.sort.js\");\n/* harmony import */ var core_js_modules_es_typed_array_sort_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_typed_array_sort_js__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! core-js/modules/web.dom-collections.iterator.js */ \"./node_modules/core-js/modules/web.dom-collections.iterator.js\");\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_6__);\n/* harmony import */ var _audioCalibrator__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../audioCalibrator */ \"./src/tasks/audioCalibrator.js\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../utils */ \"./src/utils.js\");\n/* harmony import */ var _powerCheck__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../powerCheck */ \"./src/powerCheck.js\");\n/* harmony import */ var _config_firebase__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../../config/firebase */ \"./src/config/firebase.js\");\n/* harmony import */ var firebase_database__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! firebase/database */ \"./node_modules/firebase/database/dist/esm/index.esm.js\");\n/* harmony import */ var firebase_firestore__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! firebase/firestore */ \"./node_modules/firebase/firestore/dist/esm/index.esm.js\");\n\n\n\n\n\n\n\nfunction _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }\nfunction _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError(\"Cannot initialize the same private elements twice on an object\"); }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }\nfunction _classPrivateFieldSet(s, a, r) { return s.set(_assertClassBrand(s, a), r), r; }\nfunction _assertClassBrand(e, t, n) { if (\"function\" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError(\"Private element is not present on this object\"); }\n\n\n\n\n\n\n//import { phrases } from '../../../dist/example/i18n';\n\n/**\n *\n */\nvar _download = /*#__PURE__*/new WeakMap();\nvar _mlsGenInterface = /*#__PURE__*/new WeakMap();\nvar _mlsBufferView = /*#__PURE__*/new WeakMap();\nvar _mlsOrder = /*#__PURE__*/new WeakMap();\nvar _lowHz = /*#__PURE__*/new WeakMap();\nvar _highHz = /*#__PURE__*/new WeakMap();\nvar _mls = /*#__PURE__*/new WeakMap();\nvar _P = /*#__PURE__*/new WeakMap();\nvar _audioContext = /*#__PURE__*/new WeakMap();\nvar _CALIBRATION_TONE_FREQUENCY = /*#__PURE__*/new WeakMap();\nvar _CALIBRATION_TONE_TYPE = /*#__PURE__*/new WeakMap();\nvar _currentConvolution = /*#__PURE__*/new WeakMap();\nvar _awaitDesiredMLSLength = /*#__PURE__*/new WeakMap();\nvar _awaitBackgroundNoiseRecording = /*#__PURE__*/new WeakMap();\nvar _awaitSignalOnset = /*#__PURE__*/new WeakMap();\nvar _afterMLSRecord = /*#__PURE__*/new WeakMap();\nvar _afterMLSwIIRRecord = /*#__PURE__*/new WeakMap();\nvar _createCalibrationNodeFromBuffer = /*#__PURE__*/new WeakMap();\nvar _setCalibrationNodesFromBuffer = /*#__PURE__*/new WeakMap();\nvar _playCalibrationAudio = /*#__PURE__*/new WeakMap();\nvar _getTruncatedSignal = /*#__PURE__*/new WeakMap();\nvar _createCalibrationToneWithGainValue = /*#__PURE__*/new WeakMap();\nvar _createCalibrationNode = /*#__PURE__*/new WeakMap();\nvar _playCalibrationAudioVolume = /*#__PURE__*/new WeakMap();\nvar _sendToServerForProcessing = /*#__PURE__*/new WeakMap();\nclass Combination extends _audioCalibrator__WEBPACK_IMPORTED_MODULE_7__[\"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(_ref) {\n var _this;\n let {\n download = false,\n mlsOrder = 18,\n numCaptures = 3,\n numMLSPerCapture = 2,\n lowHz: _lowHz2 = 20,\n highHz: _highHz2 = 10000\n } = _ref;\n super(numCaptures, numMLSPerCapture);\n _this = this;\n /** @private */\n _defineProperty(this, \"stepNum\", 0);\n /** @private */\n _defineProperty(this, \"totalSteps\", 25);\n /** @private */\n _classPrivateFieldInitSpec(this, _download, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _mlsGenInterface, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _mlsBufferView, void 0);\n /** @private */\n _defineProperty(this, \"componentInvertedImpulseResponse\", null);\n /** @private */\n _defineProperty(this, \"systemInvertedImpulseResponse\", null);\n //averaged and subtracted ir returned from calibration used to calculated iir\n /** @private */\n _defineProperty(this, \"ir\", null);\n /** @private */\n _defineProperty(this, \"impulseResponses\", []);\n /** @private */\n _classPrivateFieldInitSpec(this, _mlsOrder, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _lowHz, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _highHz, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _mls, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _P, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _audioContext, void 0);\n /** @private */\n _defineProperty(this, \"offsetGainNode\", void 0);\n /** @private */\n _defineProperty(this, \"componentConvolution\", void 0);\n /** @private */\n _defineProperty(this, \"componentConvolutionNoBandpass\", void 0);\n /** @private */\n _defineProperty(this, \"componentIROrigin\", {\n Freq: [],\n Gain: []\n });\n /** @private */\n _defineProperty(this, \"systemConvolution\", void 0);\n /** @private */\n _defineProperty(this, \"systemConvolutionNoBandpass\", void 0);\n ////////////////////////volume\n /** @private */\n _classPrivateFieldInitSpec(this, _CALIBRATION_TONE_FREQUENCY, 1000);\n // Hz\n\n /** @private */\n _classPrivateFieldInitSpec(this, _CALIBRATION_TONE_TYPE, 'sine');\n _defineProperty(this, \"CALIBRATION_TONE_DURATION\", 5);\n // seconds\n _defineProperty(this, \"calibrateSound1000HzPreSec\", 3.5);\n _defineProperty(this, \"calibrateSound1000HzSec\", 1.0);\n _defineProperty(this, \"calibrateSound1000HzPostSec\", 0.5);\n /** @private */\n _defineProperty(this, \"outDBSPL\", null);\n _defineProperty(this, \"THD\", null);\n _defineProperty(this, \"outDBSPL1000\", null);\n /** @private */\n _defineProperty(this, \"TAPER_SECS\", 0.01);\n // seconds\n /** @private */\n _defineProperty(this, \"status_denominator\", 8);\n /** @private */\n _defineProperty(this, \"status_numerator\", 0);\n /** @private */\n _defineProperty(this, \"percent_complete\", 0);\n /** @private */\n _defineProperty(this, \"status\", \"\");\n /**@private */\n _defineProperty(this, \"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: \".concat(this.percent_complete, \"%; height: 100%; background-color: #00aaff; border-radius: 8px;\\\"></div></div></div>\"));\n /**@private */\n _defineProperty(this, \"componentIR\", null);\n /**@private */\n _defineProperty(this, \"oldComponentIR\", null);\n /**@private */\n _defineProperty(this, \"systemIR\", null);\n /**@private */\n _defineProperty(this, \"_calibrateSoundCheck\", '');\n _defineProperty(this, \"deviceType\", null);\n _defineProperty(this, \"deviceName\", null);\n _defineProperty(this, \"deviceInfo\", null);\n _defineProperty(this, \"desired_time_per_mls\", 0);\n _defineProperty(this, \"num_mls_to_skip\", 0);\n _defineProperty(this, \"desired_sampling_rate\", 0);\n _classPrivateFieldInitSpec(this, _currentConvolution, []);\n _defineProperty(this, \"mode\", 'unfiltered');\n _defineProperty(this, \"sourceNode\", void 0);\n _defineProperty(this, \"autocorrelations\", []);\n _defineProperty(this, \"iirLength\", 0);\n _defineProperty(this, \"irLength\", 0);\n _defineProperty(this, \"calibrateSoundIIRPhase\", 'linear');\n _defineProperty(this, \"componentInvertedImpulseResponseNoBandpass\", []);\n _defineProperty(this, \"componentIRInTimeDomain\", []);\n _defineProperty(this, \"systemInvertedImpulseResponseNoBandpass\", []);\n _defineProperty(this, \"_calibrateSoundBackgroundSecs\", void 0);\n _defineProperty(this, \"_calibrateSoundSmoothOctaves\", void 0);\n _defineProperty(this, \"background_noise\", {});\n _defineProperty(this, \"numSuccessfulBackgroundCaptured\", void 0);\n _defineProperty(this, \"_calibrateSoundBurstDb\", void 0);\n _defineProperty(this, \"_calibrateSoundBurstFilteredExtraDb\", void 0);\n _defineProperty(this, \"_calibrateSoundBurstLevelReTBool\", void 0);\n _defineProperty(this, \"SDofFilteredRange\", {\n mls: undefined,\n component: undefined,\n system: undefined\n });\n _defineProperty(this, \"transducerType\", 'Loudspeaker');\n _defineProperty(this, \"componentIRPhase\", []);\n _defineProperty(this, \"systemIRPhase\", []);\n _defineProperty(this, \"webAudioDeviceNames\", {\n loudspeaker: '',\n microphone: '',\n loudspeakerText: '',\n microphoneText: ''\n });\n _defineProperty(this, \"waveforms\", {\n volume: {}\n });\n _defineProperty(this, \"recordingChecks\", {\n volume: {},\n unfiltered: [],\n system: [],\n component: [],\n warnings: []\n });\n _defineProperty(this, \"inDB\", void 0);\n _defineProperty(this, \"soundCheck\", '');\n _defineProperty(this, \"filteredMLSRange\", {\n component: {\n Min: null,\n Max: null\n },\n system: {\n Min: null,\n Max: null\n }\n });\n /** @private */\n _defineProperty(this, \"timeStamp\", []);\n _defineProperty(this, \"restartCalibration\", false);\n _defineProperty(this, \"calibrateSoundLimit\", 1);\n _defineProperty(this, \"filteredMLSAttenuation\", {\n component: 1,\n system: 1,\n maxAbsSystem: 1,\n maxAbsComponent: 1\n });\n //parameter result from volume calibration\n _defineProperty(this, \"T\", 0);\n //gainDBSPL result from volume calibration\n _defineProperty(this, \"gainDBSPL\", 0);\n //not always just using _calibrateSoundBurstDb for MLS so created a new parameter\n _defineProperty(this, \"power_dB\", 0);\n //system\n _defineProperty(this, \"systemAttenuatorGainDB\", 0);\n _defineProperty(this, \"systemFMaxHz\", 0);\n //component\n _defineProperty(this, \"componentAttentuatorGainDB\", 0);\n _defineProperty(this, \"componentFMaxHz\", 0);\n _defineProperty(this, \"dL_n\", void 0);\n _defineProperty(this, \"L_new_n\", void 0);\n _defineProperty(this, \"fs2\", void 0);\n _defineProperty(this, \"icapture\", 0);\n _defineProperty(this, \"permissionStatus\", null);\n /**generate string template that gets reevaluated as variable increases */\n _defineProperty(this, \"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 soundSubtitle = document.getElementById(this.soundSubtitleId);\n if (soundSubtitle) {\n const reportWebAudioNames = \"\".concat(this.webAudioDeviceNames.loudspeakerText, \"<br/> \").concat(this.webAudioDeviceNames.microphoneText);\n soundSubtitle.innerHTML = reportWebAudioNames;\n }\n const samplingParamText = this.phrases.RC_SamplingHzBits[this.language].replace('111', this.sourceSamplingRate).replace('222', this.sinkSamplingRate).replace('333', this.calibrateSoundSamplingDesiredBits);\n const reportParameters = \"\".concat(samplingParamText);\n if (this.flags) {\n flags = \"<br> autoGainControl: \".concat(this.flags.autoGainControl, \"; \\n echoCancellation: \").concat(this.flags.echoCancellation, \";\\n noiseSuppression: \").concat(this.flags.noiseSuppression);\n }\n if (this.SDofFilteredRange['mls']) {\n MLSsd = \"<br> Recorded MLS power SD: \".concat(this.SDofFilteredRange['mls'], \" dB\");\n }\n if (this.SDofFilteredRange['system']) {\n systemSD = \"<br> Loudspeaker+Microphone correction SD: \".concat(this.SDofFilteredRange['system'], \" dB\");\n }\n if (this.SDofFilteredRange['component']) {\n componentSD = \"<br> \".concat(this.transducerType, \" correction SD: \").concat(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: \".concat(this.percent_complete, \"%; height: 100%; background-color: #00aaff; border-radius: 8px;\\\"></div></div></div>\");\n return \"\\n \".concat(reportParameters, \" \\n \").concat(MLSsd, \"\\n \").concat(systemSD, \"\\n \").concat(componentSD, \"\\n \").concat(flags, \"\\n <br>\").concat(status, \"\\n \").concat(template);\n });\n /** increment numerator and percent for status bar */\n _defineProperty(this, \"incrementStatusBar\", () => {\n this.status_numerator += 1;\n this.percent_complete = this.status_numerator / this.status_denominator * 100;\n });\n _defineProperty(this, \"setDeviceType\", deviceType => {\n this.deviceType = deviceType;\n });\n _defineProperty(this, \"setDeviceName\", deviceName => {\n this.deviceName = deviceName;\n });\n _defineProperty(this, \"setDeviceInfo\", deviceInfo => {\n this.deviceInfo = deviceInfo;\n });\n _defineProperty(this, \"setPermissionStatus\", permissionStatus => {\n this.permissionStatus = permissionStatus;\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 _defineProperty(this, \"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 = _classPrivateFieldGet(_mls, this)[this.icapture];\n const lowHz = _classPrivateFieldGet(_lowHz, this); //gain of 1 below cutoff, need gain of 0\n const highHz = _classPrivateFieldGet(_highHz, this); //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', {\n message: this.status\n });\n return await this.pyServerAPI.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 }).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', {\n message: this.status\n });\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.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 }).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_8__.findMaxValue)(this.systemConvolution);\n this.filteredMLSAttenuation.system = this.systemConvolution.reduce((a, b) => a + b ** 2, 0) / this.systemConvolution.length;\n this.filteredMLSAttenuation.maxAbsSystem = max;\n }).catch(err => {\n console.error(err);\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 _defineProperty(this, \"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 = _classPrivateFieldGet(_mls, this)[this.icapture];\n const lowHz = _classPrivateFieldGet(_lowHz, this);\n const iirLength = this.iirLength;\n const irLength = this.irLength;\n const highHz = _classPrivateFieldGet(_highHz, this);\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', {\n message: this.status\n });\n console.log();\n return this.pyServerAPI.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 }).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', {\n message: this.status\n });\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.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 }).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_8__.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 = this.componentConvolution.reduce((a, b) => a + b ** 2, 0) / this.componentConvolution.length;\n this.filteredMLSAttenuation.maxAbsComponent = max;\n }).catch(err => {\n // this.emit('InvertedImpulseResponse', {res: false});\n console.error(err);\n });\n });\n _defineProperty(this, \"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 PSD of background');\n this.pyServerAPI.getBackgroundNoisePSDWithRetry({\n background_rec,\n sampleRate: this.sourceSamplingRate || 96000\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 }).catch(err => {\n console.error(err);\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 _defineProperty(this, \"sendRecordingToServerForProcessing\", async signalCsv => {\n const allSignals = this.getAllUnfilteredRecordedSignals();\n console.log('Obtaining last all hz unfiltered recording from #allHzUnfilteredRecordings to send to server for processing');\n const numSignals = allSignals.length;\n const mls = _classPrivateFieldGet(_mlsBufferView, this)[this.icapture];\n const payload = signalCsv && signalCsv.length > 0 ? (0,_utils__WEBPACK_IMPORTED_MODULE_8__.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', {\n message: this.status\n });\n if (this.isCalibrating) return null;\n await this.pyServerAPI.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 }).then(async result => {\n if (result) {\n if (result['sd'] > this._calibrateSoundBurstMaxSD_dB && 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 \".concat(this.inDB, \" dB because SD \").concat(result['sd'], \" > \").concat(this._calibrateSoundBurstMaxSD_dB, \" dB\"));\n this.status = this.generateTemplate(\"All Hz: Re-recording at \".concat(this.inDB, \" dB because SD \").concat(result['sd'], \" > \").concat(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.getAutocorrelation({\n mls: mls,\n payload: payload_skipped_warmUp,\n sampleRate: this.sourceSamplingRate || 96000,\n numPeriods: this.numMLSPerCapture - this.num_mls_to_skip\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(await this.pyServerAPI.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 }).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: \".concat(this.numSuccessfulCaptured, \"/\").concat(this.numCaptures, \" IRs computed...\").toString()).toString();\n this.emit('update', {\n message: this.status\n });\n return res['ir'];\n }).catch(err => {\n console.error(err);\n }));\n });\n }\n console.log('number of unfiltered recording checks:' + this.recordingChecks['unfiltered'].length);\n }\n }).catch(err => {\n console.error(err);\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 _classPrivateFieldInitSpec(this, _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() + \"\\niteration \".concat(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 = _classPrivateFieldGet(_mls, this)[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 = _classPrivateFieldGet(_currentConvolution, this).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 await (0,_utils__WEBPACK_IMPORTED_MODULE_8__.sleep)(time_to_wait);\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 _classPrivateFieldInitSpec(this, _awaitBackgroundNoiseRecording, async () => {\n console.log('Waiting ' + this._calibrateSoundBackgroundSecs + ' second(s) to record background noise');\n let time_to_wait = this._calibrateSoundBackgroundSecs + 0.5;\n this.addTimeStamp(\"Record \".concat(time_to_wait.toFixed(1), \" s of background.\"));\n await (0,_utils__WEBPACK_IMPORTED_MODULE_8__.sleep)(time_to_wait);\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 _classPrivateFieldInitSpec(this, _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 = _classPrivateFieldGet(_mls, this)[0].length / this.sourceSamplingRate * number_of_bursts_to_skip;\n } else if (this.mode === 'filtered') {\n console.log(_classPrivateFieldGet(_currentConvolution, this).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 = _classPrivateFieldGet(_currentConvolution, this).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_8__.sleep)(time_to_sleep);\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 _classPrivateFieldInitSpec(this, _afterMLSRecord, async () => {\n console.log('after record');\n this.addTimeStamp(\"Send MLS to the server\");\n await this.sendRecordingToServerForProcessing();\n });\n _classPrivateFieldInitSpec(this, _afterMLSwIIRRecord, async () => {\n await this.checkPowerVariation();\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 _defineProperty(this, \"createSCurveBuffer\", function () {\n let onSetBool = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 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 * Construct a Calibration Node with the calibration parameters.\n *\n * @param dataBuffer\n * @private\n * @example\n */\n _classPrivateFieldInitSpec(this, _createCalibrationNodeFromBuffer, dataBuffer => {\n console.log('length databuffer');\n console.log(dataBuffer.length);\n if (!this.sourceAudioContext) {\n this.makeNewSourceAudioContext();\n }\n const buffer = this.sourceAudioContext.createBuffer(1,\n // number of channels\n dataBuffer.length, this.sourceAudioContext.sampleRate // sample rate\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 this.sourceNode = this.sourceAudioContext.createBufferSource();\n this.sourceNode.buffer = buffer;\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 this.sourceNode.connect(this.sourceAudioContext.destination);\n this.addCalibrationNode(this.sourceNode);\n });\n /**\n * Given a data buffer, creates the required calibration node\n *\n * @param {*} dataBufferArray\n * @example\n */\n _classPrivateFieldInitSpec(this, _setCalibrationNodesFromBuffer, function () {\n let dataBufferArray = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [_classPrivateFieldGet(_mlsBufferView, _this)[_this.icapture]];\n if (dataBufferArray.length === 1) {\n _classPrivateFieldGet(_createCalibrationNodeFromBuffer, _this).call(_this, dataBufferArray[0]);\n } else {\n throw new Error('The length of the data buffer array must be 1');\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 _classPrivateFieldInitSpec(this, _playCalibrationAudio, () => {\n this.calibrationNodes[0].start(0);\n this.status = \"\";\n if (this.mode === 'unfiltered') {\n console.log('play calibration audio ' + this.stepNum);\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(\"Record \".concat(total_dur.toFixed(1), \" s \") + \"(\".concat(pre.toFixed(1), \" + \").concat(repeats, \"\\xD7\").concat(burst.toFixed(1), \" + \").concat(post.toFixed(1), \" s) of MLS ver. \").concat(this.icapture));\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', {\n message: this.status\n });\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 * Stops the audio with tapered offset\n *\n * @example\n */\n _defineProperty(this, \"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', {\n message: this.status\n });\n });\n _defineProperty(this, \"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(stream, _classPrivateFieldGet(_playCalibrationAudio, this), // play audio func (required)\n _classPrivateFieldGet(_createCalibrationNodeFromBuffer, this).call(this, convolution),\n // before play func\n _classPrivateFieldGet(_awaitSignalOnset, this),\n // before record\n () => this.numSuccessfulCaptured < 2, _classPrivateFieldGet(_awaitDesiredMLSLength, this),\n // during record\n _classPrivateFieldGet(_afterMLSwIIRRecord, this),\n // after record\n this.mode, checkRec);\n });\n _defineProperty(this, \"bothSoundCheck\", async stream => {\n let iir_ir_and_plots;\n _classPrivateFieldSet(_currentConvolution, this, this.componentConvolution);\n this.filteredMLSRange.component.Min = (0,_utils__WEBPACK_IMPORTED_MODULE_8__.findMinValue)(_classPrivateFieldGet(_currentConvolution, this));\n this.filteredMLSRange.component.Max = (0,_utils__WEBPACK_IMPORTED_MODULE_8__.findMaxValue)(_classPrivateFieldGet(_currentConvolution, this));\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 \".concat(total_dur, \" s of MLS with \").concat(this.soundCheck, \" IIR.\\u201D\"));\n if (this.isCalibrating) return null;\n await this.playMLSwithIIR(stream, _classPrivateFieldGet(_currentConvolution, this));\n this.stopCalibrationAudio();\n let component_conv_recs = this.getAllFilteredRecordedSignals();\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 let return_component_conv_rec = component_conv_recs[component_conv_recs.length - 1];\n this.clearAllFilteredRecordedSignals();\n this.numSuccessfulCaptured = 0;\n _classPrivateFieldSet(_currentConvolution, this, this.systemConvolution);\n this.filteredMLSRange.system.Min = (0,_utils__WEBPACK_IMPORTED_MODULE_8__.findMinValue)(_classPrivateFieldGet(_currentConvolution, this));\n this.filteredMLSRange.system.Max = (0,_utils__WEBPACK_IMPORTED_MODULE_8__.findMaxValue)(_classPrivateFieldGet(_currentConvolution, this));\n this.soundCheck = 'system';\n this.addTimeStamp(\"Record \".concat(total_dur, \" s of MLS with \").concat(this.soundCheck, \" IIR.\\u201D\"));\n if (this.isCalibrating) return null;\n await this.playMLSwithIIR(stream, _classPrivateFieldGet(_currentConvolution, this));\n this.stopCalibrationAudio();\n let system_conv_recs = this.getAllFilteredRecordedSignals();\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 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 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.getSubtractedPSDWithRetry(unconv_rec, knownGain, knownFreq, sampleRate).then(res => {\n this.incrementStatusBar();\n this.status = this.generateTemplate(\"All Hz Calibration: done computing the PSD graphs...\".toString()).toString();\n this.emit('update', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\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.getSubtractedPSDWithRetry(conv_rec, knownGain, knownFreq, sampleRate).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_8__.interpolate)(freq, knownFreq[i - 1], knownFreq[i], knownGain[i - 1], knownGain[i]);\n });\n let correctedGain = res.y.map((gain, index) => 10 * Math.log10(gain) - interpolatedGain[index]);\n let filtered_psd = correctedGain.filter((value, index) => res.x[index] >= _classPrivateFieldGet(_lowHz, this) && res.x[index] <= this.componentFMaxHz);\n this.SDofFilteredRange['component'] = (0,_utils__WEBPACK_IMPORTED_MODULE_8__.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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\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.getPSDWithRetry({\n unconv_rec,\n conv_rec,\n sampleRate: this.sourceSamplingRate || 96000\n }).then(res => {\n let filtered_psd = res.y_conv.filter((value, index) => res.x_conv[index] >= _classPrivateFieldGet(_lowHz, this) && res.x_conv[index] <= _classPrivateFieldGet(_highHz, this)).map(value => 10 * Math.log10(value));\n let mls_psd = res.y_unconv.filter((value, index) => res.x_unconv[index] >= _classPrivateFieldGet(_lowHz, this) && res.x_conv[index] <= _classPrivateFieldGet(_highHz, this)).map(value => 10 * Math.log10(value));\n this.SDofFilteredRange['mls'] = (0,_utils__WEBPACK_IMPORTED_MODULE_8__.standardDeviation)(mls_psd);\n console.log('mls_psd', this.SDofFilteredRange['mls']);\n this.SDofFilteredRange['system'] = (0,_utils__WEBPACK_IMPORTED_MODULE_8__.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', {\n message: this.status\n });\n return res;\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.getPSDWithRetry({\n unconv_rec,\n conv_rec,\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\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.getPSDWithRetry({\n unconv_rec,\n conv_rec,\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\n });\n this.addTimeStamp('Compute PSD of MLS sequence');\n if (this.isCalibrating) return null;\n let mls_psd = await this.pyServerAPI.getMLSPSDWithRetry({\n mls: _classPrivateFieldGet(_mlsBufferView, this)[0],\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\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.getMLSPSDWithRetry({\n mls: this.systemConvolution,\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\n });\n let system_no_bandpass_filtered_mls_psd = await this.pyServerAPI.getMLSPSDWithRetry({\n mls: this.systemConvolution,\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\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.getMLSPSDWithRetry({\n mls: this.componentConvolution,\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\n });\n let component_no_bandpass_filtered_mls_psd = await this.pyServerAPI.getMLSPSDWithRetry({\n mls: this.componentConvolutionNoBandpass,\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\n });\n let gainValue = this.getGainDBSPL();\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: _classPrivateFieldGet(_mlsBufferView, this),\n mls_psd: {\n x: mls_psd['x_mls'],\n y: mls_psd['y_mls']\n },\n autocorrelations: this.autocorrelations,\n impulseResponses: []\n };\n return iir_ir_and_plots;\n });\n _defineProperty(this, \"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 _classPrivateFieldSet(_currentConvolution, this, this.componentConvolution);\n this.filteredMLSRange.component.Min = (0,_utils__WEBPACK_IMPORTED_MODULE_8__.findMinValue)(_classPrivateFieldGet(_currentConvolution, this));\n this.filteredMLSRange.component.Max = (0,_utils__WEBPACK_IMPORTED_MODULE_8__.findMaxValue)(_classPrivateFieldGet(_currentConvolution, this));\n this.soundCheck = 'component';\n this.addTimeStamp(\"Record \".concat(total_dur, \" s of MLS with \").concat(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, _classPrivateFieldGet(_currentConvolution, this));\n this.stopCalibrationAudio();\n } else {\n _classPrivateFieldSet(_currentConvolution, this, this.systemConvolution);\n this.filteredMLSRange.system.Min = (0,_utils__WEBPACK_IMPORTED_MODULE_8__.findMinValue)(_classPrivateFieldGet(_currentConvolution, this));\n this.filteredMLSRange.system.Max = (0,_utils__WEBPACK_IMPORTED_MODULE_8__.findMaxValue)(_classPrivateFieldGet(_currentConvolution, this));\n this.soundCheck = 'system';\n this.addTimeStamp(\"Record \".concat(total_dur, \" s of MLS with \").concat(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, _classPrivateFieldGet(_currentConvolution, this));\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.getSubtractedPSDWithRetry(unconv_rec, knownGain, knownFreq, sampleRate).then(res => {\n console.log(res);\n let mls_psd = res.y.filter((value, index) => res.x[index] >= _classPrivateFieldGet(_lowHz, this) && res.x[index] <= this.systemFMaxHz).map(value => 10 * Math.log10(value));\n this.SDofFilteredRange['mls'] = (0,_utils__WEBPACK_IMPORTED_MODULE_8__.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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\n });\n this.addTimeStamp('Compute PSD recording of speaker+ mic IIR-filtered MLS recording');\n if (this.isCalibrating) return null;\n let conv_results = await this.pyServerAPI.getSubtractedPSDWithRetry(conv_rec, knownGain, knownFreq, sampleRate).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_8__.interpolate)(freq, knownFreq[i - 1], knownFreq[i], knownGain[i - 1], knownGain[i]);\n });\n let correctedGain = res.y.map((gain, index) => 10 * Math.log10(gain) - interpolatedGain[index]);\n let filtered_psd = correctedGain.filter((value, index) => res.x[index] >= _classPrivateFieldGet(_lowHz, this) && res.x[index] <= _classPrivateFieldGet(_highHz, this));\n this.SDofFilteredRange['component'] = (0,_utils__WEBPACK_IMPORTED_MODULE_8__.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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\n });\n unconv_rec = this.componentInvertedImpulseResponseNoBandpass;\n conv_rec = this.componentInvertedImpulseResponse;\n this.addTimeStamp('Compute PSD of speaker or mic IIR, with and without bandpass');\n if (this.isCalibrating) return null;\n let component_iir_psd = await this.pyServerAPI.getPSDWithRetry({\n unconv_rec,\n conv_rec,\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\n });\n unconv_rec = this.systemInvertedImpulseResponseNoBandpass;\n conv_rec = this.systemInvertedImpulseResponse;\n this.addTimeStamp('Compute PSD of speaker +mic IIR, with and without bandpass');\n if (this.isCalibrating) return null;\n let system_iir_psd = await this.pyServerAPI.getPSDWithRetry({\n unconv_rec,\n conv_rec,\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\n });\n this.addTimeStamp('Compute PSD of MLS');\n if (this.isCalibrating) return null;\n let mls_psd = await this.pyServerAPI.getMLSPSDWithRetry({\n mls: _classPrivateFieldGet(_mlsBufferView, this)[this.icapture],\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\n });\n this.addTimeStamp('Compute PSD of speaker or mic');\n if (this.isCalibrating) return null;\n let filtered_mls_psd = await this.pyServerAPI.getMLSPSDWithRetry({\n mls: this.componentConvolution,\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\n });\n let filtered_no_bandpass_mls_psd = await this.pyServerAPI.getMLSPSDWithRetry({\n mls: this.componentConvolutionNoBandpass,\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\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: _classPrivateFieldGet(_mlsBufferView, this),\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.getPSDWithRetry({\n unconv_rec,\n conv_rec,\n sampleRate: this.sourceSamplingRate || 96000\n }).then(res => {\n let filtered_psd = res.y_conv.filter((value, index) => res.x_conv[index] >= _classPrivateFieldGet(_lowHz, this) && res.x_conv[index] <= this.systemFMaxHz).map(value => 10 * Math.log10(value));\n let mls_psd = res.y_unconv.filter((value, index) => res.x_unconv[index] >= _classPrivateFieldGet(_lowHz, this) && res.x_conv[index] <= this.systemFMaxHz).map(value => 10 * Math.log10(value));\n this.SDofFilteredRange['mls'] = (0,_utils__WEBPACK_IMPORTED_MODULE_8__.standardDeviation)(mls_psd);\n this.SDofFilteredRange['system'] = (0,_utils__WEBPACK_IMPORTED_MODULE_8__.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', {\n message: this.status\n });\n return res;\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.getPSDWithRetry({\n unconv_rec,\n conv_rec,\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\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.getPSDWithRetry({\n unconv_rec,\n conv_rec,\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\n });\n this.addTimeStamp('Compute PSD of MLS sequence');\n if (this.isCalibrating) return null;\n let mls_psd = await this.pyServerAPI.getMLSPSDWithRetry({\n mls: _classPrivateFieldGet(_mlsBufferView, this)[this.icapture],\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\n });\n this.addTimeStamp('Compute PSD of filtered MLS (system)');\n if (this.isCalibrating) return null;\n let filtered_mls_psd = await this.pyServerAPI.getMLSPSDWithRetry({\n mls: this.systemConvolution,\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\n });\n let filtered_no_bandpass_mls_psd = await this.pyServerAPI.getMLSPSDWithRetry({\n mls: this.systemConvolutionNoBandpass,\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\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: _classPrivateFieldGet(_mlsBufferView, this),\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 if (_classPrivateFieldGet(_download, this)) {\n this.downloadSingleUnfilteredRecording();\n this.downloadSingleFilteredRecording();\n (0,_utils__WEBPACK_IMPORTED_MODULE_8__.saveToCSV)(_classPrivateFieldGet(_mls, this), 'MLS.csv');\n (0,_utils__WEBPACK_IMPORTED_MODULE_8__.saveToCSV)(this.componentConvolution, 'python_component_convolution_mls_iir.csv');\n (0,_utils__WEBPACK_IMPORTED_MODULE_8__.saveToCSV)(this.systemConvolution, 'python_system_convolution_mls_iir.csv');\n (0,_utils__WEBPACK_IMPORTED_MODULE_8__.saveToCSV)(this.componentInvertedImpulseResponse, 'componentIIR.csv');\n (0,_utils__WEBPACK_IMPORTED_MODULE_8__.saveToCSV)(this.systemInvertedImpulseResponse, 'systemIIR.csv');\n for (let i = 0; i < this.autocorrelations.length; i++) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_8__.saveToCSV)(this.autocorrelations[i], \"autocorrelation_\".concat(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_8__.saveToCSV)(res[i], \"IR_\".concat(i));\n }\n }\n });\n }\n return iir_ir_and_plots;\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 _defineProperty(this, \"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 console.log('MLS sequence should be of length: ' + this.sourceSamplingRate * desired_time);\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 if (!this._calibrateSoundBurstLevelReTBool) {\n this.power_dB = this._calibrateSoundBurstDb;\n } else {\n this.power_dB = this._calibrateSoundBurstDb + (this.T - this.gainDBSPL);\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.getMLSWithRetry({\n length,\n amplitude,\n calibrateSoundBurstMLSVersions: this.numCaptures\n }).then(res => {\n console.log(res);\n _classPrivateFieldSet(_mlsBufferView, this, res['mls']);\n _classPrivateFieldSet(_mls, this, res['unscaledMLS']);\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', {\n message: this.status\n });\n if (this.isCalibrating) return null;\n await this.recordBackground(stream,\n //stream\n () => this.numSuccessfulBackgroundCaptured < 1,\n //loop condition\n _classPrivateFieldGet(_awaitBackgroundNoiseRecording, this),\n //sleep to record\n this.sendBackgroundRecording,\n //send to get PSD\n this.mode, checkRec);\n this.incrementStatusBar();\n }\n this.mode = 'unfiltered';\n this.numSuccessfulCaptured = 0;\n if (this.isCalibrating) return null;\n for (var i = 0; i < this.numCaptures; i++) {\n this.icapture = i;\n await this.calibrationSteps(stream, _classPrivateFieldGet(_playCalibrationAudio, this), // play audio func (required)\n _classPrivateFieldGet(_createCalibrationNodeFromBuffer, this).call(this, _classPrivateFieldGet(_mlsBufferView, this)[this.icapture]),\n // before play func\n _classPrivateFieldGet(_awaitSignalOnset, this),\n // before record\n () => this.numSuccessfulCaptured < 2,\n // loop while true\n _classPrivateFieldGet(_awaitDesiredMLSLength, this),\n // during record\n _classPrivateFieldGet(_afterMLSRecord, this),\n // after record\n this.mode, checkRec);\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 this.numSuccessfulCaptured = 0;\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.getPSDWithRetry({\n unconv_rec,\n conv_rec,\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\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.getPSDWithRetry({\n unconv_rec,\n conv_rec,\n sampleRate: this.sourceSamplingRate || 96000\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', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\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: _classPrivateFieldGet(_mlsBufferView, this),\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 if (_classPrivateFieldGet(_download, this)) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_8__.saveToCSV)(_classPrivateFieldGet(_mls, this), 'MLS.csv');\n (0,_utils__WEBPACK_IMPORTED_MODULE_8__.saveToCSV)(this.componentConvolution, 'python_component_convolution_mls_iir.csv');\n (0,_utils__WEBPACK_IMPORTED_MODULE_8__.saveToCSV)(this.systemConvolution, 'python_system_convolution_mls_iir.csv');\n (0,_utils__WEBPACK_IMPORTED_MODULE_8__.saveToCSV)(this.componentInvertedImpulseResponse, 'componentIIR.csv');\n (0,_utils__WEBPACK_IMPORTED_MODULE_8__.saveToCSV)(this.systemInvertedImpulseResponse, 'systemIIR.csv');\n for (let i = 0; i < this.autocorrelations.length; i++) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_8__.saveToCSV)(this.autocorrelations[i], \"autocorrelation_\".concat(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_8__.saveToCSV)(res[i], \"IR_\".concat(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.addTimeStamp('Done');\n this.emit('update', {\n message: this.status\n });\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 //////////////////////volume\n _defineProperty(this, \"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: \".concat(data.type));\n }\n });\n _classPrivateFieldInitSpec(this, _getTruncatedSignal, function () {\n let left = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 3.5;\n let right = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 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('Obtaining last 1000 hz recording from #allVolumeRecordings to send for processing');\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('The last capture failed, all recorded signal is zero', _this.getAllVolumeRecordedSignals());\n _this.stopCalibrationAudio();\n _this.isCalibrating = true;\n // restartButton.style.display = 'none';\n _this.emit('update', {\n message: 'Connection failed, hit restart button to reconnect'\n });\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', {\n message: 'Connection failed, hit restart button to reconnect'\n });\n }\n };\n checkResult(result);\n return result;\n });\n /** \n * \n * \n Construct a calibration Node with the calibration parameters and given gain value\n * @param {*} gainValue\n * */\n _classPrivateFieldInitSpec(this, _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 oscilator.frequency.value = _classPrivateFieldGet(_CALIBRATION_TONE_FREQUENCY, this);\n oscilator.type = _classPrivateFieldGet(_CALIBRATION_TONE_TYPE, this);\n gainNode.gain.value = gainValue;\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 const gainValuesOverTime = [];\n const sampleRate = _classPrivateFieldGet(_CALIBRATION_TONE_FREQUENCY, this); // 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 gainValuesOverTime.push(gainValueAtTime);\n }\n this.waveforms['volume'][this.inDB] = gainValuesOverTime;\n this.addCalibrationNode(oscilator);\n });\n /**\n * Construct a Calibration Node with the calibration parameters.\n *\n * @private\n * @example\n */\n _classPrivateFieldInitSpec(this, _createCalibrationNode, () => {\n const audioContext = this.makeNewSourceAudioContext();\n const oscilator = audioContext.createOscillator();\n const gainNode = audioContext.createGain();\n oscilator.frequency.value = _classPrivateFieldGet(_CALIBRATION_TONE_FREQUENCY, this);\n oscilator.type = _classPrivateFieldGet(_CALIBRATION_TONE_TYPE, this);\n gainNode.gain.value = 0.04;\n oscilator.connect(gainNode);\n gainNode.connect(audioContext.destination);\n this.addCalibrationNode(oscilator);\n });\n _classPrivateFieldInitSpec(this, _playCalibrationAudioVolume, async () => {\n if (this.numCalibratingRoundsCompleted == 1) {\n this.recordingChecks['warnings'].push(\"1000Hz. Re-recorded \".concat(this.inDB, \" dB because SD \").concat(this.recordingChecks['volume'][this.inDB]['sd'], \" > \").concat(this.calibrateSound1000HzMaxSD_dB, \" dB\"));\n const currentStatus = \"1000 Hz: Re-recording at \".concat(this.inDB, \" dB because SD \\n \").concat(this.recordingChecks['volume'][this.inDB]['sd'], \" > \\n \").concat(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 this.calibrationNodes[0].start(0);\n this.calibrationNodes[0].stop(totalDuration);\n console.log(\"Playing a buffer of \".concat(this.CALIBRATION_TONE_DURATION, \" seconds of audio\"));\n console.log(\"Waiting a total of \".concat(totalDuration, \" seconds\"));\n await (0,_utils__WEBPACK_IMPORTED_MODULE_8__.sleep)(totalDuration);\n });\n _defineProperty(this, \"stopCalibrationAudioVolume\", () => {\n if (this.calibrationNodes.length > 0) {\n this.calibrationNodes[0].stop();\n }\n });\n _classPrivateFieldInitSpec(this, _sendToServerForProcessing, async lCalib => {\n console.log('Sending data to server');\n let left = this.calibrateSound1000HzPreSec;\n let right = this.calibrateSound1000HzPreSec + this.calibrateSound1000HzSec;\n if (this.isCalibrating) return null;\n this.pyServerAPI.getVolumeCalibration({\n sampleRate: this.sourceSamplingRate,\n payload: _classPrivateFieldGet(_getTruncatedSignal, this).call(this, left, right),\n lCalib: lCalib\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 }).catch(err => {\n console.warn(err);\n });\n const rec = this.getLastVolumeRecordedSignal();\n console.log('pre period power: ', (0,_powerCheck__WEBPACK_IMPORTED_MODULE_9__.getPower)(rec.slice(0, this.calibrateSound1000HzPreSec * this.sourceSamplingRate)).toFixed(1));\n console.log('pre period power: ', (0,_powerCheck__WEBPACK_IMPORTED_MODULE_9__.getPower)(rec.slice(this.calibrateSound1000HzPreSec * this.sourceSamplingRate, (this.calibrateSound1000HzPreSec + this.calibrateSound1000HzSec) * this.sourceSamplingRate)).toFixed(1));\n console.log('pre period power: ', (0,_powerCheck__WEBPACK_IMPORTED_MODULE_9__.getPower)(rec.slice((this.calibrateSound1000HzPreSec + this.calibrateSound1000HzSec) * this.sourceSamplingRate)).toFixed(1));\n const res = (0,_powerCheck__WEBPACK_IMPORTED_MODULE_9__.volumePowerCheck)(rec, this.sourceSamplingRate || 96000, this.calibrateSound1000HzPreSec, this.calibrateSound1000HzSec, this._calibrateSoundPowerBinDesiredSec);\n console.log(res);\n this.recordingChecks['volume'][this.inDB] = res;\n console.log('Recording checks in sendToServer', this.recordingChecks['volume']);\n const getSD = () => this.recordingChecks['volume'][this.inDB]['sd'];\n // const getSDMessage = () => {\n // //SOUND 6.7 s. 2.5+2.5+0.5 s. 1000 Hz at -60 dB. SD = 1.3 dB\n // // And reporting each rejected recording as\n // // SOUND 6.7 s. 2.5+2.5+0.5 s. 1000 Hz at -60 dB, SD = 19.7 > 4 dB.\n\n // if (this.numCalibratingRoundsCompleted == 1)\n // return `. SD = ${getSD()} > ${this.calibrateSound1000HzMaxSD_dB} dB.`;\n // return `. SD = ${getSD()} dB`;\n // };\n // const total_dur =\n // this.calibrateSound1000HzPreSec +\n // this.calibrateSound1000HzSec +\n // this.calibrateSound1000HzPostSec;\n\n // this.addTimeStamp(\n // `${this.calibrateSound1000HzPreSec.toFixed(1)}` +\n // `+${this.calibrateSound1000HzSec.toFixed(1)}` +\n // `+${this.calibrateSound1000HzPostSec.toFixed(1)} s.` +\n // `1000 Hz at ${this.inDB} dB${getSDMessage()}`\n // );\n });\n _defineProperty(this, \"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 \".concat(soundLevelToDiscard, \" dB\").toString()).toString();\n //this.emit('update', {message: `1000 Hz Calibration: Sound Level ${soundLevelToDiscard} dB`});\n this.emit('update', {\n message: this.status\n });\n this.startTime = new Date().getTime();\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(stream, _classPrivateFieldGet(_playCalibrationAudioVolume, this), _classPrivateFieldGet(_createCalibrationToneWithGainValue, this), _classPrivateFieldGet(_sendToServerForProcessing, this), gainToDiscard, lCalib,\n //todo make this a class parameter\n checkRec, () => {\n return this.recordingChecks['volume'][this.inDB]['sd'];\n }, this.calibrateSound1000HzMaxSD_dB, this.calibrateSound1000HzMaxTries);\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 \".concat(inDB, \" dB\").toString()).toString();\n this.emit('update', {\n message: this.status\n });\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(stream, _classPrivateFieldGet(_playCalibrationAudioVolume, this), _classPrivateFieldGet(_createCalibrationToneWithGainValue, this), _classPrivateFieldGet(_sendToServerForProcessing, this), gainValues[i], lCalib,\n //todo make this a class parameter\n checkRec, () => {\n var _this$recordingChecks;\n return ((_this$recordingChecks = this.recordingChecks) === null || _this$recordingChecks === void 0 || (_this$recordingChecks = _this$recordingChecks['volume']) === null || _this$recordingChecks === void 0 || (_this$recordingChecks = _this$recordingChecks[this.inDB]) === null || _this$recordingChecks === void 0 ? void 0 : _this$recordingChecks['sd']) || 0;\n }, this.calibrateSound1000HzMaxSD_dB, this.calibrateSound1000HzMaxTries);\n } while (this.outDBSPL === null);\n outDBSPL1000Values.push(this.outDBSPL1000);\n thdValues.push(this.THD);\n outDBSPLValues.push(this.outDBSPL);\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 const parameters = await this.pyServerAPI.getVolumeCalibrationParameters({\n inDBValues: inDBValues,\n outDBSPLValues: outDBSPL1000Values,\n lCalib: lCalib,\n componentGainDBSPL\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 return result;\n });\n _defineProperty(this, \"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 = {\n Freq: frq,\n Gain: gain\n };\n const docRef = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.doc)(_config_firebase__WEBPACK_IMPORTED_MODULE_10__[\"default\"], 'Microphones', documentID);\n await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.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 _defineProperty(this, \"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 const data = {\n Freq: sampledFrq,\n Gain: sampledGain\n };\n await (0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.set)((0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_10__[\"default\"], \"Microphone2/\".concat(OEM, \"/\").concat(speakerID, \"/linear\")), data);\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 _defineProperty(this, \"readFrqGainFromFirestore\", async (speakerID, OEM, isDefault) => {\n const collectionRef = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.collection)(_config_firebase__WEBPACK_IMPORTED_MODULE_10__[\"default\"], 'Microphones');\n const q = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.query)(collectionRef, (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.where)('ID', '==', speakerID), (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.where)('lowercaseOEM', '==', OEM), (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.where)('isDefault', '==', isDefault));\n const querySnapshot = await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.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_12__.Timestamp(querySnapshot.docs[0].data().createDate.seconds, querySnapshot.docs[0].data().createDate.nanoseconds);\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 _defineProperty(this, \"readFrqGain\", async (speakerID, OEM) => {\n const dbRef = (0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_10__[\"default\"]);\n const snapshot = await (0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.get)((0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.child)(dbRef, \"Microphone2/\".concat(OEM, \"/\").concat(speakerID, \"/linear\")));\n if (snapshot.exists()) {\n return snapshot.val();\n }\n return null;\n });\n _defineProperty(this, \"readGainat1000HzFromFirestore\", async (speakerID, OEM, isDefault) => {\n const collectionRef = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.collection)(_config_firebase__WEBPACK_IMPORTED_MODULE_10__[\"default\"], 'Microphones');\n const q = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.query)(collectionRef, (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.where)('ID', '==', speakerID), (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.where)('lowercaseOEM', '==', OEM), (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.where)('isDefault', '==', isDefault));\n const querySnapshot = await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.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 _defineProperty(this, \"readGainat1000Hz\", async (speakerID, OEM) => {\n const dbRef = (0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_10__[\"default\"]);\n const snapshot = await (0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.get)((0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.child)(dbRef, \"Microphone2/\".concat(OEM, \"/\").concat(speakerID, \"/Gain1000\")));\n if (snapshot.exists()) {\n return snapshot.val();\n }\n return null;\n });\n _defineProperty(this, \"writeGainat1000HzToFirestore\", async (speakerID, gain, OEM, documentID) => {\n const docRef = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.doc)(_config_firebase__WEBPACK_IMPORTED_MODULE_10__[\"default\"], 'Microphones', documentID);\n await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.updateDoc)(docRef, {\n Gain1000: gain\n });\n });\n _defineProperty(this, \"writeGainat1000Hz\", async (speakerID, gain, OEM) => {\n await (0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.set)((0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_10__[\"default\"], \"Microphone2/\".concat(OEM, \"/\").concat(speakerID, \"/Gain1000\")), gain);\n });\n _defineProperty(this, \"writeIsSmartPhoneToFirestore\", async (speakerID, isSmartPhone, OEM) => {\n const collectionRef = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.collection)(_config_firebase__WEBPACK_IMPORTED_MODULE_10__[\"default\"], 'Microphones');\n const q = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.query)(collectionRef, (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.where)('ID', '==', speakerID), (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.where)('lowercaseOEM', '==', OEM), (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.where)('isDefault', '==', true));\n const querySnapshot = await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.getDocs)(q);\n if (querySnapshot.size > 0) {\n const docRef = await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.addDoc)(collectionRef, {\n isSmartPhone: isSmartPhone,\n isDefault: false\n });\n return docRef.id;\n } else {\n const docRef = await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.addDoc)(collectionRef, {\n isSmartPhone: isSmartPhone,\n isDefault: true\n });\n return docRef.id;\n }\n });\n _defineProperty(this, \"writeIsSmartPhone\", async (speakerID, isSmartPhone, OEM) => {\n const data = {\n isSmartPhone: isSmartPhone\n };\n await (0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.set)((0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_10__[\"default\"], \"Microphone2/\".concat(OEM, \"/\").concat(speakerID, \"/isSmartPhone\")), isSmartPhone);\n });\n _defineProperty(this, \"writeMicrophoneInfoToFirestore\", async (speakerID, micInfo, OEM, documentID) => {\n const docRef = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.doc)(_config_firebase__WEBPACK_IMPORTED_MODULE_10__[\"default\"], 'Microphones', documentID);\n await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.setDoc)(docRef, micInfo, {\n merge: true\n });\n });\n _defineProperty(this, \"doesMicrophoneExistInFirestore\", async (speakerID, OEM, documentID) => {\n const docRef = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.doc)(_config_firebase__WEBPACK_IMPORTED_MODULE_10__[\"default\"], 'Microphone', OEM, speakerID, documentID);\n const docSnap = await (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_12__.getDoc)(docRef);\n if (docSnap.exists()) {\n return true;\n }\n return false;\n });\n _defineProperty(this, \"doesMicrophoneExist\", async (speakerID, OEM) => {\n const dbRef = (0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_10__[\"default\"]);\n const snapshot = await (0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.get)((0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.child)(dbRef, \"Microphone2/\".concat(OEM, \"/\").concat(speakerID)));\n if (snapshot.exists()) {\n return true;\n }\n return false;\n });\n _defineProperty(this, \"addMicrophoneInfo\", async (speakerID, OEM, micInfo) => {\n // add to database if /info does not exist\n const dbRef = (0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_10__[\"default\"]);\n const snapshot = await (0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.get)((0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.child)(dbRef, \"Microphone2/\".concat(OEM, \"/\").concat(speakerID, \"/info\")));\n if (!snapshot.exists()) {\n await (0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.set)((0,firebase_database__WEBPACK_IMPORTED_MODULE_11__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_10__[\"default\"], \"Microphone2/\".concat(OEM, \"/\").concat(speakerID, \"/info\")), micInfo);\n }\n });\n _defineProperty(this, \"convertToDB\", gain => {\n return Math.log10(gain) * 20;\n });\n _defineProperty(this, \"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 _defineProperty(this, \"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 await this.pyServerAPI.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 }).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 \".concat(this.inDB, \" because SD \").concat(result['sd'], \" > \").concat(this._calibrateSoundBurstMaxSD_dB, \" dB\"));\n this.status = this.generateTemplate(\"All Hz: Re-recording at \".concat(this.inDB, \" dB because SD \").concat(result['sd'], \" > \").concat(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('after mls w iir record for some reason add numSucc capt ' + this.stepNum);\n this.status = this.generateTemplate(\"All Hz Calibration: \".concat(this.numSuccessfulCaptured, \" recording of convolved MLS captured\").toString()).toString();\n this.emit('update', {\n message: this.status\n });\n }\n }\n }\n });\n });\n _defineProperty(this, \"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 _defineProperty(this, \"startCalibration\", async function (stream, gainValues) {\n let lCalib = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 104.92978421490648;\n let componentIR = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;\n let microphoneName = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 'MiniDSP-UMIK1-711-4754-vertical';\n let _calibrateSoundCheck = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 'goal';\n let isSmartPhone = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : false;\n let _calibrateSoundBurstDb = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : -18;\n let _calibrateSoundBurstFilteredExtraDb = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : 6;\n let _calibrateSoundBurstLevelReTBool = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : false;\n let _calibrateSoundBurstUses1000HzGainBool = arguments.length > 10 && arguments[10] !== undefined ? arguments[10] : false;\n let _calibrateSoundBurstRepeats = arguments.length > 11 && arguments[11] !== undefined ? arguments[11] : 3;\n let _calibrateSoundBurstSec = arguments.length > 12 && arguments[12] !== undefined ? arguments[12] : 1;\n let _calibrateSoundBurstPreSec = arguments.length > 13 && arguments[13] !== undefined ? arguments[13] : 1;\n let _calibrateSoundBurstPostSec = arguments.length > 14 && arguments[14] !== undefined ? arguments[14] : 1;\n let _calibrateSoundHz = arguments.length > 15 && arguments[15] !== undefined ? arguments[15] : 48000;\n let _calibrateSoundIRSec = arguments.length > 16 && arguments[16] !== undefined ? arguments[16] : 0.2;\n let _calibrateSoundIIRSec = arguments.length > 17 && arguments[17] !== undefined ? arguments[17] : 0.2;\n let _calibrateSoundIIRPhase = arguments.length > 18 && arguments[18] !== undefined ? arguments[18] : 'linear';\n let calibrateSound1000HzPreSec = arguments.length > 19 && arguments[19] !== undefined ? arguments[19] : 0.5;\n let calibrateSound1000HzSec = arguments.length > 20 && arguments[20] !== undefined ? arguments[20] : 0.5;\n let calibrateSound1000HzPostSec = arguments.length > 21 && arguments[21] !== undefined ? arguments[21] : 0.5;\n let _calibrateSoundBackgroundSecs = arguments.length > 22 && arguments[22] !== undefined ? arguments[22] : 0;\n let _calibrateSoundSmoothOctaves = arguments.length > 23 && arguments[23] !== undefined ? arguments[23] : 0.33;\n let _calibrateSoundSmoothMinBandwidthHz = arguments.length > 24 && arguments[24] !== undefined ? arguments[24] : 200;\n let _calibrateSoundPowerBinDesiredSec = arguments.length > 25 && arguments[25] !== undefined ? arguments[25] : 0.2;\n let _calibrateSoundPowerDbSDToleratedDb = arguments.length > 26 && arguments[26] !== undefined ? arguments[26] : 1;\n let _calibrateSoundTaperSec = arguments.length > 27 && arguments[27] !== undefined ? arguments[27] : 0.01;\n let micManufacturer = arguments.length > 28 && arguments[28] !== undefined ? arguments[28] : '';\n let micSerialNumber = arguments.length > 29 && arguments[29] !== undefined ? arguments[29] : '';\n let micModelNumber = arguments.length > 30 && arguments[30] !== undefined ? arguments[30] : '';\n let micModelName = arguments.length > 31 && arguments[31] !== undefined ? arguments[31] : '';\n let calibrateMicrophonesBool = arguments.length > 32 ? arguments[32] : undefined;\n let authorEmails = arguments.length > 33 ? arguments[33] : undefined;\n let webAudioDeviceNames = arguments.length > 34 && arguments[34] !== undefined ? arguments[34] : {\n loudspeaker: 'loudspeaker',\n microphone: 'microphone',\n microphoneText: 'xxx XXX'\n };\n let userIDs = arguments.length > 35 ? arguments[35] : undefined;\n let restartButton = arguments.length > 36 ? arguments[36] : undefined;\n let reminder = arguments.length > 37 ? arguments[37] : undefined;\n let calibrateSoundLimit = arguments.length > 38 ? arguments[38] : undefined;\n let _calibrateSoundBurstNormalizeBy1000HzGainBool = arguments.length > 39 && arguments[39] !== undefined ? arguments[39] : false;\n let _calibrateSoundBurstScalarDB = arguments.length > 40 && arguments[40] !== undefined ? arguments[40] : 71;\n let calibrateSound1000HzMaxSD_dB = arguments.length > 41 && arguments[41] !== undefined ? arguments[41] : 4;\n let calibrateSound1000HzMaxTries = arguments.length > 42 && arguments[42] !== undefined ? arguments[42] : 4;\n let _calibrateSoundBurstMaxSD_dB = arguments.length > 43 && arguments[43] !== undefined ? arguments[43] : 4;\n let calibrateSoundSamplingDesiredBits = arguments.length > 44 && arguments[44] !== undefined ? arguments[44] : 24;\n let language = arguments.length > 45 ? arguments[45] : undefined;\n let loudspeakerModelName = arguments.length > 46 && arguments[46] !== undefined ? arguments[46] : '';\n let phrases = arguments.length > 47 ? arguments[47] : undefined;\n let soundSubtitleId = arguments.length > 48 ? arguments[48] : undefined;\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 = 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 = _calibrateSoundBurstNormalizeBy1000HzGainBool;\n _this._calibrateSoundBurstScalarDB = _calibrateSoundBurstScalarDB;\n _this.webAudioDeviceNames = webAudioDeviceNames;\n _this.calibrateSoundSamplingDesiredBits = calibrateSoundSamplingDesiredBits;\n _this.phrases = phrases;\n _this.soundSubtitleId = soundSubtitleId;\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].replace('“xxx”', combinedMicText).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.calibrateSound1000HzMaxTries = calibrateSound1000HzMaxTries;\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 ? micModelName === 'UMIK-1' || micModelName === 'UMIK-2' ? 'minidsp' : _this.deviceInfo.OEM ? _this.deviceInfo.OEM.toLowerCase().split(' ').join('') : micManufacturer.toLowerCase().split(' ').join('') : micManufacturer.toLowerCase().split(' ').join('');\n // const ID = \"712-5669\";\n // const OEM = \"minidsp\";\n const micInfo = {\n micModelName: isSmartPhone ? micModelName : microphoneName,\n OEM: isSmartPhone ? micModelName === 'UMIK-1' || micModelName === 'UMIK-2' ? 'miniDSP' : _this.deviceInfo.OEM : micManufacturer,\n ID: ID,\n createDate: new Date(),\n DateText: (0,_utils__WEBPACK_IMPORTED_MODULE_8__.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 ? 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 = \"Microphone (\".concat(OEM, \",\").concat(ID, \") is not found in the database. Please add it to the database.\").toString();\n _this.emit('update', {\n message: _this.status\n });\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 _this.oldComponentIR = JSON.parse(JSON.stringify(_this.componentIR));\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', {\n message: 'Restarting calibration...'\n });\n resolve('restart');\n });\n }\n await _this.pyServerAPI.checkMemory();\n // calibrate volume\n\n let volumeResults = await _this.startCalibrationVolume(stream, gainValues, lCalib, _this.componentGainDBSPL);\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['background_noise']['recording'].map(value => value / linearScaleAttenuation);\n impulseResponseResults['system']['background_noise']['x_background'] = impulseResponseResults['background_noise']['x_background'];\n impulseResponseResults['system']['background_noise']['y_background'] = impulseResponseResults['background_noise']['y_background'].map(value => value / linearScalePowerAttenuation);\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'] = impulseResponseResults['background_noise']['recording'].map(value => value / linearScaleAttenuation);\n impulseResponseResults['component']['background_noise']['x_background'] = impulseResponseResults['background_noise']['x_background'];\n impulseResponseResults['component']['background_noise']['y_background'] = impulseResponseResults['background_noise']['y_background'].map(value => value / linearScalePowerAttenuation);\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 if (componentIR != null) {\n var _impulseResponseResul;\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 = Math.round((volumeResults.parameters.gainDBSPL - _this.componentGainDBSPL) * 10) / 10;\n let IrFreq = impulseResponseResults === null || impulseResponseResults === void 0 ? void 0 : impulseResponseResults.component.ir.Freq.map(freq => Math.round(freq));\n let IrGain = impulseResponseResults === null || impulseResponseResults === void 0 || (_impulseResponseResul = impulseResponseResults.component) === null || _impulseResponseResul === void 0 ? void 0 : _impulseResponseResul.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 = {\n ...volumeResults,\n ...impulseResponseResults\n };\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 total_results['permissionStatus'] = _this.permissionStatus;\n console.log('total results');\n console.log(total_results);\n console.log('Time Stamps');\n console.log(timeStampresult);\n resolve(total_results);\n });\n });\n _classPrivateFieldSet(_mlsOrder, this, parseInt(mlsOrder, 10));\n _classPrivateFieldSet(_P, this, 2 ** mlsOrder - 1);\n _classPrivateFieldSet(_download, this, download);\n _classPrivateFieldSet(_mls, this, []);\n _classPrivateFieldSet(_lowHz, this, _lowHz2);\n _classPrivateFieldSet(_highHz, this, _highHz2);\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_defineProperty(Combination, \"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/* harmony default export */ __webpack_exports__[\"default\"] = (Combination);\n\n//# sourceURL=webpack://speakerCalibrator/./src/tasks/combination/combination.js?");
|
|
184
184
|
|
|
185
185
|
/***/ }),
|
|
186
186
|
|
|
@@ -191,7 +191,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core
|
|
|
191
191
|
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
192
192
|
|
|
193
193
|
"use strict";
|
|
194
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_array_buffer_slice_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array-buffer.slice.js */ \"./node_modules/core-js/modules/es.array-buffer.slice.js\");\n/* harmony import */ var core_js_modules_es_array_buffer_slice_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_buffer_slice_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_es_typed_array_float32_array_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/es.typed-array.float32-array.js */ \"./node_modules/core-js/modules/es.typed-array.float32-array.js\");\n/* harmony import */ var core_js_modules_es_typed_array_float32_array_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_typed_array_float32_array_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_es_typed_array_fill_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/es.typed-array.fill.js */ \"./node_modules/core-js/modules/es.typed-array.fill.js\");\n/* harmony import */ var core_js_modules_es_typed_array_fill_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_typed_array_fill_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var core_js_modules_es_typed_array_set_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! core-js/modules/es.typed-array.set.js */ \"./node_modules/core-js/modules/es.typed-array.set.js\");\n/* harmony import */ var core_js_modules_es_typed_array_set_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_typed_array_set_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var core_js_modules_es_typed_array_sort_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! core-js/modules/es.typed-array.sort.js */ \"./node_modules/core-js/modules/es.typed-array.sort.js\");\n/* harmony import */ var core_js_modules_es_typed_array_sort_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_typed_array_sort_js__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! core-js/modules/web.dom-collections.iterator.js */ \"./node_modules/core-js/modules/web.dom-collections.iterator.js\");\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var _audioCalibrator__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../audioCalibrator */ \"./src/tasks/audioCalibrator.js\");\n/* harmony import */ var _mlsGen_mlsGenInterface__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./mlsGen/mlsGenInterface */ \"./src/tasks/impulse-response/mlsGen/mlsGenInterface.js\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../utils */ \"./src/utils.js\");\n/* harmony import */ var _config_firebase__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../config/firebase */ \"./src/config/firebase.js\");\n/* harmony import */ var firebase_database__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! firebase/database */ \"./node_modules/firebase/database/dist/esm/index.esm.js\");\n\n\n\n\n\n\nfunction _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }\nfunction _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError(\"Cannot initialize the same private elements twice on an object\"); }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }\nfunction _classPrivateFieldSet(s, a, r) { return s.set(_assertClassBrand(s, a), r), r; }\nfunction _assertClassBrand(e, t, n) { if (\"function\" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError(\"Private element is not present on this object\"); }\n\n\n\n\n\n\n/**\r\n *\r\n */\nvar _download = /*#__PURE__*/new WeakMap();\nvar _mlsGenInterface = /*#__PURE__*/new WeakMap();\nvar _mlsBufferView = /*#__PURE__*/new WeakMap();\nvar _mlsOrder = /*#__PURE__*/new WeakMap();\nvar _lowHz = /*#__PURE__*/new WeakMap();\nvar _highHz = /*#__PURE__*/new WeakMap();\nvar _mls = /*#__PURE__*/new WeakMap();\nvar _P = /*#__PURE__*/new WeakMap();\nvar _audioContext = /*#__PURE__*/new WeakMap();\nvar _awaitDesiredMLSLength = /*#__PURE__*/new WeakMap();\nvar _awaitSignalOnset = /*#__PURE__*/new WeakMap();\nvar _afterMLSRecord = /*#__PURE__*/new WeakMap();\nvar _afterMLSwIIRRecord = /*#__PURE__*/new WeakMap();\nvar _createPureTonenNode = /*#__PURE__*/new WeakMap();\nvar _createCalibrationNodeFromBuffer = /*#__PURE__*/new WeakMap();\nvar _setCalibrationNodesFromBuffer = /*#__PURE__*/new WeakMap();\nvar _putInPythonConv = /*#__PURE__*/new WeakMap();\nvar _playCalibrationAudio = /*#__PURE__*/new WeakMap();\nvar _playCalibrationAudioConvolved = /*#__PURE__*/new WeakMap();\nvar _stopCalibrationAudio = /*#__PURE__*/new WeakMap();\nvar _stopCalibrationAudioConvolved = /*#__PURE__*/new WeakMap();\nclass ImpulseResponse extends _audioCalibrator__WEBPACK_IMPORTED_MODULE_6__[\"default\"] {\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 */\n constructor(_ref) {\n var _this;\n let {\n download = false,\n mlsOrder = 18,\n numCaptures = 3,\n numMLSPerCapture = 4,\n lowHz: _lowHz2 = 20,\n highHz: _highHz2 = 10000,\n loudSpeakerIr = null\n } = _ref;\n super(numCaptures, numMLSPerCapture);\n _this = this;\n /** @private */\n _defineProperty(this, \"stepNum\", 0);\n /** @private */\n _defineProperty(this, \"totalSteps\", 25);\n /** @private */\n _classPrivateFieldInitSpec(this, _download, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _mlsGenInterface, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _mlsBufferView, void 0);\n /** @private */\n _defineProperty(this, \"invertedImpulseResponse\", null);\n /** @private */\n _defineProperty(this, \"impulseResponses\", []);\n /** @private */\n _classPrivateFieldInitSpec(this, _mlsOrder, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _lowHz, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _highHz, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _mls, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _P, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _audioContext, void 0);\n /** @private */\n _defineProperty(this, \"TAPER_SECS\", 5);\n /** @private */\n _defineProperty(this, \"offsetGainNode\", void 0);\n /** @private */\n _defineProperty(this, \"convolution\", void 0);\n /** @private */\n _defineProperty(this, \"status_denominator\", 6);\n /** @private */\n _defineProperty(this, \"status_numerator\", 0);\n /** @private */\n _defineProperty(this, \"percent_complete\", 0);\n /** @private */\n _defineProperty(this, \"status\", \"\");\n /**generate string template that gets reevaluated as variable increases */\n _defineProperty(this, \"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: \".concat(this.percent_complete, \"%; height: 100%; background-color: #00aaff; border-radius: 8px;\\\"></div></div></div>\");\n return template;\n });\n /** increment numerator and percent for status bar */\n _defineProperty(this, \"incrementStatusBar\", () => {\n this.status_numerator += 1;\n this.percent_complete = this.status_numerator / this.status_denominator * 100;\n });\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 */\n _defineProperty(this, \"sendImpulseResponsesToServerForProcessing\", async () => {\n const computedIRs = await Promise.all(this.impulseResponses);\n const filteredComputedIRs = computedIRs.filter(element => {\n return element != undefined;\n });\n const mls = _classPrivateFieldGet(_mls, this);\n const lowHz = _classPrivateFieldGet(_lowHz, this);\n const highHz = _classPrivateFieldGet(_highHz, this);\n this.stepNum += 1;\n this.status = \"computing the IIR...\".toString() + this.generateTemplate().toString();\n this.emit('update', {\n message: this.status\n });\n return this.pyServerAPI.getInverseImpulseResponseWithRetry({\n payload: filteredComputedIRs.slice(0, this.numCaptures),\n mls,\n lowHz,\n highHz\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', {\n message: this.status\n });\n this.invertedImpulseResponse = res['iir'];\n this.convolution = res['convolution'];\n }).catch(err => {\n // this.emit('InvertedImpulseResponse', {res: false});\n console.error(err);\n });\n });\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 */\n _defineProperty(this, \"sendRecordingToServerForProcessing\", signalCsv => {\n const allSignals = this.getAllRecordedSignals();\n const numSignals = allSignals.length;\n const mls = _classPrivateFieldGet(_mls, this);\n const payload = signalCsv && signalCsv.length > 0 ? (0,_utils__WEBPACK_IMPORTED_MODULE_8__.csvToArray)(signalCsv) : allSignals[numSignals - 1];\n console.log('sending rec');\n this.stepNum += 1;\n this.status = \"computing the IR of the last recording...\".toString() + this.generateTemplate().toString();\n this.emit('update', {\n message: this.status\n });\n this.impulseResponses.push(this.pyServerAPI.getImpulseResponse({\n sampleRate: this.sourceSamplingRate || 96000,\n payload,\n mls,\n P: _classPrivateFieldGet(_P, this)\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 = \"\".concat(this.numSuccessfulCaptured, \"/\").concat(this.numCaptures, \" IRs computed...\").toString() + this.generateTemplate().toString();\n this.emit('update', {\n message: this.status\n });\n return res;\n }\n }).catch(err => {\n console.error(err);\n }));\n });\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 */\n _classPrivateFieldInitSpec(this, _awaitDesiredMLSLength, async () => {\n // seconds per MLS = P / SR\n // await N * P / SR\n this.stepNum += 1;\n this.status = \"sampling the calibration signal...\".toString() + this.generateTemplate().toString();\n this.emit('update', {\n message: this.status\n });\n await (0,_utils__WEBPACK_IMPORTED_MODULE_8__.sleep)(_classPrivateFieldGet(_P, this) / this.sourceSamplingRate * this.numMLSPerCapture);\n });\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 */\n _classPrivateFieldInitSpec(this, _awaitSignalOnset, async () => {\n this.stepNum += 1;\n this.status = \"waiting for the signal to stabilize...\".toString() + this.generateTemplate().toString();\n this.emit('update', {\n message: this.status\n });\n await (0,_utils__WEBPACK_IMPORTED_MODULE_8__.sleep)(this.TAPER_SECS);\n });\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 */\n _classPrivateFieldInitSpec(this, _afterMLSRecord, () => {\n console.log('after record');\n this.sendRecordingToServerForProcessing();\n });\n _classPrivateFieldInitSpec(this, _afterMLSwIIRRecord, () => {\n if (this.numSuccessfulCaptured < 1) {\n this.numSuccessfulCaptured += 1;\n this.stepNum += 1;\n this.incrementStatusBar();\n this.status = \"\".concat(this.numSuccessfulCaptured, \" recording of convolved MLS captured\").toString() + this.generateTemplate().toString();\n this.emit('update', {\n message: this.status\n });\n }\n });\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 */\n _classPrivateFieldInitSpec(this, _createPureTonenNode, CALIBRATION_TONE_FREQUENCY => {\n const audioContext = this.makeNewSourceAudioContext();\n const oscilator = audioContext.createOscillator();\n const gainNode = audioContext.createGain();\n oscilator.frequency.value = CALIBRATION_TONE_FREQUENCY;\n oscilator.type = 'sine';\n gainNode.gain.value = 0.04;\n oscilator.connect(gainNode);\n gainNode.connect(audioContext.destination);\n this.addCalibrationNode(oscilator);\n });\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 */\n _classPrivateFieldInitSpec(this, _createCalibrationNodeFromBuffer, dataBuffer => {\n const audioContext = this.makeNewSourceAudioContext();\n const buffer = audioContext.createBuffer(1,\n // number of channels\n dataBuffer.length, audioContext.sampleRate // sample rate\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 source.buffer = buffer;\n source.loop = true;\n source.connect(onsetGainNode);\n onsetGainNode.connect(this.offsetGainNode);\n this.offsetGainNode.connect(audioContext.destination);\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 /**\r\n * Given a data buffer, creates the required calibration node\r\n *\r\n * @param {*} dataBufferArray\r\n * @example\r\n */\n _classPrivateFieldInitSpec(this, _setCalibrationNodesFromBuffer, function () {\n let dataBufferArray = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [_classPrivateFieldGet(_mlsBufferView, _this)];\n if (dataBufferArray.length === 1) {\n _classPrivateFieldGet(_createCalibrationNodeFromBuffer, _this).call(_this, dataBufferArray[0]);\n } else {\n throw new Error('The length of the data buffer array must be 1');\n }\n });\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 */\n _classPrivateFieldInitSpec(this, _putInPythonConv, () => {\n const audioCtx = this.makeNewSourceAudioContextConvolved();\n const buffer = audioCtx.createBuffer(1,\n // number of channels\n this.convolution.length, audioCtx.sampleRate // sample rate\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 const source = audioCtx.createBufferSource();\n source.buffer = buffer;\n source.loop = true;\n source.connect(audioCtx.destination);\n this.addCalibrationNodeConvolved(source);\n });\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 */\n _classPrivateFieldInitSpec(this, _playCalibrationAudio, () => {\n this.calibrationNodes[0].start(0);\n _classPrivateFieldSet(_mls, this, 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', {\n message: this.status\n });\n });\n _classPrivateFieldInitSpec(this, _playCalibrationAudioConvolved, () => {\n this.calibrationNodesConvolved[0].start(0);\n this.stepNum += 1;\n this.status = \"playing the convolved calibration tone...\".toString() + this.generateTemplate().toString();\n this.emit('update', {\n message: this.status\n });\n });\n /** .\r\n * .\r\n * .\r\n * Stops the audio with tapered offset\r\n *\r\n * @example\r\n */\n _classPrivateFieldInitSpec(this, _stopCalibrationAudio, () => {\n this.offsetGainNode.gain.setValueAtTime(this.offsetGainNode.gain.value, this.sourceAudioContext.currentTime);\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 = \"stopping the calibration tone...\".toString() + this.generateTemplate().toString();\n this.emit('update', {\n message: this.status\n });\n });\n _classPrivateFieldInitSpec(this, _stopCalibrationAudioConvolved, () => {\n this.offsetGainNode.gain.setValueAtTime(this.offsetGainNode.gain.value, this.sourceAudioContextConvolved.currentTime);\n this.offsetGainNode.gain.setTargetAtTime(0, this.sourceAudioContextConvolved.currentTime, 0.5);\n this.sourceAudioContextConvolved.close();\n this.stepNum += 1;\n this.status = \"stopping the convolved calibration tone...\".toString() + this.generateTemplate().toString();\n this.emit('update', {\n message: this.status\n });\n });\n _defineProperty(this, \"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_7__[\"default\"].factory(_classPrivateFieldGet(_mlsOrder, this), this.sinkSamplingRate, this.sourceSamplingRate).then(mlsGenInterface => {\n _classPrivateFieldSet(_mlsGenInterface, this, mlsGenInterface);\n _classPrivateFieldSet(_mlsBufferView, this, _classPrivateFieldGet(_mlsGenInterface, this).getMLS());\n });\n\n // after intializating, start the calibration steps with garbage collection\n await _classPrivateFieldGet(_mlsGenInterface, this).withGarbageCollection([() => this.calibrationSteps(stream, _classPrivateFieldGet(_playCalibrationAudioConvolved, this),\n // play audio func (required)\n _classPrivateFieldGet(_putInPythonConv, this),\n // before play func\n _classPrivateFieldGet(_awaitSignalOnset, this),\n // before record\n () => this.numSuccessfulCaptured < 1,\n // < this.numCaptures\n _classPrivateFieldGet(_awaitDesiredMLSLength, this),\n // during record\n _classPrivateFieldGet(_afterMLSwIIRRecord, this),\n // after record\n 'filtered')]);\n });\n // function to write frq and gain to firebase database given speakerID\n _defineProperty(this, \"writeFrqGain\", async (speakerID, frq, gain) => {\n const data = {\n frq,\n gain\n };\n await (0,firebase_database__WEBPACK_IMPORTED_MODULE_10__.set)((0,firebase_database__WEBPACK_IMPORTED_MODULE_10__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_9__[\"default\"], \"\".concat(speakerID, \"/linear\")), data);\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 _defineProperty(this, \"readFrqGain\", async speakerID => {\n const dbRef = (0,firebase_database__WEBPACK_IMPORTED_MODULE_10__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_9__[\"default\"]);\n const snapshot = await (0,firebase_database__WEBPACK_IMPORTED_MODULE_10__.get)((0,firebase_database__WEBPACK_IMPORTED_MODULE_10__.child)(dbRef, \"\".concat(speakerID, \"/linear\")));\n if (snapshot.exists()) {\n return snapshot.val();\n }\n return null;\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 /**\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 */\n _defineProperty(this, \"startCalibration\", async stream => {\n // initialize the MLSGenInterface object with it's factory method\n await _mlsGen_mlsGenInterface__WEBPACK_IMPORTED_MODULE_7__[\"default\"].factory(_classPrivateFieldGet(_mlsOrder, this), this.sinkSamplingRate, this.sourceSamplingRate).then(mlsGenInterface => {\n _classPrivateFieldSet(_mlsGenInterface, this, mlsGenInterface);\n _classPrivateFieldSet(_mlsBufferView, this, _classPrivateFieldGet(_mlsGenInterface, this).getMLS());\n });\n\n // after intializating, start the calibration steps with garbage collection\n await _classPrivateFieldGet(_mlsGenInterface, this).withGarbageCollection([() => this.calibrationSteps(stream, _classPrivateFieldGet(_playCalibrationAudio, this),\n // play audio func (required)\n _classPrivateFieldGet(_setCalibrationNodesFromBuffer, this),\n // before play func\n _classPrivateFieldGet(_awaitSignalOnset, this),\n // before record\n () => this.numSuccessfulCaptured < this.numCaptures,\n // loop while true\n _classPrivateFieldGet(_awaitDesiredMLSLength, this),\n // during record\n _classPrivateFieldGet(_afterMLSRecord, this),\n // after record\n 'unfiltered')]);\n _classPrivateFieldGet(_stopCalibrationAudio, this).call(this);\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 this.numSuccessfulCaptured = 0;\n // debugging function, use to test the result of the IIR\n await this.playMLSwithIIR(stream, this.invertedImpulseResponse);\n _classPrivateFieldGet(_stopCalibrationAudioConvolved, this).call(this);\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 this.status = \"computing the PSD graphs...\".toString() + this.generateTemplate().toString();\n this.emit('update', {\n message: this.status\n });\n let results = await this.pyServerAPI.getPSDWithRetry({\n unconv_rec,\n conv_rec\n }).then(res => {\n this.incrementStatusBar();\n this.status = \"done computing the PSD graphs\".toString() + this.generateTemplate().toString();\n this.emit('update', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\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 if (_classPrivateFieldGet(_download, this)) {\n this.downloadSingleUnfilteredRecording();\n this.downloadSingleFilteredRecording();\n (0,_utils__WEBPACK_IMPORTED_MODULE_8__.saveToCSV)(_classPrivateFieldGet(_mls, this), 'MLS.csv');\n (0,_utils__WEBPACK_IMPORTED_MODULE_8__.saveToCSV)(this.convolution, 'python_convolution_mls_iir.csv');\n (0,_utils__WEBPACK_IMPORTED_MODULE_8__.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_8__.saveToCSV)(res[i], \"IR_\".concat(i));\n }\n }\n });\n }\n return iir_and_plots;\n });\n _classPrivateFieldSet(_mlsOrder, this, parseInt(mlsOrder, 10));\n _classPrivateFieldSet(_P, this, 2 ** mlsOrder - 1);\n _classPrivateFieldSet(_download, this, download);\n _classPrivateFieldSet(_mls, this, []);\n _classPrivateFieldSet(_lowHz, this, _lowHz2);\n _classPrivateFieldSet(_highHz, this, _highHz2);\n }\n}\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 */\n_defineProperty(ImpulseResponse, \"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_defineProperty(ImpulseResponse, \"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/* harmony default export */ __webpack_exports__[\"default\"] = (ImpulseResponse);\n\n//# sourceURL=webpack://speakerCalibrator/./src/tasks/impulse-response/impulseResponse.js?");
|
|
194
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_array_buffer_slice_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array-buffer.slice.js */ \"./node_modules/core-js/modules/es.array-buffer.slice.js\");\n/* harmony import */ var core_js_modules_es_array_buffer_slice_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_buffer_slice_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_es_typed_array_float32_array_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/es.typed-array.float32-array.js */ \"./node_modules/core-js/modules/es.typed-array.float32-array.js\");\n/* harmony import */ var core_js_modules_es_typed_array_float32_array_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_typed_array_float32_array_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_es_typed_array_fill_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/es.typed-array.fill.js */ \"./node_modules/core-js/modules/es.typed-array.fill.js\");\n/* harmony import */ var core_js_modules_es_typed_array_fill_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_typed_array_fill_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var core_js_modules_es_typed_array_set_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! core-js/modules/es.typed-array.set.js */ \"./node_modules/core-js/modules/es.typed-array.set.js\");\n/* harmony import */ var core_js_modules_es_typed_array_set_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_typed_array_set_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var core_js_modules_es_typed_array_sort_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! core-js/modules/es.typed-array.sort.js */ \"./node_modules/core-js/modules/es.typed-array.sort.js\");\n/* harmony import */ var core_js_modules_es_typed_array_sort_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_typed_array_sort_js__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! core-js/modules/web.dom-collections.iterator.js */ \"./node_modules/core-js/modules/web.dom-collections.iterator.js\");\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var _audioCalibrator__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../audioCalibrator */ \"./src/tasks/audioCalibrator.js\");\n/* harmony import */ var _mlsGen_mlsGenInterface__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./mlsGen/mlsGenInterface */ \"./src/tasks/impulse-response/mlsGen/mlsGenInterface.js\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../utils */ \"./src/utils.js\");\n/* harmony import */ var _config_firebase__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../config/firebase */ \"./src/config/firebase.js\");\n/* harmony import */ var firebase_database__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! firebase/database */ \"./node_modules/firebase/database/dist/esm/index.esm.js\");\n\n\n\n\n\n\nfunction _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }\nfunction _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError(\"Cannot initialize the same private elements twice on an object\"); }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }\nfunction _classPrivateFieldSet(s, a, r) { return s.set(_assertClassBrand(s, a), r), r; }\nfunction _assertClassBrand(e, t, n) { if (\"function\" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError(\"Private element is not present on this object\"); }\n\n\n\n\n\n\n/**\n *\n */\nvar _download = /*#__PURE__*/new WeakMap();\nvar _mlsGenInterface = /*#__PURE__*/new WeakMap();\nvar _mlsBufferView = /*#__PURE__*/new WeakMap();\nvar _mlsOrder = /*#__PURE__*/new WeakMap();\nvar _lowHz = /*#__PURE__*/new WeakMap();\nvar _highHz = /*#__PURE__*/new WeakMap();\nvar _mls = /*#__PURE__*/new WeakMap();\nvar _P = /*#__PURE__*/new WeakMap();\nvar _audioContext = /*#__PURE__*/new WeakMap();\nvar _awaitDesiredMLSLength = /*#__PURE__*/new WeakMap();\nvar _awaitSignalOnset = /*#__PURE__*/new WeakMap();\nvar _afterMLSRecord = /*#__PURE__*/new WeakMap();\nvar _afterMLSwIIRRecord = /*#__PURE__*/new WeakMap();\nvar _createPureTonenNode = /*#__PURE__*/new WeakMap();\nvar _createCalibrationNodeFromBuffer = /*#__PURE__*/new WeakMap();\nvar _setCalibrationNodesFromBuffer = /*#__PURE__*/new WeakMap();\nvar _putInPythonConv = /*#__PURE__*/new WeakMap();\nvar _playCalibrationAudio = /*#__PURE__*/new WeakMap();\nvar _playCalibrationAudioConvolved = /*#__PURE__*/new WeakMap();\nvar _stopCalibrationAudio = /*#__PURE__*/new WeakMap();\nvar _stopCalibrationAudioConvolved = /*#__PURE__*/new WeakMap();\nclass ImpulseResponse extends _audioCalibrator__WEBPACK_IMPORTED_MODULE_6__[\"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(_ref) {\n var _this;\n let {\n download = false,\n mlsOrder = 18,\n numCaptures = 3,\n numMLSPerCapture = 4,\n lowHz: _lowHz2 = 20,\n highHz: _highHz2 = 10000,\n loudSpeakerIr = null\n } = _ref;\n super(numCaptures, numMLSPerCapture);\n _this = this;\n /** @private */\n _defineProperty(this, \"stepNum\", 0);\n /** @private */\n _defineProperty(this, \"totalSteps\", 25);\n /** @private */\n _classPrivateFieldInitSpec(this, _download, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _mlsGenInterface, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _mlsBufferView, void 0);\n /** @private */\n _defineProperty(this, \"invertedImpulseResponse\", null);\n /** @private */\n _defineProperty(this, \"impulseResponses\", []);\n /** @private */\n _classPrivateFieldInitSpec(this, _mlsOrder, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _lowHz, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _highHz, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _mls, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _P, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _audioContext, void 0);\n /** @private */\n _defineProperty(this, \"TAPER_SECS\", 5);\n /** @private */\n _defineProperty(this, \"offsetGainNode\", void 0);\n /** @private */\n _defineProperty(this, \"convolution\", void 0);\n /** @private */\n _defineProperty(this, \"status_denominator\", 6);\n /** @private */\n _defineProperty(this, \"status_numerator\", 0);\n /** @private */\n _defineProperty(this, \"percent_complete\", 0);\n /** @private */\n _defineProperty(this, \"status\", \"\");\n /**generate string template that gets reevaluated as variable increases */\n _defineProperty(this, \"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: \".concat(this.percent_complete, \"%; height: 100%; background-color: #00aaff; border-radius: 8px;\\\"></div></div></div>\");\n return template;\n });\n /** increment numerator and percent for status bar */\n _defineProperty(this, \"incrementStatusBar\", () => {\n this.status_numerator += 1;\n this.percent_complete = this.status_numerator / this.status_denominator * 100;\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 _defineProperty(this, \"sendImpulseResponsesToServerForProcessing\", async () => {\n const computedIRs = await Promise.all(this.impulseResponses);\n const filteredComputedIRs = computedIRs.filter(element => {\n return element != undefined;\n });\n const mls = _classPrivateFieldGet(_mls, this);\n const lowHz = _classPrivateFieldGet(_lowHz, this);\n const highHz = _classPrivateFieldGet(_highHz, this);\n this.stepNum += 1;\n this.status = \"computing the IIR...\".toString() + this.generateTemplate().toString();\n this.emit('update', {\n message: this.status\n });\n return this.pyServerAPI.getInverseImpulseResponseWithRetry({\n payload: filteredComputedIRs.slice(0, this.numCaptures),\n mls,\n lowHz,\n highHz\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', {\n message: this.status\n });\n this.invertedImpulseResponse = res['iir'];\n this.convolution = res['convolution'];\n }).catch(err => {\n // this.emit('InvertedImpulseResponse', {res: false});\n console.error(err);\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 _defineProperty(this, \"sendRecordingToServerForProcessing\", signalCsv => {\n const allSignals = this.getAllRecordedSignals();\n const numSignals = allSignals.length;\n const mls = _classPrivateFieldGet(_mls, this);\n const payload = signalCsv && signalCsv.length > 0 ? (0,_utils__WEBPACK_IMPORTED_MODULE_8__.csvToArray)(signalCsv) : allSignals[numSignals - 1];\n console.log('sending rec');\n this.stepNum += 1;\n this.status = \"computing the IR of the last recording...\".toString() + this.generateTemplate().toString();\n this.emit('update', {\n message: this.status\n });\n this.impulseResponses.push(this.pyServerAPI.getImpulseResponse({\n sampleRate: this.sourceSamplingRate || 96000,\n payload,\n mls,\n P: _classPrivateFieldGet(_P, this)\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 = \"\".concat(this.numSuccessfulCaptured, \"/\").concat(this.numCaptures, \" IRs computed...\").toString() + this.generateTemplate().toString();\n this.emit('update', {\n message: this.status\n });\n return res;\n }\n }).catch(err => {\n console.error(err);\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 _classPrivateFieldInitSpec(this, _awaitDesiredMLSLength, async () => {\n // seconds per MLS = P / SR\n // await N * P / SR\n this.stepNum += 1;\n this.status = \"sampling the calibration signal...\".toString() + this.generateTemplate().toString();\n this.emit('update', {\n message: this.status\n });\n await (0,_utils__WEBPACK_IMPORTED_MODULE_8__.sleep)(_classPrivateFieldGet(_P, this) / this.sourceSamplingRate * this.numMLSPerCapture);\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 _classPrivateFieldInitSpec(this, _awaitSignalOnset, async () => {\n this.stepNum += 1;\n this.status = \"waiting for the signal to stabilize...\".toString() + this.generateTemplate().toString();\n this.emit('update', {\n message: this.status\n });\n await (0,_utils__WEBPACK_IMPORTED_MODULE_8__.sleep)(this.TAPER_SECS);\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 _classPrivateFieldInitSpec(this, _afterMLSRecord, () => {\n console.log('after record');\n this.sendRecordingToServerForProcessing();\n });\n _classPrivateFieldInitSpec(this, _afterMLSwIIRRecord, () => {\n if (this.numSuccessfulCaptured < 1) {\n this.numSuccessfulCaptured += 1;\n this.stepNum += 1;\n this.incrementStatusBar();\n this.status = \"\".concat(this.numSuccessfulCaptured, \" recording of convolved MLS captured\").toString() + this.generateTemplate().toString();\n this.emit('update', {\n message: this.status\n });\n }\n });\n /**\n * Construct a Calibration Node with the calibration parameters.\n *\n * @param CALIBRATION_TONE_FREQUENCY\n * @private\n * @example\n */\n _classPrivateFieldInitSpec(this, _createPureTonenNode, CALIBRATION_TONE_FREQUENCY => {\n const audioContext = this.makeNewSourceAudioContext();\n const oscilator = audioContext.createOscillator();\n const gainNode = audioContext.createGain();\n oscilator.frequency.value = CALIBRATION_TONE_FREQUENCY;\n oscilator.type = 'sine';\n gainNode.gain.value = 0.04;\n oscilator.connect(gainNode);\n gainNode.connect(audioContext.destination);\n this.addCalibrationNode(oscilator);\n });\n /**\n * Construct a Calibration Node with the calibration parameters.\n *\n * @param dataBuffer\n * @private\n * @example\n */\n _classPrivateFieldInitSpec(this, _createCalibrationNodeFromBuffer, dataBuffer => {\n const audioContext = this.makeNewSourceAudioContext();\n const buffer = audioContext.createBuffer(1,\n // number of channels\n dataBuffer.length, audioContext.sampleRate // sample rate\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 source.buffer = buffer;\n source.loop = true;\n source.connect(onsetGainNode);\n onsetGainNode.connect(this.offsetGainNode);\n this.offsetGainNode.connect(audioContext.destination);\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 * Given a data buffer, creates the required calibration node\n *\n * @param {*} dataBufferArray\n * @example\n */\n _classPrivateFieldInitSpec(this, _setCalibrationNodesFromBuffer, function () {\n let dataBufferArray = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [_classPrivateFieldGet(_mlsBufferView, _this)];\n if (dataBufferArray.length === 1) {\n _classPrivateFieldGet(_createCalibrationNodeFromBuffer, _this).call(_this, dataBufferArray[0]);\n } else {\n throw new Error('The length of the data buffer array must be 1');\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 _classPrivateFieldInitSpec(this, _putInPythonConv, () => {\n const audioCtx = this.makeNewSourceAudioContextConvolved();\n const buffer = audioCtx.createBuffer(1,\n // number of channels\n this.convolution.length, audioCtx.sampleRate // sample rate\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 const source = audioCtx.createBufferSource();\n source.buffer = buffer;\n source.loop = true;\n source.connect(audioCtx.destination);\n this.addCalibrationNodeConvolved(source);\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 _classPrivateFieldInitSpec(this, _playCalibrationAudio, () => {\n this.calibrationNodes[0].start(0);\n _classPrivateFieldSet(_mls, this, 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', {\n message: this.status\n });\n });\n _classPrivateFieldInitSpec(this, _playCalibrationAudioConvolved, () => {\n this.calibrationNodesConvolved[0].start(0);\n this.stepNum += 1;\n this.status = \"playing the convolved calibration tone...\".toString() + this.generateTemplate().toString();\n this.emit('update', {\n message: this.status\n });\n });\n /** .\n * .\n * .\n * Stops the audio with tapered offset\n *\n * @example\n */\n _classPrivateFieldInitSpec(this, _stopCalibrationAudio, () => {\n this.offsetGainNode.gain.setValueAtTime(this.offsetGainNode.gain.value, this.sourceAudioContext.currentTime);\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 = \"stopping the calibration tone...\".toString() + this.generateTemplate().toString();\n this.emit('update', {\n message: this.status\n });\n });\n _classPrivateFieldInitSpec(this, _stopCalibrationAudioConvolved, () => {\n this.offsetGainNode.gain.setValueAtTime(this.offsetGainNode.gain.value, this.sourceAudioContextConvolved.currentTime);\n this.offsetGainNode.gain.setTargetAtTime(0, this.sourceAudioContextConvolved.currentTime, 0.5);\n this.sourceAudioContextConvolved.close();\n this.stepNum += 1;\n this.status = \"stopping the convolved calibration tone...\".toString() + this.generateTemplate().toString();\n this.emit('update', {\n message: this.status\n });\n });\n _defineProperty(this, \"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_7__[\"default\"].factory(_classPrivateFieldGet(_mlsOrder, this), this.sinkSamplingRate, this.sourceSamplingRate).then(mlsGenInterface => {\n _classPrivateFieldSet(_mlsGenInterface, this, mlsGenInterface);\n _classPrivateFieldSet(_mlsBufferView, this, _classPrivateFieldGet(_mlsGenInterface, this).getMLS());\n });\n\n // after intializating, start the calibration steps with garbage collection\n await _classPrivateFieldGet(_mlsGenInterface, this).withGarbageCollection([() => this.calibrationSteps(stream, _classPrivateFieldGet(_playCalibrationAudioConvolved, this),\n // play audio func (required)\n _classPrivateFieldGet(_putInPythonConv, this),\n // before play func\n _classPrivateFieldGet(_awaitSignalOnset, this),\n // before record\n () => this.numSuccessfulCaptured < 1,\n // < this.numCaptures\n _classPrivateFieldGet(_awaitDesiredMLSLength, this),\n // during record\n _classPrivateFieldGet(_afterMLSwIIRRecord, this),\n // after record\n 'filtered')]);\n });\n // function to write frq and gain to firebase database given speakerID\n _defineProperty(this, \"writeFrqGain\", async (speakerID, frq, gain) => {\n const data = {\n frq,\n gain\n };\n await (0,firebase_database__WEBPACK_IMPORTED_MODULE_10__.set)((0,firebase_database__WEBPACK_IMPORTED_MODULE_10__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_9__[\"default\"], \"\".concat(speakerID, \"/linear\")), data);\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 _defineProperty(this, \"readFrqGain\", async speakerID => {\n const dbRef = (0,firebase_database__WEBPACK_IMPORTED_MODULE_10__.ref)(_config_firebase__WEBPACK_IMPORTED_MODULE_9__[\"default\"]);\n const snapshot = await (0,firebase_database__WEBPACK_IMPORTED_MODULE_10__.get)((0,firebase_database__WEBPACK_IMPORTED_MODULE_10__.child)(dbRef, \"\".concat(speakerID, \"/linear\")));\n if (snapshot.exists()) {\n return snapshot.val();\n }\n return null;\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 * 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 _defineProperty(this, \"startCalibration\", async stream => {\n // initialize the MLSGenInterface object with it's factory method\n await _mlsGen_mlsGenInterface__WEBPACK_IMPORTED_MODULE_7__[\"default\"].factory(_classPrivateFieldGet(_mlsOrder, this), this.sinkSamplingRate, this.sourceSamplingRate).then(mlsGenInterface => {\n _classPrivateFieldSet(_mlsGenInterface, this, mlsGenInterface);\n _classPrivateFieldSet(_mlsBufferView, this, _classPrivateFieldGet(_mlsGenInterface, this).getMLS());\n });\n\n // after intializating, start the calibration steps with garbage collection\n await _classPrivateFieldGet(_mlsGenInterface, this).withGarbageCollection([() => this.calibrationSteps(stream, _classPrivateFieldGet(_playCalibrationAudio, this),\n // play audio func (required)\n _classPrivateFieldGet(_setCalibrationNodesFromBuffer, this),\n // before play func\n _classPrivateFieldGet(_awaitSignalOnset, this),\n // before record\n () => this.numSuccessfulCaptured < this.numCaptures,\n // loop while true\n _classPrivateFieldGet(_awaitDesiredMLSLength, this),\n // during record\n _classPrivateFieldGet(_afterMLSRecord, this),\n // after record\n 'unfiltered')]);\n _classPrivateFieldGet(_stopCalibrationAudio, this).call(this);\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 this.numSuccessfulCaptured = 0;\n // debugging function, use to test the result of the IIR\n await this.playMLSwithIIR(stream, this.invertedImpulseResponse);\n _classPrivateFieldGet(_stopCalibrationAudioConvolved, this).call(this);\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 this.status = \"computing the PSD graphs...\".toString() + this.generateTemplate().toString();\n this.emit('update', {\n message: this.status\n });\n let results = await this.pyServerAPI.getPSDWithRetry({\n unconv_rec,\n conv_rec\n }).then(res => {\n this.incrementStatusBar();\n this.status = \"done computing the PSD graphs\".toString() + this.generateTemplate().toString();\n this.emit('update', {\n message: this.status\n });\n return res;\n }).catch(err => {\n console.error(err);\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 if (_classPrivateFieldGet(_download, this)) {\n this.downloadSingleUnfilteredRecording();\n this.downloadSingleFilteredRecording();\n (0,_utils__WEBPACK_IMPORTED_MODULE_8__.saveToCSV)(_classPrivateFieldGet(_mls, this), 'MLS.csv');\n (0,_utils__WEBPACK_IMPORTED_MODULE_8__.saveToCSV)(this.convolution, 'python_convolution_mls_iir.csv');\n (0,_utils__WEBPACK_IMPORTED_MODULE_8__.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_8__.saveToCSV)(res[i], \"IR_\".concat(i));\n }\n }\n });\n }\n return iir_and_plots;\n });\n _classPrivateFieldSet(_mlsOrder, this, parseInt(mlsOrder, 10));\n _classPrivateFieldSet(_P, this, 2 ** mlsOrder - 1);\n _classPrivateFieldSet(_download, this, download);\n _classPrivateFieldSet(_mls, this, []);\n _classPrivateFieldSet(_lowHz, this, _lowHz2);\n _classPrivateFieldSet(_highHz, this, _highHz2);\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_defineProperty(ImpulseResponse, \"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_defineProperty(ImpulseResponse, \"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/* harmony default export */ __webpack_exports__[\"default\"] = (ImpulseResponse);\n\n//# sourceURL=webpack://speakerCalibrator/./src/tasks/impulse-response/impulseResponse.js?");
|
|
195
195
|
|
|
196
196
|
/***/ }),
|
|
197
197
|
|
|
@@ -202,7 +202,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core
|
|
|
202
202
|
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
203
203
|
|
|
204
204
|
"use strict";
|
|
205
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/web.dom-collections.iterator.js */ \"./node_modules/core-js/modules/web.dom-collections.iterator.js\");\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_0__);\nvar _MlsGenInterface;\n\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }\nfunction _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError(\"Cannot initialize the same private elements twice on an object\"); }\nfunction _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }\nfunction _classPrivateFieldSet(s, a, r) { return s.set(_assertClassBrand(s, a), r), r; }\nfunction _assertClassBrand(e, t, n) { if (\"function\" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError(\"Private element is not present on this object\"); }\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/**\
|
|
205
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/web.dom-collections.iterator.js */ \"./node_modules/core-js/modules/web.dom-collections.iterator.js\");\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_0__);\nvar _MlsGenInterface;\n\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }\nfunction _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError(\"Cannot initialize the same private elements twice on an object\"); }\nfunction _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }\nfunction _classPrivateFieldSet(s, a, r) { return s.set(_assertClassBrand(s, a), r), r; }\nfunction _assertClassBrand(e, t, n) { if (\"function\" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError(\"Private element is not present on this object\"); }\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 */\nvar _mlsOrder = /*#__PURE__*/new WeakMap();\nvar _WASMInstance = /*#__PURE__*/new WeakMap();\nvar _MLSGenInstance = /*#__PURE__*/new WeakMap();\nclass MlsGenInterface {\n // 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 /** @private */\n _classPrivateFieldInitSpec(this, _mlsOrder, void 0);\n /** @private */\n _classPrivateFieldInitSpec(this, _WASMInstance, void 0);\n // the WASM module instance\n\n /** @private */\n _classPrivateFieldInitSpec(this, _MLSGenInstance, void 0);\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 _defineProperty(this, \"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 (this !== undefined && this !== null && _classPrivateFieldGet(_MLSGenInstance, this) !== undefined && _classPrivateFieldGet(_MLSGenInstance, this) !== null) {\n _classPrivateFieldGet(_MLSGenInstance, this)['Destruct'](); // Call the destructor\n _classPrivateFieldGet(_MLSGenInstance, this)['delete'](); // Delete the object\n console.warn(\"GARBAGE COLLECTION: deleted MLSGen\");\n _classPrivateFieldGet(_WASMInstance, this)['doLeakCheck'](); // Check for memory leaks\n }\n }\n });\n /**\n * Calculate and return the Impulse Response of the recorded signal.\n *\n * @returns\n * @example\n */\n _defineProperty(this, \"getImpulseResponse\", () => _classPrivateFieldGet(_MLSGenInstance, this)['getImpulseResponse']());\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 _defineProperty(this, \"setRecordedSignals\", signals => {\n // get memory view\n const averagedSignals = this.average(signals);\n const recordedSignalsMemoryView = _classPrivateFieldGet(_MLSGenInstance, this)['setRecordedSignalsMemoryView'](averagedSignals.byteLength);\n for (let i = 0; i < averagedSignals.length; i += 1) {\n recordedSignalsMemoryView[i] = averagedSignals[i];\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 _defineProperty(this, \"getMLS\", () => _classPrivateFieldGet(_MLSGenInstance, this)['getMLS']());\n _classPrivateFieldSet(_mlsOrder, this, mlsOrder);\n _classPrivateFieldSet(_WASMInstance, this, WASMInstance);\n console.warn('initializing MLSGen, need to manually garbage collect');\n _classPrivateFieldSet(_MLSGenInstance, this, new (_classPrivateFieldGet(_WASMInstance, this)['MLSGen'])(mlsOrder, sourceSamplingRate, sinkSamplingRate));\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}\n_MlsGenInterface = MlsGenInterface;\n_defineProperty(MlsGenInterface, \"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(await createMLSGenModule().then(instance => instance), mlsOrder, sourceSamplingRate, sinkSamplingRate);\n});\n/* harmony default export */ __webpack_exports__[\"default\"] = (MlsGenInterface);\n\n//# sourceURL=webpack://speakerCalibrator/./src/tasks/impulse-response/mlsGen/mlsGenInterface.js?");
|
|
206
206
|
|
|
207
207
|
/***/ }),
|
|
208
208
|
|
|
@@ -213,7 +213,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core
|
|
|
213
213
|
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
214
214
|
|
|
215
215
|
"use strict";
|
|
216
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_array_buffer_slice_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array-buffer.slice.js */ \"./node_modules/core-js/modules/es.array-buffer.slice.js\");\n/* harmony import */ var core_js_modules_es_array_buffer_slice_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_buffer_slice_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_es_typed_array_float32_array_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/es.typed-array.float32-array.js */ \"./node_modules/core-js/modules/es.typed-array.float32-array.js\");\n/* harmony import */ var core_js_modules_es_typed_array_float32_array_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_typed_array_float32_array_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_es_typed_array_fill_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/es.typed-array.fill.js */ \"./node_modules/core-js/modules/es.typed-array.fill.js\");\n/* harmony import */ var core_js_modules_es_typed_array_fill_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_typed_array_fill_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var core_js_modules_es_typed_array_set_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! core-js/modules/es.typed-array.set.js */ \"./node_modules/core-js/modules/es.typed-array.set.js\");\n/* harmony import */ var core_js_modules_es_typed_array_set_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_typed_array_set_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var core_js_modules_es_typed_array_sort_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! core-js/modules/es.typed-array.sort.js */ \"./node_modules/core-js/modules/es.typed-array.sort.js\");\n/* harmony import */ var core_js_modules_es_typed_array_sort_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_typed_array_sort_js__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! core-js/modules/web.dom-collections.iterator.js */ \"./node_modules/core-js/modules/web.dom-collections.iterator.js\");\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var _audioCalibrator__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../audioCalibrator */ \"./src/tasks/audioCalibrator.js\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../utils */ \"./src/utils.js\");\n\n\n\n\n\n\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }\nfunction _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError(\"Cannot initialize the same private elements twice on an object\"); }\nfunction _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }\nfunction _assertClassBrand(e, t, n) { if (\"function\" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError(\"Private element is not present on this object\"); }\n\n\n\n\n/**\r\n *\r\n */\nvar _CALIBRATION_TONE_FREQUENCY = /*#__PURE__*/new WeakMap();\nvar _CALIBRATION_TONE_TYPE = /*#__PURE__*/new WeakMap();\nvar _CALIBRATION_TONE_DURATION = /*#__PURE__*/new WeakMap();\nvar _getTruncatedSignal = /*#__PURE__*/new WeakMap();\nvar _createCalibrationToneWithGainValue = /*#__PURE__*/new WeakMap();\nvar _createCalibrationNode = /*#__PURE__*/new WeakMap();\nvar _playCalibrationAudio = /*#__PURE__*/new WeakMap();\nvar _sendToServerForProcessing = /*#__PURE__*/new WeakMap();\nclass Volume extends _audioCalibrator__WEBPACK_IMPORTED_MODULE_6__[\"default\"] {\n constructor() {\n var _this;\n super(...arguments);\n _this = this;\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 */\n\n /** @private */\n _classPrivateFieldInitSpec(this, _CALIBRATION_TONE_FREQUENCY, 1000);\n // Hz\n\n /** @private */\n _classPrivateFieldInitSpec(this, _CALIBRATION_TONE_TYPE, 'sine');\n /** @private */\n _classPrivateFieldInitSpec(this, _CALIBRATION_TONE_DURATION, 5);\n // seconds\n /** @private */\n _defineProperty(this, \"outDBSPL\", null);\n _defineProperty(this, \"THD\", null);\n _defineProperty(this, \"outDBSPL1000\", null);\n /** @private */\n _defineProperty(this, \"TAPER_SECS\", 0.010);\n // seconds\n /** @private */\n _defineProperty(this, \"status_denominator\", 2);\n /** @private */\n _defineProperty(this, \"status_numerator\", 0);\n /** @private */\n _defineProperty(this, \"percent_complete\", 0);\n /** @private */\n _defineProperty(this, \"status\", \"\");\n /**generate string template that gets reevaluated as variable increases */\n _defineProperty(this, \"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: \".concat(this.percent_complete, \"%; height: 100%; background-color: #00aaff; border-radius: 8px;\\\"></div></div></div>\");\n return template;\n });\n /** increment numerator and percent for status bar */\n _defineProperty(this, \"incrementStatusBar\", () => {\n this.status_numerator += 1;\n this.percent_complete = this.status_numerator / this.status_denominator * 100;\n });\n _defineProperty(this, \"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: \".concat(data.type));\n }\n });\n _defineProperty(this, \"createSCurveBuffer\", function () {\n let onSetBool = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 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 _classPrivateFieldInitSpec(this, _getTruncatedSignal, function () {\n let left = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 3.5;\n let right = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 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 /**\r\n * function to check that capture was properly made\r\n * @param {*} list\r\n */\n const checkResult = list => {\n const setItem = new Set(list);\n if (setItem.size === 1 && setItem.has(0)) {\n console.warn('The last capture failed, all recorded signal is zero', _this.getAllRecordedSignals());\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 /** \r\n * \r\n * \r\n Construct a calibration Node with the calibration parameters and given gain value\r\n * @param {*} gainValue\r\n * */\n _classPrivateFieldInitSpec(this, _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 = _classPrivateFieldGet(_CALIBRATION_TONE_DURATION, this) * 1.2;\n oscilator.frequency.value = _classPrivateFieldGet(_CALIBRATION_TONE_FREQUENCY, this);\n oscilator.type = _classPrivateFieldGet(_CALIBRATION_TONE_TYPE, this);\n gainNode.gain.value = gainValue;\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 this.addCalibrationNode(oscilator);\n });\n /**\r\n * Construct a Calibration Node with the calibration parameters.\r\n *\r\n * @private\r\n * @example\r\n */\n _classPrivateFieldInitSpec(this, _createCalibrationNode, () => {\n const audioContext = this.makeNewSourceAudioContext();\n const oscilator = audioContext.createOscillator();\n const gainNode = audioContext.createGain();\n oscilator.frequency.value = _classPrivateFieldGet(_CALIBRATION_TONE_FREQUENCY, this);\n oscilator.type = _classPrivateFieldGet(_CALIBRATION_TONE_TYPE, this);\n gainNode.gain.value = 0.04;\n oscilator.connect(gainNode);\n gainNode.connect(audioContext.destination);\n this.addCalibrationNode(oscilator);\n });\n _classPrivateFieldInitSpec(this, _playCalibrationAudio, async () => {\n const totalDuration = _classPrivateFieldGet(_CALIBRATION_TONE_DURATION, this) * 1.2;\n this.calibrationNodes[0].start(0);\n this.calibrationNodes[0].stop(totalDuration);\n console.log(\"Playing a buffer of \".concat(_classPrivateFieldGet(_CALIBRATION_TONE_DURATION, this), \" seconds of audio\"));\n console.log(\"Waiting a total of \".concat(totalDuration, \" seconds\"));\n await (0,_utils__WEBPACK_IMPORTED_MODULE_7__.sleep)(totalDuration);\n });\n _classPrivateFieldInitSpec(this, _sendToServerForProcessing, function () {\n let lCalib = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 104.92978421490648;\n console.log('Sending data to server');\n _this.pyServerAPI.getVolumeCalibration({\n sampleRate: _this.sourceSamplingRate,\n payload: _classPrivateFieldGet(_getTruncatedSignal, _this).call(_this),\n lCalib: lCalib\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 }).catch(err => {\n console.warn(err);\n });\n });\n _defineProperty(this, \"startCalibration\", async function (stream, gainValues) {\n let lCalib = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 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: \".concat(soundLevelToDiscard, \" dB\").toString() + _this.generateTemplate().toString();\n _this.emit('update', {\n message: _this.status\n });\n do {\n // eslint-disable-next-line no-await-in-loop\n await _this.volumeCalibrationSteps(stream, _classPrivateFieldGet(_playCalibrationAudio, _this), _classPrivateFieldGet(_createCalibrationToneWithGainValue, _this), _classPrivateFieldGet(_sendToServerForProcessing, _this), gainToDiscard, 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: \".concat(inDB, \" dB\").toString() + _this.generateTemplate().toString();\n _this.emit('update', {\n message: _this.status\n });\n do {\n // eslint-disable-next-line no-await-in-loop\n await _this.volumeCalibrationSteps(stream, _classPrivateFieldGet(_playCalibrationAudio, _this), _classPrivateFieldGet(_createCalibrationToneWithGainValue, _this), _classPrivateFieldGet(_sendToServerForProcessing, _this), gainValues[i], 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 _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.getVolumeCalibrationParameters({\n inDBValues: inDBValues,\n outDBSPLValues: outDBSPL1000Values,\n lCalib: lCalib\n }).then(res => {\n _this.incrementStatusBar();\n _this.status = \"done with 1000 Hz calibration\".toString() + _this.generateTemplate().toString();\n _this.emit('update', {\n message: _this.status\n });\n return res;\n });\n const result = {\n parameters: parameters,\n inDBValues: inDBValues,\n outDBSPLValues: outDBSPLValues,\n outDBSPL1000Values: outDBSPL1000Values,\n thdValues: thdValues\n };\n return result;\n });\n }\n}\n/* harmony default export */ __webpack_exports__[\"default\"] = (Volume);\n\n//# sourceURL=webpack://speakerCalibrator/./src/tasks/volume/volume.js?");
|
|
216
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_array_buffer_slice_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array-buffer.slice.js */ \"./node_modules/core-js/modules/es.array-buffer.slice.js\");\n/* harmony import */ var core_js_modules_es_array_buffer_slice_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_buffer_slice_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_es_typed_array_float32_array_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/es.typed-array.float32-array.js */ \"./node_modules/core-js/modules/es.typed-array.float32-array.js\");\n/* harmony import */ var core_js_modules_es_typed_array_float32_array_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_typed_array_float32_array_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_es_typed_array_fill_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/es.typed-array.fill.js */ \"./node_modules/core-js/modules/es.typed-array.fill.js\");\n/* harmony import */ var core_js_modules_es_typed_array_fill_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_typed_array_fill_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var core_js_modules_es_typed_array_set_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! core-js/modules/es.typed-array.set.js */ \"./node_modules/core-js/modules/es.typed-array.set.js\");\n/* harmony import */ var core_js_modules_es_typed_array_set_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_typed_array_set_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var core_js_modules_es_typed_array_sort_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! core-js/modules/es.typed-array.sort.js */ \"./node_modules/core-js/modules/es.typed-array.sort.js\");\n/* harmony import */ var core_js_modules_es_typed_array_sort_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_typed_array_sort_js__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! core-js/modules/web.dom-collections.iterator.js */ \"./node_modules/core-js/modules/web.dom-collections.iterator.js\");\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var _audioCalibrator__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../audioCalibrator */ \"./src/tasks/audioCalibrator.js\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../utils */ \"./src/utils.js\");\n\n\n\n\n\n\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }\nfunction _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError(\"Cannot initialize the same private elements twice on an object\"); }\nfunction _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }\nfunction _assertClassBrand(e, t, n) { if (\"function\" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError(\"Private element is not present on this object\"); }\n\n\n\n\n/**\n *\n */\nvar _CALIBRATION_TONE_FREQUENCY = /*#__PURE__*/new WeakMap();\nvar _CALIBRATION_TONE_TYPE = /*#__PURE__*/new WeakMap();\nvar _CALIBRATION_TONE_DURATION = /*#__PURE__*/new WeakMap();\nvar _getTruncatedSignal = /*#__PURE__*/new WeakMap();\nvar _createCalibrationToneWithGainValue = /*#__PURE__*/new WeakMap();\nvar _createCalibrationNode = /*#__PURE__*/new WeakMap();\nvar _playCalibrationAudio = /*#__PURE__*/new WeakMap();\nvar _sendToServerForProcessing = /*#__PURE__*/new WeakMap();\nclass Volume extends _audioCalibrator__WEBPACK_IMPORTED_MODULE_6__[\"default\"] {\n constructor() {\n var _this;\n super(...arguments);\n _this = this;\n /**\n *\n * @param root0\n * @param root0.download\n * @param root0.numCalibrationRounds\n * @param root0.numCalibrationNodes\n * @example\n */\n\n /** @private */\n _classPrivateFieldInitSpec(this, _CALIBRATION_TONE_FREQUENCY, 1000);\n // Hz\n\n /** @private */\n _classPrivateFieldInitSpec(this, _CALIBRATION_TONE_TYPE, 'sine');\n /** @private */\n _classPrivateFieldInitSpec(this, _CALIBRATION_TONE_DURATION, 5);\n // seconds\n /** @private */\n _defineProperty(this, \"outDBSPL\", null);\n _defineProperty(this, \"THD\", null);\n _defineProperty(this, \"outDBSPL1000\", null);\n /** @private */\n _defineProperty(this, \"TAPER_SECS\", 0.010);\n // seconds\n /** @private */\n _defineProperty(this, \"status_denominator\", 2);\n /** @private */\n _defineProperty(this, \"status_numerator\", 0);\n /** @private */\n _defineProperty(this, \"percent_complete\", 0);\n /** @private */\n _defineProperty(this, \"status\", \"\");\n /**generate string template that gets reevaluated as variable increases */\n _defineProperty(this, \"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: \".concat(this.percent_complete, \"%; height: 100%; background-color: #00aaff; border-radius: 8px;\\\"></div></div></div>\");\n return template;\n });\n /** increment numerator and percent for status bar */\n _defineProperty(this, \"incrementStatusBar\", () => {\n this.status_numerator += 1;\n this.percent_complete = this.status_numerator / this.status_denominator * 100;\n });\n _defineProperty(this, \"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: \".concat(data.type));\n }\n });\n _defineProperty(this, \"createSCurveBuffer\", function () {\n let onSetBool = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 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 _classPrivateFieldInitSpec(this, _getTruncatedSignal, function () {\n let left = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 3.5;\n let right = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 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('The last capture failed, all recorded signal is zero', _this.getAllRecordedSignals());\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 Construct a calibration Node with the calibration parameters and given gain value\n * @param {*} gainValue\n * */\n _classPrivateFieldInitSpec(this, _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 = _classPrivateFieldGet(_CALIBRATION_TONE_DURATION, this) * 1.2;\n oscilator.frequency.value = _classPrivateFieldGet(_CALIBRATION_TONE_FREQUENCY, this);\n oscilator.type = _classPrivateFieldGet(_CALIBRATION_TONE_TYPE, this);\n gainNode.gain.value = gainValue;\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 this.addCalibrationNode(oscilator);\n });\n /**\n * Construct a Calibration Node with the calibration parameters.\n *\n * @private\n * @example\n */\n _classPrivateFieldInitSpec(this, _createCalibrationNode, () => {\n const audioContext = this.makeNewSourceAudioContext();\n const oscilator = audioContext.createOscillator();\n const gainNode = audioContext.createGain();\n oscilator.frequency.value = _classPrivateFieldGet(_CALIBRATION_TONE_FREQUENCY, this);\n oscilator.type = _classPrivateFieldGet(_CALIBRATION_TONE_TYPE, this);\n gainNode.gain.value = 0.04;\n oscilator.connect(gainNode);\n gainNode.connect(audioContext.destination);\n this.addCalibrationNode(oscilator);\n });\n _classPrivateFieldInitSpec(this, _playCalibrationAudio, async () => {\n const totalDuration = _classPrivateFieldGet(_CALIBRATION_TONE_DURATION, this) * 1.2;\n this.calibrationNodes[0].start(0);\n this.calibrationNodes[0].stop(totalDuration);\n console.log(\"Playing a buffer of \".concat(_classPrivateFieldGet(_CALIBRATION_TONE_DURATION, this), \" seconds of audio\"));\n console.log(\"Waiting a total of \".concat(totalDuration, \" seconds\"));\n await (0,_utils__WEBPACK_IMPORTED_MODULE_7__.sleep)(totalDuration);\n });\n _classPrivateFieldInitSpec(this, _sendToServerForProcessing, function () {\n let lCalib = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 104.92978421490648;\n console.log('Sending data to server');\n _this.pyServerAPI.getVolumeCalibration({\n sampleRate: _this.sourceSamplingRate,\n payload: _classPrivateFieldGet(_getTruncatedSignal, _this).call(_this),\n lCalib: lCalib\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 }).catch(err => {\n console.warn(err);\n });\n });\n _defineProperty(this, \"startCalibration\", async function (stream, gainValues) {\n let lCalib = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 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: \".concat(soundLevelToDiscard, \" dB\").toString() + _this.generateTemplate().toString();\n _this.emit('update', {\n message: _this.status\n });\n do {\n // eslint-disable-next-line no-await-in-loop\n await _this.volumeCalibrationSteps(stream, _classPrivateFieldGet(_playCalibrationAudio, _this), _classPrivateFieldGet(_createCalibrationToneWithGainValue, _this), _classPrivateFieldGet(_sendToServerForProcessing, _this), gainToDiscard, 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: \".concat(inDB, \" dB\").toString() + _this.generateTemplate().toString();\n _this.emit('update', {\n message: _this.status\n });\n do {\n // eslint-disable-next-line no-await-in-loop\n await _this.volumeCalibrationSteps(stream, _classPrivateFieldGet(_playCalibrationAudio, _this), _classPrivateFieldGet(_createCalibrationToneWithGainValue, _this), _classPrivateFieldGet(_sendToServerForProcessing, _this), gainValues[i], 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 _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.getVolumeCalibrationParameters({\n inDBValues: inDBValues,\n outDBSPLValues: outDBSPL1000Values,\n lCalib: lCalib\n }).then(res => {\n _this.incrementStatusBar();\n _this.status = \"done with 1000 Hz calibration\".toString() + _this.generateTemplate().toString();\n _this.emit('update', {\n message: _this.status\n });\n return res;\n });\n const result = {\n parameters: parameters,\n inDBValues: inDBValues,\n outDBSPLValues: outDBSPLValues,\n outDBSPL1000Values: outDBSPL1000Values,\n thdValues: thdValues\n };\n return result;\n });\n }\n}\n/* harmony default export */ __webpack_exports__[\"default\"] = (Volume);\n\n//# sourceURL=webpack://speakerCalibrator/./src/tasks/volume/volume.js?");
|
|
217
217
|
|
|
218
218
|
/***/ }),
|
|
219
219
|
|
|
@@ -224,7 +224,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core
|
|
|
224
224
|
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
225
225
|
|
|
226
226
|
"use strict";
|
|
227
|
-
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 core_js_modules_es_string_replace_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.string.replace.js */ \"./node_modules/core-js/modules/es.string.replace.js\");\n/* harmony import */ var core_js_modules_es_string_replace_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_string_replace_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_es_string_trim_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/es.string.trim.js */ \"./node_modules/core-js/modules/es.string.trim.js\");\n/* harmony import */ var core_js_modules_es_string_trim_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_string_trim_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/web.dom-collections.iterator.js */ \"./node_modules/core-js/modules/web.dom-collections.iterator.js\");\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var core_js_modules_web_url_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! core-js/modules/web.url.js */ \"./node_modules/core-js/modules/web.url.js\");\n/* harmony import */ var core_js_modules_web_url_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_url_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var core_js_modules_web_url_to_json_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! core-js/modules/web.url.to-json.js */ \"./node_modules/core-js/modules/web.url.to-json.js\");\n/* harmony import */ var core_js_modules_web_url_to_json_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_url_to_json_js__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var core_js_modules_web_url_search_params_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! core-js/modules/web.url-search-params.js */ \"./node_modules/core-js/modules/web.url-search-params.js\");\n/* harmony import */ var core_js_modules_web_url_search_params_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_url_search_params_js__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var sweetalert2__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! sweetalert2 */ \"./node_modules/sweetalert2/dist/sweetalert2.all.js\");\n/* harmony import */ var sweetalert2__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(sweetalert2__WEBPACK_IMPORTED_MODULE_6__);\n\n\n\n\n\n\n\n//import {phrases} from '../dist/example/i18n.js';\n/** .\
|
|
227
|
+
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 core_js_modules_es_string_replace_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.string.replace.js */ \"./node_modules/core-js/modules/es.string.replace.js\");\n/* harmony import */ var core_js_modules_es_string_replace_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_string_replace_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_es_string_trim_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/es.string.trim.js */ \"./node_modules/core-js/modules/es.string.trim.js\");\n/* harmony import */ var core_js_modules_es_string_trim_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_string_trim_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/web.dom-collections.iterator.js */ \"./node_modules/core-js/modules/web.dom-collections.iterator.js\");\n/* harmony import */ var core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_dom_collections_iterator_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var core_js_modules_web_url_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! core-js/modules/web.url.js */ \"./node_modules/core-js/modules/web.url.js\");\n/* harmony import */ var core_js_modules_web_url_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_url_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var core_js_modules_web_url_to_json_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! core-js/modules/web.url.to-json.js */ \"./node_modules/core-js/modules/web.url.to-json.js\");\n/* harmony import */ var core_js_modules_web_url_to_json_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_url_to_json_js__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var core_js_modules_web_url_search_params_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! core-js/modules/web.url-search-params.js */ \"./node_modules/core-js/modules/web.url-search-params.js\");\n/* harmony import */ var core_js_modules_web_url_search_params_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_url_search_params_js__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var sweetalert2__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! sweetalert2 */ \"./node_modules/sweetalert2/dist/sweetalert2.all.js\");\n/* harmony import */ var sweetalert2__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(sweetalert2__WEBPACK_IMPORTED_MODULE_6__);\n\n\n\n\n\n\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 => 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 = function (data) {\n let filename = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'recordedMLSignal.csv';\n // console.log(data)\n let csvContent = 'data:text/csv;charset=utf-8,';\n data.forEach((val, idx) => {\n csvContent += \"\".concat(idx, \",\").concat(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};\nconst saveToJSON = function (data) {\n let filename = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'recordedMLSignal.json';\n const jsonData = JSON.stringify(data, null, 2);\n const blob = new Blob([jsonData], {\n type: 'application/json'\n });\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 * Utility function to create a buffer from a CSV file\n *\n * @param {*} csvString\n * @param {*} delimiter\n * @returns\n * @example\n */\nconst csvToArray = function (csvString) {\n let delimiter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ',';\n return csvString.trim().split('\\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};\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};\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 return dateString.replace(\"at \", \"\");\n};\nconst standardDeviation = values => {\n const avg = average(values);\n const squareDiffs = values.map(value => {\n const diff = value - avg;\n const sqrDiff = diff * diff;\n return sqrDiff;\n });\n const avgSquareDiff = average(squareDiffs);\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};\nconst average = data => {\n const sum = data.reduce((sum, value) => {\n return sum + value;\n }, 0);\n const avg = sum / data.length;\n return avg;\n};\nfunction interpolate(x, x0, x1, y0, y1) {\n return y0 + (y1 - y0) * (x - x0) / (x1 - x0);\n}\nconst formatLineBreak = (inputStr, checkInternetConnection) => {\n let finalStr = inputStr.replace(/\\n/g, '<br>').replace('LLL', \"<a href=\\\"#\\\" id=\\\"check-connection\\\">\".concat(checkInternetConnection, \"</a>\"));\n console.log(finalStr);\n return finalStr;\n};\nconst createAndShowPopup = (lang, phrases) => {\n console.log(\"\\n <div style=\\\"text-align: left;\\\"> \\n \".concat(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 \").concat(phrases.EE_ok[lang], \"\\n </button>\\n </div>\"));\n sweetalert2__WEBPACK_IMPORTED_MODULE_6___default().fire({\n html: \"\\n <div style=\\\"text-align: left;\\\"> \\n \".concat(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 \").concat(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_6___default().close(); // Close the Swal popup\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.replace(/\\* (.*?)(<br>|$)/g, '<li>$1</li>').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//# sourceURL=webpack://speakerCalibrator/./src/utils.js?");
|
|
228
228
|
|
|
229
229
|
/***/ }),
|
|
230
230
|
|