speaker-calibration 2.2.0 → 2.2.2

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.0",
3
+ "version": "2.2.2",
4
4
  "description": "Speaker calibration library for auditory testing",
5
5
  "main": "dist/main.js",
6
6
  "directories": {
@@ -169,7 +169,7 @@ class Listener extends AudioPeer {
169
169
  }
170
170
 
171
171
  if (capabilities.sampleRate) {
172
- constraints.sampleRate = 96000;
172
+ constraints.sampleRate = 48000;
173
173
  }
174
174
 
175
175
  if (capabilities.sampleSize) {
@@ -211,7 +211,7 @@ class Listener extends AudioPeer {
211
211
  // ? {echoCancellation: {exact: false}}
212
212
  // : {}),
213
213
  ...(availableConstraints.sampleRate && availableConstraints.sampleRate == true
214
- ? {sampleRate: {ideal: 96000}}
214
+ ? {sampleRate: {ideal: 48000}}
215
215
  : {}),
216
216
  ...(availableConstraints.sampleSize && availableConstraints.sampleSize == true
217
217
  ? {sampleSize: {ideal: 24}}
@@ -91,7 +91,11 @@ class Speaker extends AudioPeer {
91
91
  params.knownIR,
92
92
  params.microphoneName,
93
93
  params.calibrateSoundCheck,
94
- params.isSmartPhone
94
+ params.isSmartPhone,
95
+ params.calibrateSoundBurstRepeats,
96
+ params.calibrateSoundBurstSec,
97
+ params.calibrateSoundBurstsWarmup,
98
+ params.calibrateSoundHz
95
99
  );
96
100
  speaker.#removeUIElems();
97
101
  resolve(speaker.result);
@@ -24,7 +24,7 @@ class PythonServerAPI {
24
24
  * @returns
25
25
  * @example
26
26
  */
27
- getImpulseResponse = async ({mls, payload, sampleRate, P}) => {
27
+ getImpulseResponse = async ({mls, payload, sampleRate, P, numPeriods}) => {
28
28
  const task = 'impulse-response';
29
29
  let res = null;
30
30
 
@@ -36,6 +36,7 @@ class PythonServerAPI {
36
36
  'sample-rate': sampleRate,
37
37
  mls,
38
38
  P,
39
+ numPeriods,
39
40
  });
40
41
 
41
42
  await axios({
@@ -56,6 +57,56 @@ class PythonServerAPI {
56
57
  return res.data[task];
57
58
  };
58
59
 
60
+ getMLS = async(length) => {
61
+ const task = 'mls';
62
+ let res = null
63
+
64
+ const data = JSON.stringify({
65
+ task,
66
+ 'length':length,
67
+ })
68
+
69
+ await axios({
70
+ method:'post',
71
+ baseURL: PythonServerAPI.PYTHON_SERVER_URL,
72
+ url: `/task/${task}`,
73
+ headers: {
74
+ 'Content-Type':'application/json',
75
+ },
76
+ data,
77
+ })
78
+ .then(response => {
79
+ res = response;
80
+ })
81
+ .catch(error => {
82
+ throw error;
83
+ })
84
+
85
+ return res.data[task];
86
+ }
87
+ getMLSWithRetry = async (length) => {
88
+ let retryCount = 0;
89
+ let response = null;
90
+
91
+ while (retryCount < this.MAX_RETRY_COUNT) {
92
+ try {
93
+ response = await this.getMLS(length);
94
+ // If the request is successful, break out of the loop
95
+ break;
96
+ } catch (error) {
97
+ console.error(`Error occurred. Retrying... (${retryCount + 1}/${this.MAX_RETRY_COUNT})`);
98
+ retryCount++;
99
+ await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS));
100
+ }
101
+ }
102
+
103
+ if (response) {
104
+ return response;
105
+ } else {
106
+ throw new Error(`Failed to get MLS after ${this.MAX_RETRY_COUNT} attempts.`);
107
+ }
108
+ };
109
+
59
110
  getPSD = async ({unconv_rec, conv_rec, sampleRate}) => {
60
111
  const task = 'psd';
61
112
  let res = null;
@@ -142,6 +142,14 @@ class Combination extends AudioCalibrator {
142
142
 
143
143
  deviceName = null;
144
144
 
145
+ desired_time_per_mls = 0;
146
+
147
+ num_mls_to_skip = 0;
148
+
149
+ desired_sampling_rate = 0;
150
+
151
+ #currentConvolution = [];
152
+
145
153
  /**generate string template that gets reevaluated as variable increases */
146
154
  generateTemplate = () => {
147
155
  if (this.percent_complete > 100) {
@@ -298,6 +306,7 @@ class Combination extends AudioCalibrator {
298
306
  payload,
299
307
  mls,
300
308
  P: this.#P,
309
+ numPeriods: this.numMLSPerCapture,
301
310
  })
302
311
  .then(res => {
303
312
  if (this.numSuccessfulCaptured < this.numCaptures) {
@@ -337,7 +346,23 @@ class Combination extends AudioCalibrator {
337
346
  this.emit('update', {
338
347
  message: this.status,
339
348
  });
340
- await sleep((this.#P / this.sourceSamplingRate) * this.numMLSPerCapture);
349
+ let time_to_wait = (this.#mls.length / this.sourceSamplingRate) * this.numMLSPerCapture;
350
+ await sleep(time_to_wait);
351
+ };
352
+
353
+ #awaitDesiredMLSLengthConvolved = async () => {
354
+ // seconds per MLS = P / SR
355
+ // await N * P / SR
356
+ this.stepNum += 1;
357
+ console.log('await desired length ' + this.stepNum);
358
+ this.status =
359
+ `All Hz Calibration: sampling the calibration signal...`.toString() + this.generateTemplate();
360
+ this.emit('update', {
361
+ message: this.status,
362
+ });
363
+ let time_to_wait =
364
+ (this.#currentConvolution.length / this.sourceSamplingRate) * this.numMLSPerCapture;
365
+ await sleep(time_to_wait);
341
366
  };
342
367
 
343
368
  /** .
@@ -356,7 +381,25 @@ class Combination extends AudioCalibrator {
356
381
  this.emit('update', {
357
382
  message: this.status,
358
383
  });
359
- await sleep(this.TAPER_SECS);
384
+ let number_of_bursts_to_skip = this.num_mls_to_skip;
385
+ let time_to_sleep = this.#mls.length / this.sourceSamplingRate;
386
+ //await sleep(this.TAPER_SECS);
387
+ await sleep(time_to_sleep);
388
+ };
389
+
390
+ #awaitSignalOnsetConvolved = async () => {
391
+ this.stepNum += 1;
392
+ console.log('await signal onset ' + this.stepNum);
393
+ this.status =
394
+ `All Hz Calibration: waiting for the signal to stabilize...`.toString() +
395
+ this.generateTemplate();
396
+ this.emit('update', {
397
+ message: this.status,
398
+ });
399
+ let number_of_bursts_to_skip = this.num_mls_to_skip;
400
+ let time_to_sleep = this.#currentConvolution.length / this.sourceSamplingRate;
401
+ //await sleep(this.TAPER_SECS);
402
+ await sleep(time_to_sleep);
360
403
  };
361
404
 
362
405
  /**
@@ -463,8 +506,6 @@ class Combination extends AudioCalibrator {
463
506
  } catch (error) {
464
507
  console.error(error);
465
508
  }
466
- console.log('mls second, same?');
467
- console.log(data);
468
509
  const onsetGainNode = audioContext.createGain();
469
510
  this.offsetGainNode = audioContext.createGain();
470
511
  const source = audioContext.createBufferSource();
@@ -488,8 +529,6 @@ class Combination extends AudioCalibrator {
488
529
  */
489
530
  #setCalibrationNodesFromBuffer = (dataBufferArray = [this.#mlsBufferView]) => {
490
531
  if (dataBufferArray.length === 1) {
491
- console.log('data buffer aray');
492
- console.log(dataBufferArray);
493
532
  this.#createCalibrationNodeFromBuffer(dataBufferArray[0]);
494
533
  } else {
495
534
  throw new Error('The length of the data buffer array must be 1');
@@ -505,6 +544,7 @@ class Combination extends AudioCalibrator {
505
544
 
506
545
  //depends on goal
507
546
  if (this._calibrateSoundCheck != 'system') {
547
+ this.#currentConvolution = this.componentConvolution;
508
548
  const buffer = audioCtx.createBuffer(
509
549
  1, // number of channels
510
550
  this.componentConvolution.length,
@@ -529,6 +569,7 @@ class Combination extends AudioCalibrator {
529
569
 
530
570
  this.addCalibrationNodeConvolved(source);
531
571
  } else {
572
+ this.#currentConvolution = this.systemConvolution;
532
573
  const buffer = audioCtx.createBuffer(
533
574
  1, // number of channels
534
575
  this.systemConvolution.length,
@@ -563,6 +604,10 @@ class Combination extends AudioCalibrator {
563
604
  */
564
605
  #playCalibrationAudio = () => {
565
606
  this.calibrationNodes[0].start(0);
607
+ console.log('sink sampling rate');
608
+ console.log(this.sinkSamplingRate);
609
+ console.log('source sampling rate');
610
+ console.log(this.sourceSamplingRate);
566
611
  this.#mls = this.calibrationNodes[0].buffer.getChannelData(0);
567
612
  this.stepNum += 1;
568
613
  console.log('play calibration audio ' + this.stepNum);
@@ -574,6 +619,10 @@ class Combination extends AudioCalibrator {
574
619
 
575
620
  #playCalibrationAudioConvolved = () => {
576
621
  this.calibrationNodesConvolved[0].start(0);
622
+ console.log('sink sampling rate');
623
+ console.log(this.sinkSamplingRate);
624
+ console.log('source sampling rate');
625
+ console.log(this.sourceSamplingRate);
577
626
  this.stepNum += 1;
578
627
  console.log('play convolved audio ' + this.stepNum);
579
628
  this.status =
@@ -635,11 +684,9 @@ class Combination extends AudioCalibrator {
635
684
  this.sourceSamplingRate
636
685
  ).then(mlsGenInterface => {
637
686
  this.#mlsGenInterface = mlsGenInterface;
638
- this.#mlsBufferView = this.#mlsGenInterface.getMLS();
687
+ //this.#mlsBufferView = this.#mlsGenInterface.getMLS();
639
688
  });
640
689
 
641
- console.log('after mls factory'); //works up to here.
642
- console.log(this.#mls);
643
690
  // after intializating, start the calibration steps with garbage collection
644
691
  await this.#mlsGenInterface.withGarbageCollection([
645
692
  () =>
@@ -647,9 +694,9 @@ class Combination extends AudioCalibrator {
647
694
  stream,
648
695
  this.#playCalibrationAudioConvolved, // play audio func (required)
649
696
  this.#putInPythonConv, // before play func
650
- this.#awaitSignalOnset, // before record
697
+ this.#awaitSignalOnsetConvolved, // before record
651
698
  () => this.numSuccessfulCaptured < 1,
652
- this.#awaitDesiredMLSLength, // during record
699
+ this.#awaitDesiredMLSLengthConvolved, // during record
653
700
  this.#afterMLSwIIRRecord, // after record
654
701
  'filtered'
655
702
  ),
@@ -673,9 +720,24 @@ class Combination extends AudioCalibrator {
673
720
  this.sourceSamplingRate
674
721
  ).then(mlsGenInterface => {
675
722
  this.#mlsGenInterface = mlsGenInterface;
676
- this.#mlsBufferView = this.#mlsGenInterface.getMLS();
723
+ //this.#mlsBufferView = this.#mlsGenInterface.getMLS();
677
724
  });
678
725
 
726
+ let desired_time = this.desired_time_per_mls;
727
+
728
+ length = this.sourceSamplingRate * desired_time;
729
+ //get mls here
730
+ await this.pyServerAPI
731
+ .getMLSWithRetry(length)
732
+ .then(res => {
733
+ console.log(res);
734
+ this.#mlsBufferView = res['mls'];
735
+ })
736
+ .catch(err => {
737
+ // this.emit('InvertedImpulseResponse', {res: false});
738
+ console.error(err);
739
+ });
740
+
679
741
  // after intializating, start the calibration steps with garbage collection
680
742
  await this.#mlsGenInterface.withGarbageCollection([
681
743
  () =>
@@ -1155,8 +1217,17 @@ class Combination extends AudioCalibrator {
1155
1217
  componentIR = null,
1156
1218
  microphoneName = 'MiniDSP-UMIK1-711-4754-vertical',
1157
1219
  _calibrateSoundCheck = 'goal', //GOAL PASSed in by default
1158
- isSmartPhone = false
1220
+ isSmartPhone = false,
1221
+ _calibrateSoundBurstRepeats = 4,
1222
+ _calibrateSoundBurstSec = 1,
1223
+ _calibrateSoundBurstsWarmup = 1,
1224
+ _calibrateSoundHz = 48000
1159
1225
  ) => {
1226
+ this.numMLSPerCapture = _calibrateSoundBurstRepeats;
1227
+ this.desired_time_per_mls = _calibrateSoundBurstSec;
1228
+ this.num_mls_to_skip = _calibrateSoundBurstsWarmup;
1229
+ this.desired_sampling_rate = _calibrateSoundHz;
1230
+
1160
1231
  //feed calibration goal here
1161
1232
  this._calibrateSoundCheck = _calibrateSoundCheck;
1162
1233
  //check if a componentIR was given to the system, if it isn't check for the microphone. using dummy data here bc we need to
@@ -1,3 +0,0 @@
1
- {
2
- "liveServer.settings.port": 5510
3
- }