cacophony 0.17.1 → 0.18.3
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/dist/basePlayback.d.ts +16 -0
- package/dist/cacophony.d.ts +14 -0
- package/dist/container.d.ts +30 -1
- package/dist/events.d.ts +8 -0
- package/dist/group.d.ts +5 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +716 -545
- package/dist/index.mjs.map +1 -1
- package/dist/oscillatorMixin.d.ts +7 -0
- package/dist/playback.d.ts +35 -1
- package/dist/sound.d.ts +6 -2
- package/dist/synth.d.ts +4 -3
- package/dist/synthPlayback.d.ts +7 -0
- package/dist/volumeMixin.d.ts +33 -0
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/Cacophony.html +11 -11
- package/docs/classes/Group.html +16 -12
- package/docs/classes/MicrophonePlayback.html +3 -3
- package/docs/classes/Playback.html +60 -29
- package/docs/classes/Sound.html +36 -15
- package/docs/classes/Synth.html +35 -14
- package/docs/classes/SynthGroup.html +2 -2
- package/docs/enums/SoundType.html +2 -2
- package/docs/hierarchy.html +1 -1
- package/docs/interfaces/AudioEventCallbacks.html +11 -0
- package/docs/interfaces/BaseAudioEvents.html +11 -0
- package/docs/interfaces/BaseSound.html +6 -2
- package/docs/interfaces/CacheErrorEvent.html +6 -0
- package/docs/interfaces/CacheHitEvent.html +5 -0
- package/docs/interfaces/CacheMissEvent.html +5 -0
- package/docs/interfaces/CacophonyEvents.html +17 -0
- package/docs/interfaces/FadeStartEvent.html +5 -0
- package/docs/interfaces/GlobalPlaybackEvent.html +4 -0
- package/docs/interfaces/LoadingCompleteEvent.html +6 -0
- package/docs/interfaces/LoadingErrorEvent.html +6 -0
- package/docs/interfaces/LoadingProgressEvent.html +8 -0
- package/docs/interfaces/LoadingStartEvent.html +4 -0
- package/docs/interfaces/PlayOptions.html +7 -0
- package/docs/interfaces/PlaybackErrorEvent.html +6 -0
- package/docs/interfaces/PlaybackEvents.html +13 -0
- package/docs/interfaces/SoundErrorEvent.html +7 -0
- package/docs/interfaces/SoundEvents.html +15 -0
- package/docs/interfaces/SynthEvents.html +15 -0
- package/docs/modules.html +23 -2
- package/docs/types/CacheEventCallback.html +2 -0
- package/docs/types/ErrorEventCallback.html +2 -0
- package/docs/types/FadeType.html +1 -1
- package/docs/types/LoadingEventCallback.html +2 -0
- package/docs/types/LoopCount.html +1 -1
- package/docs/types/Orientation.html +1 -1
- package/docs/types/PanType.html +1 -1
- package/docs/types/Position.html +1 -1
- package/package.json +1 -1
package/dist/basePlayback.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { FadeType } from './cacophony';
|
|
1
2
|
import { IPlaybackContainer } from './container';
|
|
2
3
|
import { AudioNode } from './context';
|
|
3
4
|
import { FilterManager } from './filters';
|
|
@@ -24,9 +25,16 @@ declare const BasePlayback_base: (abstract new (...args: any[]) => {
|
|
|
24
25
|
removeFilters(filters: BiquadFilterNode[]): void;
|
|
25
26
|
}) & (abstract new (...args: any[]) => {
|
|
26
27
|
gainNode?: import('./context').GainNode | undefined;
|
|
28
|
+
_fadeTimeout?: NodeJS.Timeout | undefined;
|
|
29
|
+
_isFading: boolean;
|
|
27
30
|
setGainNode(gainNode: import('./context').GainNode): void;
|
|
28
31
|
cleanup(): void;
|
|
29
32
|
volume: number;
|
|
33
|
+
readonly isFading: boolean;
|
|
34
|
+
fadeTo(value: number, duration: number, type?: FadeType): Promise<void>;
|
|
35
|
+
cancelFade(): void;
|
|
36
|
+
fadeIn(duration: number, type?: FadeType | undefined): Promise<void>;
|
|
37
|
+
fadeOut(duration: number, type?: FadeType | undefined): Promise<void>;
|
|
30
38
|
_filters: BiquadFilterNode[];
|
|
31
39
|
addFilter(filter: BiquadFilterNode): void;
|
|
32
40
|
removeFilter(filter: BiquadFilterNode): void;
|
|
@@ -60,6 +68,14 @@ export declare abstract class BasePlayback extends BasePlayback_base {
|
|
|
60
68
|
off<K extends keyof PlaybackEvents>(event: K, listener: (data: PlaybackEvents[K]) => void): void;
|
|
61
69
|
emit<K extends keyof PlaybackEvents>(event: K, data: PlaybackEvents[K]): void;
|
|
62
70
|
emitAsync<K extends keyof PlaybackEvents>(event: K, data: PlaybackEvents[K]): Promise<void>;
|
|
71
|
+
/**
|
|
72
|
+
* Fades the volume to a target value, emitting fadeStart and fadeEnd events.
|
|
73
|
+
*/
|
|
74
|
+
fadeTo(value: number, duration: number, type?: FadeType): Promise<void>;
|
|
75
|
+
/**
|
|
76
|
+
* Cancels any in-progress fade, emitting fadeCancel if a fade was active.
|
|
77
|
+
*/
|
|
78
|
+
cancelFade(): void;
|
|
63
79
|
cleanup(): void;
|
|
64
80
|
}
|
|
65
81
|
export {};
|
package/dist/cacophony.d.ts
CHANGED
|
@@ -43,6 +43,16 @@ export type FadeType = "linear" | "exponential";
|
|
|
43
43
|
* @typedef {'HRTF' | 'stereo'} PanType - The pan type, either 'HRTF' for 3D audio or 'stereo' for traditional stereo panning.
|
|
44
44
|
*/
|
|
45
45
|
export type PanType = "HRTF" | "stereo";
|
|
46
|
+
/**
|
|
47
|
+
* Options for configuring fade behavior when starting playback via Sound.play().
|
|
48
|
+
* @interface PlayOptions
|
|
49
|
+
*/
|
|
50
|
+
export interface PlayOptions {
|
|
51
|
+
fadeIn?: number;
|
|
52
|
+
fadeOut?: number;
|
|
53
|
+
fadeType?: FadeType;
|
|
54
|
+
fadeInPerLoop?: boolean;
|
|
55
|
+
}
|
|
46
56
|
/**
|
|
47
57
|
* The base interface for any sound-producing entity, including individual sounds, groups, and playbacks.
|
|
48
58
|
* @interface BaseSound
|
|
@@ -58,6 +68,10 @@ export interface BaseSound {
|
|
|
58
68
|
volume: number;
|
|
59
69
|
position?: Position;
|
|
60
70
|
threeDOptions?: any;
|
|
71
|
+
fadeTo?(value: number, duration: number, type?: FadeType): Promise<void>;
|
|
72
|
+
fadeIn?(duration: number, type?: FadeType): Promise<void>;
|
|
73
|
+
fadeOut?(duration: number, type?: FadeType): Promise<void>;
|
|
74
|
+
stopWithFade?(duration: number, type?: FadeType): Promise<void>;
|
|
61
75
|
}
|
|
62
76
|
export declare class Cacophony {
|
|
63
77
|
context: AudioContext;
|
package/dist/container.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BasePlayback } from 'basePlayback';
|
|
2
|
-
import { Position } from './cacophony';
|
|
2
|
+
import { FadeType, Position } from './cacophony';
|
|
3
3
|
import { FilterManager } from './filters';
|
|
4
4
|
type Constructor<T = FilterManager> = abstract new (...args: any[]) => T;
|
|
5
5
|
export interface IPlaybackContainer {
|
|
@@ -73,6 +73,35 @@ export declare function PlaybackContainer<TBase extends Constructor>(Base: TBase
|
|
|
73
73
|
* @returns {number} The current volume of the sound.
|
|
74
74
|
*/
|
|
75
75
|
volume: number;
|
|
76
|
+
/**
|
|
77
|
+
* Fades the volume of all playbacks to a target value over a duration.
|
|
78
|
+
* @param {number} value - The target volume (0 to 1).
|
|
79
|
+
* @param {number} duration - The fade duration in milliseconds.
|
|
80
|
+
* @param {FadeType} type - The fade curve type. Defaults to "linear".
|
|
81
|
+
* @returns {Promise<void>} Resolves when all fades complete.
|
|
82
|
+
*/
|
|
83
|
+
fadeTo(value: number, duration: number, type?: FadeType): Promise<void>;
|
|
84
|
+
/**
|
|
85
|
+
* Fades in all playbacks from silence to their current volume.
|
|
86
|
+
* @param {number} duration - The fade duration in milliseconds.
|
|
87
|
+
* @param {FadeType} type - The fade curve type. Defaults to "linear".
|
|
88
|
+
* @returns {Promise<void>} Resolves when all fades complete.
|
|
89
|
+
*/
|
|
90
|
+
fadeIn(duration: number, type?: FadeType): Promise<void>;
|
|
91
|
+
/**
|
|
92
|
+
* Fades out all playbacks from their current volume to silence.
|
|
93
|
+
* @param {number} duration - The fade duration in milliseconds.
|
|
94
|
+
* @param {FadeType} type - The fade curve type. Defaults to "linear".
|
|
95
|
+
* @returns {Promise<void>} Resolves when all fades complete.
|
|
96
|
+
*/
|
|
97
|
+
fadeOut(duration: number, type?: FadeType): Promise<void>;
|
|
98
|
+
/**
|
|
99
|
+
* Fades out all playbacks then stops them.
|
|
100
|
+
* @param {number} duration - The fade-out duration in milliseconds.
|
|
101
|
+
* @param {FadeType} type - The fade curve type. Defaults to "linear".
|
|
102
|
+
* @returns {Promise<void>} Resolves when the fade completes and all playbacks are stopped.
|
|
103
|
+
*/
|
|
104
|
+
stopWithFade(duration: number, type?: FadeType): Promise<void>;
|
|
76
105
|
_filters: BiquadFilterNode[];
|
|
77
106
|
applyFilters(connection: any): any;
|
|
78
107
|
readonly filters: BiquadFilterNode[];
|
package/dist/events.d.ts
CHANGED
|
@@ -5,6 +5,11 @@ import { Synth } from './synth';
|
|
|
5
5
|
/**
|
|
6
6
|
* Base events for all audio objects.
|
|
7
7
|
*/
|
|
8
|
+
export interface FadeStartEvent {
|
|
9
|
+
target: number;
|
|
10
|
+
duration: number;
|
|
11
|
+
type: string;
|
|
12
|
+
}
|
|
8
13
|
export interface BaseAudioEvents {
|
|
9
14
|
play: BasePlayback;
|
|
10
15
|
stop: void;
|
|
@@ -13,6 +18,9 @@ export interface BaseAudioEvents {
|
|
|
13
18
|
ended: void;
|
|
14
19
|
volumeChange: number;
|
|
15
20
|
error: PlaybackErrorEvent;
|
|
21
|
+
fadeStart: FadeStartEvent;
|
|
22
|
+
fadeEnd: void;
|
|
23
|
+
fadeCancel: void;
|
|
16
24
|
}
|
|
17
25
|
/**
|
|
18
26
|
* Sound-specific events.
|
package/dist/group.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BaseSound, LoopCount } from './cacophony';
|
|
1
|
+
import { BaseSound, FadeType, LoopCount } from './cacophony';
|
|
2
2
|
import { Playback } from './playback';
|
|
3
3
|
import { Sound } from './sound';
|
|
4
4
|
export declare class Group implements BaseSound {
|
|
@@ -57,6 +57,10 @@ export declare class Group implements BaseSound {
|
|
|
57
57
|
*/
|
|
58
58
|
stop(): void;
|
|
59
59
|
pause(): void;
|
|
60
|
+
fadeTo(value: number, duration: number, type?: FadeType): Promise<void>;
|
|
61
|
+
fadeIn(duration: number, type?: FadeType): Promise<void>;
|
|
62
|
+
fadeOut(duration: number, type?: FadeType): Promise<void>;
|
|
63
|
+
stopWithFade(duration: number, type?: FadeType): Promise<void>;
|
|
60
64
|
loop(loopCount?: LoopCount): LoopCount;
|
|
61
65
|
/**
|
|
62
66
|
* Adds a filter to all sounds in the group.
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const f=require("standardized-audio-context"),Y="data:text/javascript;base64,dmFyIHBoYXNlVm9jb2RlciA9IChmdW5jdGlvbiAoZXhwb3J0cykgewogICAgJ3VzZSBzdHJpY3QnOwoKICAgIGNvbnN0IFdFQkFVRElPX0JMT0NLX1NJWkUgPSAxMjg7CiAgICBjb25zdCBERUZBVUxUX0JMT0NLX1NJWkUgPSAxMDI0OyAvLyBEZWZhdWx0IGJsb2NrIHNpemUgaWYgbm90IHByb3ZpZGVkIGluIG9wdGlvbnMKICAgIC8qKiBPdmVybGFwLUFkZCBOb2RlICovCiAgICBjbGFzcyBPTEFQcm9jZXNzb3IgZXh0ZW5kcyBBdWRpb1dvcmtsZXRQcm9jZXNzb3IgewogICAgICAgIG5iSW5wdXRzOwogICAgICAgIG5iT3V0cHV0czsKICAgICAgICBibG9ja1NpemU7CiAgICAgICAgaG9wU2l6ZTsKICAgICAgICBuYk92ZXJsYXBzOwogICAgICAgIGlucHV0QnVmZmVycyA9IFtdOwogICAgICAgIGlucHV0QnVmZmVyc0hlYWQgPSBbXTsKICAgICAgICBpbnB1dEJ1ZmZlcnNUb1NlbmQgPSBbXTsKICAgICAgICBvdXRwdXRCdWZmZXJzID0gW107CiAgICAgICAgb3V0cHV0QnVmZmVyc1RvUmV0cmlldmUgPSBbXTsKICAgICAgICBjb25zdHJ1Y3RvcihvcHRpb25zKSB7CiAgICAgICAgICAgIHN1cGVyKG9wdGlvbnMpOwogICAgICAgICAgICB0aGlzLm5iSW5wdXRzID0gb3B0aW9ucy5udW1iZXJPZklucHV0cyB8fCAxOwogICAgICAgICAgICB0aGlzLm5iT3V0cHV0cyA9IG9wdGlvbnMubnVtYmVyT2ZPdXRwdXRzIHx8IDE7CiAgICAgICAgICAgIHRoaXMuYmxvY2tTaXplID0gb3B0aW9ucy5wcm9jZXNzb3JPcHRpb25zLmJsb2NrU2l6ZSB8fCBERUZBVUxUX0JMT0NLX1NJWkU7CiAgICAgICAgICAgIHRoaXMuaG9wU2l6ZSA9IFdFQkFVRElPX0JMT0NLX1NJWkU7CiAgICAgICAgICAgIHRoaXMubmJPdmVybGFwcyA9IE1hdGguZmxvb3IodGhpcy5ibG9ja1NpemUgLyB0aGlzLmhvcFNpemUpOwogICAgICAgICAgICB0aGlzLmluaXRpYWxpemVCdWZmZXJzKCk7CiAgICAgICAgfQogICAgICAgIGluaXRpYWxpemVCdWZmZXJzKCkgewogICAgICAgICAgICB0aGlzLmlucHV0QnVmZmVycyA9IG5ldyBBcnJheSh0aGlzLm5iSW5wdXRzKTsKICAgICAgICAgICAgdGhpcy5pbnB1dEJ1ZmZlcnNIZWFkID0gbmV3IEFycmF5KHRoaXMubmJJbnB1dHMpOwogICAgICAgICAgICB0aGlzLmlucHV0QnVmZmVyc1RvU2VuZCA9IG5ldyBBcnJheSh0aGlzLm5iSW5wdXRzKTsKICAgICAgICAgICAgdGhpcy5vdXRwdXRCdWZmZXJzID0gbmV3IEFycmF5KHRoaXMubmJPdXRwdXRzKTsKICAgICAgICAgICAgdGhpcy5vdXRwdXRCdWZmZXJzVG9SZXRyaWV2ZSA9IG5ldyBBcnJheSh0aGlzLm5iT3V0cHV0cyk7CiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5uYklucHV0czsgaSsrKSB7CiAgICAgICAgICAgICAgICB0aGlzLmFsbG9jYXRlSW5wdXRDaGFubmVscyhpLCAxKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMubmJPdXRwdXRzOyBpKyspIHsKICAgICAgICAgICAgICAgIHRoaXMuYWxsb2NhdGVPdXRwdXRDaGFubmVscyhpLCAxKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBhbGxvY2F0ZUlucHV0Q2hhbm5lbHMoaW5wdXRJbmRleCwgbmJDaGFubmVscykgewogICAgICAgICAgICB0aGlzLmlucHV0QnVmZmVyc1tpbnB1dEluZGV4XSA9IG5ldyBBcnJheShuYkNoYW5uZWxzKTsKICAgICAgICAgICAgdGhpcy5pbnB1dEJ1ZmZlcnNIZWFkW2lucHV0SW5kZXhdID0gbmV3IEFycmF5KG5iQ2hhbm5lbHMpOwogICAgICAgICAgICB0aGlzLmlucHV0QnVmZmVyc1RvU2VuZFtpbnB1dEluZGV4XSA9IG5ldyBBcnJheShuYkNoYW5uZWxzKTsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBuYkNoYW5uZWxzOyBpKyspIHsKICAgICAgICAgICAgICAgIHRoaXMuaW5wdXRCdWZmZXJzW2lucHV0SW5kZXhdW2ldID0gbmV3IEZsb2F0MzJBcnJheSh0aGlzLmJsb2NrU2l6ZSArIFdFQkFVRElPX0JMT0NLX1NJWkUpOwogICAgICAgICAgICAgICAgdGhpcy5pbnB1dEJ1ZmZlcnNbaW5wdXRJbmRleF1baV0uZmlsbCgwKTsKICAgICAgICAgICAgICAgIHRoaXMuaW5wdXRCdWZmZXJzSGVhZFtpbnB1dEluZGV4XVtpXSA9IHRoaXMuaW5wdXRCdWZmZXJzW2lucHV0SW5kZXhdW2ldLnN1YmFycmF5KDAsIHRoaXMuYmxvY2tTaXplKTsKICAgICAgICAgICAgICAgIHRoaXMuaW5wdXRCdWZmZXJzVG9TZW5kW2lucHV0SW5kZXhdW2ldID0gbmV3IEZsb2F0MzJBcnJheSh0aGlzLmJsb2NrU2l6ZSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgYWxsb2NhdGVPdXRwdXRDaGFubmVscyhvdXRwdXRJbmRleCwgbmJDaGFubmVscykgewogICAgICAgICAgICB0aGlzLm91dHB1dEJ1ZmZlcnNbb3V0cHV0SW5kZXhdID0gbmV3IEFycmF5KG5iQ2hhbm5lbHMpOwogICAgICAgICAgICB0aGlzLm91dHB1dEJ1ZmZlcnNUb1JldHJpZXZlW291dHB1dEluZGV4XSA9IG5ldyBBcnJheShuYkNoYW5uZWxzKTsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBuYkNoYW5uZWxzOyBpKyspIHsKICAgICAgICAgICAgICAgIHRoaXMub3V0cHV0QnVmZmVyc1tvdXRwdXRJbmRleF1baV0gPSBuZXcgRmxvYXQzMkFycmF5KHRoaXMuYmxvY2tTaXplKTsKICAgICAgICAgICAgICAgIHRoaXMub3V0cHV0QnVmZmVyc1tvdXRwdXRJbmRleF1baV0uZmlsbCgwKTsKICAgICAgICAgICAgICAgIHRoaXMub3V0cHV0QnVmZmVyc1RvUmV0cmlldmVbb3V0cHV0SW5kZXhdW2ldID0gbmV3IEZsb2F0MzJBcnJheSh0aGlzLmJsb2NrU2l6ZSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmVhbGxvY2F0ZUNoYW5uZWxzSWZOZWVkZWQoaW5wdXRzLCBvdXRwdXRzKSB7CiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5uYklucHV0czsgaSsrKSB7CiAgICAgICAgICAgICAgICBsZXQgbmJDaGFubmVscyA9IGlucHV0c1tpXS5sZW5ndGg7CiAgICAgICAgICAgICAgICBpZiAobmJDaGFubmVscyAhPT0gdGhpcy5pbnB1dEJ1ZmZlcnNbaV0ubGVuZ3RoKSB7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5hbGxvY2F0ZUlucHV0Q2hhbm5lbHMoaSwgbmJDaGFubmVscyk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm5iT3V0cHV0czsgaSsrKSB7CiAgICAgICAgICAgICAgICBsZXQgbmJDaGFubmVscyA9IG91dHB1dHNbaV0ubGVuZ3RoOwogICAgICAgICAgICAgICAgaWYgKG5iQ2hhbm5lbHMgIT09IHRoaXMub3V0cHV0QnVmZmVyc1tpXS5sZW5ndGgpIHsKICAgICAgICAgICAgICAgICAgICB0aGlzLmFsbG9jYXRlT3V0cHV0Q2hhbm5lbHMoaSwgbmJDaGFubmVscyk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmVhZElucHV0cyhpbnB1dHMpIHsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm5iSW5wdXRzOyBpKyspIHsKICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgdGhpcy5pbnB1dEJ1ZmZlcnNbaV0ubGVuZ3RoOyBqKyspIHsKICAgICAgICAgICAgICAgICAgICBsZXQgd2ViQXVkaW9CbG9jayA9IGlucHV0c1tpXVtqXTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmlucHV0QnVmZmVyc1tpXVtqXS5zZXQod2ViQXVkaW9CbG9jaywgdGhpcy5ibG9ja1NpemUpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHdyaXRlT3V0cHV0cyhvdXRwdXRzKSB7CiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5uYk91dHB1dHM7IGkrKykgewogICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCB0aGlzLm91dHB1dEJ1ZmZlcnNbaV0ubGVuZ3RoOyBqKyspIHsKICAgICAgICAgICAgICAgICAgICBsZXQgd2ViQXVkaW9CbG9jayA9IG91dHB1dHNbaV1bal07CiAgICAgICAgICAgICAgICAgICAgd2ViQXVkaW9CbG9jay5zZXQodGhpcy5vdXRwdXRCdWZmZXJzW2ldW2pdLnN1YmFycmF5KDAsIFdFQkFVRElPX0JMT0NLX1NJWkUpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBzaGlmdElucHV0QnVmZmVycygpIHsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm5iSW5wdXRzOyBpKyspIHsKICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgdGhpcy5pbnB1dEJ1ZmZlcnNbaV0ubGVuZ3RoOyBqKyspIHsKICAgICAgICAgICAgICAgICAgICB0aGlzLmlucHV0QnVmZmVyc1tpXVtqXS5jb3B5V2l0aGluKDAsIFdFQkFVRElPX0JMT0NLX1NJWkUpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHNoaWZ0T3V0cHV0QnVmZmVycygpIHsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm5iT3V0cHV0czsgaSsrKSB7CiAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHRoaXMub3V0cHV0QnVmZmVyc1tpXS5sZW5ndGg7IGorKykgewogICAgICAgICAgICAgICAgICAgIHRoaXMub3V0cHV0QnVmZmVyc1tpXVtqXS5jb3B5V2l0aGluKDAsIFdFQkFVRElPX0JMT0NLX1NJWkUpOwogICAgICAgICAgICAgICAgICAgIHRoaXMub3V0cHV0QnVmZmVyc1tpXVtqXS5maWxsKDAsIHRoaXMuYmxvY2tTaXplIC0gV0VCQVVESU9fQkxPQ0tfU0laRSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcHJlcGFyZUlucHV0QnVmZmVyc1RvU2VuZCgpIHsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm5iSW5wdXRzOyBpKyspIHsKICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgdGhpcy5pbnB1dEJ1ZmZlcnNbaV0ubGVuZ3RoOyBqKyspIHsKICAgICAgICAgICAgICAgICAgICB0aGlzLmlucHV0QnVmZmVyc1RvU2VuZFtpXVtqXS5zZXQodGhpcy5pbnB1dEJ1ZmZlcnNIZWFkW2ldW2pdKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBoYW5kbGVPdXRwdXRCdWZmZXJzVG9SZXRyaWV2ZSgpIHsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm5iT3V0cHV0czsgaSsrKSB7CiAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHRoaXMub3V0cHV0QnVmZmVyc1tpXS5sZW5ndGg7IGorKykgewogICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGsgPSAwOyBrIDwgdGhpcy5ibG9ja1NpemU7IGsrKykgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm91dHB1dEJ1ZmZlcnNbaV1bal1ba10gKz0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub3V0cHV0QnVmZmVyc1RvUmV0cmlldmVbaV1bal1ba10gLyB0aGlzLm5iT3ZlcmxhcHM7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHByb2Nlc3MoaW5wdXRzLCBvdXRwdXRzLCBwYXJhbWV0ZXJzKSB7CiAgICAgICAgICAgIHRoaXMucmVhbGxvY2F0ZUNoYW5uZWxzSWZOZWVkZWQoaW5wdXRzLCBvdXRwdXRzKTsKICAgICAgICAgICAgdGhpcy5yZWFkSW5wdXRzKGlucHV0cyk7CiAgICAgICAgICAgIHRoaXMuc2hpZnRJbnB1dEJ1ZmZlcnMoKTsKICAgICAgICAgICAgdGhpcy5wcmVwYXJlSW5wdXRCdWZmZXJzVG9TZW5kKCk7CiAgICAgICAgICAgIHRoaXMucHJvY2Vzc09MQSh0aGlzLmlucHV0QnVmZmVyc1RvU2VuZCwgdGhpcy5vdXRwdXRCdWZmZXJzVG9SZXRyaWV2ZSwgcGFyYW1ldGVycyk7CiAgICAgICAgICAgIHRoaXMuaGFuZGxlT3V0cHV0QnVmZmVyc1RvUmV0cmlldmUoKTsKICAgICAgICAgICAgdGhpcy53cml0ZU91dHB1dHMob3V0cHV0cyk7CiAgICAgICAgICAgIHRoaXMuc2hpZnRPdXRwdXRCdWZmZXJzKCk7CiAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KICAgIH0KCiAgICBmdW5jdGlvbiBnZXREZWZhdWx0RXhwb3J0RnJvbUNqcyAoeCkgewogICAgCXJldHVybiB4ICYmIHguX19lc01vZHVsZSAmJiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoeCwgJ2RlZmF1bHQnKSA/IHhbJ2RlZmF1bHQnXSA6IHg7CiAgICB9CgogICAgZnVuY3Rpb24gRkZUKHNpemUpIHsKICAgICAgdGhpcy5zaXplID0gc2l6ZSB8IDA7CiAgICAgIGlmICh0aGlzLnNpemUgPD0gMSB8fCAodGhpcy5zaXplICYgKHRoaXMuc2l6ZSAtIDEpKSAhPT0gMCkKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZGVCBzaXplIG11c3QgYmUgYSBwb3dlciBvZiB0d28gYW5kIGJpZ2dlciB0aGFuIDEnKTsKCiAgICAgIHRoaXMuX2NzaXplID0gc2l6ZSA8PCAxOwoKICAgICAgLy8gTk9URTogVXNlIG9mIGB2YXJgIGlzIGludGVudGlvbmFsIGZvciBvbGQgVjggdmVyc2lvbnMKICAgICAgdmFyIHRhYmxlID0gbmV3IEFycmF5KHRoaXMuc2l6ZSAqIDIpOwogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRhYmxlLmxlbmd0aDsgaSArPSAyKSB7CiAgICAgICAgY29uc3QgYW5nbGUgPSBNYXRoLlBJICogaSAvIHRoaXMuc2l6ZTsKICAgICAgICB0YWJsZVtpXSA9IE1hdGguY29zKGFuZ2xlKTsKICAgICAgICB0YWJsZVtpICsgMV0gPSAtTWF0aC5zaW4oYW5nbGUpOwogICAgICB9CiAgICAgIHRoaXMudGFibGUgPSB0YWJsZTsKCiAgICAgIC8vIEZpbmQgc2l6ZSdzIHBvd2VyIG9mIHR3bwogICAgICB2YXIgcG93ZXIgPSAwOwogICAgICBmb3IgKHZhciB0ID0gMTsgdGhpcy5zaXplID4gdDsgdCA8PD0gMSkKICAgICAgICBwb3dlcisrOwoKICAgICAgLy8gQ2FsY3VsYXRlIGluaXRpYWwgc3RlcCdzIHdpZHRoOgogICAgICAvLyAgICogSWYgd2UgYXJlIGZ1bGwgcmFkaXgtNCAtIGl0IGlzIDJ4IHNtYWxsZXIgdG8gZ2l2ZSBpbml0YWwgbGVuPTgKICAgICAgLy8gICAqIE90aGVyd2lzZSBpdCBpcyB0aGUgc2FtZSBhcyBgcG93ZXJgIHRvIGdpdmUgbGVuPTQKICAgICAgdGhpcy5fd2lkdGggPSBwb3dlciAlIDIgPT09IDAgPyBwb3dlciAtIDEgOiBwb3dlcjsKCiAgICAgIC8vIFByZS1jb21wdXRlIGJpdC1yZXZlcnNhbCBwYXR0ZXJucwogICAgICB0aGlzLl9iaXRyZXYgPSBuZXcgQXJyYXkoMSA8PCB0aGlzLl93aWR0aCk7CiAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgdGhpcy5fYml0cmV2Lmxlbmd0aDsgaisrKSB7CiAgICAgICAgdGhpcy5fYml0cmV2W2pdID0gMDsKICAgICAgICBmb3IgKHZhciBzaGlmdCA9IDA7IHNoaWZ0IDwgdGhpcy5fd2lkdGg7IHNoaWZ0ICs9IDIpIHsKICAgICAgICAgIHZhciByZXZTaGlmdCA9IHRoaXMuX3dpZHRoIC0gc2hpZnQgLSAyOwogICAgICAgICAgdGhpcy5fYml0cmV2W2pdIHw9ICgoaiA+Pj4gc2hpZnQpICYgMykgPDwgcmV2U2hpZnQ7CiAgICAgICAgfQogICAgICB9CgogICAgICB0aGlzLl9vdXQgPSBudWxsOwogICAgICB0aGlzLl9kYXRhID0gbnVsbDsKICAgICAgdGhpcy5faW52ID0gMDsKICAgIH0KICAgIHZhciBmZnQgPSBGRlQ7CgogICAgRkZULnByb3RvdHlwZS5mcm9tQ29tcGxleEFycmF5ID0gZnVuY3Rpb24gZnJvbUNvbXBsZXhBcnJheShjb21wbGV4LCBzdG9yYWdlKSB7CiAgICAgIHZhciByZXMgPSBzdG9yYWdlIHx8IG5ldyBBcnJheShjb21wbGV4Lmxlbmd0aCA+Pj4gMSk7CiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY29tcGxleC5sZW5ndGg7IGkgKz0gMikKICAgICAgICByZXNbaSA+Pj4gMV0gPSBjb21wbGV4W2ldOwogICAgICByZXR1cm4gcmVzOwogICAgfTsKCiAgICBGRlQucHJvdG90eXBlLmNyZWF0ZUNvbXBsZXhBcnJheSA9IGZ1bmN0aW9uIGNyZWF0ZUNvbXBsZXhBcnJheSgpIHsKICAgICAgY29uc3QgcmVzID0gbmV3IEFycmF5KHRoaXMuX2NzaXplKTsKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCByZXMubGVuZ3RoOyBpKyspCiAgICAgICAgcmVzW2ldID0gMDsKICAgICAgcmV0dXJuIHJlczsKICAgIH07CgogICAgRkZULnByb3RvdHlwZS50b0NvbXBsZXhBcnJheSA9IGZ1bmN0aW9uIHRvQ29tcGxleEFycmF5KGlucHV0LCBzdG9yYWdlKSB7CiAgICAgIHZhciByZXMgPSBzdG9yYWdlIHx8IHRoaXMuY3JlYXRlQ29tcGxleEFycmF5KCk7CiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmVzLmxlbmd0aDsgaSArPSAyKSB7CiAgICAgICAgcmVzW2ldID0gaW5wdXRbaSA+Pj4gMV07CiAgICAgICAgcmVzW2kgKyAxXSA9IDA7CiAgICAgIH0KICAgICAgcmV0dXJuIHJlczsKICAgIH07CgogICAgRkZULnByb3RvdHlwZS5jb21wbGV0ZVNwZWN0cnVtID0gZnVuY3Rpb24gY29tcGxldGVTcGVjdHJ1bShzcGVjdHJ1bSkgewogICAgICB2YXIgc2l6ZSA9IHRoaXMuX2NzaXplOwogICAgICB2YXIgaGFsZiA9IHNpemUgPj4+IDE7CiAgICAgIGZvciAodmFyIGkgPSAyOyBpIDwgaGFsZjsgaSArPSAyKSB7CiAgICAgICAgc3BlY3RydW1bc2l6ZSAtIGldID0gc3BlY3RydW1baV07CiAgICAgICAgc3BlY3RydW1bc2l6ZSAtIGkgKyAxXSA9IC1zcGVjdHJ1bVtpICsgMV07CiAgICAgIH0KICAgIH07CgogICAgRkZULnByb3RvdHlwZS50cmFuc2Zvcm0gPSBmdW5jdGlvbiB0cmFuc2Zvcm0ob3V0LCBkYXRhKSB7CiAgICAgIGlmIChvdXQgPT09IGRhdGEpCiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBhbmQgb3V0cHV0IGJ1ZmZlcnMgbXVzdCBiZSBkaWZmZXJlbnQnKTsKCiAgICAgIHRoaXMuX291dCA9IG91dDsKICAgICAgdGhpcy5fZGF0YSA9IGRhdGE7CiAgICAgIHRoaXMuX2ludiA9IDA7CiAgICAgIHRoaXMuX3RyYW5zZm9ybTQoKTsKICAgICAgdGhpcy5fb3V0ID0gbnVsbDsKICAgICAgdGhpcy5fZGF0YSA9IG51bGw7CiAgICB9OwoKICAgIEZGVC5wcm90b3R5cGUucmVhbFRyYW5zZm9ybSA9IGZ1bmN0aW9uIHJlYWxUcmFuc2Zvcm0ob3V0LCBkYXRhKSB7CiAgICAgIGlmIChvdXQgPT09IGRhdGEpCiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBhbmQgb3V0cHV0IGJ1ZmZlcnMgbXVzdCBiZSBkaWZmZXJlbnQnKTsKCiAgICAgIHRoaXMuX291dCA9IG91dDsKICAgICAgdGhpcy5fZGF0YSA9IGRhdGE7CiAgICAgIHRoaXMuX2ludiA9IDA7CiAgICAgIHRoaXMuX3JlYWxUcmFuc2Zvcm00KCk7CiAgICAgIHRoaXMuX291dCA9IG51bGw7CiAgICAgIHRoaXMuX2RhdGEgPSBudWxsOwogICAgfTsKCiAgICBGRlQucHJvdG90eXBlLmludmVyc2VUcmFuc2Zvcm0gPSBmdW5jdGlvbiBpbnZlcnNlVHJhbnNmb3JtKG91dCwgZGF0YSkgewogICAgICBpZiAob3V0ID09PSBkYXRhKQogICAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgYW5kIG91dHB1dCBidWZmZXJzIG11c3QgYmUgZGlmZmVyZW50Jyk7CgogICAgICB0aGlzLl9vdXQgPSBvdXQ7CiAgICAgIHRoaXMuX2RhdGEgPSBkYXRhOwogICAgICB0aGlzLl9pbnYgPSAxOwogICAgICB0aGlzLl90cmFuc2Zvcm00KCk7CiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb3V0Lmxlbmd0aDsgaSsrKQogICAgICAgIG91dFtpXSAvPSB0aGlzLnNpemU7CiAgICAgIHRoaXMuX291dCA9IG51bGw7CiAgICAgIHRoaXMuX2RhdGEgPSBudWxsOwogICAgfTsKCiAgICAvLyByYWRpeC00IGltcGxlbWVudGF0aW9uCiAgICAvLwogICAgLy8gTk9URTogVXNlcyBvZiBgdmFyYCBhcmUgaW50ZW50aW9uYWwgZm9yIG9sZGVyIFY4IHZlcnNpb24gdGhhdCBkbyBub3QKICAgIC8vIHN1cHBvcnQgYm90aCBgbGV0IGNvbXBvdW5kIGFzc2lnbm1lbnRzYCBhbmQgYGNvbnN0IHBoaWAKICAgIEZGVC5wcm90b3R5cGUuX3RyYW5zZm9ybTQgPSBmdW5jdGlvbiBfdHJhbnNmb3JtNCgpIHsKICAgICAgdmFyIG91dCA9IHRoaXMuX291dDsKICAgICAgdmFyIHNpemUgPSB0aGlzLl9jc2l6ZTsKCiAgICAgIC8vIEluaXRpYWwgc3RlcCAocGVybXV0ZSBhbmQgdHJhbnNmb3JtKQogICAgICB2YXIgd2lkdGggPSB0aGlzLl93aWR0aDsKICAgICAgdmFyIHN0ZXAgPSAxIDw8IHdpZHRoOwogICAgICB2YXIgbGVuID0gKHNpemUgLyBzdGVwKSA8PCAxOwoKICAgICAgdmFyIG91dE9mZjsKICAgICAgdmFyIHQ7CiAgICAgIHZhciBiaXRyZXYgPSB0aGlzLl9iaXRyZXY7CiAgICAgIGlmIChsZW4gPT09IDQpIHsKICAgICAgICBmb3IgKG91dE9mZiA9IDAsIHQgPSAwOyBvdXRPZmYgPCBzaXplOyBvdXRPZmYgKz0gbGVuLCB0KyspIHsKICAgICAgICAgIGNvbnN0IG9mZiA9IGJpdHJldlt0XTsKICAgICAgICAgIHRoaXMuX3NpbmdsZVRyYW5zZm9ybTIob3V0T2ZmLCBvZmYsIHN0ZXApOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICAvLyBsZW4gPT09IDgKICAgICAgICBmb3IgKG91dE9mZiA9IDAsIHQgPSAwOyBvdXRPZmYgPCBzaXplOyBvdXRPZmYgKz0gbGVuLCB0KyspIHsKICAgICAgICAgIGNvbnN0IG9mZiA9IGJpdHJldlt0XTsKICAgICAgICAgIHRoaXMuX3NpbmdsZVRyYW5zZm9ybTQob3V0T2ZmLCBvZmYsIHN0ZXApOwogICAgICAgIH0KICAgICAgfQoKICAgICAgLy8gTG9vcCB0aHJvdWdoIHN0ZXBzIGluIGRlY3JlYXNpbmcgb3JkZXIKICAgICAgdmFyIGludiA9IHRoaXMuX2ludiA/IC0xIDogMTsKICAgICAgdmFyIHRhYmxlID0gdGhpcy50YWJsZTsKICAgICAgZm9yIChzdGVwID4+PSAyOyBzdGVwID49IDI7IHN0ZXAgPj49IDIpIHsKICAgICAgICBsZW4gPSAoc2l6ZSAvIHN0ZXApIDw8IDE7CiAgICAgICAgdmFyIHF1YXJ0ZXJMZW4gPSBsZW4gPj4+IDI7CgogICAgICAgIC8vIExvb3AgdGhyb3VnaCBvZmZzZXRzIGluIHRoZSBkYXRhCiAgICAgICAgZm9yIChvdXRPZmYgPSAwOyBvdXRPZmYgPCBzaXplOyBvdXRPZmYgKz0gbGVuKSB7CiAgICAgICAgICAvLyBGdWxsIGNhc2UKICAgICAgICAgIHZhciBsaW1pdCA9IG91dE9mZiArIHF1YXJ0ZXJMZW47CiAgICAgICAgICBmb3IgKHZhciBpID0gb3V0T2ZmLCBrID0gMDsgaSA8IGxpbWl0OyBpICs9IDIsIGsgKz0gc3RlcCkgewogICAgICAgICAgICBjb25zdCBBID0gaTsKICAgICAgICAgICAgY29uc3QgQiA9IEEgKyBxdWFydGVyTGVuOwogICAgICAgICAgICBjb25zdCBDID0gQiArIHF1YXJ0ZXJMZW47CiAgICAgICAgICAgIGNvbnN0IEQgPSBDICsgcXVhcnRlckxlbjsKCiAgICAgICAgICAgIC8vIE9yaWdpbmFsIHZhbHVlcwogICAgICAgICAgICBjb25zdCBBciA9IG91dFtBXTsKICAgICAgICAgICAgY29uc3QgQWkgPSBvdXRbQSArIDFdOwogICAgICAgICAgICBjb25zdCBCciA9IG91dFtCXTsKICAgICAgICAgICAgY29uc3QgQmkgPSBvdXRbQiArIDFdOwogICAgICAgICAgICBjb25zdCBDciA9IG91dFtDXTsKICAgICAgICAgICAgY29uc3QgQ2kgPSBvdXRbQyArIDFdOwogICAgICAgICAgICBjb25zdCBEciA9IG91dFtEXTsKICAgICAgICAgICAgY29uc3QgRGkgPSBvdXRbRCArIDFdOwoKICAgICAgICAgICAgLy8gTWlkZGxlIHZhbHVlcwogICAgICAgICAgICBjb25zdCBNQXIgPSBBcjsKICAgICAgICAgICAgY29uc3QgTUFpID0gQWk7CgogICAgICAgICAgICBjb25zdCB0YWJsZUJyID0gdGFibGVba107CiAgICAgICAgICAgIGNvbnN0IHRhYmxlQmkgPSBpbnYgKiB0YWJsZVtrICsgMV07CiAgICAgICAgICAgIGNvbnN0IE1CciA9IEJyICogdGFibGVCciAtIEJpICogdGFibGVCaTsKICAgICAgICAgICAgY29uc3QgTUJpID0gQnIgKiB0YWJsZUJpICsgQmkgKiB0YWJsZUJyOwoKICAgICAgICAgICAgY29uc3QgdGFibGVDciA9IHRhYmxlWzIgKiBrXTsKICAgICAgICAgICAgY29uc3QgdGFibGVDaSA9IGludiAqIHRhYmxlWzIgKiBrICsgMV07CiAgICAgICAgICAgIGNvbnN0IE1DciA9IENyICogdGFibGVDciAtIENpICogdGFibGVDaTsKICAgICAgICAgICAgY29uc3QgTUNpID0gQ3IgKiB0YWJsZUNpICsgQ2kgKiB0YWJsZUNyOwoKICAgICAgICAgICAgY29uc3QgdGFibGVEciA9IHRhYmxlWzMgKiBrXTsKICAgICAgICAgICAgY29uc3QgdGFibGVEaSA9IGludiAqIHRhYmxlWzMgKiBrICsgMV07CiAgICAgICAgICAgIGNvbnN0IE1EciA9IERyICogdGFibGVEciAtIERpICogdGFibGVEaTsKICAgICAgICAgICAgY29uc3QgTURpID0gRHIgKiB0YWJsZURpICsgRGkgKiB0YWJsZURyOwoKICAgICAgICAgICAgLy8gUHJlLUZpbmFsIHZhbHVlcwogICAgICAgICAgICBjb25zdCBUMHIgPSBNQXIgKyBNQ3I7CiAgICAgICAgICAgIGNvbnN0IFQwaSA9IE1BaSArIE1DaTsKICAgICAgICAgICAgY29uc3QgVDFyID0gTUFyIC0gTUNyOwogICAgICAgICAgICBjb25zdCBUMWkgPSBNQWkgLSBNQ2k7CiAgICAgICAgICAgIGNvbnN0IFQyciA9IE1CciArIE1EcjsKICAgICAgICAgICAgY29uc3QgVDJpID0gTUJpICsgTURpOwogICAgICAgICAgICBjb25zdCBUM3IgPSBpbnYgKiAoTUJyIC0gTURyKTsKICAgICAgICAgICAgY29uc3QgVDNpID0gaW52ICogKE1CaSAtIE1EaSk7CgogICAgICAgICAgICAvLyBGaW5hbCB2YWx1ZXMKICAgICAgICAgICAgY29uc3QgRkFyID0gVDByICsgVDJyOwogICAgICAgICAgICBjb25zdCBGQWkgPSBUMGkgKyBUMmk7CgogICAgICAgICAgICBjb25zdCBGQ3IgPSBUMHIgLSBUMnI7CiAgICAgICAgICAgIGNvbnN0IEZDaSA9IFQwaSAtIFQyaTsKCiAgICAgICAgICAgIGNvbnN0IEZCciA9IFQxciArIFQzaTsKICAgICAgICAgICAgY29uc3QgRkJpID0gVDFpIC0gVDNyOwoKICAgICAgICAgICAgY29uc3QgRkRyID0gVDFyIC0gVDNpOwogICAgICAgICAgICBjb25zdCBGRGkgPSBUMWkgKyBUM3I7CgogICAgICAgICAgICBvdXRbQV0gPSBGQXI7CiAgICAgICAgICAgIG91dFtBICsgMV0gPSBGQWk7CiAgICAgICAgICAgIG91dFtCXSA9IEZCcjsKICAgICAgICAgICAgb3V0W0IgKyAxXSA9IEZCaTsKICAgICAgICAgICAgb3V0W0NdID0gRkNyOwogICAgICAgICAgICBvdXRbQyArIDFdID0gRkNpOwogICAgICAgICAgICBvdXRbRF0gPSBGRHI7CiAgICAgICAgICAgIG91dFtEICsgMV0gPSBGRGk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIC8vIHJhZGl4LTIgaW1wbGVtZW50YXRpb24KICAgIC8vCiAgICAvLyBOT1RFOiBPbmx5IGNhbGxlZCBmb3IgbGVuPTQKICAgIEZGVC5wcm90b3R5cGUuX3NpbmdsZVRyYW5zZm9ybTIgPSBmdW5jdGlvbiBfc2luZ2xlVHJhbnNmb3JtMihvdXRPZmYsIG9mZiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGVwKSB7CiAgICAgIGNvbnN0IG91dCA9IHRoaXMuX291dDsKICAgICAgY29uc3QgZGF0YSA9IHRoaXMuX2RhdGE7CgogICAgICBjb25zdCBldmVuUiA9IGRhdGFbb2ZmXTsKICAgICAgY29uc3QgZXZlbkkgPSBkYXRhW29mZiArIDFdOwogICAgICBjb25zdCBvZGRSID0gZGF0YVtvZmYgKyBzdGVwXTsKICAgICAgY29uc3Qgb2RkSSA9IGRhdGFbb2ZmICsgc3RlcCArIDFdOwoKICAgICAgY29uc3QgbGVmdFIgPSBldmVuUiArIG9kZFI7CiAgICAgIGNvbnN0IGxlZnRJID0gZXZlbkkgKyBvZGRJOwogICAgICBjb25zdCByaWdodFIgPSBldmVuUiAtIG9kZFI7CiAgICAgIGNvbnN0IHJpZ2h0SSA9IGV2ZW5JIC0gb2RkSTsKCiAgICAgIG91dFtvdXRPZmZdID0gbGVmdFI7CiAgICAgIG91dFtvdXRPZmYgKyAxXSA9IGxlZnRJOwogICAgICBvdXRbb3V0T2ZmICsgMl0gPSByaWdodFI7CiAgICAgIG91dFtvdXRPZmYgKyAzXSA9IHJpZ2h0STsKICAgIH07CgogICAgLy8gcmFkaXgtNAogICAgLy8KICAgIC8vIE5PVEU6IE9ubHkgY2FsbGVkIGZvciBsZW49OAogICAgRkZULnByb3RvdHlwZS5fc2luZ2xlVHJhbnNmb3JtNCA9IGZ1bmN0aW9uIF9zaW5nbGVUcmFuc2Zvcm00KG91dE9mZiwgb2ZmLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXApIHsKICAgICAgY29uc3Qgb3V0ID0gdGhpcy5fb3V0OwogICAgICBjb25zdCBkYXRhID0gdGhpcy5fZGF0YTsKICAgICAgY29uc3QgaW52ID0gdGhpcy5faW52ID8gLTEgOiAxOwogICAgICBjb25zdCBzdGVwMiA9IHN0ZXAgKiAyOwogICAgICBjb25zdCBzdGVwMyA9IHN0ZXAgKiAzOwoKICAgICAgLy8gT3JpZ2luYWwgdmFsdWVzCiAgICAgIGNvbnN0IEFyID0gZGF0YVtvZmZdOwogICAgICBjb25zdCBBaSA9IGRhdGFbb2ZmICsgMV07CiAgICAgIGNvbnN0IEJyID0gZGF0YVtvZmYgKyBzdGVwXTsKICAgICAgY29uc3QgQmkgPSBkYXRhW29mZiArIHN0ZXAgKyAxXTsKICAgICAgY29uc3QgQ3IgPSBkYXRhW29mZiArIHN0ZXAyXTsKICAgICAgY29uc3QgQ2kgPSBkYXRhW29mZiArIHN0ZXAyICsgMV07CiAgICAgIGNvbnN0IERyID0gZGF0YVtvZmYgKyBzdGVwM107CiAgICAgIGNvbnN0IERpID0gZGF0YVtvZmYgKyBzdGVwMyArIDFdOwoKICAgICAgLy8gUHJlLUZpbmFsIHZhbHVlcwogICAgICBjb25zdCBUMHIgPSBBciArIENyOwogICAgICBjb25zdCBUMGkgPSBBaSArIENpOwogICAgICBjb25zdCBUMXIgPSBBciAtIENyOwogICAgICBjb25zdCBUMWkgPSBBaSAtIENpOwogICAgICBjb25zdCBUMnIgPSBCciArIERyOwogICAgICBjb25zdCBUMmkgPSBCaSArIERpOwogICAgICBjb25zdCBUM3IgPSBpbnYgKiAoQnIgLSBEcik7CiAgICAgIGNvbnN0IFQzaSA9IGludiAqIChCaSAtIERpKTsKCiAgICAgIC8vIEZpbmFsIHZhbHVlcwogICAgICBjb25zdCBGQXIgPSBUMHIgKyBUMnI7CiAgICAgIGNvbnN0IEZBaSA9IFQwaSArIFQyaTsKCiAgICAgIGNvbnN0IEZCciA9IFQxciArIFQzaTsKICAgICAgY29uc3QgRkJpID0gVDFpIC0gVDNyOwoKICAgICAgY29uc3QgRkNyID0gVDByIC0gVDJyOwogICAgICBjb25zdCBGQ2kgPSBUMGkgLSBUMmk7CgogICAgICBjb25zdCBGRHIgPSBUMXIgLSBUM2k7CiAgICAgIGNvbnN0IEZEaSA9IFQxaSArIFQzcjsKCiAgICAgIG91dFtvdXRPZmZdID0gRkFyOwogICAgICBvdXRbb3V0T2ZmICsgMV0gPSBGQWk7CiAgICAgIG91dFtvdXRPZmYgKyAyXSA9IEZCcjsKICAgICAgb3V0W291dE9mZiArIDNdID0gRkJpOwogICAgICBvdXRbb3V0T2ZmICsgNF0gPSBGQ3I7CiAgICAgIG91dFtvdXRPZmYgKyA1XSA9IEZDaTsKICAgICAgb3V0W291dE9mZiArIDZdID0gRkRyOwogICAgICBvdXRbb3V0T2ZmICsgN10gPSBGRGk7CiAgICB9OwoKICAgIC8vIFJlYWwgaW5wdXQgcmFkaXgtNCBpbXBsZW1lbnRhdGlvbgogICAgRkZULnByb3RvdHlwZS5fcmVhbFRyYW5zZm9ybTQgPSBmdW5jdGlvbiBfcmVhbFRyYW5zZm9ybTQoKSB7CiAgICAgIHZhciBvdXQgPSB0aGlzLl9vdXQ7CiAgICAgIHZhciBzaXplID0gdGhpcy5fY3NpemU7CgogICAgICAvLyBJbml0aWFsIHN0ZXAgKHBlcm11dGUgYW5kIHRyYW5zZm9ybSkKICAgICAgdmFyIHdpZHRoID0gdGhpcy5fd2lkdGg7CiAgICAgIHZhciBzdGVwID0gMSA8PCB3aWR0aDsKICAgICAgdmFyIGxlbiA9IChzaXplIC8gc3RlcCkgPDwgMTsKCiAgICAgIHZhciBvdXRPZmY7CiAgICAgIHZhciB0OwogICAgICB2YXIgYml0cmV2ID0gdGhpcy5fYml0cmV2OwogICAgICBpZiAobGVuID09PSA0KSB7CiAgICAgICAgZm9yIChvdXRPZmYgPSAwLCB0ID0gMDsgb3V0T2ZmIDwgc2l6ZTsgb3V0T2ZmICs9IGxlbiwgdCsrKSB7CiAgICAgICAgICBjb25zdCBvZmYgPSBiaXRyZXZbdF07CiAgICAgICAgICB0aGlzLl9zaW5nbGVSZWFsVHJhbnNmb3JtMihvdXRPZmYsIG9mZiA+Pj4gMSwgc3RlcCA+Pj4gMSk7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIC8vIGxlbiA9PT0gOAogICAgICAgIGZvciAob3V0T2ZmID0gMCwgdCA9IDA7IG91dE9mZiA8IHNpemU7IG91dE9mZiArPSBsZW4sIHQrKykgewogICAgICAgICAgY29uc3Qgb2ZmID0gYml0cmV2W3RdOwogICAgICAgICAgdGhpcy5fc2luZ2xlUmVhbFRyYW5zZm9ybTQob3V0T2ZmLCBvZmYgPj4+IDEsIHN0ZXAgPj4+IDEpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgLy8gTG9vcCB0aHJvdWdoIHN0ZXBzIGluIGRlY3JlYXNpbmcgb3JkZXIKICAgICAgdmFyIGludiA9IHRoaXMuX2ludiA/IC0xIDogMTsKICAgICAgdmFyIHRhYmxlID0gdGhpcy50YWJsZTsKICAgICAgZm9yIChzdGVwID4+PSAyOyBzdGVwID49IDI7IHN0ZXAgPj49IDIpIHsKICAgICAgICBsZW4gPSAoc2l6ZSAvIHN0ZXApIDw8IDE7CiAgICAgICAgdmFyIGhhbGZMZW4gPSBsZW4gPj4+IDE7CiAgICAgICAgdmFyIHF1YXJ0ZXJMZW4gPSBoYWxmTGVuID4+PiAxOwogICAgICAgIHZhciBocXVhcnRlckxlbiA9IHF1YXJ0ZXJMZW4gPj4+IDE7CgogICAgICAgIC8vIExvb3AgdGhyb3VnaCBvZmZzZXRzIGluIHRoZSBkYXRhCiAgICAgICAgZm9yIChvdXRPZmYgPSAwOyBvdXRPZmYgPCBzaXplOyBvdXRPZmYgKz0gbGVuKSB7CiAgICAgICAgICBmb3IgKHZhciBpID0gMCwgayA9IDA7IGkgPD0gaHF1YXJ0ZXJMZW47IGkgKz0gMiwgayArPSBzdGVwKSB7CiAgICAgICAgICAgIHZhciBBID0gb3V0T2ZmICsgaTsKICAgICAgICAgICAgdmFyIEIgPSBBICsgcXVhcnRlckxlbjsKICAgICAgICAgICAgdmFyIEMgPSBCICsgcXVhcnRlckxlbjsKICAgICAgICAgICAgdmFyIEQgPSBDICsgcXVhcnRlckxlbjsKCiAgICAgICAgICAgIC8vIE9yaWdpbmFsIHZhbHVlcwogICAgICAgICAgICB2YXIgQXIgPSBvdXRbQV07CiAgICAgICAgICAgIHZhciBBaSA9IG91dFtBICsgMV07CiAgICAgICAgICAgIHZhciBCciA9IG91dFtCXTsKICAgICAgICAgICAgdmFyIEJpID0gb3V0W0IgKyAxXTsKICAgICAgICAgICAgdmFyIENyID0gb3V0W0NdOwogICAgICAgICAgICB2YXIgQ2kgPSBvdXRbQyArIDFdOwogICAgICAgICAgICB2YXIgRHIgPSBvdXRbRF07CiAgICAgICAgICAgIHZhciBEaSA9IG91dFtEICsgMV07CgogICAgICAgICAgICAvLyBNaWRkbGUgdmFsdWVzCiAgICAgICAgICAgIHZhciBNQXIgPSBBcjsKICAgICAgICAgICAgdmFyIE1BaSA9IEFpOwoKICAgICAgICAgICAgdmFyIHRhYmxlQnIgPSB0YWJsZVtrXTsKICAgICAgICAgICAgdmFyIHRhYmxlQmkgPSBpbnYgKiB0YWJsZVtrICsgMV07CiAgICAgICAgICAgIHZhciBNQnIgPSBCciAqIHRhYmxlQnIgLSBCaSAqIHRhYmxlQmk7CiAgICAgICAgICAgIHZhciBNQmkgPSBCciAqIHRhYmxlQmkgKyBCaSAqIHRhYmxlQnI7CgogICAgICAgICAgICB2YXIgdGFibGVDciA9IHRhYmxlWzIgKiBrXTsKICAgICAgICAgICAgdmFyIHRhYmxlQ2kgPSBpbnYgKiB0YWJsZVsyICogayArIDFdOwogICAgICAgICAgICB2YXIgTUNyID0gQ3IgKiB0YWJsZUNyIC0gQ2kgKiB0YWJsZUNpOwogICAgICAgICAgICB2YXIgTUNpID0gQ3IgKiB0YWJsZUNpICsgQ2kgKiB0YWJsZUNyOwoKICAgICAgICAgICAgdmFyIHRhYmxlRHIgPSB0YWJsZVszICoga107CiAgICAgICAgICAgIHZhciB0YWJsZURpID0gaW52ICogdGFibGVbMyAqIGsgKyAxXTsKICAgICAgICAgICAgdmFyIE1EciA9IERyICogdGFibGVEciAtIERpICogdGFibGVEaTsKICAgICAgICAgICAgdmFyIE1EaSA9IERyICogdGFibGVEaSArIERpICogdGFibGVEcjsKCiAgICAgICAgICAgIC8vIFByZS1GaW5hbCB2YWx1ZXMKICAgICAgICAgICAgdmFyIFQwciA9IE1BciArIE1DcjsKICAgICAgICAgICAgdmFyIFQwaSA9IE1BaSArIE1DaTsKICAgICAgICAgICAgdmFyIFQxciA9IE1BciAtIE1DcjsKICAgICAgICAgICAgdmFyIFQxaSA9IE1BaSAtIE1DaTsKICAgICAgICAgICAgdmFyIFQyciA9IE1CciArIE1EcjsKICAgICAgICAgICAgdmFyIFQyaSA9IE1CaSArIE1EaTsKICAgICAgICAgICAgdmFyIFQzciA9IGludiAqIChNQnIgLSBNRHIpOwogICAgICAgICAgICB2YXIgVDNpID0gaW52ICogKE1CaSAtIE1EaSk7CgogICAgICAgICAgICAvLyBGaW5hbCB2YWx1ZXMKICAgICAgICAgICAgdmFyIEZBciA9IFQwciArIFQycjsKICAgICAgICAgICAgdmFyIEZBaSA9IFQwaSArIFQyaTsKCiAgICAgICAgICAgIHZhciBGQnIgPSBUMXIgKyBUM2k7CiAgICAgICAgICAgIHZhciBGQmkgPSBUMWkgLSBUM3I7CgogICAgICAgICAgICBvdXRbQV0gPSBGQXI7CiAgICAgICAgICAgIG91dFtBICsgMV0gPSBGQWk7CiAgICAgICAgICAgIG91dFtCXSA9IEZCcjsKICAgICAgICAgICAgb3V0W0IgKyAxXSA9IEZCaTsKCiAgICAgICAgICAgIC8vIE91dHB1dCBmaW5hbCBtaWRkbGUgcG9pbnQKICAgICAgICAgICAgaWYgKGkgPT09IDApIHsKICAgICAgICAgICAgICB2YXIgRkNyID0gVDByIC0gVDJyOwogICAgICAgICAgICAgIHZhciBGQ2kgPSBUMGkgLSBUMmk7CiAgICAgICAgICAgICAgb3V0W0NdID0gRkNyOwogICAgICAgICAgICAgIG91dFtDICsgMV0gPSBGQ2k7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIC8vIERvIG5vdCBvdmVyd3JpdGUgb3Vyc2VsdmVzCiAgICAgICAgICAgIGlmIChpID09PSBocXVhcnRlckxlbikKICAgICAgICAgICAgICBjb250aW51ZTsKCiAgICAgICAgICAgIC8vIEluIHRoZSBmbGlwcGVkIGNhc2U6CiAgICAgICAgICAgIC8vIE1BaSA9IC1NQWkKICAgICAgICAgICAgLy8gTUJyPS1NQmksIE1CaT0tTUJyCiAgICAgICAgICAgIC8vIE1Dcj0tTUNyCiAgICAgICAgICAgIC8vIE1Ecj1NRGksIE1EaT1NRHIKICAgICAgICAgICAgdmFyIFNUMHIgPSBUMXI7CiAgICAgICAgICAgIHZhciBTVDBpID0gLVQxaTsKICAgICAgICAgICAgdmFyIFNUMXIgPSBUMHI7CiAgICAgICAgICAgIHZhciBTVDFpID0gLVQwaTsKICAgICAgICAgICAgdmFyIFNUMnIgPSAtaW52ICogVDNpOwogICAgICAgICAgICB2YXIgU1QyaSA9IC1pbnYgKiBUM3I7CiAgICAgICAgICAgIHZhciBTVDNyID0gLWludiAqIFQyaTsKICAgICAgICAgICAgdmFyIFNUM2kgPSAtaW52ICogVDJyOwoKICAgICAgICAgICAgdmFyIFNGQXIgPSBTVDByICsgU1QycjsKICAgICAgICAgICAgdmFyIFNGQWkgPSBTVDBpICsgU1QyaTsKCiAgICAgICAgICAgIHZhciBTRkJyID0gU1QxciArIFNUM2k7CiAgICAgICAgICAgIHZhciBTRkJpID0gU1QxaSAtIFNUM3I7CgogICAgICAgICAgICB2YXIgU0EgPSBvdXRPZmYgKyBxdWFydGVyTGVuIC0gaTsKICAgICAgICAgICAgdmFyIFNCID0gb3V0T2ZmICsgaGFsZkxlbiAtIGk7CgogICAgICAgICAgICBvdXRbU0FdID0gU0ZBcjsKICAgICAgICAgICAgb3V0W1NBICsgMV0gPSBTRkFpOwogICAgICAgICAgICBvdXRbU0JdID0gU0ZCcjsKICAgICAgICAgICAgb3V0W1NCICsgMV0gPSBTRkJpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfTsKCiAgICAvLyByYWRpeC0yIGltcGxlbWVudGF0aW9uCiAgICAvLwogICAgLy8gTk9URTogT25seSBjYWxsZWQgZm9yIGxlbj00CiAgICBGRlQucHJvdG90eXBlLl9zaW5nbGVSZWFsVHJhbnNmb3JtMiA9IGZ1bmN0aW9uIF9zaW5nbGVSZWFsVHJhbnNmb3JtMihvdXRPZmYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZmYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGVwKSB7CiAgICAgIGNvbnN0IG91dCA9IHRoaXMuX291dDsKICAgICAgY29uc3QgZGF0YSA9IHRoaXMuX2RhdGE7CgogICAgICBjb25zdCBldmVuUiA9IGRhdGFbb2ZmXTsKICAgICAgY29uc3Qgb2RkUiA9IGRhdGFbb2ZmICsgc3RlcF07CgogICAgICBjb25zdCBsZWZ0UiA9IGV2ZW5SICsgb2RkUjsKICAgICAgY29uc3QgcmlnaHRSID0gZXZlblIgLSBvZGRSOwoKICAgICAgb3V0W291dE9mZl0gPSBsZWZ0UjsKICAgICAgb3V0W291dE9mZiArIDFdID0gMDsKICAgICAgb3V0W291dE9mZiArIDJdID0gcmlnaHRSOwogICAgICBvdXRbb3V0T2ZmICsgM10gPSAwOwogICAgfTsKCiAgICAvLyByYWRpeC00CiAgICAvLwogICAgLy8gTk9URTogT25seSBjYWxsZWQgZm9yIGxlbj04CiAgICBGRlQucHJvdG90eXBlLl9zaW5nbGVSZWFsVHJhbnNmb3JtNCA9IGZ1bmN0aW9uIF9zaW5nbGVSZWFsVHJhbnNmb3JtNChvdXRPZmYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZmYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGVwKSB7CiAgICAgIGNvbnN0IG91dCA9IHRoaXMuX291dDsKICAgICAgY29uc3QgZGF0YSA9IHRoaXMuX2RhdGE7CiAgICAgIGNvbnN0IGludiA9IHRoaXMuX2ludiA/IC0xIDogMTsKICAgICAgY29uc3Qgc3RlcDIgPSBzdGVwICogMjsKICAgICAgY29uc3Qgc3RlcDMgPSBzdGVwICogMzsKCiAgICAgIC8vIE9yaWdpbmFsIHZhbHVlcwogICAgICBjb25zdCBBciA9IGRhdGFbb2ZmXTsKICAgICAgY29uc3QgQnIgPSBkYXRhW29mZiArIHN0ZXBdOwogICAgICBjb25zdCBDciA9IGRhdGFbb2ZmICsgc3RlcDJdOwogICAgICBjb25zdCBEciA9IGRhdGFbb2ZmICsgc3RlcDNdOwoKICAgICAgLy8gUHJlLUZpbmFsIHZhbHVlcwogICAgICBjb25zdCBUMHIgPSBBciArIENyOwogICAgICBjb25zdCBUMXIgPSBBciAtIENyOwogICAgICBjb25zdCBUMnIgPSBCciArIERyOwogICAgICBjb25zdCBUM3IgPSBpbnYgKiAoQnIgLSBEcik7CgogICAgICAvLyBGaW5hbCB2YWx1ZXMKICAgICAgY29uc3QgRkFyID0gVDByICsgVDJyOwoKICAgICAgY29uc3QgRkJyID0gVDFyOwogICAgICBjb25zdCBGQmkgPSAtVDNyOwoKICAgICAgY29uc3QgRkNyID0gVDByIC0gVDJyOwoKICAgICAgY29uc3QgRkRyID0gVDFyOwogICAgICBjb25zdCBGRGkgPSBUM3I7CgogICAgICBvdXRbb3V0T2ZmXSA9IEZBcjsKICAgICAgb3V0W291dE9mZiArIDFdID0gMDsKICAgICAgb3V0W291dE9mZiArIDJdID0gRkJyOwogICAgICBvdXRbb3V0T2ZmICsgM10gPSBGQmk7CiAgICAgIG91dFtvdXRPZmYgKyA0XSA9IEZDcjsKICAgICAgb3V0W291dE9mZiArIDVdID0gMDsKICAgICAgb3V0W291dE9mZiArIDZdID0gRkRyOwogICAgICBvdXRbb3V0T2ZmICsgN10gPSBGRGk7CiAgICB9OwoKICAgIHZhciBGRlQkMSA9IC8qQF9fUFVSRV9fKi9nZXREZWZhdWx0RXhwb3J0RnJvbUNqcyhmZnQpOwoKICAgIGNvbnN0IEJVRkZFUkVEX0JMT0NLX1NJWkUgPSAyMDQ4OwogICAgZnVuY3Rpb24gZ2VuSGFubldpbmRvdyhsZW5ndGgpIHsKICAgICAgICBsZXQgd2luID0gbmV3IEZsb2F0MzJBcnJheShsZW5ndGgpOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgd2luW2ldID0gMC41ICogKDEgLSBNYXRoLmNvcygoMiAqIE1hdGguUEkgKiBpKSAvIGxlbmd0aCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gd2luOwogICAgfQogICAgY2xhc3MgUGhhc2VWb2NvZGVyUHJvY2Vzc29yIGV4dGVuZHMgT0xBUHJvY2Vzc29yIHsKICAgICAgICBmZnRTaXplOwogICAgICAgIHRpbWVDdXJzb3I7CiAgICAgICAgaGFubldpbmRvdzsKICAgICAgICBmZnQ7CiAgICAgICAgZnJlcUNvbXBsZXhCdWZmZXI7CiAgICAgICAgZnJlcUNvbXBsZXhCdWZmZXJTaGlmdGVkOwogICAgICAgIHRpbWVDb21wbGV4QnVmZmVyOwogICAgICAgIG1hZ25pdHVkZXM7CiAgICAgICAgcGVha0luZGV4ZXM7CiAgICAgICAgbmJQZWFrczsKICAgICAgICBzdGF0aWMgZ2V0IHBhcmFtZXRlckRlc2NyaXB0b3JzKCkgewogICAgICAgICAgICByZXR1cm4gWwogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIG5hbWU6ICJwaXRjaEZhY3RvciIsCiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdFZhbHVlOiAxLjAsCiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICBdOwogICAgICAgIH0KICAgICAgICBjb25zdHJ1Y3RvcihvcHRpb25zKSB7CiAgICAgICAgICAgIG9wdGlvbnMucHJvY2Vzc29yT3B0aW9ucyA9IHsKICAgICAgICAgICAgICAgIGJsb2NrU2l6ZTogQlVGRkVSRURfQkxPQ0tfU0laRSwKICAgICAgICAgICAgfTsKICAgICAgICAgICAgc3VwZXIob3B0aW9ucyk7CiAgICAgICAgICAgIHRoaXMuZmZ0U2l6ZSA9IHRoaXMuYmxvY2tTaXplOwogICAgICAgICAgICB0aGlzLnRpbWVDdXJzb3IgPSAwOwogICAgICAgICAgICB0aGlzLmhhbm5XaW5kb3cgPSBnZW5IYW5uV2luZG93KHRoaXMuYmxvY2tTaXplKTsKICAgICAgICAgICAgLy8gcHJlcGFyZSBGRlQgYW5kIHByZS1hbGxvY2F0ZSBidWZmZXJzCiAgICAgICAgICAgIHRoaXMuZmZ0ID0gbmV3IEZGVCQxKHRoaXMuZmZ0U2l6ZSk7CiAgICAgICAgICAgIHRoaXMuZnJlcUNvbXBsZXhCdWZmZXIgPSB0aGlzLmZmdC5jcmVhdGVDb21wbGV4QXJyYXkoKTsKICAgICAgICAgICAgdGhpcy5mcmVxQ29tcGxleEJ1ZmZlclNoaWZ0ZWQgPQogICAgICAgICAgICAgICAgdGhpcy5mZnQuY3JlYXRlQ29tcGxleEFycmF5KCk7CiAgICAgICAgICAgIHRoaXMudGltZUNvbXBsZXhCdWZmZXIgPSB0aGlzLmZmdC5jcmVhdGVDb21wbGV4QXJyYXkoKTsKICAgICAgICAgICAgdGhpcy5tYWduaXR1ZGVzID0gbmV3IEZsb2F0MzJBcnJheSh0aGlzLmZmdFNpemUgLyAyICsgMSk7CiAgICAgICAgICAgIHRoaXMucGVha0luZGV4ZXMgPSBuZXcgSW50MzJBcnJheSh0aGlzLm1hZ25pdHVkZXMubGVuZ3RoKTsKICAgICAgICAgICAgdGhpcy5uYlBlYWtzID0gMDsKICAgICAgICB9CiAgICAgICAgcHJvY2Vzc09MQShpbnB1dHMsIG91dHB1dHMsIHBhcmFtZXRlcnMpIHsKICAgICAgICAgICAgY29uc3QgcGl0Y2hGYWN0b3IgPSBwYXJhbWV0ZXJzLnBpdGNoRmFjdG9yW3BhcmFtZXRlcnMucGl0Y2hGYWN0b3IubGVuZ3RoIC0gMV07CiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5uYklucHV0czsgaSsrKSB7CiAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IGlucHV0c1tpXS5sZW5ndGg7IGorKykgewogICAgICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGlucHV0c1tpXVtqXTsKICAgICAgICAgICAgICAgICAgICB2YXIgb3V0cHV0ID0gb3V0cHV0c1tpXVtqXTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmFwcGx5SGFubldpbmRvdyhpbnB1dCk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5mZnQucmVhbFRyYW5zZm9ybSh0aGlzLmZyZXFDb21wbGV4QnVmZmVyLCBpbnB1dCk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb21wdXRlTWFnbml0dWRlcygpOwogICAgICAgICAgICAgICAgICAgIHRoaXMuZmluZFBlYWtzKCk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5zaGlmdFBlYWtzKHBpdGNoRmFjdG9yKTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmZmdC5jb21wbGV0ZVNwZWN0cnVtKHRoaXMuZnJlcUNvbXBsZXhCdWZmZXJTaGlmdGVkKTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmZmdC5pbnZlcnNlVHJhbnNmb3JtKHRoaXMudGltZUNvbXBsZXhCdWZmZXIsIHRoaXMuZnJlcUNvbXBsZXhCdWZmZXJTaGlmdGVkKTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmZmdC5mcm9tQ29tcGxleEFycmF5KHRoaXMudGltZUNvbXBsZXhCdWZmZXIsIG91dHB1dCk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5hcHBseUhhbm5XaW5kb3cob3V0cHV0KTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICB0aGlzLnRpbWVDdXJzb3IgKz0gdGhpcy5ob3BTaXplOwogICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgICAgYXBwbHlIYW5uV2luZG93KGlucHV0KSB7CiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5ibG9ja1NpemU7IGkrKykgewogICAgICAgICAgICAgICAgaW5wdXRbaV0gKj0gdGhpcy5oYW5uV2luZG93W2ldOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGNvbXB1dGVNYWduaXR1ZGVzKCkgewogICAgICAgICAgICBmb3IgKGxldCBpID0gMCwgaiA9IDA7IGkgPCB0aGlzLm1hZ25pdHVkZXMubGVuZ3RoOyBpKyssIGogKz0gMikgewogICAgICAgICAgICAgICAgY29uc3QgcmVhbCA9IHRoaXMuZnJlcUNvbXBsZXhCdWZmZXJbal07CiAgICAgICAgICAgICAgICBjb25zdCBpbWFnID0gdGhpcy5mcmVxQ29tcGxleEJ1ZmZlcltqICsgMV07CiAgICAgICAgICAgICAgICB0aGlzLm1hZ25pdHVkZXNbaV0gPSByZWFsICoqIDIgKyBpbWFnICoqIDI7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgZmluZFBlYWtzKCkgewogICAgICAgICAgICB0aGlzLm5iUGVha3MgPSAwOwogICAgICAgICAgICBmb3IgKGxldCBpID0gMiwgZW5kID0gdGhpcy5tYWduaXR1ZGVzLmxlbmd0aCAtIDI7IGkgPCBlbmQ7IGkrKykgewogICAgICAgICAgICAgICAgY29uc3QgbWFnID0gdGhpcy5tYWduaXR1ZGVzW2ldOwogICAgICAgICAgICAgICAgaWYgKHRoaXMubWFnbml0dWRlc1tpIC0gMV0gPj0gbWFnIHx8CiAgICAgICAgICAgICAgICAgICAgdGhpcy5tYWduaXR1ZGVzW2kgLSAyXSA+PSBtYWcgfHwKICAgICAgICAgICAgICAgICAgICB0aGlzLm1hZ25pdHVkZXNbaSArIDFdID49IG1hZyB8fAogICAgICAgICAgICAgICAgICAgIHRoaXMubWFnbml0dWRlc1tpICsgMl0gPj0gbWFnKSB7CiAgICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB0aGlzLnBlYWtJbmRleGVzW3RoaXMubmJQZWFrcysrXSA9IGk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgc2hpZnRQZWFrcyhwaXRjaEZhY3RvcikgewogICAgICAgICAgICB0aGlzLmZyZXFDb21wbGV4QnVmZmVyU2hpZnRlZC5maWxsKDApOwogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMubmJQZWFrczsgaSsrKSB7CiAgICAgICAgICAgICAgICBjb25zdCBwZWFrSW5kZXggPSB0aGlzLnBlYWtJbmRleGVzW2ldOwogICAgICAgICAgICAgICAgY29uc3QgcGVha0luZGV4U2hpZnRlZCA9IE1hdGgucm91bmQocGVha0luZGV4ICogcGl0Y2hGYWN0b3IpOwogICAgICAgICAgICAgICAgaWYgKHBlYWtJbmRleFNoaWZ0ZWQgPiB0aGlzLm1hZ25pdHVkZXMubGVuZ3RoKSB7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBsZXQgc3RhcnRJbmRleCA9IGkgPiAwCiAgICAgICAgICAgICAgICAgICAgPyBwZWFrSW5kZXggLSBNYXRoLmZsb29yKChwZWFrSW5kZXggLSB0aGlzLnBlYWtJbmRleGVzW2kgLSAxXSkgLyAyKQogICAgICAgICAgICAgICAgICAgIDogMDsKICAgICAgICAgICAgICAgIGxldCBlbmRJbmRleCA9IGkgPCB0aGlzLm5iUGVha3MgLSAxCiAgICAgICAgICAgICAgICAgICAgPyBwZWFrSW5kZXggKyBNYXRoLmNlaWwoKHRoaXMucGVha0luZGV4ZXNbaSArIDFdIC0gcGVha0luZGV4KSAvIDIpCiAgICAgICAgICAgICAgICAgICAgOiB0aGlzLmZmdFNpemU7CiAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gc3RhcnRJbmRleCAtIHBlYWtJbmRleDsgaiA8IGVuZEluZGV4IC0gcGVha0luZGV4OyBqKyspIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBiaW5JbmRleCA9IHBlYWtJbmRleCArIGo7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgYmluSW5kZXhTaGlmdGVkID0gcGVha0luZGV4U2hpZnRlZCArIGo7CiAgICAgICAgICAgICAgICAgICAgaWYgKGJpbkluZGV4U2hpZnRlZCA+PSB0aGlzLm1hZ25pdHVkZXMubGVuZ3RoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjb25zdCBvbWVnYURlbHRhID0gKDIgKiBNYXRoLlBJICogKGJpbkluZGV4U2hpZnRlZCAtIGJpbkluZGV4KSkgLyB0aGlzLmZmdFNpemU7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGhhc2VTaGlmdFJlYWwgPSBNYXRoLmNvcyhvbWVnYURlbHRhICogdGhpcy50aW1lQ3Vyc29yKTsKICAgICAgICAgICAgICAgICAgICBjb25zdCBwaGFzZVNoaWZ0SW1hZyA9IE1hdGguc2luKG9tZWdhRGVsdGEgKiB0aGlzLnRpbWVDdXJzb3IpOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IGluZGV4UmVhbCA9IGJpbkluZGV4ICogMjsKICAgICAgICAgICAgICAgICAgICBjb25zdCBpbmRleEltYWcgPSBpbmRleFJlYWwgKyAxOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlUmVhbCA9IHRoaXMuZnJlcUNvbXBsZXhCdWZmZXJbaW5kZXhSZWFsXTsKICAgICAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZUltYWcgPSB0aGlzLmZyZXFDb21wbGV4QnVmZmVyW2luZGV4SW1hZ107CiAgICAgICAgICAgICAgICAgICAgY29uc3QgdmFsdWVTaGlmdGVkUmVhbCA9IHZhbHVlUmVhbCAqIHBoYXNlU2hpZnRSZWFsIC0gdmFsdWVJbWFnICogcGhhc2VTaGlmdEltYWc7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgdmFsdWVTaGlmdGVkSW1hZyA9IHZhbHVlUmVhbCAqIHBoYXNlU2hpZnRJbWFnICsgdmFsdWVJbWFnICogcGhhc2VTaGlmdFJlYWw7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgaW5kZXhTaGlmdGVkUmVhbCA9IGJpbkluZGV4U2hpZnRlZCAqIDI7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgaW5kZXhTaGlmdGVkSW1hZyA9IGluZGV4U2hpZnRlZFJlYWwgKyAxOwogICAgICAgICAgICAgICAgICAgIHRoaXMuZnJlcUNvbXBsZXhCdWZmZXJTaGlmdGVkW2luZGV4U2hpZnRlZFJlYWxdICs9IHZhbHVlU2hpZnRlZFJlYWw7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5mcmVxQ29tcGxleEJ1ZmZlclNoaWZ0ZWRbaW5kZXhTaGlmdGVkSW1hZ10gKz0gdmFsdWVTaGlmdGVkSW1hZzsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KICAgIC8vIEB0cy1pZ25vcmUKICAgIHJlZ2lzdGVyUHJvY2Vzc29yKCJwaGFzZS12b2NvZGVyIiwgUGhhc2VWb2NvZGVyUHJvY2Vzc29yKTsKICAgIGNvbnNvbGUubG9nKCJQaGFzZVZvY29kZXJQcm9jZXNzb3IgcmVnaXN0ZXJlZCIpOwoKICAgIGV4cG9ydHMuUGhhc2VWb2NvZGVyUHJvY2Vzc29yID0gUGhhc2VWb2NvZGVyUHJvY2Vzc29yOwoKICAgIHJldHVybiBleHBvcnRzOwoKfSkoe30pOwovLyMgc291cmNlTWFwcGluZ1VSTD1waGFzZS12b2NvZGVyLWJ1bmRsZS5qcy5tYXAK";class w{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 R=100;function E(a){if(!a)return null;const g=a.match(/max-age\s*=\s*"?(\d+)"?/i);return g?parseInt(g[1],10):null}function D(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 w(R);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(C=>{const s=C[e];if(s)try{s(t)}catch(A){console.error(`Error in ${e} callback:`,A)}})}static async getOrCreatePendingRequest(g,e,t,I){if(t?.aborted)throw new DOMException("Operation was aborted","AbortError");if(I){const s=this.pendingCallbacks.get(g)||[];s.push(I),this.pendingCallbacks.set(g,s)}let C=this.pendingRequests.get(g);if(!C){const s=(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 t?.addEventListener("abort",()=>{t.aborted&&(this.pendingRequests.delete(g),this.pendingCallbacks.delete(g))},{once:!0}),this.pendingRequests.set(g,s),s}return C}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,C,s){const A=new Headers;t&&A.append("If-None-Match",t),I&&A.append("If-Modified-Since",I),console.debug(`[AudioCache] Fetching ${g}`,{headers:Object.fromEntries(A.entries()),hasEtag:!!t,hasLastModified:!!I});const i=await fetch(g,{headers:A,signal:C});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){s?.onCacheHit&&s.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 o.arrayBuffer()}else{console.warn(`Cache inconsistency detected for ${g}: 304 response but no cached body. Re-fetching.`);const n=await fetch(g,{signal:C});if(n.status===200){const c=n.clone(),h=n.headers.get("ETag"),d=n.headers.get("Last-Modified"),m=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:m||void 0})])}catch(b){throw await e.delete(g),await e.delete(`${g}:meta`),b}if(n.body){const{stream:b,total:V}=this.createProgressTrackingStream(n,g);return await this.collectStreamToArrayBuffer(b,V||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(C?.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 t=g.headers.get("content-length"),I=t?parseInt(t,10):null;let C=0;if(!g.body)throw new Error("Response body is null");const s=g.body.getReader();return{stream:new ReadableStream({start(i){function o(){return s.read().then(({done:n,value:c})=>{if(n){r.callAllCallbacks(e,"onLoadingProgress",{url:e,loaded:C,total:I,progress:I?1:-1,timestamp:Date.now()}),i.close();return}if(c){C+=c.byteLength;const h=I?C/I:-1;r.callAllCallbacks(e,"onLoadingProgress",{url:e,loaded:C,total:I,progress:h,timestamp:Date.now()}),i.enqueue(c)}return o()}).catch(n=>{i.error(n)})}return o()},cancel(i){return s.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),C=new Uint8Array(I);let s=0;for(;;){const{done:A,value:i}=await t.read();if(A)break;i&&(C.set(i,s),s+=i.byteLength)}return I}else{let I=new Uint8Array(8192),C=0;for(;;){const{done:s,value:A}=await t.read();if(s)break;if(A){if(C+A.byteLength>I.length){const i=Math.max(I.length*2,C+A.byteLength),o=new Uint8Array(i);o.set(I.subarray(0,C)),I=o}I.set(A,C),C+=A.byteLength}}return I.slice(0,C).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],o=Uint8Array.from(atob(i),c=>c.charCodeAt(0)).buffer,n=await r.decodeAudioData(g,o);return r.decodedBuffers.set(e,n),n}const C=await r.openCache(),s=await r.getMetadataFromCache(e,C),A=(()=>{if(!s||D(s.cacheControl))return!0;const i=E(s.cacheControl);if(i!==null){const o=(Date.now()-s.timestamp)/1e3;if(i>0&&o<i)return!1}return s.etag||s.lastModified?!0:Date.now()-s.timestamp>r.cacheExpirationTime})();return r.getOrCreatePendingRequest(e,async()=>{if(A){I?.onCacheMiss&&I.onCacheMiss({url:e,reason:s?"expired":"not-found",timestamp:Date.now()});try{const i=await r.fetchAndCacheBuffer(e,C,s?.etag,s?.lastModified,t,{onCacheHit:I?.onCacheHit});I?.onLoadingComplete&&I.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 I?.onCacheError&&I.onCacheError({url:e,error:i,operation:"get",timestamp:Date.now()}),i}}else{const i=await r.getBufferFromCache(e,C);if(i){I?.onCacheHit&&I.onCacheHit({url:e,cacheType:"browser",timestamp:Date.now()});const o=await r.decodeAudioData(g,i);return r.decodedBuffers.set(e,o),o}else{I?.onCacheError&&I.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,C,s?.etag,s?.lastModified,t,{onCacheHit:I?.onCacheHit}),n=await r.decodeAudioData(g,o);return r.decodedBuffers.set(e,n),n}}},t,{onLoadingProgress:I?.onLoadingProgress})}clearMemoryCache(){r.decodedBuffers=new w(R),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(C=>Promise.resolve().then(()=>C.fn(e)).catch(s=>console.error(`Error in listener for event ${g}:`,s)));return this.listeners[g]=t.filter(C=>!C.once),Promise.all(I).then(()=>{})}return Promise.resolve()}removeAllListeners(){this.listeners={}}}class X{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 p{_filters=[];addFilter(g){if(this._filters.includes(g))throw new Error("Cannot add the same filter instance twice");this._filters.push(g)}removeFilter(g){const e=this._filters.length;if(this._filters=this._filters.filter(t=>t!==g),this._filters.length===e)throw new Error("Cannot remove filter that was never added to this container")}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 S extends p{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 N extends p{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 S(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 H(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)}removeFilter(t){super.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 K(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=v(t,-1,1),this.panner.pan.setValueAtTime(v(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,C,s]=t,A=this.panner;A.positionX.value=I,A.positionY.value=C,A.positionZ.value=s}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 v(a,g,e){return Math.min(Math.max(a,g),e)}function W(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 F extends K(W(p)){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 F{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.origin.cacophony?.emit("globalPlay",{source:this.origin,timestamp:Date.now()}),[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,this.emit("pause",void 0),this.origin.cacophony?.emit("globalPause",{source:this.origin,timestamp:Date.now()})}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),this.origin.cacophony?.emit("globalStop",{source:this.origin,timestamp:Date.now()}))}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)}get outputNode(){if(!this.gainNode)throw new Error("Cannot access output node of a playback that has been cleaned up");return this.gainNode}connect(g){return this.outputNode.connect(g)}disconnect(g){g?this.outputNode.disconnect(g):this.outputNode.disconnect()}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 C=g.loopCount!==void 0?g.loopCount:this.loopCount,s=new Z(this.origin,I,t);return s.loopCount=C,s.currentLoop=this.currentLoop,s.setPanType(e,this.context),s.volume=this.volume,s.playbackRate=this._playbackRate,s._offset=this._offset,s._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,s.addFilter(i)}),this._state===1&&s.play(),s}}class u extends H(p){constructor(g,e,t,I,C=B.Buffer,s="HRTF",A){super(),this.url=g,this.globalGainNode=I,this.soundType=C,this.panType=s,this._cacophony=A,this.buffer=e,this.context=t}buffer;context;loopCount=0;_playbackRate=1;eventEmitter=new y;get cacophony(){return this._cacophony}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,C=g.loopCount!==void 0?g.loopCount:this.loopCount,s=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,this.cacophony);return n.loop(C),n.playbackRate=s,n.volume=A,e==="HRTF"?(n.threeDOptions=I,n.position=i):n.stereoPan=t,n.addFilters(o),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=>{const C=this.context.createBiquadFilter();C.type=I.type,C.frequency.value=I.frequency.value,C.Q.value=I.Q.value,C.gain.value=I.gain.value,t.addFilter(C)}),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]),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 P=(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 M(a,g,e){const t=[];let I=0,C;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");C=A.body.getReader();let i=new ArrayBuffer(0);const o=()=>{t.length=0,C&&C.cancel("Stream aborted").catch(()=>{})};e?.addEventListener("abort",o);function n(){return e?.aborted?(o(),Promise.resolve()):C.read().then(({value:c,done:h})=>{if(e?.aborted){o();return}let d=null;if(c){if(i.byteLength?d=P(i,c.buffer):(i=c.buffer.slice(0,44),d=c.buffer),g.decodeAudioData(d,function(m){e?.aborted||(t.push(m),t.length&&s())},function(m){console.log("err(decodeAudioData): "+m)}),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 s(){for(;t.length;){let A=t.shift();const i=g.createBufferSource();if(!A)return;i.buffer=A,i.connect(g.destination),I==0&&(I=g.currentTime+.02),i.start(I),I+=i.buffer.duration}}}function z(a){class g extends F{_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 T extends z(K(W(p))){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 H(p){constructor(g,e,t=B.Oscillator,I="HRTF",C={},s){super(),this.context=g,this.globalGainNode=e,this.soundType=t,this.panType=I,this.cacophony=s,this.context=g,this._oscillatorOptions=C}_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,C=g.volume!==void 0?g.volume:this.volume,s=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,this.cacophony);return o._volume=C,o._position=s,o._stereoPan=t,o._threeDOptions=I,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 t=new T(this,g,e);return t.volume=this.volume,this._filters.forEach(I=>{const C=this.context.createBiquadFilter();C.type=I.type,C.frequency.value=I.frequency.value,C.Q.value=I.Q.value,C.gain.value=I.gain.value,t.addFilter(C)}),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 Q{context;globalGainNode;listener;prevVolume=1;finalizationRegistry;eventEmitter=new y;cache;constructor(g,e){this.context=g||new f.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",Y,g):console.warn("AudioWorklet not supported")}async createWorkletNode(g,e,t){if(!this.context.audioWorklet)throw new Error("AudioWorklet not supported");try{return new f.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(C){throw console.error(C),C}return new f.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 C=g;if(e==="HTML"){const s=new Audio;return s.src=C,s.crossOrigin="anonymous",Promise.resolve(new u(C,void 0,this.context,this.globalGainNode,"HTML",t,this))}return e==="Streaming"?Promise.resolve(new u(C,void 0,this.context,this.globalGainNode,"Streaming",t,this)):this.cache.getAudioBuffer(this.context,C,I,{onLoadingStart:s=>this.emitAsync("loadingStart",s),onLoadingProgress:s=>this.emitAsync("loadingProgress",s),onLoadingComplete:s=>this.emitAsync("loadingComplete",s),onLoadingError:s=>this.emitAsync("loadingError",s),onCacheHit:s=>this.emitAsync("cacheHit",s),onCacheMiss:s=>this.emitAsync("cacheMiss",s),onCacheError:s=>this.emitAsync("cacheError",s)}).then(s=>new u(C,s,this.context,this.globalGainNode,e,t,this))}async createGroup(g){const e=new X;return g.forEach(t=>e.addSound(t)),e}async createGroupFromUrls(g,e="Buffer",t="HRTF",I){const C=new X;return(await Promise.all(g.map(A=>this.createSound(A,e,t,I)))).forEach(A=>C.addSound(A)),C}async createStream(g,e){return M(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 C=this.context.createBiquadFilter();return C.type=g||"lowpass",C.frequency.value=e,C.gain.value=t||0,C.Q.value=I||1,C};createPanner({coneInnerAngle:g,coneOuterAngle:e,coneOuterGain:t,distanceModel:I,maxDistance:C,channelCount:s,channelCountMode:A,channelInterpretation:i,panningModel:o,refDistance:n,rolloffFactor:c,positionX:h,positionY:d,positionZ:m,orientationX:b,orientationY:V,orientationZ:k}){const l=this.context.createPanner();return l.coneInnerAngle=g||360,l.coneOuterAngle=e||360,l.coneOuterGain=t||0,l.distanceModel=I||"inverse",l.maxDistance=C||1e4,l.channelCount=s||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=m||0,l.orientationX.value=b||0,l.orientationY.value=V||0,l.orientationZ.value=k||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 N(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,C,s]=e,[A,i,o]=t;this.listener.forwardX.value=I,this.listener.forwardY.value=C,this.listener.forwardZ.value=s,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,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,C=this.context.currentTime;this.listener.positionX.setValueAtTime(e,C),this.listener.positionY.setValueAtTime(t,C),this.listener.positionZ.setValueAtTime(I,C)}}class J{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=Q;exports.Group=X;exports.MicrophonePlayback=S;exports.Playback=Z;exports.Sound=u;exports.SoundType=B;exports.Synth=G;exports.SynthGroup=J;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const V=require("standardized-audio-context"),E="data:text/javascript;base64,dmFyIHBoYXNlVm9jb2RlciA9IChmdW5jdGlvbiAoZXhwb3J0cykgewogICAgJ3VzZSBzdHJpY3QnOwoKICAgIGNvbnN0IFdFQkFVRElPX0JMT0NLX1NJWkUgPSAxMjg7CiAgICBjb25zdCBERUZBVUxUX0JMT0NLX1NJWkUgPSAxMDI0OyAvLyBEZWZhdWx0IGJsb2NrIHNpemUgaWYgbm90IHByb3ZpZGVkIGluIG9wdGlvbnMKICAgIC8qKiBPdmVybGFwLUFkZCBOb2RlICovCiAgICBjbGFzcyBPTEFQcm9jZXNzb3IgZXh0ZW5kcyBBdWRpb1dvcmtsZXRQcm9jZXNzb3IgewogICAgICAgIG5iSW5wdXRzOwogICAgICAgIG5iT3V0cHV0czsKICAgICAgICBibG9ja1NpemU7CiAgICAgICAgaG9wU2l6ZTsKICAgICAgICBuYk92ZXJsYXBzOwogICAgICAgIGlucHV0QnVmZmVycyA9IFtdOwogICAgICAgIGlucHV0QnVmZmVyc0hlYWQgPSBbXTsKICAgICAgICBpbnB1dEJ1ZmZlcnNUb1NlbmQgPSBbXTsKICAgICAgICBvdXRwdXRCdWZmZXJzID0gW107CiAgICAgICAgb3V0cHV0QnVmZmVyc1RvUmV0cmlldmUgPSBbXTsKICAgICAgICBjb25zdHJ1Y3RvcihvcHRpb25zKSB7CiAgICAgICAgICAgIHN1cGVyKG9wdGlvbnMpOwogICAgICAgICAgICB0aGlzLm5iSW5wdXRzID0gb3B0aW9ucy5udW1iZXJPZklucHV0cyB8fCAxOwogICAgICAgICAgICB0aGlzLm5iT3V0cHV0cyA9IG9wdGlvbnMubnVtYmVyT2ZPdXRwdXRzIHx8IDE7CiAgICAgICAgICAgIHRoaXMuYmxvY2tTaXplID0gb3B0aW9ucy5wcm9jZXNzb3JPcHRpb25zLmJsb2NrU2l6ZSB8fCBERUZBVUxUX0JMT0NLX1NJWkU7CiAgICAgICAgICAgIHRoaXMuaG9wU2l6ZSA9IFdFQkFVRElPX0JMT0NLX1NJWkU7CiAgICAgICAgICAgIHRoaXMubmJPdmVybGFwcyA9IE1hdGguZmxvb3IodGhpcy5ibG9ja1NpemUgLyB0aGlzLmhvcFNpemUpOwogICAgICAgICAgICB0aGlzLmluaXRpYWxpemVCdWZmZXJzKCk7CiAgICAgICAgfQogICAgICAgIGluaXRpYWxpemVCdWZmZXJzKCkgewogICAgICAgICAgICB0aGlzLmlucHV0QnVmZmVycyA9IG5ldyBBcnJheSh0aGlzLm5iSW5wdXRzKTsKICAgICAgICAgICAgdGhpcy5pbnB1dEJ1ZmZlcnNIZWFkID0gbmV3IEFycmF5KHRoaXMubmJJbnB1dHMpOwogICAgICAgICAgICB0aGlzLmlucHV0QnVmZmVyc1RvU2VuZCA9IG5ldyBBcnJheSh0aGlzLm5iSW5wdXRzKTsKICAgICAgICAgICAgdGhpcy5vdXRwdXRCdWZmZXJzID0gbmV3IEFycmF5KHRoaXMubmJPdXRwdXRzKTsKICAgICAgICAgICAgdGhpcy5vdXRwdXRCdWZmZXJzVG9SZXRyaWV2ZSA9IG5ldyBBcnJheSh0aGlzLm5iT3V0cHV0cyk7CiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5uYklucHV0czsgaSsrKSB7CiAgICAgICAgICAgICAgICB0aGlzLmFsbG9jYXRlSW5wdXRDaGFubmVscyhpLCAxKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMubmJPdXRwdXRzOyBpKyspIHsKICAgICAgICAgICAgICAgIHRoaXMuYWxsb2NhdGVPdXRwdXRDaGFubmVscyhpLCAxKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBhbGxvY2F0ZUlucHV0Q2hhbm5lbHMoaW5wdXRJbmRleCwgbmJDaGFubmVscykgewogICAgICAgICAgICB0aGlzLmlucHV0QnVmZmVyc1tpbnB1dEluZGV4XSA9IG5ldyBBcnJheShuYkNoYW5uZWxzKTsKICAgICAgICAgICAgdGhpcy5pbnB1dEJ1ZmZlcnNIZWFkW2lucHV0SW5kZXhdID0gbmV3IEFycmF5KG5iQ2hhbm5lbHMpOwogICAgICAgICAgICB0aGlzLmlucHV0QnVmZmVyc1RvU2VuZFtpbnB1dEluZGV4XSA9IG5ldyBBcnJheShuYkNoYW5uZWxzKTsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBuYkNoYW5uZWxzOyBpKyspIHsKICAgICAgICAgICAgICAgIHRoaXMuaW5wdXRCdWZmZXJzW2lucHV0SW5kZXhdW2ldID0gbmV3IEZsb2F0MzJBcnJheSh0aGlzLmJsb2NrU2l6ZSArIFdFQkFVRElPX0JMT0NLX1NJWkUpOwogICAgICAgICAgICAgICAgdGhpcy5pbnB1dEJ1ZmZlcnNbaW5wdXRJbmRleF1baV0uZmlsbCgwKTsKICAgICAgICAgICAgICAgIHRoaXMuaW5wdXRCdWZmZXJzSGVhZFtpbnB1dEluZGV4XVtpXSA9IHRoaXMuaW5wdXRCdWZmZXJzW2lucHV0SW5kZXhdW2ldLnN1YmFycmF5KDAsIHRoaXMuYmxvY2tTaXplKTsKICAgICAgICAgICAgICAgIHRoaXMuaW5wdXRCdWZmZXJzVG9TZW5kW2lucHV0SW5kZXhdW2ldID0gbmV3IEZsb2F0MzJBcnJheSh0aGlzLmJsb2NrU2l6ZSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgYWxsb2NhdGVPdXRwdXRDaGFubmVscyhvdXRwdXRJbmRleCwgbmJDaGFubmVscykgewogICAgICAgICAgICB0aGlzLm91dHB1dEJ1ZmZlcnNbb3V0cHV0SW5kZXhdID0gbmV3IEFycmF5KG5iQ2hhbm5lbHMpOwogICAgICAgICAgICB0aGlzLm91dHB1dEJ1ZmZlcnNUb1JldHJpZXZlW291dHB1dEluZGV4XSA9IG5ldyBBcnJheShuYkNoYW5uZWxzKTsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBuYkNoYW5uZWxzOyBpKyspIHsKICAgICAgICAgICAgICAgIHRoaXMub3V0cHV0QnVmZmVyc1tvdXRwdXRJbmRleF1baV0gPSBuZXcgRmxvYXQzMkFycmF5KHRoaXMuYmxvY2tTaXplKTsKICAgICAgICAgICAgICAgIHRoaXMub3V0cHV0QnVmZmVyc1tvdXRwdXRJbmRleF1baV0uZmlsbCgwKTsKICAgICAgICAgICAgICAgIHRoaXMub3V0cHV0QnVmZmVyc1RvUmV0cmlldmVbb3V0cHV0SW5kZXhdW2ldID0gbmV3IEZsb2F0MzJBcnJheSh0aGlzLmJsb2NrU2l6ZSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmVhbGxvY2F0ZUNoYW5uZWxzSWZOZWVkZWQoaW5wdXRzLCBvdXRwdXRzKSB7CiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5uYklucHV0czsgaSsrKSB7CiAgICAgICAgICAgICAgICBsZXQgbmJDaGFubmVscyA9IGlucHV0c1tpXS5sZW5ndGg7CiAgICAgICAgICAgICAgICBpZiAobmJDaGFubmVscyAhPT0gdGhpcy5pbnB1dEJ1ZmZlcnNbaV0ubGVuZ3RoKSB7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5hbGxvY2F0ZUlucHV0Q2hhbm5lbHMoaSwgbmJDaGFubmVscyk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm5iT3V0cHV0czsgaSsrKSB7CiAgICAgICAgICAgICAgICBsZXQgbmJDaGFubmVscyA9IG91dHB1dHNbaV0ubGVuZ3RoOwogICAgICAgICAgICAgICAgaWYgKG5iQ2hhbm5lbHMgIT09IHRoaXMub3V0cHV0QnVmZmVyc1tpXS5sZW5ndGgpIHsKICAgICAgICAgICAgICAgICAgICB0aGlzLmFsbG9jYXRlT3V0cHV0Q2hhbm5lbHMoaSwgbmJDaGFubmVscyk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmVhZElucHV0cyhpbnB1dHMpIHsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm5iSW5wdXRzOyBpKyspIHsKICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgdGhpcy5pbnB1dEJ1ZmZlcnNbaV0ubGVuZ3RoOyBqKyspIHsKICAgICAgICAgICAgICAgICAgICBsZXQgd2ViQXVkaW9CbG9jayA9IGlucHV0c1tpXVtqXTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmlucHV0QnVmZmVyc1tpXVtqXS5zZXQod2ViQXVkaW9CbG9jaywgdGhpcy5ibG9ja1NpemUpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHdyaXRlT3V0cHV0cyhvdXRwdXRzKSB7CiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5uYk91dHB1dHM7IGkrKykgewogICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCB0aGlzLm91dHB1dEJ1ZmZlcnNbaV0ubGVuZ3RoOyBqKyspIHsKICAgICAgICAgICAgICAgICAgICBsZXQgd2ViQXVkaW9CbG9jayA9IG91dHB1dHNbaV1bal07CiAgICAgICAgICAgICAgICAgICAgd2ViQXVkaW9CbG9jay5zZXQodGhpcy5vdXRwdXRCdWZmZXJzW2ldW2pdLnN1YmFycmF5KDAsIFdFQkFVRElPX0JMT0NLX1NJWkUpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBzaGlmdElucHV0QnVmZmVycygpIHsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm5iSW5wdXRzOyBpKyspIHsKICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgdGhpcy5pbnB1dEJ1ZmZlcnNbaV0ubGVuZ3RoOyBqKyspIHsKICAgICAgICAgICAgICAgICAgICB0aGlzLmlucHV0QnVmZmVyc1tpXVtqXS5jb3B5V2l0aGluKDAsIFdFQkFVRElPX0JMT0NLX1NJWkUpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHNoaWZ0T3V0cHV0QnVmZmVycygpIHsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm5iT3V0cHV0czsgaSsrKSB7CiAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHRoaXMub3V0cHV0QnVmZmVyc1tpXS5sZW5ndGg7IGorKykgewogICAgICAgICAgICAgICAgICAgIHRoaXMub3V0cHV0QnVmZmVyc1tpXVtqXS5jb3B5V2l0aGluKDAsIFdFQkFVRElPX0JMT0NLX1NJWkUpOwogICAgICAgICAgICAgICAgICAgIHRoaXMub3V0cHV0QnVmZmVyc1tpXVtqXS5maWxsKDAsIHRoaXMuYmxvY2tTaXplIC0gV0VCQVVESU9fQkxPQ0tfU0laRSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcHJlcGFyZUlucHV0QnVmZmVyc1RvU2VuZCgpIHsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm5iSW5wdXRzOyBpKyspIHsKICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgdGhpcy5pbnB1dEJ1ZmZlcnNbaV0ubGVuZ3RoOyBqKyspIHsKICAgICAgICAgICAgICAgICAgICB0aGlzLmlucHV0QnVmZmVyc1RvU2VuZFtpXVtqXS5zZXQodGhpcy5pbnB1dEJ1ZmZlcnNIZWFkW2ldW2pdKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBoYW5kbGVPdXRwdXRCdWZmZXJzVG9SZXRyaWV2ZSgpIHsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm5iT3V0cHV0czsgaSsrKSB7CiAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHRoaXMub3V0cHV0QnVmZmVyc1tpXS5sZW5ndGg7IGorKykgewogICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGsgPSAwOyBrIDwgdGhpcy5ibG9ja1NpemU7IGsrKykgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm91dHB1dEJ1ZmZlcnNbaV1bal1ba10gKz0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub3V0cHV0QnVmZmVyc1RvUmV0cmlldmVbaV1bal1ba10gLyB0aGlzLm5iT3ZlcmxhcHM7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHByb2Nlc3MoaW5wdXRzLCBvdXRwdXRzLCBwYXJhbWV0ZXJzKSB7CiAgICAgICAgICAgIHRoaXMucmVhbGxvY2F0ZUNoYW5uZWxzSWZOZWVkZWQoaW5wdXRzLCBvdXRwdXRzKTsKICAgICAgICAgICAgdGhpcy5yZWFkSW5wdXRzKGlucHV0cyk7CiAgICAgICAgICAgIHRoaXMuc2hpZnRJbnB1dEJ1ZmZlcnMoKTsKICAgICAgICAgICAgdGhpcy5wcmVwYXJlSW5wdXRCdWZmZXJzVG9TZW5kKCk7CiAgICAgICAgICAgIHRoaXMucHJvY2Vzc09MQSh0aGlzLmlucHV0QnVmZmVyc1RvU2VuZCwgdGhpcy5vdXRwdXRCdWZmZXJzVG9SZXRyaWV2ZSwgcGFyYW1ldGVycyk7CiAgICAgICAgICAgIHRoaXMuaGFuZGxlT3V0cHV0QnVmZmVyc1RvUmV0cmlldmUoKTsKICAgICAgICAgICAgdGhpcy53cml0ZU91dHB1dHMob3V0cHV0cyk7CiAgICAgICAgICAgIHRoaXMuc2hpZnRPdXRwdXRCdWZmZXJzKCk7CiAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KICAgIH0KCiAgICBmdW5jdGlvbiBnZXREZWZhdWx0RXhwb3J0RnJvbUNqcyAoeCkgewogICAgCXJldHVybiB4ICYmIHguX19lc01vZHVsZSAmJiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoeCwgJ2RlZmF1bHQnKSA/IHhbJ2RlZmF1bHQnXSA6IHg7CiAgICB9CgogICAgZnVuY3Rpb24gRkZUKHNpemUpIHsKICAgICAgdGhpcy5zaXplID0gc2l6ZSB8IDA7CiAgICAgIGlmICh0aGlzLnNpemUgPD0gMSB8fCAodGhpcy5zaXplICYgKHRoaXMuc2l6ZSAtIDEpKSAhPT0gMCkKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZGVCBzaXplIG11c3QgYmUgYSBwb3dlciBvZiB0d28gYW5kIGJpZ2dlciB0aGFuIDEnKTsKCiAgICAgIHRoaXMuX2NzaXplID0gc2l6ZSA8PCAxOwoKICAgICAgLy8gTk9URTogVXNlIG9mIGB2YXJgIGlzIGludGVudGlvbmFsIGZvciBvbGQgVjggdmVyc2lvbnMKICAgICAgdmFyIHRhYmxlID0gbmV3IEFycmF5KHRoaXMuc2l6ZSAqIDIpOwogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRhYmxlLmxlbmd0aDsgaSArPSAyKSB7CiAgICAgICAgY29uc3QgYW5nbGUgPSBNYXRoLlBJICogaSAvIHRoaXMuc2l6ZTsKICAgICAgICB0YWJsZVtpXSA9IE1hdGguY29zKGFuZ2xlKTsKICAgICAgICB0YWJsZVtpICsgMV0gPSAtTWF0aC5zaW4oYW5nbGUpOwogICAgICB9CiAgICAgIHRoaXMudGFibGUgPSB0YWJsZTsKCiAgICAgIC8vIEZpbmQgc2l6ZSdzIHBvd2VyIG9mIHR3bwogICAgICB2YXIgcG93ZXIgPSAwOwogICAgICBmb3IgKHZhciB0ID0gMTsgdGhpcy5zaXplID4gdDsgdCA8PD0gMSkKICAgICAgICBwb3dlcisrOwoKICAgICAgLy8gQ2FsY3VsYXRlIGluaXRpYWwgc3RlcCdzIHdpZHRoOgogICAgICAvLyAgICogSWYgd2UgYXJlIGZ1bGwgcmFkaXgtNCAtIGl0IGlzIDJ4IHNtYWxsZXIgdG8gZ2l2ZSBpbml0YWwgbGVuPTgKICAgICAgLy8gICAqIE90aGVyd2lzZSBpdCBpcyB0aGUgc2FtZSBhcyBgcG93ZXJgIHRvIGdpdmUgbGVuPTQKICAgICAgdGhpcy5fd2lkdGggPSBwb3dlciAlIDIgPT09IDAgPyBwb3dlciAtIDEgOiBwb3dlcjsKCiAgICAgIC8vIFByZS1jb21wdXRlIGJpdC1yZXZlcnNhbCBwYXR0ZXJucwogICAgICB0aGlzLl9iaXRyZXYgPSBuZXcgQXJyYXkoMSA8PCB0aGlzLl93aWR0aCk7CiAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgdGhpcy5fYml0cmV2Lmxlbmd0aDsgaisrKSB7CiAgICAgICAgdGhpcy5fYml0cmV2W2pdID0gMDsKICAgICAgICBmb3IgKHZhciBzaGlmdCA9IDA7IHNoaWZ0IDwgdGhpcy5fd2lkdGg7IHNoaWZ0ICs9IDIpIHsKICAgICAgICAgIHZhciByZXZTaGlmdCA9IHRoaXMuX3dpZHRoIC0gc2hpZnQgLSAyOwogICAgICAgICAgdGhpcy5fYml0cmV2W2pdIHw9ICgoaiA+Pj4gc2hpZnQpICYgMykgPDwgcmV2U2hpZnQ7CiAgICAgICAgfQogICAgICB9CgogICAgICB0aGlzLl9vdXQgPSBudWxsOwogICAgICB0aGlzLl9kYXRhID0gbnVsbDsKICAgICAgdGhpcy5faW52ID0gMDsKICAgIH0KICAgIHZhciBmZnQgPSBGRlQ7CgogICAgRkZULnByb3RvdHlwZS5mcm9tQ29tcGxleEFycmF5ID0gZnVuY3Rpb24gZnJvbUNvbXBsZXhBcnJheShjb21wbGV4LCBzdG9yYWdlKSB7CiAgICAgIHZhciByZXMgPSBzdG9yYWdlIHx8IG5ldyBBcnJheShjb21wbGV4Lmxlbmd0aCA+Pj4gMSk7CiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY29tcGxleC5sZW5ndGg7IGkgKz0gMikKICAgICAgICByZXNbaSA+Pj4gMV0gPSBjb21wbGV4W2ldOwogICAgICByZXR1cm4gcmVzOwogICAgfTsKCiAgICBGRlQucHJvdG90eXBlLmNyZWF0ZUNvbXBsZXhBcnJheSA9IGZ1bmN0aW9uIGNyZWF0ZUNvbXBsZXhBcnJheSgpIHsKICAgICAgY29uc3QgcmVzID0gbmV3IEFycmF5KHRoaXMuX2NzaXplKTsKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCByZXMubGVuZ3RoOyBpKyspCiAgICAgICAgcmVzW2ldID0gMDsKICAgICAgcmV0dXJuIHJlczsKICAgIH07CgogICAgRkZULnByb3RvdHlwZS50b0NvbXBsZXhBcnJheSA9IGZ1bmN0aW9uIHRvQ29tcGxleEFycmF5KGlucHV0LCBzdG9yYWdlKSB7CiAgICAgIHZhciByZXMgPSBzdG9yYWdlIHx8IHRoaXMuY3JlYXRlQ29tcGxleEFycmF5KCk7CiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmVzLmxlbmd0aDsgaSArPSAyKSB7CiAgICAgICAgcmVzW2ldID0gaW5wdXRbaSA+Pj4gMV07CiAgICAgICAgcmVzW2kgKyAxXSA9IDA7CiAgICAgIH0KICAgICAgcmV0dXJuIHJlczsKICAgIH07CgogICAgRkZULnByb3RvdHlwZS5jb21wbGV0ZVNwZWN0cnVtID0gZnVuY3Rpb24gY29tcGxldGVTcGVjdHJ1bShzcGVjdHJ1bSkgewogICAgICB2YXIgc2l6ZSA9IHRoaXMuX2NzaXplOwogICAgICB2YXIgaGFsZiA9IHNpemUgPj4+IDE7CiAgICAgIGZvciAodmFyIGkgPSAyOyBpIDwgaGFsZjsgaSArPSAyKSB7CiAgICAgICAgc3BlY3RydW1bc2l6ZSAtIGldID0gc3BlY3RydW1baV07CiAgICAgICAgc3BlY3RydW1bc2l6ZSAtIGkgKyAxXSA9IC1zcGVjdHJ1bVtpICsgMV07CiAgICAgIH0KICAgIH07CgogICAgRkZULnByb3RvdHlwZS50cmFuc2Zvcm0gPSBmdW5jdGlvbiB0cmFuc2Zvcm0ob3V0LCBkYXRhKSB7CiAgICAgIGlmIChvdXQgPT09IGRhdGEpCiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBhbmQgb3V0cHV0IGJ1ZmZlcnMgbXVzdCBiZSBkaWZmZXJlbnQnKTsKCiAgICAgIHRoaXMuX291dCA9IG91dDsKICAgICAgdGhpcy5fZGF0YSA9IGRhdGE7CiAgICAgIHRoaXMuX2ludiA9IDA7CiAgICAgIHRoaXMuX3RyYW5zZm9ybTQoKTsKICAgICAgdGhpcy5fb3V0ID0gbnVsbDsKICAgICAgdGhpcy5fZGF0YSA9IG51bGw7CiAgICB9OwoKICAgIEZGVC5wcm90b3R5cGUucmVhbFRyYW5zZm9ybSA9IGZ1bmN0aW9uIHJlYWxUcmFuc2Zvcm0ob3V0LCBkYXRhKSB7CiAgICAgIGlmIChvdXQgPT09IGRhdGEpCiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBhbmQgb3V0cHV0IGJ1ZmZlcnMgbXVzdCBiZSBkaWZmZXJlbnQnKTsKCiAgICAgIHRoaXMuX291dCA9IG91dDsKICAgICAgdGhpcy5fZGF0YSA9IGRhdGE7CiAgICAgIHRoaXMuX2ludiA9IDA7CiAgICAgIHRoaXMuX3JlYWxUcmFuc2Zvcm00KCk7CiAgICAgIHRoaXMuX291dCA9IG51bGw7CiAgICAgIHRoaXMuX2RhdGEgPSBudWxsOwogICAgfTsKCiAgICBGRlQucHJvdG90eXBlLmludmVyc2VUcmFuc2Zvcm0gPSBmdW5jdGlvbiBpbnZlcnNlVHJhbnNmb3JtKG91dCwgZGF0YSkgewogICAgICBpZiAob3V0ID09PSBkYXRhKQogICAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgYW5kIG91dHB1dCBidWZmZXJzIG11c3QgYmUgZGlmZmVyZW50Jyk7CgogICAgICB0aGlzLl9vdXQgPSBvdXQ7CiAgICAgIHRoaXMuX2RhdGEgPSBkYXRhOwogICAgICB0aGlzLl9pbnYgPSAxOwogICAgICB0aGlzLl90cmFuc2Zvcm00KCk7CiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb3V0Lmxlbmd0aDsgaSsrKQogICAgICAgIG91dFtpXSAvPSB0aGlzLnNpemU7CiAgICAgIHRoaXMuX291dCA9IG51bGw7CiAgICAgIHRoaXMuX2RhdGEgPSBudWxsOwogICAgfTsKCiAgICAvLyByYWRpeC00IGltcGxlbWVudGF0aW9uCiAgICAvLwogICAgLy8gTk9URTogVXNlcyBvZiBgdmFyYCBhcmUgaW50ZW50aW9uYWwgZm9yIG9sZGVyIFY4IHZlcnNpb24gdGhhdCBkbyBub3QKICAgIC8vIHN1cHBvcnQgYm90aCBgbGV0IGNvbXBvdW5kIGFzc2lnbm1lbnRzYCBhbmQgYGNvbnN0IHBoaWAKICAgIEZGVC5wcm90b3R5cGUuX3RyYW5zZm9ybTQgPSBmdW5jdGlvbiBfdHJhbnNmb3JtNCgpIHsKICAgICAgdmFyIG91dCA9IHRoaXMuX291dDsKICAgICAgdmFyIHNpemUgPSB0aGlzLl9jc2l6ZTsKCiAgICAgIC8vIEluaXRpYWwgc3RlcCAocGVybXV0ZSBhbmQgdHJhbnNmb3JtKQogICAgICB2YXIgd2lkdGggPSB0aGlzLl93aWR0aDsKICAgICAgdmFyIHN0ZXAgPSAxIDw8IHdpZHRoOwogICAgICB2YXIgbGVuID0gKHNpemUgLyBzdGVwKSA8PCAxOwoKICAgICAgdmFyIG91dE9mZjsKICAgICAgdmFyIHQ7CiAgICAgIHZhciBiaXRyZXYgPSB0aGlzLl9iaXRyZXY7CiAgICAgIGlmIChsZW4gPT09IDQpIHsKICAgICAgICBmb3IgKG91dE9mZiA9IDAsIHQgPSAwOyBvdXRPZmYgPCBzaXplOyBvdXRPZmYgKz0gbGVuLCB0KyspIHsKICAgICAgICAgIGNvbnN0IG9mZiA9IGJpdHJldlt0XTsKICAgICAgICAgIHRoaXMuX3NpbmdsZVRyYW5zZm9ybTIob3V0T2ZmLCBvZmYsIHN0ZXApOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICAvLyBsZW4gPT09IDgKICAgICAgICBmb3IgKG91dE9mZiA9IDAsIHQgPSAwOyBvdXRPZmYgPCBzaXplOyBvdXRPZmYgKz0gbGVuLCB0KyspIHsKICAgICAgICAgIGNvbnN0IG9mZiA9IGJpdHJldlt0XTsKICAgICAgICAgIHRoaXMuX3NpbmdsZVRyYW5zZm9ybTQob3V0T2ZmLCBvZmYsIHN0ZXApOwogICAgICAgIH0KICAgICAgfQoKICAgICAgLy8gTG9vcCB0aHJvdWdoIHN0ZXBzIGluIGRlY3JlYXNpbmcgb3JkZXIKICAgICAgdmFyIGludiA9IHRoaXMuX2ludiA/IC0xIDogMTsKICAgICAgdmFyIHRhYmxlID0gdGhpcy50YWJsZTsKICAgICAgZm9yIChzdGVwID4+PSAyOyBzdGVwID49IDI7IHN0ZXAgPj49IDIpIHsKICAgICAgICBsZW4gPSAoc2l6ZSAvIHN0ZXApIDw8IDE7CiAgICAgICAgdmFyIHF1YXJ0ZXJMZW4gPSBsZW4gPj4+IDI7CgogICAgICAgIC8vIExvb3AgdGhyb3VnaCBvZmZzZXRzIGluIHRoZSBkYXRhCiAgICAgICAgZm9yIChvdXRPZmYgPSAwOyBvdXRPZmYgPCBzaXplOyBvdXRPZmYgKz0gbGVuKSB7CiAgICAgICAgICAvLyBGdWxsIGNhc2UKICAgICAgICAgIHZhciBsaW1pdCA9IG91dE9mZiArIHF1YXJ0ZXJMZW47CiAgICAgICAgICBmb3IgKHZhciBpID0gb3V0T2ZmLCBrID0gMDsgaSA8IGxpbWl0OyBpICs9IDIsIGsgKz0gc3RlcCkgewogICAgICAgICAgICBjb25zdCBBID0gaTsKICAgICAgICAgICAgY29uc3QgQiA9IEEgKyBxdWFydGVyTGVuOwogICAgICAgICAgICBjb25zdCBDID0gQiArIHF1YXJ0ZXJMZW47CiAgICAgICAgICAgIGNvbnN0IEQgPSBDICsgcXVhcnRlckxlbjsKCiAgICAgICAgICAgIC8vIE9yaWdpbmFsIHZhbHVlcwogICAgICAgICAgICBjb25zdCBBciA9IG91dFtBXTsKICAgICAgICAgICAgY29uc3QgQWkgPSBvdXRbQSArIDFdOwogICAgICAgICAgICBjb25zdCBCciA9IG91dFtCXTsKICAgICAgICAgICAgY29uc3QgQmkgPSBvdXRbQiArIDFdOwogICAgICAgICAgICBjb25zdCBDciA9IG91dFtDXTsKICAgICAgICAgICAgY29uc3QgQ2kgPSBvdXRbQyArIDFdOwogICAgICAgICAgICBjb25zdCBEciA9IG91dFtEXTsKICAgICAgICAgICAgY29uc3QgRGkgPSBvdXRbRCArIDFdOwoKICAgICAgICAgICAgLy8gTWlkZGxlIHZhbHVlcwogICAgICAgICAgICBjb25zdCBNQXIgPSBBcjsKICAgICAgICAgICAgY29uc3QgTUFpID0gQWk7CgogICAgICAgICAgICBjb25zdCB0YWJsZUJyID0gdGFibGVba107CiAgICAgICAgICAgIGNvbnN0IHRhYmxlQmkgPSBpbnYgKiB0YWJsZVtrICsgMV07CiAgICAgICAgICAgIGNvbnN0IE1CciA9IEJyICogdGFibGVCciAtIEJpICogdGFibGVCaTsKICAgICAgICAgICAgY29uc3QgTUJpID0gQnIgKiB0YWJsZUJpICsgQmkgKiB0YWJsZUJyOwoKICAgICAgICAgICAgY29uc3QgdGFibGVDciA9IHRhYmxlWzIgKiBrXTsKICAgICAgICAgICAgY29uc3QgdGFibGVDaSA9IGludiAqIHRhYmxlWzIgKiBrICsgMV07CiAgICAgICAgICAgIGNvbnN0IE1DciA9IENyICogdGFibGVDciAtIENpICogdGFibGVDaTsKICAgICAgICAgICAgY29uc3QgTUNpID0gQ3IgKiB0YWJsZUNpICsgQ2kgKiB0YWJsZUNyOwoKICAgICAgICAgICAgY29uc3QgdGFibGVEciA9IHRhYmxlWzMgKiBrXTsKICAgICAgICAgICAgY29uc3QgdGFibGVEaSA9IGludiAqIHRhYmxlWzMgKiBrICsgMV07CiAgICAgICAgICAgIGNvbnN0IE1EciA9IERyICogdGFibGVEciAtIERpICogdGFibGVEaTsKICAgICAgICAgICAgY29uc3QgTURpID0gRHIgKiB0YWJsZURpICsgRGkgKiB0YWJsZURyOwoKICAgICAgICAgICAgLy8gUHJlLUZpbmFsIHZhbHVlcwogICAgICAgICAgICBjb25zdCBUMHIgPSBNQXIgKyBNQ3I7CiAgICAgICAgICAgIGNvbnN0IFQwaSA9IE1BaSArIE1DaTsKICAgICAgICAgICAgY29uc3QgVDFyID0gTUFyIC0gTUNyOwogICAgICAgICAgICBjb25zdCBUMWkgPSBNQWkgLSBNQ2k7CiAgICAgICAgICAgIGNvbnN0IFQyciA9IE1CciArIE1EcjsKICAgICAgICAgICAgY29uc3QgVDJpID0gTUJpICsgTURpOwogICAgICAgICAgICBjb25zdCBUM3IgPSBpbnYgKiAoTUJyIC0gTURyKTsKICAgICAgICAgICAgY29uc3QgVDNpID0gaW52ICogKE1CaSAtIE1EaSk7CgogICAgICAgICAgICAvLyBGaW5hbCB2YWx1ZXMKICAgICAgICAgICAgY29uc3QgRkFyID0gVDByICsgVDJyOwogICAgICAgICAgICBjb25zdCBGQWkgPSBUMGkgKyBUMmk7CgogICAgICAgICAgICBjb25zdCBGQ3IgPSBUMHIgLSBUMnI7CiAgICAgICAgICAgIGNvbnN0IEZDaSA9IFQwaSAtIFQyaTsKCiAgICAgICAgICAgIGNvbnN0IEZCciA9IFQxciArIFQzaTsKICAgICAgICAgICAgY29uc3QgRkJpID0gVDFpIC0gVDNyOwoKICAgICAgICAgICAgY29uc3QgRkRyID0gVDFyIC0gVDNpOwogICAgICAgICAgICBjb25zdCBGRGkgPSBUMWkgKyBUM3I7CgogICAgICAgICAgICBvdXRbQV0gPSBGQXI7CiAgICAgICAgICAgIG91dFtBICsgMV0gPSBGQWk7CiAgICAgICAgICAgIG91dFtCXSA9IEZCcjsKICAgICAgICAgICAgb3V0W0IgKyAxXSA9IEZCaTsKICAgICAgICAgICAgb3V0W0NdID0gRkNyOwogICAgICAgICAgICBvdXRbQyArIDFdID0gRkNpOwogICAgICAgICAgICBvdXRbRF0gPSBGRHI7CiAgICAgICAgICAgIG91dFtEICsgMV0gPSBGRGk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIC8vIHJhZGl4LTIgaW1wbGVtZW50YXRpb24KICAgIC8vCiAgICAvLyBOT1RFOiBPbmx5IGNhbGxlZCBmb3IgbGVuPTQKICAgIEZGVC5wcm90b3R5cGUuX3NpbmdsZVRyYW5zZm9ybTIgPSBmdW5jdGlvbiBfc2luZ2xlVHJhbnNmb3JtMihvdXRPZmYsIG9mZiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGVwKSB7CiAgICAgIGNvbnN0IG91dCA9IHRoaXMuX291dDsKICAgICAgY29uc3QgZGF0YSA9IHRoaXMuX2RhdGE7CgogICAgICBjb25zdCBldmVuUiA9IGRhdGFbb2ZmXTsKICAgICAgY29uc3QgZXZlbkkgPSBkYXRhW29mZiArIDFdOwogICAgICBjb25zdCBvZGRSID0gZGF0YVtvZmYgKyBzdGVwXTsKICAgICAgY29uc3Qgb2RkSSA9IGRhdGFbb2ZmICsgc3RlcCArIDFdOwoKICAgICAgY29uc3QgbGVmdFIgPSBldmVuUiArIG9kZFI7CiAgICAgIGNvbnN0IGxlZnRJID0gZXZlbkkgKyBvZGRJOwogICAgICBjb25zdCByaWdodFIgPSBldmVuUiAtIG9kZFI7CiAgICAgIGNvbnN0IHJpZ2h0SSA9IGV2ZW5JIC0gb2RkSTsKCiAgICAgIG91dFtvdXRPZmZdID0gbGVmdFI7CiAgICAgIG91dFtvdXRPZmYgKyAxXSA9IGxlZnRJOwogICAgICBvdXRbb3V0T2ZmICsgMl0gPSByaWdodFI7CiAgICAgIG91dFtvdXRPZmYgKyAzXSA9IHJpZ2h0STsKICAgIH07CgogICAgLy8gcmFkaXgtNAogICAgLy8KICAgIC8vIE5PVEU6IE9ubHkgY2FsbGVkIGZvciBsZW49OAogICAgRkZULnByb3RvdHlwZS5fc2luZ2xlVHJhbnNmb3JtNCA9IGZ1bmN0aW9uIF9zaW5nbGVUcmFuc2Zvcm00KG91dE9mZiwgb2ZmLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXApIHsKICAgICAgY29uc3Qgb3V0ID0gdGhpcy5fb3V0OwogICAgICBjb25zdCBkYXRhID0gdGhpcy5fZGF0YTsKICAgICAgY29uc3QgaW52ID0gdGhpcy5faW52ID8gLTEgOiAxOwogICAgICBjb25zdCBzdGVwMiA9IHN0ZXAgKiAyOwogICAgICBjb25zdCBzdGVwMyA9IHN0ZXAgKiAzOwoKICAgICAgLy8gT3JpZ2luYWwgdmFsdWVzCiAgICAgIGNvbnN0IEFyID0gZGF0YVtvZmZdOwogICAgICBjb25zdCBBaSA9IGRhdGFbb2ZmICsgMV07CiAgICAgIGNvbnN0IEJyID0gZGF0YVtvZmYgKyBzdGVwXTsKICAgICAgY29uc3QgQmkgPSBkYXRhW29mZiArIHN0ZXAgKyAxXTsKICAgICAgY29uc3QgQ3IgPSBkYXRhW29mZiArIHN0ZXAyXTsKICAgICAgY29uc3QgQ2kgPSBkYXRhW29mZiArIHN0ZXAyICsgMV07CiAgICAgIGNvbnN0IERyID0gZGF0YVtvZmYgKyBzdGVwM107CiAgICAgIGNvbnN0IERpID0gZGF0YVtvZmYgKyBzdGVwMyArIDFdOwoKICAgICAgLy8gUHJlLUZpbmFsIHZhbHVlcwogICAgICBjb25zdCBUMHIgPSBBciArIENyOwogICAgICBjb25zdCBUMGkgPSBBaSArIENpOwogICAgICBjb25zdCBUMXIgPSBBciAtIENyOwogICAgICBjb25zdCBUMWkgPSBBaSAtIENpOwogICAgICBjb25zdCBUMnIgPSBCciArIERyOwogICAgICBjb25zdCBUMmkgPSBCaSArIERpOwogICAgICBjb25zdCBUM3IgPSBpbnYgKiAoQnIgLSBEcik7CiAgICAgIGNvbnN0IFQzaSA9IGludiAqIChCaSAtIERpKTsKCiAgICAgIC8vIEZpbmFsIHZhbHVlcwogICAgICBjb25zdCBGQXIgPSBUMHIgKyBUMnI7CiAgICAgIGNvbnN0IEZBaSA9IFQwaSArIFQyaTsKCiAgICAgIGNvbnN0IEZCciA9IFQxciArIFQzaTsKICAgICAgY29uc3QgRkJpID0gVDFpIC0gVDNyOwoKICAgICAgY29uc3QgRkNyID0gVDByIC0gVDJyOwogICAgICBjb25zdCBGQ2kgPSBUMGkgLSBUMmk7CgogICAgICBjb25zdCBGRHIgPSBUMXIgLSBUM2k7CiAgICAgIGNvbnN0IEZEaSA9IFQxaSArIFQzcjsKCiAgICAgIG91dFtvdXRPZmZdID0gRkFyOwogICAgICBvdXRbb3V0T2ZmICsgMV0gPSBGQWk7CiAgICAgIG91dFtvdXRPZmYgKyAyXSA9IEZCcjsKICAgICAgb3V0W291dE9mZiArIDNdID0gRkJpOwogICAgICBvdXRbb3V0T2ZmICsgNF0gPSBGQ3I7CiAgICAgIG91dFtvdXRPZmYgKyA1XSA9IEZDaTsKICAgICAgb3V0W291dE9mZiArIDZdID0gRkRyOwogICAgICBvdXRbb3V0T2ZmICsgN10gPSBGRGk7CiAgICB9OwoKICAgIC8vIFJlYWwgaW5wdXQgcmFkaXgtNCBpbXBsZW1lbnRhdGlvbgogICAgRkZULnByb3RvdHlwZS5fcmVhbFRyYW5zZm9ybTQgPSBmdW5jdGlvbiBfcmVhbFRyYW5zZm9ybTQoKSB7CiAgICAgIHZhciBvdXQgPSB0aGlzLl9vdXQ7CiAgICAgIHZhciBzaXplID0gdGhpcy5fY3NpemU7CgogICAgICAvLyBJbml0aWFsIHN0ZXAgKHBlcm11dGUgYW5kIHRyYW5zZm9ybSkKICAgICAgdmFyIHdpZHRoID0gdGhpcy5fd2lkdGg7CiAgICAgIHZhciBzdGVwID0gMSA8PCB3aWR0aDsKICAgICAgdmFyIGxlbiA9IChzaXplIC8gc3RlcCkgPDwgMTsKCiAgICAgIHZhciBvdXRPZmY7CiAgICAgIHZhciB0OwogICAgICB2YXIgYml0cmV2ID0gdGhpcy5fYml0cmV2OwogICAgICBpZiAobGVuID09PSA0KSB7CiAgICAgICAgZm9yIChvdXRPZmYgPSAwLCB0ID0gMDsgb3V0T2ZmIDwgc2l6ZTsgb3V0T2ZmICs9IGxlbiwgdCsrKSB7CiAgICAgICAgICBjb25zdCBvZmYgPSBiaXRyZXZbdF07CiAgICAgICAgICB0aGlzLl9zaW5nbGVSZWFsVHJhbnNmb3JtMihvdXRPZmYsIG9mZiA+Pj4gMSwgc3RlcCA+Pj4gMSk7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIC8vIGxlbiA9PT0gOAogICAgICAgIGZvciAob3V0T2ZmID0gMCwgdCA9IDA7IG91dE9mZiA8IHNpemU7IG91dE9mZiArPSBsZW4sIHQrKykgewogICAgICAgICAgY29uc3Qgb2ZmID0gYml0cmV2W3RdOwogICAgICAgICAgdGhpcy5fc2luZ2xlUmVhbFRyYW5zZm9ybTQob3V0T2ZmLCBvZmYgPj4+IDEsIHN0ZXAgPj4+IDEpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgLy8gTG9vcCB0aHJvdWdoIHN0ZXBzIGluIGRlY3JlYXNpbmcgb3JkZXIKICAgICAgdmFyIGludiA9IHRoaXMuX2ludiA/IC0xIDogMTsKICAgICAgdmFyIHRhYmxlID0gdGhpcy50YWJsZTsKICAgICAgZm9yIChzdGVwID4+PSAyOyBzdGVwID49IDI7IHN0ZXAgPj49IDIpIHsKICAgICAgICBsZW4gPSAoc2l6ZSAvIHN0ZXApIDw8IDE7CiAgICAgICAgdmFyIGhhbGZMZW4gPSBsZW4gPj4+IDE7CiAgICAgICAgdmFyIHF1YXJ0ZXJMZW4gPSBoYWxmTGVuID4+PiAxOwogICAgICAgIHZhciBocXVhcnRlckxlbiA9IHF1YXJ0ZXJMZW4gPj4+IDE7CgogICAgICAgIC8vIExvb3AgdGhyb3VnaCBvZmZzZXRzIGluIHRoZSBkYXRhCiAgICAgICAgZm9yIChvdXRPZmYgPSAwOyBvdXRPZmYgPCBzaXplOyBvdXRPZmYgKz0gbGVuKSB7CiAgICAgICAgICBmb3IgKHZhciBpID0gMCwgayA9IDA7IGkgPD0gaHF1YXJ0ZXJMZW47IGkgKz0gMiwgayArPSBzdGVwKSB7CiAgICAgICAgICAgIHZhciBBID0gb3V0T2ZmICsgaTsKICAgICAgICAgICAgdmFyIEIgPSBBICsgcXVhcnRlckxlbjsKICAgICAgICAgICAgdmFyIEMgPSBCICsgcXVhcnRlckxlbjsKICAgICAgICAgICAgdmFyIEQgPSBDICsgcXVhcnRlckxlbjsKCiAgICAgICAgICAgIC8vIE9yaWdpbmFsIHZhbHVlcwogICAgICAgICAgICB2YXIgQXIgPSBvdXRbQV07CiAgICAgICAgICAgIHZhciBBaSA9IG91dFtBICsgMV07CiAgICAgICAgICAgIHZhciBCciA9IG91dFtCXTsKICAgICAgICAgICAgdmFyIEJpID0gb3V0W0IgKyAxXTsKICAgICAgICAgICAgdmFyIENyID0gb3V0W0NdOwogICAgICAgICAgICB2YXIgQ2kgPSBvdXRbQyArIDFdOwogICAgICAgICAgICB2YXIgRHIgPSBvdXRbRF07CiAgICAgICAgICAgIHZhciBEaSA9IG91dFtEICsgMV07CgogICAgICAgICAgICAvLyBNaWRkbGUgdmFsdWVzCiAgICAgICAgICAgIHZhciBNQXIgPSBBcjsKICAgICAgICAgICAgdmFyIE1BaSA9IEFpOwoKICAgICAgICAgICAgdmFyIHRhYmxlQnIgPSB0YWJsZVtrXTsKICAgICAgICAgICAgdmFyIHRhYmxlQmkgPSBpbnYgKiB0YWJsZVtrICsgMV07CiAgICAgICAgICAgIHZhciBNQnIgPSBCciAqIHRhYmxlQnIgLSBCaSAqIHRhYmxlQmk7CiAgICAgICAgICAgIHZhciBNQmkgPSBCciAqIHRhYmxlQmkgKyBCaSAqIHRhYmxlQnI7CgogICAgICAgICAgICB2YXIgdGFibGVDciA9IHRhYmxlWzIgKiBrXTsKICAgICAgICAgICAgdmFyIHRhYmxlQ2kgPSBpbnYgKiB0YWJsZVsyICogayArIDFdOwogICAgICAgICAgICB2YXIgTUNyID0gQ3IgKiB0YWJsZUNyIC0gQ2kgKiB0YWJsZUNpOwogICAgICAgICAgICB2YXIgTUNpID0gQ3IgKiB0YWJsZUNpICsgQ2kgKiB0YWJsZUNyOwoKICAgICAgICAgICAgdmFyIHRhYmxlRHIgPSB0YWJsZVszICoga107CiAgICAgICAgICAgIHZhciB0YWJsZURpID0gaW52ICogdGFibGVbMyAqIGsgKyAxXTsKICAgICAgICAgICAgdmFyIE1EciA9IERyICogdGFibGVEciAtIERpICogdGFibGVEaTsKICAgICAgICAgICAgdmFyIE1EaSA9IERyICogdGFibGVEaSArIERpICogdGFibGVEcjsKCiAgICAgICAgICAgIC8vIFByZS1GaW5hbCB2YWx1ZXMKICAgICAgICAgICAgdmFyIFQwciA9IE1BciArIE1DcjsKICAgICAgICAgICAgdmFyIFQwaSA9IE1BaSArIE1DaTsKICAgICAgICAgICAgdmFyIFQxciA9IE1BciAtIE1DcjsKICAgICAgICAgICAgdmFyIFQxaSA9IE1BaSAtIE1DaTsKICAgICAgICAgICAgdmFyIFQyciA9IE1CciArIE1EcjsKICAgICAgICAgICAgdmFyIFQyaSA9IE1CaSArIE1EaTsKICAgICAgICAgICAgdmFyIFQzciA9IGludiAqIChNQnIgLSBNRHIpOwogICAgICAgICAgICB2YXIgVDNpID0gaW52ICogKE1CaSAtIE1EaSk7CgogICAgICAgICAgICAvLyBGaW5hbCB2YWx1ZXMKICAgICAgICAgICAgdmFyIEZBciA9IFQwciArIFQycjsKICAgICAgICAgICAgdmFyIEZBaSA9IFQwaSArIFQyaTsKCiAgICAgICAgICAgIHZhciBGQnIgPSBUMXIgKyBUM2k7CiAgICAgICAgICAgIHZhciBGQmkgPSBUMWkgLSBUM3I7CgogICAgICAgICAgICBvdXRbQV0gPSBGQXI7CiAgICAgICAgICAgIG91dFtBICsgMV0gPSBGQWk7CiAgICAgICAgICAgIG91dFtCXSA9IEZCcjsKICAgICAgICAgICAgb3V0W0IgKyAxXSA9IEZCaTsKCiAgICAgICAgICAgIC8vIE91dHB1dCBmaW5hbCBtaWRkbGUgcG9pbnQKICAgICAgICAgICAgaWYgKGkgPT09IDApIHsKICAgICAgICAgICAgICB2YXIgRkNyID0gVDByIC0gVDJyOwogICAgICAgICAgICAgIHZhciBGQ2kgPSBUMGkgLSBUMmk7CiAgICAgICAgICAgICAgb3V0W0NdID0gRkNyOwogICAgICAgICAgICAgIG91dFtDICsgMV0gPSBGQ2k7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIC8vIERvIG5vdCBvdmVyd3JpdGUgb3Vyc2VsdmVzCiAgICAgICAgICAgIGlmIChpID09PSBocXVhcnRlckxlbikKICAgICAgICAgICAgICBjb250aW51ZTsKCiAgICAgICAgICAgIC8vIEluIHRoZSBmbGlwcGVkIGNhc2U6CiAgICAgICAgICAgIC8vIE1BaSA9IC1NQWkKICAgICAgICAgICAgLy8gTUJyPS1NQmksIE1CaT0tTUJyCiAgICAgICAgICAgIC8vIE1Dcj0tTUNyCiAgICAgICAgICAgIC8vIE1Ecj1NRGksIE1EaT1NRHIKICAgICAgICAgICAgdmFyIFNUMHIgPSBUMXI7CiAgICAgICAgICAgIHZhciBTVDBpID0gLVQxaTsKICAgICAgICAgICAgdmFyIFNUMXIgPSBUMHI7CiAgICAgICAgICAgIHZhciBTVDFpID0gLVQwaTsKICAgICAgICAgICAgdmFyIFNUMnIgPSAtaW52ICogVDNpOwogICAgICAgICAgICB2YXIgU1QyaSA9IC1pbnYgKiBUM3I7CiAgICAgICAgICAgIHZhciBTVDNyID0gLWludiAqIFQyaTsKICAgICAgICAgICAgdmFyIFNUM2kgPSAtaW52ICogVDJyOwoKICAgICAgICAgICAgdmFyIFNGQXIgPSBTVDByICsgU1QycjsKICAgICAgICAgICAgdmFyIFNGQWkgPSBTVDBpICsgU1QyaTsKCiAgICAgICAgICAgIHZhciBTRkJyID0gU1QxciArIFNUM2k7CiAgICAgICAgICAgIHZhciBTRkJpID0gU1QxaSAtIFNUM3I7CgogICAgICAgICAgICB2YXIgU0EgPSBvdXRPZmYgKyBxdWFydGVyTGVuIC0gaTsKICAgICAgICAgICAgdmFyIFNCID0gb3V0T2ZmICsgaGFsZkxlbiAtIGk7CgogICAgICAgICAgICBvdXRbU0FdID0gU0ZBcjsKICAgICAgICAgICAgb3V0W1NBICsgMV0gPSBTRkFpOwogICAgICAgICAgICBvdXRbU0JdID0gU0ZCcjsKICAgICAgICAgICAgb3V0W1NCICsgMV0gPSBTRkJpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfTsKCiAgICAvLyByYWRpeC0yIGltcGxlbWVudGF0aW9uCiAgICAvLwogICAgLy8gTk9URTogT25seSBjYWxsZWQgZm9yIGxlbj00CiAgICBGRlQucHJvdG90eXBlLl9zaW5nbGVSZWFsVHJhbnNmb3JtMiA9IGZ1bmN0aW9uIF9zaW5nbGVSZWFsVHJhbnNmb3JtMihvdXRPZmYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZmYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGVwKSB7CiAgICAgIGNvbnN0IG91dCA9IHRoaXMuX291dDsKICAgICAgY29uc3QgZGF0YSA9IHRoaXMuX2RhdGE7CgogICAgICBjb25zdCBldmVuUiA9IGRhdGFbb2ZmXTsKICAgICAgY29uc3Qgb2RkUiA9IGRhdGFbb2ZmICsgc3RlcF07CgogICAgICBjb25zdCBsZWZ0UiA9IGV2ZW5SICsgb2RkUjsKICAgICAgY29uc3QgcmlnaHRSID0gZXZlblIgLSBvZGRSOwoKICAgICAgb3V0W291dE9mZl0gPSBsZWZ0UjsKICAgICAgb3V0W291dE9mZiArIDFdID0gMDsKICAgICAgb3V0W291dE9mZiArIDJdID0gcmlnaHRSOwogICAgICBvdXRbb3V0T2ZmICsgM10gPSAwOwogICAgfTsKCiAgICAvLyByYWRpeC00CiAgICAvLwogICAgLy8gTk9URTogT25seSBjYWxsZWQgZm9yIGxlbj04CiAgICBGRlQucHJvdG90eXBlLl9zaW5nbGVSZWFsVHJhbnNmb3JtNCA9IGZ1bmN0aW9uIF9zaW5nbGVSZWFsVHJhbnNmb3JtNChvdXRPZmYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZmYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGVwKSB7CiAgICAgIGNvbnN0IG91dCA9IHRoaXMuX291dDsKICAgICAgY29uc3QgZGF0YSA9IHRoaXMuX2RhdGE7CiAgICAgIGNvbnN0IGludiA9IHRoaXMuX2ludiA/IC0xIDogMTsKICAgICAgY29uc3Qgc3RlcDIgPSBzdGVwICogMjsKICAgICAgY29uc3Qgc3RlcDMgPSBzdGVwICogMzsKCiAgICAgIC8vIE9yaWdpbmFsIHZhbHVlcwogICAgICBjb25zdCBBciA9IGRhdGFbb2ZmXTsKICAgICAgY29uc3QgQnIgPSBkYXRhW29mZiArIHN0ZXBdOwogICAgICBjb25zdCBDciA9IGRhdGFbb2ZmICsgc3RlcDJdOwogICAgICBjb25zdCBEciA9IGRhdGFbb2ZmICsgc3RlcDNdOwoKICAgICAgLy8gUHJlLUZpbmFsIHZhbHVlcwogICAgICBjb25zdCBUMHIgPSBBciArIENyOwogICAgICBjb25zdCBUMXIgPSBBciAtIENyOwogICAgICBjb25zdCBUMnIgPSBCciArIERyOwogICAgICBjb25zdCBUM3IgPSBpbnYgKiAoQnIgLSBEcik7CgogICAgICAvLyBGaW5hbCB2YWx1ZXMKICAgICAgY29uc3QgRkFyID0gVDByICsgVDJyOwoKICAgICAgY29uc3QgRkJyID0gVDFyOwogICAgICBjb25zdCBGQmkgPSAtVDNyOwoKICAgICAgY29uc3QgRkNyID0gVDByIC0gVDJyOwoKICAgICAgY29uc3QgRkRyID0gVDFyOwogICAgICBjb25zdCBGRGkgPSBUM3I7CgogICAgICBvdXRbb3V0T2ZmXSA9IEZBcjsKICAgICAgb3V0W291dE9mZiArIDFdID0gMDsKICAgICAgb3V0W291dE9mZiArIDJdID0gRkJyOwogICAgICBvdXRbb3V0T2ZmICsgM10gPSBGQmk7CiAgICAgIG91dFtvdXRPZmYgKyA0XSA9IEZDcjsKICAgICAgb3V0W291dE9mZiArIDVdID0gMDsKICAgICAgb3V0W291dE9mZiArIDZdID0gRkRyOwogICAgICBvdXRbb3V0T2ZmICsgN10gPSBGRGk7CiAgICB9OwoKICAgIHZhciBGRlQkMSA9IC8qQF9fUFVSRV9fKi9nZXREZWZhdWx0RXhwb3J0RnJvbUNqcyhmZnQpOwoKICAgIGNvbnN0IEJVRkZFUkVEX0JMT0NLX1NJWkUgPSAyMDQ4OwogICAgZnVuY3Rpb24gZ2VuSGFubldpbmRvdyhsZW5ndGgpIHsKICAgICAgICBsZXQgd2luID0gbmV3IEZsb2F0MzJBcnJheShsZW5ndGgpOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgd2luW2ldID0gMC41ICogKDEgLSBNYXRoLmNvcygoMiAqIE1hdGguUEkgKiBpKSAvIGxlbmd0aCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gd2luOwogICAgfQogICAgY2xhc3MgUGhhc2VWb2NvZGVyUHJvY2Vzc29yIGV4dGVuZHMgT0xBUHJvY2Vzc29yIHsKICAgICAgICBmZnRTaXplOwogICAgICAgIHRpbWVDdXJzb3I7CiAgICAgICAgaGFubldpbmRvdzsKICAgICAgICBmZnQ7CiAgICAgICAgZnJlcUNvbXBsZXhCdWZmZXI7CiAgICAgICAgZnJlcUNvbXBsZXhCdWZmZXJTaGlmdGVkOwogICAgICAgIHRpbWVDb21wbGV4QnVmZmVyOwogICAgICAgIG1hZ25pdHVkZXM7CiAgICAgICAgcGVha0luZGV4ZXM7CiAgICAgICAgbmJQZWFrczsKICAgICAgICBzdGF0aWMgZ2V0IHBhcmFtZXRlckRlc2NyaXB0b3JzKCkgewogICAgICAgICAgICByZXR1cm4gWwogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIG5hbWU6ICJwaXRjaEZhY3RvciIsCiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdFZhbHVlOiAxLjAsCiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICBdOwogICAgICAgIH0KICAgICAgICBjb25zdHJ1Y3RvcihvcHRpb25zKSB7CiAgICAgICAgICAgIG9wdGlvbnMucHJvY2Vzc29yT3B0aW9ucyA9IHsKICAgICAgICAgICAgICAgIGJsb2NrU2l6ZTogQlVGRkVSRURfQkxPQ0tfU0laRSwKICAgICAgICAgICAgfTsKICAgICAgICAgICAgc3VwZXIob3B0aW9ucyk7CiAgICAgICAgICAgIHRoaXMuZmZ0U2l6ZSA9IHRoaXMuYmxvY2tTaXplOwogICAgICAgICAgICB0aGlzLnRpbWVDdXJzb3IgPSAwOwogICAgICAgICAgICB0aGlzLmhhbm5XaW5kb3cgPSBnZW5IYW5uV2luZG93KHRoaXMuYmxvY2tTaXplKTsKICAgICAgICAgICAgLy8gcHJlcGFyZSBGRlQgYW5kIHByZS1hbGxvY2F0ZSBidWZmZXJzCiAgICAgICAgICAgIHRoaXMuZmZ0ID0gbmV3IEZGVCQxKHRoaXMuZmZ0U2l6ZSk7CiAgICAgICAgICAgIHRoaXMuZnJlcUNvbXBsZXhCdWZmZXIgPSB0aGlzLmZmdC5jcmVhdGVDb21wbGV4QXJyYXkoKTsKICAgICAgICAgICAgdGhpcy5mcmVxQ29tcGxleEJ1ZmZlclNoaWZ0ZWQgPQogICAgICAgICAgICAgICAgdGhpcy5mZnQuY3JlYXRlQ29tcGxleEFycmF5KCk7CiAgICAgICAgICAgIHRoaXMudGltZUNvbXBsZXhCdWZmZXIgPSB0aGlzLmZmdC5jcmVhdGVDb21wbGV4QXJyYXkoKTsKICAgICAgICAgICAgdGhpcy5tYWduaXR1ZGVzID0gbmV3IEZsb2F0MzJBcnJheSh0aGlzLmZmdFNpemUgLyAyICsgMSk7CiAgICAgICAgICAgIHRoaXMucGVha0luZGV4ZXMgPSBuZXcgSW50MzJBcnJheSh0aGlzLm1hZ25pdHVkZXMubGVuZ3RoKTsKICAgICAgICAgICAgdGhpcy5uYlBlYWtzID0gMDsKICAgICAgICB9CiAgICAgICAgcHJvY2Vzc09MQShpbnB1dHMsIG91dHB1dHMsIHBhcmFtZXRlcnMpIHsKICAgICAgICAgICAgY29uc3QgcGl0Y2hGYWN0b3IgPSBwYXJhbWV0ZXJzLnBpdGNoRmFjdG9yW3BhcmFtZXRlcnMucGl0Y2hGYWN0b3IubGVuZ3RoIC0gMV07CiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5uYklucHV0czsgaSsrKSB7CiAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IGlucHV0c1tpXS5sZW5ndGg7IGorKykgewogICAgICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGlucHV0c1tpXVtqXTsKICAgICAgICAgICAgICAgICAgICB2YXIgb3V0cHV0ID0gb3V0cHV0c1tpXVtqXTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmFwcGx5SGFubldpbmRvdyhpbnB1dCk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5mZnQucmVhbFRyYW5zZm9ybSh0aGlzLmZyZXFDb21wbGV4QnVmZmVyLCBpbnB1dCk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb21wdXRlTWFnbml0dWRlcygpOwogICAgICAgICAgICAgICAgICAgIHRoaXMuZmluZFBlYWtzKCk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5zaGlmdFBlYWtzKHBpdGNoRmFjdG9yKTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmZmdC5jb21wbGV0ZVNwZWN0cnVtKHRoaXMuZnJlcUNvbXBsZXhCdWZmZXJTaGlmdGVkKTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmZmdC5pbnZlcnNlVHJhbnNmb3JtKHRoaXMudGltZUNvbXBsZXhCdWZmZXIsIHRoaXMuZnJlcUNvbXBsZXhCdWZmZXJTaGlmdGVkKTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmZmdC5mcm9tQ29tcGxleEFycmF5KHRoaXMudGltZUNvbXBsZXhCdWZmZXIsIG91dHB1dCk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5hcHBseUhhbm5XaW5kb3cob3V0cHV0KTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICB0aGlzLnRpbWVDdXJzb3IgKz0gdGhpcy5ob3BTaXplOwogICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgICAgYXBwbHlIYW5uV2luZG93KGlucHV0KSB7CiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5ibG9ja1NpemU7IGkrKykgewogICAgICAgICAgICAgICAgaW5wdXRbaV0gKj0gdGhpcy5oYW5uV2luZG93W2ldOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGNvbXB1dGVNYWduaXR1ZGVzKCkgewogICAgICAgICAgICBmb3IgKGxldCBpID0gMCwgaiA9IDA7IGkgPCB0aGlzLm1hZ25pdHVkZXMubGVuZ3RoOyBpKyssIGogKz0gMikgewogICAgICAgICAgICAgICAgY29uc3QgcmVhbCA9IHRoaXMuZnJlcUNvbXBsZXhCdWZmZXJbal07CiAgICAgICAgICAgICAgICBjb25zdCBpbWFnID0gdGhpcy5mcmVxQ29tcGxleEJ1ZmZlcltqICsgMV07CiAgICAgICAgICAgICAgICB0aGlzLm1hZ25pdHVkZXNbaV0gPSByZWFsICoqIDIgKyBpbWFnICoqIDI7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgZmluZFBlYWtzKCkgewogICAgICAgICAgICB0aGlzLm5iUGVha3MgPSAwOwogICAgICAgICAgICBmb3IgKGxldCBpID0gMiwgZW5kID0gdGhpcy5tYWduaXR1ZGVzLmxlbmd0aCAtIDI7IGkgPCBlbmQ7IGkrKykgewogICAgICAgICAgICAgICAgY29uc3QgbWFnID0gdGhpcy5tYWduaXR1ZGVzW2ldOwogICAgICAgICAgICAgICAgaWYgKHRoaXMubWFnbml0dWRlc1tpIC0gMV0gPj0gbWFnIHx8CiAgICAgICAgICAgICAgICAgICAgdGhpcy5tYWduaXR1ZGVzW2kgLSAyXSA+PSBtYWcgfHwKICAgICAgICAgICAgICAgICAgICB0aGlzLm1hZ25pdHVkZXNbaSArIDFdID49IG1hZyB8fAogICAgICAgICAgICAgICAgICAgIHRoaXMubWFnbml0dWRlc1tpICsgMl0gPj0gbWFnKSB7CiAgICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB0aGlzLnBlYWtJbmRleGVzW3RoaXMubmJQZWFrcysrXSA9IGk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgc2hpZnRQZWFrcyhwaXRjaEZhY3RvcikgewogICAgICAgICAgICB0aGlzLmZyZXFDb21wbGV4QnVmZmVyU2hpZnRlZC5maWxsKDApOwogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMubmJQZWFrczsgaSsrKSB7CiAgICAgICAgICAgICAgICBjb25zdCBwZWFrSW5kZXggPSB0aGlzLnBlYWtJbmRleGVzW2ldOwogICAgICAgICAgICAgICAgY29uc3QgcGVha0luZGV4U2hpZnRlZCA9IE1hdGgucm91bmQocGVha0luZGV4ICogcGl0Y2hGYWN0b3IpOwogICAgICAgICAgICAgICAgaWYgKHBlYWtJbmRleFNoaWZ0ZWQgPiB0aGlzLm1hZ25pdHVkZXMubGVuZ3RoKSB7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBsZXQgc3RhcnRJbmRleCA9IGkgPiAwCiAgICAgICAgICAgICAgICAgICAgPyBwZWFrSW5kZXggLSBNYXRoLmZsb29yKChwZWFrSW5kZXggLSB0aGlzLnBlYWtJbmRleGVzW2kgLSAxXSkgLyAyKQogICAgICAgICAgICAgICAgICAgIDogMDsKICAgICAgICAgICAgICAgIGxldCBlbmRJbmRleCA9IGkgPCB0aGlzLm5iUGVha3MgLSAxCiAgICAgICAgICAgICAgICAgICAgPyBwZWFrSW5kZXggKyBNYXRoLmNlaWwoKHRoaXMucGVha0luZGV4ZXNbaSArIDFdIC0gcGVha0luZGV4KSAvIDIpCiAgICAgICAgICAgICAgICAgICAgOiB0aGlzLmZmdFNpemU7CiAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gc3RhcnRJbmRleCAtIHBlYWtJbmRleDsgaiA8IGVuZEluZGV4IC0gcGVha0luZGV4OyBqKyspIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBiaW5JbmRleCA9IHBlYWtJbmRleCArIGo7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgYmluSW5kZXhTaGlmdGVkID0gcGVha0luZGV4U2hpZnRlZCArIGo7CiAgICAgICAgICAgICAgICAgICAgaWYgKGJpbkluZGV4U2hpZnRlZCA+PSB0aGlzLm1hZ25pdHVkZXMubGVuZ3RoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjb25zdCBvbWVnYURlbHRhID0gKDIgKiBNYXRoLlBJICogKGJpbkluZGV4U2hpZnRlZCAtIGJpbkluZGV4KSkgLyB0aGlzLmZmdFNpemU7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGhhc2VTaGlmdFJlYWwgPSBNYXRoLmNvcyhvbWVnYURlbHRhICogdGhpcy50aW1lQ3Vyc29yKTsKICAgICAgICAgICAgICAgICAgICBjb25zdCBwaGFzZVNoaWZ0SW1hZyA9IE1hdGguc2luKG9tZWdhRGVsdGEgKiB0aGlzLnRpbWVDdXJzb3IpOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IGluZGV4UmVhbCA9IGJpbkluZGV4ICogMjsKICAgICAgICAgICAgICAgICAgICBjb25zdCBpbmRleEltYWcgPSBpbmRleFJlYWwgKyAxOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlUmVhbCA9IHRoaXMuZnJlcUNvbXBsZXhCdWZmZXJbaW5kZXhSZWFsXTsKICAgICAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZUltYWcgPSB0aGlzLmZyZXFDb21wbGV4QnVmZmVyW2luZGV4SW1hZ107CiAgICAgICAgICAgICAgICAgICAgY29uc3QgdmFsdWVTaGlmdGVkUmVhbCA9IHZhbHVlUmVhbCAqIHBoYXNlU2hpZnRSZWFsIC0gdmFsdWVJbWFnICogcGhhc2VTaGlmdEltYWc7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgdmFsdWVTaGlmdGVkSW1hZyA9IHZhbHVlUmVhbCAqIHBoYXNlU2hpZnRJbWFnICsgdmFsdWVJbWFnICogcGhhc2VTaGlmdFJlYWw7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgaW5kZXhTaGlmdGVkUmVhbCA9IGJpbkluZGV4U2hpZnRlZCAqIDI7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgaW5kZXhTaGlmdGVkSW1hZyA9IGluZGV4U2hpZnRlZFJlYWwgKyAxOwogICAgICAgICAgICAgICAgICAgIHRoaXMuZnJlcUNvbXBsZXhCdWZmZXJTaGlmdGVkW2luZGV4U2hpZnRlZFJlYWxdICs9IHZhbHVlU2hpZnRlZFJlYWw7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5mcmVxQ29tcGxleEJ1ZmZlclNoaWZ0ZWRbaW5kZXhTaGlmdGVkSW1hZ10gKz0gdmFsdWVTaGlmdGVkSW1hZzsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KICAgIC8vIEB0cy1pZ25vcmUKICAgIHJlZ2lzdGVyUHJvY2Vzc29yKCJwaGFzZS12b2NvZGVyIiwgUGhhc2VWb2NvZGVyUHJvY2Vzc29yKTsKICAgIGNvbnNvbGUubG9nKCJQaGFzZVZvY29kZXJQcm9jZXNzb3IgcmVnaXN0ZXJlZCIpOwoKICAgIGV4cG9ydHMuUGhhc2VWb2NvZGVyUHJvY2Vzc29yID0gUGhhc2VWb2NvZGVyUHJvY2Vzc29yOwoKICAgIHJldHVybiBleHBvcnRzOwoKfSkoe30pOwovLyMgc291cmNlTWFwcGluZ1VSTD1waGFzZS12b2NvZGVyLWJ1bmRsZS5qcy5tYXAK";class w{maxSize;cache;constructor(e){this.maxSize=e,this.cache=new Map}get(e){if(!this.cache.has(e))return;const g=this.cache.get(e);return this.cache.delete(e),this.cache.set(e,g),g}set(e,g){if(this.cache.has(e))this.cache.delete(e);else if(this.cache.size>=this.maxSize){const t=this.cache.keys().next().value;t!==void 0&&this.cache.delete(t)}this.cache.set(e,g)}has(e){return this.cache.has(e)}}const R=100;function Y(a){if(!a)return null;const e=a.match(/max-age\s*=\s*"?(\d+)"?/i);return e?parseInt(e[1],10):null}function D(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 w(R);static cacheExpirationTime=1440*60*1e3;static setCacheExpirationTime(e){this.cacheExpirationTime=e}static async openCache(){try{return await caches.open("audio-cache")}catch(e){throw console.error("Failed to open cache:",e),e}}static callAllCallbacks(e,g,t){const I=this.pendingCallbacks.get(e);I&&I.forEach(C=>{const i=C[g];if(i)try{i(t)}catch(o){console.error(`Error in ${g} callback:`,o)}})}static async getOrCreatePendingRequest(e,g,t,I){if(t?.aborted)throw new DOMException("Operation was aborted","AbortError");if(I){const i=this.pendingCallbacks.get(e)||[];i.push(I),this.pendingCallbacks.set(e,i)}let C=this.pendingRequests.get(e);if(!C){const i=(async()=>{try{const o=await g();if(o===void 0)throw new Error("Failed to create audio buffer.");return o}finally{this.pendingRequests.delete(e),this.pendingCallbacks.delete(e)}})();return t?.addEventListener("abort",()=>{t.aborted&&(this.pendingRequests.delete(e),this.pendingCallbacks.delete(e))},{once:!0}),this.pendingRequests.set(e,i),i}return C}static async updateMetadata(e,g,t){const I={url:g,timestamp:Date.now(),...t};await e.put(`${g}:meta`,new Response(JSON.stringify(I),{headers:{"Content-Type":"application/json"}}))}static async getBufferFromCache(e,g){try{const t=await g.match(e);return t&&t.ok?await t.arrayBuffer():null}catch(t){return console.error("Failed to get data from cache:",t),null}}static async fetchAndCacheBuffer(e,g,t,I,C,i){const o=new Headers;t&&o.append("If-None-Match",t),I&&o.append("If-Modified-Since",I),console.debug(`[AudioCache] Fetching ${e}`,{headers:Object.fromEntries(o.entries()),hasEtag:!!t,hasLastModified:!!I});const s=await fetch(e,{headers:o,signal:C});if(console.debug(`[AudioCache] Response ${e}`,{status:s.status,statusText:s.statusText,etag:s.headers?.get("ETag"),lastModified:s.headers?.get("Last-Modified"),cacheControl:s.headers?.get("Cache-Control")}),s.status===304){const A=await g.match(e);if(A){i?.onCacheHit&&i.onCacheHit({url:e,cacheType:"browser",timestamp:Date.now()});const n=Date.now(),c=s.headers?.get("Cache-Control");return await this.updateMetadata(g,e,{timestamp:n,etag:t,lastModified:I,...c?{cacheControl:c}:{}}),await A.arrayBuffer()}else{console.warn(`Cache inconsistency detected for ${e}: 304 response but no cached body. Re-fetching.`);const n=await fetch(e,{signal:C});if(n.status===200){const c=n.clone(),h=n.headers.get("ETag"),d=n.headers.get("Last-Modified"),m=n.headers.get("Cache-Control");try{await Promise.all([g.put(e,c),this.updateMetadata(g,e,{timestamp:Date.now(),etag:h||void 0,lastModified:d||void 0,cacheControl:m||void 0})])}catch(b){throw await g.delete(e),await g.delete(`${e}:meta`),b}if(n.body){const{stream:b,total:f}=this.createProgressTrackingStream(n,e);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(s.status===200){const A=s.clone(),n=s.headers.get("ETag"),c=s.headers.get("Last-Modified"),h=s.headers.get("Cache-Control");try{await Promise.all([g.put(e,A),this.updateMetadata(g,e,{timestamp:Date.now(),etag:n||void 0,lastModified:c||void 0,cacheControl:h||void 0})])}catch(d){throw await g.delete(e),await g.delete(`${e}:meta`),d}}if(C?.aborted)throw new DOMException("Operation was aborted","AbortError");if(s.body){const{stream:A,total:n}=this.createProgressTrackingStream(s,e);return await this.collectStreamToArrayBuffer(A,n||void 0)}else return await s.arrayBuffer()}static createProgressTrackingStream(e,g){const t=e.headers.get("content-length"),I=t?parseInt(t,10):null;let C=0;if(!e.body)throw new Error("Response body is null");const i=e.body.getReader();return{stream:new ReadableStream({start(s){function A(){return i.read().then(({done:n,value:c})=>{if(n){r.callAllCallbacks(g,"onLoadingProgress",{url:g,loaded:C,total:I,progress:I?1:-1,timestamp:Date.now()}),s.close();return}if(c){C+=c.byteLength;const h=I?C/I:-1;r.callAllCallbacks(g,"onLoadingProgress",{url:g,loaded:C,total:I,progress:h,timestamp:Date.now()}),s.enqueue(c)}return A()}).catch(n=>{s.error(n)})}return A()},cancel(s){return i.cancel(s)}}),total:I}}static async collectStreamToArrayBuffer(e,g){const t=e.getReader();try{if(g!==void 0&&g>0){const I=new ArrayBuffer(g),C=new Uint8Array(I);let i=0;for(;;){const{done:o,value:s}=await t.read();if(o)break;s&&(C.set(s,i),i+=s.byteLength)}return I}else{let I=new Uint8Array(8192),C=0;for(;;){const{done:i,value:o}=await t.read();if(i)break;if(o){if(C+o.byteLength>I.length){const s=Math.max(I.length*2,C+o.byteLength),A=new Uint8Array(s);A.set(I.subarray(0,C)),I=A}I.set(o,C),C+=o.byteLength}}return I.slice(0,C).buffer}}finally{t.releaseLock()}}static async decodeAudioData(e,g){try{return await e.decodeAudioData(g)}catch(t){throw console.error("Failed to decode audio data:",t),t}}static async getMetadataFromCache(e,g){try{const t=await g.match(e+":meta");return t&&t.ok?await t.json():null}catch(t){return console.error("Failed to get metadata from cache:",t),null}}async getAudioBuffer(e,g,t,I){if(I?.onLoadingStart&&I.onLoadingStart({url:g,timestamp:Date.now()}),r.decodedBuffers.has(g))return I?.onCacheHit&&I.onCacheHit({url:g,cacheType:"memory",timestamp:Date.now()}),r.decodedBuffers.get(g);if(g.startsWith("data:")){const s=g.split(",")[1],A=Uint8Array.from(atob(s),c=>c.charCodeAt(0)).buffer,n=await r.decodeAudioData(e,A);return r.decodedBuffers.set(g,n),n}const C=await r.openCache(),i=await r.getMetadataFromCache(g,C),o=(()=>{if(!i||D(i.cacheControl))return!0;const s=Y(i.cacheControl);if(s!==null){const A=(Date.now()-i.timestamp)/1e3;if(s>0&&A<s)return!1}return i.etag||i.lastModified?!0:Date.now()-i.timestamp>r.cacheExpirationTime})();return r.getOrCreatePendingRequest(g,async()=>{if(o){I?.onCacheMiss&&I.onCacheMiss({url:g,reason:i?"expired":"not-found",timestamp:Date.now()});try{const s=await r.fetchAndCacheBuffer(g,C,i?.etag,i?.lastModified,t,{onCacheHit:I?.onCacheHit});I?.onLoadingComplete&&I.onLoadingComplete({url:g,duration:0,size:s.byteLength,timestamp:Date.now()});const A=await r.decodeAudioData(e,s);return r.decodedBuffers.set(g,A),A}catch(s){throw I?.onCacheError&&I.onCacheError({url:g,error:s,operation:"get",timestamp:Date.now()}),s}}else{const s=await r.getBufferFromCache(g,C);if(s){I?.onCacheHit&&I.onCacheHit({url:g,cacheType:"browser",timestamp:Date.now()});const A=await r.decodeAudioData(e,s);return r.decodedBuffers.set(g,A),A}else{I?.onCacheError&&I.onCacheError({url:g,error:new Error("Cache inconsistency: metadata exists but body is missing"),operation:"get",timestamp:Date.now()});const A=await r.fetchAndCacheBuffer(g,C,i?.etag,i?.lastModified,t,{onCacheHit:I?.onCacheHit}),n=await r.decodeAudioData(e,A);return r.decodedBuffers.set(g,n),n}}},t,{onLoadingProgress:I?.onLoadingProgress})}clearMemoryCache(){r.decodedBuffers=new w(R),r.pendingRequests.clear()}}class y{listeners={};on(e,g){return this.listeners[e]=this.listeners[e]??[],this.listeners[e].push({fn:g,once:!1}),()=>this.off(e,g)}once(e,g){return this.listeners[e]=this.listeners[e]??[],this.listeners[e].push({fn:g,once:!0}),()=>this.off(e,g)}off(e,g){const t=this.listeners[e];t&&(this.listeners[e]=t.filter(I=>I.fn!==g))}emit(e,g){const t=this.listeners[e];t&&(t.forEach(I=>I.fn(g)),this.listeners[e]=t.filter(I=>!I.once))}emitAsync(e,g){const t=this.listeners[e];if(t){const I=t.map(C=>Promise.resolve().then(()=>C.fn(g)).catch(i=>console.error(`Error in listener for event ${e}:`,i)));return this.listeners[e]=t.filter(C=>!C.once),Promise.all(I).then(()=>{})}return Promise.resolve()}removeAllListeners(){this.listeners={}}}class X{constructor(e=[]){this.sounds=e}_position=[0,0,0];loopCount=0;playIndex=0;preplayRandom(){if(this.sounds.length===0)return;const g=this.randomSound().preplay();return g.length>0?g[0]:void 0}playRandom(){const e=this.preplayRandom();return e&&e.play(),e}preplayOrdered(e=!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,!e&&this.playIndex===0&&(this.playIndex=this.sounds.length),t[0]}playOrdered(e=!0){const g=this.preplayOrdered(e);return g&&g.play(),g}get duration(){return this.sounds.map(e=>e.duration).reduce((e,g)=>Math.max(e,g),0)}seek(e){this.sounds.forEach(g=>g.seek&&g.seek(e))}addSound(e){this.sounds.push(e)}randomSound(){if(this.sounds.length===0)throw new Error("Cannot get a random sound from an empty group");const e=Math.floor(Math.random()*this.sounds.length);return this.sounds[e]}preplay(){return this.sounds.map(g=>g.preplay()).flat()}play(){const e=[];return this.preplay().forEach(g=>{g.play(),e.push(g)}),e}get isPlaying(){return this.sounds.some(e=>e.isPlaying)}stop(){this.sounds.forEach(e=>e.stop())}pause(){this.sounds.forEach(e=>e.pause())}fadeTo(e,g,t){return Promise.all(this.sounds.map(I=>I.fadeTo(e,g,t))).then(()=>{})}fadeIn(e,g){return Promise.all(this.sounds.map(t=>t.fadeIn(e,g))).then(()=>{})}fadeOut(e,g){return Promise.all(this.sounds.map(t=>t.fadeOut(e,g))).then(()=>{})}stopWithFade(e,g){return Promise.all(this.sounds.map(t=>t.stopWithFade(e,g))).then(()=>{})}loop(e){return e===void 0?this.loopCount:(this.loopCount=e,this.sounds.forEach(g=>g.loop(e)),this.loopCount)}addFilter(e){this.sounds.forEach(g=>g.addFilter(e))}removeFilter(e){this.sounds.forEach(g=>g.removeFilter(e))}set position(e){this._position=e,this.sounds.forEach(g=>g.position=this._position)}get position(){return this._position}get volume(){return this.sounds.map(e=>e.volume).reduce((e,g)=>e+g,0)/this.sounds.length}set volume(e){this.sounds.forEach(g=>g.volume=e)}get playbackRate(){return this.sounds.length===0?1:this.sounds[0].playbackRate}set playbackRate(e){this.sounds.forEach(g=>g.playbackRate=e)}}class p{_filters=[];addFilter(e){if(this._filters.includes(e))throw new Error("Cannot add the same filter instance twice");this._filters.push(e)}removeFilter(e){const g=this._filters.length;if(this._filters=this._filters.filter(t=>t!==e),this._filters.length===g)throw new Error("Cannot remove filter that was never added to this container")}applyFilters(e){return this._filters.reduce((g,t)=>(g.connect(t),t),e),this._filters.length>0?this._filters[this._filters.length-1]:e}get filters(){return this._filters}addFilters(e){e.forEach(g=>this.addFilter(g))}removeFilters(e){e.forEach(g=>this.removeFilter(g))}cleanup(){this._filters.forEach(e=>e.disconnect()),this._filters=[]}}class S extends p{context;source;gainNode;panner;constructor(e,g,t,I=0){super(),this.source=e,this.gainNode=g,this.context=t,this.panner=t.createPanner(),e.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(e){if(!this.gainNode)throw new Error("Cannot set volume of a sound that has been cleaned up");this.gainNode.gain.value=e}stop(){if(!this.source)throw new Error("Cannot stop a sound that has been cleaned up");this.source.mediaStream.getTracks().forEach(e=>e.stop())}pause(){if(!this.source)throw new Error("Cannot pause a sound that has been cleaned up");this.source.mediaStream.getTracks().forEach(e=>e.enabled=!1)}resume(){if(!this.source)throw new Error("Cannot resume a sound that has been cleaned up");this.source.mediaStream.getTracks().forEach(e=>e.enabled=!0)}addFilter(e){super.addFilter(e),this.refreshFilters()}removeFilter(e){super.removeFilter(e),this.refreshFilters()}set position(e){if(!this.panner)throw new Error("Cannot move a sound that has been cleaned up");const[g,t,I]=e;this.panner.positionX.value=g,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 e=this.source;this.source.disconnect(),e=this.applyFilters(e),e.connect(this.gainNode)}get playbackRate(){return 1}set playbackRate(e){}}class N extends p{context;_position=[0,0,0];loopCount=0;prevVolume=1;microphoneGainNode;streamPlayback;stream;streamSource;constructor(e){super(),this.context=e,this.microphoneGainNode=this.context.createGain()}play(){return this.stream||navigator.mediaDevices.getUserMedia({audio:!0}).then(e=>{this.stream=e,this.streamSource=this.context.createMediaStreamSource(this.stream),this.streamPlayback=new S(this.streamSource,this.microphoneGainNode,this.context),this.streamPlayback.play()}).catch(e=>{console.error("Error initializing microphone stream:",e)}),this.streamPlayback?[this.streamPlayback]:[]}get duration(){return 0}seek(e){}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(e){this.streamPlayback&&this.streamPlayback.addFilter(e)}removeFilter(e){this.streamPlayback&&this.streamPlayback.removeFilter(e)}get volume(){return this.streamPlayback?this.streamPlayback.volume:0}set volume(e){this.streamPlayback&&(this.streamPlayback.volume=e)}get position(){return[0,0,0]}set position(e){}loop(e){return 0}get playbackRate(){return 1}set playbackRate(e){}}function H(a){class e 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(),t.cleanup()}),this.playbacks=[]}pause(){this.playbacks.forEach(t=>t.pause())}addFilter(t){super.addFilter(t)}removeFilter(t){super.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)}fadeTo(t,I,C){return this._volume=t,Promise.all(this.playbacks.map(i=>i.fadeTo(t,I,C))).then(()=>{})}fadeIn(t,I){return Promise.all(this.playbacks.map(C=>C.fadeIn(t,I))).then(()=>{})}fadeOut(t,I){return Promise.all(this.playbacks.map(C=>C.fadeOut(t,I))).then(()=>{})}stopWithFade(t,I){return this.fadeOut(t,I).then(()=>this.stop())}}return e}function K(a){class e 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=v(t,-1,1),this.panner.pan.setValueAtTime(v(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,C,i]=t,o=this.panner;o.positionX.value=I,o.positionY.value=C,o.positionZ.value=i}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 e}function v(a,e,g){return Math.min(Math.max(a,e),g)}function F(a){class e extends a{gainNode;_fadeTimeout;_isFading=!1;setGainNode(t){this.gainNode=t}cleanup(){this.cancelFade(),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.cancelFade(),this.gainNode.gain.value=t}get isFading(){return this._isFading}fadeTo(t,I,C="linear"){if(!this.gainNode)throw new Error("Cannot fade a sound that has been cleaned up");this.cancelFade();const i=this.gainNode.context.currentTime,o=i+I/1e3;return this.gainNode.gain.setValueAtTime(this.gainNode.gain.value,i),C==="exponential"?this.gainNode.gain.exponentialRampToValueAtTime(t===0?1e-4:t,o):this.gainNode.gain.linearRampToValueAtTime(t,o),this._isFading=!0,new Promise(s=>{this._fadeTimeout=setTimeout(()=>{this._isFading=!1,t===0&&C==="exponential"&&this.gainNode&&(this.gainNode.gain.value=0),s()},I)})}cancelFade(){if(this._fadeTimeout&&(clearTimeout(this._fadeTimeout),this._fadeTimeout=void 0),this._isFading&&this.gainNode){const t=this.gainNode.context.currentTime;this.gainNode.gain.cancelScheduledValues(t),this.gainNode.gain.setValueAtTime(this.gainNode.gain.value,t)}this._isFading=!1}fadeIn(t,I){if(!this.gainNode)throw new Error("Cannot fade a sound that has been cleaned up");const C=this.gainNode.gain.value;return this.gainNode.gain.setValueAtTime(1e-4,this.gainNode.context.currentTime),this.fadeTo(C,t,I)}fadeOut(t,I){return this.fadeTo(0,t,I)}}return e}class W extends K(F(p)){source;_playing=!1;origin;eventEmitter=new y;constructor(){super()}get isPlaying(){return this.source?this._playing:!1}on(e,g){this.eventEmitter.on(e,g)}off(e,g){this.eventEmitter.off(e,g)}emit(e,g){this.eventEmitter.emit(e,g)}async emitAsync(e,g){return this.eventEmitter.emitAsync(e,g)}fadeTo(e,g,t="linear"){return this.emit("fadeStart",{target:e,duration:g,type:t}),super.fadeTo(e,g,t).then(()=>{this.emit("fadeEnd",void 0)})}cancelFade(){const e=this._isFading;super.cancelFade(),e&&this.emit("fadeCancel",void 0)}cleanup(){this.eventEmitter.removeAllListeners(),super.cleanup()}}class Z extends W{constructor(e,g,t){super(),this.origin=e,this.context=e.context,this.loopCount=e.loopCount,this.setPanType(e.panType,e.context),this.source=g,"buffer"in g&&g.buffer&&(this.buffer=g.buffer),this.setupSourceNode(g),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;_fadeInConfig;_fadeOutConfig;setupSourceNode(e){if("mediaElement"in e&&e.mediaElement)e.mediaElement.onended=this.loopEnded;else if("onended"in e)e.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(e){if(e<=0)throw new Error("Playback rate must be greater than 0");if(this._state===1){const g=(this.context.currentTime-this._startTime)*this._playbackRate;this._offset+=g,this._startTime=this.context.currentTime}this._playbackRate=e,this.source&&("playbackRate"in this.source&&(this.source.playbackRate.value=e),"mediaElement"in this.source&&this.source.mediaElement&&(this.source.mediaElement.playbackRate=e))}loopEnded=()=>{!this.source||this._state!==1||(this.currentLoop++,this.loopCount!=="infinite"&&this.currentLoop>this.loopCount?this._fadeOutConfig?this.fadeOut(this._fadeOutConfig.duration,this._fadeOutConfig.type).then(()=>this.stop()):this.stop():(this.seek(0),"mediaElement"in this.source&&this.source.mediaElement?this.source.mediaElement.play():this.play(),this._fadeInConfig?.perLoop&&this.gainNode&&(this.gainNode.gain.setValueAtTime(1e-4,this.gainNode.context.currentTime),this.fadeTo(this._fadeInConfig.targetVolume,this._fadeInConfig.duration,this._fadeInConfig.type))))};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.origin.cacophony?.emit("globalPlay",{source:this.origin,timestamp:Date.now()}),[this]}catch(e){throw this.emitAsync("error",{error:e,errorType:"source",timestamp:Date.now(),recoverable:!0}),e}}pause(){if(!this.source||this._state!==1)return;const e=(this.context.currentTime-this._startTime)*this._playbackRate;this._offset+=e,"mediaElement"in this.source&&this.source.mediaElement?this.source.mediaElement.pause():"stop"in this.source&&this.source.stop(),this._state=2,this.emit("pause",void 0),this.origin.cacophony?.emit("globalPause",{source:this.origin,timestamp:Date.now()})}stop(){if(!this.source)throw new Error("Cannot stop a sound that has been cleaned up");this._state===3||this._state===0||(this.cancelFade(),"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),this.origin.cacophony?.emit("globalStop",{source:this.origin,timestamp:Date.now()}))}fadeIn(e,g,t){return t?.perLoop&&(this._fadeInConfig={duration:e,type:g||"linear",perLoop:!0,targetVolume:this.gainNode.gain.value}),super.fadeIn(e,g)}configureFadeOut(e,g){this._fadeOutConfig={duration:e,type:g||"linear"}}stopWithFade(e,g){return this.fadeOut(e,g).then(()=>this.stop())}seek(e){if(!this.source||!this.gainNode||!this.panner)throw new Error("Cannot seek a sound that has been cleaned up");if(!isFinite(e)||e<0)throw new Error("Invalid time value for seek");const g=this._state===1;g&&this.pause(),this._offset=e,"mediaElement"in this.source&&this.source.mediaElement&&(this.source.mediaElement.currentTime=e),g&&this.play()}get currentTime(){if(this._state===1){const e=(this.context.currentTime-this._startTime)*this._playbackRate;return this._offset+e}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(e){throw this.emitAsync("error",{error:e,errorType:"source",timestamp:Date.now(),recoverable:!1}),e}}set sourceLoop(e){if(!this.source)throw new Error("Cannot set loop on a sound that has been cleaned up");"loop"in this.source&&(this.source.loop=e),"mediaElement"in this.source&&this.source.mediaElement&&(this.source.mediaElement.loop=e)}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(e){this.assertNotCleanedUp(),super.addFilter(e),this.refreshFilters()}removeFilter(e){this.assertNotCleanedUp(),super.removeFilter(e),this.refreshFilters()}loop(e){if(!this.source)throw new Error("Cannot loop a sound that has been cleaned up");if(e!==void 0&&(this.loopCount=e==="infinite"?"infinite":Math.max(0,e),this.currentLoop=0),"mediaElement"in this.source&&this.source.mediaElement){const g=this.source.mediaElement;g.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 e=this.panner;e.disconnect(),e=this.applyFilters(e),e.connect(this.gainNode)}get outputNode(){if(!this.gainNode)throw new Error("Cannot access output node of a playback that has been cleaned up");return this.gainNode}connect(e){return this.outputNode.connect(e)}disconnect(e){e?this.outputNode.disconnect(e):this.outputNode.disconnect()}clone(e={}){if(!this.source||!this.gainNode||!this.context)throw new Error("Cannot clone a sound that has been cleaned up");const g=e.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 C=e.loopCount!==void 0?e.loopCount:this.loopCount,i=new Z(this.origin,I,t);return i.loopCount=C,i.currentLoop=this.currentLoop,i.setPanType(g,this.context),i.volume=this.volume,i.playbackRate=this._playbackRate,i._offset=this._offset,i._state=this._state,this._filters.forEach(o=>{const s=this.context.createBiquadFilter();s.type=o.type,s.frequency.value=o.frequency.value,s.Q.value=o.Q.value,s.gain.value=o.gain.value,i.addFilter(s)}),this._state===1&&i.play(),i}}class u extends H(p){constructor(e,g,t,I,C=B.Buffer,i="HRTF",o){super(),this.url=e,this.globalGainNode=I,this.soundType=C,this.panType=i,this._cacophony=o,this.buffer=g,this.context=t}buffer;context;loopCount=0;_playbackRate=1;eventEmitter=new y;get cacophony(){return this._cacophony}get volume(){return super.volume}on(e,g){this.eventEmitter.on(e,g)}off(e,g){this.eventEmitter.off(e,g)}emit(e,g){this.eventEmitter.emit(e,g)}async emitAsync(e,g){return this.eventEmitter.emitAsync(e,g)}clone(e={}){const g=e.panType||this.panType,t=e.stereoPan!==void 0?e.stereoPan:this.stereoPan,I=e.threeDOptions||this.threeDOptions,C=e.loopCount!==void 0?e.loopCount:this.loopCount,i=e.playbackRate||this.playbackRate,o=e.volume!==void 0?e.volume:this.volume,s=e.position!==void 0?e.position:this.position,A=e.filters&&e.filters.length?e.filters:this._filters,n=new u(this.url,this.buffer,this.context,this.globalGainNode,this.soundType,g,this.cacophony);return n.loop(C),n.playbackRate=i,n.volume=o,g==="HRTF"?(n.threeDOptions=I,n.position=s):n.stereoPan=t,n.addFilters(A),n}preplay(){try{let e;if(this.buffer)e=this.context.createBufferSource(),e.buffer=this.buffer;else{const I=new Audio;I.crossOrigin="anonymous",I.src=this.url,I.preload="auto",e=this.context.createMediaElementSource(I)}const g=this.context.createGain();g.connect(this.globalGainNode);const t=new Z(this,e,g);return t.setGainNode(g),t.volume=this.volume,t.playbackRate=this.playbackRate,this._filters.forEach(I=>{const C=this.context.createBiquadFilter();C.type=I.type,C.frequency.value=I.frequency.value,C.Q.value=I.Q.value,C.gain.value=I.gain.value,t.addFilter(C)}),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(e){const g={url:this.url,error:e,errorType:"playback",timestamp:Date.now(),recoverable:!0};throw this.emitAsync("soundError",g),e}}play(e){const g=super.play();if(this.emit("play",g[0]),e)for(const t of g)e.fadeIn!==void 0&&t.fadeIn(e.fadeIn,e.fadeType,{perLoop:e.fadeInPerLoop}),e.fadeOut!==void 0&&t.configureFadeOut(e.fadeOut,e.fadeType);return g}stop(){super.stop(),this.emit("stop",void 0)}pause(){super.pause(),this.emit("pause",void 0)}seek(e){this.playbacks.forEach(g=>g.seek(e))}get duration(){return this.playbacks.length>0?this.playbacks[0].duration:this.buffer?.duration||NaN}loop(e){return e===void 0?this.loopCount:(this.loopCount=e,this.playbacks.forEach(g=>g.loop(e)),this.loopCount)}get playbackRate(){return this._playbackRate}set playbackRate(e){this._playbackRate=e,this.playbacks.forEach(g=>g.playbackRate=e),this.emit("rateChange",e)}set volume(e){super.volume=e,this.emit("volumeChange",e)}cleanup(){this.playbacks.forEach(e=>e.cleanup()),this.playbacks=[],this.eventEmitter.removeAllListeners()}}const P=(a,e)=>{var g=new Uint8Array(a.byteLength+e.byteLength);return g.set(new Uint8Array(a),0),g.set(new Uint8Array(e),a.byteLength),g.buffer};function T(a,e,g){const t=[];let I=0,C;if(g?.aborted){console.error("Stream error:",new DOMException("Operation was aborted","AbortError"));return}fetch(a,g?{signal:g}:void 0).then(function(o){if(!o.ok)throw new Error("HTTP error, status = "+o.status);if(!o.body)throw new Error("Missing body");C=o.body.getReader();let s=new ArrayBuffer(0);const A=()=>{t.length=0,C&&C.cancel("Stream aborted").catch(()=>{})};g?.addEventListener("abort",A);function n(){return g?.aborted?(A(),Promise.resolve()):C.read().then(({value:c,done:h})=>{if(g?.aborted){A();return}let d=null;if(c){if(s.byteLength?d=P(s,c.buffer):(s=c.buffer.slice(0,44),d=c.buffer),e.decodeAudioData(d,function(m){g?.aborted||(t.push(m),t.length&&i())},function(m){console.log("err(decodeAudioData): "+m)}),h){console.log("done"),g?.removeEventListener("abort",A);return}n()}}).catch(c=>{g?.aborted||c.name==="AbortError"||console.error("Stream read error:",c)})}n()}).catch(function(o){console.error("Stream error:",o)});function i(){for(;t.length;){let o=t.shift();const s=e.createBufferSource();if(!o)return;s.buffer=o,s.connect(e.destination),I==0&&(I=e.currentTime+.02),s.start(I),I+=s.buffer.duration}}}function M(a){class e extends W{_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 e}class z extends M(K(F(p))){constructor(e,g,t){super(),this.origin=e,this.source=g,this.context=e.context,this.setPanType(e.panType,e.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 e=this.panner;e.disconnect(),e=this.applyFilters(e),e.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 H(p){constructor(e,g,t=B.Oscillator,I="HRTF",C={},i){super(),this.context=e,this.globalGainNode=g,this.soundType=t,this.panType=I,this.cacophony=i,this.context=e,this._oscillatorOptions=C}_oscillatorOptions;playbacks=[];eventEmitter=new y;on(e,g){this.eventEmitter.on(e,g)}off(e,g){this.eventEmitter.off(e,g)}emit(e,g){this.eventEmitter.emit(e,g)}async emitAsync(e,g){return this.eventEmitter.emitAsync(e,g)}clone(e={}){const g=e.panType||this.panType,t=e.stereoPan!==void 0?e.stereoPan:this.stereoPan??0,I=e.threeDOptions||this.threeDOptions,C=e.volume!==void 0?e.volume:this.volume,i=e.position&&e.position.length?e.position:this.position,o=e.filters&&e.filters.length?e.filters:this._filters,s=e.oscillatorOptions||this._oscillatorOptions,A=new G(this.context,this.globalGainNode,this.soundType,g,s,this.cacophony);return A._volume=C,A._position=i,A._stereoPan=t,A._threeDOptions=I,A.addFilters(o),A}preplay(){const e=this.context.createOscillator();return this.createPlayback(e)}createPlayback(e){this.oscillatorOptions.detune&&(e.detune.value=this.oscillatorOptions.detune),this.oscillatorOptions.frequency&&(e.frequency.value=this.oscillatorOptions.frequency),this.oscillatorOptions.type&&(e.type=this.oscillatorOptions.type);const g=this.context.createGain();g.connect(this.globalGainNode);const t=new z(this,e,g);return t.volume=this.volume,this._filters.forEach(I=>{const C=this.context.createBiquadFilter();C.type=I.type,C.frequency.value=I.frequency.value,C.Q.value=I.Q.value,C.gain.value=I.gain.value,t.addFilter(C)}),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 e=super.play();return this.emit("play",e[0]),this.cacophony?.emit("globalPlay",{source:this,timestamp:Date.now()}),e}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(e){this._oscillatorOptions=e,this.playbacks.forEach(g=>{g.source instanceof OscillatorNode&&(this.oscillatorOptions.detune&&(g.source.detune.value=this.oscillatorOptions.detune),this.oscillatorOptions.frequency&&(g.source.frequency.value=this.oscillatorOptions.frequency),this.oscillatorOptions.type&&(g.source.type=this.oscillatorOptions.type))})}get frequency(){return this.oscillatorOptions.frequency||440}set frequency(e){this._oscillatorOptions.frequency=e,this.playbacks.forEach(g=>g.frequency=e),this.emit("frequencyChange",e)}get detune(){return this.oscillatorOptions.detune}set detune(e){this._oscillatorOptions.detune=e,this.playbacks.forEach(g=>g.detune=e),this.emit("detuneChange",e)}get type(){return this.oscillatorOptions.type||"sine"}set type(e){this._oscillatorOptions.type=e,this.playbacks.forEach(g=>g.type=e),this.emit("typeChange",e)}}var B=(a=>(a.HTML="HTML",a.Streaming="Streaming",a.Buffer="Buffer",a.Oscillator="oscillator",a))(B||{});class Q{context;globalGainNode;listener;prevVolume=1;finalizationRegistry;eventEmitter=new y;cache;constructor(e,g){this.context=e||new V.AudioContext,this.listener=this.context.listener,this.globalGainNode=this.context.createGain(),this.globalGainNode.connect(this.context.destination),this.cache=g||new r,this.finalizationRegistry=new FinalizationRegistry(t=>{t.cleanup()})}on(e,g){this.eventEmitter.on(e,g)}off(e,g){this.eventEmitter.off(e,g)}emit(e,g){this.eventEmitter.emit(e,g)}async emitAsync(e,g){return this.eventEmitter.emitAsync(e,g)}async loadWorklets(e){this.context.audioWorklet?await this.createWorkletNode("phase-vocoder",E,e):console.warn("AudioWorklet not supported")}async createWorkletNode(e,g,t){if(!this.context.audioWorklet)throw new Error("AudioWorklet not supported");try{return new V.AudioWorkletNode(this.context,e)}catch(I){console.error(I),console.log("Loading worklet from url",g);try{await this.context.audioWorklet.addModule(g,{credentials:"same-origin",...t&&{signal:t}})}catch(C){throw console.error(C),C}return new V.AudioWorkletNode(this.context,e)}}clearMemoryCache(){this.cache.clearMemoryCache()}createOscillator(e,g="HRTF"){return new G(this.context,this.globalGainNode,"oscillator",g,e,this)}async createSound(e,g="Buffer",t="HRTF",I){if(typeof e=="object")return Promise.resolve(new u("",e,this.context,this.globalGainNode,"Buffer",t,this));const C=e;if(g==="HTML"){const i=new Audio;return i.src=C,i.crossOrigin="anonymous",Promise.resolve(new u(C,void 0,this.context,this.globalGainNode,"HTML",t,this))}return g==="Streaming"?Promise.resolve(new u(C,void 0,this.context,this.globalGainNode,"Streaming",t,this)):this.cache.getAudioBuffer(this.context,C,I,{onLoadingStart:i=>this.emitAsync("loadingStart",i),onLoadingProgress:i=>this.emitAsync("loadingProgress",i),onLoadingComplete:i=>this.emitAsync("loadingComplete",i),onLoadingError:i=>this.emitAsync("loadingError",i),onCacheHit:i=>this.emitAsync("cacheHit",i),onCacheMiss:i=>this.emitAsync("cacheMiss",i),onCacheError:i=>this.emitAsync("cacheError",i)}).then(i=>new u(C,i,this.context,this.globalGainNode,g,t,this))}async createGroup(e){const g=new X;return e.forEach(t=>g.addSound(t)),g}async createGroupFromUrls(e,g="Buffer",t="HRTF",I){const C=new X;return(await Promise.all(e.map(o=>this.createSound(o,g,t,I)))).forEach(o=>C.addSound(o)),C}async createStream(e,g){return T(e,this.context,g),new u(e,void 0,this.context,this.globalGainNode,"Streaming","HRTF",this)}createBiquadFilter=({type:e,frequency:g,gain:t,Q:I})=>{g===void 0&&(g=350);const C=this.context.createBiquadFilter();return C.type=e||"lowpass",C.frequency.value=g,C.gain.value=t||0,C.Q.value=I||1,C};createPanner({coneInnerAngle:e,coneOuterAngle:g,coneOuterGain:t,distanceModel:I,maxDistance:C,channelCount:i,channelCountMode:o,channelInterpretation:s,panningModel:A,refDistance:n,rolloffFactor:c,positionX:h,positionY:d,positionZ:m,orientationX:b,orientationY:f,orientationZ:k}){const l=this.context.createPanner();return l.coneInnerAngle=e||360,l.coneOuterAngle=g||360,l.coneOuterGain=t||0,l.distanceModel=I||"inverse",l.maxDistance=C||1e4,l.channelCount=i||2,l.channelCountMode=o||"clamped-max",l.channelInterpretation=s||"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=m||0,l.orientationX.value=b||0,l.orientationY.value=f||0,l.orientationZ.value=k||0,l}pause(){"suspend"in this.context&&this.context.suspend()}resume(){"resume"in this.context&&this.context.resume()}setGlobalVolume(e){this.globalGainNode.gain.value=e}get volume(){return this.globalGainNode.gain.value}set volume(e){if(this.muted){this.prevVolume=e;return}this.setGlobalVolume(e)}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(e){e!==this.muted&&(e?this.mute():this.unmute())}getMicrophoneStream(){return new Promise((e,g)=>{navigator.mediaDevices.getUserMedia({audio:!0}).then(t=>{const I=new N(this.context);I.play(),e(I)}).catch(t=>{g(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(e){const{forward:g,up:t}=e,[I,C,i]=g,[o,s,A]=t;this.listener.forwardX.value=I,this.listener.forwardY.value=C,this.listener.forwardZ.value=i,this.listener.upX.value=o,this.listener.upY.value=s,this.listener.upZ.value=A}get listenerUpOrientation(){return[this.listener.upX.value,this.listener.upY.value,this.listener.upZ.value]}set listenerUpOrientation(e){const[g,t,I]=e;this.listener.upX.value=g,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(e){const[g,t,I]=e;this.listener.forwardX.value=g,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(e){const[g,t,I]=e,C=this.context.currentTime;this.listener.positionX.setValueAtTime(g,C),this.listener.positionY.setValueAtTime(t,C),this.listener.positionZ.setValueAtTime(I,C)}}class J{constructor(e=[]){this.synths=e}addSynth(e){this.synths.push(e)}removeSynth(e){const g=this.synths.indexOf(e);if(g!==-1)this.synths.splice(g,1);else throw new Error("Synth not found in group")}play(){this.synths.forEach(e=>e.play())}stop(){this.synths.forEach(e=>e.stop())}setVolume(e){this.synths.forEach(g=>g.volume=e)}set stereoPan(e){this.synths.forEach(g=>g.stereoPan=e)}set position(e){this.synths.forEach(g=>g.position=e)}}exports.Cacophony=Q;exports.Group=X;exports.MicrophonePlayback=S;exports.Playback=Z;exports.Sound=u;exports.SoundType=B;exports.Synth=G;exports.SynthGroup=J;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|