speaker-calibration 2.2.7 → 2.2.9

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.7",
3
+ "version": "2.2.9",
4
4
  "description": "Speaker calibration library for auditory testing",
5
5
  "main": "dist/main.js",
6
6
  "directories": {
@@ -219,8 +219,13 @@ class Listener extends AudioPeer {
219
219
  ...(availableConstraints.channelCount && availableConstraints.channelCount == true
220
220
  ? {channelCount: {exact: 1}}
221
221
  : {}),
222
+ echoCanellation: false,
223
+ noiseSuppression: false,
224
+ autoGainControl: false
222
225
  };
223
226
 
227
+ console.log(contraints);
228
+
224
229
  this.displayUpdate(
225
230
  `Listener MediaDevices Contraints - ${JSON.stringify(contraints, undefined, 2)}`
226
231
  );
@@ -247,6 +247,7 @@ class AudioCalibrator extends AudioRecorder {
247
247
  }
248
248
  downloadSingleFilteredRecording = () => {
249
249
  const recordings = this.getAllFilteredRecordedSignals();
250
+ console.log("Single filtered recording should be of length: " + recordings[0].length);
250
251
  saveToCSV(recordings[0], `recordedMLSignal_convolved.csv`);
251
252
  }
252
253
  downloadUnfilteredRecordings = () => {
@@ -38,6 +38,7 @@ class AudioRecorder extends MyEventEmitter {
38
38
  const data = audioBuffer.getChannelData(0);
39
39
 
40
40
  console.log(`Decoded audio buffer with ${data.length} samples`);
41
+ console.log(`Unfiltered recording should be of length: ${data.length}`);
41
42
  this.#recordedSignals.push(Array.from(data));
42
43
  };
43
44
 
@@ -47,6 +48,7 @@ class AudioRecorder extends MyEventEmitter {
47
48
  const data = audioBuffer.getChannelData(0);
48
49
 
49
50
  console.log(`Decoded audio buffer with ${data.length} samples`);
51
+ console.log(`Filtered recording should be of length: ${data.length}`);
50
52
  this.#filteredRecordings.push(Array.from(data));
51
53
  };
52
54
 
@@ -1,5 +1,4 @@
1
1
  import AudioCalibrator from '../audioCalibrator';
2
- import MlsGenInterface from './mlsGen/mlsGenInterface';
3
2
 
4
3
  import {sleep, csvToArray, saveToCSV} from '../../utils';
5
4
  import database from '../../config/firebase';
@@ -150,6 +149,10 @@ class Combination extends AudioCalibrator {
150
149
 
151
150
  #currentConvolution = [];
152
151
 
152
+ mode = 'unfiltered';
153
+
154
+ sourceNode;
155
+
153
156
  /**generate string template that gets reevaluated as variable increases */
154
157
  generateTemplate = () => {
155
158
  if (this.percent_complete > 100) {
@@ -186,8 +189,6 @@ class Combination extends AudioCalibrator {
186
189
  const filteredComputedIRs = computedIRs.filter(element => {
187
190
  return element != undefined;
188
191
  });
189
- //const componentIRGains = this.componentIR['Gain'];
190
- //const componentIRFreqs = this.componentIR['Freq'];
191
192
  const mls = this.#mls;
192
193
  const lowHz = this.#lowHz;
193
194
  const highHz = this.#highHz;
@@ -215,12 +216,9 @@ class Combination extends AudioCalibrator {
215
216
  this.emit('update', {message: this.status});
216
217
  this.systemInvertedImpulseResponse = res['iir'];
217
218
  this.systemIR = res['ir'];
218
- //this.componentIR['Gain'] = res['ir'];
219
- //this.componentIR['Freq'] = res['frequencies'];
220
219
  this.systemConvolution = res['convolution'];
221
220
  })
222
221
  .catch(err => {
223
- // this.emit('InvertedImpulseResponse', {res: false});
224
222
  console.error(err);
225
223
  });
226
224
  };
@@ -348,26 +346,17 @@ class Combination extends AudioCalibrator {
348
346
  this.emit('update', {
349
347
  message: this.status,
350
348
  });
351
- let time_to_wait = (this.#mls.length / this.sourceSamplingRate) * this.numMLSPerCapture;
352
- await sleep(time_to_wait);
353
- };
354
-
355
- #awaitDesiredMLSLengthConvolved = async () => {
356
- // seconds per MLS = P / SR
357
- // await N * P / SR
358
- this.stepNum += 1;
359
- console.log('await desired length ' + this.stepNum);
360
- this.status =
361
- `All Hz Calibration: sampling the calibration signal...`.toString() +
362
- `\niteration ${this.stepNum}`;
363
- +this.generateTemplate();
364
-
365
- this.emit('update', {
366
- message: this.status,
367
- });
368
- let time_to_wait =
349
+ let time_to_wait = 0;
350
+ if (this.mode === 'unfiltered'){
351
+ time_to_wait = (this.#mls.length / this.sourceSamplingRate) * this.numMLSPerCapture;
352
+ }else if (this.mode === 'filtered'){
353
+ time_to_wait =
369
354
  (this.#currentConvolution.length / this.sourceSamplingRate) * this.numMLSPerCapture;
370
- await sleep(time_to_wait);
355
+ }else{
356
+ throw new Error("Mode broke in awaitDesiredMLSLength");
357
+ }
358
+
359
+ await sleep(time_to_wait*1.1);
371
360
  };
372
361
 
373
362
  /** .
@@ -387,23 +376,14 @@ class Combination extends AudioCalibrator {
387
376
  message: this.status,
388
377
  });
389
378
  let number_of_bursts_to_skip = this.num_mls_to_skip;
390
- let time_to_sleep = this.#mls.length / this.sourceSamplingRate;
391
- //await sleep(this.TAPER_SECS);
392
- await sleep(time_to_sleep);
393
- };
394
-
395
- #awaitSignalOnsetConvolved = async () => {
396
- this.stepNum += 1;
397
- console.log('await signal onset ' + this.stepNum);
398
- this.status =
399
- `All Hz Calibration: waiting for the signal to stabilize...`.toString() +
400
- this.generateTemplate();
401
- this.emit('update', {
402
- message: this.status,
403
- });
404
- let number_of_bursts_to_skip = this.num_mls_to_skip;
405
- let time_to_sleep = this.#currentConvolution.length / this.sourceSamplingRate;
406
- //await sleep(this.TAPER_SECS);
379
+ let time_to_sleep = 0;
380
+ if (this.mode === 'unfiltered'){
381
+ time_to_sleep = this.#mls.length / this.sourceSamplingRate;
382
+ }else if (this.mode === 'filtered'){
383
+ time_to_sleep = this.#currentConvolution.length / this.sourceSamplingRate;
384
+ }else{
385
+ throw new Error("Mode broke in awaitSignalOnset");
386
+ }
407
387
  await sleep(time_to_sleep);
408
388
  };
409
389
 
@@ -465,28 +445,6 @@ class Combination extends AudioCalibrator {
465
445
  return curve;
466
446
  };
467
447
 
468
- /**
469
- * Construct a Calibration Node with the calibration parameters.
470
- *
471
- * @param CALIBRATION_TONE_FREQUENCY
472
- * @private
473
- * @example
474
- */
475
- #createPureTonenNode = CALIBRATION_TONE_FREQUENCY => {
476
- const audioContext = this.makeNewSourceAudioContext();
477
- const oscilator = audioContext.createOscillator();
478
- const gainNode = audioContext.createGain();
479
-
480
- oscilator.frequency.value = CALIBRATION_TONE_FREQUENCY;
481
- oscilator.type = 'sine';
482
- gainNode.gain.value = 0.04;
483
-
484
- oscilator.connect(gainNode);
485
- gainNode.connect(audioContext.destination);
486
-
487
- this.addCalibrationNode(oscilator);
488
- };
489
-
490
448
  /**
491
449
  * Construct a Calibration Node with the calibration parameters.
492
450
  *
@@ -495,11 +453,16 @@ class Combination extends AudioCalibrator {
495
453
  * @example
496
454
  */
497
455
  #createCalibrationNodeFromBuffer = dataBuffer => {
498
- const audioContext = this.makeNewSourceAudioContext();
499
- const buffer = audioContext.createBuffer(
456
+ console.log('databuffer');
457
+ console.log(dataBuffer);
458
+ if (!this.sourceAudioContext){
459
+ this.makeNewSourceAudioContext();
460
+ }
461
+
462
+ const buffer = this.sourceAudioContext.createBuffer(
500
463
  1, // number of channels
501
464
  dataBuffer.length,
502
- audioContext.sampleRate // sample rate
465
+ this.sourceAudioContext.sampleRate // sample rate
503
466
  );
504
467
 
505
468
  const data = buffer.getChannelData(0); // get data
@@ -511,19 +474,16 @@ class Combination extends AudioCalibrator {
511
474
  } catch (error) {
512
475
  console.error(error);
513
476
  }
514
- const onsetGainNode = audioContext.createGain();
515
- this.offsetGainNode = audioContext.createGain();
516
- const source = audioContext.createBufferSource();
517
-
518
- source.buffer = buffer;
519
- source.loop = true;
520
- source.connect(onsetGainNode);
521
- onsetGainNode.connect(this.offsetGainNode);
522
- this.offsetGainNode.connect(audioContext.destination);
523
-
524
- const onsetCurve = Combination.createSCurveBuffer(this.sourceSamplingRate, Math.PI / 2);
525
- onsetGainNode.gain.setValueCurveAtTime(onsetCurve, 0, this.TAPER_SECS);
526
- this.addCalibrationNode(source);
477
+
478
+ this.sourceNode = this.sourceAudioContext.createBufferSource();
479
+
480
+
481
+
482
+ this.sourceNode.buffer = buffer;
483
+ this.sourceNode.loop = true;
484
+ this.sourceNode.connect(this.sourceAudioContext.destination);
485
+
486
+ this.addCalibrationNode(this.sourceNode);
527
487
  };
528
488
 
529
489
  /**
@@ -608,34 +568,32 @@ class Combination extends AudioCalibrator {
608
568
  * @example
609
569
  */
610
570
  #playCalibrationAudio = () => {
611
- this.calibrationNodes[0].start(0);
612
- console.log('sink sampling rate');
613
- console.log(this.sinkSamplingRate);
614
- console.log('source sampling rate');
615
- console.log(this.sourceSamplingRate);
616
- this.#mls = this.calibrationNodes[0].buffer.getChannelData(0);
617
- this.stepNum += 1;
618
- console.log('play calibration audio ' + this.stepNum);
619
- this.status =
571
+ if (this.mode === 'unfiltered'){
572
+ this.calibrationNodes[0].start(0);
573
+ this.#mls = this.calibrationNodes[0].buffer.getChannelData(0);
574
+ console.log('play calibration audio ' + this.stepNum);
575
+ this.status =
620
576
  `All Hz Calibration: playing the calibration tone...`.toString() +
621
577
  this.generateTemplate().toString();
622
- this.emit('update', {message: this.status});
623
- };
624
-
625
- #playCalibrationAudioConvolved = () => {
626
- this.calibrationNodesConvolved[0].start(0);
578
+ this.emit('update', {message: this.status});
579
+ } else if (this.mode === 'filtered'){
580
+ this.calibrationNodes[0].start(0);
581
+ console.log('play convolved audio ' + this.stepNum);
582
+ this.status =
583
+ `All Hz Calibration: playing the convolved calibration tone...`.toString() +
584
+ this.generateTemplate().toString();
585
+ this.emit('update', {message: this.status});
586
+ } else{
587
+ throw new Error("Mode is incorrect");
588
+ }
589
+ this.stepNum += 1;
627
590
  console.log('sink sampling rate');
628
591
  console.log(this.sinkSamplingRate);
629
592
  console.log('source sampling rate');
630
593
  console.log(this.sourceSamplingRate);
631
- this.stepNum += 1;
632
- console.log('play convolved audio ' + this.stepNum);
633
- this.status =
634
- `All Hz Calibration: playing the convolved calibration tone...`.toString() +
635
- this.generateTemplate().toString();
636
- this.emit('update', {message: this.status});
637
594
  };
638
595
 
596
+
639
597
  /** .
640
598
  * .
641
599
  * .
@@ -644,14 +602,10 @@ class Combination extends AudioCalibrator {
644
602
  * @example
645
603
  */
646
604
  #stopCalibrationAudio = () => {
647
- this.offsetGainNode.gain.setValueAtTime(
648
- this.offsetGainNode.gain.value,
649
- this.sourceAudioContext.currentTime
650
- );
651
605
 
652
- this.offsetGainNode.gain.setTargetAtTime(0, this.sourceAudioContext.currentTime, 0.5);
653
606
  this.calibrationNodes[0].stop(0);
654
- this.sourceAudioContext.close();
607
+ this.calibrationNodes = [];
608
+ this.sourceNode.disconnect();
655
609
  this.stepNum += 1;
656
610
  console.log('stop calibration audio ' + this.stepNum);
657
611
  this.status =
@@ -660,52 +614,21 @@ class Combination extends AudioCalibrator {
660
614
  this.emit('update', {message: this.status});
661
615
  };
662
616
 
663
- #stopCalibrationAudioConvolved = () => {
664
- this.offsetGainNode.gain.setValueAtTime(
665
- this.offsetGainNode.gain.value,
666
- this.sourceAudioContextConvolved.currentTime
667
- );
668
-
669
- this.offsetGainNode.gain.setTargetAtTime(0, this.sourceAudioContextConvolved.currentTime, 0.5);
670
- //this.calibrationNodesConvolved[0].stop(0);
671
- console.log('right before closing volved audio context');
672
- this.sourceAudioContextConvolved.close();
673
- this.stepNum += 1;
674
- console.log('stop convolved calibration audio ' + this.stepNum);
675
- this.status =
676
- `All Hz Calibration: stopping the convolved calibration tone...`.toString() +
677
- this.generateTemplate().toString();
678
- this.emit('update', {message: this.status});
679
- };
680
-
681
617
  playMLSwithIIR = async (stream, iir) => {
618
+ this.mode = 'filtered';
682
619
  console.log('play mls with iir');
683
620
  this.invertedImpulseResponse = iir;
684
- // initialize the MLSGenInterface object with it's factory method
685
-
686
- await MlsGenInterface.factory(
687
- this.#mlsOrder,
688
- this.sinkSamplingRate,
689
- this.sourceSamplingRate
690
- ).then(mlsGenInterface => {
691
- this.#mlsGenInterface = mlsGenInterface;
692
- //this.#mlsBufferView = this.#mlsGenInterface.getMLS();
693
- });
694
621
 
695
- // after intializating, start the calibration steps with garbage collection
696
- await this.#mlsGenInterface.withGarbageCollection([
697
- () =>
698
- this.calibrationSteps(
699
- stream,
700
- this.#playCalibrationAudioConvolved, // play audio func (required)
701
- this.#putInPythonConv, // before play func
702
- this.#awaitSignalOnsetConvolved, // before record
703
- () => this.numSuccessfulCaptured < 1,
704
- this.#awaitDesiredMLSLengthConvolved, // during record
705
- this.#afterMLSwIIRRecord, // after record
706
- 'filtered'
707
- ),
708
- ]);
622
+ await this.calibrationSteps(
623
+ stream,
624
+ this.#playCalibrationAudio, // play audio func (required)
625
+ this.#createCalibrationNodeFromBuffer(this.#currentConvolution), // before play func
626
+ this.#awaitSignalOnset, // before record
627
+ () => this.numSuccessfulCaptured < 1,
628
+ this.#awaitDesiredMLSLength, // during record
629
+ this.#afterMLSwIIRRecord, // after record
630
+ this.mode
631
+ )
709
632
  };
