speaker-calibration 2.2.10 → 2.2.12

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "speaker-calibration",
3
- "version": "2.2.10",
3
+ "version": "2.2.12",
4
4
  "description": "Speaker calibration library for auditory testing",
5
5
  "main": "dist/main.js",
6
6
  "directories": {
@@ -21,6 +21,10 @@ class Listener extends AudioPeer {
21
21
  this.receiverPeerId = null;
22
22
 
23
23
  const urlParameters = this.parseURLSearchParams();
24
+ this.calibrateSoundHz =
25
+ urlParameters.calibrateSoundHz !== null && urlParameters.calibrateSoundHz !== undefined
26
+ ? urlParameters.calibrateSoundHz
27
+ : 48000;
24
28
  this.speakerPeerId = urlParameters.speakerPeerId;
25
29
 
26
30
  this.peer.on('open', this.onPeerOpen);
@@ -99,7 +103,7 @@ class Listener extends AudioPeer {
99
103
  this.displayUpdate('Created connection');
100
104
  this.conn.on('open', async () => {
101
105
  this.displayUpdate('Listener - conn open');
102
- // await this.getDeviceType();
106
+ await this.getDeviceInfo();
103
107
  // this.sendSamplingRate();
104
108
  await this.openAudioStream();
105
109
  });
@@ -134,27 +138,35 @@ class Listener extends AudioPeer {
134
138
  });
135
139
  };
136
140
 
137
- getDeviceType = async () => {
138
- const deviceType = deviceAPI.deviceType;
139
- var deviceName = deviceAPI.deviceName;
140
-
141
- // if deviceName is a comma separated string, only send the first part
142
- if (deviceName.includes(',')) {
143
- deviceName = deviceName.split(',')[0];
141
+ getDeviceInfo = async () => {
142
+ try {
143
+ const deviceInfo = {};
144
+ fod.complete(function (data) {
145
+ deviceInfo['IsMobile'] = data.device['ismobile'];
146
+ deviceInfo['HardwareName'] = data.device['hardwarename'];
147
+ deviceInfo['HardwareFamily'] = data.device['hardwarefamily'];
148
+ deviceInfo['HardwareModel'] = data.device['hardwaremodel'];
149
+ deviceInfo['OEM'] = data.device['oem'];
150
+ deviceInfo['HardwareModelVariants'] = data.device['hardwaremodelvariants'];
151
+ deviceInfo['DeviceId'] = data.device['deviceid'];
152
+ deviceInfo['PlatformName'] = data.device['platformname'];
153
+ deviceInfo['PlatformVersion'] = data.device['platformversion'];
154
+ deviceInfo['DeviceType'] = data.device['devicetype'];
155
+ });
156
+ this.conn.send({
157
+ name: 'deviceInfo',
158
+ payload: deviceInfo,
159
+ });
160
+ return deviceInfo;
161
+ } catch (error) {
162
+ console.error('Error fetching or executing script:', error.message);
163
+ return null;
144
164
  }
145
-
146
- this.conn.send({
147
- name: 'deviceType',
148
- payload: deviceType,
149
- });
150
- this.conn.send({
151
- name: 'deviceName',
152
- payload: deviceName,
153
- });
154
165
  };
155
166
 
156
167
  applyHQTrackConstraints = async stream => {
157
168
  // Contraint the incoming audio to the sampling rate we want
169
+
158
170
  const track = stream.getAudioTracks()[0];
159
171
  const capabilities = track.getCapabilities();
160
172
 
@@ -169,7 +181,7 @@ class Listener extends AudioPeer {
169
181
  }
170
182
 
171
183
  if (capabilities.sampleRate) {
172
- constraints.sampleRate = 48000;
184
+ constraints.sampleRate = this.calibrateSoundHz;
173
185
  }
174
186
 
175
187
  if (capabilities.sampleSize) {
@@ -211,7 +223,7 @@ class Listener extends AudioPeer {
211
223
  // ? {echoCancellation: {exact: false}}
212
224
  // : {}),
213
225
  ...(availableConstraints.sampleRate && availableConstraints.sampleRate == true
214
- ? {sampleRate: {ideal: 48000}}
226
+ ? {sampleRate: {ideal: this.calibrateSoundHz}}
215
227
  : {}),
216
228
  ...(availableConstraints.sampleSize && availableConstraints.sampleSize == true
217
229
  ? {sampleSize: {ideal: 24}}
@@ -219,9 +231,9 @@ class Listener extends AudioPeer {
219
231
  ...(availableConstraints.channelCount && availableConstraints.channelCount == true
220
232
  ? {channelCount: {exact: 1}}
221
233
  : {}),
222
- echoCancellation: false,
223
- noiseSuppression: false,
224
- autoGainControl: false
234
+ echoCancellation: false,
235
+ noiseSuppression: false,
236
+ autoGainControl: false,
225
237
  };
226
238
 
227
239
  console.log(contraints);
@@ -32,6 +32,7 @@ class Speaker extends AudioPeer {
32
32
  this.result = null;
33
33
  this.debug = params?.debug ?? false;
34
34
  this.isSmartPhone = params?.isSmartPhone ?? false;
35
+ this.calibrateSoundHz = params?.calibrateSoundHz ?? 48000;
35
36
  this.instructionDisplayId = params?.instructionDisplayId ?? '';
36
37
  this.titleDisplayId = params?.titleDisplayId ?? '';
37
38
  this.timeToCalibrate = params?.timeToCalibrate ?? 10;
@@ -99,7 +100,11 @@ class Speaker extends AudioPeer {
99
100
  params.calibrateSoundBurstRepeats,
100
101
  params.calibrateSoundBurstSec,
101
102
  params.calibrateSoundBurstsWarmup,
102
- params.calibrateSoundHz
103
+ params.calibrateSoundHz,
104
+ params.micManufacturer,
105
+ params.micSerialNumber,
106
+ params.micModelNumber,
107
+ params.micModelName
103
108
  );
104
109
  speaker.#removeUIElems();
105
110
  resolve(speaker.result);
@@ -173,6 +178,7 @@ class Speaker extends AudioPeer {
173
178
  const queryStringParameters = {
174
179
  speakerPeerId: this.peer.id,
175
180
  isSmartPhone: this.isSmartPhone,
181
+ calibrateSoundHz: this.calibrateSoundHz,
176
182
  };
177
183
  const queryString = this.queryStringFromObject(queryStringParameters);
178
184
  const uri = this.siteUrl + queryString;
@@ -379,6 +385,8 @@ class Speaker extends AudioPeer {
379
385
  case 'deviceName':
380
386
  this.ac.setDeviceName(data.payload);
381
387
  break;
388
+ case 'deviceInfo':
389
+ this.ac.setDeviceInfo(data.payload);
382
390
  case UnsupportedDeviceError.name:
383
391
  case MissingSpeakerIdError.name:
384
392
  throw data.payload;
@@ -141,6 +141,8 @@ class Combination extends AudioCalibrator {
141
141
 
142
142
  deviceName = null;
143
143
 
144
+ deviceInfo = null;
145
+
144
146
  desired_time_per_mls = 0;
145
147
 
146
148
  num_mls_to_skip = 0;
@@ -153,6 +155,8 @@ class Combination extends AudioCalibrator {
153
155
 
154
156
  sourceNode;
155
157
 
158
+ autocorrelations = [];
159
+
156
160
  /**generate string template that gets reevaluated as variable increases */
157
161
  generateTemplate = () => {
158
162
  if (this.percent_complete > 100) {
@@ -176,6 +180,10 @@ class Combination extends AudioCalibrator {
176
180
  this.deviceName = deviceName;
177
181
  };
178
182
 
183
+ setDeviceInfo = deviceInfo => {
184
+ this.deviceInfo = deviceInfo;
185
+ };
186
+
179
187
  /** .
180
188
  * .
181
189
  * .
@@ -319,7 +327,8 @@ class Combination extends AudioCalibrator {
319
327
  this.emit('update', {
320
328
  message: this.status,
321
329
  });
322
- return res;
330
+ this.autocorrelations.push(res['autocorrelation']);
331
+ return res['ir'];
323
332
  }
324
333
  })
325
334
  .catch(err => {
@@ -347,16 +356,16 @@ class Combination extends AudioCalibrator {
347
356
  message: this.status,
348
357
  });
349
358
  let time_to_wait = 0;
350
- if (this.mode === 'unfiltered'){
359
+ if (this.mode === 'unfiltered') {
351
360
  time_to_wait = (this.#mls.length / this.sourceSamplingRate) * this.numMLSPerCapture;
352
- }else if (this.mode === 'filtered'){
361
+ } else if (this.mode === 'filtered') {
353
362
  time_to_wait =
354
- (this.#currentConvolution.length / this.sourceSamplingRate) * this.numMLSPerCapture;
355
- }else{
356
- throw new Error("Mode broke in awaitDesiredMLSLength");
363
+ (this.#currentConvolution.length / this.sourceSamplingRate) * this.numMLSPerCapture;
364
+ } else {
365
+ throw new Error('Mode broke in awaitDesiredMLSLength');
357
366
  }
358
-
359
- await sleep(time_to_wait*1.1);
367
+
368
+ await sleep(time_to_wait * 1.1);
360
369
  };
361
370
 
362
371
  /** .
@@ -377,12 +386,12 @@ class Combination extends AudioCalibrator {
377
386
  });
378
387
  let number_of_bursts_to_skip = this.num_mls_to_skip;
379
388
  let time_to_sleep = 0;
380
- if (this.mode === 'unfiltered'){
389
+ if (this.mode === 'unfiltered') {
381
390
  time_to_sleep = this.#mls.length / this.sourceSamplingRate;
382
- }else if (this.mode === 'filtered'){
391
+ } else if (this.mode === 'filtered') {
383
392
  time_to_sleep = this.#currentConvolution.length / this.sourceSamplingRate;
384
- }else{
385
- throw new Error("Mode broke in awaitSignalOnset");
393
+ } else {
394
+ throw new Error('Mode broke in awaitSignalOnset');
386
395
  }
387
396
  await sleep(time_to_sleep);
388
397
  };
@@ -455,10 +464,10 @@ class Combination extends AudioCalibrator {
455
464
  #createCalibrationNodeFromBuffer = dataBuffer => {
456
465
  console.log('databuffer');
457
466
  console.log(dataBuffer);
458
- if (!this.sourceAudioContext){
467
+ if (!this.sourceAudioContext) {
459
468
  this.makeNewSourceAudioContext();
460
469
  }
461
-
470
+
462
471
  const buffer = this.sourceAudioContext.createBuffer(
463
472
  1, // number of channels
464
473
  dataBuffer.length,
@@ -474,10 +483,8 @@ class Combination extends AudioCalibrator {
474
483
  } catch (error) {
475
484
  console.error(error);
476
485
  }
477
-
486
+
478
487
  this.sourceNode = this.sourceAudioContext.createBufferSource();
479
-
480
-
481
488
 
482
489
  this.sourceNode.buffer = buffer;
483
490
  this.sourceNode.loop = true;
@@ -568,23 +575,23 @@ class Combination extends AudioCalibrator {
568
575
  * @example
569
576
  */
570
577
  #playCalibrationAudio = () => {
571
- if (this.mode === 'unfiltered'){
578
+ if (this.mode === 'unfiltered') {
572
579
  this.calibrationNodes[0].start(0);
573
580
  this.#mls = this.calibrationNodes[0].buffer.getChannelData(0);
574
581
  console.log('play calibration audio ' + this.stepNum);
575
582
  this.status =
576
- `All Hz Calibration: playing the calibration tone...`.toString() +
577
- this.generateTemplate().toString();
583
+ `All Hz Calibration: playing the calibration tone...`.toString() +
584
+ this.generateTemplate().toString();
578
585
  this.emit('update', {message: this.status});
579
- } else if (this.mode === 'filtered'){
586
+ } else if (this.mode === 'filtered') {
580
587
  this.calibrationNodes[0].start(0);
581
588
  console.log('play convolved audio ' + this.stepNum);
582
589
  this.status =
583
590
  `All Hz Calibration: playing the convolved calibration tone...`.toString() +
584
- this.generateTemplate().toString();
591
+ this.generateTemplate().toString();
585
592
  this.emit('update', {message: this.status});
586
- } else{
587
- throw new Error("Mode is incorrect");
593
+ } else {
594
+ throw new Error('Mode is incorrect');
588
595
  }
589
596
  this.stepNum += 1;
590
597
  console.log('sink sampling rate');
@@ -593,7 +600,6 @@ class Combination extends AudioCalibrator {
593
600
  console.log(this.sourceSamplingRate);
594
601
  };
595
602
 
596
-
597
603
  /** .
598
604
  * .
599
605
  * .
@@ -602,7 +608,6 @@ class Combination extends AudioCalibrator {
602
608
  * @example
603
609
  */
604
610
  #stopCalibrationAudio = () => {
605
-
606
611
  this.calibrationNodes[0].stop(0);
607
612
  this.calibrationNodes = [];
608
613
  this.sourceNode.disconnect();
@@ -628,7 +633,7 @@ class Combination extends AudioCalibrator {
628
633
  this.#awaitDesiredMLSLength, // during record
629
634
  this.#afterMLSwIIRRecord, // after record
630
635
  this.mode
631
- )
636
+ );
632
637
  };
633
638
 
634
639
  /**
@@ -641,11 +646,9 @@ class Combination extends AudioCalibrator {
641
646
  * @example
642
647
  */
643
648
  startCalibrationImpulseResponse = async stream => {
644
-
645
649
  let desired_time = this.desired_time_per_mls;
646
650
 
647
- console.log("MLS sequence should be of length: " + (this.sourceSamplingRate * desired_time));
648
-
651
+ console.log('MLS sequence should be of length: ' + this.sourceSamplingRate * desired_time);
649
652
 
650
653
  length = this.sourceSamplingRate * desired_time;
651
654
  //get mls here
@@ -669,8 +672,7 @@ class Combination extends AudioCalibrator {
669
672
  this.#afterMLSRecord, // after record
670
673
  this.mode
671
674
  ),
672
-
673
- this.#stopCalibrationAudio();
675
+ this.#stopCalibrationAudio();
674
676
 
675
677
  // at this stage we've captured all the required signals,
676
678
  // and have received IRs for each one
@@ -684,7 +686,7 @@ class Combination extends AudioCalibrator {
684
686
  if (this._calibrateSoundCheck != 'none') {
685
687
  if (this._calibrateSoundCheck != 'system') {
686
688
  this.#currentConvolution = this.componentConvolution;
687
- }else{
689
+ } else {
688
690
  this.#currentConvolution = this.systemConvolution;
689
691
  }
690
692
  await this.playMLSwithIIR(stream, this.invertedImpulseResponse);
@@ -773,6 +775,9 @@ class Combination extends AudioCalibrator {
773
775
  saveToCSV(this.systemConvolution, 'python_system_convolution_mls_iir.csv');
774
776
  saveToCSV(this.componentInvertedImpulseResponse, 'componentIIR.csv');
775
777
  saveToCSV(this.systemInvertedImpulseResponse, 'systemIIR.csv');
778
+ for (let i = 0; i < this.autocorrelations.length; i++){
779
+ saveToCSV(this.autocorrelations[i],`autocorrelation_${i}`);
780
+ }
776
781
  const computedIRagain = await Promise.all(this.impulseResponses).then(res => {
777
782
  for (let i = 0; i < res.length; i++) {
778
783
  if (res[i] != undefined) {
@@ -798,6 +803,9 @@ class Combination extends AudioCalibrator {
798
803
  saveToCSV(this.systemConvolution, 'python_system_convolution_mls_iir.csv');
799
804
  saveToCSV(this.componentInvertedImpulseResponse, 'componentIIR.csv');
800
805
  saveToCSV(this.systemInvertedImpulseResponse, 'systemIIR.csv');
806
+ for (let i = 0; i < this.autocorrelations.length; i++){
807
+ saveToCSV(this.autocorrelations[i],`autocorrelation_${i}`);
808
+ }
801
809
  const computedIRagain = await Promise.all(this.impulseResponses).then(res => {
802
810
  for (let i = 0; i < res.length; i++) {
803
811
  if (res[i] != undefined) {
@@ -841,8 +849,8 @@ class Combination extends AudioCalibrator {
841
849
  j += 1 / this.sourceSamplingRate;
842
850
  }
843
851
  return curve;
844
- };
845
-
852
+ };
853
+
846
854
  #getTruncatedSignal = (left = 3.5, right = 4.5) => {
847
855
  const start = Math.floor(left * this.sourceSamplingRate);
848
856
  const end = Math.floor(right * this.sourceSamplingRate);
@@ -1141,7 +1149,11 @@ class Combination extends AudioCalibrator {
1141
1149
  _calibrateSoundBurstRepeats = 4,
1142
1150
  _calibrateSoundBurstSec = 1,
1143
1151
  _calibrateSoundBurstsWarmup = 1,
1144
- _calibrateSoundHz = 48000
1152
+ _calibrateSoundHz = 48000,
1153
+ micManufacturer = '',
1154
+ micSerialNumber = '',
1155
+ micModelNumber = '',
1156
+ micModelName = ''
1145
1157
  ) => {
1146
1158
  this.numMLSPerCapture = _calibrateSoundBurstRepeats;
1147
1159
  this.desired_time_per_mls = _calibrateSoundBurstSec;