speaker-calibration 2.0.0 → 2.1.0

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.
Files changed (126) hide show
  1. package/.eslintignore +72 -0
  2. package/.eslintrc.json +40 -0
  3. package/.gitignore +78 -0
  4. package/.prettierignore +70 -0
  5. package/.prettierrc +15 -0
  6. package/LICENSE +20 -20
  7. package/README.md +133 -133
  8. package/__mocks__/fileMock.js +1 -0
  9. package/__mocks__/styleMock.js +1 -0
  10. package/babel.config.js +3 -0
  11. package/coverage/clover.xml +71 -0
  12. package/coverage/coverage-final.json +224 -0
  13. package/coverage/lcov-report/PythonServerInterface.js.html +265 -0
  14. package/coverage/lcov-report/base.css +354 -0
  15. package/coverage/lcov-report/block-navigation.js +82 -0
  16. package/coverage/lcov-report/favicon.png +0 -0
  17. package/coverage/lcov-report/index.html +123 -0
  18. package/coverage/lcov-report/prettify.css +101 -0
  19. package/coverage/lcov-report/prettify.js +937 -0
  20. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  21. package/coverage/lcov-report/sorter.js +189 -0
  22. package/coverage/lcov-report/src/index.html +121 -0
  23. package/coverage/lcov-report/src/server/PythonServerInterface.js.html +268 -0
  24. package/coverage/lcov-report/src/server/index.html +123 -0
  25. package/coverage/lcov-report/src/tasks/audioCalibrator.js.html +499 -0
  26. package/coverage/lcov-report/src/tasks/audioRecorder.js.html +412 -0
  27. package/coverage/lcov-report/src/tasks/index.html +143 -0
  28. package/coverage/lcov-report/src/tasks/volume/index.html +123 -0
  29. package/coverage/lcov-report/src/tasks/volume/volume.js.html +409 -0
  30. package/coverage/lcov-report/src/utils.js.html +172 -0
  31. package/coverage/lcov.info +91 -0
  32. package/dist/example/Queen-Bohemian_Rhapsody.wav +0 -0
  33. package/dist/example/Queen-Bohemian_Rhapsody_g_filtered.wav +0 -0
  34. package/dist/example/index.html +47 -0
  35. package/dist/example/listener.html +89 -0
  36. package/dist/example/server.js +49 -0
  37. package/dist/example/speaker.html +126 -0
  38. package/dist/example/speakerUI.js +217 -0
  39. package/dist/example/styles.css +40 -0
  40. package/dist/main.js +1 -1
  41. package/dist/mlsGen.js +6814 -6814
  42. package/dist/mlsGen.wasm +0 -0
  43. package/doc/AudioCalibrator.html +417 -0
  44. package/doc/AudioPeer.html +251 -0
  45. package/doc/AudioRecorder.html +195 -0
  46. package/doc/ImpulseResponse.html +215 -0
  47. package/doc/Listener.html +308 -0
  48. package/doc/MlsGenInterface.html +226 -0
  49. package/doc/MyEventEmitter.html +274 -0
  50. package/doc/PythonServerAPI.html +109 -0
  51. package/doc/Speaker-Calibration-UML-Diagram.png +0 -0
  52. package/doc/Speaker.html +276 -0
  53. package/doc/Takes%20a%20target%20element%20where%20html%20elements%20will%20be%20appended..html +128 -0
  54. package/doc/Takes%20the%20url%20of%20the%20current%20site%0Aand%20a%20target%20element%20where%20html%20elements%20will%20be%20appended..html +138 -0
  55. package/doc/Takes%20the%20url%20of%20the%20current%20site%20and%20a%20target%20element%20where%20html%20elements%20will%20be%20appended..html +137 -0
  56. package/doc/Volume.html +88 -0
  57. package/doc/audioCalibrator.js.html +179 -0
  58. package/doc/audioPeer.js.html +175 -0
  59. package/doc/audioRecorder.js.html +163 -0
  60. package/doc/creates%20a%20new%20AudioRecorder%20instance.%20%0ASets%20up%20the%20audio%20context%20and%20file%20reader..html +114 -0
  61. package/doc/fonts/OpenSans-Bold-webfont.eot +0 -0
  62. package/doc/fonts/OpenSans-Bold-webfont.svg +1830 -0
  63. package/doc/fonts/OpenSans-Bold-webfont.woff +0 -0
  64. package/doc/fonts/OpenSans-BoldItalic-webfont.eot +0 -0
  65. package/doc/fonts/OpenSans-BoldItalic-webfont.svg +1830 -0
  66. package/doc/fonts/OpenSans-BoldItalic-webfont.woff +0 -0
  67. package/doc/fonts/OpenSans-Italic-webfont.eot +0 -0
  68. package/doc/fonts/OpenSans-Italic-webfont.svg +1830 -0
  69. package/doc/fonts/OpenSans-Italic-webfont.woff +0 -0
  70. package/doc/fonts/OpenSans-Light-webfont.eot +0 -0
  71. package/doc/fonts/OpenSans-Light-webfont.svg +1831 -0
  72. package/doc/fonts/OpenSans-Light-webfont.woff +0 -0
  73. package/doc/fonts/OpenSans-LightItalic-webfont.eot +0 -0
  74. package/doc/fonts/OpenSans-LightItalic-webfont.svg +1835 -0
  75. package/doc/fonts/OpenSans-LightItalic-webfont.woff +0 -0
  76. package/doc/fonts/OpenSans-Regular-webfont.eot +0 -0
  77. package/doc/fonts/OpenSans-Regular-webfont.svg +1831 -0
  78. package/doc/fonts/OpenSans-Regular-webfont.woff +0 -0
  79. package/doc/global.html +308 -0
  80. package/doc/index.html +58 -0
  81. package/doc/listener.js.html +170 -0
  82. package/doc/mlsGen_mlsGenInterface.js.html +117 -0
  83. package/doc/myEventEmitter.js.html +124 -0
  84. package/doc/peer-connection_audioPeer.js.html +188 -0
  85. package/doc/peer-connection_listener.js.html +311 -0
  86. package/doc/peer-connection_speaker.js.html +381 -0
  87. package/doc/sc-activity-diagram.png +0 -0
  88. package/doc/scripts/linenumber.js +25 -0
  89. package/doc/scripts/prettify/Apache-License-2.0.txt +202 -0
  90. package/doc/scripts/prettify/lang-css.js +24 -0
  91. package/doc/scripts/prettify/prettify.js +640 -0
  92. package/doc/server_PythonServerAPI.js.html +160 -0
  93. package/doc/speaker.js.html +248 -0
  94. package/doc/styles/jsdoc-default.css +371 -0
  95. package/doc/styles/prettify-jsdoc.css +111 -0
  96. package/doc/styles/prettify-tomorrow.css +163 -0
  97. package/doc/tasks_audioCalibrator.js.html +207 -0
  98. package/doc/tasks_audioRecorder.js.html +190 -0
  99. package/doc/tasks_impulse-response_impulseResponse.js.html +442 -0
  100. package/doc/tasks_impulse-response_mlsGen_mlsGenInterface.js.html +175 -0
  101. package/doc/tasks_volume_volume.js.html +185 -0
  102. package/doc/utils.js.html +105 -0
  103. package/jest.config.js +173 -0
  104. package/netlify.toml +27 -0
  105. package/package.json +67 -66
  106. package/src/index.html +21 -0
  107. package/src/main.js +21 -0
  108. package/src/myEventEmitter.js +83 -0
  109. package/src/peer-connection/audioPeer.js +151 -0
  110. package/src/peer-connection/listener.js +251 -0
  111. package/src/peer-connection/peerErrors.js +25 -0
  112. package/src/peer-connection/speaker.js +346 -0
  113. package/src/server/PythonServerAPI.js +117 -0
  114. package/src/tasks/audioCalibrator.js +218 -0
  115. package/src/tasks/audioRecorder.js +148 -0
  116. package/src/tasks/impulse-response/impulseResponse.js +436 -0
  117. package/src/tasks/impulse-response/mlsGen/mlsGen.cpp +99 -0
  118. package/src/tasks/impulse-response/mlsGen/mlsGen.hpp +304 -0
  119. package/src/tasks/impulse-response/mlsGen/mlsGenInterface.js +131 -0
  120. package/src/tasks/impulse-response/mlsGen/mlsGenTest.cpp +181 -0
  121. package/src/tasks/volume/volume.cpp +3 -0
  122. package/src/tasks/volume/volume.hpp +23 -0
  123. package/src/tasks/volume/volume.js +157 -0
  124. package/src/utils.js +55 -0
  125. package/webpack.config.js +37 -0
  126. package/README +0 -3