710
633
 
711
634
  /**
@@ -718,18 +641,12 @@ class Combination extends AudioCalibrator {
718
641
  * @example
719
642
  */
720
643
  startCalibrationImpulseResponse = async stream => {
721
- // initialize the MLSGenInterface object with it's factory method
722
- await MlsGenInterface.factory(
723
- this.#mlsOrder,
724
- this.sinkSamplingRate,
725
- this.sourceSamplingRate
726
- ).then(mlsGenInterface => {
727
- this.#mlsGenInterface = mlsGenInterface;
728
- //this.#mlsBufferView = this.#mlsGenInterface.getMLS();
729
- });
730
644
 
731
645
  let desired_time = this.desired_time_per_mls;
732
646
 
647
+ console.log("MLS sequence should be of length: " + (this.sourceSamplingRate * desired_time));
648
+
649
+
733
650
  length = this.sourceSamplingRate * desired_time;
734
651
  //get mls here
735
652
  await this.pyServerAPI
@@ -742,21 +659,16 @@ class Combination extends AudioCalibrator {
742
659
  // this.emit('InvertedImpulseResponse', {res: false});
743
660
  console.error(err);
744
661
  });
745
-
746
- // after intializating, start the calibration steps with garbage collection
747
- await this.#mlsGenInterface.withGarbageCollection([
748
- () =>
749
- this.calibrationSteps(
750
- stream,
751
- this.#playCalibrationAudio, // play audio func (required)
752
- this.#setCalibrationNodesFromBuffer, // before play func
753
- this.#awaitSignalOnset, // before record
754
- () => this.numSuccessfulCaptured < this.numCaptures, // loop while true
755
- this.#awaitDesiredMLSLength, // during record
756
- this.#afterMLSRecord, // after record
757
- 'unfiltered'
758
- ),
759
- ]);
662
+ await this.calibrationSteps(
663
+ stream,
664
+ this.#playCalibrationAudio, // play audio func (required)
665
+ this.#createCalibrationNodeFromBuffer(this.#mlsBufferView), // before play func
666
+ this.#awaitSignalOnset, // before record
667
+ () => this.numSuccessfulCaptured < this.numCaptures, // loop while true
668
+ this.#awaitDesiredMLSLength, // during record
669
+ this.#afterMLSRecord, // after record
670
+ this.mode
671
+ ),
760
672
 
