cacophony 0.15.0 → 0.15.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/README.md CHANGED
@@ -151,6 +151,35 @@ cacophony.on('cacheMiss', (event) => {
151
151
  });
152
152
  ```
153
153
 
154
+ ### Global Playback Events
155
+
156
+ Track all audio activity across your application:
157
+
158
+ ```typescript
159
+ // Monitor all playback globally
160
+ cacophony.on('globalPlay', (event) => {
161
+ console.log('Audio started:', event.source);
162
+ showGlobalAudioIndicator();
163
+ });
164
+
165
+ cacophony.on('globalStop', (event) => {
166
+ console.log('Audio stopped:', event.source);
167
+ hideGlobalAudioIndicator();
168
+ });
169
+
170
+ cacophony.on('globalPause', (event) => {
171
+ console.log('Audio paused:', event.source);
172
+ });
173
+
174
+ // Use case: pause all audio when app backgrounds
175
+ document.addEventListener('visibilitychange', () => {
176
+ if (document.hidden) {
177
+ // Global events let you track what's playing without manual state management
178
+ console.log('App backgrounded - track via global events');
179
+ }
180
+ });
181
+ ```
182
+
154
183
  ### Playback Events
155
184
 
156
185
  React to playback state changes:
@@ -172,6 +201,96 @@ sound.on('volumeChange', (volume) => {
172
201
  });
173
202
  ```
174
203
 
204
+ ### Complete Event Reference
205
+
206
+ #### Cacophony Events
207
+
208
+ The main Cacophony instance emits global events for loading, caching, and errors:
209
+
210
+ | Event | Payload | Description |
211
+ |-------|---------|-------------|
212
+ | `loadingStart` | `LoadingStartEvent` | Fired when audio loading begins. Contains `url` and `timestamp`. |
213
+ | `loadingProgress` | `LoadingProgressEvent` | Fired during download. Contains `url`, `loaded`, `total`, `progress` (0-1), `timestamp`. |
214
+ | `loadingComplete` | `LoadingCompleteEvent` | Fired when loading succeeds. Contains `url`, `duration`, `size`, `timestamp`. |
215
+ | `loadingError` | `LoadingErrorEvent` | Fired when loading fails. Contains `url`, `error`, `errorType`, `timestamp`. |
216
+ | `cacheHit` | `CacheHitEvent` | Fired on cache hit. Contains `url`, `cacheType` ('memory'\|'browser'\|'conditional'), `timestamp`. |
217
+ | `cacheMiss` | `CacheMissEvent` | Fired on cache miss. Contains `url`, `reason` ('not-found'\|'expired'\|'invalid'), `timestamp`. |
218
+ | `cacheError` | `CacheErrorEvent` | Fired on cache operation error. Contains `url`, `error`, `operation`, `timestamp`. |
219
+ | `globalPlay` | `GlobalPlaybackEvent` | Fired when any Sound or Synth starts playing. Contains `source`, `timestamp`. |
220
+ | `globalStop` | `GlobalPlaybackEvent` | Fired when any Sound or Synth stops. Contains `source`, `timestamp`. |
221
+ | `globalPause` | `GlobalPlaybackEvent` | Fired when any Sound or Synth pauses. Contains `source`, `timestamp`. |
222
+
223
+ #### Sound Events
224
+
225
+ Sound instances emit events for playback state and property changes:
226
+
227
+ | Event | Payload | Description |
228
+ |-------|---------|-------------|
229
+ | `play` | `Playback` | Fired when sound starts playing. Receives the Playback instance. |
230
+ | `stop` | `void` | Fired when sound stops. |
231
+ | `pause` | `void` | Fired when sound pauses. |
232
+ | `volumeChange` | `number` | Fired when volume changes. Receives new volume value. |
233
+ | `rateChange` | `number` | Fired when playback rate changes. Receives new rate value. |
234
+ | `soundError` | `SoundErrorEvent` | Fired on playback errors. Contains `url`, `error`, `errorType`, `timestamp`, `recoverable`. |
235
+
236
+ #### Playback Events
237
+
238
+ Individual Playback instances emit fine-grained playback events:
239
+
240
+ | Event | Payload | Description |
241
+ |-------|---------|-------------|
242
+ | `play` | `BasePlayback` | Fired when playback starts. Receives the Playback instance. |
243
+ | `stop` | `void` | Fired when playback stops. |
244
+ | `error` | `PlaybackErrorEvent` | Fired on playback errors. Contains `error`, `errorType`, `timestamp`, `recoverable`. |
245
+
246
+ ```typescript
247
+ const sound = await cacophony.createSound('audio.mp3');
248
+ const [playback] = sound.play();
249
+
250
+ playback.on('play', (pb) => {
251
+ console.log('Playback started:', pb.currentTime);
252
+ });
253
+
254
+ playback.on('error', (event) => {
255
+ if (event.recoverable) {
256
+ console.log('Recoverable error, retrying...');
257
+ playback.play();
258
+ }
259
+ });
260
+ ```
261
+
262
+ #### Synth Events
263
+
264
+ Synth instances emit events for synthesis parameter changes:
265
+
266
+ | Event | Payload | Description |
267
+ |-------|---------|-------------|
268
+ | `play` | `SynthPlayback` | Fired when synth starts playing. Receives the SynthPlayback instance. |
269
+ | `stop` | `void` | Fired when synth stops. |
270
+ | `pause` | `void` | Fired when synth pauses. |
271
+ | `frequencyChange` | `number` | Fired when frequency changes. Receives new frequency in Hz. |
272
+ | `typeChange` | `OscillatorType` | Fired when waveform type changes. Receives new type ('sine'\|'square'\|'sawtooth'\|'triangle'). |
273
+ | `detuneChange` | `number` | Fired when detune changes. Receives new detune value in cents. |
274
+ | `volumeChange` | `number` | Fired when volume changes. Receives new volume value. |
275
+ | `error` | `PlaybackErrorEvent` | Fired on playback errors. Contains `error`, `errorType`, `timestamp`, `recoverable`. |
276
+
277
+ ```typescript
278
+ const synth = cacophony.createOscillator({ frequency: 440, type: 'sine' });
279
+
280
+ synth.on('frequencyChange', (freq) => {
281
+ console.log('Frequency changed to:', freq, 'Hz');
282
+ updateFrequencyDisplay(freq);
283
+ });
284
+
285
+ synth.on('typeChange', (type) => {
286
+ console.log('Waveform changed to:', type);
287
+ updateWaveformDisplay(type);
288
+ });
289
+
290
+ synth.frequency = 880; // Triggers frequencyChange event
291
+ synth.type = 'square'; // Triggers typeChange event
292
+ ```
293
+
175
294
  ## Synthesizer Functionality
176
295
 
177
296
  Create and manipulate synthesized sounds with advanced control:
@@ -77,8 +77,8 @@ export declare class Cacophony {
77
77
  * Remove event listener.
78
78
  */
79
79
  off<K extends keyof CacophonyEvents>(event: K, listener: (data: CacophonyEvents[K]) => void): void;
80
- protected emit<K extends keyof CacophonyEvents>(event: K, data: CacophonyEvents[K]): void;
81
- protected emitAsync<K extends keyof CacophonyEvents>(event: K, data: CacophonyEvents[K]): Promise<void>;
80
+ emit<K extends keyof CacophonyEvents>(event: K, data: CacophonyEvents[K]): void;
81
+ emitAsync<K extends keyof CacophonyEvents>(event: K, data: CacophonyEvents[K]): Promise<void>;
82
82
  loadWorklets(signal?: AbortSignal): Promise<void>;
83
83
  createWorkletNode(name: string, url: string, signal?: AbortSignal): Promise<import('standardized-audio-context').IAudioWorkletNode<import('standardized-audio-context').IAudioContext>>;
84
84
  clearMemoryCache(): void;
package/dist/events.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  import { BasePlayback } from './basePlayback';
2
2
  import { SynthPlayback } from './synthPlayback';
3
+ import { Sound } from './sound';
4
+ import { Synth } from './synth';
3
5
  /**
4
6
  * Base events for all audio objects.
5
7
  */
@@ -35,6 +37,13 @@ export interface SynthEvents extends Omit<BaseAudioEvents, 'play'> {
35
37
  typeChange: OscillatorType;
36
38
  detuneChange: number;
37
39
  }
40
+ /**
41
+ * Global playback event fired when any Sound or Synth plays/stops/pauses.
42
+ */
43
+ export interface GlobalPlaybackEvent {
44
+ source: Sound | Synth;
45
+ timestamp: number;
46
+ }
38
47
  /**
39
48
  * Global Cacophony events including loading and cache operations.
40
49
  */
@@ -51,6 +60,9 @@ export interface CacophonyEvents {
51
60
  cacheHit: CacheHitEvent;
52
61
  cacheMiss: CacheMissEvent;
53
62
  cacheError: CacheErrorEvent;
63
+ globalPlay: GlobalPlaybackEvent;
64
+ globalStop: GlobalPlaybackEvent;
65
+ globalPause: GlobalPlaybackEvent;
54
66
  }
55
67
  /**
56
68
  * Fired when loading starts. Use for loading spinners.
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const X=require("standardized-audio-context"),K="data:text/javascript;base64,KGZ1bmN0aW9uIChleHBvcnRzKSB7CiAgICAndXNlIHN0cmljdCc7CgogICAgY29uc3QgV0VCQVVESU9fQkxPQ0tfU0laRSA9IDEyODsKICAgIGNvbnN0IERFRkFVTFRfQkxPQ0tfU0laRSA9IDEwMjQ7IC8vIERlZmF1bHQgYmxvY2sgc2l6ZSBpZiBub3QgcHJvdmlkZWQgaW4gb3B0aW9ucwogICAgLyoqIE92ZXJsYXAtQWRkIE5vZGUgKi8KICAgIGNsYXNzIE9MQVByb2Nlc3NvciBleHRlbmRzIEF1ZGlvV29ya2xldFByb2Nlc3NvciB7CiAgICAgICAgbmJJbnB1dHM7CiAgICAgICAgbmJPdXRwdXRzOwogICAgICAgIGJsb2NrU2l6ZTsKICAgICAgICBob3BTaXplOwogICAgICAgIG5iT3ZlcmxhcHM7CiAgICAgICAgaW5wdXRCdWZmZXJzID0gW107CiAgICAgICAgaW5wdXRCdWZmZXJzSGVhZCA9IFtdOwogICAgICAgIGlucHV0QnVmZmVyc1RvU2VuZCA9IFtdOwogICAgICAgIG91dHB1dEJ1ZmZlcnMgPSBbXTsKICAgICAgICBvdXRwdXRCdWZmZXJzVG9SZXRyaWV2ZSA9IFtdOwogICAgICAgIGNvbnN0cnVjdG9yKG9wdGlvbnMpIHsKICAgICAgICAgICAgc3VwZXIob3B0aW9ucyk7CiAgICAgICAgICAgIHRoaXMubmJJbnB1dHMgPSBvcHRpb25zLm51bWJlck9mSW5wdXRzIHx8IDE7CiAgICAgICAgICAgIHRoaXMubmJPdXRwdXRzID0gb3B0aW9ucy5udW1iZXJPZk91dHB1dHMgfHwgMTsKICAgICAgICAgICAgdGhpcy5ibG9ja1NpemUgPSBvcHRpb25zLnByb2Nlc3Nvck9wdGlvbnMuYmxvY2tTaXplIHx8IERFRkFVTFRfQkxPQ0tfU0laRTsKICAgICAgICAgICAgdGhpcy5ob3BTaXplID0gV0VCQVVESU9fQkxPQ0tfU0laRTsKICAgICAgICAgICAgdGhpcy5uYk92ZXJsYXBzID0gTWF0aC5mbG9vcih0aGlzLmJsb2NrU2l6ZSAvIHRoaXMuaG9wU2l6ZSk7CiAgICAgICAgICAgIHRoaXMuaW5pdGlhbGl6ZUJ1ZmZlcnMoKTsKICAgICAgICB9CiAgICAgICAgaW5pdGlhbGl6ZUJ1ZmZlcnMoKSB7CiAgICAgICAgICAgIHRoaXMuaW5wdXRCdWZmZXJzID0gbmV3IEFycmF5KHRoaXMubmJJbnB1dHMpOwogICAgICAgICAgICB0aGlzLmlucHV0QnVmZmVyc0hlYWQgPSBuZXcgQXJyYXkodGhpcy5uYklucHV0cyk7CiAgICAgICAgICAgIHRoaXMuaW5wdXRCdWZmZXJzVG9TZW5kID0gbmV3IEFycmF5KHRoaXMubmJJbnB1dHMpOwogICAgICAgICAgICB0aGlzLm91dHB1dEJ1ZmZlcnMgPSBuZXcgQXJyYXkodGhpcy5uYk91dHB1dHMpOwogICAgICAgICAgICB0aGlzLm91dHB1dEJ1ZmZlcnNUb1JldHJpZXZlID0gbmV3IEFycmF5KHRoaXMubmJPdXRwdXRzKTsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm5iSW5wdXRzOyBpKyspIHsKICAgICAgICAgICAgICAgIHRoaXMuYWxsb2NhdGVJbnB1dENoYW5uZWxzKGksIDEpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5uYk91dHB1dHM7IGkrKykgewogICAgICAgICAgICAgICAgdGhpcy5hbGxvY2F0ZU91dHB1dENoYW5uZWxzKGksIDEpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGFsbG9jYXRlSW5wdXRDaGFubmVscyhpbnB1dEluZGV4LCBuYkNoYW5uZWxzKSB7CiAgICAgICAgICAgIHRoaXMuaW5wdXRCdWZmZXJzW2lucHV0SW5kZXhdID0gbmV3IEFycmF5KG5iQ2hhbm5lbHMpOwogICAgICAgICAgICB0aGlzLmlucHV0QnVmZmVyc0hlYWRbaW5wdXRJbmRleF0gPSBuZXcgQXJyYXkobmJDaGFubmVscyk7CiAgICAgICAgICAgIHRoaXMuaW5wdXRCdWZmZXJzVG9TZW5kW2lucHV0SW5kZXhdID0gbmV3IEFycmF5KG5iQ2hhbm5lbHMpOwogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5iQ2hhbm5lbHM7IGkrKykgewogICAgICAgICAgICAgICAgdGhpcy5pbnB1dEJ1ZmZlcnNbaW5wdXRJbmRleF1baV0gPSBuZXcgRmxvYXQzMkFycmF5KHRoaXMuYmxvY2tTaXplICsgV0VCQVVESU9fQkxPQ0tfU0laRSk7CiAgICAgICAgICAgICAgICB0aGlzLmlucHV0QnVmZmVyc1tpbnB1dEluZGV4XVtpXS5maWxsKDApOwogICAgICAgICAgICAgICAgdGhpcy5pbnB1dEJ1ZmZlcnNIZWFkW2lucHV0SW5kZXhdW2ldID0gdGhpcy5pbnB1dEJ1ZmZlcnNbaW5wdXRJbmRleF1baV0uc3ViYXJyYXkoMCwgdGhpcy5ibG9ja1NpemUpOwogICAgICAgICAgICAgICAgdGhpcy5pbnB1dEJ1ZmZlcnNUb1NlbmRbaW5wdXRJbmRleF1baV0gPSBuZXcgRmxvYXQzMkFycmF5KHRoaXMuYmxvY2tTaXplKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBhbGxvY2F0ZU91dHB1dENoYW5uZWxzKG91dHB1dEluZGV4LCBuYkNoYW5uZWxzKSB7CiAgICAgICAgICAgIHRoaXMub3V0cHV0QnVmZmVyc1tvdXRwdXRJbmRleF0gPSBuZXcgQXJyYXkobmJDaGFubmVscyk7CiAgICAgICAgICAgIHRoaXMub3V0cHV0QnVmZmVyc1RvUmV0cmlldmVbb3V0cHV0SW5kZXhdID0gbmV3IEFycmF5KG5iQ2hhbm5lbHMpOwogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5iQ2hhbm5lbHM7IGkrKykgewogICAgICAgICAgICAgICAgdGhpcy5vdXRwdXRCdWZmZXJzW291dHB1dEluZGV4XVtpXSA9IG5ldyBGbG9hdDMyQXJyYXkodGhpcy5ibG9ja1NpemUpOwogICAgICAgICAgICAgICAgdGhpcy5vdXRwdXRCdWZmZXJzW291dHB1dEluZGV4XVtpXS5maWxsKDApOwogICAgICAgICAgICAgICAgdGhpcy5vdXRwdXRCdWZmZXJzVG9SZXRyaWV2ZVtvdXRwdXRJbmRleF1baV0gPSBuZXcgRmxvYXQzMkFycmF5KHRoaXMuYmxvY2tTaXplKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZWFsbG9jYXRlQ2hhbm5lbHNJZk5lZWRlZChpbnB1dHMsIG91dHB1dHMpIHsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm5iSW5wdXRzOyBpKyspIHsKICAgICAgICAgICAgICAgIGxldCBuYkNoYW5uZWxzID0gaW5wdXRzW2ldLmxlbmd0aDsKICAgICAgICAgICAgICAgIGlmIChuYkNoYW5uZWxzICE9PSB0aGlzLmlucHV0QnVmZmVyc1tpXS5sZW5ndGgpIHsKICAgICAgICAgICAgICAgICAgICB0aGlzLmFsbG9jYXRlSW5wdXRDaGFubmVscyhpLCBuYkNoYW5uZWxzKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMubmJPdXRwdXRzOyBpKyspIHsKICAgICAgICAgICAgICAgIGxldCBuYkNoYW5uZWxzID0gb3V0cHV0c1tpXS5sZW5ndGg7CiAgICAgICAgICAgICAgICBpZiAobmJDaGFubmVscyAhPT0gdGhpcy5vdXRwdXRCdWZmZXJzW2ldLmxlbmd0aCkgewogICAgICAgICAgICAgICAgICAgIHRoaXMuYWxsb2NhdGVPdXRwdXRDaGFubmVscyhpLCBuYkNoYW5uZWxzKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZWFkSW5wdXRzKGlucHV0cykgewogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMubmJJbnB1dHM7IGkrKykgewogICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCB0aGlzLmlucHV0QnVmZmVyc1tpXS5sZW5ndGg7IGorKykgewogICAgICAgICAgICAgICAgICAgIGxldCB3ZWJBdWRpb0Jsb2NrID0gaW5wdXRzW2ldW2pdOwogICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXRCdWZmZXJzW2ldW2pdLnNldCh3ZWJBdWRpb0Jsb2NrLCB0aGlzLmJsb2NrU2l6ZSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgd3JpdGVPdXRwdXRzKG91dHB1dHMpIHsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm5iT3V0cHV0czsgaSsrKSB7CiAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHRoaXMub3V0cHV0QnVmZmVyc1tpXS5sZW5ndGg7IGorKykgewogICAgICAgICAgICAgICAgICAgIGxldCB3ZWJBdWRpb0Jsb2NrID0gb3V0cHV0c1tpXVtqXTsKICAgICAgICAgICAgICAgICAgICB3ZWJBdWRpb0Jsb2NrLnNldCh0aGlzLm91dHB1dEJ1ZmZlcnNbaV1bal0uc3ViYXJyYXkoMCwgV0VCQVVESU9fQkxPQ0tfU0laRSkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHNoaWZ0SW5wdXRCdWZmZXJzKCkgewogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMubmJJbnB1dHM7IGkrKykgewogICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCB0aGlzLmlucHV0QnVmZmVyc1tpXS5sZW5ndGg7IGorKykgewogICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXRCdWZmZXJzW2ldW2pdLmNvcHlXaXRoaW4oMCwgV0VCQVVESU9fQkxPQ0tfU0laRSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgc2hpZnRPdXRwdXRCdWZmZXJzKCkgewogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMubmJPdXRwdXRzOyBpKyspIHsKICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgdGhpcy5vdXRwdXRCdWZmZXJzW2ldLmxlbmd0aDsgaisrKSB7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5vdXRwdXRCdWZmZXJzW2ldW2pdLmNvcHlXaXRoaW4oMCwgV0VCQVVESU9fQkxPQ0tfU0laRSk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5vdXRwdXRCdWZmZXJzW2ldW2pdLmZpbGwoMCwgdGhpcy5ibG9ja1NpemUgLSBXRUJBVURJT19CTE9DS19TSVpFKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBwcmVwYXJlSW5wdXRCdWZmZXJzVG9TZW5kKCkgewogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMubmJJbnB1dHM7IGkrKykgewogICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCB0aGlzLmlucHV0QnVmZmVyc1tpXS5sZW5ndGg7IGorKykgewogICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXRCdWZmZXJzVG9TZW5kW2ldW2pdLnNldCh0aGlzLmlucHV0QnVmZmVyc0hlYWRbaV1bal0pOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGhhbmRsZU91dHB1dEJ1ZmZlcnNUb1JldHJpZXZlKCkgewogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMubmJPdXRwdXRzOyBpKyspIHsKICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgdGhpcy5vdXRwdXRCdWZmZXJzW2ldLmxlbmd0aDsgaisrKSB7CiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgayA9IDA7IGsgPCB0aGlzLmJsb2NrU2l6ZTsgaysrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub3V0cHV0QnVmZmVyc1tpXVtqXVtrXSArPSB0aGlzLm91dHB1dEJ1ZmZlcnNUb1JldHJpZXZlW2ldW2pdW2tdIC8gdGhpcy5uYk92ZXJsYXBzOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBwcm9jZXNzKGlucHV0cywgb3V0cHV0cywgcGFyYW1ldGVycykgewogICAgICAgICAgICB0aGlzLnJlYWxsb2NhdGVDaGFubmVsc0lmTmVlZGVkKGlucHV0cywgb3V0cHV0cyk7CiAgICAgICAgICAgIHRoaXMucmVhZElucHV0cyhpbnB1dHMpOwogICAgICAgICAgICB0aGlzLnNoaWZ0SW5wdXRCdWZmZXJzKCk7CiAgICAgICAgICAgIHRoaXMucHJlcGFyZUlucHV0QnVmZmVyc1RvU2VuZCgpOwogICAgICAgICAgICB0aGlzLnByb2Nlc3NPTEEodGhpcy5pbnB1dEJ1ZmZlcnNUb1NlbmQsIHRoaXMub3V0cHV0QnVmZmVyc1RvUmV0cmlldmUsIHBhcmFtZXRlcnMpOwogICAgICAgICAgICB0aGlzLmhhbmRsZU91dHB1dEJ1ZmZlcnNUb1JldHJpZXZlKCk7CiAgICAgICAgICAgIHRoaXMud3JpdGVPdXRwdXRzKG91dHB1dHMpOwogICAgICAgICAgICB0aGlzLnNoaWZ0T3V0cHV0QnVmZmVycygpOwogICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICB9CgogICAgZnVuY3Rpb24gZ2V0RGVmYXVsdEV4cG9ydEZyb21DanMgKHgpIHsKICAgIAlyZXR1cm4geCAmJiB4Ll9fZXNNb2R1bGUgJiYgT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHgsICdkZWZhdWx0JykgPyB4WydkZWZhdWx0J10gOiB4OwogICAgfQoKICAgIGZ1bmN0aW9uIEZGVChzaXplKSB7CiAgICAgIHRoaXMuc2l6ZSA9IHNpemUgfCAwOwogICAgICBpZiAodGhpcy5zaXplIDw9IDEgfHwgKHRoaXMuc2l6ZSAmICh0aGlzLnNpemUgLSAxKSkgIT09IDApCiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdGRlQgc2l6ZSBtdXN0IGJlIGEgcG93ZXIgb2YgdHdvIGFuZCBiaWdnZXIgdGhhbiAxJyk7CgogICAgICB0aGlzLl9jc2l6ZSA9IHNpemUgPDwgMTsKCiAgICAgIC8vIE5PVEU6IFVzZSBvZiBgdmFyYCBpcyBpbnRlbnRpb25hbCBmb3Igb2xkIFY4IHZlcnNpb25zCiAgICAgIHZhciB0YWJsZSA9IG5ldyBBcnJheSh0aGlzLnNpemUgKiAyKTsKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0YWJsZS5sZW5ndGg7IGkgKz0gMikgewogICAgICAgIGNvbnN0IGFuZ2xlID0gTWF0aC5QSSAqIGkgLyB0aGlzLnNpemU7CiAgICAgICAgdGFibGVbaV0gPSBNYXRoLmNvcyhhbmdsZSk7CiAgICAgICAgdGFibGVbaSArIDFdID0gLU1hdGguc2luKGFuZ2xlKTsKICAgICAgfQogICAgICB0aGlzLnRhYmxlID0gdGFibGU7CgogICAgICAvLyBGaW5kIHNpemUncyBwb3dlciBvZiB0d28KICAgICAgdmFyIHBvd2VyID0gMDsKICAgICAgZm9yICh2YXIgdCA9IDE7IHRoaXMuc2l6ZSA+IHQ7IHQgPDw9IDEpCiAgICAgICAgcG93ZXIrKzsKCiAgICAgIC8vIENhbGN1bGF0ZSBpbml0aWFsIHN0ZXAncyB3aWR0aDoKICAgICAgLy8gICAqIElmIHdlIGFyZSBmdWxsIHJhZGl4LTQgLSBpdCBpcyAyeCBzbWFsbGVyIHRvIGdpdmUgaW5pdGFsIGxlbj04CiAgICAgIC8vICAgKiBPdGhlcndpc2UgaXQgaXMgdGhlIHNhbWUgYXMgYHBvd2VyYCB0byBnaXZlIGxlbj00CiAgICAgIHRoaXMuX3dpZHRoID0gcG93ZXIgJSAyID09PSAwID8gcG93ZXIgLSAxIDogcG93ZXI7CgogICAgICAvLyBQcmUtY29tcHV0ZSBiaXQtcmV2ZXJzYWwgcGF0dGVybnMKICAgICAgdGhpcy5fYml0cmV2ID0gbmV3IEFycmF5KDEgPDwgdGhpcy5fd2lkdGgpOwogICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHRoaXMuX2JpdHJldi5sZW5ndGg7IGorKykgewogICAgICAgIHRoaXMuX2JpdHJldltqXSA9IDA7CiAgICAgICAgZm9yICh2YXIgc2hpZnQgPSAwOyBzaGlmdCA8IHRoaXMuX3dpZHRoOyBzaGlmdCArPSAyKSB7CiAgICAgICAgICB2YXIgcmV2U2hpZnQgPSB0aGlzLl93aWR0aCAtIHNoaWZ0IC0gMjsKICAgICAgICAgIHRoaXMuX2JpdHJldltqXSB8PSAoKGogPj4+IHNoaWZ0KSAmIDMpIDw8IHJldlNoaWZ0OwogICAgICAgIH0KICAgICAgfQoKICAgICAgdGhpcy5fb3V0ID0gbnVsbDsKICAgICAgdGhpcy5fZGF0YSA9IG51bGw7CiAgICAgIHRoaXMuX2ludiA9IDA7CiAgICB9CiAgICB2YXIgZmZ0ID0gRkZUOwoKICAgIEZGVC5wcm90b3R5cGUuZnJvbUNvbXBsZXhBcnJheSA9IGZ1bmN0aW9uIGZyb21Db21wbGV4QXJyYXkoY29tcGxleCwgc3RvcmFnZSkgewogICAgICB2YXIgcmVzID0gc3RvcmFnZSB8fCBuZXcgQXJyYXkoY29tcGxleC5sZW5ndGggPj4+IDEpOwogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvbXBsZXgubGVuZ3RoOyBpICs9IDIpCiAgICAgICAgcmVzW2kgPj4+IDFdID0gY29tcGxleFtpXTsKICAgICAgcmV0dXJuIHJlczsKICAgIH07CgogICAgRkZULnByb3RvdHlwZS5jcmVhdGVDb21wbGV4QXJyYXkgPSBmdW5jdGlvbiBjcmVhdGVDb21wbGV4QXJyYXkoKSB7CiAgICAgIGNvbnN0IHJlcyA9IG5ldyBBcnJheSh0aGlzLl9jc2l6ZSk7CiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmVzLmxlbmd0aDsgaSsrKQogICAgICAgIHJlc1tpXSA9IDA7CiAgICAgIHJldHVybiByZXM7CiAgICB9OwoKICAgIEZGVC5wcm90b3R5cGUudG9Db21wbGV4QXJyYXkgPSBmdW5jdGlvbiB0b0NvbXBsZXhBcnJheShpbnB1dCwgc3RvcmFnZSkgewogICAgICB2YXIgcmVzID0gc3RvcmFnZSB8fCB0aGlzLmNyZWF0ZUNvbXBsZXhBcnJheSgpOwogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJlcy5sZW5ndGg7IGkgKz0gMikgewogICAgICAgIHJlc1tpXSA9IGlucHV0W2kgPj4+IDFdOwogICAgICAgIHJlc1tpICsgMV0gPSAwOwogICAgICB9CiAgICAgIHJldHVybiByZXM7CiAgICB9OwoKICAgIEZGVC5wcm90b3R5cGUuY29tcGxldGVTcGVjdHJ1bSA9IGZ1bmN0aW9uIGNvbXBsZXRlU3BlY3RydW0oc3BlY3RydW0pIHsKICAgICAgdmFyIHNpemUgPSB0aGlzLl9jc2l6ZTsKICAgICAgdmFyIGhhbGYgPSBzaXplID4+PiAxOwogICAgICBmb3IgKHZhciBpID0gMjsgaSA8IGhhbGY7IGkgKz0gMikgewogICAgICAgIHNwZWN0cnVtW3NpemUgLSBpXSA9IHNwZWN0cnVtW2ldOwogICAgICAgIHNwZWN0cnVtW3NpemUgLSBpICsgMV0gPSAtc3BlY3RydW1baSArIDFdOwogICAgICB9CiAgICB9OwoKICAgIEZGVC5wcm90b3R5cGUudHJhbnNmb3JtID0gZnVuY3Rpb24gdHJhbnNmb3JtKG91dCwgZGF0YSkgewogICAgICBpZiAob3V0ID09PSBkYXRhKQogICAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgYW5kIG91dHB1dCBidWZmZXJzIG11c3QgYmUgZGlmZmVyZW50Jyk7CgogICAgICB0aGlzLl9vdXQgPSBvdXQ7CiAgICAgIHRoaXMuX2RhdGEgPSBkYXRhOwogICAgICB0aGlzLl9pbnYgPSAwOwogICAgICB0aGlzLl90cmFuc2Zvcm00KCk7CiAgICAgIHRoaXMuX291dCA9IG51bGw7CiAgICAgIHRoaXMuX2RhdGEgPSBudWxsOwogICAgfTsKCiAgICBGRlQucHJvdG90eXBlLnJlYWxUcmFuc2Zvcm0gPSBmdW5jdGlvbiByZWFsVHJhbnNmb3JtKG91dCwgZGF0YSkgewogICAgICBpZiAob3V0ID09PSBkYXRhKQogICAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgYW5kIG91dHB1dCBidWZmZXJzIG11c3QgYmUgZGlmZmVyZW50Jyk7CgogICAgICB0aGlzLl9vdXQgPSBvdXQ7CiAgICAgIHRoaXMuX2RhdGEgPSBkYXRhOwogICAgICB0aGlzLl9pbnYgPSAwOwogICAgICB0aGlzLl9yZWFsVHJhbnNmb3JtNCgpOwogICAgICB0aGlzLl9vdXQgPSBudWxsOwogICAgICB0aGlzLl9kYXRhID0gbnVsbDsKICAgIH07CgogICAgRkZULnByb3RvdHlwZS5pbnZlcnNlVHJhbnNmb3JtID0gZnVuY3Rpb24gaW52ZXJzZVRyYW5zZm9ybShvdXQsIGRhdGEpIHsKICAgICAgaWYgKG91dCA9PT0gZGF0YSkKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IGFuZCBvdXRwdXQgYnVmZmVycyBtdXN0IGJlIGRpZmZlcmVudCcpOwoKICAgICAgdGhpcy5fb3V0ID0gb3V0OwogICAgICB0aGlzLl9kYXRhID0gZGF0YTsKICAgICAgdGhpcy5faW52ID0gMTsKICAgICAgdGhpcy5fdHJhbnNmb3JtNCgpOwogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG91dC5sZW5ndGg7IGkrKykKICAgICAgICBvdXRbaV0gLz0gdGhpcy5zaXplOwogICAgICB0aGlzLl9vdXQgPSBudWxsOwogICAgICB0aGlzLl9kYXRhID0gbnVsbDsKICAgIH07CgogICAgLy8gcmFkaXgtNCBpbXBsZW1lbnRhdGlvbgogICAgLy8KICAgIC8vIE5PVEU6IFVzZXMgb2YgYHZhcmAgYXJlIGludGVudGlvbmFsIGZvciBvbGRlciBWOCB2ZXJzaW9uIHRoYXQgZG8gbm90CiAgICAvLyBzdXBwb3J0IGJvdGggYGxldCBjb21wb3VuZCBhc3NpZ25tZW50c2AgYW5kIGBjb25zdCBwaGlgCiAgICBGRlQucHJvdG90eXBlLl90cmFuc2Zvcm00ID0gZnVuY3Rpb24gX3RyYW5zZm9ybTQoKSB7CiAgICAgIHZhciBvdXQgPSB0aGlzLl9vdXQ7CiAgICAgIHZhciBzaXplID0gdGhpcy5fY3NpemU7CgogICAgICAvLyBJbml0aWFsIHN0ZXAgKHBlcm11dGUgYW5kIHRyYW5zZm9ybSkKICAgICAgdmFyIHdpZHRoID0gdGhpcy5fd2lkdGg7CiAgICAgIHZhciBzdGVwID0gMSA8PCB3aWR0aDsKICAgICAgdmFyIGxlbiA9IChzaXplIC8gc3RlcCkgPDwgMTsKCiAgICAgIHZhciBvdXRPZmY7CiAgICAgIHZhciB0OwogICAgICB2YXIgYml0cmV2ID0gdGhpcy5fYml0cmV2OwogICAgICBpZiAobGVuID09PSA0KSB7CiAgICAgICAgZm9yIChvdXRPZmYgPSAwLCB0ID0gMDsgb3V0T2ZmIDwgc2l6ZTsgb3V0T2ZmICs9IGxlbiwgdCsrKSB7CiAgICAgICAgICBjb25zdCBvZmYgPSBiaXRyZXZbdF07CiAgICAgICAgICB0aGlzLl9zaW5nbGVUcmFuc2Zvcm0yKG91dE9mZiwgb2ZmLCBzdGVwKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgLy8gbGVuID09PSA4CiAgICAgICAgZm9yIChvdXRPZmYgPSAwLCB0ID0gMDsgb3V0T2ZmIDwgc2l6ZTsgb3V0T2ZmICs9IGxlbiwgdCsrKSB7CiAgICAgICAgICBjb25zdCBvZmYgPSBiaXRyZXZbdF07CiAgICAgICAgICB0aGlzLl9zaW5nbGVUcmFuc2Zvcm00KG91dE9mZiwgb2ZmLCBzdGVwKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIC8vIExvb3AgdGhyb3VnaCBzdGVwcyBpbiBkZWNyZWFzaW5nIG9yZGVyCiAgICAgIHZhciBpbnYgPSB0aGlzLl9pbnYgPyAtMSA6IDE7CiAgICAgIHZhciB0YWJsZSA9IHRoaXMudGFibGU7CiAgICAgIGZvciAoc3RlcCA+Pj0gMjsgc3RlcCA+PSAyOyBzdGVwID4+PSAyKSB7CiAgICAgICAgbGVuID0gKHNpemUgLyBzdGVwKSA8PCAxOwogICAgICAgIHZhciBxdWFydGVyTGVuID0gbGVuID4+PiAyOwoKICAgICAgICAvLyBMb29wIHRocm91Z2ggb2Zmc2V0cyBpbiB0aGUgZGF0YQogICAgICAgIGZvciAob3V0T2ZmID0gMDsgb3V0T2ZmIDwgc2l6ZTsgb3V0T2ZmICs9IGxlbikgewogICAgICAgICAgLy8gRnVsbCBjYXNlCiAgICAgICAgICB2YXIgbGltaXQgPSBvdXRPZmYgKyBxdWFydGVyTGVuOwogICAgICAgICAgZm9yICh2YXIgaSA9IG91dE9mZiwgayA9IDA7IGkgPCBsaW1pdDsgaSArPSAyLCBrICs9IHN0ZXApIHsKICAgICAgICAgICAgY29uc3QgQSA9IGk7CiAgICAgICAgICAgIGNvbnN0IEIgPSBBICsgcXVhcnRlckxlbjsKICAgICAgICAgICAgY29uc3QgQyA9IEIgKyBxdWFydGVyTGVuOwogICAgICAgICAgICBjb25zdCBEID0gQyArIHF1YXJ0ZXJMZW47CgogICAgICAgICAgICAvLyBPcmlnaW5hbCB2YWx1ZXMKICAgICAgICAgICAgY29uc3QgQXIgPSBvdXRbQV07CiAgICAgICAgICAgIGNvbnN0IEFpID0gb3V0W0EgKyAxXTsKICAgICAgICAgICAgY29uc3QgQnIgPSBvdXRbQl07CiAgICAgICAgICAgIGNvbnN0IEJpID0gb3V0W0IgKyAxXTsKICAgICAgICAgICAgY29uc3QgQ3IgPSBvdXRbQ107CiAgICAgICAgICAgIGNvbnN0IENpID0gb3V0W0MgKyAxXTsKICAgICAgICAgICAgY29uc3QgRHIgPSBvdXRbRF07CiAgICAgICAgICAgIGNvbnN0IERpID0gb3V0W0QgKyAxXTsKCiAgICAgICAgICAgIC8vIE1pZGRsZSB2YWx1ZXMKICAgICAgICAgICAgY29uc3QgTUFyID0gQXI7CiAgICAgICAgICAgIGNvbnN0IE1BaSA9IEFpOwoKICAgICAgICAgICAgY29uc3QgdGFibGVCciA9IHRhYmxlW2tdOwogICAgICAgICAgICBjb25zdCB0YWJsZUJpID0gaW52ICogdGFibGVbayArIDFdOwogICAgICAgICAgICBjb25zdCBNQnIgPSBCciAqIHRhYmxlQnIgLSBCaSAqIHRhYmxlQmk7CiAgICAgICAgICAgIGNvbnN0IE1CaSA9IEJyICogdGFibGVCaSArIEJpICogdGFibGVCcjsKCiAgICAgICAgICAgIGNvbnN0IHRhYmxlQ3IgPSB0YWJsZVsyICoga107CiAgICAgICAgICAgIGNvbnN0IHRhYmxlQ2kgPSBpbnYgKiB0YWJsZVsyICogayArIDFdOwogICAgICAgICAgICBjb25zdCBNQ3IgPSBDciAqIHRhYmxlQ3IgLSBDaSAqIHRhYmxlQ2k7CiAgICAgICAgICAgIGNvbnN0IE1DaSA9IENyICogdGFibGVDaSArIENpICogdGFibGVDcjsKCiAgICAgICAgICAgIGNvbnN0IHRhYmxlRHIgPSB0YWJsZVszICoga107CiAgICAgICAgICAgIGNvbnN0IHRhYmxlRGkgPSBpbnYgKiB0YWJsZVszICogayArIDFdOwogICAgICAgICAgICBjb25zdCBNRHIgPSBEciAqIHRhYmxlRHIgLSBEaSAqIHRhYmxlRGk7CiAgICAgICAgICAgIGNvbnN0IE1EaSA9IERyICogdGFibGVEaSArIERpICogdGFibGVEcjsKCiAgICAgICAgICAgIC8vIFByZS1GaW5hbCB2YWx1ZXMKICAgICAgICAgICAgY29uc3QgVDByID0gTUFyICsgTUNyOwogICAgICAgICAgICBjb25zdCBUMGkgPSBNQWkgKyBNQ2k7CiAgICAgICAgICAgIGNvbnN0IFQxciA9IE1BciAtIE1DcjsKICAgICAgICAgICAgY29uc3QgVDFpID0gTUFpIC0gTUNpOwogICAgICAgICAgICBjb25zdCBUMnIgPSBNQnIgKyBNRHI7CiAgICAgICAgICAgIGNvbnN0IFQyaSA9IE1CaSArIE1EaTsKICAgICAgICAgICAgY29uc3QgVDNyID0gaW52ICogKE1CciAtIE1Ecik7CiAgICAgICAgICAgIGNvbnN0IFQzaSA9IGludiAqIChNQmkgLSBNRGkpOwoKICAgICAgICAgICAgLy8gRmluYWwgdmFsdWVzCiAgICAgICAgICAgIGNvbnN0IEZBciA9IFQwciArIFQycjsKICAgICAgICAgICAgY29uc3QgRkFpID0gVDBpICsgVDJpOwoKICAgICAgICAgICAgY29uc3QgRkNyID0gVDByIC0gVDJyOwogICAgICAgICAgICBjb25zdCBGQ2kgPSBUMGkgLSBUMmk7CgogICAgICAgICAgICBjb25zdCBGQnIgPSBUMXIgKyBUM2k7CiAgICAgICAgICAgIGNvbnN0IEZCaSA9IFQxaSAtIFQzcjsKCiAgICAgICAgICAgIGNvbnN0IEZEciA9IFQxciAtIFQzaTsKICAgICAgICAgICAgY29uc3QgRkRpID0gVDFpICsgVDNyOwoKICAgICAgICAgICAgb3V0W0FdID0gRkFyOwogICAgICAgICAgICBvdXRbQSArIDFdID0gRkFpOwogICAgICAgICAgICBvdXRbQl0gPSBGQnI7CiAgICAgICAgICAgIG91dFtCICsgMV0gPSBGQmk7CiAgICAgICAgICAgIG91dFtDXSA9IEZDcjsKICAgICAgICAgICAgb3V0W0MgKyAxXSA9IEZDaTsKICAgICAgICAgICAgb3V0W0RdID0gRkRyOwogICAgICAgICAgICBvdXRbRCArIDFdID0gRkRpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfTsKCiAgICAvLyByYWRpeC0yIGltcGxlbWVudGF0aW9uCiAgICAvLwogICAgLy8gTk9URTogT25seSBjYWxsZWQgZm9yIGxlbj00CiAgICBGRlQucHJvdG90eXBlLl9zaW5nbGVUcmFuc2Zvcm0yID0gZnVuY3Rpb24gX3NpbmdsZVRyYW5zZm9ybTIob3V0T2ZmLCBvZmYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RlcCkgewogICAgICBjb25zdCBvdXQgPSB0aGlzLl9vdXQ7CiAgICAgIGNvbnN0IGRhdGEgPSB0aGlzLl9kYXRhOwoKICAgICAgY29uc3QgZXZlblIgPSBkYXRhW29mZl07CiAgICAgIGNvbnN0IGV2ZW5JID0gZGF0YVtvZmYgKyAxXTsKICAgICAgY29uc3Qgb2RkUiA9IGRhdGFbb2ZmICsgc3RlcF07CiAgICAgIGNvbnN0IG9kZEkgPSBkYXRhW29mZiArIHN0ZXAgKyAxXTsKCiAgICAgIGNvbnN0IGxlZnRSID0gZXZlblIgKyBvZGRSOwogICAgICBjb25zdCBsZWZ0SSA9IGV2ZW5JICsgb2RkSTsKICAgICAgY29uc3QgcmlnaHRSID0gZXZlblIgLSBvZGRSOwogICAgICBjb25zdCByaWdodEkgPSBldmVuSSAtIG9kZEk7CgogICAgICBvdXRbb3V0T2ZmXSA9IGxlZnRSOwogICAgICBvdXRbb3V0T2ZmICsgMV0gPSBsZWZ0STsKICAgICAgb3V0W291dE9mZiArIDJdID0gcmlnaHRSOwogICAgICBvdXRbb3V0T2ZmICsgM10gPSByaWdodEk7CiAgICB9OwoKICAgIC8vIHJhZGl4LTQKICAgIC8vCiAgICAvLyBOT1RFOiBPbmx5IGNhbGxlZCBmb3IgbGVuPTgKICAgIEZGVC5wcm90b3R5cGUuX3NpbmdsZVRyYW5zZm9ybTQgPSBmdW5jdGlvbiBfc2luZ2xlVHJhbnNmb3JtNChvdXRPZmYsIG9mZiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGVwKSB7CiAgICAgIGNvbnN0IG91dCA9IHRoaXMuX291dDsKICAgICAgY29uc3QgZGF0YSA9IHRoaXMuX2RhdGE7CiAgICAgIGNvbnN0IGludiA9IHRoaXMuX2ludiA/IC0xIDogMTsKICAgICAgY29uc3Qgc3RlcDIgPSBzdGVwICogMjsKICAgICAgY29uc3Qgc3RlcDMgPSBzdGVwICogMzsKCiAgICAgIC8vIE9yaWdpbmFsIHZhbHVlcwogICAgICBjb25zdCBBciA9IGRhdGFbb2ZmXTsKICAgICAgY29uc3QgQWkgPSBkYXRhW29mZiArIDFdOwogICAgICBjb25zdCBCciA9IGRhdGFbb2ZmICsgc3RlcF07CiAgICAgIGNvbnN0IEJpID0gZGF0YVtvZmYgKyBzdGVwICsgMV07CiAgICAgIGNvbnN0IENyID0gZGF0YVtvZmYgKyBzdGVwMl07CiAgICAgIGNvbnN0IENpID0gZGF0YVtvZmYgKyBzdGVwMiArIDFdOwogICAgICBjb25zdCBEciA9IGRhdGFbb2ZmICsgc3RlcDNdOwogICAgICBjb25zdCBEaSA9IGRhdGFbb2ZmICsgc3RlcDMgKyAxXTsKCiAgICAgIC8vIFByZS1GaW5hbCB2YWx1ZXMKICAgICAgY29uc3QgVDByID0gQXIgKyBDcjsKICAgICAgY29uc3QgVDBpID0gQWkgKyBDaTsKICAgICAgY29uc3QgVDFyID0gQXIgLSBDcjsKICAgICAgY29uc3QgVDFpID0gQWkgLSBDaTsKICAgICAgY29uc3QgVDJyID0gQnIgKyBEcjsKICAgICAgY29uc3QgVDJpID0gQmkgKyBEaTsKICAgICAgY29uc3QgVDNyID0gaW52ICogKEJyIC0gRHIpOwogICAgICBjb25zdCBUM2kgPSBpbnYgKiAoQmkgLSBEaSk7CgogICAgICAvLyBGaW5hbCB2YWx1ZXMKICAgICAgY29uc3QgRkFyID0gVDByICsgVDJyOwogICAgICBjb25zdCBGQWkgPSBUMGkgKyBUMmk7CgogICAgICBjb25zdCBGQnIgPSBUMXIgKyBUM2k7CiAgICAgIGNvbnN0IEZCaSA9IFQxaSAtIFQzcjsKCiAgICAgIGNvbnN0IEZDciA9IFQwciAtIFQycjsKICAgICAgY29uc3QgRkNpID0gVDBpIC0gVDJpOwoKICAgICAgY29uc3QgRkRyID0gVDFyIC0gVDNpOwogICAgICBjb25zdCBGRGkgPSBUMWkgKyBUM3I7CgogICAgICBvdXRbb3V0T2ZmXSA9IEZBcjsKICAgICAgb3V0W291dE9mZiArIDFdID0gRkFpOwogICAgICBvdXRbb3V0T2ZmICsgMl0gPSBGQnI7CiAgICAgIG91dFtvdXRPZmYgKyAzXSA9IEZCaTsKICAgICAgb3V0W291dE9mZiArIDRdID0gRkNyOwogICAgICBvdXRbb3V0T2ZmICsgNV0gPSBGQ2k7CiAgICAgIG91dFtvdXRPZmYgKyA2XSA9IEZEcjsKICAgICAgb3V0W291dE9mZiArIDddID0gRkRpOwogICAgfTsKCiAgICAvLyBSZWFsIGlucHV0IHJhZGl4LTQgaW1wbGVtZW50YXRpb24KICAgIEZGVC5wcm90b3R5cGUuX3JlYWxUcmFuc2Zvcm00ID0gZnVuY3Rpb24gX3JlYWxUcmFuc2Zvcm00KCkgewogICAgICB2YXIgb3V0ID0gdGhpcy5fb3V0OwogICAgICB2YXIgc2l6ZSA9IHRoaXMuX2NzaXplOwoKICAgICAgLy8gSW5pdGlhbCBzdGVwIChwZXJtdXRlIGFuZCB0cmFuc2Zvcm0pCiAgICAgIHZhciB3aWR0aCA9IHRoaXMuX3dpZHRoOwogICAgICB2YXIgc3RlcCA9IDEgPDwgd2lkdGg7CiAgICAgIHZhciBsZW4gPSAoc2l6ZSAvIHN0ZXApIDw8IDE7CgogICAgICB2YXIgb3V0T2ZmOwogICAgICB2YXIgdDsKICAgICAgdmFyIGJpdHJldiA9IHRoaXMuX2JpdHJldjsKICAgICAgaWYgKGxlbiA9PT0gNCkgewogICAgICAgIGZvciAob3V0T2ZmID0gMCwgdCA9IDA7IG91dE9mZiA8IHNpemU7IG91dE9mZiArPSBsZW4sIHQrKykgewogICAgICAgICAgY29uc3Qgb2ZmID0gYml0cmV2W3RdOwogICAgICAgICAgdGhpcy5fc2luZ2xlUmVhbFRyYW5zZm9ybTIob3V0T2ZmLCBvZmYgPj4+IDEsIHN0ZXAgPj4+IDEpOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICAvLyBsZW4gPT09IDgKICAgICAgICBmb3IgKG91dE9mZiA9IDAsIHQgPSAwOyBvdXRPZmYgPCBzaXplOyBvdXRPZmYgKz0gbGVuLCB0KyspIHsKICAgICAgICAgIGNvbnN0IG9mZiA9IGJpdHJldlt0XTsKICAgICAgICAgIHRoaXMuX3NpbmdsZVJlYWxUcmFuc2Zvcm00KG91dE9mZiwgb2ZmID4+PiAxLCBzdGVwID4+PiAxKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIC8vIExvb3AgdGhyb3VnaCBzdGVwcyBpbiBkZWNyZWFzaW5nIG9yZGVyCiAgICAgIHZhciBpbnYgPSB0aGlzLl9pbnYgPyAtMSA6IDE7CiAgICAgIHZhciB0YWJsZSA9IHRoaXMudGFibGU7CiAgICAgIGZvciAoc3RlcCA+Pj0gMjsgc3RlcCA+PSAyOyBzdGVwID4+PSAyKSB7CiAgICAgICAgbGVuID0gKHNpemUgLyBzdGVwKSA8PCAxOwogICAgICAgIHZhciBoYWxmTGVuID0gbGVuID4+PiAxOwogICAgICAgIHZhciBxdWFydGVyTGVuID0gaGFsZkxlbiA+Pj4gMTsKICAgICAgICB2YXIgaHF1YXJ0ZXJMZW4gPSBxdWFydGVyTGVuID4+PiAxOwoKICAgICAgICAvLyBMb29wIHRocm91Z2ggb2Zmc2V0cyBpbiB0aGUgZGF0YQogICAgICAgIGZvciAob3V0T2ZmID0gMDsgb3V0T2ZmIDwgc2l6ZTsgb3V0T2ZmICs9IGxlbikgewogICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGsgPSAwOyBpIDw9IGhxdWFydGVyTGVuOyBpICs9IDIsIGsgKz0gc3RlcCkgewogICAgICAgICAgICB2YXIgQSA9IG91dE9mZiArIGk7CiAgICAgICAgICAgIHZhciBCID0gQSArIHF1YXJ0ZXJMZW47CiAgICAgICAgICAgIHZhciBDID0gQiArIHF1YXJ0ZXJMZW47CiAgICAgICAgICAgIHZhciBEID0gQyArIHF1YXJ0ZXJMZW47CgogICAgICAgICAgICAvLyBPcmlnaW5hbCB2YWx1ZXMKICAgICAgICAgICAgdmFyIEFyID0gb3V0W0FdOwogICAgICAgICAgICB2YXIgQWkgPSBvdXRbQSArIDFdOwogICAgICAgICAgICB2YXIgQnIgPSBvdXRbQl07CiAgICAgICAgICAgIHZhciBCaSA9IG91dFtCICsgMV07CiAgICAgICAgICAgIHZhciBDciA9IG91dFtDXTsKICAgICAgICAgICAgdmFyIENpID0gb3V0W0MgKyAxXTsKICAgICAgICAgICAgdmFyIERyID0gb3V0W0RdOwogICAgICAgICAgICB2YXIgRGkgPSBvdXRbRCArIDFdOwoKICAgICAgICAgICAgLy8gTWlkZGxlIHZhbHVlcwogICAgICAgICAgICB2YXIgTUFyID0gQXI7CiAgICAgICAgICAgIHZhciBNQWkgPSBBaTsKCiAgICAgICAgICAgIHZhciB0YWJsZUJyID0gdGFibGVba107CiAgICAgICAgICAgIHZhciB0YWJsZUJpID0gaW52ICogdGFibGVbayArIDFdOwogICAgICAgICAgICB2YXIgTUJyID0gQnIgKiB0YWJsZUJyIC0gQmkgKiB0YWJsZUJpOwogICAgICAgICAgICB2YXIgTUJpID0gQnIgKiB0YWJsZUJpICsgQmkgKiB0YWJsZUJyOwoKICAgICAgICAgICAgdmFyIHRhYmxlQ3IgPSB0YWJsZVsyICoga107CiAgICAgICAgICAgIHZhciB0YWJsZUNpID0gaW52ICogdGFibGVbMiAqIGsgKyAxXTsKICAgICAgICAgICAgdmFyIE1DciA9IENyICogdGFibGVDciAtIENpICogdGFibGVDaTsKICAgICAgICAgICAgdmFyIE1DaSA9IENyICogdGFibGVDaSArIENpICogdGFibGVDcjsKCiAgICAgICAgICAgIHZhciB0YWJsZURyID0gdGFibGVbMyAqIGtdOwogICAgICAgICAgICB2YXIgdGFibGVEaSA9IGludiAqIHRhYmxlWzMgKiBrICsgMV07CiAgICAgICAgICAgIHZhciBNRHIgPSBEciAqIHRhYmxlRHIgLSBEaSAqIHRhYmxlRGk7CiAgICAgICAgICAgIHZhciBNRGkgPSBEciAqIHRhYmxlRGkgKyBEaSAqIHRhYmxlRHI7CgogICAgICAgICAgICAvLyBQcmUtRmluYWwgdmFsdWVzCiAgICAgICAgICAgIHZhciBUMHIgPSBNQXIgKyBNQ3I7CiAgICAgICAgICAgIHZhciBUMGkgPSBNQWkgKyBNQ2k7CiAgICAgICAgICAgIHZhciBUMXIgPSBNQXIgLSBNQ3I7CiAgICAgICAgICAgIHZhciBUMWkgPSBNQWkgLSBNQ2k7CiAgICAgICAgICAgIHZhciBUMnIgPSBNQnIgKyBNRHI7CiAgICAgICAgICAgIHZhciBUMmkgPSBNQmkgKyBNRGk7CiAgICAgICAgICAgIHZhciBUM3IgPSBpbnYgKiAoTUJyIC0gTURyKTsKICAgICAgICAgICAgdmFyIFQzaSA9IGludiAqIChNQmkgLSBNRGkpOwoKICAgICAgICAgICAgLy8gRmluYWwgdmFsdWVzCiAgICAgICAgICAgIHZhciBGQXIgPSBUMHIgKyBUMnI7CiAgICAgICAgICAgIHZhciBGQWkgPSBUMGkgKyBUMmk7CgogICAgICAgICAgICB2YXIgRkJyID0gVDFyICsgVDNpOwogICAgICAgICAgICB2YXIgRkJpID0gVDFpIC0gVDNyOwoKICAgICAgICAgICAgb3V0W0FdID0gRkFyOwogICAgICAgICAgICBvdXRbQSArIDFdID0gRkFpOwogICAgICAgICAgICBvdXRbQl0gPSBGQnI7CiAgICAgICAgICAgIG91dFtCICsgMV0gPSBGQmk7CgogICAgICAgICAgICAvLyBPdXRwdXQgZmluYWwgbWlkZGxlIHBvaW50CiAgICAgICAgICAgIGlmIChpID09PSAwKSB7CiAgICAgICAgICAgICAgdmFyIEZDciA9IFQwciAtIFQycjsKICAgICAgICAgICAgICB2YXIgRkNpID0gVDBpIC0gVDJpOwogICAgICAgICAgICAgIG91dFtDXSA9IEZDcjsKICAgICAgICAgICAgICBvdXRbQyArIDFdID0gRkNpOwogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CgogICAgICAgICAgICAvLyBEbyBub3Qgb3ZlcndyaXRlIG91cnNlbHZlcwogICAgICAgICAgICBpZiAoaSA9PT0gaHF1YXJ0ZXJMZW4pCiAgICAgICAgICAgICAgY29udGludWU7CgogICAgICAgICAgICAvLyBJbiB0aGUgZmxpcHBlZCBjYXNlOgogICAgICAgICAgICAvLyBNQWkgPSAtTUFpCiAgICAgICAgICAgIC8vIE1Ccj0tTUJpLCBNQmk9LU1CcgogICAgICAgICAgICAvLyBNQ3I9LU1DcgogICAgICAgICAgICAvLyBNRHI9TURpLCBNRGk9TURyCiAgICAgICAgICAgIHZhciBTVDByID0gVDFyOwogICAgICAgICAgICB2YXIgU1QwaSA9IC1UMWk7CiAgICAgICAgICAgIHZhciBTVDFyID0gVDByOwogICAgICAgICAgICB2YXIgU1QxaSA9IC1UMGk7CiAgICAgICAgICAgIHZhciBTVDJyID0gLWludiAqIFQzaTsKICAgICAgICAgICAgdmFyIFNUMmkgPSAtaW52ICogVDNyOwogICAgICAgICAgICB2YXIgU1QzciA9IC1pbnYgKiBUMmk7CiAgICAgICAgICAgIHZhciBTVDNpID0gLWludiAqIFQycjsKCiAgICAgICAgICAgIHZhciBTRkFyID0gU1QwciArIFNUMnI7CiAgICAgICAgICAgIHZhciBTRkFpID0gU1QwaSArIFNUMmk7CgogICAgICAgICAgICB2YXIgU0ZCciA9IFNUMXIgKyBTVDNpOwogICAgICAgICAgICB2YXIgU0ZCaSA9IFNUMWkgLSBTVDNyOwoKICAgICAgICAgICAgdmFyIFNBID0gb3V0T2ZmICsgcXVhcnRlckxlbiAtIGk7CiAgICAgICAgICAgIHZhciBTQiA9IG91dE9mZiArIGhhbGZMZW4gLSBpOwoKICAgICAgICAgICAgb3V0W1NBXSA9IFNGQXI7CiAgICAgICAgICAgIG91dFtTQSArIDFdID0gU0ZBaTsKICAgICAgICAgICAgb3V0W1NCXSA9IFNGQnI7CiAgICAgICAgICAgIG91dFtTQiArIDFdID0gU0ZCaTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH07CgogICAgLy8gcmFkaXgtMiBpbXBsZW1lbnRhdGlvbgogICAgLy8KICAgIC8vIE5PVEU6IE9ubHkgY2FsbGVkIGZvciBsZW49NAogICAgRkZULnByb3RvdHlwZS5fc2luZ2xlUmVhbFRyYW5zZm9ybTIgPSBmdW5jdGlvbiBfc2luZ2xlUmVhbFRyYW5zZm9ybTIob3V0T2ZmLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb2ZmLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RlcCkgewogICAgICBjb25zdCBvdXQgPSB0aGlzLl9vdXQ7CiAgICAgIGNvbnN0IGRhdGEgPSB0aGlzLl9kYXRhOwoKICAgICAgY29uc3QgZXZlblIgPSBkYXRhW29mZl07CiAgICAgIGNvbnN0IG9kZFIgPSBkYXRhW29mZiArIHN0ZXBdOwoKICAgICAgY29uc3QgbGVmdFIgPSBldmVuUiArIG9kZFI7CiAgICAgIGNvbnN0IHJpZ2h0UiA9IGV2ZW5SIC0gb2RkUjsKCiAgICAgIG91dFtvdXRPZmZdID0gbGVmdFI7CiAgICAgIG91dFtvdXRPZmYgKyAxXSA9IDA7CiAgICAgIG91dFtvdXRPZmYgKyAyXSA9IHJpZ2h0UjsKICAgICAgb3V0W291dE9mZiArIDNdID0gMDsKICAgIH07CgogICAgLy8gcmFkaXgtNAogICAgLy8KICAgIC8vIE5PVEU6IE9ubHkgY2FsbGVkIGZvciBsZW49OAogICAgRkZULnByb3RvdHlwZS5fc2luZ2xlUmVhbFRyYW5zZm9ybTQgPSBmdW5jdGlvbiBfc2luZ2xlUmVhbFRyYW5zZm9ybTQob3V0T2ZmLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb2ZmLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RlcCkgewogICAgICBjb25zdCBvdXQgPSB0aGlzLl9vdXQ7CiAgICAgIGNvbnN0IGRhdGEgPSB0aGlzLl9kYXRhOwogICAgICBjb25zdCBpbnYgPSB0aGlzLl9pbnYgPyAtMSA6IDE7CiAgICAgIGNvbnN0IHN0ZXAyID0gc3RlcCAqIDI7CiAgICAgIGNvbnN0IHN0ZXAzID0gc3RlcCAqIDM7CgogICAgICAvLyBPcmlnaW5hbCB2YWx1ZXMKICAgICAgY29uc3QgQXIgPSBkYXRhW29mZl07CiAgICAgIGNvbnN0IEJyID0gZGF0YVtvZmYgKyBzdGVwXTsKICAgICAgY29uc3QgQ3IgPSBkYXRhW29mZiArIHN0ZXAyXTsKICAgICAgY29uc3QgRHIgPSBkYXRhW29mZiArIHN0ZXAzXTsKCiAgICAgIC8vIFByZS1GaW5hbCB2YWx1ZXMKICAgICAgY29uc3QgVDByID0gQXIgKyBDcjsKICAgICAgY29uc3QgVDFyID0gQXIgLSBDcjsKICAgICAgY29uc3QgVDJyID0gQnIgKyBEcjsKICAgICAgY29uc3QgVDNyID0gaW52ICogKEJyIC0gRHIpOwoKICAgICAgLy8gRmluYWwgdmFsdWVzCiAgICAgIGNvbnN0IEZBciA9IFQwciArIFQycjsKCiAgICAgIGNvbnN0IEZCciA9IFQxcjsKICAgICAgY29uc3QgRkJpID0gLVQzcjsKCiAgICAgIGNvbnN0IEZDciA9IFQwciAtIFQycjsKCiAgICAgIGNvbnN0IEZEciA9IFQxcjsKICAgICAgY29uc3QgRkRpID0gVDNyOwoKICAgICAgb3V0W291dE9mZl0gPSBGQXI7CiAgICAgIG91dFtvdXRPZmYgKyAxXSA9IDA7CiAgICAgIG91dFtvdXRPZmYgKyAyXSA9IEZCcjsKICAgICAgb3V0W291dE9mZiArIDNdID0gRkJpOwogICAgICBvdXRbb3V0T2ZmICsgNF0gPSBGQ3I7CiAgICAgIG91dFtvdXRPZmYgKyA1XSA9IDA7CiAgICAgIG91dFtvdXRPZmYgKyA2XSA9IEZEcjsKICAgICAgb3V0W291dE9mZiArIDddID0gRkRpOwogICAgfTsKCiAgICB2YXIgRkZUJDEgPSAvKkBfX1BVUkVfXyovZ2V0RGVmYXVsdEV4cG9ydEZyb21DanMoZmZ0KTsKCiAgICBjb25zdCBCVUZGRVJFRF9CTE9DS19TSVpFID0gMjA0ODsKICAgIGZ1bmN0aW9uIGdlbkhhbm5XaW5kb3cobGVuZ3RoKSB7CiAgICAgICAgbGV0IHdpbiA9IG5ldyBGbG9hdDMyQXJyYXkobGVuZ3RoKTsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIHdpbltpXSA9IDAuNSAqICgxIC0gTWF0aC5jb3MoMiAqIE1hdGguUEkgKiBpIC8gbGVuZ3RoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB3aW47CiAgICB9CiAgICBjbGFzcyBQaGFzZVZvY29kZXJQcm9jZXNzb3IgZXh0ZW5kcyBPTEFQcm9jZXNzb3IgewogICAgICAgIGZmdFNpemU7CiAgICAgICAgdGltZUN1cnNvcjsKICAgICAgICBoYW5uV2luZG93OwogICAgICAgIGZmdDsKICAgICAgICBmcmVxQ29tcGxleEJ1ZmZlcjsKICAgICAgICBmcmVxQ29tcGxleEJ1ZmZlclNoaWZ0ZWQ7CiAgICAgICAgdGltZUNvbXBsZXhCdWZmZXI7CiAgICAgICAgbWFnbml0dWRlczsKICAgICAgICBwZWFrSW5kZXhlczsKICAgICAgICBuYlBlYWtzOwogICAgICAgIHN0YXRpYyBnZXQgcGFyYW1ldGVyRGVzY3JpcHRvcnMoKSB7CiAgICAgICAgICAgIHJldHVybiBbewogICAgICAgICAgICAgICAgICAgIG5hbWU6ICdwaXRjaEZhY3RvcicsCiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdFZhbHVlOiAxLjAKICAgICAgICAgICAgICAgIH1dOwogICAgICAgIH0KICAgICAgICBjb25zdHJ1Y3RvcihvcHRpb25zKSB7CiAgICAgICAgICAgIG9wdGlvbnMucHJvY2Vzc29yT3B0aW9ucyA9IHsKICAgICAgICAgICAgICAgIGJsb2NrU2l6ZTogQlVGRkVSRURfQkxPQ0tfU0laRSwKICAgICAgICAgICAgfTsKICAgICAgICAgICAgc3VwZXIob3B0aW9ucyk7CiAgICAgICAgICAgIHRoaXMuZmZ0U2l6ZSA9IHRoaXMuYmxvY2tTaXplOwogICAgICAgICAgICB0aGlzLnRpbWVDdXJzb3IgPSAwOwogICAgICAgICAgICB0aGlzLmhhbm5XaW5kb3cgPSBnZW5IYW5uV2luZG93KHRoaXMuYmxvY2tTaXplKTsKICAgICAgICAgICAgLy8gcHJlcGFyZSBGRlQgYW5kIHByZS1hbGxvY2F0ZSBidWZmZXJzCiAgICAgICAgICAgIHRoaXMuZmZ0ID0gbmV3IEZGVCQxKHRoaXMuZmZ0U2l6ZSk7CiAgICAgICAgICAgIHRoaXMuZnJlcUNvbXBsZXhCdWZmZXIgPSB0aGlzLmZmdC5jcmVhdGVDb21wbGV4QXJyYXkoKTsKICAgICAgICAgICAgdGhpcy5mcmVxQ29tcGxleEJ1ZmZlclNoaWZ0ZWQgPSB0aGlzLmZmdC5jcmVhdGVDb21wbGV4QXJyYXkoKTsKICAgICAgICAgICAgdGhpcy50aW1lQ29tcGxleEJ1ZmZlciA9IHRoaXMuZmZ0LmNyZWF0ZUNvbXBsZXhBcnJheSgpOwogICAgICAgICAgICB0aGlzLm1hZ25pdHVkZXMgPSBuZXcgRmxvYXQzMkFycmF5KHRoaXMuZmZ0U2l6ZSAvIDIgKyAxKTsKICAgICAgICAgICAgdGhpcy5wZWFrSW5kZXhlcyA9IG5ldyBJbnQzMkFycmF5KHRoaXMubWFnbml0dWRlcy5sZW5ndGgpOwogICAgICAgICAgICB0aGlzLm5iUGVha3MgPSAwOwogICAgICAgIH0KICAgICAgICBwcm9jZXNzT0xBKGlucHV0cywgb3V0cHV0cywgcGFyYW1ldGVycykgewogICAgICAgICAgICAvLyBAdHMtaWdub3JlCiAgICAgICAgICAgIGNvbnN0IHBpdGNoRmFjdG9yID0gcGFyYW1ldGVycy5waXRjaEZhY3RvcltwYXJhbWV0ZXJzLnBpdGNoRmFjdG9yLmxlbmd0aCAtIDFdOwogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMubmJJbnB1dHM7IGkrKykgewogICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBpbnB1dHNbaV0ubGVuZ3RoOyBqKyspIHsKICAgICAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSBpbnB1dHNbaV1bal07CiAgICAgICAgICAgICAgICAgICAgdmFyIG91dHB1dCA9IG91dHB1dHNbaV1bal07CiAgICAgICAgICAgICAgICAgICAgdGhpcy5hcHBseUhhbm5XaW5kb3coaW5wdXQpOwogICAgICAgICAgICAgICAgICAgIHRoaXMuZmZ0LnJlYWxUcmFuc2Zvcm0odGhpcy5mcmVxQ29tcGxleEJ1ZmZlciwgaW5wdXQpOwogICAgICAgICAgICAgICAgICAgIHRoaXMuY29tcHV0ZU1hZ25pdHVkZXMoKTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmZpbmRQZWFrcygpOwogICAgICAgICAgICAgICAgICAgIHRoaXMuc2hpZnRQZWFrcyhwaXRjaEZhY3Rvcik7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5mZnQuY29tcGxldGVTcGVjdHJ1bSh0aGlzLmZyZXFDb21wbGV4QnVmZmVyU2hpZnRlZCk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5mZnQuaW52ZXJzZVRyYW5zZm9ybSh0aGlzLnRpbWVDb21wbGV4QnVmZmVyLCB0aGlzLmZyZXFDb21wbGV4QnVmZmVyU2hpZnRlZCk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5mZnQuZnJvbUNvbXBsZXhBcnJheSh0aGlzLnRpbWVDb21wbGV4QnVmZmVyLCBvdXRwdXQpOwogICAgICAgICAgICAgICAgICAgIHRoaXMuYXBwbHlIYW5uV2luZG93KG91dHB1dCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdGhpcy50aW1lQ3Vyc29yICs9IHRoaXMuaG9wU2l6ZTsKICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgICAgIGFwcGx5SGFubldpbmRvdyhpbnB1dCkgewogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuYmxvY2tTaXplOyBpKyspIHsKICAgICAgICAgICAgICAgIGlucHV0W2ldICo9IHRoaXMuaGFubldpbmRvd1tpXTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBjb21wdXRlTWFnbml0dWRlcygpIHsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDAsIGogPSAwOyBpIDwgdGhpcy5tYWduaXR1ZGVzLmxlbmd0aDsgaSsrLCBqICs9IDIpIHsKICAgICAgICAgICAgICAgIGNvbnN0IHJlYWwgPSB0aGlzLmZyZXFDb21wbGV4QnVmZmVyW2pdOwogICAgICAgICAgICAgICAgY29uc3QgaW1hZyA9IHRoaXMuZnJlcUNvbXBsZXhCdWZmZXJbaiArIDFdOwogICAgICAgICAgICAgICAgdGhpcy5tYWduaXR1ZGVzW2ldID0gcmVhbCAqKiAyICsgaW1hZyAqKiAyOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGZpbmRQZWFrcygpIHsKICAgICAgICAgICAgdGhpcy5uYlBlYWtzID0gMDsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDIsIGVuZCA9IHRoaXMubWFnbml0dWRlcy5sZW5ndGggLSAyOyBpIDwgZW5kOyBpKyspIHsKICAgICAgICAgICAgICAgIGNvbnN0IG1hZyA9IHRoaXMubWFnbml0dWRlc1tpXTsKICAgICAgICAgICAgICAgIGlmICh0aGlzLm1hZ25pdHVkZXNbaSAtIDFdID49IG1hZyB8fCB0aGlzLm1hZ25pdHVkZXNbaSAtIDJdID49IG1hZyB8fCB0aGlzLm1hZ25pdHVkZXNbaSArIDFdID49IG1hZyB8fCB0aGlzLm1hZ25pdHVkZXNbaSArIDJdID49IG1hZykgewogICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgdGhpcy5wZWFrSW5kZXhlc1t0aGlzLm5iUGVha3MrK10gPSBpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHNoaWZ0UGVha3MocGl0Y2hGYWN0b3IpIHsKICAgICAgICAgICAgdGhpcy5mcmVxQ29tcGxleEJ1ZmZlclNoaWZ0ZWQuZmlsbCgwKTsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm5iUGVha3M7IGkrKykgewogICAgICAgICAgICAgICAgY29uc3QgcGVha0luZGV4ID0gdGhpcy5wZWFrSW5kZXhlc1tpXTsKICAgICAgICAgICAgICAgIGNvbnN0IHBlYWtJbmRleFNoaWZ0ZWQgPSBNYXRoLnJvdW5kKHBlYWtJbmRleCAqIHBpdGNoRmFjdG9yKTsKICAgICAgICAgICAgICAgIGlmIChwZWFrSW5kZXhTaGlmdGVkID4gdGhpcy5tYWduaXR1ZGVzLmxlbmd0aCkgewogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgbGV0IHN0YXJ0SW5kZXggPSAoaSA+IDApID8gcGVha0luZGV4IC0gTWF0aC5mbG9vcigocGVha0luZGV4IC0gdGhpcy5wZWFrSW5kZXhlc1tpIC0gMV0pIC8gMikgOiAwOwogICAgICAgICAgICAgICAgbGV0IGVuZEluZGV4ID0gKGkgPCB0aGlzLm5iUGVha3MgLSAxKSA/IHBlYWtJbmRleCArIE1hdGguY2VpbCgodGhpcy5wZWFrSW5kZXhlc1tpICsgMV0gLSBwZWFrSW5kZXgpIC8gMikgOiB0aGlzLmZmdFNpemU7CiAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gc3RhcnRJbmRleCAtIHBlYWtJbmRleDsgaiA8IGVuZEluZGV4IC0gcGVha0luZGV4OyBqKyspIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBiaW5JbmRleCA9IHBlYWtJbmRleCArIGo7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgYmluSW5kZXhTaGlmdGVkID0gcGVha0luZGV4U2hpZnRlZCArIGo7CiAgICAgICAgICAgICAgICAgICAgaWYgKGJpbkluZGV4U2hpZnRlZCA+PSB0aGlzLm1hZ25pdHVkZXMubGVuZ3RoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjb25zdCBvbWVnYURlbHRhID0gMiAqIE1hdGguUEkgKiAoYmluSW5kZXhTaGlmdGVkIC0gYmluSW5kZXgpIC8gdGhpcy5mZnRTaXplOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHBoYXNlU2hpZnRSZWFsID0gTWF0aC5jb3Mob21lZ2FEZWx0YSAqIHRoaXMudGltZUN1cnNvcik7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGhhc2VTaGlmdEltYWcgPSBNYXRoLnNpbihvbWVnYURlbHRhICogdGhpcy50aW1lQ3Vyc29yKTsKICAgICAgICAgICAgICAgICAgICBjb25zdCBpbmRleFJlYWwgPSBiaW5JbmRleCAqIDI7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgaW5kZXhJbWFnID0gaW5kZXhSZWFsICsgMTsKICAgICAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZVJlYWwgPSB0aGlzLmZyZXFDb21wbGV4QnVmZmVyW2luZGV4UmVhbF07CiAgICAgICAgICAgICAgICAgICAgY29uc3QgdmFsdWVJbWFnID0gdGhpcy5mcmVxQ29tcGxleEJ1ZmZlcltpbmRleEltYWddOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlU2hpZnRlZFJlYWwgPSB2YWx1ZVJlYWwgKiBwaGFzZVNoaWZ0UmVhbCAtIHZhbHVlSW1hZyAqIHBoYXNlU2hpZnRJbWFnOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlU2hpZnRlZEltYWcgPSB2YWx1ZVJlYWwgKiBwaGFzZVNoaWZ0SW1hZyArIHZhbHVlSW1hZyAqIHBoYXNlU2hpZnRSZWFsOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IGluZGV4U2hpZnRlZFJlYWwgPSBiaW5JbmRleFNoaWZ0ZWQgKiAyOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IGluZGV4U2hpZnRlZEltYWcgPSBpbmRleFNoaWZ0ZWRSZWFsICsgMTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmZyZXFDb21wbGV4QnVmZmVyU2hpZnRlZFtpbmRleFNoaWZ0ZWRSZWFsXSArPSB2YWx1ZVNoaWZ0ZWRSZWFsOwogICAgICAgICAgICAgICAgICAgIHRoaXMuZnJlcUNvbXBsZXhCdWZmZXJTaGlmdGVkW2luZGV4U2hpZnRlZEltYWddICs9IHZhbHVlU2hpZnRlZEltYWc7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CiAgICAvLyBAdHMtaWdub3JlCiAgICByZWdpc3RlclByb2Nlc3NvcigicGhhc2Utdm9jb2RlciIsIFBoYXNlVm9jb2RlclByb2Nlc3Nvcik7CiAgICBjb25zb2xlLmxvZygiUGhhc2VWb2NvZGVyUHJvY2Vzc29yIHJlZ2lzdGVyZWQiKTsKCiAgICBleHBvcnRzLlBoYXNlVm9jb2RlclByb2Nlc3NvciA9IFBoYXNlVm9jb2RlclByb2Nlc3NvcjsKCiAgICByZXR1cm4gZXhwb3J0czsKCn0pKHt9KTsK";class R{maxSize;cache;constructor(g){this.maxSize=g,this.cache=new Map}get(g){if(!this.cache.has(g))return;const e=this.cache.get(g);return this.cache.delete(g),this.cache.set(g,e),e}set(g,e){if(this.cache.has(g))this.cache.delete(g);else if(this.cache.size>=this.maxSize){const I=this.cache.keys().next().value;I!==void 0&&this.cache.delete(I)}this.cache.set(g,e)}has(g){return this.cache.has(g)}}const V=100;function Y(a){if(!a)return null;const g=a.match(/max-age\s*=\s*"?(\d+)"?/i);return g?parseInt(g[1],10):null}function N(a){return a?/(?:^|,)\s*(no-cache|no-store|must-revalidate)\s*(?:,|$)/i.test(a):!1}class r{static pendingRequests=new Map;static pendingCallbacks=new Map;static decodedBuffers=new R(V);static cacheExpirationTime=24*60*60*1e3;static setCacheExpirationTime(g){this.cacheExpirationTime=g}static async openCache(){try{return await caches.open("audio-cache")}catch(g){throw console.error("Failed to open cache:",g),g}}static callAllCallbacks(g,e,I){const t=this.pendingCallbacks.get(g);t&&t.forEach(s=>{const C=s[e];if(C)try{C(I)}catch(A){console.error(`Error in ${e} callback:`,A)}})}static async getOrCreatePendingRequest(g,e,I,t){if(I?.aborted)throw new DOMException("Operation was aborted","AbortError");if(t){const C=this.pendingCallbacks.get(g)||[];C.push(t),this.pendingCallbacks.set(g,C)}let s=this.pendingRequests.get(g);if(!s){const C=(async()=>{try{const A=await e();if(A===void 0)throw new Error("Failed to create audio buffer.");return A}finally{this.pendingRequests.delete(g),this.pendingCallbacks.delete(g)}})();return I?.addEventListener("abort",()=>{I.aborted&&(this.pendingRequests.delete(g),this.pendingCallbacks.delete(g))},{once:!0}),this.pendingRequests.set(g,C),C}return s}static async updateMetadata(g,e,I){const t={url:e,timestamp:Date.now(),...I};await g.put(`${e}:meta`,new Response(JSON.stringify(t),{headers:{"Content-Type":"application/json"}}))}static async getBufferFromCache(g,e){try{const I=await e.match(g);return I&&I.ok?await I.arrayBuffer():null}catch(I){return console.error("Failed to get data from cache:",I),null}}static async fetchAndCacheBuffer(g,e,I,t,s,C){const A=new Headers;I&&A.append("If-None-Match",I),t&&A.append("If-Modified-Since",t),console.debug(`[AudioCache] Fetching ${g}`,{headers:Object.fromEntries(A.entries()),hasEtag:!!I,hasLastModified:!!t});const i=await fetch(g,{headers:A,signal:s});if(console.debug(`[AudioCache] Response ${g}`,{status:i.status,statusText:i.statusText,etag:i.headers?.get("ETag"),lastModified:i.headers?.get("Last-Modified"),cacheControl:i.headers?.get("Cache-Control")}),i.status===304){const o=await e.match(g);if(o){C?.onCacheHit&&C.onCacheHit({url:g,cacheType:"browser",timestamp:Date.now()});const n=Date.now(),c=i.headers?.get("Cache-Control");return await this.updateMetadata(e,g,{timestamp:n,etag:I,lastModified:t,...c?{cacheControl:c}:{}}),await o.arrayBuffer()}else{console.warn(`Cache inconsistency detected for ${g}: 304 response but no cached body. Re-fetching.`);const n=await fetch(g,{signal:s});if(n.status===200){const c=n.clone(),h=n.headers.get("ETag"),d=n.headers.get("Last-Modified"),p=n.headers.get("Cache-Control");try{await Promise.all([e.put(g,c),this.updateMetadata(e,g,{timestamp:Date.now(),etag:h||void 0,lastModified:d||void 0,cacheControl:p||void 0})])}catch(b){throw await e.delete(g),await e.delete(`${g}:meta`),b}if(n.body){const{stream:b,total:f}=this.createProgressTrackingStream(n,g);return await this.collectStreamToArrayBuffer(b,f||void 0)}else return await n.arrayBuffer()}else throw new Error(`Failed to fetch resource after cache inconsistency: ${n.status} ${n.statusText}`)}}if(i.status===200){const o=i.clone(),n=i.headers.get("ETag"),c=i.headers.get("Last-Modified"),h=i.headers.get("Cache-Control");try{await Promise.all([e.put(g,o),this.updateMetadata(e,g,{timestamp:Date.now(),etag:n||void 0,lastModified:c||void 0,cacheControl:h||void 0})])}catch(d){throw await e.delete(g),await e.delete(`${g}:meta`),d}}if(s?.aborted)throw new DOMException("Operation was aborted","AbortError");if(i.body){const{stream:o,total:n}=this.createProgressTrackingStream(i,g);return await this.collectStreamToArrayBuffer(o,n||void 0)}else return await i.arrayBuffer()}static createProgressTrackingStream(g,e){const I=g.headers.get("content-length"),t=I?parseInt(I,10):null;let s=0;if(!g.body)throw new Error("Response body is null");const C=g.body.getReader();return{stream:new ReadableStream({start(i){function o(){return C.read().then(({done:n,value:c})=>{if(n){r.callAllCallbacks(e,"onLoadingProgress",{url:e,loaded:s,total:t,progress:t?1:-1,timestamp:Date.now()}),i.close();return}if(c){s+=c.byteLength;const h=t?s/t:-1;r.callAllCallbacks(e,"onLoadingProgress",{url:e,loaded:s,total:t,progress:h,timestamp:Date.now()}),i.enqueue(c)}return o()}).catch(n=>{i.error(n)})}return o()},cancel(i){return C.cancel(i)}}),total:t}}static async collectStreamToArrayBuffer(g,e){const I=g.getReader();try{if(e!==void 0&&e>0){const t=new ArrayBuffer(e),s=new Uint8Array(t);let C=0;for(;;){const{done:A,value:i}=await I.read();if(A)break;i&&(s.set(i,C),C+=i.byteLength)}return t}else{let t=new Uint8Array(8192),s=0;for(;;){const{done:C,value:A}=await I.read();if(C)break;if(A){if(s+A.byteLength>t.length){const i=Math.max(t.length*2,s+A.byteLength),o=new Uint8Array(i);o.set(t.subarray(0,s)),t=o}t.set(A,s),s+=A.byteLength}}return t.slice(0,s).buffer}}finally{I.releaseLock()}}static async decodeAudioData(g,e){try{return await g.decodeAudioData(e)}catch(I){throw console.error("Failed to decode audio data:",I),I}}static async getMetadataFromCache(g,e){try{const I=await e.match(g+":meta");return I&&I.ok?await I.json():null}catch(I){return console.error("Failed to get metadata from cache:",I),null}}async getAudioBuffer(g,e,I,t){if(t?.onLoadingStart&&t.onLoadingStart({url:e,timestamp:Date.now()}),r.decodedBuffers.has(e))return t?.onCacheHit&&t.onCacheHit({url:e,cacheType:"memory",timestamp:Date.now()}),r.decodedBuffers.get(e);if(e.startsWith("data:")){const i=e.split(",")[1],o=Uint8Array.from(atob(i),c=>c.charCodeAt(0)).buffer,n=await r.decodeAudioData(g,o);return r.decodedBuffers.set(e,n),n}const s=await r.openCache(),C=await r.getMetadataFromCache(e,s),A=(()=>{if(!C||N(C.cacheControl))return!0;const i=Y(C.cacheControl);if(i!==null){const o=(Date.now()-C.timestamp)/1e3;if(i>0&&o<i)return!1}return C.etag||C.lastModified?!0:Date.now()-C.timestamp>r.cacheExpirationTime})();return r.getOrCreatePendingRequest(e,async()=>{if(A){t?.onCacheMiss&&t.onCacheMiss({url:e,reason:C?"expired":"not-found",timestamp:Date.now()});try{const i=await r.fetchAndCacheBuffer(e,s,C?.etag,C?.lastModified,I,{onCacheHit:t?.onCacheHit});t?.onLoadingComplete&&t.onLoadingComplete({url:e,duration:0,size:i.byteLength,timestamp:Date.now()});const o=await r.decodeAudioData(g,i);return r.decodedBuffers.set(e,o),o}catch(i){throw t?.onCacheError&&t.onCacheError({url:e,error:i,operation:"get",timestamp:Date.now()}),i}}else{const i=await r.getBufferFromCache(e,s);if(i){t?.onCacheHit&&t.onCacheHit({url:e,cacheType:"browser",timestamp:Date.now()});const o=await r.decodeAudioData(g,i);return r.decodedBuffers.set(e,o),o}else{t?.onCacheError&&t.onCacheError({url:e,error:new Error("Cache inconsistency: metadata exists but body is missing"),operation:"get",timestamp:Date.now()});const o=await r.fetchAndCacheBuffer(e,s,C?.etag,C?.lastModified,I,{onCacheHit:t?.onCacheHit}),n=await r.decodeAudioData(g,o);return r.decodedBuffers.set(e,n),n}}},I,{onLoadingProgress:t?.onLoadingProgress})}clearMemoryCache(){r.decodedBuffers=new R(V),r.pendingRequests.clear()}}class y{listeners={};on(g,e){return this.listeners[g]=this.listeners[g]??[],this.listeners[g].push({fn:e,once:!1}),()=>this.off(g,e)}once(g,e){return this.listeners[g]=this.listeners[g]??[],this.listeners[g].push({fn:e,once:!0}),()=>this.off(g,e)}off(g,e){const I=this.listeners[g];I&&(this.listeners[g]=I.filter(t=>t.fn!==e))}emit(g,e){const I=this.listeners[g];I&&(I.forEach(t=>t.fn(e)),this.listeners[g]=I.filter(t=>!t.once))}emitAsync(g,e){const I=this.listeners[g];if(I){const t=I.map(s=>Promise.resolve().then(()=>s.fn(e)).catch(C=>console.error(`Error in listener for event ${g}:`,C)));return this.listeners[g]=I.filter(s=>!s.once),Promise.all(t).then(()=>{})}return Promise.resolve()}removeAllListeners(){this.listeners={}}}class w{constructor(g=[]){this.sounds=g}_position=[0,0,0];loopCount=0;playIndex=0;preplayRandom(){if(this.sounds.length===0)return;const e=this.randomSound().preplay();return e.length>0?e[0]:void 0}playRandom(){const g=this.preplayRandom();return g&&g.play(),g}preplayOrdered(g=!0){if(this.sounds.length===0)return;const I=this.sounds[this.playIndex].preplay();if(I.length!==0)return this.playIndex=(this.playIndex+1)%this.sounds.length,!g&&this.playIndex===0&&(this.playIndex=this.sounds.length),I[0]}playOrdered(g=!0){const e=this.preplayOrdered(g);return e&&e.play(),e}get duration(){return this.sounds.map(g=>g.duration).reduce((g,e)=>Math.max(g,e),0)}seek(g){this.sounds.forEach(e=>e.seek&&e.seek(g))}addSound(g){this.sounds.push(g)}randomSound(){if(this.sounds.length===0)throw new Error("Cannot get a random sound from an empty group");const g=Math.floor(Math.random()*this.sounds.length);return this.sounds[g]}preplay(){return this.sounds.map(e=>e.preplay()).flat()}play(){const g=[];return this.preplay().forEach(e=>{e.play(),g.push(e)}),g}get isPlaying(){return this.sounds.some(g=>g.isPlaying)}stop(){this.sounds.forEach(g=>g.stop())}pause(){this.sounds.forEach(g=>g.pause())}loop(g){return g===void 0?this.loopCount:(this.loopCount=g,this.sounds.forEach(e=>e.loop(g)),this.loopCount)}addFilter(g){this.sounds.forEach(e=>e.addFilter(g))}removeFilter(g){this.sounds.forEach(e=>e.removeFilter(g))}set position(g){this._position=g,this.sounds.forEach(e=>e.position=this._position)}get position(){return this._position}get volume(){return this.sounds.map(g=>g.volume).reduce((g,e)=>g+e,0)/this.sounds.length}set volume(g){this.sounds.forEach(e=>e.volume=g)}get playbackRate(){return this.sounds.length===0?1:this.sounds[0].playbackRate}set playbackRate(g){this.sounds.forEach(e=>e.playbackRate=g)}}class m{_filters=[];addFilter(g){this._filters.push(g)}removeFilter(g){this._filters=this._filters.filter(e=>e.frequency.value!==g.frequency.value&&e.type!==g.type&&e.Q.value!==g.Q.value&&e.gain.value!==g.gain.value)}applyFilters(g){return this._filters.reduce((e,I)=>(e.connect(I),I),g),this._filters.length>0?this._filters[this._filters.length-1]:g}get filters(){return this._filters}addFilters(g){g.forEach(e=>this.addFilter(e))}removeFilters(g){g.forEach(e=>this.removeFilter(e))}cleanup(){this._filters.forEach(g=>g.disconnect()),this._filters=[]}}class v extends m{context;source;gainNode;panner;constructor(g,e,I,t=0){super(),this.source=g,this.gainNode=e,this.context=I,this.panner=I.createPanner(),g.connect(this.panner).connect(this.gainNode),this.refreshFilters()}get duration(){return 0}play(){if(!this.source)throw new Error("Cannot play a sound that has been cleaned up");return[this]}get isPlaying(){return!!this.source}get volume(){if(!this.gainNode)throw new Error("Cannot get volume of a sound that has been cleaned up");return this.gainNode.gain.value}set volume(g){if(!this.gainNode)throw new Error("Cannot set volume of a sound that has been cleaned up");this.gainNode.gain.value=g}stop(){if(!this.source)throw new Error("Cannot stop a sound that has been cleaned up");this.source.mediaStream.getTracks().forEach(g=>g.stop())}pause(){if(!this.source)throw new Error("Cannot pause a sound that has been cleaned up");this.source.mediaStream.getTracks().forEach(g=>g.enabled=!1)}resume(){if(!this.source)throw new Error("Cannot resume a sound that has been cleaned up");this.source.mediaStream.getTracks().forEach(g=>g.enabled=!0)}addFilter(g){super.addFilter(g),this.refreshFilters()}removeFilter(g){super.removeFilter(g),this.refreshFilters()}set position(g){if(!this.panner)throw new Error("Cannot move a sound that has been cleaned up");const[e,I,t]=g;this.panner.positionX.value=e,this.panner.positionY.value=I,this.panner.positionZ.value=t}get position(){if(!this.panner)throw new Error("Cannot get position of a sound that has been cleaned up");return[this.panner.positionX.value,this.panner.positionY.value,this.panner.positionZ.value]}refreshFilters(){if(!this.source||!this.gainNode)throw new Error("Cannot update filters on a sound that has been cleaned up");let g=this.source;this.source.disconnect(),g=this.applyFilters(g),g.connect(this.gainNode)}get playbackRate(){return 1}set playbackRate(g){}}class E extends m{context;_position=[0,0,0];loopCount=0;prevVolume=1;microphoneGainNode;streamPlayback;stream;streamSource;constructor(g){super(),this.context=g,this.microphoneGainNode=this.context.createGain()}play(){return this.stream||navigator.mediaDevices.getUserMedia({audio:!0}).then(g=>{this.stream=g,this.streamSource=this.context.createMediaStreamSource(this.stream),this.streamPlayback=new v(this.streamSource,this.microphoneGainNode,this.context),this.streamPlayback.play()}).catch(g=>{console.error("Error initializing microphone stream:",g)}),this.streamPlayback?[this.streamPlayback]:[]}get duration(){return 0}seek(g){}get isPlaying(){return!!this.streamPlayback}stop(){this.streamPlayback&&(this.streamPlayback.stop(),this.streamPlayback=void 0)}pause(){this.streamPlayback&&this.streamPlayback.pause()}resume(){this.streamPlayback&&this.streamPlayback.resume()}addFilter(g){this.streamPlayback&&this.streamPlayback.addFilter(g)}removeFilter(g){this.streamPlayback&&this.streamPlayback.removeFilter(g)}get volume(){return this.streamPlayback?this.streamPlayback.volume:0}set volume(g){this.streamPlayback&&(this.streamPlayback.volume=g)}get position(){return[0,0,0]}set position(g){}loop(g){return 0}get playbackRate(){return 1}set playbackRate(g){}}function S(a){class g extends a{playbacks=[];_position=[0,0,0];_stereoPan=0;_threeDOptions={coneInnerAngle:360,coneOuterAngle:360,coneOuterGain:0,distanceModel:"inverse",maxDistance:1e4,channelCount:2,channelCountMode:"clamped-max",channelInterpretation:"speakers",panningModel:"HRTF",refDistance:1,rolloffFactor:1,positionX:0,positionY:0,positionZ:0,orientationX:0,orientationY:0,orientationZ:0};_volume=1;play(){const I=this.preplay();return I.forEach(t=>t.play()),I}stop(){this.playbacks.forEach(I=>I.stop()),this.playbacks=[]}pause(){this.playbacks.forEach(I=>I.pause())}addFilter(I){super.addFilter(I),this.playbacks.forEach(t=>t.addFilter(I))}removeFilter(I){super.removeFilter(I),this.playbacks.forEach(t=>t.removeFilter(I))}get isPlaying(){return this.playbacks.some(I=>I.isPlaying)}get position(){return[this._threeDOptions.positionX,this._threeDOptions.positionY,this._threeDOptions.positionZ]}set position(I){this._threeDOptions.positionX=I[0],this._threeDOptions.positionY=I[1],this._threeDOptions.positionZ=I[2],this.playbacks.forEach(t=>t.position=I)}get threeDOptions(){return this._threeDOptions}set threeDOptions(I){this._threeDOptions={...this._threeDOptions,...I},this.playbacks.forEach(t=>t.threeDOptions=this._threeDOptions)}get stereoPan(){return this._stereoPan}set stereoPan(I){this._stereoPan=I,this.playbacks.forEach(t=>t.stereoPan=I)}get volume(){return this._volume}set volume(I){this._volume=I,this.playbacks.forEach(t=>t.volume=I)}}return g}function H(a){class g extends a{panner;_panType="stereo";get panType(){return this._panType}setPanType(I,t){this._panType===I&&this.panner||(this.panner&&this.panner.disconnect(),this._panType=I,I==="stereo"?this.panner=t.createStereoPanner():this.panner=t.createPanner())}setPannerNode(I){this.panner=I}get stereoPan(){return this.panType==="stereo"?this.panner.pan.value:null}set stereoPan(I){if(this.panType!=="stereo")throw new Error("Stereo panning is not available when using HRTF.");if(!this.panner)throw new Error("Cannot set stereo pan of a sound that has been cleaned up");I=W(I,-1,1),this.panner.pan.setValueAtTime(W(I,-1,1),this.panner.context.currentTime)}get threeDOptions(){if(!this.panner)throw new Error("Cannot get 3D options of a sound that has been cleaned up");if(this.panType!=="HRTF")throw new Error("Cannot get 3D options of a sound that is not using HRTF");const I=this.panner;return{coneInnerAngle:I.coneInnerAngle,coneOuterAngle:I.coneOuterAngle,coneOuterGain:I.coneOuterGain,distanceModel:I.distanceModel,maxDistance:I.maxDistance,channelCount:this.panner.channelCount,channelCountMode:I.channelCountMode,channelInterpretation:I.channelInterpretation,panningModel:I.panningModel,refDistance:I.refDistance,rolloffFactor:I.rolloffFactor,positionX:I.positionX.value,positionY:I.positionY.value,positionZ:I.positionZ.value,orientationX:I.orientationX.value,orientationY:I.orientationY.value,orientationZ:I.orientationZ.value}}set threeDOptions(I){if(!this.panner)throw new Error("Cannot set 3D options of a sound that has been cleaned up");if(this.panType!=="HRTF")throw new Error("Cannot set 3D options of a sound that is not using HRTF");const t=this.panner;t.coneInnerAngle=I.coneInnerAngle!==void 0?I.coneInnerAngle:t.coneInnerAngle,t.coneOuterAngle=I.coneOuterAngle!==void 0?I.coneOuterAngle:t.coneOuterAngle,t.coneOuterGain=I.coneOuterGain!==void 0?I.coneOuterGain:t.coneOuterGain,t.distanceModel=I.distanceModel||t.distanceModel,t.maxDistance=I.maxDistance!==void 0?I.maxDistance:t.maxDistance,t.channelCount=I.channelCount!==void 0?I.channelCount:t.channelCount,t.channelCountMode=I.channelCountMode||t.channelCountMode,t.channelInterpretation=I.channelInterpretation||t.channelInterpretation,t.panningModel=I.panningModel||t.panningModel,t.refDistance=I.refDistance!==void 0?I.refDistance:t.refDistance,t.rolloffFactor=I.rolloffFactor!==void 0?I.rolloffFactor:t.rolloffFactor,t.positionX.value=I.positionX!==void 0?I.positionX:t.positionX.value,t.positionY.value=I.positionY!==void 0?I.positionY:t.positionY.value,t.positionZ.value=I.positionZ!==void 0?I.positionZ:t.positionZ.value,t.orientationX.value=I.orientationX!==void 0?I.orientationX:t.orientationX.value,t.orientationY.value=I.orientationY!==void 0?I.orientationY:t.orientationY.value,t.orientationZ.value=I.orientationZ!==void 0?I.orientationZ:t.orientationZ.value}set position(I){if(!this.panner)throw new Error("Cannot move a sound that has been cleaned up");if(this.panType!=="HRTF")throw new Error("Cannot move a sound that is not using HRTF");const[t,s,C]=I,A=this.panner;A.positionX.value=t,A.positionY.value=s,A.positionZ.value=C}get position(){if(!this.panner)throw new Error("Cannot get position of a sound that has been cleaned up");if(this.panType!=="HRTF")throw new Error("Cannot get position of a sound that is not using HRTF");const I=this.panner;return[I.positionX.value,I.positionY.value,I.positionZ.value]}cleanup(){this.panner&&(this.panner.disconnect(),this.panner=void 0),super.cleanup()}}return g}function W(a,g,e){return Math.min(Math.max(a,g),e)}function D(a){class g extends a{gainNode;setGainNode(I){this.gainNode=I}cleanup(){this.gainNode&&(this.gainNode.disconnect(),this.gainNode=void 0),super.cleanup()}get volume(){if(!this.gainNode)throw new Error("Cannot get volume of a sound that has been cleaned up");return this.gainNode.gain.value}set volume(I){if(!this.gainNode)throw new Error("Cannot set volume of a sound that has been cleaned up");this.gainNode.gain.value=I}}return g}class k extends H(D(m)){source;_playing=!1;origin;eventEmitter=new y;constructor(){super()}get isPlaying(){return this.source?this._playing:!1}on(g,e){this.eventEmitter.on(g,e)}off(g,e){this.eventEmitter.off(g,e)}emit(g,e){this.eventEmitter.emit(g,e)}async emitAsync(g,e){return this.eventEmitter.emitAsync(g,e)}cleanup(){this.eventEmitter.removeAllListeners(),super.cleanup()}}class Z extends k{constructor(g,e,I){super(),this.origin=g,this.context=g.context,this.loopCount=g.loopCount,this.setPanType(g.panType,g.context),this.source=e,"buffer"in e&&e.buffer&&(this.buffer=e.buffer),this.setupSourceNode(e),this.source.connect(this.panner),this.setGainNode(I),this.panner.connect(this.gainNode),this.refreshFilters()}context;loopCount=0;currentLoop=0;buffer;_offset=0;_startTime=0;_state=0;_playbackRate=1;setupSourceNode(g){if("mediaElement"in g&&g.mediaElement)g.mediaElement.onended=this.loopEnded;else if("onended"in g)g.onended=this.loopEnded;else throw new Error("Unsupported source type")}get isPlaying(){return this._state===1}get duration(){if(!this.source)throw new Error("Cannot get duration of a sound that has been cleaned up");return"mediaElement"in this.source&&this.source.mediaElement?this.source.mediaElement.duration:this.buffer?this.buffer.duration||NaN:NaN}get playbackRate(){return this._playbackRate}set playbackRate(g){if(g<=0)throw new Error("Playback rate must be greater than 0");if(this._state===1){const e=(this.context.currentTime-this._startTime)*this._playbackRate;this._offset+=e,this._startTime=this.context.currentTime}this._playbackRate=g,this.source&&("playbackRate"in this.source&&(this.source.playbackRate.value=g),"mediaElement"in this.source&&this.source.mediaElement&&(this.source.mediaElement.playbackRate=g))}loopEnded=()=>{!this.source||this._state!==1||(this.currentLoop++,this.loopCount!=="infinite"&&this.currentLoop>this.loopCount?this.stop():(this.seek(0),"mediaElement"in this.source&&this.source.mediaElement?this.source.mediaElement.play():this.play()))};play(){if(!this.source)throw new Error("Cannot play a sound that has been cleaned up");if(this._state===1)return[this];try{return this._state===2?"mediaElement"in this.source&&this.source.mediaElement?this.source.mediaElement.play():(this.recreateSource(),"start"in this.source&&this.source.start&&this.source.start(0,this._offset)):"mediaElement"in this.source&&this.source.mediaElement?(this.source.mediaElement.currentTime=this._offset,this.source.mediaElement.play()):"start"in this.source&&this.source.start&&(this.recreateSource(),this.source.start(0,this._offset)),this._startTime=this.context.currentTime,this._state=1,this.emit("play",this),[this]}catch(g){throw this.emitAsync("error",{error:g,errorType:"source",timestamp:Date.now(),recoverable:!0}),g}}pause(){if(!this.source||this._state!==1)return;const g=(this.context.currentTime-this._startTime)*this._playbackRate;this._offset+=g,"mediaElement"in this.source&&this.source.mediaElement?this.source.mediaElement.pause():"stop"in this.source&&this.source.stop(),this._state=2}stop(){if(!this.source)throw new Error("Cannot stop a sound that has been cleaned up");this._state===3||this._state===0||("stop"in this.source&&this._state===1&&this.source.stop(),"mediaElement"in this.source&&this.source.mediaElement&&(this.source.mediaElement.pause(),this.source.mediaElement.currentTime=0),this._offset=0,this._startTime=0,this._state=3,this.emit("stop",void 0))}seek(g){if(!this.source||!this.gainNode||!this.panner)throw new Error("Cannot seek a sound that has been cleaned up");if(!isFinite(g)||g<0)throw new Error("Invalid time value for seek");const e=this._state===1;e&&this.pause(),this._offset=g,"mediaElement"in this.source&&this.source.mediaElement&&(this.source.mediaElement.currentTime=g),e&&this.play()}get currentTime(){if(this._state===1){const g=(this.context.currentTime-this._startTime)*this._playbackRate;return this._offset+g}else return this._offset}recreateSource(){if(!this.buffer||!this.panner||!this.context||!this.gainNode)throw new Error("Cannot recreate source of a sound that has been cleaned up");try{this.source&&(!("mediaElement"in this.source)&&"onended"in this.source&&(this.source.onended=null),this.source.disconnect()),this.source=this.context.createBufferSource(),this.source.buffer=this.buffer,this.source.connect(this.panner),this.source.onended=this.loopEnded,this.playbackRate=this._playbackRate,this.refreshFilters()}catch(g){throw this.emitAsync("error",{error:g,errorType:"source",timestamp:Date.now(),recoverable:!1}),g}}set sourceLoop(g){if(!this.source)throw new Error("Cannot set loop on a sound that has been cleaned up");"loop"in this.source&&(this.source.loop=g),"mediaElement"in this.source&&this.source.mediaElement&&(this.source.mediaElement.loop=g)}cleanup(){this.source&&(this.source.disconnect(),this.source=void 0,super.cleanup())}assertNotCleanedUp(){if(!this.source||!this.gainNode||!this.panner)throw new Error("Cannot perform operation on a sound that has been cleaned up")}addFilter(g){this.assertNotCleanedUp(),super.addFilter(g),this.refreshFilters()}removeFilter(g){this.assertNotCleanedUp(),super.removeFilter(g),this.refreshFilters()}loop(g){if(!this.source)throw new Error("Cannot loop a sound that has been cleaned up");if(g!==void 0&&(this.loopCount=g==="infinite"?"infinite":Math.max(0,g),this.currentLoop=0),"mediaElement"in this.source&&this.source.mediaElement){const e=this.source.mediaElement;e.loop=this.loopCount==="infinite"}else if("loop"in this.source)this.source.loop=this.loopCount==="infinite",this.source.buffer&&(this.source.loopEnd=this.source.buffer.duration,this.source.loopStart=0);else throw new Error("Unsupported source type");return this.loopCount}refreshFilters(){if(!this.panner||!this.gainNode)throw new Error("Cannot update filters on a sound that has been cleaned up");let g=this.panner;g.disconnect(),g=this.applyFilters(g),g.connect(this.gainNode)}clone(g={}){if(!this.source||!this.gainNode||!this.context)throw new Error("Cannot clone a sound that has been cleaned up");const e=g.panType||this.panType,I=this.context.createGain();let t;if("buffer"in this.source&&this.source.buffer)t=this.context.createBufferSource(),t.buffer=this.source.buffer;else if("mediaElement"in this.source&&this.source.mediaElement)t=this.context.createMediaElementSource(this.source.mediaElement);else throw new Error("Unsupported source type");const s=g.loopCount!==void 0?g.loopCount:this.loopCount,C=new Z(this.origin,t,I);return C.loopCount=s,C.currentLoop=this.currentLoop,C.setPanType(e,this.context),C.volume=this.volume,C.playbackRate=this._playbackRate,C._offset=this._offset,C._state=this._state,this._filters.forEach(A=>{const i=this.context.createBiquadFilter();i.type=A.type,i.frequency.value=A.frequency.value,i.Q.value=A.Q.value,i.gain.value=A.gain.value,C.addFilter(i)}),this._state===1&&C.play(),C}}class u extends S(m){constructor(g,e,I,t,s=B.Buffer,C="HRTF"){super(),this.url=g,this.globalGainNode=t,this.soundType=s,this.panType=C,this.buffer=e,this.context=I}buffer;context;loopCount=0;_playbackRate=1;eventEmitter=new y;get volume(){return super.volume}on(g,e){this.eventEmitter.on(g,e)}off(g,e){this.eventEmitter.off(g,e)}emit(g,e){this.eventEmitter.emit(g,e)}async emitAsync(g,e){return this.eventEmitter.emitAsync(g,e)}clone(g={}){const e=g.panType||this.panType,I=g.stereoPan!==void 0?g.stereoPan:this.stereoPan,t=g.threeDOptions||this.threeDOptions,s=g.loopCount!==void 0?g.loopCount:this.loopCount,C=g.playbackRate||this.playbackRate,A=g.volume!==void 0?g.volume:this.volume,i=g.position!==void 0?g.position:this.position,o=g.filters&&g.filters.length?g.filters:this._filters,n=new u(this.url,this.buffer,this.context,this.globalGainNode,this.soundType,e);return n.loop(s),n.playbackRate=C,n.volume=A,e==="HRTF"?(n.threeDOptions=t,n.position=i):n.stereoPan=I,n.addFilters(o),n}preplay(){try{let g;if(this.buffer)g=this.context.createBufferSource(),g.buffer=this.buffer;else{const t=new Audio;t.crossOrigin="anonymous",t.src=this.url,t.preload="auto",g=this.context.createMediaElementSource(t)}const e=this.context.createGain();e.connect(this.globalGainNode);const I=new Z(this,g,e);return I.setGainNode(e),I.volume=this.volume,I.playbackRate=this.playbackRate,this._filters.forEach(t=>I.addFilter(t)),this.panType==="HRTF"?(I.threeDOptions=this.threeDOptions,I.position=this.position):this.panType==="stereo"&&(I.stereoPan=this.stereoPan),I.on("error",t=>{this.emitAsync("soundError",{url:this.url,error:t.error,errorType:"playback",timestamp:t.timestamp,recoverable:t.recoverable})}),this.playbacks.push(I),[I]}catch(g){const e={url:this.url,error:g,errorType:"playback",timestamp:Date.now(),recoverable:!0};throw this.emitAsync("soundError",e),g}}play(){const g=super.play();return this.emit("play",g[0]),g}stop(){super.stop(),this.emit("stop",void 0)}pause(){super.pause(),this.emit("pause",void 0)}seek(g){this.playbacks.forEach(e=>e.seek(g))}get duration(){return this.playbacks.length>0?this.playbacks[0].duration:this.buffer?.duration||NaN}loop(g){return g===void 0?this.loopCount:(this.loopCount=g,this.playbacks.forEach(e=>e.loop(g)),this.loopCount)}get playbackRate(){return this._playbackRate}set playbackRate(g){this._playbackRate=g,this.playbacks.forEach(e=>e.playbackRate=g),this.emit("rateChange",g)}set volume(g){super.volume=g,this.emit("volumeChange",g)}cleanup(){this.playbacks.forEach(g=>g.cleanup()),this.playbacks=[],this.eventEmitter.removeAllListeners()}}const Q=(a,g)=>{var e=new Uint8Array(a.byteLength+g.byteLength);return e.set(new Uint8Array(a),0),e.set(new Uint8Array(g),a.byteLength),e.buffer};function P(a,g,e){const I=[];let t=0,s;if(e?.aborted){console.error("Stream error:",new DOMException("Operation was aborted","AbortError"));return}fetch(a,e?{signal:e}:void 0).then(function(A){if(!A.ok)throw new Error("HTTP error, status = "+A.status);if(!A.body)throw new Error("Missing body");s=A.body.getReader();let i=new ArrayBuffer(0);const o=()=>{I.length=0,s&&s.cancel("Stream aborted").catch(()=>{})};e?.addEventListener("abort",o);function n(){return e?.aborted?(o(),Promise.resolve()):s.read().then(({value:c,done:h})=>{if(e?.aborted){o();return}let d=null;if(c){if(i.byteLength?d=Q(i,c.buffer):(i=c.buffer.slice(0,44),d=c.buffer),g.decodeAudioData(d,function(p){e?.aborted||(I.push(p),I.length&&C())},function(p){console.log("err(decodeAudioData): "+p)}),h){console.log("done"),e?.removeEventListener("abort",o);return}n()}}).catch(c=>{e?.aborted||c.name==="AbortError"||console.error("Stream read error:",c)})}n()}).catch(function(A){console.error("Stream error:",A)});function C(){for(;I.length;){let A=I.shift();const i=g.createBufferSource();if(!A)return;i.buffer=A,i.connect(g.destination),t==0&&(t=g.currentTime+.02),i.start(t),t+=i.buffer.duration}}}function M(a){class g extends k{_oscillatorOptions={};get oscillatorOptions(){return this._oscillatorOptions}set oscillatorOptions(I){this._oscillatorOptions=I,this.source&&this.source instanceof OscillatorNode&&(this.oscillatorOptions.detune&&(this.source.detune.value=this.oscillatorOptions.detune),this.oscillatorOptions.frequency&&(this.source.frequency.value=this.oscillatorOptions.frequency),this.oscillatorOptions.type&&(this.source.type=this.oscillatorOptions.type))}play(){if(!this.source)throw new Error("No source node found");return this.oscillatorOptions.detune&&(this.source.detune.value=this.oscillatorOptions.detune),this.oscillatorOptions.frequency&&(this.source.frequency.value=this.oscillatorOptions.frequency),this.oscillatorOptions.type&&(this.source.type=this.oscillatorOptions.type),this.source.start(),this._playing=!0,[this]}stop(){this.source&&this.source.stop&&(this.source.stop(),this._playing=!1)}pause(){this.stop()}get frequency(){return this.source.frequency.value}set frequency(I){this.source.frequency.value=I,this.oscillatorOptions.frequency=I}get detune(){return this.source.detune.value}set detune(I){this.source.detune.value=I,this.oscillatorOptions.detune=I}get type(){return this.source.type}set type(I){this.source.type=I,this.oscillatorOptions.type=I}}return g}class x extends M(H(D(m))){constructor(g,e,I){super(),this.origin=g,this.source=e,this.context=g.context,this.setPanType(g.panType,g.context),this.source.connect(this.panner),this.setGainNode(I),this.panner.connect(this.gainNode),this.refreshFilters()}context;refreshFilters(){if(!this.panner||!this.gainNode)throw new Error("Cannot update filters on a sound that has been cleaned up");let g=this.panner;g.disconnect(),g=this.applyFilters(g),g.connect(this.gainNode)}cleanup(){this.panner&&this.gainNode&&(this.source.disconnect(this.panner),this.panner.disconnect(),this.gainNode.disconnect()),this.eventEmitter.removeAllListeners()}}class G extends S(m){constructor(g,e,I=B.Oscillator,t="HRTF",s={}){super(),this.context=g,this.globalGainNode=e,this.soundType=I,this.panType=t,this.context=g,this._oscillatorOptions=s}_oscillatorOptions;playbacks=[];eventEmitter=new y;on(g,e){this.eventEmitter.on(g,e)}off(g,e){this.eventEmitter.off(g,e)}emit(g,e){this.eventEmitter.emit(g,e)}async emitAsync(g,e){return this.eventEmitter.emitAsync(g,e)}clone(g={}){const e=g.panType||this.panType,I=g.stereoPan!==void 0?g.stereoPan:this.stereoPan??0,t=g.threeDOptions||this.threeDOptions,s=g.volume!==void 0?g.volume:this.volume,C=g.position&&g.position.length?g.position:this.position,A=g.filters&&g.filters.length?g.filters:this._filters,i=g.oscillatorOptions||this._oscillatorOptions,o=new G(this.context,this.globalGainNode,this.soundType,e,i);return o._volume=s,o._position=C,o._stereoPan=I,o._threeDOptions=t,o.addFilters(A),o}preplay(){const g=this.context.createOscillator();return this.createPlayback(g)}createPlayback(g){this.oscillatorOptions.detune&&(g.detune.value=this.oscillatorOptions.detune),this.oscillatorOptions.frequency&&(g.frequency.value=this.oscillatorOptions.frequency),this.oscillatorOptions.type&&(g.type=this.oscillatorOptions.type);const e=this.context.createGain();e.connect(this.globalGainNode);const I=new x(this,g,e);return I.volume=this.volume,this._filters.forEach(t=>I.addFilter(t)),this.panType==="HRTF"?(I.threeDOptions=this.threeDOptions,I.position=this.position):this.panType==="stereo"&&(I.stereoPan=this.stereoPan),this.playbacks.push(I),[I]}play(){const g=super.play();return this.emit("play",g[0]),g}stop(){super.stop(),this.emit("stop",void 0)}pause(){super.pause(),this.emit("pause",void 0)}get oscillatorOptions(){return this._oscillatorOptions}set oscillatorOptions(g){this._oscillatorOptions=g,this.playbacks.forEach(e=>{e.source instanceof OscillatorNode&&(this.oscillatorOptions.detune&&(e.source.detune.value=this.oscillatorOptions.detune),this.oscillatorOptions.frequency&&(e.source.frequency.value=this.oscillatorOptions.frequency),this.oscillatorOptions.type&&(e.source.type=this.oscillatorOptions.type))})}get frequency(){return this.oscillatorOptions.frequency||440}set frequency(g){this._oscillatorOptions.frequency=g,this.playbacks.forEach(e=>e.frequency=g),this.emit("frequencyChange",g)}get detune(){return this.oscillatorOptions.detune}set detune(g){this._oscillatorOptions.detune=g,this.playbacks.forEach(e=>e.detune=g),this.emit("detuneChange",g)}get type(){return this.oscillatorOptions.type||"sine"}set type(g){this._oscillatorOptions.type=g,this.playbacks.forEach(e=>e.type=g),this.emit("typeChange",g)}}var B=(a=>(a.HTML="HTML",a.Streaming="Streaming",a.Buffer="Buffer",a.Oscillator="oscillator",a))(B||{});class J{context;globalGainNode;listener;prevVolume=1;finalizationRegistry;eventEmitter=new y;cache;constructor(g,e){this.context=g||new X.AudioContext,this.listener=this.context.listener,this.globalGainNode=this.context.createGain(),this.globalGainNode.connect(this.context.destination),this.cache=e||new r,this.finalizationRegistry=new FinalizationRegistry(I=>{I.cleanup()})}on(g,e){this.eventEmitter.on(g,e)}off(g,e){this.eventEmitter.off(g,e)}emit(g,e){this.eventEmitter.emit(g,e)}async emitAsync(g,e){return this.eventEmitter.emitAsync(g,e)}async loadWorklets(g){this.context.audioWorklet?await this.createWorkletNode("phase-vocoder",K,g):console.warn("AudioWorklet not supported")}async createWorkletNode(g,e,I){if(!this.context.audioWorklet)throw new Error("AudioWorklet not supported");try{return new X.AudioWorkletNode(this.context,g)}catch(t){console.error(t),console.log("Loading worklet from url",e);try{await this.context.audioWorklet.addModule(e,{credentials:"same-origin",...I&&{signal:I}})}catch(s){throw console.error(s),s}return new X.AudioWorkletNode(this.context,g)}}clearMemoryCache(){this.cache.clearMemoryCache()}createOscillator(g,e="HRTF"){return new G(this.context,this.globalGainNode,"oscillator",e,g)}async createSound(g,e="Buffer",I="HRTF",t){if(typeof g=="object")return Promise.resolve(new u("",g,this.context,this.globalGainNode,"Buffer",I));const s=g;if(e==="HTML"){const C=new Audio;return C.src=s,C.crossOrigin="anonymous",Promise.resolve(new u(s,void 0,this.context,this.globalGainNode,"HTML",I))}return e==="Streaming"?Promise.resolve(new u(s,void 0,this.context,this.globalGainNode,"Streaming",I)):this.cache.getAudioBuffer(this.context,s,t,{onLoadingStart:C=>this.emitAsync("loadingStart",C),onLoadingProgress:C=>this.emitAsync("loadingProgress",C),onLoadingComplete:C=>this.emitAsync("loadingComplete",C),onLoadingError:C=>this.emitAsync("loadingError",C),onCacheHit:C=>this.emitAsync("cacheHit",C),onCacheMiss:C=>this.emitAsync("cacheMiss",C),onCacheError:C=>this.emitAsync("cacheError",C)}).then(C=>new u(s,C,this.context,this.globalGainNode,e,I))}async createGroup(g){const e=new w;return g.forEach(I=>e.addSound(I)),e}async createGroupFromUrls(g,e="Buffer",I="HRTF",t){const s=new w;return(await Promise.all(g.map(A=>this.createSound(A,e,I,t)))).forEach(A=>s.addSound(A)),s}async createStream(g,e){return P(g,this.context,e),new u(g,void 0,this.context,this.globalGainNode,"Streaming")}createBiquadFilter=({type:g,frequency:e,gain:I,Q:t})=>{e===void 0&&(e=350);const s=this.context.createBiquadFilter();return s.type=g||"lowpass",s.frequency.value=e,s.gain.value=I||0,s.Q.value=t||1,s};createPanner({coneInnerAngle:g,coneOuterAngle:e,coneOuterGain:I,distanceModel:t,maxDistance:s,channelCount:C,channelCountMode:A,channelInterpretation:i,panningModel:o,refDistance:n,rolloffFactor:c,positionX:h,positionY:d,positionZ:p,orientationX:b,orientationY:f,orientationZ:F}){const l=this.context.createPanner();return l.coneInnerAngle=g||360,l.coneOuterAngle=e||360,l.coneOuterGain=I||0,l.distanceModel=t||"inverse",l.maxDistance=s||1e4,l.channelCount=C||2,l.channelCountMode=A||"clamped-max",l.channelInterpretation=i||"speakers",l.panningModel=o||"HRTF",l.refDistance=n||1,l.rolloffFactor=c||1,l.positionX.value=h||0,l.positionY.value=d||0,l.positionZ.value=p||0,l.orientationX.value=b||0,l.orientationY.value=f||0,l.orientationZ.value=F||0,l}pause(){"suspend"in this.context&&this.context.suspend()}resume(){"resume"in this.context&&this.context.resume()}setGlobalVolume(g){this.globalGainNode.gain.value=g}get volume(){return this.globalGainNode.gain.value}set volume(g){if(this.muted){this.prevVolume=g;return}this.setGlobalVolume(g)}mute(){this.muted||(this.prevVolume=this.globalGainNode.gain.value,this.setGlobalVolume(0))}unmute(){this.muted&&this.setGlobalVolume(this.prevVolume)}get muted(){return this.globalGainNode.gain.value===0}set muted(g){g!==this.muted&&(g?this.mute():this.unmute())}getMicrophoneStream(){return new Promise((g,e)=>{navigator.mediaDevices.getUserMedia({audio:!0}).then(I=>{const t=new E(this.context);t.play(),g(t)}).catch(I=>{e(I)})})}get listenerOrientation(){return{forward:[this.listener.forwardX.value,this.listener.forwardY.value,this.listener.forwardZ.value],up:[this.listener.upX.value,this.listener.upY.value,this.listener.upZ.value]}}set listenerOrientation(g){const{forward:e,up:I}=g,[t,s,C]=e,[A,i,o]=I;this.listener.forwardX.value=t,this.listener.forwardY.value=s,this.listener.forwardZ.value=C,this.listener.upX.value=A,this.listener.upY.value=i,this.listener.upZ.value=o}get listenerUpOrientation(){return[this.listener.upX.value,this.listener.upY.value,this.listener.upZ.value]}set listenerUpOrientation(g){const[e,I,t]=g;this.listener.upX.value=e,this.listener.upY.value=I,this.listener.upZ.value=t}get listenerForwardOrientation(){return[this.listener.forwardX.value,this.listener.forwardY.value,this.listener.forwardZ.value]}set listenerForwardOrientation(g){const[e,I,t]=g;this.listener.forwardX.value=e,this.listener.forwardY.value=I,this.listener.forwardZ.value=t}get listenerPosition(){return[this.listener.positionX.value,this.listener.positionY.value,this.listener.positionZ.value]}set listenerPosition(g){const[e,I,t]=g,s=this.context.currentTime;this.listener.positionX.setValueAtTime(e,s),this.listener.positionY.setValueAtTime(I,s),this.listener.positionZ.setValueAtTime(t,s)}}class T{constructor(g=[]){this.synths=g}addSynth(g){this.synths.push(g)}removeSynth(g){const e=this.synths.indexOf(g);if(e!==-1)this.synths.splice(e,1);else throw new Error("Synth not found in group")}play(){this.synths.forEach(g=>g.play())}stop(){this.synths.forEach(g=>g.stop())}setVolume(g){this.synths.forEach(e=>e.volume=g)}set stereoPan(g){this.synths.forEach(e=>e.stereoPan=g)}set position(g){this.synths.forEach(e=>e.position=g)}}exports.Cacophony=J;exports.Group=w;exports.MicrophonePlayback=v;exports.Playback=Z;exports.Sound=u;exports.SoundType=B;exports.Synth=G;exports.SynthGroup=T;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const X=require("standardized-audio-context"),K="data:text/javascript;base64,KGZ1bmN0aW9uIChleHBvcnRzKSB7CiAgICAndXNlIHN0cmljdCc7CgogICAgY29uc3QgV0VCQVVESU9fQkxPQ0tfU0laRSA9IDEyODsKICAgIGNvbnN0IERFRkFVTFRfQkxPQ0tfU0laRSA9IDEwMjQ7IC8vIERlZmF1bHQgYmxvY2sgc2l6ZSBpZiBub3QgcHJvdmlkZWQgaW4gb3B0aW9ucwogICAgLyoqIE92ZXJsYXAtQWRkIE5vZGUgKi8KICAgIGNsYXNzIE9MQVByb2Nlc3NvciBleHRlbmRzIEF1ZGlvV29ya2xldFByb2Nlc3NvciB7CiAgICAgICAgbmJJbnB1dHM7CiAgICAgICAgbmJPdXRwdXRzOwogICAgICAgIGJsb2NrU2l6ZTsKICAgICAgICBob3BTaXplOwogICAgICAgIG5iT3ZlcmxhcHM7CiAgICAgICAgaW5wdXRCdWZmZXJzID0gW107CiAgICAgICAgaW5wdXRCdWZmZXJzSGVhZCA9IFtdOwogICAgICAgIGlucHV0QnVmZmVyc1RvU2VuZCA9IFtdOwogICAgICAgIG91dHB1dEJ1ZmZlcnMgPSBbXTsKICAgICAgICBvdXRwdXRCdWZmZXJzVG9SZXRyaWV2ZSA9IFtdOwogICAgICAgIGNvbnN0cnVjdG9yKG9wdGlvbnMpIHsKICAgICAgICAgICAgc3VwZXIob3B0aW9ucyk7CiAgICAgICAgICAgIHRoaXMubmJJbnB1dHMgPSBvcHRpb25zLm51bWJlck9mSW5wdXRzIHx8IDE7CiAgICAgICAgICAgIHRoaXMubmJPdXRwdXRzID0gb3B0aW9ucy5udW1iZXJPZk91dHB1dHMgfHwgMTsKICAgICAgICAgICAgdGhpcy5ibG9ja1NpemUgPSBvcHRpb25zLnByb2Nlc3Nvck9wdGlvbnMuYmxvY2tTaXplIHx8IERFRkFVTFRfQkxPQ0tfU0laRTsKICAgICAgICAgICAgdGhpcy5ob3BTaXplID0gV0VCQVVESU9fQkxPQ0tfU0laRTsKICAgICAgICAgICAgdGhpcy5uYk92ZXJsYXBzID0gTWF0aC5mbG9vcih0aGlzLmJsb2NrU2l6ZSAvIHRoaXMuaG9wU2l6ZSk7CiAgICAgICAgICAgIHRoaXMuaW5pdGlhbGl6ZUJ1ZmZlcnMoKTsKICAgICAgICB9CiAgICAgICAgaW5pdGlhbGl6ZUJ1ZmZlcnMoKSB7CiAgICAgICAgICAgIHRoaXMuaW5wdXRCdWZmZXJzID0gbmV3IEFycmF5KHRoaXMubmJJbnB1dHMpOwogICAgICAgICAgICB0aGlzLmlucHV0QnVmZmVyc0hlYWQgPSBuZXcgQXJyYXkodGhpcy5uYklucHV0cyk7CiAgICAgICAgICAgIHRoaXMuaW5wdXRCdWZmZXJzVG9TZW5kID0gbmV3IEFycmF5KHRoaXMubmJJbnB1dHMpOwogICAgICAgICAgICB0aGlzLm91dHB1dEJ1ZmZlcnMgPSBuZXcgQXJyYXkodGhpcy5uYk91dHB1dHMpOwogICAgICAgICAgICB0aGlzLm91dHB1dEJ1ZmZlcnNUb1JldHJpZXZlID0gbmV3IEFycmF5KHRoaXMubmJPdXRwdXRzKTsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm5iSW5wdXRzOyBpKyspIHsKICAgICAgICAgICAgICAgIHRoaXMuYWxsb2NhdGVJbnB1dENoYW5uZWxzKGksIDEpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5uYk91dHB1dHM7IGkrKykgewogICAgICAgICAgICAgICAgdGhpcy5hbGxvY2F0ZU91dHB1dENoYW5uZWxzKGksIDEpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGFsbG9jYXRlSW5wdXRDaGFubmVscyhpbnB1dEluZGV4LCBuYkNoYW5uZWxzKSB7CiAgICAgICAgICAgIHRoaXMuaW5wdXRCdWZmZXJzW2lucHV0SW5kZXhdID0gbmV3IEFycmF5KG5iQ2hhbm5lbHMpOwogICAgICAgICAgICB0aGlzLmlucHV0QnVmZmVyc0hlYWRbaW5wdXRJbmRleF0gPSBuZXcgQXJyYXkobmJDaGFubmVscyk7CiAgICAgICAgICAgIHRoaXMuaW5wdXRCdWZmZXJzVG9TZW5kW2lucHV0SW5kZXhdID0gbmV3IEFycmF5KG5iQ2hhbm5lbHMpOwogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5iQ2hhbm5lbHM7IGkrKykgewogICAgICAgICAgICAgICAgdGhpcy5pbnB1dEJ1ZmZlcnNbaW5wdXRJbmRleF1baV0gPSBuZXcgRmxvYXQzMkFycmF5KHRoaXMuYmxvY2tTaXplICsgV0VCQVVESU9fQkxPQ0tfU0laRSk7CiAgICAgICAgICAgICAgICB0aGlzLmlucHV0QnVmZmVyc1tpbnB1dEluZGV4XVtpXS5maWxsKDApOwogICAgICAgICAgICAgICAgdGhpcy5pbnB1dEJ1ZmZlcnNIZWFkW2lucHV0SW5kZXhdW2ldID0gdGhpcy5pbnB1dEJ1ZmZlcnNbaW5wdXRJbmRleF1baV0uc3ViYXJyYXkoMCwgdGhpcy5ibG9ja1NpemUpOwogICAgICAgICAgICAgICAgdGhpcy5pbnB1dEJ1ZmZlcnNUb1NlbmRbaW5wdXRJbmRleF1baV0gPSBuZXcgRmxvYXQzMkFycmF5KHRoaXMuYmxvY2tTaXplKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBhbGxvY2F0ZU91dHB1dENoYW5uZWxzKG91dHB1dEluZGV4LCBuYkNoYW5uZWxzKSB7CiAgICAgICAgICAgIHRoaXMub3V0cHV0QnVmZmVyc1tvdXRwdXRJbmRleF0gPSBuZXcgQXJyYXkobmJDaGFubmVscyk7CiAgICAgICAgICAgIHRoaXMub3V0cHV0QnVmZmVyc1RvUmV0cmlldmVbb3V0cHV0SW5kZXhdID0gbmV3IEFycmF5KG5iQ2hhbm5lbHMpOwogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5iQ2hhbm5lbHM7IGkrKykgewogICAgICAgICAgICAgICAgdGhpcy5vdXRwdXRCdWZmZXJzW291dHB1dEluZGV4XVtpXSA9IG5ldyBGbG9hdDMyQXJyYXkodGhpcy5ibG9ja1NpemUpOwogICAgICAgICAgICAgICAgdGhpcy5vdXRwdXRCdWZmZXJzW291dHB1dEluZGV4XVtpXS5maWxsKDApOwogICAgICAgICAgICAgICAgdGhpcy5vdXRwdXRCdWZmZXJzVG9SZXRyaWV2ZVtvdXRwdXRJbmRleF1baV0gPSBuZXcgRmxvYXQzMkFycmF5KHRoaXMuYmxvY2tTaXplKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZWFsbG9jYXRlQ2hhbm5lbHNJZk5lZWRlZChpbnB1dHMsIG91dHB1dHMpIHsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm5iSW5wdXRzOyBpKyspIHsKICAgICAgICAgICAgICAgIGxldCBuYkNoYW5uZWxzID0gaW5wdXRzW2ldLmxlbmd0aDsKICAgICAgICAgICAgICAgIGlmIChuYkNoYW5uZWxzICE9PSB0aGlzLmlucHV0QnVmZmVyc1tpXS5sZW5ndGgpIHsKICAgICAgICAgICAgICAgICAgICB0aGlzLmFsbG9jYXRlSW5wdXRDaGFubmVscyhpLCBuYkNoYW5uZWxzKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMubmJPdXRwdXRzOyBpKyspIHsKICAgICAgICAgICAgICAgIGxldCBuYkNoYW5uZWxzID0gb3V0cHV0c1tpXS5sZW5ndGg7CiAgICAgICAgICAgICAgICBpZiAobmJDaGFubmVscyAhPT0gdGhpcy5vdXRwdXRCdWZmZXJzW2ldLmxlbmd0aCkgewogICAgICAgICAgICAgICAgICAgIHRoaXMuYWxsb2NhdGVPdXRwdXRDaGFubmVscyhpLCBuYkNoYW5uZWxzKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZWFkSW5wdXRzKGlucHV0cykgewogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMubmJJbnB1dHM7IGkrKykgewogICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCB0aGlzLmlucHV0QnVmZmVyc1tpXS5sZW5ndGg7IGorKykgewogICAgICAgICAgICAgICAgICAgIGxldCB3ZWJBdWRpb0Jsb2NrID0gaW5wdXRzW2ldW2pdOwogICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXRCdWZmZXJzW2ldW2pdLnNldCh3ZWJBdWRpb0Jsb2NrLCB0aGlzLmJsb2NrU2l6ZSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgd3JpdGVPdXRwdXRzKG91dHB1dHMpIHsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm5iT3V0cHV0czsgaSsrKSB7CiAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHRoaXMub3V0cHV0QnVmZmVyc1tpXS5sZW5ndGg7IGorKykgewogICAgICAgICAgICAgICAgICAgIGxldCB3ZWJBdWRpb0Jsb2NrID0gb3V0cHV0c1tpXVtqXTsKICAgICAgICAgICAgICAgICAgICB3ZWJBdWRpb0Jsb2NrLnNldCh0aGlzLm91dHB1dEJ1ZmZlcnNbaV1bal0uc3ViYXJyYXkoMCwgV0VCQVVESU9fQkxPQ0tfU0laRSkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHNoaWZ0SW5wdXRCdWZmZXJzKCkgewogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMubmJJbnB1dHM7IGkrKykgewogICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCB0aGlzLmlucHV0QnVmZmVyc1tpXS5sZW5ndGg7IGorKykgewogICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXRCdWZmZXJzW2ldW2pdLmNvcHlXaXRoaW4oMCwgV0VCQVVESU9fQkxPQ0tfU0laRSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgc2hpZnRPdXRwdXRCdWZmZXJzKCkgewogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMubmJPdXRwdXRzOyBpKyspIHsKICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgdGhpcy5vdXRwdXRCdWZmZXJzW2ldLmxlbmd0aDsgaisrKSB7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5vdXRwdXRCdWZmZXJzW2ldW2pdLmNvcHlXaXRoaW4oMCwgV0VCQVVESU9fQkxPQ0tfU0laRSk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5vdXRwdXRCdWZmZXJzW2ldW2pdLmZpbGwoMCwgdGhpcy5ibG9ja1NpemUgLSBXRUJBVURJT19CTE9DS19TSVpFKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBwcmVwYXJlSW5wdXRCdWZmZXJzVG9TZW5kKCkgewogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMubmJJbnB1dHM7IGkrKykgewogICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCB0aGlzLmlucHV0QnVmZmVyc1tpXS5sZW5ndGg7IGorKykgewogICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXRCdWZmZXJzVG9TZW5kW2ldW2pdLnNldCh0aGlzLmlucHV0QnVmZmVyc0hlYWRbaV1bal0pOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGhhbmRsZU91dHB1dEJ1ZmZlcnNUb1JldHJpZXZlKCkgewogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMubmJPdXRwdXRzOyBpKyspIHsKICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgdGhpcy5vdXRwdXRCdWZmZXJzW2ldLmxlbmd0aDsgaisrKSB7CiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgayA9IDA7IGsgPCB0aGlzLmJsb2NrU2l6ZTsgaysrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub3V0cHV0QnVmZmVyc1tpXVtqXVtrXSArPSB0aGlzLm91dHB1dEJ1ZmZlcnNUb1JldHJpZXZlW2ldW2pdW2tdIC8gdGhpcy5uYk92ZXJsYXBzOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBwcm9jZXNzKGlucHV0cywgb3V0cHV0cywgcGFyYW1ldGVycykgewogICAgICAgICAgICB0aGlzLnJlYWxsb2NhdGVDaGFubmVsc0lmTmVlZGVkKGlucHV0cywgb3V0cHV0cyk7CiAgICAgICAgICAgIHRoaXMucmVhZElucHV0cyhpbnB1dHMpOwogICAgICAgICAgICB0aGlzLnNoaWZ0SW5wdXRCdWZmZXJzKCk7CiAgICAgICAgICAgIHRoaXMucHJlcGFyZUlucHV0QnVmZmVyc1RvU2VuZCgpOwogICAgICAgICAgICB0aGlzLnByb2Nlc3NPTEEodGhpcy5pbnB1dEJ1ZmZlcnNUb1NlbmQsIHRoaXMub3V0cHV0QnVmZmVyc1RvUmV0cmlldmUsIHBhcmFtZXRlcnMpOwogICAgICAgICAgICB0aGlzLmhhbmRsZU91dHB1dEJ1ZmZlcnNUb1JldHJpZXZlKCk7CiAgICAgICAgICAgIHRoaXMud3JpdGVPdXRwdXRzKG91dHB1dHMpOwogICAgICAgICAgICB0aGlzLnNoaWZ0T3V0cHV0QnVmZmVycygpOwogICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICB9CgogICAgZnVuY3Rpb24gZ2V0RGVmYXVsdEV4cG9ydEZyb21DanMgKHgpIHsKICAgIAlyZXR1cm4geCAmJiB4Ll9fZXNNb2R1bGUgJiYgT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHgsICdkZWZhdWx0JykgPyB4WydkZWZhdWx0J10gOiB4OwogICAgfQoKICAgIGZ1bmN0aW9uIEZGVChzaXplKSB7CiAgICAgIHRoaXMuc2l6ZSA9IHNpemUgfCAwOwogICAgICBpZiAodGhpcy5zaXplIDw9IDEgfHwgKHRoaXMuc2l6ZSAmICh0aGlzLnNpemUgLSAxKSkgIT09IDApCiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdGRlQgc2l6ZSBtdXN0IGJlIGEgcG93ZXIgb2YgdHdvIGFuZCBiaWdnZXIgdGhhbiAxJyk7CgogICAgICB0aGlzLl9jc2l6ZSA9IHNpemUgPDwgMTsKCiAgICAgIC8vIE5PVEU6IFVzZSBvZiBgdmFyYCBpcyBpbnRlbnRpb25hbCBmb3Igb2xkIFY4IHZlcnNpb25zCiAgICAgIHZhciB0YWJsZSA9IG5ldyBBcnJheSh0aGlzLnNpemUgKiAyKTsKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0YWJsZS5sZW5ndGg7IGkgKz0gMikgewogICAgICAgIGNvbnN0IGFuZ2xlID0gTWF0aC5QSSAqIGkgLyB0aGlzLnNpemU7CiAgICAgICAgdGFibGVbaV0gPSBNYXRoLmNvcyhhbmdsZSk7CiAgICAgICAgdGFibGVbaSArIDFdID0gLU1hdGguc2luKGFuZ2xlKTsKICAgICAgfQogICAgICB0aGlzLnRhYmxlID0gdGFibGU7CgogICAgICAvLyBGaW5kIHNpemUncyBwb3dlciBvZiB0d28KICAgICAgdmFyIHBvd2VyID0gMDsKICAgICAgZm9yICh2YXIgdCA9IDE7IHRoaXMuc2l6ZSA+IHQ7IHQgPDw9IDEpCiAgICAgICAgcG93ZXIrKzsKCiAgICAgIC8vIENhbGN1bGF0ZSBpbml0aWFsIHN0ZXAncyB3aWR0aDoKICAgICAgLy8gICAqIElmIHdlIGFyZSBmdWxsIHJhZGl4LTQgLSBpdCBpcyAyeCBzbWFsbGVyIHRvIGdpdmUgaW5pdGFsIGxlbj04CiAgICAgIC8vICAgKiBPdGhlcndpc2UgaXQgaXMgdGhlIHNhbWUgYXMgYHBvd2VyYCB0byBnaXZlIGxlbj00CiAgICAgIHRoaXMuX3dpZHRoID0gcG93ZXIgJSAyID09PSAwID8gcG93ZXIgLSAxIDogcG93ZXI7CgogICAgICAvLyBQcmUtY29tcHV0ZSBiaXQtcmV2ZXJzYWwgcGF0dGVybnMKICAgICAgdGhpcy5fYml0cmV2ID0gbmV3IEFycmF5KDEgPDwgdGhpcy5fd2lkdGgpOwogICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHRoaXMuX2JpdHJldi5sZW5ndGg7IGorKykgewogICAgICAgIHRoaXMuX2JpdHJldltqXSA9IDA7CiAgICAgICAgZm9yICh2YXIgc2hpZnQgPSAwOyBzaGlmdCA8IHRoaXMuX3dpZHRoOyBzaGlmdCArPSAyKSB7CiAgICAgICAgICB2YXIgcmV2U2hpZnQgPSB0aGlzLl93aWR0aCAtIHNoaWZ0IC0gMjsKICAgICAgICAgIHRoaXMuX2JpdHJldltqXSB8PSAoKGogPj4+IHNoaWZ0KSAmIDMpIDw8IHJldlNoaWZ0OwogICAgICAgIH0KICAgICAgfQoKICAgICAgdGhpcy5fb3V0ID0gbnVsbDsKICAgICAgdGhpcy5fZGF0YSA9IG51bGw7CiAgICAgIHRoaXMuX2ludiA9IDA7CiAgICB9CiAgICB2YXIgZmZ0ID0gRkZUOwoKICAgIEZGVC5wcm90b3R5cGUuZnJvbUNvbXBsZXhBcnJheSA9IGZ1bmN0aW9uIGZyb21Db21wbGV4QXJyYXkoY29tcGxleCwgc3RvcmFnZSkgewogICAgICB2YXIgcmVzID0gc3RvcmFnZSB8fCBuZXcgQXJyYXkoY29tcGxleC5sZW5ndGggPj4+IDEpOwogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvbXBsZXgubGVuZ3RoOyBpICs9IDIpCiAgICAgICAgcmVzW2kgPj4+IDFdID0gY29tcGxleFtpXTsKICAgICAgcmV0dXJuIHJlczsKICAgIH07CgogICAgRkZULnByb3RvdHlwZS5jcmVhdGVDb21wbGV4QXJyYXkgPSBmdW5jdGlvbiBjcmVhdGVDb21wbGV4QXJyYXkoKSB7CiAgICAgIGNvbnN0IHJlcyA9IG5ldyBBcnJheSh0aGlzLl9jc2l6ZSk7CiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmVzLmxlbmd0aDsgaSsrKQogICAgICAgIHJlc1tpXSA9IDA7CiAgICAgIHJldHVybiByZXM7CiAgICB9OwoKICAgIEZGVC5wcm90b3R5cGUudG9Db21wbGV4QXJyYXkgPSBmdW5jdGlvbiB0b0NvbXBsZXhBcnJheShpbnB1dCwgc3RvcmFnZSkgewogICAgICB2YXIgcmVzID0gc3RvcmFnZSB8fCB0aGlzLmNyZWF0ZUNvbXBsZXhBcnJheSgpOwogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJlcy5sZW5ndGg7IGkgKz0gMikgewogICAgICAgIHJlc1tpXSA9IGlucHV0W2kgPj4+IDFdOwogICAgICAgIHJlc1tpICsgMV0gPSAwOwogICAgICB9CiAgICAgIHJldHVybiByZXM7CiAgICB9OwoKICAgIEZGVC5wcm90b3R5cGUuY29tcGxldGVTcGVjdHJ1bSA9IGZ1bmN0aW9uIGNvbXBsZXRlU3BlY3RydW0oc3BlY3RydW0pIHsKICAgICAgdmFyIHNpemUgPSB0aGlzLl9jc2l6ZTsKICAgICAgdmFyIGhhbGYgPSBzaXplID4+PiAxOwogICAgICBmb3IgKHZhciBpID0gMjsgaSA8IGhhbGY7IGkgKz0gMikgewogICAgICAgIHNwZWN0cnVtW3NpemUgLSBpXSA9IHNwZWN0cnVtW2ldOwogICAgICAgIHNwZWN0cnVtW3NpemUgLSBpICsgMV0gPSAtc3BlY3RydW1baSArIDFdOwogICAgICB9CiAgICB9OwoKICAgIEZGVC5wcm90b3R5cGUudHJhbnNmb3JtID0gZnVuY3Rpb24gdHJhbnNmb3JtKG91dCwgZGF0YSkgewogICAgICBpZiAob3V0ID09PSBkYXRhKQogICAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgYW5kIG91dHB1dCBidWZmZXJzIG11c3QgYmUgZGlmZmVyZW50Jyk7CgogICAgICB0aGlzLl9vdXQgPSBvdXQ7CiAgICAgIHRoaXMuX2RhdGEgPSBkYXRhOwogICAgICB0aGlzLl9pbnYgPSAwOwogICAgICB0aGlzLl90cmFuc2Zvcm00KCk7CiAgICAgIHRoaXMuX291dCA9IG51bGw7CiAgICAgIHRoaXMuX2RhdGEgPSBudWxsOwogICAgfTsKCiAgICBGRlQucHJvdG90eXBlLnJlYWxUcmFuc2Zvcm0gPSBmdW5jdGlvbiByZWFsVHJhbnNmb3JtKG91dCwgZGF0YSkgewogICAgICBpZiAob3V0ID09PSBkYXRhKQogICAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgYW5kIG91dHB1dCBidWZmZXJzIG11c3QgYmUgZGlmZmVyZW50Jyk7CgogICAgICB0aGlzLl9vdXQgPSBvdXQ7CiAgICAgIHRoaXMuX2RhdGEgPSBkYXRhOwogICAgICB0aGlzLl9pbnYgPSAwOwogICAgICB0aGlzLl9yZWFsVHJhbnNmb3JtNCgpOwogICAgICB0aGlzLl9vdXQgPSBudWxsOwogICAgICB0aGlzLl9kYXRhID0gbnVsbDsKICAgIH07CgogICAgRkZULnByb3RvdHlwZS5pbnZlcnNlVHJhbnNmb3JtID0gZnVuY3Rpb24gaW52ZXJzZVRyYW5zZm9ybShvdXQsIGRhdGEpIHsKICAgICAgaWYgKG91dCA9PT0gZGF0YSkKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IGFuZCBvdXRwdXQgYnVmZmVycyBtdXN0IGJlIGRpZmZlcmVudCcpOwoKICAgICAgdGhpcy5fb3V0ID0gb3V0OwogICAgICB0aGlzLl9kYXRhID0gZGF0YTsKICAgICAgdGhpcy5faW52ID0gMTsKICAgICAgdGhpcy5fdHJhbnNmb3JtNCgpOwogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG91dC5sZW5ndGg7IGkrKykKICAgICAgICBvdXRbaV0gLz0gdGhpcy5zaXplOwogICAgICB0aGlzLl9vdXQgPSBudWxsOwogICAgICB0aGlzLl9kYXRhID0gbnVsbDsKICAgIH07CgogICAgLy8gcmFkaXgtNCBpbXBsZW1lbnRhdGlvbgogICAgLy8KICAgIC8vIE5PVEU6IFVzZXMgb2YgYHZhcmAgYXJlIGludGVudGlvbmFsIGZvciBvbGRlciBWOCB2ZXJzaW9uIHRoYXQgZG8gbm90CiAgICAvLyBzdXBwb3J0IGJvdGggYGxldCBjb21wb3VuZCBhc3NpZ25tZW50c2AgYW5kIGBjb25zdCBwaGlgCiAgICBGRlQucHJvdG90eXBlLl90cmFuc2Zvcm00ID0gZnVuY3Rpb24gX3RyYW5zZm9ybTQoKSB7CiAgICAgIHZhciBvdXQgPSB0aGlzLl9vdXQ7CiAgICAgIHZhciBzaXplID0gdGhpcy5fY3NpemU7CgogICAgICAvLyBJbml0aWFsIHN0ZXAgKHBlcm11dGUgYW5kIHRyYW5zZm9ybSkKICAgICAgdmFyIHdpZHRoID0gdGhpcy5fd2lkdGg7CiAgICAgIHZhciBzdGVwID0gMSA8PCB3aWR0aDsKICAgICAgdmFyIGxlbiA9IChzaXplIC8gc3RlcCkgPDwgMTsKCiAgICAgIHZhciBvdXRPZmY7CiAgICAgIHZhciB0OwogICAgICB2YXIgYml0cmV2ID0gdGhpcy5fYml0cmV2OwogICAgICBpZiAobGVuID09PSA0KSB7CiAgICAgICAgZm9yIChvdXRPZmYgPSAwLCB0ID0gMDsgb3V0T2ZmIDwgc2l6ZTsgb3V0T2ZmICs9IGxlbiwgdCsrKSB7CiAgICAgICAgICBjb25zdCBvZmYgPSBiaXRyZXZbdF07CiAgICAgICAgICB0aGlzLl9zaW5nbGVUcmFuc2Zvcm0yKG91dE9mZiwgb2ZmLCBzdGVwKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgLy8gbGVuID09PSA4CiAgICAgICAgZm9yIChvdXRPZmYgPSAwLCB0ID0gMDsgb3V0T2ZmIDwgc2l6ZTsgb3V0T2ZmICs9IGxlbiwgdCsrKSB7CiAgICAgICAgICBjb25zdCBvZmYgPSBiaXRyZXZbdF07CiAgICAgICAgICB0aGlzLl9zaW5nbGVUcmFuc2Zvcm00KG91dE9mZiwgb2ZmLCBzdGVwKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIC8vIExvb3AgdGhyb3VnaCBzdGVwcyBpbiBkZWNyZWFzaW5nIG9yZGVyCiAgICAgIHZhciBpbnYgPSB0aGlzLl9pbnYgPyAtMSA6IDE7CiAgICAgIHZhciB0YWJsZSA9IHRoaXMudGFibGU7CiAgICAgIGZvciAoc3RlcCA+Pj0gMjsgc3RlcCA+PSAyOyBzdGVwID4+PSAyKSB7CiAgICAgICAgbGVuID0gKHNpemUgLyBzdGVwKSA8PCAxOwogICAgICAgIHZhciBxdWFydGVyTGVuID0gbGVuID4+PiAyOwoKICAgICAgICAvLyBMb29wIHRocm91Z2ggb2Zmc2V0cyBpbiB0aGUgZGF0YQogICAgICAgIGZvciAob3V0T2ZmID0gMDsgb3V0T2ZmIDwgc2l6ZTsgb3V0T2ZmICs9IGxlbikgewogICAgICAgICAgLy8gRnVsbCBjYXNlCiAgICAgICAgICB2YXIgbGltaXQgPSBvdXRPZmYgKyBxdWFydGVyTGVuOwogICAgICAgICAgZm9yICh2YXIgaSA9IG91dE9mZiwgayA9IDA7IGkgPCBsaW1pdDsgaSArPSAyLCBrICs9IHN0ZXApIHsKICAgICAgICAgICAgY29uc3QgQSA9IGk7CiAgICAgICAgICAgIGNvbnN0IEIgPSBBICsgcXVhcnRlckxlbjsKICAgICAgICAgICAgY29uc3QgQyA9IEIgKyBxdWFydGVyTGVuOwogICAgICAgICAgICBjb25zdCBEID0gQyArIHF1YXJ0ZXJMZW47CgogICAgICAgICAgICAvLyBPcmlnaW5hbCB2YWx1ZXMKICAgICAgICAgICAgY29uc3QgQXIgPSBvdXRbQV07CiAgICAgICAgICAgIGNvbnN0IEFpID0gb3V0W0EgKyAxXTsKICAgICAgICAgICAgY29uc3QgQnIgPSBvdXRbQl07CiAgICAgICAgICAgIGNvbnN0IEJpID0gb3V0W0IgKyAxXTsKICAgICAgICAgICAgY29uc3QgQ3IgPSBvdXRbQ107CiAgICAgICAgICAgIGNvbnN0IENpID0gb3V0W0MgKyAxXTsKICAgICAgICAgICAgY29uc3QgRHIgPSBvdXRbRF07CiAgICAgICAgICAgIGNvbnN0IERpID0gb3V0W0QgKyAxXTsKCiAgICAgICAgICAgIC8vIE1pZGRsZSB2YWx1ZXMKICAgICAgICAgICAgY29uc3QgTUFyID0gQXI7CiAgICAgICAgICAgIGNvbnN0IE1BaSA9IEFpOwoKICAgICAgICAgICAgY29uc3QgdGFibGVCciA9IHRhYmxlW2tdOwogICAgICAgICAgICBjb25zdCB0YWJsZUJpID0gaW52ICogdGFibGVbayArIDFdOwogICAgICAgICAgICBjb25zdCBNQnIgPSBCciAqIHRhYmxlQnIgLSBCaSAqIHRhYmxlQmk7CiAgICAgICAgICAgIGNvbnN0IE1CaSA9IEJyICogdGFibGVCaSArIEJpICogdGFibGVCcjsKCiAgICAgICAgICAgIGNvbnN0IHRhYmxlQ3IgPSB0YWJsZVsyICoga107CiAgICAgICAgICAgIGNvbnN0IHRhYmxlQ2kgPSBpbnYgKiB0YWJsZVsyICogayArIDFdOwogICAgICAgICAgICBjb25zdCBNQ3IgPSBDciAqIHRhYmxlQ3IgLSBDaSAqIHRhYmxlQ2k7CiAgICAgICAgICAgIGNvbnN0IE1DaSA9IENyICogdGFibGVDaSArIENpICogdGFibGVDcjsKCiAgICAgICAgICAgIGNvbnN0IHRhYmxlRHIgPSB0YWJsZVszICoga107CiAgICAgICAgICAgIGNvbnN0IHRhYmxlRGkgPSBpbnYgKiB0YWJsZVszICogayArIDFdOwogICAgICAgICAgICBjb25zdCBNRHIgPSBEciAqIHRhYmxlRHIgLSBEaSAqIHRhYmxlRGk7CiAgICAgICAgICAgIGNvbnN0IE1EaSA9IERyICogdGFibGVEaSArIERpICogdGFibGVEcjsKCiAgICAgICAgICAgIC8vIFByZS1GaW5hbCB2YWx1ZXMKICAgICAgICAgICAgY29uc3QgVDByID0gTUFyICsgTUNyOwogICAgICAgICAgICBjb25zdCBUMGkgPSBNQWkgKyBNQ2k7CiAgICAgICAgICAgIGNvbnN0IFQxciA9IE1BciAtIE1DcjsKICAgICAgICAgICAgY29uc3QgVDFpID0gTUFpIC0gTUNpOwogICAgICAgICAgICBjb25zdCBUMnIgPSBNQnIgKyBNRHI7CiAgICAgICAgICAgIGNvbnN0IFQyaSA9IE1CaSArIE1EaTsKICAgICAgICAgICAgY29uc3QgVDNyID0gaW52ICogKE1CciAtIE1Ecik7CiAgICAgICAgICAgIGNvbnN0IFQzaSA9IGludiAqIChNQmkgLSBNRGkpOwoKICAgICAgICAgICAgLy8gRmluYWwgdmFsdWVzCiAgICAgICAgICAgIGNvbnN0IEZBciA9IFQwciArIFQycjsKICAgICAgICAgICAgY29uc3QgRkFpID0gVDBpICsgVDJpOwoKICAgICAgICAgICAgY29uc3QgRkNyID0gVDByIC0gVDJyOwogICAgICAgICAgICBjb25zdCBGQ2kgPSBUMGkgLSBUMmk7CgogICAgICAgICAgICBjb25zdCBGQnIgPSBUMXIgKyBUM2k7CiAgICAgICAgICAgIGNvbnN0IEZCaSA9IFQxaSAtIFQzcjsKCiAgICAgICAgICAgIGNvbnN0IEZEciA9IFQxciAtIFQzaTsKICAgICAgICAgICAgY29uc3QgRkRpID0gVDFpICsgVDNyOwoKICAgICAgICAgICAgb3V0W0FdID0gRkFyOwogICAgICAgICAgICBvdXRbQSArIDFdID0gRkFpOwogICAgICAgICAgICBvdXRbQl0gPSBGQnI7CiAgICAgICAgICAgIG91dFtCICsgMV0gPSBGQmk7CiAgICAgICAgICAgIG91dFtDXSA9IEZDcjsKICAgICAgICAgICAgb3V0W0MgKyAxXSA9IEZDaTsKICAgICAgICAgICAgb3V0W0RdID0gRkRyOwogICAgICAgICAgICBvdXRbRCArIDFdID0gRkRpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfTsKCiAgICAvLyByYWRpeC0yIGltcGxlbWVudGF0aW9uCiAgICAvLwogICAgLy8gTk9URTogT25seSBjYWxsZWQgZm9yIGxlbj00CiAgICBGRlQucHJvdG90eXBlLl9zaW5nbGVUcmFuc2Zvcm0yID0gZnVuY3Rpb24gX3NpbmdsZVRyYW5zZm9ybTIob3V0T2ZmLCBvZmYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RlcCkgewogICAgICBjb25zdCBvdXQgPSB0aGlzLl9vdXQ7CiAgICAgIGNvbnN0IGRhdGEgPSB0aGlzLl9kYXRhOwoKICAgICAgY29uc3QgZXZlblIgPSBkYXRhW29mZl07CiAgICAgIGNvbnN0IGV2ZW5JID0gZGF0YVtvZmYgKyAxXTsKICAgICAgY29uc3Qgb2RkUiA9IGRhdGFbb2ZmICsgc3RlcF07CiAgICAgIGNvbnN0IG9kZEkgPSBkYXRhW29mZiArIHN0ZXAgKyAxXTsKCiAgICAgIGNvbnN0IGxlZnRSID0gZXZlblIgKyBvZGRSOwogICAgICBjb25zdCBsZWZ0SSA9IGV2ZW5JICsgb2RkSTsKICAgICAgY29uc3QgcmlnaHRSID0gZXZlblIgLSBvZGRSOwogICAgICBjb25zdCByaWdodEkgPSBldmVuSSAtIG9kZEk7CgogICAgICBvdXRbb3V0T2ZmXSA9IGxlZnRSOwogICAgICBvdXRbb3V0T2ZmICsgMV0gPSBsZWZ0STsKICAgICAgb3V0W291dE9mZiArIDJdID0gcmlnaHRSOwogICAgICBvdXRbb3V0T2ZmICsgM10gPSByaWdodEk7CiAgICB9OwoKICAgIC8vIHJhZGl4LTQKICAgIC8vCiAgICAvLyBOT1RFOiBPbmx5IGNhbGxlZCBmb3IgbGVuPTgKICAgIEZGVC5wcm90b3R5cGUuX3NpbmdsZVRyYW5zZm9ybTQgPSBmdW5jdGlvbiBfc2luZ2xlVHJhbnNmb3JtNChvdXRPZmYsIG9mZiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGVwKSB7CiAgICAgIGNvbnN0IG91dCA9IHRoaXMuX291dDsKICAgICAgY29uc3QgZGF0YSA9IHRoaXMuX2RhdGE7CiAgICAgIGNvbnN0IGludiA9IHRoaXMuX2ludiA/IC0xIDogMTsKICAgICAgY29uc3Qgc3RlcDIgPSBzdGVwICogMjsKICAgICAgY29uc3Qgc3RlcDMgPSBzdGVwICogMzsKCiAgICAgIC8vIE9yaWdpbmFsIHZhbHVlcwogICAgICBjb25zdCBBciA9IGRhdGFbb2ZmXTsKICAgICAgY29uc3QgQWkgPSBkYXRhW29mZiArIDFdOwogICAgICBjb25zdCBCciA9IGRhdGFbb2ZmICsgc3RlcF07CiAgICAgIGNvbnN0IEJpID0gZGF0YVtvZmYgKyBzdGVwICsgMV07CiAgICAgIGNvbnN0IENyID0gZGF0YVtvZmYgKyBzdGVwMl07CiAgICAgIGNvbnN0IENpID0gZGF0YVtvZmYgKyBzdGVwMiArIDFdOwogICAgICBjb25zdCBEciA9IGRhdGFbb2ZmICsgc3RlcDNdOwogICAgICBjb25zdCBEaSA9IGRhdGFbb2ZmICsgc3RlcDMgKyAxXTsKCiAgICAgIC8vIFByZS1GaW5hbCB2YWx1ZXMKICAgICAgY29uc3QgVDByID0gQXIgKyBDcjsKICAgICAgY29uc3QgVDBpID0gQWkgKyBDaTsKICAgICAgY29uc3QgVDFyID0gQXIgLSBDcjsKICAgICAgY29uc3QgVDFpID0gQWkgLSBDaTsKICAgICAgY29uc3QgVDJyID0gQnIgKyBEcjsKICAgICAgY29uc3QgVDJpID0gQmkgKyBEaTsKICAgICAgY29uc3QgVDNyID0gaW52ICogKEJyIC0gRHIpOwogICAgICBjb25zdCBUM2kgPSBpbnYgKiAoQmkgLSBEaSk7CgogICAgICAvLyBGaW5hbCB2YWx1ZXMKICAgICAgY29uc3QgRkFyID0gVDByICsgVDJyOwogICAgICBjb25zdCBGQWkgPSBUMGkgKyBUMmk7CgogICAgICBjb25zdCBGQnIgPSBUMXIgKyBUM2k7CiAgICAgIGNvbnN0IEZCaSA9IFQxaSAtIFQzcjsKCiAgICAgIGNvbnN0IEZDciA9IFQwciAtIFQycjsKICAgICAgY29uc3QgRkNpID0gVDBpIC0gVDJpOwoKICAgICAgY29uc3QgRkRyID0gVDFyIC0gVDNpOwogICAgICBjb25zdCBGRGkgPSBUMWkgKyBUM3I7CgogICAgICBvdXRbb3V0T2ZmXSA9IEZBcjsKICAgICAgb3V0W291dE9mZiArIDFdID0gRkFpOwogICAgICBvdXRbb3V0T2ZmICsgMl0gPSBGQnI7CiAgICAgIG91dFtvdXRPZmYgKyAzXSA9IEZCaTsKICAgICAgb3V0W291dE9mZiArIDRdID0gRkNyOwogICAgICBvdXRbb3V0T2ZmICsgNV0gPSBGQ2k7CiAgICAgIG91dFtvdXRPZmYgKyA2XSA9IEZEcjsKICAgICAgb3V0W291dE9mZiArIDddID0gRkRpOwogICAgfTsKCiAgICAvLyBSZWFsIGlucHV0IHJhZGl4LTQgaW1wbGVtZW50YXRpb24KICAgIEZGVC5wcm90b3R5cGUuX3JlYWxUcmFuc2Zvcm00ID0gZnVuY3Rpb24gX3JlYWxUcmFuc2Zvcm00KCkgewogICAgICB2YXIgb3V0ID0gdGhpcy5fb3V0OwogICAgICB2YXIgc2l6ZSA9IHRoaXMuX2NzaXplOwoKICAgICAgLy8gSW5pdGlhbCBzdGVwIChwZXJtdXRlIGFuZCB0cmFuc2Zvcm0pCiAgICAgIHZhciB3aWR0aCA9IHRoaXMuX3dpZHRoOwogICAgICB2YXIgc3RlcCA9IDEgPDwgd2lkdGg7CiAgICAgIHZhciBsZW4gPSAoc2l6ZSAvIHN0ZXApIDw8IDE7CgogICAgICB2YXIgb3V0T2ZmOwogICAgICB2YXIgdDsKICAgICAgdmFyIGJpdHJldiA9IHRoaXMuX2JpdHJldjsKICAgICAgaWYgKGxlbiA9PT0gNCkgewogICAgICAgIGZvciAob3V0T2ZmID0gMCwgdCA9IDA7IG91dE9mZiA8IHNpemU7IG91dE9mZiArPSBsZW4sIHQrKykgewogICAgICAgICAgY29uc3Qgb2ZmID0gYml0cmV2W3RdOwogICAgICAgICAgdGhpcy5fc2luZ2xlUmVhbFRyYW5zZm9ybTIob3V0T2ZmLCBvZmYgPj4+IDEsIHN0ZXAgPj4+IDEpOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICAvLyBsZW4gPT09IDgKICAgICAgICBmb3IgKG91dE9mZiA9IDAsIHQgPSAwOyBvdXRPZmYgPCBzaXplOyBvdXRPZmYgKz0gbGVuLCB0KyspIHsKICAgICAgICAgIGNvbnN0IG9mZiA9IGJpdHJldlt0XTsKICAgICAgICAgIHRoaXMuX3NpbmdsZVJlYWxUcmFuc2Zvcm00KG91dE9mZiwgb2ZmID4+PiAxLCBzdGVwID4+PiAxKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIC8vIExvb3AgdGhyb3VnaCBzdGVwcyBpbiBkZWNyZWFzaW5nIG9yZGVyCiAgICAgIHZhciBpbnYgPSB0aGlzLl9pbnYgPyAtMSA6IDE7CiAgICAgIHZhciB0YWJsZSA9IHRoaXMudGFibGU7CiAgICAgIGZvciAoc3RlcCA+Pj0gMjsgc3RlcCA+PSAyOyBzdGVwID4+PSAyKSB7CiAgICAgICAgbGVuID0gKHNpemUgLyBzdGVwKSA8PCAxOwogICAgICAgIHZhciBoYWxmTGVuID0gbGVuID4+PiAxOwogICAgICAgIHZhciBxdWFydGVyTGVuID0gaGFsZkxlbiA+Pj4gMTsKICAgICAgICB2YXIgaHF1YXJ0ZXJMZW4gPSBxdWFydGVyTGVuID4+PiAxOwoKICAgICAgICAvLyBMb29wIHRocm91Z2ggb2Zmc2V0cyBpbiB0aGUgZGF0YQogICAgICAgIGZvciAob3V0T2ZmID0gMDsgb3V0T2ZmIDwgc2l6ZTsgb3V0T2ZmICs9IGxlbikgewogICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGsgPSAwOyBpIDw9IGhxdWFydGVyTGVuOyBpICs9IDIsIGsgKz0gc3RlcCkgewogICAgICAgICAgICB2YXIgQSA9IG91dE9mZiArIGk7CiAgICAgICAgICAgIHZhciBCID0gQSArIHF1YXJ0ZXJMZW47CiAgICAgICAgICAgIHZhciBDID0gQiArIHF1YXJ0ZXJMZW47CiAgICAgICAgICAgIHZhciBEID0gQyArIHF1YXJ0ZXJMZW47CgogICAgICAgICAgICAvLyBPcmlnaW5hbCB2YWx1ZXMKICAgICAgICAgICAgdmFyIEFyID0gb3V0W0FdOwogICAgICAgICAgICB2YXIgQWkgPSBvdXRbQSArIDFdOwogICAgICAgICAgICB2YXIgQnIgPSBvdXRbQl07CiAgICAgICAgICAgIHZhciBCaSA9IG91dFtCICsgMV07CiAgICAgICAgICAgIHZhciBDciA9IG91dFtDXTsKICAgICAgICAgICAgdmFyIENpID0gb3V0W0MgKyAxXTsKICAgICAgICAgICAgdmFyIERyID0gb3V0W0RdOwogICAgICAgICAgICB2YXIgRGkgPSBvdXRbRCArIDFdOwoKICAgICAgICAgICAgLy8gTWlkZGxlIHZhbHVlcwogICAgICAgICAgICB2YXIgTUFyID0gQXI7CiAgICAgICAgICAgIHZhciBNQWkgPSBBaTsKCiAgICAgICAgICAgIHZhciB0YWJsZUJyID0gdGFibGVba107CiAgICAgICAgICAgIHZhciB0YWJsZUJpID0gaW52ICogdGFibGVbayArIDFdOwogICAgICAgICAgICB2YXIgTUJyID0gQnIgKiB0YWJsZUJyIC0gQmkgKiB0YWJsZUJpOwogICAgICAgICAgICB2YXIgTUJpID0gQnIgKiB0YWJsZUJpICsgQmkgKiB0YWJsZUJyOwoKICAgICAgICAgICAgdmFyIHRhYmxlQ3IgPSB0YWJsZVsyICoga107CiAgICAgICAgICAgIHZhciB0YWJsZUNpID0gaW52ICogdGFibGVbMiAqIGsgKyAxXTsKICAgICAgICAgICAgdmFyIE1DciA9IENyICogdGFibGVDciAtIENpICogdGFibGVDaTsKICAgICAgICAgICAgdmFyIE1DaSA9IENyICogdGFibGVDaSArIENpICogdGFibGVDcjsKCiAgICAgICAgICAgIHZhciB0YWJsZURyID0gdGFibGVbMyAqIGtdOwogICAgICAgICAgICB2YXIgdGFibGVEaSA9IGludiAqIHRhYmxlWzMgKiBrICsgMV07CiAgICAgICAgICAgIHZhciBNRHIgPSBEciAqIHRhYmxlRHIgLSBEaSAqIHRhYmxlRGk7CiAgICAgICAgICAgIHZhciBNRGkgPSBEciAqIHRhYmxlRGkgKyBEaSAqIHRhYmxlRHI7CgogICAgICAgICAgICAvLyBQcmUtRmluYWwgdmFsdWVzCiAgICAgICAgICAgIHZhciBUMHIgPSBNQXIgKyBNQ3I7CiAgICAgICAgICAgIHZhciBUMGkgPSBNQWkgKyBNQ2k7CiAgICAgICAgICAgIHZhciBUMXIgPSBNQXIgLSBNQ3I7CiAgICAgICAgICAgIHZhciBUMWkgPSBNQWkgLSBNQ2k7CiAgICAgICAgICAgIHZhciBUMnIgPSBNQnIgKyBNRHI7CiAgICAgICAgICAgIHZhciBUMmkgPSBNQmkgKyBNRGk7CiAgICAgICAgICAgIHZhciBUM3IgPSBpbnYgKiAoTUJyIC0gTURyKTsKICAgICAgICAgICAgdmFyIFQzaSA9IGludiAqIChNQmkgLSBNRGkpOwoKICAgICAgICAgICAgLy8gRmluYWwgdmFsdWVzCiAgICAgICAgICAgIHZhciBGQXIgPSBUMHIgKyBUMnI7CiAgICAgICAgICAgIHZhciBGQWkgPSBUMGkgKyBUMmk7CgogICAgICAgICAgICB2YXIgRkJyID0gVDFyICsgVDNpOwogICAgICAgICAgICB2YXIgRkJpID0gVDFpIC0gVDNyOwoKICAgICAgICAgICAgb3V0W0FdID0gRkFyOwogICAgICAgICAgICBvdXRbQSArIDFdID0gRkFpOwogICAgICAgICAgICBvdXRbQl0gPSBGQnI7CiAgICAgICAgICAgIG91dFtCICsgMV0gPSBGQmk7CgogICAgICAgICAgICAvLyBPdXRwdXQgZmluYWwgbWlkZGxlIHBvaW50CiAgICAgICAgICAgIGlmIChpID09PSAwKSB7CiAgICAgICAgICAgICAgdmFyIEZDciA9IFQwciAtIFQycjsKICAgICAgICAgICAgICB2YXIgRkNpID0gVDBpIC0gVDJpOwogICAgICAgICAgICAgIG91dFtDXSA9IEZDcjsKICAgICAgICAgICAgICBvdXRbQyArIDFdID0gRkNpOwogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CgogICAgICAgICAgICAvLyBEbyBub3Qgb3ZlcndyaXRlIG91cnNlbHZlcwogICAgICAgICAgICBpZiAoaSA9PT0gaHF1YXJ0ZXJMZW4pCiAgICAgICAgICAgICAgY29udGludWU7CgogICAgICAgICAgICAvLyBJbiB0aGUgZmxpcHBlZCBjYXNlOgogICAgICAgICAgICAvLyBNQWkgPSAtTUFpCiAgICAgICAgICAgIC8vIE1Ccj0tTUJpLCBNQmk9LU1CcgogICAgICAgICAgICAvLyBNQ3I9LU1DcgogICAgICAgICAgICAvLyBNRHI9TURpLCBNRGk9TURyCiAgICAgICAgICAgIHZhciBTVDByID0gVDFyOwogICAgICAgICAgICB2YXIgU1QwaSA9IC1UMWk7CiAgICAgICAgICAgIHZhciBTVDFyID0gVDByOwogICAgICAgICAgICB2YXIgU1QxaSA9IC1UMGk7CiAgICAgICAgICAgIHZhciBTVDJyID0gLWludiAqIFQzaTsKICAgICAgICAgICAgdmFyIFNUMmkgPSAtaW52ICogVDNyOwogICAgICAgICAgICB2YXIgU1QzciA9IC1pbnYgKiBUMmk7CiAgICAgICAgICAgIHZhciBTVDNpID0gLWludiAqIFQycjsKCiAgICAgICAgICAgIHZhciBTRkFyID0gU1QwciArIFNUMnI7CiAgICAgICAgICAgIHZhciBTRkFpID0gU1QwaSArIFNUMmk7CgogICAgICAgICAgICB2YXIgU0ZCciA9IFNUMXIgKyBTVDNpOwogICAgICAgICAgICB2YXIgU0ZCaSA9IFNUMWkgLSBTVDNyOwoKICAgICAgICAgICAgdmFyIFNBID0gb3V0T2ZmICsgcXVhcnRlckxlbiAtIGk7CiAgICAgICAgICAgIHZhciBTQiA9IG91dE9mZiArIGhhbGZMZW4gLSBpOwoKICAgICAgICAgICAgb3V0W1NBXSA9IFNGQXI7CiAgICAgICAgICAgIG91dFtTQSArIDFdID0gU0ZBaTsKICAgICAgICAgICAgb3V0W1NCXSA9IFNGQnI7CiAgICAgICAgICAgIG91dFtTQiArIDFdID0gU0ZCaTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH07CgogICAgLy8gcmFkaXgtMiBpbXBsZW1lbnRhdGlvbgogICAgLy8KICAgIC8vIE5PVEU6IE9ubHkgY2FsbGVkIGZvciBsZW49NAogICAgRkZULnByb3RvdHlwZS5fc2luZ2xlUmVhbFRyYW5zZm9ybTIgPSBmdW5jdGlvbiBfc2luZ2xlUmVhbFRyYW5zZm9ybTIob3V0T2ZmLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb2ZmLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RlcCkgewogICAgICBjb25zdCBvdXQgPSB0aGlzLl9vdXQ7CiAgICAgIGNvbnN0IGRhdGEgPSB0aGlzLl9kYXRhOwoKICAgICAgY29uc3QgZXZlblIgPSBkYXRhW29mZl07CiAgICAgIGNvbnN0IG9kZFIgPSBkYXRhW29mZiArIHN0ZXBdOwoKICAgICAgY29uc3QgbGVmdFIgPSBldmVuUiArIG9kZFI7CiAgICAgIGNvbnN0IHJpZ2h0UiA9IGV2ZW5SIC0gb2RkUjsKCiAgICAgIG91dFtvdXRPZmZdID0gbGVmdFI7CiAgICAgIG91dFtvdXRPZmYgKyAxXSA9IDA7CiAgICAgIG91dFtvdXRPZmYgKyAyXSA9IHJpZ2h0UjsKICAgICAgb3V0W291dE9mZiArIDNdID0gMDsKICAgIH07CgogICAgLy8gcmFkaXgtNAogICAgLy8KICAgIC8vIE5PVEU6IE9ubHkgY2FsbGVkIGZvciBsZW49OAogICAgRkZULnByb3RvdHlwZS5fc2luZ2xlUmVhbFRyYW5zZm9ybTQgPSBmdW5jdGlvbiBfc2luZ2xlUmVhbFRyYW5zZm9ybTQob3V0T2ZmLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb2ZmLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RlcCkgewogICAgICBjb25zdCBvdXQgPSB0aGlzLl9vdXQ7CiAgICAgIGNvbnN0IGRhdGEgPSB0aGlzLl9kYXRhOwogICAgICBjb25zdCBpbnYgPSB0aGlzLl9pbnYgPyAtMSA6IDE7CiAgICAgIGNvbnN0IHN0ZXAyID0gc3RlcCAqIDI7CiAgICAgIGNvbnN0IHN0ZXAzID0gc3RlcCAqIDM7CgogICAgICAvLyBPcmlnaW5hbCB2YWx1ZXMKICAgICAgY29uc3QgQXIgPSBkYXRhW29mZl07CiAgICAgIGNvbnN0IEJyID0gZGF0YVtvZmYgKyBzdGVwXTsKICAgICAgY29uc3QgQ3IgPSBkYXRhW29mZiArIHN0ZXAyXTsKICAgICAgY29uc3QgRHIgPSBkYXRhW29mZiArIHN0ZXAzXTsKCiAgICAgIC8vIFByZS1GaW5hbCB2YWx1ZXMKICAgICAgY29uc3QgVDByID0gQXIgKyBDcjsKICAgICAgY29uc3QgVDFyID0gQXIgLSBDcjsKICAgICAgY29uc3QgVDJyID0gQnIgKyBEcjsKICAgICAgY29uc3QgVDNyID0gaW52ICogKEJyIC0gRHIpOwoKICAgICAgLy8gRmluYWwgdmFsdWVzCiAgICAgIGNvbnN0IEZBciA9IFQwciArIFQycjsKCiAgICAgIGNvbnN0IEZCciA9IFQxcjsKICAgICAgY29uc3QgRkJpID0gLVQzcjsKCiAgICAgIGNvbnN0IEZDciA9IFQwciAtIFQycjsKCiAgICAgIGNvbnN0IEZEciA9IFQxcjsKICAgICAgY29uc3QgRkRpID0gVDNyOwoKICAgICAgb3V0W291dE9mZl0gPSBGQXI7CiAgICAgIG91dFtvdXRPZmYgKyAxXSA9IDA7CiAgICAgIG91dFtvdXRPZmYgKyAyXSA9IEZCcjsKICAgICAgb3V0W291dE9mZiArIDNdID0gRkJpOwogICAgICBvdXRbb3V0T2ZmICsgNF0gPSBGQ3I7CiAgICAgIG91dFtvdXRPZmYgKyA1XSA9IDA7CiAgICAgIG91dFtvdXRPZmYgKyA2XSA9IEZEcjsKICAgICAgb3V0W291dE9mZiArIDddID0gRkRpOwogICAgfTsKCiAgICB2YXIgRkZUJDEgPSAvKkBfX1BVUkVfXyovZ2V0RGVmYXVsdEV4cG9ydEZyb21DanMoZmZ0KTsKCiAgICBjb25zdCBCVUZGRVJFRF9CTE9DS19TSVpFID0gMjA0ODsKICAgIGZ1bmN0aW9uIGdlbkhhbm5XaW5kb3cobGVuZ3RoKSB7CiAgICAgICAgbGV0IHdpbiA9IG5ldyBGbG9hdDMyQXJyYXkobGVuZ3RoKTsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIHdpbltpXSA9IDAuNSAqICgxIC0gTWF0aC5jb3MoMiAqIE1hdGguUEkgKiBpIC8gbGVuZ3RoKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB3aW47CiAgICB9CiAgICBjbGFzcyBQaGFzZVZvY29kZXJQcm9jZXNzb3IgZXh0ZW5kcyBPTEFQcm9jZXNzb3IgewogICAgICAgIGZmdFNpemU7CiAgICAgICAgdGltZUN1cnNvcjsKICAgICAgICBoYW5uV2luZG93OwogICAgICAgIGZmdDsKICAgICAgICBmcmVxQ29tcGxleEJ1ZmZlcjsKICAgICAgICBmcmVxQ29tcGxleEJ1ZmZlclNoaWZ0ZWQ7CiAgICAgICAgdGltZUNvbXBsZXhCdWZmZXI7CiAgICAgICAgbWFnbml0dWRlczsKICAgICAgICBwZWFrSW5kZXhlczsKICAgICAgICBuYlBlYWtzOwogICAgICAgIHN0YXRpYyBnZXQgcGFyYW1ldGVyRGVzY3JpcHRvcnMoKSB7CiAgICAgICAgICAgIHJldHVybiBbewogICAgICAgICAgICAgICAgICAgIG5hbWU6ICdwaXRjaEZhY3RvcicsCiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdFZhbHVlOiAxLjAKICAgICAgICAgICAgICAgIH1dOwogICAgICAgIH0KICAgICAgICBjb25zdHJ1Y3RvcihvcHRpb25zKSB7CiAgICAgICAgICAgIG9wdGlvbnMucHJvY2Vzc29yT3B0aW9ucyA9IHsKICAgICAgICAgICAgICAgIGJsb2NrU2l6ZTogQlVGRkVSRURfQkxPQ0tfU0laRSwKICAgICAgICAgICAgfTsKICAgICAgICAgICAgc3VwZXIob3B0aW9ucyk7CiAgICAgICAgICAgIHRoaXMuZmZ0U2l6ZSA9IHRoaXMuYmxvY2tTaXplOwogICAgICAgICAgICB0aGlzLnRpbWVDdXJzb3IgPSAwOwogICAgICAgICAgICB0aGlzLmhhbm5XaW5kb3cgPSBnZW5IYW5uV2luZG93KHRoaXMuYmxvY2tTaXplKTsKICAgICAgICAgICAgLy8gcHJlcGFyZSBGRlQgYW5kIHByZS1hbGxvY2F0ZSBidWZmZXJzCiAgICAgICAgICAgIHRoaXMuZmZ0ID0gbmV3IEZGVCQxKHRoaXMuZmZ0U2l6ZSk7CiAgICAgICAgICAgIHRoaXMuZnJlcUNvbXBsZXhCdWZmZXIgPSB0aGlzLmZmdC5jcmVhdGVDb21wbGV4QXJyYXkoKTsKICAgICAgICAgICAgdGhpcy5mcmVxQ29tcGxleEJ1ZmZlclNoaWZ0ZWQgPSB0aGlzLmZmdC5jcmVhdGVDb21wbGV4QXJyYXkoKTsKICAgICAgICAgICAgdGhpcy50aW1lQ29tcGxleEJ1ZmZlciA9IHRoaXMuZmZ0LmNyZWF0ZUNvbXBsZXhBcnJheSgpOwogICAgICAgICAgICB0aGlzLm1hZ25pdHVkZXMgPSBuZXcgRmxvYXQzMkFycmF5KHRoaXMuZmZ0U2l6ZSAvIDIgKyAxKTsKICAgICAgICAgICAgdGhpcy5wZWFrSW5kZXhlcyA9IG5ldyBJbnQzMkFycmF5KHRoaXMubWFnbml0dWRlcy5sZW5ndGgpOwogICAgICAgICAgICB0aGlzLm5iUGVha3MgPSAwOwogICAgICAgIH0KICAgICAgICBwcm9jZXNzT0xBKGlucHV0cywgb3V0cHV0cywgcGFyYW1ldGVycykgewogICAgICAgICAgICAvLyBAdHMtaWdub3JlCiAgICAgICAgICAgIGNvbnN0IHBpdGNoRmFjdG9yID0gcGFyYW1ldGVycy5waXRjaEZhY3RvcltwYXJhbWV0ZXJzLnBpdGNoRmFjdG9yLmxlbmd0aCAtIDFdOwogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMubmJJbnB1dHM7IGkrKykgewogICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBpbnB1dHNbaV0ubGVuZ3RoOyBqKyspIHsKICAgICAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSBpbnB1dHNbaV1bal07CiAgICAgICAgICAgICAgICAgICAgdmFyIG91dHB1dCA9IG91dHB1dHNbaV1bal07CiAgICAgICAgICAgICAgICAgICAgdGhpcy5hcHBseUhhbm5XaW5kb3coaW5wdXQpOwogICAgICAgICAgICAgICAgICAgIHRoaXMuZmZ0LnJlYWxUcmFuc2Zvcm0odGhpcy5mcmVxQ29tcGxleEJ1ZmZlciwgaW5wdXQpOwogICAgICAgICAgICAgICAgICAgIHRoaXMuY29tcHV0ZU1hZ25pdHVkZXMoKTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmZpbmRQZWFrcygpOwogICAgICAgICAgICAgICAgICAgIHRoaXMuc2hpZnRQZWFrcyhwaXRjaEZhY3Rvcik7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5mZnQuY29tcGxldGVTcGVjdHJ1bSh0aGlzLmZyZXFDb21wbGV4QnVmZmVyU2hpZnRlZCk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5mZnQuaW52ZXJzZVRyYW5zZm9ybSh0aGlzLnRpbWVDb21wbGV4QnVmZmVyLCB0aGlzLmZyZXFDb21wbGV4QnVmZmVyU2hpZnRlZCk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5mZnQuZnJvbUNvbXBsZXhBcnJheSh0aGlzLnRpbWVDb21wbGV4QnVmZmVyLCBvdXRwdXQpOwogICAgICAgICAgICAgICAgICAgIHRoaXMuYXBwbHlIYW5uV2luZG93KG91dHB1dCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdGhpcy50aW1lQ3Vyc29yICs9IHRoaXMuaG9wU2l6ZTsKICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgICAgIGFwcGx5SGFubldpbmRvdyhpbnB1dCkgewogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuYmxvY2tTaXplOyBpKyspIHsKICAgICAgICAgICAgICAgIGlucHV0W2ldICo9IHRoaXMuaGFubldpbmRvd1tpXTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBjb21wdXRlTWFnbml0dWRlcygpIHsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDAsIGogPSAwOyBpIDwgdGhpcy5tYWduaXR1ZGVzLmxlbmd0aDsgaSsrLCBqICs9IDIpIHsKICAgICAgICAgICAgICAgIGNvbnN0IHJlYWwgPSB0aGlzLmZyZXFDb21wbGV4QnVmZmVyW2pdOwogICAgICAgICAgICAgICAgY29uc3QgaW1hZyA9IHRoaXMuZnJlcUNvbXBsZXhCdWZmZXJbaiArIDFdOwogICAgICAgICAgICAgICAgdGhpcy5tYWduaXR1ZGVzW2ldID0gcmVhbCAqKiAyICsgaW1hZyAqKiAyOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGZpbmRQZWFrcygpIHsKICAgICAgICAgICAgdGhpcy5uYlBlYWtzID0gMDsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDIsIGVuZCA9IHRoaXMubWFnbml0dWRlcy5sZW5ndGggLSAyOyBpIDwgZW5kOyBpKyspIHsKICAgICAgICAgICAgICAgIGNvbnN0IG1hZyA9IHRoaXMubWFnbml0dWRlc1tpXTsKICAgICAgICAgICAgICAgIGlmICh0aGlzLm1hZ25pdHVkZXNbaSAtIDFdID49IG1hZyB8fCB0aGlzLm1hZ25pdHVkZXNbaSAtIDJdID49IG1hZyB8fCB0aGlzLm1hZ25pdHVkZXNbaSArIDFdID49IG1hZyB8fCB0aGlzLm1hZ25pdHVkZXNbaSArIDJdID49IG1hZykgewogICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgdGhpcy5wZWFrSW5kZXhlc1t0aGlzLm5iUGVha3MrK10gPSBpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHNoaWZ0UGVha3MocGl0Y2hGYWN0b3IpIHsKICAgICAgICAgICAgdGhpcy5mcmVxQ29tcGxleEJ1ZmZlclNoaWZ0ZWQuZmlsbCgwKTsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm5iUGVha3M7IGkrKykgewogICAgICAgICAgICAgICAgY29uc3QgcGVha0luZGV4ID0gdGhpcy5wZWFrSW5kZXhlc1tpXTsKICAgICAgICAgICAgICAgIGNvbnN0IHBlYWtJbmRleFNoaWZ0ZWQgPSBNYXRoLnJvdW5kKHBlYWtJbmRleCAqIHBpdGNoRmFjdG9yKTsKICAgICAgICAgICAgICAgIGlmIChwZWFrSW5kZXhTaGlmdGVkID4gdGhpcy5tYWduaXR1ZGVzLmxlbmd0aCkgewogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgbGV0IHN0YXJ0SW5kZXggPSAoaSA+IDApID8gcGVha0luZGV4IC0gTWF0aC5mbG9vcigocGVha0luZGV4IC0gdGhpcy5wZWFrSW5kZXhlc1tpIC0gMV0pIC8gMikgOiAwOwogICAgICAgICAgICAgICAgbGV0IGVuZEluZGV4ID0gKGkgPCB0aGlzLm5iUGVha3MgLSAxKSA/IHBlYWtJbmRleCArIE1hdGguY2VpbCgodGhpcy5wZWFrSW5kZXhlc1tpICsgMV0gLSBwZWFrSW5kZXgpIC8gMikgOiB0aGlzLmZmdFNpemU7CiAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gc3RhcnRJbmRleCAtIHBlYWtJbmRleDsgaiA8IGVuZEluZGV4IC0gcGVha0luZGV4OyBqKyspIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBiaW5JbmRleCA9IHBlYWtJbmRleCArIGo7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgYmluSW5kZXhTaGlmdGVkID0gcGVha0luZGV4U2hpZnRlZCArIGo7CiAgICAgICAgICAgICAgICAgICAgaWYgKGJpbkluZGV4U2hpZnRlZCA+PSB0aGlzLm1hZ25pdHVkZXMubGVuZ3RoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjb25zdCBvbWVnYURlbHRhID0gMiAqIE1hdGguUEkgKiAoYmluSW5kZXhTaGlmdGVkIC0gYmluSW5kZXgpIC8gdGhpcy5mZnRTaXplOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHBoYXNlU2hpZnRSZWFsID0gTWF0aC5jb3Mob21lZ2FEZWx0YSAqIHRoaXMudGltZUN1cnNvcik7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGhhc2VTaGlmdEltYWcgPSBNYXRoLnNpbihvbWVnYURlbHRhICogdGhpcy50aW1lQ3Vyc29yKTsKICAgICAgICAgICAgICAgICAgICBjb25zdCBpbmRleFJlYWwgPSBiaW5JbmRleCAqIDI7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgaW5kZXhJbWFnID0gaW5kZXhSZWFsICsgMTsKICAgICAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZVJlYWwgPSB0aGlzLmZyZXFDb21wbGV4QnVmZmVyW2luZGV4UmVhbF07CiAgICAgICAgICAgICAgICAgICAgY29uc3QgdmFsdWVJbWFnID0gdGhpcy5mcmVxQ29tcGxleEJ1ZmZlcltpbmRleEltYWddOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlU2hpZnRlZFJlYWwgPSB2YWx1ZVJlYWwgKiBwaGFzZVNoaWZ0UmVhbCAtIHZhbHVlSW1hZyAqIHBoYXNlU2hpZnRJbWFnOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlU2hpZnRlZEltYWcgPSB2YWx1ZVJlYWwgKiBwaGFzZVNoaWZ0SW1hZyArIHZhbHVlSW1hZyAqIHBoYXNlU2hpZnRSZWFsOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IGluZGV4U2hpZnRlZFJlYWwgPSBiaW5JbmRleFNoaWZ0ZWQgKiAyOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IGluZGV4U2hpZnRlZEltYWcgPSBpbmRleFNoaWZ0ZWRSZWFsICsgMTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmZyZXFDb21wbGV4QnVmZmVyU2hpZnRlZFtpbmRleFNoaWZ0ZWRSZWFsXSArPSB2YWx1ZVNoaWZ0ZWRSZWFsOwogICAgICAgICAgICAgICAgICAgIHRoaXMuZnJlcUNvbXBsZXhCdWZmZXJTaGlmdGVkW2luZGV4U2hpZnRlZEltYWddICs9IHZhbHVlU2hpZnRlZEltYWc7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CiAgICAvLyBAdHMtaWdub3JlCiAgICByZWdpc3RlclByb2Nlc3NvcigicGhhc2Utdm9jb2RlciIsIFBoYXNlVm9jb2RlclByb2Nlc3Nvcik7CiAgICBjb25zb2xlLmxvZygiUGhhc2VWb2NvZGVyUHJvY2Vzc29yIHJlZ2lzdGVyZWQiKTsKCiAgICBleHBvcnRzLlBoYXNlVm9jb2RlclByb2Nlc3NvciA9IFBoYXNlVm9jb2RlclByb2Nlc3NvcjsKCiAgICByZXR1cm4gZXhwb3J0czsKCn0pKHt9KTsK";class R{maxSize;cache;constructor(g){this.maxSize=g,this.cache=new Map}get(g){if(!this.cache.has(g))return;const e=this.cache.get(g);return this.cache.delete(g),this.cache.set(g,e),e}set(g,e){if(this.cache.has(g))this.cache.delete(g);else if(this.cache.size>=this.maxSize){const t=this.cache.keys().next().value;t!==void 0&&this.cache.delete(t)}this.cache.set(g,e)}has(g){return this.cache.has(g)}}const V=100;function Y(a){if(!a)return null;const g=a.match(/max-age\s*=\s*"?(\d+)"?/i);return g?parseInt(g[1],10):null}function N(a){return a?/(?:^|,)\s*(no-cache|no-store|must-revalidate)\s*(?:,|$)/i.test(a):!1}class r{static pendingRequests=new Map;static pendingCallbacks=new Map;static decodedBuffers=new R(V);static cacheExpirationTime=1440*60*1e3;static setCacheExpirationTime(g){this.cacheExpirationTime=g}static async openCache(){try{return await caches.open("audio-cache")}catch(g){throw console.error("Failed to open cache:",g),g}}static callAllCallbacks(g,e,t){const I=this.pendingCallbacks.get(g);I&&I.forEach(s=>{const C=s[e];if(C)try{C(t)}catch(o){console.error(`Error in ${e} callback:`,o)}})}static async getOrCreatePendingRequest(g,e,t,I){if(t?.aborted)throw new DOMException("Operation was aborted","AbortError");if(I){const C=this.pendingCallbacks.get(g)||[];C.push(I),this.pendingCallbacks.set(g,C)}let s=this.pendingRequests.get(g);if(!s){const C=(async()=>{try{const o=await e();if(o===void 0)throw new Error("Failed to create audio buffer.");return o}finally{this.pendingRequests.delete(g),this.pendingCallbacks.delete(g)}})();return t?.addEventListener("abort",()=>{t.aborted&&(this.pendingRequests.delete(g),this.pendingCallbacks.delete(g))},{once:!0}),this.pendingRequests.set(g,C),C}return s}static async updateMetadata(g,e,t){const I={url:e,timestamp:Date.now(),...t};await g.put(`${e}:meta`,new Response(JSON.stringify(I),{headers:{"Content-Type":"application/json"}}))}static async getBufferFromCache(g,e){try{const t=await e.match(g);return t&&t.ok?await t.arrayBuffer():null}catch(t){return console.error("Failed to get data from cache:",t),null}}static async fetchAndCacheBuffer(g,e,t,I,s,C){const o=new Headers;t&&o.append("If-None-Match",t),I&&o.append("If-Modified-Since",I),console.debug(`[AudioCache] Fetching ${g}`,{headers:Object.fromEntries(o.entries()),hasEtag:!!t,hasLastModified:!!I});const i=await fetch(g,{headers:o,signal:s});if(console.debug(`[AudioCache] Response ${g}`,{status:i.status,statusText:i.statusText,etag:i.headers?.get("ETag"),lastModified:i.headers?.get("Last-Modified"),cacheControl:i.headers?.get("Cache-Control")}),i.status===304){const A=await e.match(g);if(A){C?.onCacheHit&&C.onCacheHit({url:g,cacheType:"browser",timestamp:Date.now()});const n=Date.now(),c=i.headers?.get("Cache-Control");return await this.updateMetadata(e,g,{timestamp:n,etag:t,lastModified:I,...c?{cacheControl:c}:{}}),await A.arrayBuffer()}else{console.warn(`Cache inconsistency detected for ${g}: 304 response but no cached body. Re-fetching.`);const n=await fetch(g,{signal:s});if(n.status===200){const c=n.clone(),h=n.headers.get("ETag"),d=n.headers.get("Last-Modified"),p=n.headers.get("Cache-Control");try{await Promise.all([e.put(g,c),this.updateMetadata(e,g,{timestamp:Date.now(),etag:h||void 0,lastModified:d||void 0,cacheControl:p||void 0})])}catch(b){throw await e.delete(g),await e.delete(`${g}:meta`),b}if(n.body){const{stream:b,total:f}=this.createProgressTrackingStream(n,g);return await this.collectStreamToArrayBuffer(b,f||void 0)}else return await n.arrayBuffer()}else throw new Error(`Failed to fetch resource after cache inconsistency: ${n.status} ${n.statusText}`)}}if(i.status===200){const A=i.clone(),n=i.headers.get("ETag"),c=i.headers.get("Last-Modified"),h=i.headers.get("Cache-Control");try{await Promise.all([e.put(g,A),this.updateMetadata(e,g,{timestamp:Date.now(),etag:n||void 0,lastModified:c||void 0,cacheControl:h||void 0})])}catch(d){throw await e.delete(g),await e.delete(`${g}:meta`),d}}if(s?.aborted)throw new DOMException("Operation was aborted","AbortError");if(i.body){const{stream:A,total:n}=this.createProgressTrackingStream(i,g);return await this.collectStreamToArrayBuffer(A,n||void 0)}else return await i.arrayBuffer()}static createProgressTrackingStream(g,e){const t=g.headers.get("content-length"),I=t?parseInt(t,10):null;let s=0;if(!g.body)throw new Error("Response body is null");const C=g.body.getReader();return{stream:new ReadableStream({start(i){function A(){return C.read().then(({done:n,value:c})=>{if(n){r.callAllCallbacks(e,"onLoadingProgress",{url:e,loaded:s,total:I,progress:I?1:-1,timestamp:Date.now()}),i.close();return}if(c){s+=c.byteLength;const h=I?s/I:-1;r.callAllCallbacks(e,"onLoadingProgress",{url:e,loaded:s,total:I,progress:h,timestamp:Date.now()}),i.enqueue(c)}return A()}).catch(n=>{i.error(n)})}return A()},cancel(i){return C.cancel(i)}}),total:I}}static async collectStreamToArrayBuffer(g,e){const t=g.getReader();try{if(e!==void 0&&e>0){const I=new ArrayBuffer(e),s=new Uint8Array(I);let C=0;for(;;){const{done:o,value:i}=await t.read();if(o)break;i&&(s.set(i,C),C+=i.byteLength)}return I}else{let I=new Uint8Array(8192),s=0;for(;;){const{done:C,value:o}=await t.read();if(C)break;if(o){if(s+o.byteLength>I.length){const i=Math.max(I.length*2,s+o.byteLength),A=new Uint8Array(i);A.set(I.subarray(0,s)),I=A}I.set(o,s),s+=o.byteLength}}return I.slice(0,s).buffer}}finally{t.releaseLock()}}static async decodeAudioData(g,e){try{return await g.decodeAudioData(e)}catch(t){throw console.error("Failed to decode audio data:",t),t}}static async getMetadataFromCache(g,e){try{const t=await e.match(g+":meta");return t&&t.ok?await t.json():null}catch(t){return console.error("Failed to get metadata from cache:",t),null}}async getAudioBuffer(g,e,t,I){if(I?.onLoadingStart&&I.onLoadingStart({url:e,timestamp:Date.now()}),r.decodedBuffers.has(e))return I?.onCacheHit&&I.onCacheHit({url:e,cacheType:"memory",timestamp:Date.now()}),r.decodedBuffers.get(e);if(e.startsWith("data:")){const i=e.split(",")[1],A=Uint8Array.from(atob(i),c=>c.charCodeAt(0)).buffer,n=await r.decodeAudioData(g,A);return r.decodedBuffers.set(e,n),n}const s=await r.openCache(),C=await r.getMetadataFromCache(e,s),o=(()=>{if(!C||N(C.cacheControl))return!0;const i=Y(C.cacheControl);if(i!==null){const A=(Date.now()-C.timestamp)/1e3;if(i>0&&A<i)return!1}return C.etag||C.lastModified?!0:Date.now()-C.timestamp>r.cacheExpirationTime})();return r.getOrCreatePendingRequest(e,async()=>{if(o){I?.onCacheMiss&&I.onCacheMiss({url:e,reason:C?"expired":"not-found",timestamp:Date.now()});try{const i=await r.fetchAndCacheBuffer(e,s,C?.etag,C?.lastModified,t,{onCacheHit:I?.onCacheHit});I?.onLoadingComplete&&I.onLoadingComplete({url:e,duration:0,size:i.byteLength,timestamp:Date.now()});const A=await r.decodeAudioData(g,i);return r.decodedBuffers.set(e,A),A}catch(i){throw I?.onCacheError&&I.onCacheError({url:e,error:i,operation:"get",timestamp:Date.now()}),i}}else{const i=await r.getBufferFromCache(e,s);if(i){I?.onCacheHit&&I.onCacheHit({url:e,cacheType:"browser",timestamp:Date.now()});const A=await r.decodeAudioData(g,i);return r.decodedBuffers.set(e,A),A}else{I?.onCacheError&&I.onCacheError({url:e,error:new Error("Cache inconsistency: metadata exists but body is missing"),operation:"get",timestamp:Date.now()});const A=await r.fetchAndCacheBuffer(e,s,C?.etag,C?.lastModified,t,{onCacheHit:I?.onCacheHit}),n=await r.decodeAudioData(g,A);return r.decodedBuffers.set(e,n),n}}},t,{onLoadingProgress:I?.onLoadingProgress})}clearMemoryCache(){r.decodedBuffers=new R(V),r.pendingRequests.clear()}}class y{listeners={};on(g,e){return this.listeners[g]=this.listeners[g]??[],this.listeners[g].push({fn:e,once:!1}),()=>this.off(g,e)}once(g,e){return this.listeners[g]=this.listeners[g]??[],this.listeners[g].push({fn:e,once:!0}),()=>this.off(g,e)}off(g,e){const t=this.listeners[g];t&&(this.listeners[g]=t.filter(I=>I.fn!==e))}emit(g,e){const t=this.listeners[g];t&&(t.forEach(I=>I.fn(e)),this.listeners[g]=t.filter(I=>!I.once))}emitAsync(g,e){const t=this.listeners[g];if(t){const I=t.map(s=>Promise.resolve().then(()=>s.fn(e)).catch(C=>console.error(`Error in listener for event ${g}:`,C)));return this.listeners[g]=t.filter(s=>!s.once),Promise.all(I).then(()=>{})}return Promise.resolve()}removeAllListeners(){this.listeners={}}}class w{constructor(g=[]){this.sounds=g}_position=[0,0,0];loopCount=0;playIndex=0;preplayRandom(){if(this.sounds.length===0)return;const e=this.randomSound().preplay();return e.length>0?e[0]:void 0}playRandom(){const g=this.preplayRandom();return g&&g.play(),g}preplayOrdered(g=!0){if(this.sounds.length===0)return;const t=this.sounds[this.playIndex].preplay();if(t.length!==0)return this.playIndex=(this.playIndex+1)%this.sounds.length,!g&&this.playIndex===0&&(this.playIndex=this.sounds.length),t[0]}playOrdered(g=!0){const e=this.preplayOrdered(g);return e&&e.play(),e}get duration(){return this.sounds.map(g=>g.duration).reduce((g,e)=>Math.max(g,e),0)}seek(g){this.sounds.forEach(e=>e.seek&&e.seek(g))}addSound(g){this.sounds.push(g)}randomSound(){if(this.sounds.length===0)throw new Error("Cannot get a random sound from an empty group");const g=Math.floor(Math.random()*this.sounds.length);return this.sounds[g]}preplay(){return this.sounds.map(e=>e.preplay()).flat()}play(){const g=[];return this.preplay().forEach(e=>{e.play(),g.push(e)}),g}get isPlaying(){return this.sounds.some(g=>g.isPlaying)}stop(){this.sounds.forEach(g=>g.stop())}pause(){this.sounds.forEach(g=>g.pause())}loop(g){return g===void 0?this.loopCount:(this.loopCount=g,this.sounds.forEach(e=>e.loop(g)),this.loopCount)}addFilter(g){this.sounds.forEach(e=>e.addFilter(g))}removeFilter(g){this.sounds.forEach(e=>e.removeFilter(g))}set position(g){this._position=g,this.sounds.forEach(e=>e.position=this._position)}get position(){return this._position}get volume(){return this.sounds.map(g=>g.volume).reduce((g,e)=>g+e,0)/this.sounds.length}set volume(g){this.sounds.forEach(e=>e.volume=g)}get playbackRate(){return this.sounds.length===0?1:this.sounds[0].playbackRate}set playbackRate(g){this.sounds.forEach(e=>e.playbackRate=g)}}class m{_filters=[];addFilter(g){this._filters.push(g)}removeFilter(g){this._filters=this._filters.filter(e=>e.frequency.value!==g.frequency.value&&e.type!==g.type&&e.Q.value!==g.Q.value&&e.gain.value!==g.gain.value)}applyFilters(g){return this._filters.reduce((e,t)=>(e.connect(t),t),g),this._filters.length>0?this._filters[this._filters.length-1]:g}get filters(){return this._filters}addFilters(g){g.forEach(e=>this.addFilter(e))}removeFilters(g){g.forEach(e=>this.removeFilter(e))}cleanup(){this._filters.forEach(g=>g.disconnect()),this._filters=[]}}class v extends m{context;source;gainNode;panner;constructor(g,e,t,I=0){super(),this.source=g,this.gainNode=e,this.context=t,this.panner=t.createPanner(),g.connect(this.panner).connect(this.gainNode),this.refreshFilters()}get duration(){return 0}play(){if(!this.source)throw new Error("Cannot play a sound that has been cleaned up");return[this]}get isPlaying(){return!!this.source}get volume(){if(!this.gainNode)throw new Error("Cannot get volume of a sound that has been cleaned up");return this.gainNode.gain.value}set volume(g){if(!this.gainNode)throw new Error("Cannot set volume of a sound that has been cleaned up");this.gainNode.gain.value=g}stop(){if(!this.source)throw new Error("Cannot stop a sound that has been cleaned up");this.source.mediaStream.getTracks().forEach(g=>g.stop())}pause(){if(!this.source)throw new Error("Cannot pause a sound that has been cleaned up");this.source.mediaStream.getTracks().forEach(g=>g.enabled=!1)}resume(){if(!this.source)throw new Error("Cannot resume a sound that has been cleaned up");this.source.mediaStream.getTracks().forEach(g=>g.enabled=!0)}addFilter(g){super.addFilter(g),this.refreshFilters()}removeFilter(g){super.removeFilter(g),this.refreshFilters()}set position(g){if(!this.panner)throw new Error("Cannot move a sound that has been cleaned up");const[e,t,I]=g;this.panner.positionX.value=e,this.panner.positionY.value=t,this.panner.positionZ.value=I}get position(){if(!this.panner)throw new Error("Cannot get position of a sound that has been cleaned up");return[this.panner.positionX.value,this.panner.positionY.value,this.panner.positionZ.value]}refreshFilters(){if(!this.source||!this.gainNode)throw new Error("Cannot update filters on a sound that has been cleaned up");let g=this.source;this.source.disconnect(),g=this.applyFilters(g),g.connect(this.gainNode)}get playbackRate(){return 1}set playbackRate(g){}}class E extends m{context;_position=[0,0,0];loopCount=0;prevVolume=1;microphoneGainNode;streamPlayback;stream;streamSource;constructor(g){super(),this.context=g,this.microphoneGainNode=this.context.createGain()}play(){return this.stream||navigator.mediaDevices.getUserMedia({audio:!0}).then(g=>{this.stream=g,this.streamSource=this.context.createMediaStreamSource(this.stream),this.streamPlayback=new v(this.streamSource,this.microphoneGainNode,this.context),this.streamPlayback.play()}).catch(g=>{console.error("Error initializing microphone stream:",g)}),this.streamPlayback?[this.streamPlayback]:[]}get duration(){return 0}seek(g){}get isPlaying(){return!!this.streamPlayback}stop(){this.streamPlayback&&(this.streamPlayback.stop(),this.streamPlayback=void 0)}pause(){this.streamPlayback&&this.streamPlayback.pause()}resume(){this.streamPlayback&&this.streamPlayback.resume()}addFilter(g){this.streamPlayback&&this.streamPlayback.addFilter(g)}removeFilter(g){this.streamPlayback&&this.streamPlayback.removeFilter(g)}get volume(){return this.streamPlayback?this.streamPlayback.volume:0}set volume(g){this.streamPlayback&&(this.streamPlayback.volume=g)}get position(){return[0,0,0]}set position(g){}loop(g){return 0}get playbackRate(){return 1}set playbackRate(g){}}function S(a){class g extends a{playbacks=[];_position=[0,0,0];_stereoPan=0;_threeDOptions={coneInnerAngle:360,coneOuterAngle:360,coneOuterGain:0,distanceModel:"inverse",maxDistance:1e4,channelCount:2,channelCountMode:"clamped-max",channelInterpretation:"speakers",panningModel:"HRTF",refDistance:1,rolloffFactor:1,positionX:0,positionY:0,positionZ:0,orientationX:0,orientationY:0,orientationZ:0};_volume=1;play(){const t=this.preplay();return t.forEach(I=>I.play()),t}stop(){this.playbacks.forEach(t=>t.stop()),this.playbacks=[]}pause(){this.playbacks.forEach(t=>t.pause())}addFilter(t){super.addFilter(t),this.playbacks.forEach(I=>I.addFilter(t))}removeFilter(t){super.removeFilter(t),this.playbacks.forEach(I=>I.removeFilter(t))}get isPlaying(){return this.playbacks.some(t=>t.isPlaying)}get position(){return[this._threeDOptions.positionX,this._threeDOptions.positionY,this._threeDOptions.positionZ]}set position(t){this._threeDOptions.positionX=t[0],this._threeDOptions.positionY=t[1],this._threeDOptions.positionZ=t[2],this.playbacks.forEach(I=>I.position=t)}get threeDOptions(){return this._threeDOptions}set threeDOptions(t){this._threeDOptions={...this._threeDOptions,...t},this.playbacks.forEach(I=>I.threeDOptions=this._threeDOptions)}get stereoPan(){return this._stereoPan}set stereoPan(t){this._stereoPan=t,this.playbacks.forEach(I=>I.stereoPan=t)}get volume(){return this._volume}set volume(t){this._volume=t,this.playbacks.forEach(I=>I.volume=t)}}return g}function H(a){class g extends a{panner;_panType="stereo";get panType(){return this._panType}setPanType(t,I){this._panType===t&&this.panner||(this.panner&&this.panner.disconnect(),this._panType=t,t==="stereo"?this.panner=I.createStereoPanner():this.panner=I.createPanner())}setPannerNode(t){this.panner=t}get stereoPan(){return this.panType==="stereo"?this.panner.pan.value:null}set stereoPan(t){if(this.panType!=="stereo")throw new Error("Stereo panning is not available when using HRTF.");if(!this.panner)throw new Error("Cannot set stereo pan of a sound that has been cleaned up");t=W(t,-1,1),this.panner.pan.setValueAtTime(W(t,-1,1),this.panner.context.currentTime)}get threeDOptions(){if(!this.panner)throw new Error("Cannot get 3D options of a sound that has been cleaned up");if(this.panType!=="HRTF")throw new Error("Cannot get 3D options of a sound that is not using HRTF");const t=this.panner;return{coneInnerAngle:t.coneInnerAngle,coneOuterAngle:t.coneOuterAngle,coneOuterGain:t.coneOuterGain,distanceModel:t.distanceModel,maxDistance:t.maxDistance,channelCount:this.panner.channelCount,channelCountMode:t.channelCountMode,channelInterpretation:t.channelInterpretation,panningModel:t.panningModel,refDistance:t.refDistance,rolloffFactor:t.rolloffFactor,positionX:t.positionX.value,positionY:t.positionY.value,positionZ:t.positionZ.value,orientationX:t.orientationX.value,orientationY:t.orientationY.value,orientationZ:t.orientationZ.value}}set threeDOptions(t){if(!this.panner)throw new Error("Cannot set 3D options of a sound that has been cleaned up");if(this.panType!=="HRTF")throw new Error("Cannot set 3D options of a sound that is not using HRTF");const I=this.panner;I.coneInnerAngle=t.coneInnerAngle!==void 0?t.coneInnerAngle:I.coneInnerAngle,I.coneOuterAngle=t.coneOuterAngle!==void 0?t.coneOuterAngle:I.coneOuterAngle,I.coneOuterGain=t.coneOuterGain!==void 0?t.coneOuterGain:I.coneOuterGain,I.distanceModel=t.distanceModel||I.distanceModel,I.maxDistance=t.maxDistance!==void 0?t.maxDistance:I.maxDistance,I.channelCount=t.channelCount!==void 0?t.channelCount:I.channelCount,I.channelCountMode=t.channelCountMode||I.channelCountMode,I.channelInterpretation=t.channelInterpretation||I.channelInterpretation,I.panningModel=t.panningModel||I.panningModel,I.refDistance=t.refDistance!==void 0?t.refDistance:I.refDistance,I.rolloffFactor=t.rolloffFactor!==void 0?t.rolloffFactor:I.rolloffFactor,I.positionX.value=t.positionX!==void 0?t.positionX:I.positionX.value,I.positionY.value=t.positionY!==void 0?t.positionY:I.positionY.value,I.positionZ.value=t.positionZ!==void 0?t.positionZ:I.positionZ.value,I.orientationX.value=t.orientationX!==void 0?t.orientationX:I.orientationX.value,I.orientationY.value=t.orientationY!==void 0?t.orientationY:I.orientationY.value,I.orientationZ.value=t.orientationZ!==void 0?t.orientationZ:I.orientationZ.value}set position(t){if(!this.panner)throw new Error("Cannot move a sound that has been cleaned up");if(this.panType!=="HRTF")throw new Error("Cannot move a sound that is not using HRTF");const[I,s,C]=t,o=this.panner;o.positionX.value=I,o.positionY.value=s,o.positionZ.value=C}get position(){if(!this.panner)throw new Error("Cannot get position of a sound that has been cleaned up");if(this.panType!=="HRTF")throw new Error("Cannot get position of a sound that is not using HRTF");const t=this.panner;return[t.positionX.value,t.positionY.value,t.positionZ.value]}cleanup(){this.panner&&(this.panner.disconnect(),this.panner=void 0),super.cleanup()}}return g}function W(a,g,e){return Math.min(Math.max(a,g),e)}function D(a){class g extends a{gainNode;setGainNode(t){this.gainNode=t}cleanup(){this.gainNode&&(this.gainNode.disconnect(),this.gainNode=void 0),super.cleanup()}get volume(){if(!this.gainNode)throw new Error("Cannot get volume of a sound that has been cleaned up");return this.gainNode.gain.value}set volume(t){if(!this.gainNode)throw new Error("Cannot set volume of a sound that has been cleaned up");this.gainNode.gain.value=t}}return g}class k extends H(D(m)){source;_playing=!1;origin;eventEmitter=new y;constructor(){super()}get isPlaying(){return this.source?this._playing:!1}on(g,e){this.eventEmitter.on(g,e)}off(g,e){this.eventEmitter.off(g,e)}emit(g,e){this.eventEmitter.emit(g,e)}async emitAsync(g,e){return this.eventEmitter.emitAsync(g,e)}cleanup(){this.eventEmitter.removeAllListeners(),super.cleanup()}}class Z extends k{constructor(g,e,t){super(),this.origin=g,this.context=g.context,this.loopCount=g.loopCount,this.setPanType(g.panType,g.context),this.source=e,"buffer"in e&&e.buffer&&(this.buffer=e.buffer),this.setupSourceNode(e),this.source.connect(this.panner),this.setGainNode(t),this.panner.connect(this.gainNode),this.refreshFilters()}context;loopCount=0;currentLoop=0;buffer;_offset=0;_startTime=0;_state=0;_playbackRate=1;setupSourceNode(g){if("mediaElement"in g&&g.mediaElement)g.mediaElement.onended=this.loopEnded;else if("onended"in g)g.onended=this.loopEnded;else throw new Error("Unsupported source type")}get isPlaying(){return this._state===1}get duration(){if(!this.source)throw new Error("Cannot get duration of a sound that has been cleaned up");return"mediaElement"in this.source&&this.source.mediaElement?this.source.mediaElement.duration:this.buffer?this.buffer.duration||NaN:NaN}get playbackRate(){return this._playbackRate}set playbackRate(g){if(g<=0)throw new Error("Playback rate must be greater than 0");if(this._state===1){const e=(this.context.currentTime-this._startTime)*this._playbackRate;this._offset+=e,this._startTime=this.context.currentTime}this._playbackRate=g,this.source&&("playbackRate"in this.source&&(this.source.playbackRate.value=g),"mediaElement"in this.source&&this.source.mediaElement&&(this.source.mediaElement.playbackRate=g))}loopEnded=()=>{!this.source||this._state!==1||(this.currentLoop++,this.loopCount!=="infinite"&&this.currentLoop>this.loopCount?this.stop():(this.seek(0),"mediaElement"in this.source&&this.source.mediaElement?this.source.mediaElement.play():this.play()))};play(){if(!this.source)throw new Error("Cannot play a sound that has been cleaned up");if(this._state===1)return[this];try{return this._state===2?"mediaElement"in this.source&&this.source.mediaElement?this.source.mediaElement.play():(this.recreateSource(),"start"in this.source&&this.source.start&&this.source.start(0,this._offset)):"mediaElement"in this.source&&this.source.mediaElement?(this.source.mediaElement.currentTime=this._offset,this.source.mediaElement.play()):"start"in this.source&&this.source.start&&(this.recreateSource(),this.source.start(0,this._offset)),this._startTime=this.context.currentTime,this._state=1,this.emit("play",this),[this]}catch(g){throw this.emitAsync("error",{error:g,errorType:"source",timestamp:Date.now(),recoverable:!0}),g}}pause(){if(!this.source||this._state!==1)return;const g=(this.context.currentTime-this._startTime)*this._playbackRate;this._offset+=g,"mediaElement"in this.source&&this.source.mediaElement?this.source.mediaElement.pause():"stop"in this.source&&this.source.stop(),this._state=2}stop(){if(!this.source)throw new Error("Cannot stop a sound that has been cleaned up");this._state===3||this._state===0||("stop"in this.source&&this._state===1&&this.source.stop(),"mediaElement"in this.source&&this.source.mediaElement&&(this.source.mediaElement.pause(),this.source.mediaElement.currentTime=0),this._offset=0,this._startTime=0,this._state=3,this.emit("stop",void 0))}seek(g){if(!this.source||!this.gainNode||!this.panner)throw new Error("Cannot seek a sound that has been cleaned up");if(!isFinite(g)||g<0)throw new Error("Invalid time value for seek");const e=this._state===1;e&&this.pause(),this._offset=g,"mediaElement"in this.source&&this.source.mediaElement&&(this.source.mediaElement.currentTime=g),e&&this.play()}get currentTime(){if(this._state===1){const g=(this.context.currentTime-this._startTime)*this._playbackRate;return this._offset+g}else return this._offset}recreateSource(){if(!this.buffer||!this.panner||!this.context||!this.gainNode)throw new Error("Cannot recreate source of a sound that has been cleaned up");try{this.source&&(!("mediaElement"in this.source)&&"onended"in this.source&&(this.source.onended=null),this.source.disconnect()),this.source=this.context.createBufferSource(),this.source.buffer=this.buffer,this.source.connect(this.panner),this.source.onended=this.loopEnded,this.playbackRate=this._playbackRate,this.refreshFilters()}catch(g){throw this.emitAsync("error",{error:g,errorType:"source",timestamp:Date.now(),recoverable:!1}),g}}set sourceLoop(g){if(!this.source)throw new Error("Cannot set loop on a sound that has been cleaned up");"loop"in this.source&&(this.source.loop=g),"mediaElement"in this.source&&this.source.mediaElement&&(this.source.mediaElement.loop=g)}cleanup(){this.source&&(this.source.disconnect(),this.source=void 0,super.cleanup())}assertNotCleanedUp(){if(!this.source||!this.gainNode||!this.panner)throw new Error("Cannot perform operation on a sound that has been cleaned up")}addFilter(g){this.assertNotCleanedUp(),super.addFilter(g),this.refreshFilters()}removeFilter(g){this.assertNotCleanedUp(),super.removeFilter(g),this.refreshFilters()}loop(g){if(!this.source)throw new Error("Cannot loop a sound that has been cleaned up");if(g!==void 0&&(this.loopCount=g==="infinite"?"infinite":Math.max(0,g),this.currentLoop=0),"mediaElement"in this.source&&this.source.mediaElement){const e=this.source.mediaElement;e.loop=this.loopCount==="infinite"}else if("loop"in this.source)this.source.loop=this.loopCount==="infinite",this.source.buffer&&(this.source.loopEnd=this.source.buffer.duration,this.source.loopStart=0);else throw new Error("Unsupported source type");return this.loopCount}refreshFilters(){if(!this.panner||!this.gainNode)throw new Error("Cannot update filters on a sound that has been cleaned up");let g=this.panner;g.disconnect(),g=this.applyFilters(g),g.connect(this.gainNode)}clone(g={}){if(!this.source||!this.gainNode||!this.context)throw new Error("Cannot clone a sound that has been cleaned up");const e=g.panType||this.panType,t=this.context.createGain();let I;if("buffer"in this.source&&this.source.buffer)I=this.context.createBufferSource(),I.buffer=this.source.buffer;else if("mediaElement"in this.source&&this.source.mediaElement)I=this.context.createMediaElementSource(this.source.mediaElement);else throw new Error("Unsupported source type");const s=g.loopCount!==void 0?g.loopCount:this.loopCount,C=new Z(this.origin,I,t);return C.loopCount=s,C.currentLoop=this.currentLoop,C.setPanType(e,this.context),C.volume=this.volume,C.playbackRate=this._playbackRate,C._offset=this._offset,C._state=this._state,this._filters.forEach(o=>{const i=this.context.createBiquadFilter();i.type=o.type,i.frequency.value=o.frequency.value,i.Q.value=o.Q.value,i.gain.value=o.gain.value,C.addFilter(i)}),this._state===1&&C.play(),C}}class u extends S(m){constructor(g,e,t,I,s=B.Buffer,C="HRTF",o){super(),this.url=g,this.globalGainNode=I,this.soundType=s,this.panType=C,this.cacophony=o,this.buffer=e,this.context=t}buffer;context;loopCount=0;_playbackRate=1;eventEmitter=new y;get volume(){return super.volume}on(g,e){this.eventEmitter.on(g,e)}off(g,e){this.eventEmitter.off(g,e)}emit(g,e){this.eventEmitter.emit(g,e)}async emitAsync(g,e){return this.eventEmitter.emitAsync(g,e)}clone(g={}){const e=g.panType||this.panType,t=g.stereoPan!==void 0?g.stereoPan:this.stereoPan,I=g.threeDOptions||this.threeDOptions,s=g.loopCount!==void 0?g.loopCount:this.loopCount,C=g.playbackRate||this.playbackRate,o=g.volume!==void 0?g.volume:this.volume,i=g.position!==void 0?g.position:this.position,A=g.filters&&g.filters.length?g.filters:this._filters,n=new u(this.url,this.buffer,this.context,this.globalGainNode,this.soundType,e,this.cacophony);return n.loop(s),n.playbackRate=C,n.volume=o,e==="HRTF"?(n.threeDOptions=I,n.position=i):n.stereoPan=t,n.addFilters(A),n}preplay(){try{let g;if(this.buffer)g=this.context.createBufferSource(),g.buffer=this.buffer;else{const I=new Audio;I.crossOrigin="anonymous",I.src=this.url,I.preload="auto",g=this.context.createMediaElementSource(I)}const e=this.context.createGain();e.connect(this.globalGainNode);const t=new Z(this,g,e);return t.setGainNode(e),t.volume=this.volume,t.playbackRate=this.playbackRate,this._filters.forEach(I=>t.addFilter(I)),this.panType==="HRTF"?(t.threeDOptions=this.threeDOptions,t.position=this.position):this.panType==="stereo"&&(t.stereoPan=this.stereoPan),t.on("error",I=>{this.emitAsync("soundError",{url:this.url,error:I.error,errorType:"playback",timestamp:I.timestamp,recoverable:I.recoverable})}),this.playbacks.push(t),[t]}catch(g){const e={url:this.url,error:g,errorType:"playback",timestamp:Date.now(),recoverable:!0};throw this.emitAsync("soundError",e),g}}play(){const g=super.play();return this.emit("play",g[0]),this.cacophony?.emit("globalPlay",{source:this,timestamp:Date.now()}),g}stop(){super.stop(),this.emit("stop",void 0),this.cacophony?.emit("globalStop",{source:this,timestamp:Date.now()})}pause(){super.pause(),this.emit("pause",void 0),this.cacophony?.emit("globalPause",{source:this,timestamp:Date.now()})}seek(g){this.playbacks.forEach(e=>e.seek(g))}get duration(){return this.playbacks.length>0?this.playbacks[0].duration:this.buffer?.duration||NaN}loop(g){return g===void 0?this.loopCount:(this.loopCount=g,this.playbacks.forEach(e=>e.loop(g)),this.loopCount)}get playbackRate(){return this._playbackRate}set playbackRate(g){this._playbackRate=g,this.playbacks.forEach(e=>e.playbackRate=g),this.emit("rateChange",g)}set volume(g){super.volume=g,this.emit("volumeChange",g)}cleanup(){this.playbacks.forEach(g=>g.cleanup()),this.playbacks=[],this.eventEmitter.removeAllListeners()}}const Q=(a,g)=>{var e=new Uint8Array(a.byteLength+g.byteLength);return e.set(new Uint8Array(a),0),e.set(new Uint8Array(g),a.byteLength),e.buffer};function P(a,g,e){const t=[];let I=0,s;if(e?.aborted){console.error("Stream error:",new DOMException("Operation was aborted","AbortError"));return}fetch(a,e?{signal:e}:void 0).then(function(o){if(!o.ok)throw new Error("HTTP error, status = "+o.status);if(!o.body)throw new Error("Missing body");s=o.body.getReader();let i=new ArrayBuffer(0);const A=()=>{t.length=0,s&&s.cancel("Stream aborted").catch(()=>{})};e?.addEventListener("abort",A);function n(){return e?.aborted?(A(),Promise.resolve()):s.read().then(({value:c,done:h})=>{if(e?.aborted){A();return}let d=null;if(c){if(i.byteLength?d=Q(i,c.buffer):(i=c.buffer.slice(0,44),d=c.buffer),g.decodeAudioData(d,function(p){e?.aborted||(t.push(p),t.length&&C())},function(p){console.log("err(decodeAudioData): "+p)}),h){console.log("done"),e?.removeEventListener("abort",A);return}n()}}).catch(c=>{e?.aborted||c.name==="AbortError"||console.error("Stream read error:",c)})}n()}).catch(function(o){console.error("Stream error:",o)});function C(){for(;t.length;){let o=t.shift();const i=g.createBufferSource();if(!o)return;i.buffer=o,i.connect(g.destination),I==0&&(I=g.currentTime+.02),i.start(I),I+=i.buffer.duration}}}function M(a){class g extends k{_oscillatorOptions={};get oscillatorOptions(){return this._oscillatorOptions}set oscillatorOptions(t){this._oscillatorOptions=t,this.source&&this.source instanceof OscillatorNode&&(this.oscillatorOptions.detune&&(this.source.detune.value=this.oscillatorOptions.detune),this.oscillatorOptions.frequency&&(this.source.frequency.value=this.oscillatorOptions.frequency),this.oscillatorOptions.type&&(this.source.type=this.oscillatorOptions.type))}play(){if(!this.source)throw new Error("No source node found");return this.oscillatorOptions.detune&&(this.source.detune.value=this.oscillatorOptions.detune),this.oscillatorOptions.frequency&&(this.source.frequency.value=this.oscillatorOptions.frequency),this.oscillatorOptions.type&&(this.source.type=this.oscillatorOptions.type),this.source.start(),this._playing=!0,[this]}stop(){this.source&&this.source.stop&&(this.source.stop(),this._playing=!1)}pause(){this.stop()}get frequency(){return this.source.frequency.value}set frequency(t){this.source.frequency.value=t,this.oscillatorOptions.frequency=t}get detune(){return this.source.detune.value}set detune(t){this.source.detune.value=t,this.oscillatorOptions.detune=t}get type(){return this.source.type}set type(t){this.source.type=t,this.oscillatorOptions.type=t}}return g}class x extends M(H(D(m))){constructor(g,e,t){super(),this.origin=g,this.source=e,this.context=g.context,this.setPanType(g.panType,g.context),this.source.connect(this.panner),this.setGainNode(t),this.panner.connect(this.gainNode),this.refreshFilters()}context;refreshFilters(){if(!this.panner||!this.gainNode)throw new Error("Cannot update filters on a sound that has been cleaned up");let g=this.panner;g.disconnect(),g=this.applyFilters(g),g.connect(this.gainNode)}cleanup(){this.panner&&this.gainNode&&(this.source.disconnect(this.panner),this.panner.disconnect(),this.gainNode.disconnect()),this.eventEmitter.removeAllListeners()}}class G extends S(m){constructor(g,e,t=B.Oscillator,I="HRTF",s={},C){super(),this.context=g,this.globalGainNode=e,this.soundType=t,this.panType=I,this.cacophony=C,this.context=g,this._oscillatorOptions=s}_oscillatorOptions;playbacks=[];eventEmitter=new y;on(g,e){this.eventEmitter.on(g,e)}off(g,e){this.eventEmitter.off(g,e)}emit(g,e){this.eventEmitter.emit(g,e)}async emitAsync(g,e){return this.eventEmitter.emitAsync(g,e)}clone(g={}){const e=g.panType||this.panType,t=g.stereoPan!==void 0?g.stereoPan:this.stereoPan??0,I=g.threeDOptions||this.threeDOptions,s=g.volume!==void 0?g.volume:this.volume,C=g.position&&g.position.length?g.position:this.position,o=g.filters&&g.filters.length?g.filters:this._filters,i=g.oscillatorOptions||this._oscillatorOptions,A=new G(this.context,this.globalGainNode,this.soundType,e,i,this.cacophony);return A._volume=s,A._position=C,A._stereoPan=t,A._threeDOptions=I,A.addFilters(o),A}preplay(){const g=this.context.createOscillator();return this.createPlayback(g)}createPlayback(g){this.oscillatorOptions.detune&&(g.detune.value=this.oscillatorOptions.detune),this.oscillatorOptions.frequency&&(g.frequency.value=this.oscillatorOptions.frequency),this.oscillatorOptions.type&&(g.type=this.oscillatorOptions.type);const e=this.context.createGain();e.connect(this.globalGainNode);const t=new x(this,g,e);return t.volume=this.volume,this._filters.forEach(I=>t.addFilter(I)),this.panType==="HRTF"?(t.threeDOptions=this.threeDOptions,t.position=this.position):this.panType==="stereo"&&(t.stereoPan=this.stereoPan),this.playbacks.push(t),[t]}play(){const g=super.play();return this.emit("play",g[0]),this.cacophony?.emit("globalPlay",{source:this,timestamp:Date.now()}),g}stop(){super.stop(),this.emit("stop",void 0),this.cacophony?.emit("globalStop",{source:this,timestamp:Date.now()})}pause(){super.pause(),this.emit("pause",void 0),this.cacophony?.emit("globalPause",{source:this,timestamp:Date.now()})}get oscillatorOptions(){return this._oscillatorOptions}set oscillatorOptions(g){this._oscillatorOptions=g,this.playbacks.forEach(e=>{e.source instanceof OscillatorNode&&(this.oscillatorOptions.detune&&(e.source.detune.value=this.oscillatorOptions.detune),this.oscillatorOptions.frequency&&(e.source.frequency.value=this.oscillatorOptions.frequency),this.oscillatorOptions.type&&(e.source.type=this.oscillatorOptions.type))})}get frequency(){return this.oscillatorOptions.frequency||440}set frequency(g){this._oscillatorOptions.frequency=g,this.playbacks.forEach(e=>e.frequency=g),this.emit("frequencyChange",g)}get detune(){return this.oscillatorOptions.detune}set detune(g){this._oscillatorOptions.detune=g,this.playbacks.forEach(e=>e.detune=g),this.emit("detuneChange",g)}get type(){return this.oscillatorOptions.type||"sine"}set type(g){this._oscillatorOptions.type=g,this.playbacks.forEach(e=>e.type=g),this.emit("typeChange",g)}}var B=(a=>(a.HTML="HTML",a.Streaming="Streaming",a.Buffer="Buffer",a.Oscillator="oscillator",a))(B||{});class J{context;globalGainNode;listener;prevVolume=1;finalizationRegistry;eventEmitter=new y;cache;constructor(g,e){this.context=g||new X.AudioContext,this.listener=this.context.listener,this.globalGainNode=this.context.createGain(),this.globalGainNode.connect(this.context.destination),this.cache=e||new r,this.finalizationRegistry=new FinalizationRegistry(t=>{t.cleanup()})}on(g,e){this.eventEmitter.on(g,e)}off(g,e){this.eventEmitter.off(g,e)}emit(g,e){this.eventEmitter.emit(g,e)}async emitAsync(g,e){return this.eventEmitter.emitAsync(g,e)}async loadWorklets(g){this.context.audioWorklet?await this.createWorkletNode("phase-vocoder",K,g):console.warn("AudioWorklet not supported")}async createWorkletNode(g,e,t){if(!this.context.audioWorklet)throw new Error("AudioWorklet not supported");try{return new X.AudioWorkletNode(this.context,g)}catch(I){console.error(I),console.log("Loading worklet from url",e);try{await this.context.audioWorklet.addModule(e,{credentials:"same-origin",...t&&{signal:t}})}catch(s){throw console.error(s),s}return new X.AudioWorkletNode(this.context,g)}}clearMemoryCache(){this.cache.clearMemoryCache()}createOscillator(g,e="HRTF"){return new G(this.context,this.globalGainNode,"oscillator",e,g,this)}async createSound(g,e="Buffer",t="HRTF",I){if(typeof g=="object")return Promise.resolve(new u("",g,this.context,this.globalGainNode,"Buffer",t,this));const s=g;if(e==="HTML"){const C=new Audio;return C.src=s,C.crossOrigin="anonymous",Promise.resolve(new u(s,void 0,this.context,this.globalGainNode,"HTML",t,this))}return e==="Streaming"?Promise.resolve(new u(s,void 0,this.context,this.globalGainNode,"Streaming",t,this)):this.cache.getAudioBuffer(this.context,s,I,{onLoadingStart:C=>this.emitAsync("loadingStart",C),onLoadingProgress:C=>this.emitAsync("loadingProgress",C),onLoadingComplete:C=>this.emitAsync("loadingComplete",C),onLoadingError:C=>this.emitAsync("loadingError",C),onCacheHit:C=>this.emitAsync("cacheHit",C),onCacheMiss:C=>this.emitAsync("cacheMiss",C),onCacheError:C=>this.emitAsync("cacheError",C)}).then(C=>new u(s,C,this.context,this.globalGainNode,e,t,this))}async createGroup(g){const e=new w;return g.forEach(t=>e.addSound(t)),e}async createGroupFromUrls(g,e="Buffer",t="HRTF",I){const s=new w;return(await Promise.all(g.map(o=>this.createSound(o,e,t,I)))).forEach(o=>s.addSound(o)),s}async createStream(g,e){return P(g,this.context,e),new u(g,void 0,this.context,this.globalGainNode,"Streaming","HRTF",this)}createBiquadFilter=({type:g,frequency:e,gain:t,Q:I})=>{e===void 0&&(e=350);const s=this.context.createBiquadFilter();return s.type=g||"lowpass",s.frequency.value=e,s.gain.value=t||0,s.Q.value=I||1,s};createPanner({coneInnerAngle:g,coneOuterAngle:e,coneOuterGain:t,distanceModel:I,maxDistance:s,channelCount:C,channelCountMode:o,channelInterpretation:i,panningModel:A,refDistance:n,rolloffFactor:c,positionX:h,positionY:d,positionZ:p,orientationX:b,orientationY:f,orientationZ:F}){const l=this.context.createPanner();return l.coneInnerAngle=g||360,l.coneOuterAngle=e||360,l.coneOuterGain=t||0,l.distanceModel=I||"inverse",l.maxDistance=s||1e4,l.channelCount=C||2,l.channelCountMode=o||"clamped-max",l.channelInterpretation=i||"speakers",l.panningModel=A||"HRTF",l.refDistance=n||1,l.rolloffFactor=c||1,l.positionX.value=h||0,l.positionY.value=d||0,l.positionZ.value=p||0,l.orientationX.value=b||0,l.orientationY.value=f||0,l.orientationZ.value=F||0,l}pause(){"suspend"in this.context&&this.context.suspend()}resume(){"resume"in this.context&&this.context.resume()}setGlobalVolume(g){this.globalGainNode.gain.value=g}get volume(){return this.globalGainNode.gain.value}set volume(g){if(this.muted){this.prevVolume=g;return}this.setGlobalVolume(g)}mute(){this.muted||(this.prevVolume=this.globalGainNode.gain.value,this.setGlobalVolume(0))}unmute(){this.muted&&this.setGlobalVolume(this.prevVolume)}get muted(){return this.globalGainNode.gain.value===0}set muted(g){g!==this.muted&&(g?this.mute():this.unmute())}getMicrophoneStream(){return new Promise((g,e)=>{navigator.mediaDevices.getUserMedia({audio:!0}).then(t=>{const I=new E(this.context);I.play(),g(I)}).catch(t=>{e(t)})})}get listenerOrientation(){return{forward:[this.listener.forwardX.value,this.listener.forwardY.value,this.listener.forwardZ.value],up:[this.listener.upX.value,this.listener.upY.value,this.listener.upZ.value]}}set listenerOrientation(g){const{forward:e,up:t}=g,[I,s,C]=e,[o,i,A]=t;this.listener.forwardX.value=I,this.listener.forwardY.value=s,this.listener.forwardZ.value=C,this.listener.upX.value=o,this.listener.upY.value=i,this.listener.upZ.value=A}get listenerUpOrientation(){return[this.listener.upX.value,this.listener.upY.value,this.listener.upZ.value]}set listenerUpOrientation(g){const[e,t,I]=g;this.listener.upX.value=e,this.listener.upY.value=t,this.listener.upZ.value=I}get listenerForwardOrientation(){return[this.listener.forwardX.value,this.listener.forwardY.value,this.listener.forwardZ.value]}set listenerForwardOrientation(g){const[e,t,I]=g;this.listener.forwardX.value=e,this.listener.forwardY.value=t,this.listener.forwardZ.value=I}get listenerPosition(){return[this.listener.positionX.value,this.listener.positionY.value,this.listener.positionZ.value]}set listenerPosition(g){const[e,t,I]=g,s=this.context.currentTime;this.listener.positionX.setValueAtTime(e,s),this.listener.positionY.setValueAtTime(t,s),this.listener.positionZ.setValueAtTime(I,s)}}class T{constructor(g=[]){this.synths=g}addSynth(g){this.synths.push(g)}removeSynth(g){const e=this.synths.indexOf(g);if(e!==-1)this.synths.splice(e,1);else throw new Error("Synth not found in group")}play(){this.synths.forEach(g=>g.play())}stop(){this.synths.forEach(g=>g.stop())}setVolume(g){this.synths.forEach(e=>e.volume=g)}set stereoPan(g){this.synths.forEach(e=>e.stereoPan=g)}set position(g){this.synths.forEach(e=>e.position=g)}}exports.Cacophony=J;exports.Group=w;exports.MicrophonePlayback=v;exports.Playback=Z;exports.Sound=u;exports.SoundType=B;exports.Synth=G;exports.SynthGroup=T;
2
2
  //# sourceMappingURL=index.cjs.map