@@ -0,0 +1,157 @@
1
+ import AudioCalibrator from '../audioCalibrator';
2
+
3
+ import {sleep} from '../../utils';
4
+
5
+ /**
6
+ *
7
+ */
8
+ class Volume extends AudioCalibrator {
9
+ /**
10
+ *
11
+ * @param root0
12
+ * @param root0.download
13
+ * @param root0.numCalibrationRounds
14
+ * @param root0.numCalibrationNodes
15
+ * @example
16
+ */
17
+
18
+ /** @private */
19
+ #CALIBRATION_TONE_FREQUENCY = 1000; // Hz
20
+
21
+ /** @private */
22
+ #CALIBRATION_TONE_TYPE = 'sine';
23
+
24
+ /** @private */
25
+ #CALIBRATION_TONE_DURATION = 5; // seconds
26
+
27
+ /** @private */
28
+ soundGainDBSPL = null;
29
+
30
+ handleIncomingData = data => {
31
+ console.log('Received data: ', data);
32
+ if (data.type === 'soundGainDBSPL') {
33
+ this.soundGainDBSPL = data.value;
34
+ } else {
35
+ throw new Error(`Unknown data type: ${data.type}`);
36
+ }
37
+ };
38
+
39
+ #getTruncatedSignal = (left = 3.5, right = 4.5) => {
40
+ const start = Math.floor(left * this.sourceSamplingRate);
41
+ const end = Math.floor(right * this.sourceSamplingRate);
42
+ const result = Array.from(this.getLastRecordedSignal().slice(start, end));
43
+
44
+ /**
45
+ * function to check that capture was properly made
46
+ * @param {*} list
47
+ */
48
+ const checkResult = list => {
49
+ const setItem = new Set(list);
50
+ if (setItem.size === 1 && setItem.has(0)) {
51
+ console.warn(
52
+ 'The last capture failed, all recorded signal is zero',
53
+ this.getAllRecordedSignals()
54
+ );
55
+ }
56
+ if (setItem.size === 0) {
57
+ console.warn('The last capture failed, no recorded signal');
58
+ }
59
+ };
60
+ checkResult(result);
61
+ return result;
62
+ };
63
+
64
+ /**
65
+ *
66
+ *
67
+ Construct a calibration Node with the calibration parameters and given gain value
68
+ * @param {*} gainValue
69
+ * */
70
+ #createCalibrationToneWithGainValue = gainValue => {
71
+ const audioContext = this.makeNewSourceAudioContext();
72
+ const oscilator = audioContext.createOscillator();
73
+ const gainNode = audioContext.createGain();
74
+
75
+ oscilator.frequency.value = this.#CALIBRATION_TONE_FREQUENCY;
76
+ oscilator.type = this.#CALIBRATION_TONE_TYPE;
77
+ gainNode.gain.value = gainValue;
78
+
79
+ oscilator.connect(gainNode);
80
+ gainNode.connect(audioContext.destination);
81
+
82
+ this.addCalibrationNode(oscilator);
83
+ };
84
+
85
+ /**
86
+ * Construct a Calibration Node with the calibration parameters.
87
+ *
88
+ * @private
89
+ * @example
90
+ */
91
+ #createCalibrationNode = () => {
92
+ const audioContext = this.makeNewSourceAudioContext();
93
+ const oscilator = audioContext.createOscillator();
94
+ const gainNode = audioContext.createGain();
95
+
96
+ oscilator.frequency.value = this.#CALIBRATION_TONE_FREQUENCY;
97
+ oscilator.type = this.#CALIBRATION_TONE_TYPE;
98
+ gainNode.gain.value = 0.04;
99
+
100
+ oscilator.connect(gainNode);
101
+ gainNode.connect(audioContext.destination);
102
+
103
+ this.addCalibrationNode(oscilator);
104
+ };
105
+
106
+ #playCalibrationAudio = async () => {
107
+ const totalDuration = this.#CALIBRATION_TONE_DURATION * 1.2;
108
+
109
+ this.calibrationNodes[0].start(0);
110
+ this.calibrationNodes[0].stop(totalDuration);
111
+ console.log(`Playing a buffer of ${this.#CALIBRATION_TONE_DURATION} seconds of audio`);
112
+ console.log(`Waiting a total of ${totalDuration} seconds`);
113
+ await sleep(totalDuration);
114
+ };
115
+
116
+ #sendToServerForProcessing = () => {
117
+ console.log('Sending data to server');
118
+ this.pyServerAPI
119
+ .getVolumeCalibration({
120
+ sampleRate: this.sourceSamplingRate,
121
+ payload: this.#getTruncatedSignal(),
122
+ })
123
+ .then(res => {
124
+ if (this.soundGainDBSPL === null) {
125
+ this.soundGainDBSPL = res;
126
+ }
127
+ })
128
+ .catch(err => {
129
+ console.warn(err);
130
+ });
131
+ };
132
+
133
+ startCalibration = async (stream, gainValues) => {
134
+ const trialIterations = gainValues.length;
135
+ const soundGainDBSPLValues = [];
136
+ // run the calibration at different gain values provided by the user
137
+ for (let i = 0; i < trialIterations; i++) {
138
+ do {
139
+ // console.log('Processing gain value: ', gainValues[i]);
140
+ // eslint-disable-next-line no-await-in-loop
141
+ await this.volumeCalibrationSteps(
142
+ stream,
143
+ this.#playCalibrationAudio,
144
+ this.#createCalibrationToneWithGainValue,
145
+ this.#sendToServerForProcessing,
146
+ gainValues[i]
147
+ );
148
+ } while (this.soundGainDBSPL === null);
149
+ soundGainDBSPLValues.push(this.soundGainDBSPL);
150
+ this.soundGainDBSPL = null;
151
+ }
152
+ // return this.soundGainDBSPL;
153
+ return soundGainDBSPLValues;
154
+ };
155
+ }
156
+
157
+ export default Volume;
package/src/utils.js ADDED
@@ -0,0 +1,55 @@
1
+ /** .
2
+ * .
3
+ * .
4
+ * Utlity function to pause execution for a given time
5
+ *
6
+ * @param {number} seconds
7
+ * @returns {Promise}
8
+ * @example
9
+ */
10
+ const sleep = seconds =>
11
+ new Promise(resolve => {
12
+ setTimeout(resolve, seconds * 1000);
13
+ });
14
+
15
+ /** .
16
+ * .
17
+ * .
18
+ * Uiltity function to create and save a CSV file from a buffer
19
+ *
20
+ * @param {*} data
21
+ * @param {*} filename
22
+ * @example
23
+ */
24
+ const saveToCSV = (data, filename = 'recordedMLSignal.csv') => {
25
+ // console.log(data)
26
+ let csvContent = 'data:text/csv;charset=utf-8,';
27
+
28
+ data.forEach((val, idx) => {
29
+ csvContent += `${idx},${val}\r\n`;
30
+ });
31
+ const encodedUri = encodeURI(csvContent);
32
+ const link = document.createElement('a');
33
+ link.setAttribute('href', encodedUri);
34
+ link.setAttribute('download', filename);
35
+ document.body.appendChild(link);
36
+ link.click();
37
+ };
38
+
39
+ /** .
40
+ * .
41
+ * .
42
+ * Utility function to create a buffer from a CSV file
43
+ *
44
+ * @param {*} csvString
45
+ * @param {*} delimiter
46
+ * @returns
47
+ * @example
48
+ */
49
+ const csvToArray = (csvString, delimiter = ',') =>
50
+ csvString
51
+ .trim()
52
+ .split('\n')
53
+ .map(row => parseFloat(row.trim().split(delimiter)[1]));
54
+
55
+ export {sleep, saveToCSV, csvToArray};
@@ -0,0 +1,37 @@
1
+ const path = require('path');
2
+ const {BundleAnalyzerPlugin} = require('webpack-bundle-analyzer');
3
+
4
+ const config = {
5
+ entry: {
6
+ main: './src/main.js',
7
+ },
8
+ output: {
9
+ path: path.resolve(__dirname, 'dist'),
10
+ filename: '[name].js',
11
+ library: {
12
+ name: 'speakerCalibrator',
13
+ type: 'umd',
14
+ },
15
+ },
16
+ module: {
17
+ rules: [
18
+ {
19
+ test: /\.css$/,
20
+ use: ['style-loader', 'css-loader'],
21
+ },
22
+ ],
23
+ },
24
+ plugins: [],
25
+ resolve: {
26
+ fallback: {
27
+ path: require.resolve('path-browserify'),
28
+ fs: false,
29
+ },
30
+ },
31
+ };
32
+
33
+ if (process.env.WEBPACK_ANALYZE === 'true') {
34
+ config.plugins.push(new BundleAnalyzerPlugin());
35
+ }
36
+
37
+ module.exports = config;
package/README DELETED
@@ -1,3 +0,0 @@
1
- # Speaker-Calibration: Javascript Speaker Calibration Library for Auditory Testing
2
-
3
- Speaker-Calibration provides a simple API for performing speaker calibration in Javascript. The Library has minimal dependencies and is designed to be used in the browser.