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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "speaker-calibration",
3
- "version": "2.2.250",
3
+ "version": "2.2.252",
4
4
  "description": "Speaker calibration library for auditory testing",
5
5
  "main": "dist/main.js",
6
6
  "directories": {
@@ -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
- impulseResponseMicrophone,
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
- impulse_response_microphone: impulseResponseMicrophone,
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('Obtaining unfiltered recording from #allHzUnfilteredRecordings to calculate spectrum');
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
- if (isSmartPhone && !simulationEnabled) {
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
- const frequencyResponse = await this.pyServerAPI.getFrequencyResponseFromImpulseResponse({
3491
- impulseResponseMicrophone: this.calibrateSoundSimulateMicrophone,
3492
- impulseResponseLoudspeaker: this.calibrateSoundSimulateLoudspeaker,
3493
- sampleRate: this.sourceSamplingRate,
3494
- timeArray: calibrateSoundSimulateMicrophoneTime,
3495
- totalDuration: allHzDuation,
3496
- totalDuration1000Hz: this.CALIBRATION_TONE_DURATION,
3497
- });
3498
- this.calibrateSoundSimulateMicrophone = frequencyResponse.impulse_response_microphone;
3499
- this.calibrateSoundSimulateLoudspeaker = frequencyResponse.impulse_response_loudspeaker;
3500
- this.calibrateSoundSimulateMicrophone1000Hz =
3501
- frequencyResponse.impulse_response_1000hz_microphone;
3502
- this.calibrateSoundSimulateLoudspeaker1000Hz =
3503
- frequencyResponse.impulse_response_1000hz_loudspeaker;
3504
- this.simulatedLoudspeakerIR = {
3505
- Freq: frequencyResponse.frequencies_loudspeaker,
3506
- Gain: frequencyResponse.gains_loudspeaker,
3507
- };
3508
- this.simulatedMicrophoneIR = {
3509
- Freq: frequencyResponse.frequencies_microphone,
3510
- Gain: frequencyResponse.gains_microphone,
3511
- };
3512
- console.log('simulatedMicrophoneIR', this.simulatedMicrophoneIR);
3513
- console.log('simulatedLoudspeakerIR', this.simulatedLoudspeakerIR);
3514
-
3515
- if (isLoudspeakerCalibration) {
3516
- //define this.componentIR, this.componentGainDBSPL
3517
- this.componentIR = {
3518
- Freq: frequencyResponse.frequencies_microphone,
3519
- Gain: frequencyResponse.gains_microphone,
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
- //define this.componentIR, this.componentGainDBSPL
3526
- this.componentIR = {
3527
- Freq: frequencyResponse.frequencies_loudspeaker,
3528
- Gain: frequencyResponse.gains_loudspeaker,
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
- this.componentGainDBSPL = frequencyResponse.gain_at_1000hz_loudspeaker;
3531
- lCalib = this.componentGainDBSPL;
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