speaker-calibration 2.2.204 → 2.2.206
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/package.json
CHANGED
|
@@ -26,16 +26,11 @@ class Listener extends AudioPeer {
|
|
|
26
26
|
|
|
27
27
|
const urlParameters = this.parseURLSearchParams();
|
|
28
28
|
this.calibrateSoundHz =
|
|
29
|
-
|
|
30
|
-
urlParameters.hz !== null && urlParameters.hz !== undefined
|
|
31
|
-
? urlParameters.hz
|
|
32
|
-
: 48000;
|
|
29
|
+
// previous calibrateSoundHz
|
|
30
|
+
urlParameters.hz !== null && urlParameters.hz !== undefined ? urlParameters.hz : 48000;
|
|
33
31
|
this.calibrateSoundSamplingDesiredBits =
|
|
34
|
-
|
|
35
|
-
urlParameters.bits !== null &&
|
|
36
|
-
urlParameters.bits !== undefined
|
|
37
|
-
? urlParameters.bits
|
|
38
|
-
: 24;
|
|
32
|
+
// previous calibrateSoundSamplingDesiredBits
|
|
33
|
+
urlParameters.bits !== null && urlParameters.bits !== undefined ? urlParameters.bits : 24;
|
|
39
34
|
this.speakerPeerId = urlParameters.speakerPeerId;
|
|
40
35
|
|
|
41
36
|
this.peer.on('open', this.onPeerOpen);
|
|
@@ -161,9 +156,9 @@ class Listener extends AudioPeer {
|
|
|
161
156
|
this.displayUpdate('Listener - sendFlags');
|
|
162
157
|
this.conn.send({
|
|
163
158
|
name: 'flags',
|
|
164
|
-
payload: flags
|
|
159
|
+
payload: flags,
|
|
165
160
|
});
|
|
166
|
-
}
|
|
161
|
+
};
|
|
167
162
|
|
|
168
163
|
getDeviceInfo = async () => {
|
|
169
164
|
try {
|
|
@@ -200,7 +195,9 @@ class Listener extends AudioPeer {
|
|
|
200
195
|
|
|
201
196
|
applyHQTrackConstraints = async stream => {
|
|
202
197
|
// Contraint the incoming audio to the sampling rate we want
|
|
203
|
-
stream.getAudioTracks().forEach(track => {
|
|
198
|
+
stream.getAudioTracks().forEach(track => {
|
|
199
|
+
console.log(track, track.enabled);
|
|
200
|
+
});
|
|
204
201
|
const track = stream.getAudioTracks()[0];
|
|
205
202
|
console.log(track);
|
|
206
203
|
const capabilities = track.getCapabilities();
|
|
@@ -242,47 +239,54 @@ class Listener extends AudioPeer {
|
|
|
242
239
|
return settings;
|
|
243
240
|
};
|
|
244
241
|
|
|
245
|
-
getMediaDevicesAudioContraints = () => {
|
|
242
|
+
getMediaDevicesAudioContraints = async () => {
|
|
246
243
|
const availableConstraints = navigator.mediaDevices.getSupportedConstraints();
|
|
247
244
|
|
|
248
|
-
this.displayUpdate(
|
|
249
|
-
`Listener MediaDevices Available Contraints - ${JSON.stringify(
|
|
250
|
-
availableConstraints,
|
|
251
|
-
undefined,
|
|
252
|
-
2
|
|
253
|
-
)}`
|
|
254
|
-
);
|
|
255
|
-
|
|
256
245
|
const contraints = {
|
|
257
246
|
// ...(availableConstraints.echoCancellation && availableConstraints.echoCancellation == true
|
|
258
247
|
// ? {echoCancellation: {exact: false}}
|
|
259
248
|
// : {}),
|
|
260
|
-
...(availableConstraints.sampleRate && availableConstraints.sampleRate == true
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
...(availableConstraints.sampleSize && availableConstraints.sampleSize == true
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
...(availableConstraints.channelCount && availableConstraints.channelCount == true
|
|
267
|
-
|
|
268
|
-
|
|
249
|
+
// ...(availableConstraints.sampleRate && availableConstraints.sampleRate == true
|
|
250
|
+
// ? {sampleRate: {ideal: this.calibrateSoundHz}}
|
|
251
|
+
// : {}),
|
|
252
|
+
// ...(availableConstraints.sampleSize && availableConstraints.sampleSize == true
|
|
253
|
+
// ? {sampleSize: {ideal: this.calibrateSoundSamplingDesiredBits}}
|
|
254
|
+
// : {}),
|
|
255
|
+
// ...(availableConstraints.channelCount && availableConstraints.channelCount == true
|
|
256
|
+
// ? {channelCount: {exact: 1}}
|
|
257
|
+
// : {}),
|
|
269
258
|
echoCancellation: false,
|
|
270
|
-
|
|
271
|
-
autoGainControl: false,
|
|
259
|
+
channelCount: 1,
|
|
272
260
|
};
|
|
273
261
|
|
|
274
262
|
if (this.microphoneDeviceId !== '') {
|
|
275
|
-
contraints.deviceId = {exact: this.microphoneDeviceId};
|
|
263
|
+
contraints.deviceId = {exact: await this.getDeviceIdByLabel(this.microphoneDeviceId)};
|
|
276
264
|
}
|
|
277
265
|
|
|
278
266
|
console.log(contraints);
|
|
279
267
|
|
|
280
|
-
this.displayUpdate(
|
|
281
|
-
`Listener MediaDevices Contraints - ${JSON.stringify(contraints, undefined, 2)}`
|
|
282
|
-
);
|
|
283
|
-
|
|
284
268
|
return contraints;
|
|
285
269
|
};
|
|
270
|
+
getDeviceIdByLabel = async targetLabel => {
|
|
271
|
+
try {
|
|
272
|
+
// Enumerate available media devices
|
|
273
|
+
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
274
|
+
|
|
275
|
+
// Find the device with the matching label
|
|
276
|
+
const matchingDevice = devices.find(
|
|
277
|
+
device => device.kind === 'audioinput' && device.label === targetLabel
|
|
278
|
+
);
|
|
279
|
+
|
|
280
|
+
if (matchingDevice) {
|
|
281
|
+
return matchingDevice.deviceId; // Return the deviceId if found
|
|
282
|
+
} else {
|
|
283
|
+
throw new Error(`No audio input device found with label: "${targetLabel}"`);
|
|
284
|
+
}
|
|
285
|
+
} catch (error) {
|
|
286
|
+
console.error('Error finding device ID:', error);
|
|
287
|
+
return null;
|
|
288
|
+
}
|
|
289
|
+
};
|
|
286
290
|
|
|
287
291
|
openAudioStream = async () => {
|
|
288
292
|
this.displayUpdate('Listener - openAudioStream');
|
|
@@ -295,28 +299,35 @@ class Listener extends AudioPeer {
|
|
|
295
299
|
});
|
|
296
300
|
return;
|
|
297
301
|
}
|
|
298
|
-
|
|
302
|
+
const constraints = await this.getMediaDevicesAudioContraints();
|
|
303
|
+
console.log('Constraints right before getUserMedia:', constraints);
|
|
299
304
|
navigator.mediaDevices
|
|
300
305
|
.getUserMedia({
|
|
301
|
-
|
|
302
|
-
audio: {echoCancellation: false, channelCount: 1},
|
|
306
|
+
audio: constraints,
|
|
303
307
|
video: false,
|
|
308
|
+
//audio: {echoCancellation: false, noiseSuppression: false, autoGainControl: false, deviceId: {exact: await this.getDeviceIdByLabel(this.microphoneDeviceId) }},
|
|
304
309
|
})
|
|
305
310
|
.then(stream => {
|
|
306
|
-
this.displayUpdate(
|
|
311
|
+
this.displayUpdate(
|
|
312
|
+
`Listener Track settings before applied constraints - ${JSON.stringify(
|
|
313
|
+
stream.getAudioTracks()[0].getSettings(),
|
|
314
|
+
undefined,
|
|
315
|
+
2
|
|
316
|
+
)}`
|
|
317
|
+
);
|
|
307
318
|
this.applyHQTrackConstraints(stream)
|
|
308
319
|
.then(settings => {
|
|
309
320
|
console.log(settings);
|
|
310
321
|
this.sendSamplingRate(settings.sampleRate);
|
|
311
322
|
let sampleSize = settings.sampleSize;
|
|
312
|
-
if (!sampleSize){
|
|
323
|
+
if (!sampleSize) {
|
|
313
324
|
sampleSize = this.calibrateSoundSamplingDesiredBits;
|
|
314
325
|
}
|
|
315
326
|
this.sendSampleSize(sampleSize);
|
|
316
327
|
this.sendFlags({
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
328
|
+
autoGainControl: settings.autoGainControl,
|
|
329
|
+
noiseSuppression: settings.noiseSuppression,
|
|
330
|
+
echoCancellation: settings.echoCancellation,
|
|
320
331
|
});
|
|
321
332
|
this.peer.call(this.speakerPeerId, stream); // one-way call
|
|
322
333
|
this.displayUpdate('Listener - openAudioStream');
|
|
@@ -330,6 +341,15 @@ class Listener extends AudioPeer {
|
|
|
330
341
|
})
|
|
331
342
|
.catch(err => {
|
|
332
343
|
console.error(err);
|
|
344
|
+
if (err.name === 'OverconstrainedError') {
|
|
345
|
+
const constraint = err.constraint;
|
|
346
|
+
const message = `The constraint "${constraint}" cannot be satisfied by the selected microphone. Please adjust your calibration settings or choose a different microphone.`;
|
|
347
|
+
|
|
348
|
+
this.displayUpdate(`Listener - OverconstrainedError: ${message}`);
|
|
349
|
+
console.error(message);
|
|
350
|
+
|
|
351
|
+
alert(`Overconstrained Error: ${message}`);
|
|
352
|
+
}
|
|
333
353
|
this.displayUpdate(
|
|
334
354
|
`Listener - Error in getUserMedia - ${JSON.stringify(err, undefined, 2)}`
|
|
335
355
|
);
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
CalibrationTimedOutError,
|
|
8
8
|
} from './peerErrors';
|
|
9
9
|
|
|
10
|
-
import {phrases} from '../../dist/example/i18n';
|
|
10
|
+
//import {phrases} from '../../dist/example/i18n';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* @class Handles the speaker's side of the connection. Responsible for initiating the connection,
|
|
@@ -41,7 +41,9 @@ class Speaker extends AudioPeer {
|
|
|
41
41
|
this.timeToCalibrate = params?.timeToCalibrate ?? 10;
|
|
42
42
|
this.isParticipant = params?.isParticipant ?? false;
|
|
43
43
|
this.isLoudspeakerCalibration = params?.isLoudspeakerCalibration ?? false;
|
|
44
|
+
this.deviceId = params?.micrpohoneIdFromWebAudioApi ?? '';
|
|
44
45
|
this.buttonsContainer = params?.buttonsContainer ?? document.createElement('div');
|
|
46
|
+
this.phrases = params?. phrases ?? {};
|
|
45
47
|
|
|
46
48
|
/* Set up callbacks that handle any events related to our peer object. */
|
|
47
49
|
}
|
|
@@ -207,6 +209,7 @@ class Speaker extends AudioPeer {
|
|
|
207
209
|
params.calibrateSoundSamplingDesiredBits,
|
|
208
210
|
params.language,
|
|
209
211
|
params.loudspeakerModelName,
|
|
212
|
+
params.phrases,
|
|
210
213
|
);
|
|
211
214
|
speaker.#removeUIElems();
|
|
212
215
|
resolve(speaker.result);
|
|
@@ -284,6 +287,7 @@ class Speaker extends AudioPeer {
|
|
|
284
287
|
hz: this.calibrateSoundHz,
|
|
285
288
|
bits: this.calibrateSoundSamplingDesiredBits,
|
|
286
289
|
lang: this.language,
|
|
290
|
+
deviceId: this.deviceId
|
|
287
291
|
};
|
|
288
292
|
const queryString = this.queryStringFromObject(queryStringParameters);
|
|
289
293
|
this.uri = this.siteUrl + queryString;
|
|
@@ -327,10 +331,10 @@ class Speaker extends AudioPeer {
|
|
|
327
331
|
})
|
|
328
332
|
.then(data => {
|
|
329
333
|
explanation.innerHTML = formatLineBreak(
|
|
330
|
-
phrases.RC_skipQR_ExplanationWithoutPreferNot[this.language]
|
|
334
|
+
this.phrases.RC_skipQR_ExplanationWithoutPreferNot[this.language]
|
|
331
335
|
.replace('xxx', `<b style="user-select: text">${data.shortURL}</b>`)
|
|
332
336
|
.replace('XXX', `<b style="user-select: text">${data.shortURL}</b>`),
|
|
333
|
-
phrases.RC_checkInternetConnection[this.language]
|
|
337
|
+
this.phrases.RC_checkInternetConnection[this.language]
|
|
334
338
|
);
|
|
335
339
|
const checkConnection = document.createElement('a');
|
|
336
340
|
checkConnection.id = 'check-connection';
|
|
@@ -340,7 +344,7 @@ class Speaker extends AudioPeer {
|
|
|
340
344
|
checkConnection.addEventListener('click', function (event) {
|
|
341
345
|
console.log('clicked');
|
|
342
346
|
event.preventDefault(); // Prevent the default link action
|
|
343
|
-
createAndShowPopup(lang);
|
|
347
|
+
createAndShowPopup(lang, this.phrases);
|
|
344
348
|
});
|
|
345
349
|
explanation.querySelector('a#check-connection').replaceWith(checkConnection);
|
|
346
350
|
})
|
|
@@ -386,7 +390,7 @@ class Speaker extends AudioPeer {
|
|
|
386
390
|
const proceedButton = document.createElement('button');
|
|
387
391
|
proceedButton.setAttribute('id', 'calibrationProceedButton');
|
|
388
392
|
proceedButton.setAttribute('class', 'btn btn-success');
|
|
389
|
-
proceedButton.innerHTML = phrases.T_proceed[this.language];
|
|
393
|
+
proceedButton.innerHTML = this.phrases.T_proceed[this.language];
|
|
390
394
|
proceedButton.onclick = () => {
|
|
391
395
|
// open the link in a new tab
|
|
392
396
|
window.open(this.uri, '_blank');
|
|
@@ -423,7 +427,7 @@ class Speaker extends AudioPeer {
|
|
|
423
427
|
instructionDisplay.style.whiteSpace = 'nowrap';
|
|
424
428
|
instructionDisplay.style.fontWeight = 'bold';
|
|
425
429
|
instructionDisplay.style.width = 'fit-content';
|
|
426
|
-
instructionDisplay.innerHTML = phrases.RC_soundRecording[this.language];
|
|
430
|
+
instructionDisplay.innerHTML = this.phrases.RC_soundRecording[this.language];
|
|
427
431
|
let fontSize = 100;
|
|
428
432
|
instructionDisplay.style.fontSize = fontSize + 'px';
|
|
429
433
|
while (instructionDisplay.scrollWidth > background.scrollWidth * 0.9 && fontSize > 10) {
|
|
@@ -442,7 +446,7 @@ class Speaker extends AudioPeer {
|
|
|
442
446
|
|
|
443
447
|
const timeToCalibrateDisplay = document.getElementById(this.timeToCalibrateDisplay);
|
|
444
448
|
if (timeToCalibrateDisplay) {
|
|
445
|
-
const timeToCalibrateText = phrases.RC_howLongToCalibrate[this.language];
|
|
449
|
+
const timeToCalibrateText = this.phrases.RC_howLongToCalibrate[this.language];
|
|
446
450
|
timeToCalibrateDisplay.innerHTML = timeToCalibrateText.replace('111', this.timeToCalibrate);
|
|
447
451
|
timeToCalibrateDisplay.style.fontWeight = 'normal';
|
|
448
452
|
timeToCalibrateDisplay.style.fontSize = '1rem';
|
|
@@ -469,13 +473,13 @@ class Speaker extends AudioPeer {
|
|
|
469
473
|
} else if (this.isSmartPhone) {
|
|
470
474
|
titleDisplay.innerHTML = titleDisplay.innerHTML.replace('6', '7');
|
|
471
475
|
} else {
|
|
472
|
-
titleDisplay.innerHTML = titleDisplay.innerHTML.replace('
|
|
476
|
+
titleDisplay.innerHTML = titleDisplay.innerHTML.replace('4', '5');
|
|
473
477
|
}
|
|
474
478
|
} else {
|
|
475
479
|
if (this.isSmartPhone) {
|
|
476
480
|
titleDisplay.innerHTML = titleDisplay.innerHTML.replace('5', '6');
|
|
477
481
|
} else {
|
|
478
|
-
titleDisplay.innerHTML = titleDisplay.innerHTML.replace('
|
|
482
|
+
titleDisplay.innerHTML = titleDisplay.innerHTML.replace('3', '4');
|
|
479
483
|
}
|
|
480
484
|
}
|
|
481
485
|
}
|
|
@@ -714,6 +718,7 @@ class Speaker extends AudioPeer {
|
|
|
714
718
|
params.calibrateSoundSamplingDesiredBits,
|
|
715
719
|
params.language,
|
|
716
720
|
params.loudspeakerModelName,
|
|
721
|
+
params.phrases,
|
|
717
722
|
);
|
|
718
723
|
this.#removeUIElems();
|
|
719
724
|
resolve(result);
|
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
where,
|
|
33
33
|
Timestamp,
|
|
34
34
|
} from 'firebase/firestore';
|
|
35
|
-
import { phrases } from '../../../dist/example/i18n';
|
|
35
|
+
//import { phrases } from '../../../dist/example/i18n';
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
38
|
*
|
|
@@ -312,7 +312,7 @@ class Combination extends AudioCalibrator {
|
|
|
312
312
|
let systemSD = '';
|
|
313
313
|
let flags = '';
|
|
314
314
|
const reportWebAudioNames = `<strong>${this.webAudioDeviceNames.loudspeakerText} </strong> <strong>${this.webAudioDeviceNames.microphoneText} </strong>`;
|
|
315
|
-
const samplingParamText =
|
|
315
|
+
const samplingParamText = this.phrases.RC_SamplingHzBits[this.language].replace('111', this.sourceSamplingRate).replace('222',this.sinkSamplingRate).replace('333', this.calibrateSoundSamplingDesiredBits);
|
|
316
316
|
const reportParameters = `${samplingParamText}`;
|
|
317
317
|
if (this.flags) {
|
|
318
318
|
flags = `<br> autoGainControl: ${this.flags.autoGainControl};
|
|
@@ -2735,6 +2735,7 @@ class Combination extends AudioCalibrator {
|
|
|
2735
2735
|
calibrateSoundSamplingDesiredBits = 24,
|
|
2736
2736
|
language,
|
|
2737
2737
|
loudspeakerModelName='',
|
|
2738
|
+
phrases,
|
|
2738
2739
|
|
|
2739
2740
|
) => {
|
|
2740
2741
|
this._calibrateSoundBurstPreSec = _calibrateSoundBurstPreSec;
|
|
@@ -2772,7 +2773,17 @@ class Combination extends AudioCalibrator {
|
|
|
2772
2773
|
this._calibrateSoundBurstScalarDB = _calibrateSoundBurstScalarDB;
|
|
2773
2774
|
this.webAudioDeviceNames = webAudioDeviceNames;
|
|
2774
2775
|
this.calibrateSoundSamplingDesiredBits = calibrateSoundSamplingDesiredBits;
|
|
2775
|
-
|
|
2776
|
+
this.phrases = phrases;
|
|
2777
|
+
if (isSmartPhone) {
|
|
2778
|
+
const leftQuote = "\u201C"; // “
|
|
2779
|
+
const rightQuote = "\u201D"; // ”
|
|
2780
|
+
this.webAudioDeviceNames.microphone = this.deviceInfo.microphoneFromAPI;
|
|
2781
|
+
const quotedWebAudioMic = leftQuote + this.webAudioDeviceNames.microphone + rightQuote;
|
|
2782
|
+
const combinedMicText = this.micModelName + " " + quotedWebAudioMic;
|
|
2783
|
+
webAudioDeviceNames.microphoneText = this.phrases.RC_nameMicrophone[this.language]
|
|
2784
|
+
.replace("“xxx”", combinedMicText)
|
|
2785
|
+
.replace("“XXX”", combinedMicText);
|
|
2786
|
+
}
|
|
2776
2787
|
// this.webAudioDeviceNames.microphoneText = this.webAudioDeviceNames.microphoneText
|
|
2777
2788
|
// .replace('xxx', this.webAudioDeviceNames.microphone)
|
|
2778
2789
|
// .replace('XXX', this.webAudioDeviceNames.microphone);
|
package/src/utils.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Swal from "sweetalert2";
|
|
2
|
-
import {phrases} from '../dist/example/i18n.js';
|
|
2
|
+
//import {phrases} from '../dist/example/i18n.js';
|
|
3
3
|
/** .
|
|
4
4
|
* .
|
|
5
5
|
* .
|
|
@@ -147,7 +147,7 @@ export const formatLineBreak =(inputStr,checkInternetConnection) => {
|
|
|
147
147
|
|
|
148
148
|
|
|
149
149
|
|
|
150
|
-
export const createAndShowPopup = (lang) => {
|
|
150
|
+
export const createAndShowPopup = (lang, phrases) => {
|
|
151
151
|
console.log(`
|
|
152
152
|
<div style="text-align: left;">
|
|
153
153
|
${convertAsterisksToList(phrases.RC_NeedInternetConnectedPhone[lang].replace(/\n/g, '<br>'))}
|