761
673
  this.#stopCalibrationAudio();
762
674
 
@@ -767,13 +679,17 @@ class Combination extends AudioCalibrator {
767
679
  await this.sendComponentImpulseResponsesToServerForProcessing();
768
680
 
769
681
  this.numSuccessfulCaptured = 0;
770
- // debugging function, use to test the result of the IIR
771
682
 
772
- //if goal == loudspeaker etc,
773
683
  let iir_ir_and_plots;
774
684
  if (this._calibrateSoundCheck != 'none') {
685
+ if (this._calibrateSoundCheck != 'system') {
686
+ this.#currentConvolution = this.componentConvolution;
687
+ }else{
688
+ this.#currentConvolution = this.systemConvolution;
689
+ }
775
690
  await this.playMLSwithIIR(stream, this.invertedImpulseResponse);
776
- this.#stopCalibrationAudioConvolved();
691
+ this.#stopCalibrationAudio();
692
+ this.sourceAudioContext.close();
777
693
  let conv_recs = this.getAllFilteredRecordedSignals();
778
694
  let recs = this.getAllRecordedSignals();
779
695
  let unconv_rec = recs[0];
@@ -913,7 +829,6 @@ class Combination extends AudioCalibrator {
913
829
  throw new Error(`Unknown data type: ${data.type}`);
914
830
  }
915
831
  };
916
-
917
832
  createSCurveBuffer = (onSetBool = true) => {
918
833
  const curve = new Float32Array(this.TAPER_SECS * this.sourceSamplingRate + 1);
919
834
  const frequency = 1 / (4 * this.TAPER_SECS);
@@ -926,8 +841,8 @@ class Combination extends AudioCalibrator {
926
841
  j += 1 / this.sourceSamplingRate;
927
842
  }
928
843
  return curve;
929
- };
930
-
844
+ };
845
+
931
846
  #getTruncatedSignal = (left = 3.5, right = 4.5) => {
