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,124 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>JSDoc: Source: myEventEmitter.js</title>
6
+
7
+ <script src="scripts/prettify/prettify.js"></script>
8
+ <script src="scripts/prettify/lang-css.js"></script>
9
+ <!--[if lt IE 9]>
10
+ <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
11
+ <![endif]-->
12
+ <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css" />
13
+ <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css" />
14
+ </head>
15
+
16
+ <body>
17
+ <div id="main">
18
+ <h1 class="page-title">Source: myEventEmitter.js</h1>
19
+
20
+ <section>
21
+ <article>
22
+ <pre class="prettyprint source linenums"><code>/**
23
+ * A simple event emitter class. Objects that inheret this class or implement it can then bubble events up to the UI
24
+ * similar to existings event emitter such as 'onChange' or 'onClick'
25
+ */
26
+ class MyEventEmitter {
27
+ #events;
28
+
29
+ /**
30
+ * Default constructor, intializes an empty object to store events
31
+ */
32
+ constructor() {
33
+ this.#events = {};
34
+ }
35
+
36
+ /**
37
+ * The external API for this class. Gets called with an event name and a callback function that is fired when the event is emitted.
38
+ * @param {*} name
39
+ * @param {*} listener
40
+ */
41
+ on(name, listener) {
42
+ if (!this.#events[name]) {
43
+ this.#events[name] = [];
44
+ }
45
+
46
+ this.#events[name].push(listener);
47
+ }
48
+
49
+ /**
50
+ * Function to remove a listener that was previously set
51
+ * @param {*} name
52
+ * @param {*} listenerToRemove
53
+ */
54
+ removeListener(name, listenerToRemove) {
55
+ if (!this.#events[name]) {
56
+ throw new Error(`Can't remove a listener. Event "${name}" doesn't exits.`);
57
+ }
58
+
59
+ const filterListeners = listener => listener !== listenerToRemove;
60
+
61
+ this.#events[name] = this.#events[name].filter(filterListeners);
62
+ }
63
+
64
+ /**
65
+ * The internal API for this class. Gets called with an event name and a data object.
66
+ * Any callbacks that have been set to listen to the matching event are dispatched.
67
+ * @param {*} name
68
+ * @param {*} data
69
+ */
70
+ emit(name, data) {
71
+ if (!this.#events[name]) {
72
+ throw new Error(`Can't emit an event. Event "${name}" doesn't exits.`);
73
+ }
74
+
75
+ const fireCallbacks = callback => {
76
+ callback(data);
77
+ };
78
+
79
+ this.#events[name].forEach(fireCallbacks);
80
+ }
81
+ }
82
+
83
+ export default MyEventEmitter;
84
+ </code></pre>
85
+ </article>
86
+ </section>
87
+ </div>
88
+
89
+ <nav>
90
+ <h2><a href="index.html">Home</a></h2>
91
+ <h3>Classes</h3>
92
+ <ul>
93
+ <li><a href="AudioCalibrator.html">AudioCalibrator</a></li>
94
+ <li><a href="AudioPeer.html">AudioPeer</a></li>
95
+ <li><a href="AudioRecorder.html">AudioRecorder</a></li>
96
+ <li><a href="ImpulseResponse.html">ImpulseResponse</a></li>
97
+ <li><a href="Listener.html">Listener</a></li>
98
+ <li><a href="MlsGenInterface.html">MlsGenInterface</a></li>
99
+ <li><a href="MyEventEmitter.html">MyEventEmitter</a></li>
100
+ <li><a href="PythonServerAPI.html">PythonServerAPI</a></li>
101
+ <li><a href="Speaker.html">Speaker</a></li>
102
+ <li><a href="Volume.html">Volume</a></li>
103
+ </ul>
104
+ <h3>Global</h3>
105
+ <ul>
106
+ <li><a href="global.html#csvToArray">csvToArray</a></li>
107
+ <li><a href="global.html#saveToCSV">saveToCSV</a></li>
108
+ <li><a href="global.html#sleep">sleep</a></li>
109
+ </ul>
110
+ </nav>
111
+
112
+ <br class="clear" />
113
+
114
+ <footer>
115
+ Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 3.6.10</a> on Fri
116
+ Jul 29 2022 15:09:48 GMT-0400 (Eastern Daylight Time)
117
+ </footer>
118
+
119
+ <script>
120
+ prettyPrint();
121
+ </script>
122
+ <script src="scripts/linenumber.js"></script>
123
+ </body>
124
+ </html>
@@ -0,0 +1,188 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>JSDoc: Source: peer-connection/audioPeer.js</title>
6
+
7
+ <script src="scripts/prettify/prettify.js"></script>
8
+ <script src="scripts/prettify/lang-css.js"></script>
9
+ <!--[if lt IE 9]>
10
+ <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
11
+ <![endif]-->
12
+ <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css" />
13
+ <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css" />
14
+ </head>
15
+
16
+ <body>
17
+ <div id="main">
18
+ <h1 class="page-title">Source: peer-connection/audioPeer.js</h1>
19
+
20
+ <section>
21
+ <article>
22
+ <pre class="prettyprint source linenums"><code>import Peer from 'peerjs';
23
+
24
+ // TODO: this was already here before, but appears to be unused
25
+ const pressFeedbackURI =
26
+ 'data:audio/mpeg;base64,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VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//uSZIIP9BFGHYksMlIAAA0gAAABAAABpAAAACAAADSAAAAEVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVQ==';
27
+
28
+ /**
29
+ * @typedef initParameters - Parameters for initializing the AudioPeer
30
+ * @type {object}
31
+ * @property {string} targetElementId - target element where new elements will be appended
32
+ * @property {string} siteUrl: the url of the current site
33
+ */
34
+ const initParameters = {
35
+ targetElementId: null,
36
+ siteUrl: null,
37
+ };
38
+
39
+ /**
40
+ * @class The first layer of abstraction on the PeerJS library.
41
+ * It meant to be extended by the two seperate client classes, Speaker and Listener.
42
+ * It implements the shared methods and properties of both classes.
43
+ */
44
+ class AudioPeer {
45
+ /**
46
+ * Creates an instance of AudioPeer
47
+ * Takes the url of the current site and a target element where html elements will be appended.
48
+ * @param {initParameters} params - see type definition for initParameters
49
+ */
50
+ constructor(param = initParameters) {
51
+ // PeerJS
52
+ /* Create the Peer object for our end of the connection. */
53
+ this.peer = new Peer({
54
+ secure: true,
55
+ host: 'easyeyes-peer-server.herokuapp.com',
56
+ port: 443,
57
+ });
58
+ this.conn = null;
59
+ this.lastPeerId = null;
60
+
61
+ // Display information to HTML elem with given id
62
+ this.targetElement = param.targetElementId;
63
+
64
+ this.siteUrl = param.siteUrl;
65
+
66
+ // Store for all incoming data
67
+ this.dataStore = [];
68
+
69
+ // Create and play sounds using this audio context
70
+ this.sourceAudioContext = new (window.AudioContext ||
71
+ window.webkitAudioContext ||
72
+ window.audioContext)();
73
+ }
74
+
75
+ /**
76
+ * Helper method to display information to DOM element
77
+ * @param {string} message
78
+ * @param {boolean} append
79
+ */
80
+ displayUpdate = (message, append = true) => {
81
+ // If the specified elem exists, update that elem
82
+ if (document.getElementById(this.targetElement)) {
83
+ const displayElement = document.getElementById(this.targetElement);
84
+ if (append) {
85
+ displayElement.innerText += `\n${message}`;
86
+ } else {
87
+ displayElement.innerText = message;
88
+ }
89
+ } else {
90
+ console.log('MESSAGE: ', message);
91
+ }
92
+ };
93
+
94
+ /**
95
+ * Callback method for when a peer connection is lost
96
+ * saves the last peer id, last server id, and attempts to reconnect
97
+ */
98
+ onPeerDisconnected = () => {
99
+ this.displayUpdate('Connection lost. Please reconnect');
100
+
101
+ // Workaround for peer.reconnect deleting previous id
102
+ this.peer.id = this.lastPeerId;
103
+ // eslint-disable-next-line no-underscore-dangle
104
+ this.peer._lastServerId = this.lastPeerId;
105
+ this.peer.reconnect();
106
+ };
107
+
108
+ /**
109
+ * Callback method that cleans up after peer connection is closed
110
+ */
111
+ onPeerClose = () => {
112
+ this.displayUpdate('Connection closed');
113
+ this.conn = null;
114
+ };
115
+
116
+ /**
117
+ * Helper method for when an error occurs
118
+ * @param {*} err
119
+ */
120
+ onPeerError = err => {
121
+ this.displayUpdate(err);
122
+ console.log(`${err}`);
123
+ };
124
+
125
+ /**
126
+ * Helper method that converts url paramters to an object
127
+ * @returns {object}
128
+ */
129
+ parseURLSearchParams = () =>
130
+ // SOURCE: chickens, https://stackoverflow.com/questions/8648892/how-to-convert-url-parameters-to-a-javascript-object
131
+ // eslint-disable-next-line no-restricted-globals
132
+ Object.fromEntries(new URLSearchParams(location.search));
133
+
134
+ /**
135
+ * Helper method that converts an object to a query string
136
+ * @param {object} params
137
+ * @returns {string}
138
+ */
139
+ queryStringFromObject = params =>
140
+ Object.keys(params)
141
+ .map(key => `${key}=${params[key]}`)
142
+ .join('&amp;');
143
+
144
+ static keypressFeedbackSound = pressFeedbackURI;
145
+ }
146
+
147
+ export default AudioPeer;
148
+ </code></pre>
149
+ </article>
150
+ </section>
151
+ </div>
152
+
153
+ <nav>
154
+ <h2><a href="index.html">Home</a></h2>
155
+ <h3>Classes</h3>
156
+ <ul>
157
+ <li><a href="AudioCalibrator.html">AudioCalibrator</a></li>
158
+ <li><a href="AudioPeer.html">AudioPeer</a></li>
159
+ <li><a href="AudioRecorder.html">AudioRecorder</a></li>
160
+ <li><a href="ImpulseResponse.html">ImpulseResponse</a></li>
161
+ <li><a href="Listener.html">Listener</a></li>
162
+ <li><a href="MlsGenInterface.html">MlsGenInterface</a></li>
163
+ <li><a href="MyEventEmitter.html">MyEventEmitter</a></li>
164
+ <li><a href="PythonServerAPI.html">PythonServerAPI</a></li>
165
+ <li><a href="Speaker.html">Speaker</a></li>
166
+ <li><a href="Volume.html">Volume</a></li>
167
+ </ul>
168
+ <h3>Global</h3>
169
+ <ul>
170
+ <li><a href="global.html#csvToArray">csvToArray</a></li>
171
+ <li><a href="global.html#saveToCSV">saveToCSV</a></li>
172
+ <li><a href="global.html#sleep">sleep</a></li>
173
+ </ul>
174
+ </nav>
175
+
176
+ <br class="clear" />
177
+
178
+ <footer>
179
+ Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 3.6.10</a> on Fri
180
+ Jul 29 2022 15:09:48 GMT-0400 (Eastern Daylight Time)
181
+ </footer>
182
+
183
+ <script>
184
+ prettyPrint();
185
+ </script>
186
+ <script src="scripts/linenumber.js"></script>
187
+ </body>
188
+ </html>
@@ -0,0 +1,311 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>JSDoc: Source: peer-connection/listener.js</title>
6
+
7
+ <script src="scripts/prettify/prettify.js"></script>
8
+ <script src="scripts/prettify/lang-css.js"></script>
9
+ <!--[if lt IE 9]>
10
+ <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
11
+ <![endif]-->
12
+ <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css" />
13
+ <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css" />
14
+ </head>
15
+
16
+ <body>
17
+ <div id="main">
18
+ <h1 class="page-title">Source: peer-connection/listener.js</h1>
19
+
20
+ <section>
21
+ <article>
22
+ <pre class="prettyprint source linenums"><code>import AudioPeer from './audioPeer';
23
+ import {UnsupportedDeviceError, MissingSpeakerIdError} from './peerErrors';
24
+
25
+ /**
26
+ * @class Handles the listener's side of the connection. Responsible for getting access to user's microphone,
27
+ * and initiating a call to the Speaker.
28
+ * @extends AudioPeer
29
+ */
30
+ class Listener extends AudioPeer {
31
+ /**
32
+ * Takes a target element where html elements will be appended.
33
+ * @param {initParameters} params - see type definition for initParameters
34
+ */
35
+ constructor(params) {
36
+ super(params);
37
+
38
+ this.startTime = Date.now();
39
+ this.receiverPeerId = null;
40
+
41
+ const urlParameters = this.parseURLSearchParams();
42
+ this.speakerPeerId = urlParameters.speakerPeerId;
43
+
44
+ this.peer.on('open', this.onPeerOpen);
45
+ this.peer.on('connection', this.onPeerConnection);
46
+ this.peer.on('disconnected', this.onPeerDisconnected);
47
+ this.peer.on('close', this.onPeerClose);
48
+ this.peer.on('error', this.onPeerError);
49
+ }
50
+
51
+ onPeerOpen = id => {
52
+ this.displayUpdate('Listener - onPeerOpen');
53
+ // Workaround for peer.reconnect deleting previous id
54
+
55
+ if (id === null) {
56
+ this.displayUpdate('Received null id from peer open');
57
+ this.peer.id = this.lastPeerId;
58
+ } else {
59
+ this.lastPeerId = this.peer.id;
60
+ }
61
+
62
+ this.join();
63
+ };
64
+
65
+ onPeerConnection = connection => {
66
+ this.displayUpdate('Listener - onPeerConnection');
67
+ // Disallow incoming connections
68
+ connection.on('open', () => {
69
+ connection.send('Sender does not accept incoming connections');
70
+ setTimeout(() => {
71
+ connection.close();
72
+ }, 500);
73
+ });
74
+ };
75
+
76
+ onConnData = data => {
77
+ this.displayUpdate('Listener - onConnData');
78
+ const hasSpeakerID = Object.prototype.hasOwnProperty.call(data, 'speakerPeerId');
79
+ if (!hasSpeakerID) {
80
+ this.displayUpdate('Error in parsing data received! Must set "speakerPeerId" property');
81
+ throw new MissingSpeakerIdError('Must set "speakerPeerId" property');
82
+ } else {
83
+ // this.conn.close();
84
+ this.displayUpdate(this.speakerPeerId);
85
+ this.speakerPeerId = data.speakerPeerId;
86
+ const newParams = {
87
+ speakerPeerId: this.speakerPeerId,
88
+ };
89
+ /*
90
+ FUTURE does this limit usable environments?
91
+ ie does this work if internet is lost after initial page load?
92
+ */
93
+ window.location.search = this.queryStringFromObject(newParams); // Redirect to correctly constructed keypad page
94
+ }
95
+ };
96
+
97
+ join = () => {
98
+ this.displayUpdate('Listener - join');
99
+ /**
100
+ * Create the connection between the two Peers.
101
+ *
102
+ * Sets up callbacks that handle any events related to the
103
+ * connection and data received on it.
104
+ */
105
+ // Close old connection
106
+ if (this.conn) {
107
+ this.displayUpdate('Closing old connection');
108
+ this.conn.close();
109
+ }
110
+
111
+ // Create connection to destination peer specified by the query param
112
+ this.displayUpdate(`Creating connection to: ${this.speakerPeerId}`);
113
+ this.conn = this.peer.connect(this.speakerPeerId, {
114
+ reliable: true,
115
+ });
116
+
117
+ this.displayUpdate('Created connection');
118
+
119
+ this.conn.on('open', async () => {
120
+ this.displayUpdate('Listener - conn open');
121
+ // this.sendSamplingRate();
122
+ await this.openAudioStream();
123
+ });
124
+
125
+ // Handle incoming data (messages only since this is the signal sender)
126
+ this.conn.on('data', this.onConnData);
127
+ this.conn.on('close', () => {
128
+ console.log('Connection closed');
129
+ });
130
+ };
131
+
132
+ getMobileOS = () => {
133
+ const ua = navigator.userAgent;
134
+ if (/android/i.test(ua)) {
135
+ return 'Android';
136
+ }
137
+ if (
138
+ /iPad|iPhone|iPod/.test(ua) ||
139
+ ((navigator?.userAgentData?.platform || navigator?.platform) === 'MacIntel' &amp;&amp;
140
+ navigator.maxTouchPoints > 1)
141
+ ) {
142
+ return 'iOS';
143
+ }
144
+ return 'Other';
145
+ };
146
+
147
+ sendSamplingRate = sampleRate => {
148
+ this.displayUpdate('Listener - sendSamplingRate');
149
+ this.conn.send({
150
+ name: 'samplingRate',
151
+ payload: sampleRate,
152
+ });
153
+ };
154
+
155
+ applyHQTrackConstraints = async stream => {
156
+ // Contraint the incoming audio to the sampling rate we want
157
+ const track = stream.getAudioTracks()[0];
158
+ const capabilities = track.getCapabilities();
159
+
160
+ this.displayUpdate(
161
+ `Listener Track Capabilities - ${JSON.stringify(capabilities, undefined, 2)}`
162
+ );
163
+
164
+ const constraints = track.getConstraints();
165
+
166
+ if (capabilities.echoCancellation) {
167
+ constraints.echoCancellation = false;
168
+ }
169
+
170
+ if (capabilities.sampleRate) {
171
+ constraints.sampleRate = 96000;
172
+ }
173
+
174
+ if (capabilities.sampleSize) {
175
+ constraints.sampleSize = 24;
176
+ }
177
+
178
+ if (capabilities.channelCount) {
179
+ constraints.channelCount = 1;
180
+ }
181
+
182
+ this.displayUpdate(`Listener Track Constraints - ${JSON.stringify(constraints, undefined, 2)}`);
183
+
184
+ // await the promise
185
+ try {
186
+ await track.applyConstraints(constraints);
187
+ } catch (err) {
188
+ console.error(err);
189
+ this.displayUpdate(`Error applying constraints to track: ${err}`);
190
+ }
191
+
192
+ const settings = track.getSettings();
193
+ this.displayUpdate(`Listener Track Settings - ${JSON.stringify(settings, undefined, 2)}`);
194
+ return settings.sampleRate;
195
+ };
196
+
197
+ getMediaDevicesAudioContraints = () => {
198
+ const availableConstraints = navigator.mediaDevices.getSupportedConstraints();
199
+
200
+ this.displayUpdate(
201
+ `Listener MediaDevices Available Contraints - ${JSON.stringify(
202
+ availableConstraints,
203
+ undefined,
204
+ 2
205
+ )}`
206
+ );
207
+
208
+ const contraints = {
209
+ // ...(availableConstraints.echoCancellation &amp;&amp; availableConstraints.echoCancellation == true
210
+ // ? {echoCancellation: {exact: false}}
211
+ // : {}),
212
+ ...(availableConstraints.sampleRate &amp;&amp; availableConstraints.sampleRate == true
213
+ ? {sampleRate: {ideal: 96000}}
214
+ : {}),
215
+ ...(availableConstraints.sampleSize &amp;&amp; availableConstraints.sampleSize == true
216
+ ? {sampleSize: {ideal: 24}}
217
+ : {}),
218
+ ...(availableConstraints.channelCount &amp;&amp; availableConstraints.channelCount == true
219
+ ? {channelCount: {exact: 1}}
220
+ : {}),
221
+ };
222
+
223
+ this.displayUpdate(
224
+ `Listener MediaDevices Contraints - ${JSON.stringify(contraints, undefined, 2)}`
225
+ );
226
+
227
+ return contraints;
228
+ };
229
+
230
+ openAudioStream = async () => {
231
+ this.displayUpdate('Listener - openAudioStream');
232
+ const mobileOS = this.getMobileOS();
233
+ if (process.env.NODE_ENV !== 'development' &amp;&amp; mobileOS !== 'iOS') {
234
+ const err = new UnsupportedDeviceError(`${mobileOS} is not supported`);
235
+ this.conn.send({
236
+ name: err.name,
237
+ payload: err,
238
+ });
239
+ return;
240
+ }
241
+
242
+ navigator.mediaDevices
243
+ .getUserMedia({
244
+ audio: this.getMediaDevicesAudioContraints(),
245
+ video: false,
246
+ })
247
+ .then(stream => {
248
+ this.applyHQTrackConstraints(stream)
249
+ .then(sampleRate => {
250
+ this.sendSamplingRate(sampleRate);
251
+ this.peer.call(this.speakerPeerId, stream); // one-way call
252
+ this.displayUpdate('Listener - openAudioStream');
253
+ })
254
+ .catch(err => {
255
+ console.log(err);
256
+ this.displayUpdate(
257
+ `Listener - Error in applyHQTrackConstraints - ${JSON.stringify(err, undefined, 2)}`
258
+ );
259
+ });
260
+ })
261
+ .catch(err => {
262
+ console.error(err);
263
+ this.displayUpdate(
264
+ `Listener - Error in getUserMedia - ${JSON.stringify(err, undefined, 2)}`
265
+ );
266
+ });
267
+ };
268
+ }
269
+
270
+ export default Listener;
271
+ </code></pre>
272
+ </article>
273
+ </section>
274
+ </div>
275
+
276
+ <nav>
277
+ <h2><a href="index.html">Home</a></h2>
278
+ <h3>Classes</h3>
279
+ <ul>
280
+ <li><a href="AudioCalibrator.html">AudioCalibrator</a></li>
281
+ <li><a href="AudioPeer.html">AudioPeer</a></li>
282
+ <li><a href="AudioRecorder.html">AudioRecorder</a></li>
283
+ <li><a href="ImpulseResponse.html">ImpulseResponse</a></li>
284
+ <li><a href="Listener.html">Listener</a></li>
285
+ <li><a href="MlsGenInterface.html">MlsGenInterface</a></li>
286
+ <li><a href="MyEventEmitter.html">MyEventEmitter</a></li>
287
+ <li><a href="PythonServerAPI.html">PythonServerAPI</a></li>
288
+ <li><a href="Speaker.html">Speaker</a></li>
289
+ <li><a href="Volume.html">Volume</a></li>
290
+ </ul>
291
+ <h3>Global</h3>
292
+ <ul>
293
+ <li><a href="global.html#csvToArray">csvToArray</a></li>
294
+ <li><a href="global.html#saveToCSV">saveToCSV</a></li>
295
+ <li><a href="global.html#sleep">sleep</a></li>
296
+ </ul>
297
+ </nav>
298
+
299
+ <br class="clear" />
300
+
301
+ <footer>
302
+ Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 3.6.10</a> on Fri
303
+ Jul 29 2022 15:09:48 GMT-0400 (Eastern Daylight Time)
304
+ </footer>
305
+
306
+ <script>
307
+ prettyPrint();
308
+ </script>
309
+ <script src="scripts/linenumber.js"></script>
310
+ </body>
311
+ </html>