speaker-calibration 2.2.250 → 2.2.252
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/dist/phonePeer.js
CHANGED
|
@@ -36,7 +36,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
36
36
|
\***************************************/
|
|
37
37
|
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
38
38
|
|
|
39
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ PhonePeer: function() { return /* binding */ PhonePeer; }\n/* harmony export */ });\n/* harmony import */ var _dist_example_i18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../dist/example/i18n.js */ \"./dist/example/i18n.js\");\n/* harmony import */ var _peer_connection_listener_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../peer-connection/listener.js */ \"./src/peer-connection/listener.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\nclass PhonePeer {\n constructor() {\n var _this = this;\n _defineProperty(this, \"register\", manager => {\n this.connectionManager = manager;\n });\n _defineProperty(this, \"onMessage\", (data, manager) => {\n if (!data || !data.message) return;\n switch (data.message) {\n case 'connectionParams':\n console.log('connectionParams', data.payload);\n this.handleConnectionParams(data.payload);\n break;\n case 'phrases':\n console.log('phrases', data.payload);\n this.handlePhrases(data.payload);\n break;\n }\n });\n _defineProperty(this, \"handleConnectionParams\", async payload => {\n this.isSmartPhone = payload.sp;\n this.listenerParameters.speakerPeerId = payload.speakerPeerId;\n this.listenerParameters.hz = payload.hz;\n this.listenerParameters.bits = payload.bits;\n this.listenerParameters.lang = payload.lang;\n this.listenerParameters.deviceId = payload.deviceId;\n this.listenerParameters.sp = payload.sp;\n this.listenerParameters.microphoneDeviceId = payload.deviceId;\n this.handleStartCalibration();\n });\n _defineProperty(this, \"handlePhrases\", payload => {\n this.phrases = payload;\n });\n _defineProperty(this, \"createUI\", () => {\n const container = document.createElement('div');\n container.id = 'listenerContainer';\n container.className = 'container';\n container.innerHTML = \"\\n <p id=\\\"turnMeToReadBelow\\\"></p>\\n <div id=\\\"updateDisplay\\\">\\n <h1 id=\\\"recordingInProgress\\\"></h1>\\n <p id=\\\"allowMicrophone\\\"></p>\\n <button id=\\\"calibrationBeginButton\\\" class=\\\"btn btn-success\\\">Proceed</button>\\n </div>\\n <div id=\\\"display\\\"></div>\\n <div id=\\\"message\\\"></div>\\n <div id=\\\"phrases\\\"></div>\\n \";\n const target = document.getElementById('target');\n if (target) {\n console.log('target found');\n //clear the target\n target.innerHTML = '';\n target.appendChild(container);\n } else {\n console.log('target not found');\n //create a new target\n const newTarget = document.createElement('div');\n newTarget.id = 'target';\n document.body.appendChild(newTarget);\n newTarget.appendChild(container);\n }\n console.log('UI created');\n });\n _defineProperty(this, \"handleStartCalibration\", async () => {\n this.createUI();\n if (this.isSmartPhone) {\n await this.initializeSmartPhoneMode();\n } else {\n await this.initializeDesktopMode();\n }\n });\n _defineProperty(this, \"initializeListener\", async () => {\n this.listener = new _peer_connection_listener_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"](this.listenerParameters);\n this.listener.connectionManager = this.connectionManager;\n });\n _defineProperty(this, \"waitForConnection\", async function () {\n let timeout = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 30000;\n const startTime = Date.now();\n while (Date.now() - startTime < timeout) {\n if (_this.listener.connectionManager.peer.id !== null && _this.listener.connectionManager.conn !== null && _this.listener.connectionManager.connOpen) {\n console.log('Connection established successfully');\n return true;\n }\n console.log('Waiting for connection setup...');\n await new Promise(resolve => setTimeout(resolve, 100));\n }\n console.error('Connection setup timed out after 30 seconds');\n return false;\n });\n _defineProperty(this, \"initializeSmartPhoneMode\", async () => {\n // Hide target element\n const targetElement = document.getElementById('display');\n targetElement.style.display = 'none';\n\n // Initialize listener\n await this.initializeListener();\n if (await this.waitForConnection()) {\n await this.checkAndRequestMicrophonePermission();\n } else {\n const allowMicrophoneElement = document.getElementById('allowMicrophone');\n allowMicrophoneElement.innerText = this.phrases.RC_microphonePermissionDenied['en-US'];\n this.listener.sendPermissionStatus({\n type: 'error',\n error: 'Connection setup timed out after 30 seconds'\n });\n }\n });\n _defineProperty(this, \"checkAndRequestMicrophonePermission\", async () => {\n const container = document.getElementById('listenerContainer');\n const allowMicrophoneElement = document.getElementById('allowMicrophone');\n\n // Show permission request message\n allowMicrophoneElement.innerText = this.phrases.RC_microphonePermission['en-US'];\n container.style.display = 'block';\n\n // Function to request microphone access\n const requestMicAccess = async function () {\n let attempt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;\n try {\n await navigator.mediaDevices.getUserMedia({\n audio: true\n });\n // Permission granted, proceed to normal flow\n _this.initializeSmartPhoneDisplay();\n } catch (err) {\n if (err.name === 'NotAllowedError') {\n console.log('Permission explicitly denied');\n // Permission explicitly denied\n allowMicrophoneElement.innerText = _this.phrases.RC_microphonePermissionDenied['en-US'];\n // Send denied status and end study\n let error = JSON.stringify(err);\n _this.listener.sendPermissionStatus({\n type: 'denied',\n error: error\n });\n return;\n }\n\n // If 10 seconds passed, try again\n if (attempt < 3) {\n console.log('Retrying microphone access');\n // Limit retries\n setTimeout(() => requestMicAccess(attempt + 1), 10000);\n } else {\n console.log('All retries failed, treating as denied');\n // After all retries failed, treat as denied\n allowMicrophoneElement.innerText = _this.phrases.RC_microphonePermissionDenied['en-US'];\n let error = JSON.stringify(err);\n _this.listener.sendPermissionStatus({\n type: 'error',\n error: error\n });\n }\n }\n };\n try {\n await requestMicAccess();\n } catch (err) {\n console.error('Error requesting microphone permission:', err);\n allowMicrophoneElement.innerText = this.phrases.RC_microphonePermissionDenied['en-US'];\n let error = JSON.stringify(err);\n this.listener.sendPermissionStatus({\n type: 'error',\n error: error\n });\n }\n });\n _defineProperty(this, \"initializeSmartPhoneDisplay\", () => {\n const container = document.getElementById('listenerContainer');\n const allowMicrophoneElement = document.getElementById('allowMicrophone');\n const turnMessageElement = document.getElementById('turnMeToReadBelow');\n const placeSmartphoneMicrophone = this.phrases.RC_placeSmartphoneMicrophone['en-US'];\n const turnMeToReadBelow = this.phrases.RC_turnMeToReadBelow['en-US'];\n allowMicrophoneElement.innerText = placeSmartphoneMicrophone;\n allowMicrophoneElement.style.lineHeight = '1.2rem';\n allowMicrophoneElement.style.fontSize = '14px';\n turnMessageElement.innerText = turnMeToReadBelow;\n turnMessageElement.style.fontSize = '14px';\n turnMessageElement.style.position = 'fixed';\n turnMessageElement.style.top = '20px';\n turnMessageElement.style.left = '20px';\n turnMessageElement.style.lineHeight = '1.2rem';\n turnMessageElement.style.textAlign = 'left';\n\n // Show the html upsidedown and adjust layout\n const phrasesContainer = document.getElementById('phrases');\n phrasesContainer.classList.add('phrases');\n\n // Hide all elements except what's needed for calibration\n const html = document.querySelector('html');\n html.style.overflow = 'hidden';\n\n // Adjust the display container\n const display = document.getElementById('updateDisplay');\n display.classList.add('updateDisplay');\n display.style.position = 'absolute';\n display.style.top = '70%';\n display.style.left = '50%';\n display.style.transform = 'translate(-50%, -50%) rotate(180deg)';\n display.style.width = '100%';\n display.style.textAlign = 'left';\n display.style.padding = '15px';\n container.style.display = 'block';\n\n // event listener for id calibrationBeginButton\n const calibrationBeginButton = document.getElementById('calibrationBeginButton');\n console.log('Waiting for proceed button click');\n calibrationBeginButton.addEventListener('click', async () => {\n console.log('Proceed button clicked');\n this.handleCalibrationButtonClick();\n });\n });\n _defineProperty(this, \"handleCalibrationButtonClick\", async () => {\n const calibrationBeginButton = document.getElementById('calibrationBeginButton');\n const turnMessageElement = document.getElementById('turnMeToReadBelow');\n const allowMicrophoneElement = document.getElementById('allowMicrophone');\n const container = document.getElementById('listenerContainer');\n const targetElement = document.getElementById('display');\n\n // Clear unnecessary elements\n calibrationBeginButton.remove();\n turnMessageElement.remove();\n\n // Create a header container for fixed elements\n const headerContainer = document.createElement('div');\n headerContainer.id = 'headerContainer';\n headerContainer.style.position = 'fixed';\n headerContainer.style.bottom = '0';\n headerContainer.style.left = '0';\n headerContainer.style.width = '100%';\n headerContainer.style.background = 'white';\n headerContainer.style.padding = '10px';\n headerContainer.style.zIndex = '1000';\n headerContainer.style.transform = 'rotate(180deg)';\n container.appendChild(headerContainer);\n\n // Set title based on screen width\n const title = document.createElement('h1');\n const titleText = window.innerWidth >= 1366 ? this.phrases.RC_soundRecording['en-US'] : this.phrases.RC_soundRecordingSmallScreen['en-US'];\n\n // Split small screen title into lines if needed\n if (window.innerWidth < 1366 && titleText.includes('\\n')) {\n const lines = titleText.split('\\n');\n\n // Create container for title lines\n const titleContainer = document.createElement('div');\n titleContainer.style.display = 'flex';\n titleContainer.style.flexDirection = 'column';\n titleContainer.style.alignItems = 'left';\n titleContainer.style.lineHeight = '1.2';\n\n // Add each line\n lines.forEach(line => {\n const lineDiv = document.createElement('p');\n lineDiv.textContent = line;\n lineDiv.style.width = 'fit-content';\n titleContainer.appendChild(lineDiv);\n });\n title.appendChild(titleContainer);\n } else {\n title.textContent = titleText;\n title.style.lineHeight = '1.2';\n }\n title.style.margin = '0';\n title.style.whiteSpace = 'pre-line'; // Preserve line breaks\n headerContainer.appendChild(title);\n\n // Function to adjust font size to fill width\n const adjustFontSize = (element, maxWidth) => {\n let fontSize = 20; // Start with a reasonable minimum size\n element.style.fontSize = fontSize + 'px';\n // Increase font size until text fills width (minus margins)\n while (element.scrollWidth < maxWidth - 40 && fontSize < 200) {\n fontSize++;\n element.style.fontSize = fontSize + 'px';\n }\n\n // Step back one to ensure we don't overflow\n fontSize--;\n element.style.fontSize = fontSize + 'px';\n return fontSize;\n };\n\n // For small screen, ensure all lines use same font size\n if (window.innerWidth < 1366 && titleText.includes('\\n')) {\n const lines = title.querySelectorAll('p');\n let minFontSize = Infinity;\n\n // First pass: find the smallest font size that fits for any line\n lines.forEach(line => {\n const fontSize = adjustFontSize(line, window.innerWidth);\n minFontSize = Math.min(minFontSize, fontSize);\n });\n\n // Second pass: apply the smallest font size to all lines\n lines.forEach(line => {\n line.style.fontSize = minFontSize + 'px';\n });\n } else {\n // For single line title, just adjust to fill width\n adjustFontSize(title, window.innerWidth);\n }\n\n // Get the header height after text is added and sized\n const headerHeight = headerContainer.getBoundingClientRect().height;\n\n // Adjust the display container to start after header\n const display = document.getElementById('updateDisplay');\n display.classList.add('updateDisplay');\n display.style.position = 'fixed';\n display.style.bottom = \"\".concat(headerHeight, \"px\"); // Start after header\n display.style.left = '0';\n display.style.right = '0';\n display.style.top = '0';\n display.style.transform = 'rotate(180deg)';\n display.style.overflowY = 'auto';\n display.style.padding = '20px';\n display.style.background = 'white';\n\n // Position microphone instruction at the top (appears at bottom due to rotation)\n allowMicrophoneElement.innerText = '';\n allowMicrophoneElement.style.position = 'fixed';\n allowMicrophoneElement.style.top = '20px';\n allowMicrophoneElement.style.left = '50%';\n allowMicrophoneElement.style.transform = 'translateX(-50%) rotate(180deg)';\n allowMicrophoneElement.style.width = '90%';\n allowMicrophoneElement.style.textAlign = 'left';\n allowMicrophoneElement.style.zIndex = '1000';\n let lock = null;\n try {\n if ('wakeLock' in navigator) {\n lock = await navigator.wakeLock.request('screen');\n }\n } catch (err) {\n console.log(err);\n }\n this.setupMicrophone();\n\n // show target element\n targetElement.style.display = 'block';\n await this.listener.startCalibration();\n if (lock) {\n lock.release();\n }\n });\n _defineProperty(this, \"setupMicrophone\", async () => {\n const webAudioDeviceNames = {\n microphone: '',\n deviceID: ''\n };\n const externalMicList = ['UMIK', 'Airpods', 'Bluetooth'];\n try {\n const stream = await navigator.mediaDevices.getUserMedia({\n audio: true\n });\n if (stream) {\n const devices = await navigator.mediaDevices.enumerateDevices();\n const mics = devices.filter(device => device.kind === 'audioinput');\n mics.forEach(mic => {\n if (externalMicList.some(externalMic => mic.label.includes(externalMic))) {\n webAudioDeviceNames.microphone = mic.label;\n webAudioDeviceNames.deviceID = mic.deviceId;\n }\n });\n if (webAudioDeviceNames.microphone === '') {\n webAudioDeviceNames.microphone = mics[0].label;\n webAudioDeviceNames.deviceID = mics[0].deviceId;\n }\n }\n } catch (err) {\n console.log(err);\n }\n this.listener.setMicrophoneFromAPI(webAudioDeviceNames.microphone);\n this.listener.setMicrophoneDeviceId(webAudioDeviceNames.microphone);\n });\n _defineProperty(this, \"initializeDesktopMode\", async () => {\n await this.initializeListener();\n if (await this.waitForConnection()) {\n await this.setupDesktopUI();\n } else {\n console.error('Connection setup timed out after 30 seconds');\n }\n });\n _defineProperty(this, \"setupDesktopUI\", async () => {\n const container = document.getElementById('listenerContainer');\n const recordingInProgressElement = document.getElementById('recordingInProgress');\n const allowMicrophoneElement = document.getElementById('allowMicrophone');\n const recordingInProgress = this.phrases.RC_soundRecording['en-US'];\n const backToExperimentWindow = this.phrases.RC_backToExperimentWindow['en-US'];\n const allowMicrophone = this.phrases.RC_allowMicrophoneUse['en-US'];\n\n // remove the button\n const calibrationBeginButton = document.getElementById('calibrationBeginButton');\n calibrationBeginButton.remove();\n container.style.display = 'block';\n\n //update the display to be\n const display = document.getElementById('display');\n if (display) {\n display.style.textAlign = 'left';\n display.style.fontSize = '11px';\n }\n\n // set the text of the html elements\n recordingInProgressElement.innerText = recordingInProgress;\n allowMicrophoneElement.innerText = allowMicrophone;\n allowMicrophoneElement.style.marginBottom = '0.5rem';\n allowMicrophoneElement.style.fontSize = '17px';\n recordingInProgressElement.style.whiteSpace = 'nowrap';\n recordingInProgressElement.style.fontWeight = 'bold';\n\n // fit content\n recordingInProgressElement.style.width = 'fit-content';\n let fontSize = 100;\n recordingInProgressElement.style.fontSize = fontSize + 'px';\n while (recordingInProgressElement.scrollWidth > window.innerWidth * 0.9 && fontSize > 10) {\n fontSize--;\n recordingInProgressElement.style.fontSize = fontSize + 'px';\n }\n const message = document.getElementById('message');\n message.style.lineHeight = '2.5rem';\n const p = document.createElement('p');\n p.innerText = backToExperimentWindow;\n p.style.fontSize = '17px';\n message.appendChild(p);\n await this.listener.startCalibration();\n });\n this.phrases = _dist_example_i18n_js__WEBPACK_IMPORTED_MODULE_0__.phrases;\n this.name = 'SoundCalibration';\n this.listenerParameters = {\n targetElementId: 'display',\n microphoneFromAPI: '',\n microphoneDeviceId: ''\n };\n this.listener = null;\n this.connectionManager = null;\n }\n}\nasync function main() {\n const pp = new PhonePeer();\n if (window.phoneApp) {\n window.phoneApp.registerSubmodule(pp);\n } else {\n console.log('PhoneApp not found');\n }\n}\nmain().catch(err => console.error(err));\n\n//# sourceURL=webpack://speakerCalibrator/./src/listener-app/PhonePeer.js?");
|
|
39
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ PhonePeer: function() { return /* binding */ PhonePeer; }\n/* harmony export */ });\n/* harmony import */ var _dist_example_i18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../dist/example/i18n.js */ \"./dist/example/i18n.js\");\n/* harmony import */ var _peer_connection_listener_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../peer-connection/listener.js */ \"./src/peer-connection/listener.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\nclass PhonePeer {\n constructor() {\n var _this = this;\n _defineProperty(this, \"register\", manager => {\n this.connectionManager = manager;\n });\n _defineProperty(this, \"onMessage\", (data, manager) => {\n if (!data || !data.message) return;\n switch (data.message) {\n case 'connectionParams':\n console.log('connectionParams', data.payload);\n this.handleConnectionParams(data.payload);\n break;\n case 'phrases':\n console.log('phrases', data.payload);\n this.handlePhrases(data.payload);\n break;\n }\n });\n _defineProperty(this, \"handleConnectionParams\", async payload => {\n this.isSmartPhone = payload.sp;\n this.listenerParameters.speakerPeerId = payload.speakerPeerId;\n this.listenerParameters.hz = payload.hz;\n this.listenerParameters.bits = payload.bits;\n this.listenerParameters.lang = payload.lang;\n this.listenerParameters.deviceId = payload.deviceId;\n this.listenerParameters.sp = payload.sp;\n this.listenerParameters.microphoneDeviceId = payload.deviceId;\n this.handleStartCalibration();\n });\n _defineProperty(this, \"handlePhrases\", payload => {\n this.phrases = payload;\n });\n _defineProperty(this, \"createUI\", () => {\n const container = document.createElement('div');\n container.id = 'listenerContainer';\n container.className = 'container';\n container.innerHTML = \"\\n <p id=\\\"turnMeToReadBelow\\\"></p>\\n <div id=\\\"updateDisplay\\\">\\n <h1 id=\\\"recordingInProgress\\\"></h1>\\n <p id=\\\"allowMicrophone\\\"></p>\\n <button id=\\\"calibrationBeginButton\\\" class=\\\"btn btn-success\\\">Proceed</button>\\n </div>\\n <div id=\\\"display\\\"></div>\\n <div id=\\\"message\\\"></div>\\n <div id=\\\"phrases\\\"></div>\\n \";\n const target = document.getElementById('target');\n if (target) {\n console.log('target found');\n //clear the target\n target.innerHTML = '';\n target.appendChild(container);\n } else {\n console.log('target not found');\n //create a new target\n const newTarget = document.createElement('div');\n newTarget.id = 'target';\n document.body.appendChild(newTarget);\n newTarget.appendChild(container);\n }\n console.log('UI created');\n });\n _defineProperty(this, \"handleStartCalibration\", async () => {\n this.createUI();\n if (this.isSmartPhone) {\n await this.initializeSmartPhoneMode();\n } else {\n await this.initializeDesktopMode();\n }\n });\n _defineProperty(this, \"initializeListener\", async () => {\n this.listener = new _peer_connection_listener_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"](this.listenerParameters);\n this.listener.connectionManager = this.connectionManager;\n });\n _defineProperty(this, \"waitForConnection\", async function () {\n let timeout = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 30000;\n const startTime = Date.now();\n while (Date.now() - startTime < timeout) {\n if (_this.listener.connectionManager.peer.id !== null && _this.listener.connectionManager.conn !== null && _this.listener.connectionManager.connOpen) {\n console.log('Connection established successfully');\n return true;\n }\n console.log('Waiting for connection setup...');\n await new Promise(resolve => setTimeout(resolve, 100));\n }\n console.error('Connection setup timed out after 30 seconds');\n return false;\n });\n _defineProperty(this, \"initializeSmartPhoneMode\", async () => {\n // Hide target element\n const targetElement = document.getElementById('display');\n targetElement.style.display = 'none';\n\n // Initialize listener\n await this.initializeListener();\n if (await this.waitForConnection()) {\n await this.checkAndRequestMicrophonePermission();\n } else {\n const allowMicrophoneElement = document.getElementById('allowMicrophone');\n allowMicrophoneElement.innerText = this.phrases.RC_microphonePermissionDenied['en-US'];\n this.listener.sendPermissionStatus({\n type: 'error',\n error: 'Connection setup timed out after 30 seconds'\n });\n }\n });\n _defineProperty(this, \"checkAndRequestMicrophonePermission\", async () => {\n const container = document.getElementById('listenerContainer');\n const allowMicrophoneElement = document.getElementById('allowMicrophone');\n\n // Show permission request message\n allowMicrophoneElement.innerText = this.phrases.RC_microphonePermission['en-US'];\n container.style.display = 'block';\n\n // Function to request microphone access\n const requestMicAccess = async function () {\n let attempt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;\n try {\n await navigator.mediaDevices.getUserMedia({\n audio: true\n });\n // Permission granted, proceed to normal flow\n _this.initializeSmartPhoneDisplay();\n } catch (err) {\n if (err.name === 'NotAllowedError') {\n console.log('Permission explicitly denied');\n // Permission explicitly denied\n allowMicrophoneElement.innerText = _this.phrases.RC_microphonePermissionDenied['en-US'];\n // Send denied status and end study\n let error = JSON.stringify(err);\n _this.listener.sendPermissionStatus({\n type: 'denied',\n error: error\n });\n return;\n }\n\n // If 10 seconds passed, try again\n if (attempt < 3) {\n console.log('Retrying microphone access');\n // Limit retries\n setTimeout(() => requestMicAccess(attempt + 1), 10000);\n } else {\n console.log('All retries failed, treating as denied');\n // After all retries failed, treat as denied\n allowMicrophoneElement.innerText = _this.phrases.RC_microphonePermissionDenied['en-US'];\n let error = JSON.stringify(err);\n _this.listener.sendPermissionStatus({\n type: 'error',\n error: error\n });\n }\n }\n };\n try {\n await requestMicAccess();\n } catch (err) {\n console.error('Error requesting microphone permission:', err);\n allowMicrophoneElement.innerText = this.phrases.RC_microphonePermissionDenied['en-US'];\n let error = JSON.stringify(err);\n this.listener.sendPermissionStatus({\n type: 'error',\n error: error\n });\n }\n });\n _defineProperty(this, \"initializeSmartPhoneDisplay\", () => {\n const container = document.getElementById('listenerContainer');\n const allowMicrophoneElement = document.getElementById('allowMicrophone');\n const turnMessageElement = document.getElementById('turnMeToReadBelow');\n const placeSmartphoneMicrophone = this.phrases.RC_placeSmartphoneMicrophone['en-US'];\n const turnMeToReadBelow = this.phrases.RC_turnMeToReadBelow['en-US'];\n allowMicrophoneElement.innerText = placeSmartphoneMicrophone;\n allowMicrophoneElement.style.lineHeight = '1.2rem';\n allowMicrophoneElement.style.fontSize = '14px';\n turnMessageElement.innerText = turnMeToReadBelow;\n turnMessageElement.style.fontSize = '14px';\n turnMessageElement.style.position = 'fixed';\n turnMessageElement.style.top = '20px';\n turnMessageElement.style.left = '20px';\n turnMessageElement.style.lineHeight = '1.2rem';\n turnMessageElement.style.textAlign = 'left';\n\n // Show the html upsidedown and adjust layout\n const phrasesContainer = document.getElementById('phrases');\n phrasesContainer.classList.add('phrases');\n\n // Hide all elements except what's needed for calibration\n const html = document.querySelector('html');\n html.style.overflow = 'hidden';\n\n // Adjust the display container\n const display = document.getElementById('updateDisplay');\n display.classList.add('updateDisplay');\n display.style.position = 'absolute';\n display.style.top = '70%';\n display.style.left = '50%';\n display.style.transform = 'translate(-50%, -50%) rotate(180deg)';\n display.style.width = '100%';\n display.style.textAlign = 'left';\n display.style.padding = '15px';\n container.style.display = 'block';\n\n // event listener for id calibrationBeginButton\n const calibrationBeginButton = document.getElementById('calibrationBeginButton');\n console.log('Waiting for proceed button click');\n calibrationBeginButton.addEventListener('click', async () => {\n console.log('Proceed button clicked');\n this.handleCalibrationButtonClick();\n });\n });\n _defineProperty(this, \"handleCalibrationButtonClick\", async () => {\n const calibrationBeginButton = document.getElementById('calibrationBeginButton');\n const turnMessageElement = document.getElementById('turnMeToReadBelow');\n const allowMicrophoneElement = document.getElementById('allowMicrophone');\n const container = document.getElementById('listenerContainer');\n const targetElement = document.getElementById('display');\n\n // Clear unnecessary elements\n calibrationBeginButton.remove();\n turnMessageElement.remove();\n\n // Create a header container for fixed elements\n const headerContainer = document.createElement('div');\n headerContainer.id = 'headerContainer';\n headerContainer.style.position = 'fixed';\n headerContainer.style.bottom = '0';\n headerContainer.style.left = '0';\n headerContainer.style.width = '100%';\n headerContainer.style.background = 'white';\n headerContainer.style.padding = '10px';\n headerContainer.style.zIndex = '1000';\n headerContainer.style.transform = 'rotate(180deg)';\n container.appendChild(headerContainer);\n\n // Set title based on screen width\n const title = document.createElement('h1');\n const titleText = window.innerWidth >= 1366 ? this.phrases.RC_soundRecording['en-US'] : this.phrases.RC_soundRecordingSmallScreen['en-US'];\n\n // Split small screen title into lines if needed\n if (window.innerWidth < 1366 && titleText.includes('\\n')) {\n const lines = titleText.split('\\n');\n\n // Create container for title lines\n const titleContainer = document.createElement('div');\n titleContainer.style.display = 'flex';\n titleContainer.style.flexDirection = 'column';\n titleContainer.style.alignItems = 'left';\n titleContainer.style.lineHeight = '1.2';\n\n // Add each line\n lines.forEach(line => {\n const lineDiv = document.createElement('p');\n lineDiv.textContent = line;\n lineDiv.style.width = 'fit-content';\n titleContainer.appendChild(lineDiv);\n });\n title.appendChild(titleContainer);\n } else {\n title.textContent = titleText;\n title.style.lineHeight = '1.2';\n }\n title.style.margin = '0';\n title.style.whiteSpace = 'pre-line'; // Preserve line breaks\n headerContainer.appendChild(title);\n\n // Function to adjust font size to fill width\n const adjustFontSize = (element, maxWidth) => {\n let fontSize = 20; // Start with a reasonable minimum size\n element.style.fontSize = fontSize + 'px';\n // Increase font size until text fills width (minus margins)\n while (element.scrollWidth < maxWidth - 40 && fontSize < 200) {\n fontSize++;\n element.style.fontSize = fontSize + 'px';\n }\n\n // Step back one to ensure we don't overflow\n fontSize--;\n element.style.fontSize = fontSize + 'px';\n return fontSize;\n };\n\n // For small screen, ensure all lines use same font size\n if (window.innerWidth < 1366 && titleText.includes('\\n')) {\n const lines = title.querySelectorAll('p');\n let minFontSize = Infinity;\n\n // First pass: find the smallest font size that fits for any line\n lines.forEach(line => {\n const fontSize = adjustFontSize(line, window.innerWidth);\n minFontSize = Math.min(minFontSize, fontSize);\n });\n\n // Second pass: apply the smallest font size to all lines\n lines.forEach(line => {\n line.style.fontSize = minFontSize + 'px';\n });\n } else {\n // For single line title, just adjust to fill width\n adjustFontSize(title, window.innerWidth);\n }\n\n // Get the header height after text is added and sized\n const headerHeight = headerContainer.getBoundingClientRect().height;\n\n // Adjust the display container to start after header\n const display = document.getElementById('updateDisplay');\n display.classList.add('updateDisplay');\n display.style.position = 'fixed';\n display.style.bottom = \"\".concat(headerHeight, \"px\"); // Start after header\n display.style.left = '0';\n display.style.right = '0';\n display.style.top = '0';\n display.style.transform = 'rotate(180deg)';\n display.style.overflowY = 'auto';\n display.style.padding = '20px';\n display.style.background = 'white';\n\n // Position microphone instruction at the top (appears at bottom due to rotation)\n allowMicrophoneElement.innerText = '';\n allowMicrophoneElement.style.position = 'fixed';\n allowMicrophoneElement.style.top = '20px';\n allowMicrophoneElement.style.left = '50%';\n allowMicrophoneElement.style.transform = 'translateX(-50%) rotate(180deg)';\n allowMicrophoneElement.style.width = '90%';\n allowMicrophoneElement.style.textAlign = 'left';\n allowMicrophoneElement.style.zIndex = '1000';\n const webAudioDeviceNames = {\n microphone: '',\n deviceID: ''\n };\n const externalMicList = ['UMIK', 'Airpods', 'Bluetooth'];\n try {\n const stream = await navigator.mediaDevices.getUserMedia({\n audio: true\n });\n if (stream) {\n const devices = await navigator.mediaDevices.enumerateDevices();\n const mics = devices.filter(device => device.kind === 'audioinput');\n mics.forEach(mic => {\n if (externalMicList.some(externalMic => mic.label.includes(externalMic))) {\n webAudioDeviceNames.microphone = mic.label;\n webAudioDeviceNames.deviceID = mic.deviceId;\n }\n });\n if (webAudioDeviceNames.microphone === '') {\n webAudioDeviceNames.microphone = mics[0].label;\n webAudioDeviceNames.deviceID = mics[0].deviceId;\n }\n }\n } catch (err) {\n console.log(err);\n }\n let lock = null;\n try {\n if ('wakeLock' in navigator) {\n lock = await navigator.wakeLock.request('screen');\n }\n } catch (err) {\n console.log(err);\n }\n this.setupMicrophone();\n\n // show target element\n targetElement.style.display = 'block';\n await this.listener.startCalibration({\n microphoneFromAPI: webAudioDeviceNames.microphone,\n microphoneDeviceId: webAudioDeviceNames.deviceID\n });\n if (lock) {\n lock.release();\n }\n });\n _defineProperty(this, \"setupMicrophone\", async () => {\n const webAudioDeviceNames = {\n microphone: '',\n deviceID: ''\n };\n const externalMicList = ['UMIK', 'Airpods', 'Bluetooth'];\n try {\n const stream = await navigator.mediaDevices.getUserMedia({\n audio: true\n });\n if (stream) {\n const devices = await navigator.mediaDevices.enumerateDevices();\n const mics = devices.filter(device => device.kind === 'audioinput');\n mics.forEach(mic => {\n if (externalMicList.some(externalMic => mic.label.includes(externalMic))) {\n webAudioDeviceNames.microphone = mic.label;\n webAudioDeviceNames.deviceID = mic.deviceId;\n }\n });\n if (webAudioDeviceNames.microphone === '') {\n webAudioDeviceNames.microphone = mics[0].label;\n webAudioDeviceNames.deviceID = mics[0].deviceId;\n }\n }\n } catch (err) {\n console.log(err);\n }\n this.listener.setMicrophoneFromAPI(webAudioDeviceNames.microphone);\n this.listener.setMicrophoneDeviceId(webAudioDeviceNames.microphone);\n });\n _defineProperty(this, \"initializeDesktopMode\", async () => {\n await this.initializeListener();\n if (await this.waitForConnection()) {\n await this.setupDesktopUI();\n } else {\n console.error('Connection setup timed out after 30 seconds');\n }\n });\n _defineProperty(this, \"setupDesktopUI\", async () => {\n const container = document.getElementById('listenerContainer');\n const recordingInProgressElement = document.getElementById('recordingInProgress');\n const allowMicrophoneElement = document.getElementById('allowMicrophone');\n const recordingInProgress = this.phrases.RC_soundRecording['en-US'];\n const backToExperimentWindow = this.phrases.RC_backToExperimentWindow['en-US'];\n const allowMicrophone = this.phrases.RC_allowMicrophoneUse['en-US'];\n\n // remove the button\n const calibrationBeginButton = document.getElementById('calibrationBeginButton');\n calibrationBeginButton.remove();\n container.style.display = 'block';\n\n //update the display to be\n const display = document.getElementById('display');\n if (display) {\n display.style.textAlign = 'left';\n display.style.fontSize = '11px';\n }\n\n // set the text of the html elements\n recordingInProgressElement.innerText = recordingInProgress;\n allowMicrophoneElement.innerText = allowMicrophone;\n allowMicrophoneElement.style.marginBottom = '0.5rem';\n allowMicrophoneElement.style.fontSize = '17px';\n recordingInProgressElement.style.whiteSpace = 'nowrap';\n recordingInProgressElement.style.fontWeight = 'bold';\n\n // fit content\n recordingInProgressElement.style.width = 'fit-content';\n let fontSize = 100;\n recordingInProgressElement.style.fontSize = fontSize + 'px';\n while (recordingInProgressElement.scrollWidth > window.innerWidth * 0.9 && fontSize > 10) {\n fontSize--;\n recordingInProgressElement.style.fontSize = fontSize + 'px';\n }\n const message = document.getElementById('message');\n message.style.lineHeight = '2.5rem';\n const p = document.createElement('p');\n p.innerText = backToExperimentWindow;\n p.style.fontSize = '17px';\n message.appendChild(p);\n await this.listener.startCalibration();\n });\n this.phrases = _dist_example_i18n_js__WEBPACK_IMPORTED_MODULE_0__.phrases;\n this.name = 'SoundCalibration';\n this.listenerParameters = {\n targetElementId: 'display',\n microphoneFromAPI: '',\n microphoneDeviceId: ''\n };\n this.listener = null;\n this.connectionManager = null;\n }\n}\nasync function main() {\n const pp = new PhonePeer();\n if (window.phoneApp) {\n window.phoneApp.registerSubmodule(pp);\n } else {\n console.log('PhoneApp not found');\n }\n}\nmain().catch(err => console.error(err));\n\n//# sourceURL=webpack://speakerCalibrator/./src/listener-app/PhonePeer.js?");
|
|
40
40
|
|
|
41
41
|
/***/ }),
|
|
42
42
|
|
package/package.json
CHANGED
|
@@ -357,6 +357,28 @@ export class PhonePeer {
|
|
|
357
357
|
allowMicrophoneElement.style.textAlign = 'left';
|
|
358
358
|
allowMicrophoneElement.style.zIndex = '1000';
|
|
359
359
|
|
|
360
|
+
const webAudioDeviceNames = {microphone: '', deviceID: ''};
|
|
361
|
+
const externalMicList = ['UMIK', 'Airpods', 'Bluetooth'];
|
|
362
|
+
try {
|
|
363
|
+
const stream = await navigator.mediaDevices.getUserMedia({audio: true});
|
|
364
|
+
if (stream) {
|
|
365
|
+
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
366
|
+
const mics = devices.filter(device => device.kind === 'audioinput');
|
|
367
|
+
mics.forEach(mic => {
|
|
368
|
+
if (externalMicList.some(externalMic => mic.label.includes(externalMic))) {
|
|
369
|
+
webAudioDeviceNames.microphone = mic.label;
|
|
370
|
+
webAudioDeviceNames.deviceID = mic.deviceId;
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
if (webAudioDeviceNames.microphone === '') {
|
|
374
|
+
webAudioDeviceNames.microphone = mics[0].label;
|
|
375
|
+
webAudioDeviceNames.deviceID = mics[0].deviceId;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
} catch (err) {
|
|
379
|
+
console.log(err);
|
|
380
|
+
}
|
|
381
|
+
|
|
360
382
|
let lock = null;
|
|
361
383
|
try {
|
|
362
384
|
if ('wakeLock' in navigator) {
|
|
@@ -370,7 +392,10 @@ export class PhonePeer {
|
|
|
370
392
|
|
|
371
393
|
// show target element
|
|
372
394
|
targetElement.style.display = 'block';
|
|
373
|
-
await this.listener.startCalibration(
|
|
395
|
+
await this.listener.startCalibration({
|
|
396
|
+
microphoneFromAPI: webAudioDeviceNames.microphone,
|
|
397
|
+
microphoneDeviceId: webAudioDeviceNames.deviceID,
|
|
398
|
+
});
|
|
374
399
|
if (lock) {
|
|
375
400
|
lock.release();
|
|
376
401
|
}
|
|
@@ -209,6 +209,10 @@ class Speaker extends AudioPeer {
|
|
|
209
209
|
params.calibrateSoundSimulateMicrophoneTime,
|
|
210
210
|
params.calibrateSoundSimulateLoudspeaker,
|
|
211
211
|
params.calibrateSoundSimulateLoudspeakerTime,
|
|
212
|
+
params.calibrateSoundSimulateMicrophoneFrequencies,
|
|
213
|
+
params.calibrateSoundSimulateLoudspeakerFrequencies,
|
|
214
|
+
params.calibrateSoundSimulateMicrophoneType,
|
|
215
|
+
params.calibrateSoundSimulateLoudspeakerType,
|
|
212
216
|
params.isLoudspeakerCalibration
|
|
213
217
|
);
|
|
214
218
|
speaker.#removeUIElems();
|
|
@@ -347,6 +351,10 @@ class Speaker extends AudioPeer {
|
|
|
347
351
|
params.calibrateSoundSimulateMicrophoneTime,
|
|
348
352
|
params.calibrateSoundSimulateLoudspeaker,
|
|
349
353
|
params.calibrateSoundSimulateLoudspeakerTime,
|
|
354
|
+
params.calibrateSoundSimulateMicrophoneFrequencies,
|
|
355
|
+
params.calibrateSoundSimulateLoudspeakerFrequencies,
|
|
356
|
+
params.calibrateSoundSimulateMicrophoneType,
|
|
357
|
+
params.calibrateSoundSimulateLoudspeakerType,
|
|
350
358
|
params.isLoudspeakerCalibration
|
|
351
359
|
);
|
|
352
360
|
speaker.#removeUIElems();
|
|
@@ -939,6 +947,10 @@ class Speaker extends AudioPeer {
|
|
|
939
947
|
params.calibrateSoundSimulateMicrophoneTime,
|
|
940
948
|
params.calibrateSoundSimulateLoudspeaker,
|
|
941
949
|
params.calibrateSoundSimulateLoudspeakerTime,
|
|
950
|
+
params.calibrateSoundSimulateMicrophoneFrequencies,
|
|
951
|
+
params.calibrateSoundSimulateLoudspeakerFrequencies,
|
|
952
|
+
params.calibrateSoundSimulateMicrophoneType,
|
|
953
|
+
params.calibrateSoundSimulateLoudspeakerType,
|
|
942
954
|
params.isLoudspeakerCalibration
|
|
943
955
|
);
|
|
944
956
|
clearInterval(permissionCheckInterval);
|
|
@@ -126,9 +126,50 @@ class PythonServerAPI {
|
|
|
126
126
|
return res.data[task];
|
|
127
127
|
};
|
|
128
128
|
|
|
129
|
+
getImpulseResponseFromFrequencyResponse = async ({
|
|
130
|
+
frequencies,
|
|
131
|
+
gains,
|
|
132
|
+
sample_rate,
|
|
133
|
+
iir_length,
|
|
134
|
+
calibrateSoundIIRPhase,
|
|
135
|
+
totalDuration,
|
|
136
|
+
totalDuration1000Hz,
|
|
137
|
+
}) => {
|
|
138
|
+
const task = 'frequency-response-to-impulse-response';
|
|
139
|
+
let res = null;
|
|
140
|
+
|
|
141
|
+
const data = JSON.stringify({
|
|
142
|
+
task,
|
|
143
|
+
frequencies,
|
|
144
|
+
gains,
|
|
145
|
+
sample_rate,
|
|
146
|
+
iir_length,
|
|
147
|
+
calibrateSoundIIRPhase,
|
|
148
|
+
total_duration: totalDuration,
|
|
149
|
+
total_duration_1000hz: totalDuration1000Hz,
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
await axios({
|
|
153
|
+
method: 'post',
|
|
154
|
+
baseURL: PythonServerAPI.PYTHON_SERVER_URL,
|
|
155
|
+
url: `/task/${task}`,
|
|
156
|
+
headers: {
|
|
157
|
+
'Content-Type': 'application/json',
|
|
158
|
+
},
|
|
159
|
+
data,
|
|
160
|
+
})
|
|
161
|
+
.then(response => {
|
|
162
|
+
res = response;
|
|
163
|
+
})
|
|
164
|
+
.catch(error => {
|
|
165
|
+
throw error;
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
return res.data[task];
|
|
169
|
+
};
|
|
170
|
+
|
|
129
171
|
getFrequencyResponseFromImpulseResponse = async ({
|
|
130
|
-
|
|
131
|
-
impulseResponseLoudspeaker,
|
|
172
|
+
impulseResponse,
|
|
132
173
|
sampleRate,
|
|
133
174
|
timeArray,
|
|
134
175
|
totalDuration,
|
|
@@ -139,8 +180,7 @@ class PythonServerAPI {
|
|
|
139
180
|
|
|
140
181
|
const data = JSON.stringify({
|
|
141
182
|
task,
|
|
142
|
-
|
|
143
|
-
impulse_response_loudspeaker: impulseResponseLoudspeaker,
|
|
183
|
+
impulse_response: impulseResponse,
|
|
144
184
|
sample_rate: sampleRate,
|
|
145
185
|
time_array: timeArray,
|
|
146
186
|
total_duration: totalDuration,
|
|
@@ -1735,7 +1735,9 @@ class Combination extends AudioCalibrator {
|
|
|
1735
1735
|
}
|
|
1736
1736
|
}
|
|
1737
1737
|
this.clearAllFilteredRecordedSignals();
|
|
1738
|
-
console.log(
|
|
1738
|
+
console.log(
|
|
1739
|
+
'Obtaining unfiltered recording from #allHzUnfilteredRecordings to calculate spectrum'
|
|
1740
|
+
);
|
|
1739
1741
|
console.log('Obtaining filtered recording from #allHzFilteredRecordings to calculate spectrum');
|
|
1740
1742
|
let unconv_rec = recs[0];
|
|
1741
1743
|
let return_unconv_rec = unconv_rec;
|
|
@@ -3321,6 +3323,10 @@ class Combination extends AudioCalibrator {
|
|
|
3321
3323
|
calibrateSoundSimulateMicrophoneTime = null,
|
|
3322
3324
|
calibrateSoundSimulateLoudspeaker = null,
|
|
3323
3325
|
calibrateSoundSimulateLoudspeakerTime = null,
|
|
3326
|
+
calibrateSoundSimulateMicrophoneFrequencies = null,
|
|
3327
|
+
calibrateSoundSimulateLoudspeakerFrequencies = null,
|
|
3328
|
+
calibrateSoundSimulateMicrophoneType = 'impulseResponse',
|
|
3329
|
+
calibrateSoundSimulateLoudspeakerType = 'impulseResponse',
|
|
3324
3330
|
isLoudspeakerCalibration = true
|
|
3325
3331
|
) => {
|
|
3326
3332
|
this._calibrateSoundBurstDownsample = calibrateSoundBurstDownsample;
|
|
@@ -3375,19 +3381,7 @@ class Combination extends AudioCalibrator {
|
|
|
3375
3381
|
this._calibrateSoundBurstPreSec +
|
|
3376
3382
|
this._calibrateSoundBurstRepeats * this._calibrateSoundBurstSec +
|
|
3377
3383
|
this._calibrateSoundBurstPostSec;
|
|
3378
|
-
|
|
3379
|
-
const leftQuote = '\u201C'; // "
|
|
3380
|
-
const rightQuote = '\u201D'; // "
|
|
3381
|
-
this.webAudioDeviceNames.microphone = this.deviceInfo.microphoneFromAPI;
|
|
3382
|
-
const quotedWebAudioMic = leftQuote + this.webAudioDeviceNames.microphone + rightQuote;
|
|
3383
|
-
const combinedMicText = this.micModelName + ' ' + quotedWebAudioMic;
|
|
3384
|
-
webAudioDeviceNames.microphoneText = this.phrases.RC_nameMicrophone[this.language]
|
|
3385
|
-
.replace('"xxx"', combinedMicText)
|
|
3386
|
-
.replace('"XXX"', combinedMicText);
|
|
3387
|
-
}
|
|
3388
|
-
// this.webAudioDeviceNames.microphoneText = this.webAudioDeviceNames.microphoneText
|
|
3389
|
-
// .replace('xxx', this.webAudioDeviceNames.microphone)
|
|
3390
|
-
// .replace('XXX', this.webAudioDeviceNames.microphone);
|
|
3384
|
+
|
|
3391
3385
|
//feed calibration goal here
|
|
3392
3386
|
this._calibrateSoundCheck = _calibrateSoundCheck;
|
|
3393
3387
|
this.calibrateSound1000HzMaxSD_dB = calibrateSound1000HzMaxSD_dB;
|
|
@@ -3487,48 +3481,103 @@ class Combination extends AudioCalibrator {
|
|
|
3487
3481
|
}
|
|
3488
3482
|
} else {
|
|
3489
3483
|
//simulation.
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3484
|
+
if (calibrateSoundSimulateMicrophoneType === 'impulseResponse') {
|
|
3485
|
+
const frequencyResponse = await this.pyServerAPI.getFrequencyResponseFromImpulseResponse({
|
|
3486
|
+
impulseResponse: this.calibrateSoundSimulateMicrophone,
|
|
3487
|
+
sampleRate: this.sourceSamplingRate,
|
|
3488
|
+
timeArray: calibrateSoundSimulateMicrophoneTime,
|
|
3489
|
+
totalDuration: allHzDuation,
|
|
3490
|
+
totalDuration1000Hz: this.CALIBRATION_TONE_DURATION,
|
|
3491
|
+
});
|
|
3492
|
+
this.calibrateSoundSimulateMicrophone = frequencyResponse.impulse_response;
|
|
3493
|
+
this.calibrateSoundSimulateMicrophone1000Hz = frequencyResponse.impulse_response_1000hz;
|
|
3494
|
+
this.simulatedMicrophoneIR = {
|
|
3495
|
+
Freq: frequencyResponse.frequencies,
|
|
3496
|
+
Gain: frequencyResponse.gains,
|
|
3497
|
+
};
|
|
3498
|
+
if (isLoudspeakerCalibration) {
|
|
3499
|
+
this.componentIR = {
|
|
3500
|
+
Freq: frequencyResponse.frequencies,
|
|
3501
|
+
Gain: frequencyResponse.gains,
|
|
3502
|
+
};
|
|
3503
|
+
this.componentGainDBSPL = frequencyResponse.gain_at_1000hz;
|
|
3504
|
+
lCalib = this.componentGainDBSPL;
|
|
3505
|
+
}
|
|
3506
|
+
} else {
|
|
3507
|
+
const impulseResponse = await this.pyServerAPI.getImpulseResponseFromFrequencyResponse({
|
|
3508
|
+
frequencies: calibrateSoundSimulateMicrophoneFrequencies,
|
|
3509
|
+
gains: this.calibrateSoundSimulateMicrophone,
|
|
3510
|
+
sample_rate: this.sourceSamplingRate,
|
|
3511
|
+
iir_length: this.iirLength,
|
|
3512
|
+
calibrateSoundIIRPhase: this.calibrateSoundIIRPhase,
|
|
3513
|
+
totalDuration: allHzDuation,
|
|
3514
|
+
totalDuration1000Hz: this.CALIBRATION_TONE_DURATION,
|
|
3515
|
+
});
|
|
3516
|
+
if (isLoudspeakerCalibration) {
|
|
3517
|
+
this.componentIR = {
|
|
3518
|
+
Freq: impulseResponse.frequencies,
|
|
3519
|
+
Gain: impulseResponse.gains,
|
|
3520
|
+
};
|
|
3521
|
+
this.componentGainDBSPL = impulseResponse.gain_at_1000hz;
|
|
3522
|
+
lCalib = this.componentGainDBSPL;
|
|
3523
|
+
}
|
|
3524
|
+
this.simulatedMicrophoneIR = {
|
|
3525
|
+
Freq: impulseResponse.frequencies,
|
|
3526
|
+
Gain: impulseResponse.gains,
|
|
3527
|
+
};
|
|
3528
|
+
this.calibrateSoundSimulateMicrophone = impulseResponse.impulse_response;
|
|
3529
|
+
this.calibrateSoundSimulateMicrophone1000Hz = impulseResponse.impulse_response_1000hz;
|
|
3530
|
+
}
|
|
3531
|
+
|
|
3532
|
+
if (calibrateSoundSimulateLoudspeakerType === 'impulseResponse') {
|
|
3533
|
+
const frequencyResponse = await this.pyServerAPI.getFrequencyResponseFromImpulseResponse({
|
|
3534
|
+
impulseResponse: this.calibrateSoundSimulateLoudspeaker,
|
|
3535
|
+
sampleRate: this.sourceSamplingRate,
|
|
3536
|
+
timeArray: calibrateSoundSimulateLoudspeakerTime,
|
|
3537
|
+
totalDuration: allHzDuation,
|
|
3538
|
+
totalDuration1000Hz: this.CALIBRATION_TONE_DURATION,
|
|
3539
|
+
});
|
|
3540
|
+
|
|
3541
|
+
if (!isLoudspeakerCalibration) {
|
|
3542
|
+
this.componentIR = {
|
|
3543
|
+
Freq: frequencyResponse.frequencies,
|
|
3544
|
+
Gain: frequencyResponse.gains,
|
|
3545
|
+
};
|
|
3546
|
+
this.componentGainDBSPL = frequencyResponse.gain_at_1000hz;
|
|
3547
|
+
lCalib = this.componentGainDBSPL;
|
|
3548
|
+
}
|
|
3549
|
+
|
|
3550
|
+
this.calibrateSoundSimulateLoudspeaker = frequencyResponse.impulse_response;
|
|
3551
|
+
this.calibrateSoundSimulateLoudspeaker1000Hz = frequencyResponse.impulse_response_1000hz;
|
|
3552
|
+
this.simulatedLoudspeakerIR = {
|
|
3553
|
+
Freq: frequencyResponse.frequencies,
|
|
3554
|
+
Gain: frequencyResponse.gains,
|
|
3520
3555
|
};
|
|
3521
|
-
console.log('this.componentIR', this.componentIR);
|
|
3522
|
-
this.componentGainDBSPL = frequencyResponse.gain_at_1000hz_microphone;
|
|
3523
|
-
lCalib = this.componentGainDBSPL;
|
|
3524
3556
|
} else {
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3557
|
+
const impulseResponse = await this.pyServerAPI.getImpulseResponseFromFrequencyResponse({
|
|
3558
|
+
frequencies: calibrateSoundSimulateLoudspeakerFrequencies,
|
|
3559
|
+
gains: this.calibrateSoundSimulateLoudspeaker,
|
|
3560
|
+
sample_rate: this.sourceSamplingRate,
|
|
3561
|
+
iir_length: this.iirLength,
|
|
3562
|
+
calibrateSoundIIRPhase: this.calibrateSoundIIRPhase,
|
|
3563
|
+
totalDuration: allHzDuation,
|
|
3564
|
+
totalDuration1000Hz: this.CALIBRATION_TONE_DURATION,
|
|
3565
|
+
});
|
|
3566
|
+
|
|
3567
|
+
this.simulatedLoudspeakerIR = {
|
|
3568
|
+
Freq: impulseResponse.frequencies,
|
|
3569
|
+
Gain: impulseResponse.gains,
|
|
3529
3570
|
};
|
|
3530
|
-
|
|
3531
|
-
|
|
3571
|
+
if (!isLoudspeakerCalibration) {
|
|
3572
|
+
this.componentIR = {
|
|
3573
|
+
Freq: impulseResponse.frequencies,
|
|
3574
|
+
Gain: impulseResponse.gains,
|
|
3575
|
+
};
|
|
3576
|
+
this.componentGainDBSPL = impulseResponse.gain_at_1000hz;
|
|
3577
|
+
lCalib = this.componentGainDBSPL;
|
|
3578
|
+
}
|
|
3579
|
+
this.calibrateSoundSimulateLoudspeaker = impulseResponse.impulse_response;
|
|
3580
|
+
this.calibrateSoundSimulateLoudspeaker1000Hz = impulseResponse.impulse_response_1000hz;
|
|
3532
3581
|
}
|
|
3533
3582
|
}
|
|
3534
3583
|
|