932
847
  const start = Math.floor(left * this.sourceSamplingRate);
933
848
  const end = Math.floor(right * this.sourceSamplingRate);
@@ -1268,17 +1183,6 @@ class Combination extends AudioCalibrator {
1268
1183
 
1269
1184
  this.oldComponentIR = this.componentIR;
1270
1185
 
1271
- //TODO:
1272
- //if *1000 is in, lcalib is that value and componentGainDBSPL is that value converted to dB
1273
- //this value (lcalib) is 1000 hz offset so it must be added to every gain
1274
- //if *1000 is not in, interpolate to get gain at 1000 hz (lcalib) and obtain componentGainDBSPL by converting lCalib to dB
1275
-
1276
- //lCalib is gain at 1000 hz, componentGainDBSPL is gain at 1000 hz converted to db
1277
- //TODO: get this parameter from DB
1278
- // lCalib = -37.4;
1279
- // this.componentGainDBSPL = -30;
1280
- // componentGainDBSPL = -30;
1281
-
1282
1186
  let volumeResults = await this.startCalibrationVolume(
1283
1187
  stream,
1284
1188
  gainValues,
@@ -1287,7 +1191,6 @@ class Combination extends AudioCalibrator {
1287
1191
  );
1288
1192
 
1289
1193
  let impulseResponseResults = await this.startCalibrationImpulseResponse(stream);
1290
- //TODO: if needed, insert componentIR into db
1291
1194
 
1292
1195
  if (componentIR != null) {
1293
1196
  //insert Freq and Gain from this.componentIR into db