speaker-calibration 2.2.219 → 2.2.221
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/.eslintignore +71 -71
- package/.eslintrc.json +40 -40
- package/.gitignore +81 -0
- package/.prettierignore +69 -69
- package/.prettierrc +14 -14
- package/LICENSE +20 -20
- package/README.md +133 -133
- package/__mocks__/fileMock.js +1 -1
- package/__mocks__/styleMock.js +1 -1
- package/babel.config.js +3 -3
- package/coverage/clover.xml +71 -71
- package/coverage/coverage-final.json +224 -224
- package/coverage/lcov-report/PythonServerInterface.js.html +265 -265
- package/coverage/lcov-report/base.css +354 -354
- package/coverage/lcov-report/block-navigation.js +82 -82
- package/coverage/lcov-report/index.html +123 -123
- package/coverage/lcov-report/prettify.css +101 -101
- package/coverage/lcov-report/prettify.js +937 -937
- package/coverage/lcov-report/sorter.js +189 -189
- package/coverage/lcov-report/src/index.html +121 -121
- package/coverage/lcov-report/src/server/PythonServerInterface.js.html +268 -268
- package/coverage/lcov-report/src/server/index.html +123 -123
- package/coverage/lcov-report/src/tasks/audioCalibrator.js.html +499 -499
- package/coverage/lcov-report/src/tasks/audioRecorder.js.html +412 -412
- package/coverage/lcov-report/src/tasks/index.html +143 -143
- package/coverage/lcov-report/src/tasks/volume/index.html +123 -123
- package/coverage/lcov-report/src/tasks/volume/volume.js.html +409 -409
- package/coverage/lcov-report/src/utils.js.html +172 -172
- package/coverage/lcov.info +91 -91
- package/dist/example/NoSleep.min.js +1 -1
- package/dist/example/fetch-languages-sheets.js +77 -77
- package/dist/example/i18n.js +29082 -28681
- package/dist/example/index.html +47 -47
- package/dist/example/listener.html +81 -79
- package/dist/example/server.js +51 -51
- package/dist/example/speaker.html +145 -145
- package/dist/example/speakerUI.js +273 -273
- package/dist/example/styles.css +152 -152
- package/dist/listener.js +411 -4
- package/dist/main.js +11 -11
- package/dist/mlsGen.js +6814 -6814
- package/dist/mlsGen.wasm +0 -0
- package/dist/package-lock.json +1018 -1018
- package/dist/package.json +18 -18
- package/doc/AudioCalibrator.html +417 -417
- package/doc/AudioPeer.html +251 -251
- package/doc/AudioRecorder.html +195 -195
- package/doc/ImpulseResponse.html +215 -215
- package/doc/Listener.html +308 -308
- package/doc/MlsGenInterface.html +226 -226
- package/doc/MyEventEmitter.html +274 -274
- package/doc/PythonServerAPI.html +109 -109
- package/doc/Speaker.html +276 -276
- package/doc/Takes%20a%20target%20element%20where%20html%20elements%20will%20be%20appended..html +128 -128
- package/doc/Takes%20the%20url%20of%20the%20current%20site%0Aand%20a%20target%20element%20where%20html%20elements%20will%20be%20appended..html +138 -138
- package/doc/Takes%20the%20url%20of%20the%20current%20site%20and%20a%20target%20element%20where%20html%20elements%20will%20be%20appended..html +137 -137
- package/doc/Volume.html +88 -88
- package/doc/audioCalibrator.js.html +179 -179
- package/doc/audioPeer.js.html +175 -175
- package/doc/audioRecorder.js.html +163 -163
- package/doc/creates%20a%20new%20AudioRecorder%20instance.%20%0ASets%20up%20the%20audio%20context%20and%20file%20reader..html +114 -114
- package/doc/fonts/OpenSans-Bold-webfont.svg +1829 -1829
- package/doc/fonts/OpenSans-BoldItalic-webfont.svg +1829 -1829
- package/doc/fonts/OpenSans-Italic-webfont.svg +1829 -1829
- package/doc/fonts/OpenSans-Light-webfont.svg +1830 -1830
- package/doc/fonts/OpenSans-LightItalic-webfont.svg +1834 -1834
- package/doc/fonts/OpenSans-Regular-webfont.svg +1830 -1830
- package/doc/global.html +308 -308
- package/doc/index.html +58 -58
- package/doc/listener.js.html +170 -170
- package/doc/mlsGen_mlsGenInterface.js.html +117 -117
- package/doc/myEventEmitter.js.html +124 -124
- package/doc/peer-connection_audioPeer.js.html +188 -188
- package/doc/peer-connection_listener.js.html +311 -311
- package/doc/peer-connection_speaker.js.html +381 -381
- package/doc/scripts/linenumber.js +25 -25
- package/doc/scripts/prettify/Apache-License-2.0.txt +202 -202
- package/doc/scripts/prettify/lang-css.js +24 -24
- package/doc/scripts/prettify/prettify.js +640 -640
- package/doc/server_PythonServerAPI.js.html +160 -160
- package/doc/speaker.js.html +248 -248
- package/doc/styles/jsdoc-default.css +371 -371
- package/doc/styles/prettify-jsdoc.css +111 -111
- package/doc/styles/prettify-tomorrow.css +163 -163
- package/doc/tasks_audioCalibrator.js.html +207 -207
- package/doc/tasks_audioRecorder.js.html +190 -190
- package/doc/tasks_impulse-response_impulseResponse.js.html +442 -442
- package/doc/tasks_impulse-response_mlsGen_mlsGenInterface.js.html +175 -175
- package/doc/tasks_volume_volume.js.html +185 -185
- package/doc/utils.js.html +105 -105
- package/jest.config.js +173 -173
- package/netlify.toml +26 -26
- package/package.json +78 -78
- package/src/config/firebase.js +26 -26
- package/src/index.html +21 -21
- package/src/listener-app/listener.js +377 -351
- package/src/main.js +22 -22
- package/src/myEventEmitter.js +83 -83
- package/src/peer-connection/audioPeer.js +148 -183
- package/src/peer-connection/listener.js +467 -389
- package/src/peer-connection/peerErrors.js +25 -25
- package/src/peer-connection/speaker.js +812 -810
- package/src/powerCheck.js +98 -98
- package/src/server/PythonServerAPI.js +869 -869
- package/src/tasks/audioCalibrator.js +360 -360
- package/src/tasks/audioRecorder.js +315 -315
- package/src/tasks/combination/combination.js +3171 -3167
- package/src/tasks/combination/mlsGen/mlsGen.cpp +98 -98
- package/src/tasks/combination/mlsGen/mlsGen.hpp +303 -303
- package/src/tasks/combination/mlsGen/mlsGenInterface.js +131 -131
- package/src/tasks/combination/mlsGen/mlsGenTest.cpp +180 -180
- package/src/tasks/impulse-response/impulseResponse.js +610 -610
- package/src/tasks/impulse-response/mlsGen/mlsGen.cpp +98 -98
- package/src/tasks/impulse-response/mlsGen/mlsGen.hpp +303 -303
- package/src/tasks/impulse-response/mlsGen/mlsGenInterface.js +131 -131
- package/src/tasks/impulse-response/mlsGen/mlsGenTest.cpp +180 -180
- package/src/tasks/volume/volume.cpp +2 -2
- package/src/tasks/volume/volume.hpp +22 -22
- package/src/tasks/volume/volume.js +279 -279
- package/src/utils.js +205 -205
- package/webpack.config.js +64 -64
- package/.github/workflows/update-phrases.yml +0 -37
- package/makefile +0 -74
|
@@ -1,273 +1,273 @@
|
|
|
1
|
-
window.onload = () => {
|
|
2
|
-
const flexSwitchCheckIR = document.getElementById('flexSwitchCheckIR');
|
|
3
|
-
const flexSwitchCheckVolume = document.getElementById('flexSwitchCheckVolume');
|
|
4
|
-
const flexSwitchCheckCombo = document.getElementById('flexSwitchCheckCombo');
|
|
5
|
-
const previousCaptureCSV = document.getElementById('previous-capture-csv');
|
|
6
|
-
const iirCSV = document.getElementById('iir-csv');
|
|
7
|
-
const playAndRecord = document.getElementById('flexSwitchPlayAndRecord');
|
|
8
|
-
const sendToServerButton = document.getElementById('sendToServerButton');
|
|
9
|
-
const wavFile = document.getElementById('wav-file');
|
|
10
|
-
|
|
11
|
-
const {Speaker, VolumeCalibration, ImpulseResponseCalibration, CombinationCalibration} =
|
|
12
|
-
speakerCalibrator;
|
|
13
|
-
|
|
14
|
-
const normalize = (min, max) => {
|
|
15
|
-
var delta = max - min;
|
|
16
|
-
return val => {
|
|
17
|
-
return (val - min) / delta;
|
|
18
|
-
};
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
const useIRResult = async invertedIR => {
|
|
22
|
-
// invertedIRNorm = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
|
|
23
|
-
const AudioContext = window.AudioContext || window.webkitAudioContext;
|
|
24
|
-
const audioCtx = new AudioContext();
|
|
25
|
-
const invertedIRNorm = invertedIR;
|
|
26
|
-
const audioFileName = 'Queen-Bohemian_Rhapsody.wav';
|
|
27
|
-
const audioFileURL = window.location.hostname.includes('localhost')
|
|
28
|
-
? '../example/' + audioFileName
|
|
29
|
-
: './' + audioFileName;
|
|
30
|
-
const audioFile = fetch(audioFileURL)
|
|
31
|
-
.then(response => response.arrayBuffer())
|
|
32
|
-
.then(buffer => audioCtx.decodeAudioData(buffer))
|
|
33
|
-
.then(async buffer => {
|
|
34
|
-
buffer.channelCount = 1;
|
|
35
|
-
buffer.numberOfChannels = 1;
|
|
36
|
-
|
|
37
|
-
const track = audioCtx.createBufferSource(1, buffer.length, audioCtx.sampleRate);
|
|
38
|
-
track.buffer = buffer;
|
|
39
|
-
track.channelCount = 1;
|
|
40
|
-
|
|
41
|
-
const convolverBuffer = audioCtx.createBuffer(
|
|
42
|
-
1,
|
|
43
|
-
invertedIR.length - 1,
|
|
44
|
-
audioCtx.sampleRate
|
|
45
|
-
);
|
|
46
|
-
|
|
47
|
-
// Fill the buffer with white noise;
|
|
48
|
-
// just random values between -1.0 and 1.0
|
|
49
|
-
// This gives us the actual ArrayBuffer that contains the data
|
|
50
|
-
const nowBuffering = convolverBuffer.getChannelData(0);
|
|
51
|
-
for (let i = 0; i < convolverBuffer.length; i++) {
|
|
52
|
-
// Math.random() is in [0; 1.0]
|
|
53
|
-
// audio needs to be in [-1.0; 1.0]
|
|
54
|
-
nowBuffering[i] = invertedIRNorm[i];
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const convolver = audioCtx.createConvolver();
|
|
58
|
-
convolver.normalize = false;
|
|
59
|
-
convolver.channelCount = 1;
|
|
60
|
-
convolver.buffer = convolverBuffer;
|
|
61
|
-
|
|
62
|
-
console.log({convolver});
|
|
63
|
-
console.log({track});
|
|
64
|
-
|
|
65
|
-
track.connect(convolver);
|
|
66
|
-
convolver.connect(audioCtx.destination);
|
|
67
|
-
track.start(0);
|
|
68
|
-
});
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
const handlePreviousCaptureUpload = e => {
|
|
72
|
-
const calibratorParams = {
|
|
73
|
-
numCaptures: 0,
|
|
74
|
-
numMLSPerCapture: 0,
|
|
75
|
-
download: false,
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
const f = e.target.files[0];
|
|
79
|
-
if (f) {
|
|
80
|
-
e.preventDefault();
|
|
81
|
-
const reader = new FileReader();
|
|
82
|
-
|
|
83
|
-
reader.onload = async e => {
|
|
84
|
-
console.log('Hello World');
|
|
85
|
-
const text = e.target.result;
|
|
86
|
-
const testIRCalibration = new ImpulseResponseCalibration(calibratorParams);
|
|
87
|
-
|
|
88
|
-
const handleImpulseResponsEvent = data => {
|
|
89
|
-
if (data.res) {
|
|
90
|
-
testIRCalibration.sendImpulseResponsesToServerForProcessing();
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
const handleInvertedImpulseResponseEvent = async data => {
|
|
95
|
-
if (data.res) {
|
|
96
|
-
await useIRResult(testIRCalibration.invertedImpulseResponse);
|
|
97
|
-
}
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
testIRCalibration.on('ImpulseResponse', handleImpulseResponsEvent);
|
|
101
|
-
testIRCalibration.on('InvertedImpulseResponse', handleInvertedImpulseResponseEvent);
|
|
102
|
-
|
|
103
|
-
testIRCalibration.sourceSamplingRate = 96000;
|
|
104
|
-
testIRCalibration.sendRecordingToServerForProcessing(text);
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
reader.readAsText(f);
|
|
108
|
-
}
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
const handleIIRUplaod = e => {
|
|
112
|
-
const f = e.target.files[0];
|
|
113
|
-
if (f) {
|
|
114
|
-
e.preventDefault();
|
|
115
|
-
const reader = new FileReader();
|
|
116
|
-
|
|
117
|
-
reader.onload = async e => {
|
|
118
|
-
const g_string = e.target.result;
|
|
119
|
-
const g = g_string.split('\n').map(val => parseFloat(val));
|
|
120
|
-
console.log({g});
|
|
121
|
-
|
|
122
|
-
if (playAndRecord.checked) {
|
|
123
|
-
// call SC
|
|
124
|
-
useSpeakerCalibrator(1, g);
|
|
125
|
-
} else {
|
|
126
|
-
useIRResult(g);
|
|
127
|
-
}
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
reader.readAsText(f);
|
|
131
|
-
}
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
const handleWavFileUpload = e => {
|
|
135
|
-
var sound = document.getElementById('sound');
|
|
136
|
-
sound.src = URL.createObjectURL(e.target.files[0]);
|
|
137
|
-
// not really needed in this exact case, but since it is really important in other cases,
|
|
138
|
-
// don't forget to revoke the blobURI when you don't need it
|
|
139
|
-
sound.onend = e => {
|
|
140
|
-
URL.revokeObjectURL(e.tartget.src);
|
|
141
|
-
};
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
previousCaptureCSV.addEventListener('change', handlePreviousCaptureUpload);
|
|
145
|
-
|
|
146
|
-
iirCSV.addEventListener('change', handleIIRUplaod);
|
|
147
|
-
|
|
148
|
-
wavFile.addEventListener('change', handleWavFileUpload);
|
|
149
|
-
|
|
150
|
-
flexSwitchCheckIR.onchange = () => {
|
|
151
|
-
flexSwitchCheckVolume.checked = !flexSwitchCheckIR.checked;
|
|
152
|
-
flexSwitchCheckCombo.checked = !flexSwitchCheckIR.checked;
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
flexSwitchCheckVolume.onchange = () => {
|
|
156
|
-
flexSwitchCheckIR.checked = !flexSwitchCheckVolume.checked;
|
|
157
|
-
flexSwitchCheckCombo.checked = !flexSwitchCheckVolume.checked;
|
|
158
|
-
};
|
|
159
|
-
|
|
160
|
-
flexSwitchCheckCombo.onchange = () => {
|
|
161
|
-
flexSwitchCheckIR.checked = !flexSwitchCheckCombo.checked;
|
|
162
|
-
flexSwitchCheckVolume.checked = !flexSwitchCheckCombo.checked;
|
|
163
|
-
};
|
|
164
|
-
|
|
165
|
-
const useSpeakerCalibrator = async (calibrationLevel = 0, iir = null) => {
|
|
166
|
-
let invertedIR;
|
|
167
|
-
const spinner = document.getElementById('spinner');
|
|
168
|
-
const calibrationResult = document.getElementById('calibrationResult');
|
|
169
|
-
const updateTarget = document.getElementById('updates');
|
|
170
|
-
|
|
171
|
-
const speakerParameters = {
|
|
172
|
-
siteUrl: window.location.href.substring(0, location.href.lastIndexOf('/')),
|
|
173
|
-
targetElementId: 'display',
|
|
174
|
-
soundMessageId: 'speak123',
|
|
175
|
-
calibrateSoundSamplingDesiredBits: document.getElementById(
|
|
176
|
-
'calibrateSoundSamplingDesiredBitsBox'
|
|
177
|
-
).value,
|
|
178
|
-
// gainValues: [0.1, 0.5, 0.9], // example gain values
|
|
179
|
-
// gainValues: [
|
|
180
|
-
// 0.6998419960022735, 0.44668359215096315, 0.31622776601683794, 0.17782794100389226, 0.1,
|
|
181
|
-
// 0.03162277660168379, 0.01, 0.000009999999999999999,
|
|
182
|
-
// ], //example gain values
|
|
183
|
-
gainValues: [
|
|
184
|
-
0.001, 0.0031622776601683794, 0.01, 0.03162277660168379, 0.1, 0.17782794100389226,
|
|
185
|
-
0.31622776601683794, 0.6998419960022735,
|
|
186
|
-
],
|
|
187
|
-
debug: true,
|
|
188
|
-
ICalib: 31,
|
|
189
|
-
};
|
|
190
|
-
|
|
191
|
-
const runImpulseResponseCalibration = async calibrationLevel => {
|
|
192
|
-
const calibratorParams = {
|
|
193
|
-
numCaptures: document.getElementById('numCapturesInput').value,
|
|
194
|
-
numMLSPerCapture: document.getElementById('numMLSPerCaptureInput').value,
|
|
195
|
-
mlsOrder: document.getElementById('mlsOrder').value,
|
|
196
|
-
download: document.getElementById('flexSwitchCheckDownload').checked,
|
|
197
|
-
};
|
|
198
|
-
|
|
199
|
-
const calibrator = new ImpulseResponseCalibration(calibratorParams);
|
|
200
|
-
|
|
201
|
-
calibrator.on('update', ({message, ...rest}) => {
|
|
202
|
-
updateTarget.innerHTML = message;
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
try {
|
|
206
|
-
if (calibrationLevel == 0) {
|
|
207
|
-
invertedIR = await Speaker.startCalibration(speakerParameters, calibrator);
|
|
208
|
-
console.log({invertedIR});
|
|
209
|
-
await useIRResult(invertedIR);
|
|
210
|
-
} else {
|
|
211
|
-
await Speaker.testIIR(speakerParameters, calibrator, iir);
|
|
212
|
-
}
|
|
213
|
-
} catch (err) {
|
|
214
|
-
calibrationResult.innerText = `${err.name}: ${err.message}`;
|
|
215
|
-
}
|
|
216
|
-
};
|
|
217
|
-
|
|
218
|
-
const runCombinationCalibration = async calibrationLevel => {
|
|
219
|
-
const calibratorParams = {
|
|
220
|
-
numCaptures: document.getElementById('numCapturesInput').value,
|
|
221
|
-
numMLSPerCapture: document.getElementById('numMLSPerCaptureInput').value,
|
|
222
|
-
mlsOrder: document.getElementById('mlsOrder').value,
|
|
223
|
-
download: document.getElementById('flexSwitchCheckDownload').checked,
|
|
224
|
-
calibrateSoundHz: document.getElementById('calibrateSoundHzBox').value,
|
|
225
|
-
calibrateSoundSamplingDesiredBits: document.getElementById(
|
|
226
|
-
'calibrateSoundSamplingDesiredBitsBox'
|
|
227
|
-
).value,
|
|
228
|
-
};
|
|
229
|
-
|
|
230
|
-
const calibrator = new CombinationCalibration(calibratorParams);
|
|
231
|
-
|
|
232
|
-
calibrator.on('update', ({message, ...rest}) => {
|
|
233
|
-
updateTarget.innerHTML = message;
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
try {
|
|
237
|
-
if (calibrationLevel == 0) {
|
|
238
|
-
invertedIR = await Speaker.startCalibration(speakerParameters, calibrator);
|
|
239
|
-
console.log({invertedIR});
|
|
240
|
-
await useIRResult(invertedIR);
|
|
241
|
-
} else {
|
|
242
|
-
await Speaker.testIIR(speakerParameters, calibrator, iir);
|
|
243
|
-
}
|
|
244
|
-
} catch (err) {
|
|
245
|
-
calibrationResult.innerText = `${err.name}: ${err.message}`;
|
|
246
|
-
}
|
|
247
|
-
};
|
|
248
|
-
|
|
249
|
-
const runVolumeCalibration = async () => {
|
|
250
|
-
const calibrator = new VolumeCalibration({});
|
|
251
|
-
calibrator.on('update', ({message, ...rest}) => {
|
|
252
|
-
updateTarget.innerHTML = message;
|
|
253
|
-
});
|
|
254
|
-
|
|
255
|
-
try {
|
|
256
|
-
soundGainDBSPL = await Speaker.startCalibration(speakerParameters, calibrator);
|
|
257
|
-
updateTarget.innerText = `${soundGainDBSPL} DBSPL`;
|
|
258
|
-
} catch (err) {
|
|
259
|
-
updateTarget.innerText = `${err.name}: ${err.message}`;
|
|
260
|
-
}
|
|
261
|
-
};
|
|
262
|
-
|
|
263
|
-
if (flexSwitchCheckIR.checked) {
|
|
264
|
-
runImpulseResponseCalibration(calibrationLevel);
|
|
265
|
-
} else if (flexSwitchCheckVolume.checked) {
|
|
266
|
-
runVolumeCalibration();
|
|
267
|
-
} else {
|
|
268
|
-
runCombinationCalibration(calibrationLevel);
|
|
269
|
-
}
|
|
270
|
-
};
|
|
271
|
-
|
|
272
|
-
document.getElementById('calibrationBeginButton').onclick = () => useSpeakerCalibrator();
|
|
273
|
-
};
|
|
1
|
+
window.onload = () => {
|
|
2
|
+
const flexSwitchCheckIR = document.getElementById('flexSwitchCheckIR');
|
|
3
|
+
const flexSwitchCheckVolume = document.getElementById('flexSwitchCheckVolume');
|
|
4
|
+
const flexSwitchCheckCombo = document.getElementById('flexSwitchCheckCombo');
|
|
5
|
+
const previousCaptureCSV = document.getElementById('previous-capture-csv');
|
|
6
|
+
const iirCSV = document.getElementById('iir-csv');
|
|
7
|
+
const playAndRecord = document.getElementById('flexSwitchPlayAndRecord');
|
|
8
|
+
const sendToServerButton = document.getElementById('sendToServerButton');
|
|
9
|
+
const wavFile = document.getElementById('wav-file');
|
|
10
|
+
|
|
11
|
+
const {Speaker, VolumeCalibration, ImpulseResponseCalibration, CombinationCalibration} =
|
|
12
|
+
speakerCalibrator;
|
|
13
|
+
|
|
14
|
+
const normalize = (min, max) => {
|
|
15
|
+
var delta = max - min;
|
|
16
|
+
return val => {
|
|
17
|
+
return (val - min) / delta;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const useIRResult = async invertedIR => {
|
|
22
|
+
// invertedIRNorm = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
|
|
23
|
+
const AudioContext = window.AudioContext || window.webkitAudioContext;
|
|
24
|
+
const audioCtx = new AudioContext();
|
|
25
|
+
const invertedIRNorm = invertedIR;
|
|
26
|
+
const audioFileName = 'Queen-Bohemian_Rhapsody.wav';
|
|
27
|
+
const audioFileURL = window.location.hostname.includes('localhost')
|
|
28
|
+
? '../example/' + audioFileName
|
|
29
|
+
: './' + audioFileName;
|
|
30
|
+
const audioFile = fetch(audioFileURL)
|
|
31
|
+
.then(response => response.arrayBuffer())
|
|
32
|
+
.then(buffer => audioCtx.decodeAudioData(buffer))
|
|
33
|
+
.then(async buffer => {
|
|
34
|
+
buffer.channelCount = 1;
|
|
35
|
+
buffer.numberOfChannels = 1;
|
|
36
|
+
|
|
37
|
+
const track = audioCtx.createBufferSource(1, buffer.length, audioCtx.sampleRate);
|
|
38
|
+
track.buffer = buffer;
|
|
39
|
+
track.channelCount = 1;
|
|
40
|
+
|
|
41
|
+
const convolverBuffer = audioCtx.createBuffer(
|
|
42
|
+
1,
|
|
43
|
+
invertedIR.length - 1,
|
|
44
|
+
audioCtx.sampleRate
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
// Fill the buffer with white noise;
|
|
48
|
+
// just random values between -1.0 and 1.0
|
|
49
|
+
// This gives us the actual ArrayBuffer that contains the data
|
|
50
|
+
const nowBuffering = convolverBuffer.getChannelData(0);
|
|
51
|
+
for (let i = 0; i < convolverBuffer.length; i++) {
|
|
52
|
+
// Math.random() is in [0; 1.0]
|
|
53
|
+
// audio needs to be in [-1.0; 1.0]
|
|
54
|
+
nowBuffering[i] = invertedIRNorm[i];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const convolver = audioCtx.createConvolver();
|
|
58
|
+
convolver.normalize = false;
|
|
59
|
+
convolver.channelCount = 1;
|
|
60
|
+
convolver.buffer = convolverBuffer;
|
|
61
|
+
|
|
62
|
+
console.log({convolver});
|
|
63
|
+
console.log({track});
|
|
64
|
+
|
|
65
|
+
track.connect(convolver);
|
|
66
|
+
convolver.connect(audioCtx.destination);
|
|
67
|
+
track.start(0);
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const handlePreviousCaptureUpload = e => {
|
|
72
|
+
const calibratorParams = {
|
|
73
|
+
numCaptures: 0,
|
|
74
|
+
numMLSPerCapture: 0,
|
|
75
|
+
download: false,
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const f = e.target.files[0];
|
|
79
|
+
if (f) {
|
|
80
|
+
e.preventDefault();
|
|
81
|
+
const reader = new FileReader();
|
|
82
|
+
|
|
83
|
+
reader.onload = async e => {
|
|
84
|
+
console.log('Hello World');
|
|
85
|
+
const text = e.target.result;
|
|
86
|
+
const testIRCalibration = new ImpulseResponseCalibration(calibratorParams);
|
|
87
|
+
|
|
88
|
+
const handleImpulseResponsEvent = data => {
|
|
89
|
+
if (data.res) {
|
|
90
|
+
testIRCalibration.sendImpulseResponsesToServerForProcessing();
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const handleInvertedImpulseResponseEvent = async data => {
|
|
95
|
+
if (data.res) {
|
|
96
|
+
await useIRResult(testIRCalibration.invertedImpulseResponse);
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
testIRCalibration.on('ImpulseResponse', handleImpulseResponsEvent);
|
|
101
|
+
testIRCalibration.on('InvertedImpulseResponse', handleInvertedImpulseResponseEvent);
|
|
102
|
+
|
|
103
|
+
testIRCalibration.sourceSamplingRate = 96000;
|
|
104
|
+
testIRCalibration.sendRecordingToServerForProcessing(text);
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
reader.readAsText(f);
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const handleIIRUplaod = e => {
|
|
112
|
+
const f = e.target.files[0];
|
|
113
|
+
if (f) {
|
|
114
|
+
e.preventDefault();
|
|
115
|
+
const reader = new FileReader();
|
|
116
|
+
|
|
117
|
+
reader.onload = async e => {
|
|
118
|
+
const g_string = e.target.result;
|
|
119
|
+
const g = g_string.split('\n').map(val => parseFloat(val));
|
|
120
|
+
console.log({g});
|
|
121
|
+
|
|
122
|
+
if (playAndRecord.checked) {
|
|
123
|
+
// call SC
|
|
124
|
+
useSpeakerCalibrator(1, g);
|
|
125
|
+
} else {
|
|
126
|
+
useIRResult(g);
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
reader.readAsText(f);
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const handleWavFileUpload = e => {
|
|
135
|
+
var sound = document.getElementById('sound');
|
|
136
|
+
sound.src = URL.createObjectURL(e.target.files[0]);
|
|
137
|
+
// not really needed in this exact case, but since it is really important in other cases,
|
|
138
|
+
// don't forget to revoke the blobURI when you don't need it
|
|
139
|
+
sound.onend = e => {
|
|
140
|
+
URL.revokeObjectURL(e.tartget.src);
|
|
141
|
+
};
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
previousCaptureCSV.addEventListener('change', handlePreviousCaptureUpload);
|
|
145
|
+
|
|
146
|
+
iirCSV.addEventListener('change', handleIIRUplaod);
|
|
147
|
+
|
|
148
|
+
wavFile.addEventListener('change', handleWavFileUpload);
|
|
149
|
+
|
|
150
|
+
flexSwitchCheckIR.onchange = () => {
|
|
151
|
+
flexSwitchCheckVolume.checked = !flexSwitchCheckIR.checked;
|
|
152
|
+
flexSwitchCheckCombo.checked = !flexSwitchCheckIR.checked;
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
flexSwitchCheckVolume.onchange = () => {
|
|
156
|
+
flexSwitchCheckIR.checked = !flexSwitchCheckVolume.checked;
|
|
157
|
+
flexSwitchCheckCombo.checked = !flexSwitchCheckVolume.checked;
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
flexSwitchCheckCombo.onchange = () => {
|
|
161
|
+
flexSwitchCheckIR.checked = !flexSwitchCheckCombo.checked;
|
|
162
|
+
flexSwitchCheckVolume.checked = !flexSwitchCheckCombo.checked;
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
const useSpeakerCalibrator = async (calibrationLevel = 0, iir = null) => {
|
|
166
|
+
let invertedIR;
|
|
167
|
+
const spinner = document.getElementById('spinner');
|
|
168
|
+
const calibrationResult = document.getElementById('calibrationResult');
|
|
169
|
+
const updateTarget = document.getElementById('updates');
|
|
170
|
+
|
|
171
|
+
const speakerParameters = {
|
|
172
|
+
siteUrl: window.location.href.substring(0, location.href.lastIndexOf('/')),
|
|
173
|
+
targetElementId: 'display',
|
|
174
|
+
soundMessageId: 'speak123',
|
|
175
|
+
calibrateSoundSamplingDesiredBits: document.getElementById(
|
|
176
|
+
'calibrateSoundSamplingDesiredBitsBox'
|
|
177
|
+
).value,
|
|
178
|
+
// gainValues: [0.1, 0.5, 0.9], // example gain values
|
|
179
|
+
// gainValues: [
|
|
180
|
+
// 0.6998419960022735, 0.44668359215096315, 0.31622776601683794, 0.17782794100389226, 0.1,
|
|
181
|
+
// 0.03162277660168379, 0.01, 0.000009999999999999999,
|
|
182
|
+
// ], //example gain values
|
|
183
|
+
gainValues: [
|
|
184
|
+
0.001, 0.0031622776601683794, 0.01, 0.03162277660168379, 0.1, 0.17782794100389226,
|
|
185
|
+
0.31622776601683794, 0.6998419960022735,
|
|
186
|
+
],
|
|
187
|
+
debug: true,
|
|
188
|
+
ICalib: 31,
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
const runImpulseResponseCalibration = async calibrationLevel => {
|
|
192
|
+
const calibratorParams = {
|
|
193
|
+
numCaptures: document.getElementById('numCapturesInput').value,
|
|
194
|
+
numMLSPerCapture: document.getElementById('numMLSPerCaptureInput').value,
|
|
195
|
+
mlsOrder: document.getElementById('mlsOrder').value,
|
|
196
|
+
download: document.getElementById('flexSwitchCheckDownload').checked,
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
const calibrator = new ImpulseResponseCalibration(calibratorParams);
|
|
200
|
+
|
|
201
|
+
calibrator.on('update', ({message, ...rest}) => {
|
|
202
|
+
updateTarget.innerHTML = message;
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
try {
|
|
206
|
+
if (calibrationLevel == 0) {
|
|
207
|
+
invertedIR = await Speaker.startCalibration(speakerParameters, calibrator);
|
|
208
|
+
console.log({invertedIR});
|
|
209
|
+
await useIRResult(invertedIR);
|
|
210
|
+
} else {
|
|
211
|
+
await Speaker.testIIR(speakerParameters, calibrator, iir);
|
|
212
|
+
}
|
|
213
|
+
} catch (err) {
|
|
214
|
+
calibrationResult.innerText = `${err.name}: ${err.message}`;
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
const runCombinationCalibration = async calibrationLevel => {
|
|
219
|
+
const calibratorParams = {
|
|
220
|
+
numCaptures: document.getElementById('numCapturesInput').value,
|
|
221
|
+
numMLSPerCapture: document.getElementById('numMLSPerCaptureInput').value,
|
|
222
|
+
mlsOrder: document.getElementById('mlsOrder').value,
|
|
223
|
+
download: document.getElementById('flexSwitchCheckDownload').checked,
|
|
224
|
+
calibrateSoundHz: document.getElementById('calibrateSoundHzBox').value,
|
|
225
|
+
calibrateSoundSamplingDesiredBits: document.getElementById(
|
|
226
|
+
'calibrateSoundSamplingDesiredBitsBox'
|
|
227
|
+
).value,
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
const calibrator = new CombinationCalibration(calibratorParams);
|
|
231
|
+
|
|
232
|
+
calibrator.on('update', ({message, ...rest}) => {
|
|
233
|
+
updateTarget.innerHTML = message;
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
try {
|
|
237
|
+
if (calibrationLevel == 0) {
|
|
238
|
+
invertedIR = await Speaker.startCalibration(speakerParameters, calibrator);
|
|
239
|
+
console.log({invertedIR});
|
|
240
|
+
await useIRResult(invertedIR);
|
|
241
|
+
} else {
|
|
242
|
+
await Speaker.testIIR(speakerParameters, calibrator, iir);
|
|
243
|
+
}
|
|
244
|
+
} catch (err) {
|
|
245
|
+
calibrationResult.innerText = `${err.name}: ${err.message}`;
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
const runVolumeCalibration = async () => {
|
|
250
|
+
const calibrator = new VolumeCalibration({});
|
|
251
|
+
calibrator.on('update', ({message, ...rest}) => {
|
|
252
|
+
updateTarget.innerHTML = message;
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
try {
|
|
256
|
+
soundGainDBSPL = await Speaker.startCalibration(speakerParameters, calibrator);
|
|
257
|
+
updateTarget.innerText = `${soundGainDBSPL} DBSPL`;
|
|
258
|
+
} catch (err) {
|
|
259
|
+
updateTarget.innerText = `${err.name}: ${err.message}`;
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
if (flexSwitchCheckIR.checked) {
|
|
264
|
+
runImpulseResponseCalibration(calibrationLevel);
|
|
265
|
+
} else if (flexSwitchCheckVolume.checked) {
|
|
266
|
+
runVolumeCalibration();
|
|
267
|
+
} else {
|
|
268
|
+
runCombinationCalibration(calibrationLevel);
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
document.getElementById('calibrationBeginButton').onclick = () => useSpeakerCalibrator();
|
|
273
|
+
};
|