{"version":3,"file":"pixi-sound.js","sources":["../src/Filterable.ts","../src/htmlaudio/HTMLAudioInstance.ts","../src/htmlaudio/HTMLAudioMedia.ts","../node_modules/promise-polyfill/promise.js","../src/filters/Filter.ts","../src/webaudio/WebAudioUtils.ts","../src/filters/EqualizerFilter.ts","../src/filters/DistortionFilter.ts","../src/filters/StereoFilter.ts","../src/filters/ReverbFilter.ts","../src/filters/MonoFilter.ts","../src/filters/TelephoneFilter.ts","../src/htmlaudio/HTMLAudioContext.ts","../src/webaudio/WebAudioInstance.ts","../src/webaudio/WebAudioNodes.ts","../src/webaudio/WebAudioMedia.ts","../src/utils/SoundUtils.ts","../src/loader/Loader.ts","../src/loader/LoaderMiddleware.ts","../src/sprites/SoundSprite.ts","../src/webaudio/WebAudioContext.ts","../src/SoundLibrary.ts","../src/Sound.ts","../src/index.ts"],"sourcesContent":["import Filter from \"./filters/Filter\";\n\n/**\n * Abstract class which SoundNodes and SoundContext\n * both extend. This provides the functionality for adding\n * dynamic filters.\n * @class Filterable\n * @memberof PIXI.sound\n * @param {AudioNode} source The source audio node\n * @param {AudioNode} destination The output audio node\n * @private\n */\nexport default class Filterable\n{\n    /**\n     * Get the gain node\n     * @name PIXI.sound.Filterable#_input\n     * @type {AudioNode}\n     * @private\n     */\n    private _input: AudioNode;\n\n    /**\n     * The destination output audio node\n     * @name PIXI.sound.Filterable#_output\n     * @type {AudioNode}\n     * @private\n     */\n    private _output: AudioNode;\n\n    /**\n     * Collection of filters.\n     * @name PIXI.sound.Filterable#_filters\n     * @type {PIXI.sound.filters.Filter[]}\n     * @private\n     */\n    private _filters: Filter[];\n\n    constructor(input: AudioNode, output: AudioNode)\n    {\n        this._output = output;\n        this._input = input;\n    }\n\n    /**\n     * The destination output audio node\n     * @name PIXI.sound.Filterable#destination\n     * @type {AudioNode}\n     * @readonly\n     */\n    get destination(): AudioNode\n    {\n        return this._input;\n    }\n\n    /**\n     * The collection of filters\n     * @name PIXI.sound.Filterable#filters\n     * @type {PIXI.sound.filters.Filter[]}\n     */\n    get filters(): Filter[]\n    {\n        return this._filters;\n    }\n    set filters(filters: Filter[])\n    {\n        if (this._filters)\n        {\n            this._filters.forEach((filter: Filter) => {\n                if (filter)\n                {\n                    filter.disconnect();\n                }\n            });\n            this._filters = null;\n            // Reconnect direct path\n            this._input.connect(this._output);\n        }\n\n        if (filters && filters.length)\n        {\n            this._filters = filters.slice(0);\n\n            // Disconnect direct path before inserting filters\n            this._input.disconnect();\n\n            // Connect each filter\n            let prevFilter: Filter = null;\n            filters.forEach((filter: Filter) => {\n                if (prevFilter === null)\n                {\n                    // first filter is the destination\n                    // for the analyser\n                    this._input.connect(filter.destination);\n                }\n                else\n                {\n                    prevFilter.connect(filter.destination);\n                }\n                prevFilter = filter;\n            });\n            prevFilter.connect(this._output);\n        }\n    }\n\n    /**\n     * Cleans up.\n     * @method PIXI.sound.Filterable#destroy\n     */\n    public destroy(): void\n    {\n        this.filters = null;\n        this._input = null;\n        this._output = null;\n    }\n}\n","import HTMLAudioMedia from \"./HTMLAudioMedia\";\nimport {IMediaInstance} from \"../interfaces/IMediaInstance\";\nimport {PlayOptions} from \"../Sound\";\n\nlet id = 0;\n\n/**\n * Instance which wraps the `<audio>` element playback.\n * @private\n * @class HTMLAudioInstance\n * @memberof PIXI.sound.htmlaudio\n */\nexport default class HTMLAudioInstance extends PIXI.utils.EventEmitter implements IMediaInstance\n{\n    /**\n     * Extra padding, in seconds, to deal with low-latecy of HTMLAudio.\n     * @name PIXI.sound.htmlaudio.HTMLAudioInstance.PADDING\n     * @readonly\n     * @default 0.1\n     */\n    public static PADDING: number = 0.1;\n\n    /**\n     * The current unique ID for this instance.\n     * @name PIXI.sound.htmlaudio.HTMLAudioInstance#id\n     * @readonly\n     */\n    public id: number;\n\n    /**\n     * The instance of the Audio element.\n     * @type {HTMLAudioElement}\n     * @name PIXI.sound.htmlaudio.HTMLAudioInstance#_source\n     * @private\n     */\n    private _source: HTMLAudioElement;\n\n    /**\n     * The instance of the Audio media element.\n     * @type {PIXI.sound.htmlaudio.HTMLAudioMedia}\n     * @name PIXI.sound.htmlaudio.HTMLAudioInstance#_media\n     * @private\n     */\n    private _media: HTMLAudioMedia;\n\n    /**\n     * Playback rate, where 1 is 100%.\n     * @type {number}\n     * @name PIXI.sound.htmlaudio.HTMLAudioInstance#_end\n     * @private\n     */\n    private _end: number;\n\n    /**\n     * Current instance paused state.\n     * @type {boolean}\n     * @name PIXI.sound.htmlaudio.HTMLAudioInstance#_paused\n     * @private\n     */\n    private _paused: boolean;\n\n    /**\n     * Current instance muted state.\n     * @type {boolean}\n     * @name PIXI.sound.htmlaudio.HTMLAudioInstance#_muted\n     * @private\n     */\n    private _muted: boolean;\n\n    /**\n     * Current actual paused state.\n     * @type {boolean}\n     * @name PIXI.sound.htmlaudio.HTMLAudioInstance#_pausedReal\n     * @private\n     */\n    private _pausedReal: boolean;\n\n    /**\n     * Total length of the audio.\n     * @type {number}\n     * @name PIXI.sound.htmlaudio.HTMLAudioInstance#_duration\n     * @private\n     */\n    private _duration: number;\n\n    /**\n     * Playback rate, where 1 is 100%.\n     * @type {number}\n     * @name PIXI.sound.htmlaudio.HTMLAudioInstance#_start\n     * @private\n     */\n    private _start: number;\n\n    /**\n     * `true` if the audio is actually playing.\n     * @type {boolean}\n     * @name PIXI.sound.htmlaudio.HTMLAudioInstance#_playing\n     * @private\n     */\n    private _playing: boolean;\n\n    /**\n     * Volume for the instance.\n     * @type {number}\n     * @name PIXI.sound.htmlaudio.HTMLAudioInstance#_volume\n     * @private\n     */\n    private _volume: number;\n\n    /**\n     * Speed for the instance.\n     * @type {number}\n     * @name PIXI.sound.htmlaudio.HTMLAudioInstance#_speed\n     * @private\n     */\n    private _speed: number;\n\n    /**\n     * `true` for looping the playback\n     * @type {boolean}\n     * @name PIXI.sound.htmlaudio.HTMLAudioInstance#_loop\n     * @private\n     */\n    private _loop: boolean;\n\n    constructor(parent: HTMLAudioMedia)\n    {\n        super();\n\n        this.id = id++;\n\n        this.init(parent);  \n    }\n\n    /**\n     * The current playback progress from 0 to 1.\n     * @type {number}\n     * @name PIXI.sound.htmlaudio.HTMLAudioInstance#progress\n     */\n    public get progress(): number\n    {\n        const {currentTime} = this._source;\n        return currentTime / this._duration;\n    }\n\n    /**\n     * Pauses the sound.\n     * @type {boolean}\n     * @name PIXI.sound.htmlaudio.HTMLAudioInstance#paused\n     */\n    public get paused(): boolean\n    {\n        return this._paused;\n    }\n    public set paused(paused: boolean)\n    {\n        this._paused = paused;\n        this.refreshPaused();\n    }\n\n    /**\n     * Reference: http://stackoverflow.com/a/40370077\n     */\n    private _onPlay(): void\n    {\n        this._playing = true;\n    }\n\n    /**\n     * Reference: http://stackoverflow.com/a/40370077\n     */\n    private _onPause(): void\n    {\n        this._playing = false;\n    }\n\n    /**\n     * Initialize the instance.\n     * @method PIXI.sound.htmlaudio.HTMLAudioInstance#init\n     * @param {PIXI.sound.htmlaudio.HTMLAudioMedia} media\n     */\n    public init(media: HTMLAudioMedia): void\n    {\n        this._playing = false;\n        this._duration = media.source.duration;\n        const source = this._source = media.source.cloneNode(false) as HTMLAudioElement;\n        source.src = media.parent.url;\n        source.onplay = this._onPlay.bind(this);\n        source.onpause = this._onPause.bind(this);\n        media.context.on('refresh', this.refresh, this);\n        media.context.on('refreshPaused', this.refreshPaused, this);\n        this._media = media;\n    }\n\n    /**\n     * Stop the sound playing\n     * @method PIXI.sound.htmlaudio.HTMLAudioInstance#_internalStop\n     * @private\n     */\n    private _internalStop(): void\n    {\n        if (this._source && this._playing)\n        {\n            this._source.onended = null;\n            this._source.pause();\n        }\n    }\n\n    /**\n     * Stop the sound playing\n     * @method PIXI.sound.htmlaudio.HTMLAudioInstance#stop\n     */\n    public stop(): void\n    {\n        this._internalStop();\n\n        if (this._source)\n        {\n            this.emit(\"stop\");\n        }\n    }\n\n    /**\n     * Set the instance speed from 0 to 1\n     * @member {number} PIXI.sound.htmlaudio.HTMLAudioInstance#speed\n     */\n    public get speed(): number\n    {\n        return this._speed;\n    }\n    public set speed(speed: number)\n    {\n        this._speed = speed;\n        this.refresh();\n    }\n\n    /**\n     * Get the set the volume for this instance from 0 to 1\n     * @member {number} PIXI.sound.htmlaudio.HTMLAudioInstance#volume\n     */\n    public get volume(): number\n    {\n        return this._volume;\n    }\n    public set volume(volume: number)\n    {\n        this._volume = volume;\n        this.refresh();\n    }\n\n    /**\n     * If the sound instance should loop playback\n     * @member {boolean} PIXI.sound.htmlaudio.HTMLAudioInstance#loop\n     */\n    public get loop(): boolean\n    {\n        return this._loop;\n    }\n    public set loop(loop: boolean)\n    {\n        this._loop = loop;\n        this.refresh();\n    }\n\n    /**\n     * `true` if the sound is muted\n     * @member {boolean} PIXI.sound.htmlaudio.HTMLAudioInstance#muted\n     */\n    public get muted(): boolean\n    {\n        return this._muted;\n    }\n    public set muted(muted: boolean)\n    {\n        this._muted = muted;\n        this.refresh();\n    }\n\n    /**\n     * Call whenever the loop, speed or volume changes\n     * @method PIXI.sound.htmlaudio.HTMLAudioInstance#refresh\n     */\n    public refresh(): void \n    {\n        const global = this._media.context;\n        const sound = this._media.parent;\n\n        // Update the looping\n        this._source.loop = this._loop || sound.loop;\n\n        // Update the volume\n        const globalVolume = global.volume * (global.muted ? 0 : 1);\n        const soundVolume = sound.volume * (sound.muted ? 0 : 1);\n        const instanceVolume = this._volume * (this._muted ? 0 : 1);\n        this._source.volume = instanceVolume * globalVolume * soundVolume;\n\n        // Update the speed\n        this._source.playbackRate = this._speed * global.speed * sound.speed;\n    }\n\n    /**\n     * Handle changes in paused state, either globally or sound or instance\n     * @method PIXI.sound.htmlaudio.HTMLAudioInstance#refreshPaused\n     */\n    public refreshPaused(): void\n    {\n        const global = this._media.context;\n        const sound = this._media.parent;\n\n        // Handle the paused state\n        const pausedReal = this._paused || sound.paused || global.paused;\n\n        if (pausedReal !== this._pausedReal)\n        {\n            this._pausedReal = pausedReal;\n\n            if (pausedReal)\n            {\n                this._internalStop();\n\n                /**\n                 * The sound is paused.\n                 * @event PIXI.sound.htmlaudio.HTMLAudioInstance#paused\n                 */\n                this.emit(\"paused\");\n            }\n            else\n            {\n                /**\n                 * The sound is unpaused.\n                 * @event PIXI.sound.htmlaudio.HTMLAudioInstance#resumed\n                 */\n                this.emit(\"resumed\");\n\n                // resume the playing with offset\n                this.play({\n                    start: this._source.currentTime,\n                    end: this._end,\n                    volume: this._volume,\n                    speed: this._speed,\n                    loop: this._loop\n                });\n            }\n\n            /**\n             * The sound is paused or unpaused.\n             * @event PIXI.sound.htmlaudio.HTMLAudioInstance#pause\n             * @property {boolean} paused If the instance was paused or not.\n             */\n            this.emit(\"pause\", pausedReal);\n        }\n    }\n\n    /**\n     * Start playing the sound/\n     * @method PIXI.sound.htmlaudio.HTMLAudioInstance#play\n     */\n    public play(options: PlayOptions): void\n    {\n        const {start, end, speed, loop, volume, muted} = options;\n\n        // @if DEBUG\n        if (end)\n        {\n            console.assert(end > start, \"End time is before start time\");\n        }\n        // @endif\n        \n        this._speed = speed;\n        this._volume = volume;\n        this._loop = !!loop;\n        this._muted = muted;\n        this.refresh();\n\n        // WebAudio doesn't support looping when a duration is set\n        // we'll set this just for the heck of it\n        if (this.loop && end !== null)\n        {\n            // @if DEBUG\n            console.warn('Looping not support when specifying an \"end\" time');\n            // @endif\n            this.loop = false;\n        }\n        \n        this._start = start;\n        this._end = end || this._duration;\n\n        // Lets expand the start and end a little\n        // to deal with the low-latecy of playing audio this way\n        // this is a little fudge-factor\n        this._start = Math.max(0, this._start - HTMLAudioInstance.PADDING);\n        this._end = Math.min(this._end + HTMLAudioInstance.PADDING, this._duration);\n\n        this._source.onloadedmetadata = () => {\n            if (this._source)\n            {\n                this._source.currentTime = start;\n                this._source.onloadedmetadata = null;\n                this.emit(\"progress\", start, this._duration);\n                PIXI.ticker.shared.add(this._onUpdate, this);\n            }\n        };\n        this._source.onended = this._onComplete.bind(this);\n        this._source.play();\n\n        /**\n         * The sound is started.\n         * @event PIXI.sound.htmlaudio.HTMLAudioInstance#start\n         */\n        this.emit(\"start\");\n    }\n\n    /**\n     * Handle time update on sound.\n     * @method PIXI.sound.htmlaudio.HTMLAudioInstance#_onUpdate\n     * @private\n     */\n    private _onUpdate(): void\n    {\n        this.emit(\"progress\", this.progress, this._duration);\n        if (this._source.currentTime >= this._end && !this._source.loop)\n        {\n            this._onComplete();\n        }\n    }\n\n    /**\n     * Callback when completed.\n     * @method PIXI.sound.htmlaudio.HTMLAudioInstance#_onComplete\n     * @private\n     */\n    private _onComplete(): void\n    {\n        PIXI.ticker.shared.remove(this._onUpdate, this);\n        this._internalStop();\n        this.emit(\"progress\", 1, this._duration);\n        /**\n         * The sound ends, don't use after this\n         * @event PIXI.sound.htmlaudio.HTMLAudioInstance#end\n         */\n        this.emit(\"end\", this);\n    }\n\n    /**\n     * Don't use after this.\n     * @method PIXI.sound.htmlaudio.HTMLAudioInstance#destroy\n     */\n    public destroy(): void\n    {\n        PIXI.ticker.shared.remove(this._onUpdate, this);\n        this.removeAllListeners();\n\n        const source = this._source;\n\n        if (source)\n        {\n            // Remove the listeners\n            source.onended = null;\n            source.onplay = null;\n            source.onpause = null;\n\n            this._internalStop();\n        }\n\n        this._source = null;\n        this._speed = 1;\n        this._volume = 1;\n        this._loop = false;\n        this._end = null;\n        this._start = 0;\n        this._duration = 0;\n        this._playing = false;\n        this._pausedReal = false;\n        this._paused = false;\n        this._muted = false;\n\n        if (this._media)\n        {\n            this._media.context.off('refresh', this.refresh, this);\n            this._media.context.off('refreshPaused', this.refreshPaused, this);\n            this._media = null;\n        }\n    }\n\n    /**\n     * To string method for instance.\n     * @method PIXI.sound.htmlaudio.HTMLAudioInstance#toString\n     * @return {String} The string representation of instance.\n     * @private\n     */\n    public toString(): string\n    {\n        return \"[HTMLAudioInstance id=\" + this.id + \"]\";\n    }\n}\n","import {Options, LoadedCallback, CompleteCallback, PlayOptions} from '../Sound';\nimport Sound from \"../Sound\";\nimport {SoundSpriteData, SoundSprites} from \"../sprites/SoundSprite\";\nimport SoundSprite from \"../sprites/SoundSprite\";\nimport {IMedia} from '../interfaces/IMedia';\nimport HTMLAudioContext from \"./HTMLAudioContext\";\nimport HTMLAudioInstance from \"./HTMLAudioInstance\";\nimport Filter from \"../filters/Filter\";\n\n/**\n * The fallback version of Sound which uses `<audio>` instead of WebAudio API.\n * @private\n * @class HTMLAudioMedia\n * @memberof PIXI.sound.htmlaudio\n * @param {HTMLAudioElement|String|Object} options Either the path or url to the source file.\n *        or the object of options to use. See {@link PIXI.sound.Sound.from}\n */\nexport default class HTMLAudioMedia extends PIXI.utils.EventEmitter implements IMedia\n{\n    public parent: Sound;\n    private _source: HTMLAudioElement;\n\n    init(parent: Sound): void\n    {\n        this.parent = parent;\n        this._source = parent.options.source as HTMLAudioElement || new Audio();\n        if (parent.url)\n        {\n            this._source.src = parent.url;\n        }\n    }\n\n    // Implement create\n    public create(): HTMLAudioInstance\n    {\n        return new HTMLAudioInstance(this);\n    }\n\n    // Implement isPlayable\n    public get isPlayable(): boolean\n    {\n        return !!this._source && this._source.readyState === 4;\n    }\n\n    // Implement duration\n    public get duration(): number\n    {\n        return this._source.duration;\n    }\n\n    // Implement context\n    public get context(): HTMLAudioContext\n    {\n        return this.parent.context as HTMLAudioContext;\n    }\n\n    // Implement filters\n    public get filters(): Filter[]\n    {\n        return null;\n    }\n    public set filters(filters: Filter[])\n    {\n        // @if DEBUG\n        console.warn('HTML Audio does not support filters');\n        // @endif\n    }\n\n    // Override the destroy\n    public destroy(): void\n    {\n        this.removeAllListeners();\n\n        this.parent = null;\n\n        if (this._source)\n        {\n            this._source.src = \"\";\n            this._source.load();\n            this._source = null;\n        }\n    }\n\n    /**\n     * Get the audio source element.\n     * @name PIXI.sound.legacy.LegacySound#source\n     * @type {HTMLAudioElement}\n     * @readonly\n     */\n    public get source(): HTMLAudioElement\n    {\n        return this._source;\n    }\n\n    // Implement the method to being preloading\n    public load(callback?: LoadedCallback): void\n    {\n        const source = this._source;\n        const sound = this.parent;\n\n        // See if the source is already loaded\n        if (source.readyState === 4)\n        {\n            sound.isLoaded = true;\n            const instance = sound.autoPlayStart();\n            if (callback)\n            {\n                setTimeout(() =>\n                {\n                    callback(null, sound, instance);\n                }, 0);\n            }\n            return;\n        }\n\n        // If there's no source, we cannot load\n        if (!sound.url)\n        {\n            return callback(new Error(\"sound.url or sound.source must be set\"));\n        }\n\n        // Set the source\n        source.src = sound.url;\n\n        // Remove all event listeners\n        const removeListeners = () =>\n        {\n            // Listen for callback\n            source.removeEventListener('canplaythrough', onLoad);\n            source.removeEventListener('load', onLoad);\n            source.removeEventListener('abort', onAbort);\n            source.removeEventListener('error', onError);\n        };\n\n        const onLoad = () =>\n        {\n            removeListeners();\n            sound.isLoaded = true;\n            const instance = sound.autoPlayStart();\n            if (callback)\n            {\n                callback(null, sound, instance);\n            }\n        };\n\n        const onAbort = () =>\n        {\n            removeListeners();\n            if (callback)\n            {\n                callback(new Error('Sound loading has been aborted'));\n            }\n        };\n\n        const onError = () =>\n        {\n            removeListeners();\n            const message = `Failed to load audio element (code: ${source.error.code})`;\n            if (callback)\n            {\n                callback(new Error(message));\n            }\n            else\n            {\n                console.error(message);\n            }\n        };\n\n        // Listen for callback\n        source.addEventListener('canplaythrough', onLoad, false);\n        source.addEventListener('load', onLoad, false);\n        source.addEventListener('abort', onAbort, false);\n        source.addEventListener('error', onError, false);\n\n        // Begin the loading\n        source.load();\n    }\n}\n","(function (root) {\n\n  // Store setTimeout reference so promise-polyfill will be unaffected by\n  // other code modifying setTimeout (like sinon.useFakeTimers())\n  var setTimeoutFunc = setTimeout;\n\n  function noop() {}\n  \n  // Polyfill for Function.prototype.bind\n  function bind(fn, thisArg) {\n    return function () {\n      fn.apply(thisArg, arguments);\n    };\n  }\n\n  function Promise(fn) {\n    if (!(this instanceof Promise)) throw new TypeError('Promises must be constructed via new');\n    if (typeof fn !== 'function') throw new TypeError('not a function');\n    this._state = 0;\n    this._handled = false;\n    this._value = undefined;\n    this._deferreds = [];\n\n    doResolve(fn, this);\n  }\n\n  function handle(self, deferred) {\n    while (self._state === 3) {\n      self = self._value;\n    }\n    if (self._state === 0) {\n      self._deferreds.push(deferred);\n      return;\n    }\n    self._handled = true;\n    Promise._immediateFn(function () {\n      var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;\n      if (cb === null) {\n        (self._state === 1 ? resolve : reject)(deferred.promise, self._value);\n        return;\n      }\n      var ret;\n      try {\n        ret = cb(self._value);\n      } catch (e) {\n        reject(deferred.promise, e);\n        return;\n      }\n      resolve(deferred.promise, ret);\n    });\n  }\n\n  function resolve(self, newValue) {\n    try {\n      // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure\n      if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.');\n      if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {\n        var then = newValue.then;\n        if (newValue instanceof Promise) {\n          self._state = 3;\n          self._value = newValue;\n          finale(self);\n          return;\n        } else if (typeof then === 'function') {\n          doResolve(bind(then, newValue), self);\n          return;\n        }\n      }\n      self._state = 1;\n      self._value = newValue;\n      finale(self);\n    } catch (e) {\n      reject(self, e);\n    }\n  }\n\n  function reject(self, newValue) {\n    self._state = 2;\n    self._value = newValue;\n    finale(self);\n  }\n\n  function finale(self) {\n    if (self._state === 2 && self._deferreds.length === 0) {\n      Promise._immediateFn(function() {\n        if (!self._handled) {\n          Promise._unhandledRejectionFn(self._value);\n        }\n      });\n    }\n\n    for (var i = 0, len = self._deferreds.length; i < len; i++) {\n      handle(self, self._deferreds[i]);\n    }\n    self._deferreds = null;\n  }\n\n  function Handler(onFulfilled, onRejected, promise) {\n    this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;\n    this.onRejected = typeof onRejected === 'function' ? onRejected : null;\n    this.promise = promise;\n  }\n\n  /**\n   * Take a potentially misbehaving resolver function and make sure\n   * onFulfilled and onRejected are only called once.\n   *\n   * Makes no guarantees about asynchrony.\n   */\n  function doResolve(fn, self) {\n    var done = false;\n    try {\n      fn(function (value) {\n        if (done) return;\n        done = true;\n        resolve(self, value);\n      }, function (reason) {\n        if (done) return;\n        done = true;\n        reject(self, reason);\n      });\n    } catch (ex) {\n      if (done) return;\n      done = true;\n      reject(self, ex);\n    }\n  }\n\n  Promise.prototype['catch'] = function (onRejected) {\n    return this.then(null, onRejected);\n  };\n\n  Promise.prototype.then = function (onFulfilled, onRejected) {\n    var prom = new (this.constructor)(noop);\n\n    handle(this, new Handler(onFulfilled, onRejected, prom));\n    return prom;\n  };\n\n  Promise.all = function (arr) {\n    return new Promise(function (resolve, reject) {\n      if (!arr || typeof arr.length === 'undefined') throw new TypeError('Promise.all accepts an array');\n      var args = Array.prototype.slice.call(arr);\n      if (args.length === 0) return resolve([]);\n      var remaining = args.length;\n\n      function res(i, val) {\n        try {\n          if (val && (typeof val === 'object' || typeof val === 'function')) {\n            var then = val.then;\n            if (typeof then === 'function') {\n              then.call(val, function (val) {\n                res(i, val);\n              }, reject);\n              return;\n            }\n          }\n          args[i] = val;\n          if (--remaining === 0) {\n            resolve(args);\n          }\n        } catch (ex) {\n          reject(ex);\n        }\n      }\n\n      for (var i = 0; i < args.length; i++) {\n        res(i, args[i]);\n      }\n    });\n  };\n\n  Promise.resolve = function (value) {\n    if (value && typeof value === 'object' && value.constructor === Promise) {\n      return value;\n    }\n\n    return new Promise(function (resolve) {\n      resolve(value);\n    });\n  };\n\n  Promise.reject = function (value) {\n    return new Promise(function (resolve, reject) {\n      reject(value);\n    });\n  };\n\n  Promise.race = function (values) {\n    return new Promise(function (resolve, reject) {\n      for (var i = 0, len = values.length; i < len; i++) {\n        values[i].then(resolve, reject);\n      }\n    });\n  };\n\n  // Use polyfill for setImmediate for performance gains\n  Promise._immediateFn = (typeof setImmediate === 'function' && function (fn) { setImmediate(fn); }) ||\n    function (fn) {\n      setTimeoutFunc(fn, 0);\n    };\n\n  Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) {\n    if (typeof console !== 'undefined' && console) {\n      console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console\n    }\n  };\n\n  /**\n   * Set the immediate function to execute callbacks\n   * @param fn {function} Function to execute\n   * @deprecated\n   */\n  Promise._setImmediateFn = function _setImmediateFn(fn) {\n    Promise._immediateFn = fn;\n  };\n\n  /**\n   * Change the function to execute on unhandled rejection\n   * @param {function} fn Function to execute on unhandled rejection\n   * @deprecated\n   */\n  Promise._setUnhandledRejectionFn = function _setUnhandledRejectionFn(fn) {\n    Promise._unhandledRejectionFn = fn;\n  };\n  \n  if (typeof module !== 'undefined' && module.exports) {\n    module.exports = Promise;\n  } else if (!root.Promise) {\n    root.Promise = Promise;\n  }\n\n})(this);\n","/**\n * Represents a single sound element. Can be used to play, pause, etc. sound instances.\n *\n * @class Filter\n * @memberof PIXI.sound.filters\n * @param {AudioNode} destination The audio node to use as the destination for the input AudioNode\n * @param {AudioNode} [source] Optional output node, defaults to destination node. This is useful\n *        when creating filters which contains multiple AudioNode elements chained together.\n */\nexport default class Filter\n{\n    /**\n     * The node to connect for the filter to the previous filter.\n     * @name PIXI.sound.filters.Filter#destination\n     * @type {AudioNode}\n     */\n    public destination:AudioNode;\n\n    /**\n     * The node to connect for the filter to the previous filter.\n     * @name PIXI.sound.filters.Filter#source\n     * @type {AudioNode}\n     */\n    public source:AudioNode;\n    \n    constructor(destination:AudioNode, source?:AudioNode)\n    {\n        this.destination = destination;\n        this.source = source || destination;\n    }\n\n    /**\n     * Connect to the destination.\n     * @method PIXI.sound.filters.Filter#connect\n     * @param {AudioNode} destination The destination node to connect the output to\n     */\n    connect(destination:AudioNode): void\n    {\n        this.source.connect(destination);\n    }\n\n    /**\n     * Completely disconnect filter from destination and source nodes.\n     * @method PIXI.sound.filters.Filter#disconnect\n     */\n    disconnect(): void\n    {\n        this.source.disconnect();\n    }\n\n    /**\n     * Destroy the filter and don't use after this.\n     * @method PIXI.sound.filters.Filter#destroy\n     */\n    destroy(): void\n    {\n        this.disconnect();\n        this.destination = null;\n        this.source = null;\n    }\n}\n","import SoundLibrary from '../SoundLibrary';\nimport WebAudioContext from './WebAudioContext';\n\n/**\n * Internal class for Web Audio abstractions and convenience methods.\n * @private\n * @class WebAudioUtils\n * @memberof PIXI.sound.webaudio\n */\nexport default class WebAudioUtils\n{\n    /**\n     * Dezippering is removed in the future Web Audio API, instead\n     * we use the `setValueAtTime` method, however, this is not available\n     * in all environments (e.g., Android webview), so we fallback to the `value` setter.\n     * @method PIXI.sound.webaudio.WebAudioUtils.setParamValue\n     * @private\n     * @param {AudioParam} param - AudioNode parameter object\n     * @param {number} value - Value to set\n     * @return {number} The value set\n     */\n    public static setParamValue(param: AudioParam, value: number): number\n    {\n        if (param.setValueAtTime)\n        {\n            const context = SoundLibrary.instance.context as WebAudioContext;\n            param.setValueAtTime(value, context.audioContext.currentTime);\n        }\n        else\n        {\n            param.value = value;\n        }\n        return value;\n    }\n}\n","import Filter from './Filter';\nimport SoundLibrary from '../SoundLibrary';\nimport WebAudioUtils from '../webaudio/WebAudioUtils';\n\ninterface Band {\n    f:number;\n    type:string;\n    gain:number;\n}\n\n/**\n * Filter for adding equalizer bands.\n *\n * @class EqualizerFilter\n * @memberof PIXI.sound.filters\n * @param {number} [f32=0] Default gain for 32 Hz\n * @param {number} [f64=0] Default gain for 64 Hz\n * @param {number} [f125=0] Default gain for 125 Hz\n * @param {number} [f250=0] Default gain for 250 Hz\n * @param {number} [f500=0] Default gain for 500 Hz\n * @param {number} [f1k=0] Default gain for 1000 Hz\n * @param {number} [f2k=0] Default gain for 2000 Hz\n * @param {number} [f4k=0] Default gain for 4000 Hz\n * @param {number} [f8k=0] Default gain for 8000 Hz\n * @param {number} [f16k=0] Default gain for 16000 Hz\n */\nexport default class EqualizerFilter extends Filter\n{\n    /**\n     * Band at 32 Hz\n     * @name PIXI.sound.filters.EqualizerFilter.F32\n     * @type {number}\n     * @readonly\n     */\n    public static F32:number = 32;\n\n    /**\n     * Band at 64 Hz\n     * @name PIXI.sound.filters.EqualizerFilter.F64\n     * @type {number}\n     * @readonly\n     */\n    public static F64:number = 64;\n    \n    /**\n     * Band at 125 Hz\n     * @name PIXI.sound.filters.EqualizerFilter.F125\n     * @type {number}\n     * @readonly\n     */\n    public static F125:number = 125;\n    \n    /**\n     * Band at 250 Hz\n     * @name PIXI.sound.filters.EqualizerFilter.F250\n     * @type {number}\n     * @readonly\n     */\n    public static F250:number = 250;\n    \n    /**\n     * Band at 500 Hz\n     * @name PIXI.sound.filters.EqualizerFilter.F500\n     * @type {number}\n     * @readonly\n     */\n    public static F500:number = 500;\n    \n    /**\n     * Band at 1000 Hz\n     * @name PIXI.sound.filters.EqualizerFilter.F1K\n     * @type {number}\n     * @readonly\n     */\n    public static F1K:number = 1000;\n    \n    /**\n     * Band at 2000 Hz\n     * @name PIXI.sound.filters.EqualizerFilter.F2K\n     * @type {number}\n     * @readonly\n     */\n    public static F2K:number = 2000;\n    \n    /**\n     * Band at 4000 Hz\n     * @name PIXI.sound.filters.EqualizerFilter.F4K\n     * @type {number}\n     * @readonly\n     */\n    public static F4K:number = 4000;\n    \n    /**\n     * Band at 8000 Hz\n     * @name PIXI.sound.filters.EqualizerFilter.F8K\n     * @type {number}\n     * @readonly\n     */\n    public static F8K:number = 8000;\n    \n    /**\n     * Band at 16000 Hz\n     * @name PIXI.sound.filters.EqualizerFilter.F16K\n     * @type {number}\n     * @readonly\n     */\n    public static F16K:number = 16000;\n\n    /**\n     * The list of bands \n     * @name PIXI.sounds.filters.EqualizerFilter#bands\n     * @type {BiquadFilterNode[]}\n     * @readonly\n     */\n    public bands:BiquadFilterNode[];\n\n    /**\n     * The map of bands to frequency\n     * @name PIXI.sounds.filters.EqualizerFilter#bandsMap\n     * @type {Object}\n     * @readonly\n     */\n    public bandsMap:{[id:number]:BiquadFilterNode};\n\n    constructor(f32:number = 0, f64:number = 0, f125:number = 0, f250:number = 0, f500:number = 0,\n        f1k:number = 0, f2k:number = 0, f4k:number = 0, f8k:number = 0, f16k:number = 0)\n    {\n        if (SoundLibrary.instance.useLegacy)\n        {\n            super(null);\n            return;\n        }\n\n        const equalizerBands:Band[] = [\n            {\n                f: EqualizerFilter.F32,\n                type: 'lowshelf',\n                gain: f32\n            },\n            {\n                f: EqualizerFilter.F64,\n                type: 'peaking',\n                gain: f64\n            },\n            {\n                f: EqualizerFilter.F125,\n                type: 'peaking',\n                gain: f125\n            },\n            {\n                f: EqualizerFilter.F250,\n                type: 'peaking',\n                gain: f250\n            },\n            {\n                f: EqualizerFilter.F500,\n                type: 'peaking',\n                gain: f500\n            },\n            {\n                f: EqualizerFilter.F1K,\n                type: 'peaking',\n                gain: f1k\n            },\n            {\n                f: EqualizerFilter.F2K,\n                type: 'peaking',\n                gain: f2k\n            },\n            {\n                f: EqualizerFilter.F4K,\n                type: 'peaking',\n                gain: f4k\n            },\n            {\n                f: EqualizerFilter.F8K,\n                type: 'peaking',\n                gain: f8k\n            },\n            {\n                f: EqualizerFilter.F16K,\n                type: 'highshelf',\n                gain: f16k\n            }\n        ];\n        \n        const bands:BiquadFilterNode[] = equalizerBands.map(function (band:Band)\n        {\n            const filter:BiquadFilterNode = SoundLibrary.instance.context.audioContext.createBiquadFilter();\n            filter.type = band.type as BiquadFilterType;\n            WebAudioUtils.setParamValue(filter.gain, band.gain);\n            WebAudioUtils.setParamValue(filter.Q, 1);\n            WebAudioUtils.setParamValue(filter.frequency, band.f);\n            return filter;\n        });\n\n        // Setup the constructor AudioNode, where first is the input, and last is the output\n        super(bands[0], bands[bands.length - 1]);\n\n        // Manipulate the bands\n        this.bands = bands;\n\n        // Create a map\n        this.bandsMap = {};\n\n        for (let i = 0; i < this.bands.length; i++)\n        {\n            const node:BiquadFilterNode = this.bands[i];\n\n            // Connect the previous band to the current one\n            if (i > 0)\n            {\n                this.bands[i - 1].connect(node);\n            }\n            this.bandsMap[node.frequency.value] = node;\n        }\n    }\n\n    /**\n     * Set gain on a specific frequency.\n     * @method PIXI.sound.filters.EqualizerFilter#setGain\n     * @param {number} frequency The frequency, see EqualizerFilter.F* for bands\n     * @param {number} [gain=0] Recommended -40 to 40.\n     */\n    setGain(frequency:number, gain:number = 0): void\n    {\n        if (!this.bandsMap[frequency])\n        {\n            throw 'No band found for frequency ' + frequency;\n        }\n        WebAudioUtils.setParamValue(this.bandsMap[frequency].gain, gain);\n    }\n\n    /**\n     * Get gain amount on a specific frequency.\n     * @method PIXI.sound.filters.EqualizerFilter#getGain\n     * @return {number} The amount of gain set.\n     */\n    getGain(frequency:number): number\n    {\n        if (!this.bandsMap[frequency])\n        {\n            throw 'No band found for frequency ' + frequency;\n        }\n        return this.bandsMap[frequency].gain.value;\n    }\n\n    /**\n     * Gain at 32 Hz frequencey.\n     * @name PIXI.sound.filters.EqualizerFilter#f32\n     * @type {number}\n     * @default 0\n     */\n    public set f32(value:number)\n    {\n        this.setGain(EqualizerFilter.F32, value);\n    }\n    public get f32(): number\n    {\n        return this.getGain(EqualizerFilter.F32);\n    }\n\n    /**\n     * Gain at 64 Hz frequencey.\n     * @name PIXI.sound.filters.EqualizerFilter#f64\n     * @type {number}\n     * @default 0\n     */\n    public set f64(value:number)\n    {\n        this.setGain(EqualizerFilter.F64, value);\n    }\n    public get f64(): number\n    {\n        return this.getGain(EqualizerFilter.F64);\n    }\n\n    /**\n     * Gain at 125 Hz frequencey.\n     * @name PIXI.sound.filters.EqualizerFilter#f125\n     * @type {number}\n     * @default 0\n     */\n    public set f125(value:number)\n    {\n        this.setGain(EqualizerFilter.F125, value);\n    }\n    public get f125(): number\n    {\n        return this.getGain(EqualizerFilter.F125);\n    }\n\n    /**\n     * Gain at 250 Hz frequencey.\n     * @name PIXI.sound.filters.EqualizerFilter#f250\n     * @type {number}\n     * @default 0\n     */\n    public set f250(value:number)\n    {\n        this.setGain(EqualizerFilter.F250, value);\n    }\n    public get f250(): number\n    {\n        return this.getGain(EqualizerFilter.F250);\n    }\n\n    /**\n     * Gain at 500 Hz frequencey.\n     * @name PIXI.sound.filters.EqualizerFilter#f500\n     * @type {number}\n     * @default 0\n     */\n    public set f500(value:number)\n    {\n        this.setGain(EqualizerFilter.F500, value);\n    }\n    public get f500(): number\n    {\n        return this.getGain(EqualizerFilter.F500);\n    }\n\n    /**\n     * Gain at 1 KHz frequencey.\n     * @name PIXI.sound.filters.EqualizerFilter#f1k\n     * @type {number}\n     * @default 0\n     */\n    public set f1k(value:number)\n    {\n        this.setGain(EqualizerFilter.F1K, value);\n    }\n    public get f1k(): number\n    {\n        return this.getGain(EqualizerFilter.F1K);\n    }\n\n    /**\n     * Gain at 2 KHz frequencey.\n     * @name PIXI.sound.filters.EqualizerFilter#f2k\n     * @type {number}\n     * @default 0\n     */\n    public set f2k(value:number)\n    {\n        this.setGain(EqualizerFilter.F2K, value);\n    }\n    public get f2k(): number\n    {\n        return this.getGain(EqualizerFilter.F2K);\n    }\n\n    /**\n     * Gain at 4 KHz frequencey.\n     * @name PIXI.sound.filters.EqualizerFilter#f4k\n     * @type {number}\n     * @default 0\n     */\n    public set f4k(value:number)\n    {\n        this.setGain(EqualizerFilter.F4K, value);\n    }\n    public get f4k(): number\n    {\n        return this.getGain(EqualizerFilter.F4K);\n    }\n\n    /**\n     * Gain at 8 KHz frequencey.\n     * @name PIXI.sound.filters.EqualizerFilter#f8k\n     * @type {number}\n     * @default 0\n     */\n    public set f8k(value:number)\n    {\n        this.setGain(EqualizerFilter.F8K, value);\n    }\n    public get f8k(): number\n    {\n        return this.getGain(EqualizerFilter.F8K);\n    }\n\n    /**\n     * Gain at 16 KHz frequencey.\n     * @name PIXI.sound.filters.EqualizerFilter#f16k\n     * @type {number}\n     * @default 0\n     */\n    public set f16k(value:number)\n    {\n        this.setGain(EqualizerFilter.F16K, value);\n    }\n    public get f16k(): number\n    {\n        return this.getGain(EqualizerFilter.F16K);\n    }\n\n    /**\n     * Reset all frequency bands to have gain of 0\n     * @method PIXI.sound.filters.EqualizerFilter#reset\n     */\n    reset(): void\n    {\n        this.bands.forEach((band:BiquadFilterNode) => {\n            WebAudioUtils.setParamValue(band.gain, 0);\n        });\n    }\n\n    destroy(): void\n    {\n        this.bands.forEach((band:BiquadFilterNode) => {\n            band.disconnect();\n        });\n        this.bands = null;\n        this.bandsMap = null;\n    }\n}\n","import Filter from './Filter';\nimport SoundLibrary from '../SoundLibrary';\n\n/**\n * Filter for adding adding delaynode.\n *\n * @class DistortionFilter\n * @memberof PIXI.sound.filters\n * @param {number} [amount=0] The amount of distoration from 0 to 1.\n */\nexport default class DistortionFilter extends Filter\n{\n    /**\n     * The Wave shape node use to distort\n     * @name PIXI.sound.filters.DistortionFilter#_distortion\n     * @type {WaveShaperNode}\n     * @private\n     */\n    private _distortion:WaveShaperNode;\n\n    /**\n     * The amount of distoration\n     * @name PIXI.sound.filters.DistortionFilter#_amount\n     * @type {number}\n     * @private\n     */\n    private _amount:number;\n\n    constructor(amount:number = 0)\n    {\n        if (SoundLibrary.instance.useLegacy)\n        {\n            super(null);\n            return;\n        }\n        \n        const context = SoundLibrary.instance.context;\n        const distortion:WaveShaperNode = context.audioContext.createWaveShaper();\n\n        super(distortion);\n\n        this._distortion = distortion;\n\n        this.amount = amount;\n    }\n\n    /**\n     * @name PIXI.sound.filters.Distoration#amount\n     * @type {number}\n     */\n    set amount(value:number)\n    {\n        value *= 1000;\n        this._amount = value;\n        const samples:number = 44100;\n        const curve:Float32Array = new Float32Array(samples);\n        const deg:number = Math.PI / 180;\n\n        let i:number = 0;\n        let x:number;\n\n        for ( ; i < samples; ++i )\n        {\n            x = i * 2 / samples - 1;\n            curve[i] = ( 3 + value ) * x * 20 * deg / ( Math.PI + value * Math.abs(x) );\n        }\n        this._distortion.curve = curve;\n        this._distortion.oversample = '4x';\n    }\n    get amount(): number\n    {\n        return this._amount;\n    }\n\n    destroy(): void\n    {\n        this._distortion = null;\n        super.destroy();\n    }\n}\n","import Filter from './Filter';\nimport SoundLibrary from '../SoundLibrary';\nimport WebAudioUtils from '../webaudio/WebAudioUtils';\n\n/**\n * Filter for adding Stereo panning.\n *\n * @class StereoFilter\n * @memberof PIXI.sound.filters\n * @param {number} [pan=0] The amount of panning, -1 is left, 1 is right, 0 is centered.\n */\nexport default class StereoFilter extends Filter\n{\n    /**\n     * The stereo panning node\n     * @name PIXI.sound.filters.StereoFilter#_stereo\n     * @type {StereoPannerNode}\n     * @private\n     */\n    private _stereo:StereoPannerNode;\n\n    /**\n     * The stereo panning node\n     * @name PIXI.sound.filters.StereoFilter#_panner\n     * @type {PannerNode}\n     * @private\n     */\n    private _panner:PannerNode;\n\n    /**\n     * The amount of panning, -1 is left, 1 is right, 0 is centered\n     * @name PIXI.sound.filters.StereoFilter#_pan\n     * @type {number}\n     * @private\n     */\n    private _pan:number;\n\n    constructor(pan:number = 0)\n    {\n        if (SoundLibrary.instance.useLegacy)\n        {\n            super(null);\n            return;\n        }\n\n        let stereo:StereoPannerNode;\n        let panner:PannerNode;\n        let destination:AudioNode;\n        const audioContext = SoundLibrary.instance.context.audioContext;\n\n        if (audioContext.createStereoPanner)\n        {\n            stereo = audioContext.createStereoPanner();\n            destination = stereo;\n        }\n        else\n        {\n            panner = audioContext.createPanner();\n            panner.panningModel = 'equalpower';\n            destination = panner;\n        }\n\n        super(destination);\n\n        this._stereo = stereo;\n        this._panner = panner;\n\n        this.pan = pan;\n    }\n\n    /**\n     * Set the amount of panning, where -1 is left, 1 is right, and 0 is centered\n     * @name PIXI.sound.filters.StereoFilter#pan\n     * @type {number}\n     */\n    set pan(value:number)\n    {\n        this._pan = value;\n        if (this._stereo)\n        {\n            WebAudioUtils.setParamValue(this._stereo.pan, value);\n        }\n        else\n        {\n            this._panner.setPosition(value, 0, 1 - Math.abs(value));\n        }\n    }\n    get pan(): number\n    {\n        return this._pan;\n    }\n\n    destroy(): void\n    {\n        super.destroy();\n        this._stereo = null;\n        this._panner = null;\n    }\n}\n","import Filter from './Filter';\nimport SoundLibrary from '../SoundLibrary';\n\n/**\n * Filter for adding reverb. Refactored from \n * https://github.com/web-audio-components/simple-reverb/\n *\n * @class ReverbFilter\n * @memberof PIXI.sound.filters\n * @param {number} [seconds=3] Seconds for reverb\n * @param {number} [decay=2] The decay length\n * @param {boolean} [reverse=false] Reverse reverb\n */\nexport default class ReverbFilter extends Filter\n{\n    /**\n     * The covolver node\n     * @name PIXI.sound.filters.ReverbFilter#_convolver\n     * @type {ConvolverNode}\n     * @private\n     */\n    private _convolver:ConvolverNode;\n\n    /**\n     * @name PIXI.sound.filters.ReverbFilter#_seconds\n     * @type {number}\n     * @private\n     */\n    private _seconds:number;\n\n    /**\n     * @name PIXI.sound.filters.ReverbFilter#_decay\n     * @type {number}\n     * @private\n     */\n    private _decay:number;\n\n    /**\n     * @name PIXI.sound.filters.ReverbFilter#_reverse\n     * @type {number}\n     * @private\n     */\n    private _reverse:boolean;\n\n    constructor(seconds:number = 3, decay:number = 2, reverse:boolean = false)\n    {\n        if (SoundLibrary.instance.useLegacy)\n        {\n            super(null);\n            return;\n        }\n\n        const convolver:ConvolverNode = SoundLibrary.instance.context.audioContext.createConvolver();\n\n        super(convolver);\n\n        this._convolver = convolver;\n        this._seconds = this._clamp(seconds, 1, 50);\n        this._decay = this._clamp(decay, 0, 100);\n        this._reverse = reverse;\n        this._rebuild();\n    }\n\n    /**\n     * Clamp a value\n     * @method PIXI.sound.filters.ReverbFilter#_clamp \n     * @private\n     * @param {number} value\n     * @param {number} min Minimum value\n     * @param {number} max Maximum value\n     * @return {number} Clamped number\n     */\n    private _clamp(value:number, min:number, max:number): number\n    {\n        return Math.min(max, Math.max(min, value));\n    }\n\n    /**\n     * Length of reverb in seconds from 1 to 50\n     * @name PIXI.sound.filters.ReverbFilter#decay\n     * @type {number}\n     * @default 3\n     */\n    get seconds():number\n    {\n        return this._seconds;\n    }\n    set seconds(seconds:number)\n    {\n        this._seconds = this._clamp(seconds, 1, 50);\n        this._rebuild();\n    }\n\n    /**\n     * Decay value from 0 to 100\n     * @name PIXI.sound.filters.ReverbFilter#decay\n     * @type {number}\n     * @default 2\n     */\n    get decay():number\n    {\n        return this._decay;\n    }\n    set decay(decay:number)\n    {\n        this._decay = this._clamp(decay, 0, 100);\n        this._rebuild();\n    }\n\n    /**\n     * Reverse value from 0 to 1\n     * @name PIXI.sound.filters.ReverbFilter#reverse\n     * @type {boolean}\n     * @default false\n     */\n    get reverse():boolean\n    {\n        return this._reverse;\n    }\n    set reverse(reverse:boolean)\n    {\n        this._reverse = reverse;\n        this._rebuild();\n    }\n\n    /**\n     * Utility function for building an impulse response\n     * from the module parameters.\n     * @method PIXI.sound.filters.ReverbFilter#_rebuild\n     * @private\n     */\n    private _rebuild(): void\n    {\n        const context = SoundLibrary.instance.context.audioContext;\n        const rate:number = context.sampleRate;\n        const length:number = rate * this._seconds;\n        const impulse:AudioBuffer = context.createBuffer(2, length, rate);\n        const impulseL:Float32Array = impulse.getChannelData(0);\n        const impulseR:Float32Array = impulse.getChannelData(1);\n        let n:number;\n\n        for (let i:number = 0; i < length; i++)\n        {\n            n = this._reverse ? length - i : i;\n            impulseL[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, this._decay);\n            impulseR[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, this._decay);\n        }\n        this._convolver.buffer = impulse;\n    }\n\n    destroy(): void\n    {\n        this._convolver = null;\n        super.destroy();\n    }\n}\n","import Filter from './Filter';\nimport SoundLibrary from '../SoundLibrary';\n\n/**\n * Combine all channels into mono channel.\n *\n * @class MonoFilter\n * @memberof PIXI.sound.filters\n */\nexport default class MonoFilter extends Filter\n{\n    /**\n     * Merger node\n     * @name PIXI.sound.filters.MonoFilter#_merge\n     * @type {ChannelMergerNode}\n     * @private\n     */\n    private _merger:ChannelMergerNode;\n\n    constructor()\n    {\n        if (SoundLibrary.instance.useLegacy)\n        {\n            super(null);\n        }\n        const audioContext:AudioContext = SoundLibrary.instance.context.audioContext;\n        const splitter:ChannelSplitterNode = audioContext.createChannelSplitter();\n        const merger:ChannelMergerNode = audioContext.createChannelMerger();\n        merger.connect(splitter);\n        super(merger, splitter);\n        this._merger = merger;\n    }\n\n    public destroy(): void\n    {\n        this._merger.disconnect();\n        this._merger = null;\n        super.destroy();\n    }\n}\n","import Filter from './Filter';\nimport SoundLibrary from '../SoundLibrary';\nimport WebAudioUtils from '../webaudio/WebAudioUtils';\n\n/**\n * Creates a telephone-sound filter.\n *\n * @class TelephoneFilter\n * @memberof PIXI.sound.filters\n */\nexport default class TelephoneFilter extends Filter\n{\n    constructor()\n    {\n        if (SoundLibrary.instance.useLegacy)\n        {\n            super(null);\n            return;\n        }\n\n        const {audioContext} = SoundLibrary.instance.context;\n        const lpf1 = audioContext.createBiquadFilter();\n        const lpf2 = audioContext.createBiquadFilter();\n        const hpf1 = audioContext.createBiquadFilter();\n        const hpf2 = audioContext.createBiquadFilter();\n\n        lpf1.type = 'lowpass';\n        WebAudioUtils.setParamValue(lpf1.frequency, 2000.0);\n\n        lpf2.type = 'lowpass';\n        WebAudioUtils.setParamValue(lpf2.frequency, 2000.0);\n\n        hpf1.type = 'highpass';\n        WebAudioUtils.setParamValue(hpf1.frequency, 500.0);\n\n        hpf2.type = 'highpass';\n        WebAudioUtils.setParamValue(hpf2.frequency, 500.0);\n\n        lpf1.connect(lpf2);\n        lpf2.connect(hpf1);\n        hpf1.connect(hpf2);\n\n        super(lpf1, hpf2);\n    }\n}\n","import {IMediaContext} from \"../interfaces/IMediaContext\";\nimport Filter from \"../filters/Filter\";\n\n/**\n * The fallback version of WebAudioContext which uses `<audio>` instead of WebAudio API.\n * @private\n * @class HTMLAudioContext\n * @extends PIXI.util.EventEmitter\n * @memberof PIXI.sound.htmlaudio\n */\nexport default class HTMLAudioContext extends PIXI.utils.EventEmitter implements IMediaContext\n{\n    /**\n     * Current global speed from 0 to 1\n     * @name PIXI.sound.htmlaudio.HTMLAudioContext#speed\n     * @type {number}\n     * @default 1\n     */\n    public speed: number;\n\n    /**\n     * Current muted status of the context\n     * @name PIXI.sound.htmlaudio.HTMLAudioContext#muted\n     * @type {boolean}\n     * @default false\n     */\n    public muted: boolean;\n\n    /**\n     * Current volume from 0 to 1\n     * @name PIXI.sound.htmlaudio.HTMLAudioContext#volume\n     * @type {number}\n     * @default 1\n     */\n    public volume: number;\n\n    /**\n     * Current paused status\n     * @name PIXI.sound.htmlaudio.HTMLAudioContext#paused\n     * @type {boolean}\n     * @default false\n     */\n    public paused: boolean;\n\n    constructor()\n    {\n        super();\n\n        this.speed = 1;\n        this.volume = 1;\n        this.muted = false;\n        this.paused = false;\n    }\n\n    /**\n     * Internal trigger when volume, mute or speed changes\n     * @method PIXI.sound.htmlaudio.HTMLAudioContext#refresh\n     * @private\n     */\n    public refresh(): void\n    {\n        this.emit('refresh');\n    }\n\n    /**\n     * Internal trigger paused changes\n     * @method PIXI.sound.htmlaudio.HTMLAudioContext#refreshPaused\n     * @private\n     */\n    public refreshPaused(): void\n    {\n        this.emit('refreshPaused');\n    }\n\n    /**\n     * HTML Audio does not support filters, this is non-functional API.\n     * @type {Array<PIXI.sound.filters.Filter>}\n     * @name PIXI.sound.htmlaudio.HTMLAudioContext#filters\n     * @default null\n     */\n    public get filters(): Filter[]\n    {\n        // @if DEBUG\n        console.warn('HTML Audio does not support filters');\n        // @endif\n        return null;\n    }\n    public set filters(filters: Filter[])\n    {\n        // @if DEBUG\n        console.warn('HTML Audio does not support filters');\n        // @endif\n    }\n\n    /**\n     * HTML Audio does not support `audioContext`\n     * @type {null}\n     * @name PIXI.sound.htmlaudio.HTMLAudioContext#audioContext\n     * @default null\n     * @readonly\n     */\n    public get audioContext(): AudioContext\n    {\n        // @if DEBUG\n        console.warn('HTML Audio does not support audioContext');\n        // @endif\n        return null;\n    }\n\n    /**\n     * Toggles the muted state.\n     * @method PIXI.sound.htmlaudio.HTMLAudioContext#toggleMute\n     * @return {boolean} The current muted state.\n     */\n    public toggleMute(): boolean\n    {\n        this.muted = !this.muted;\n        this.refresh();\n        return this.muted;\n    }\n\n    /**\n     * Toggles the paused state.\n     * @method PIXI.sound.htmlaudio.HTMLAudioContext#togglePause\n     * @return {boolean} The current paused state.\n     */\n    public togglePause(): boolean\n    {\n        this.paused = !this.paused;\n        this.refreshPaused();\n        return this.paused;\n    }\n\n    /**\n     * Destroy and don't use after this\n     * @method PIXI.sound.htmlaudio.HTMLAudioContext#destroy\n     */\n    public destroy(): void\n    {\n        this.removeAllListeners();\n    }\n}","import WebAudioMedia from \"./WebAudioMedia\";\nimport {IMediaInstance} from \"../interfaces/IMediaInstance\";\nimport {PlayOptions} from \"../Sound\";\nimport WebAudioUtils from \"./WebAudioUtils\";\n\nlet id = 0;\n\n/**\n * A single play instance that handles the AudioBufferSourceNode.\n * @private\n * @class WebAudioInstance\n * @memberof PIXI.sound.webaudio\n * @param {SoundNodes} source Reference to the SoundNodes.\n */\nexport default class WebAudioInstance extends PIXI.utils.EventEmitter implements IMediaInstance\n{\n    /**\n     * The current unique ID for this instance.\n     * @name PIXI.sound.webaudio.WebAudioInstance#id\n     * @readonly\n     */\n    public id: number;\n\n    /**\n     * The source Sound.\n     * @type {PIXI.sound.webaudio.WebAudioMedia}\n     * @name PIXI.sound.webaudio.WebAudioInstance#_media\n     * @private\n     */\n    private _media: WebAudioMedia;\n\n    /**\n     * true if paused.\n     * @type {boolean}\n     * @name PIXI.sound.webaudio.WebAudioInstance#_paused\n     * @private\n     */\n    private _paused: boolean;\n\n    /**\n     * true if muted.\n     * @type {boolean}\n     * @name PIXI.sound.webaudio.WebAudioInstance#_muted\n     * @private\n     */\n    private _muted: boolean;\n\n    /**\n     * true if paused.\n     * @type {boolean}\n     * @name PIXI.sound.webaudio.WebAudioInstance#_pausedReal\n     * @private\n     */\n    private _pausedReal: boolean;\n\n    /**\n     * The instance volume\n     * @type {number}\n     * @name PIXI.sound.webaudio.WebAudioInstance#_volume\n     * @private\n     */\n    private _volume: number;\n\n    /**\n     * Last update frame number.\n     * @type {number}\n     * @name PIXI.sound.webaudio.WebAudioInstance#_lastUpdate\n     * @private\n     */\n    private _lastUpdate: number;\n\n    /**\n     * The total number of seconds elapsed in playback.\n     * @type {number}\n     * @name PIXI.sound.webaudio.WebAudioInstance#_elapsed\n     * @private\n     */\n    private _elapsed: number;\n\n    /**\n     * Playback rate, where 1 is 100%.\n     * @type {number}\n     * @name PIXI.sound.webaudio.WebAudioInstance#_speed\n     * @private\n     */\n    private _speed: number;\n\n    /**\n     * Playback rate, where 1 is 100%.\n     * @type {number}\n     * @name PIXI.sound.webaudio.WebAudioInstance#_end\n     * @private\n     */\n    private _end: number;\n\n    /**\n     * `true` if should be looping.\n     * @type {boolean}\n     * @name PIXI.sound.webaudio.WebAudioInstance#_loop\n     * @private\n     */\n    private _loop: boolean;\n\n    /**\n     * Gain node for controlling volume of instance\n     * @type {GainNode}\n     * @name PIXI.sound.webaudio.WebAudioInstance#_gain\n     * @private\n     */\n    private _gain: GainNode;\n\n    /**\n     * Length of the sound in seconds.\n     * @type {number}\n     * @name PIXI.sound.webaudio.WebAudioInstance#_duration\n     * @private\n     */\n    private _duration: number;\n\n    /**\n     * The progress of the sound from 0 to 1.\n     * @type {number}\n     * @name PIXI.sound.webaudio.WebAudioInstance#_progress\n     * @private\n     */\n    private _progress: number;\n\n    /**\n     * Callback for update listener\n     * @type {EventListener}\n     * @name PIXI.sound.webaudio.WebAudioInstance#_updateListener\n     * @private\n     */   \n    private _updateListener: EventListener;\n\n    /**\n     * Audio buffer source clone from Sound object.\n     * @type {AudioBufferSourceNode}\n     * @name PIXI.sound.webaudio.WebAudioInstance#_source\n     * @private\n     */\n    private _source: AudioBufferSourceNode;\n\n    constructor(media: WebAudioMedia)\n    {\n        super();\n\n        this.id = id++;\n        this._media = null;\n        this._paused = false;\n        this._muted = false;\n        this._elapsed = 0;\n        this._updateListener = this._update.bind(this) as EventListener;\n\n        // Initialize\n        this.init(media);\n    }\n\n    /**\n     * Stops the instance, don't use after this.\n     * @method PIXI.sound.webaudio.WebAudioInstance#stop\n     */\n    public stop(): void\n    {\n        if (this._source)\n        {\n            this._internalStop();\n\n            /**\n             * The sound is stopped. Don't use after this is called.\n             * @event PIXI.sound.webaudio.WebAudioInstance#stop\n             */\n            this.emit(\"stop\");\n        }\n    }\n\n    /**\n     * Set the instance speed from 0 to 1\n     * @member {number} PIXI.sound.htmlaudio.HTMLAudioInstance#speed\n     */\n    public get speed(): number\n    {\n        return this._speed;\n    }\n    public set speed(speed: number)\n    {\n        this._speed = speed;\n        this.refresh();\n        this._update(true); // update progress\n    }\n\n    /**\n     * Get the set the volume for this instance from 0 to 1\n     * @member {number} PIXI.sound.htmlaudio.HTMLAudioInstance#volume\n     */\n    public get volume(): number\n    {\n        return this._volume;\n    }\n    public set volume(volume: number)\n    {\n        this._volume = volume;\n        this.refresh();\n    }\n\n    /**\n     * `true` if the sound is muted\n     * @member {boolean} PIXI.sound.htmlaudio.HTMLAudioInstance#muted\n     */\n    public get muted(): boolean\n    {\n        return this._muted;\n    }\n    public set muted(muted: boolean)\n    {\n        this._muted = muted;\n        this.refresh();\n    }\n\n    /**\n     * If the sound instance should loop playback\n     * @member {boolean} PIXI.sound.htmlaudio.HTMLAudioInstance#loop\n     */\n    public get loop(): boolean\n    {\n        return this._loop;\n    }\n    public set loop(loop: boolean)\n    {\n        this._loop = loop;\n        this.refresh();\n    }\n\n    /**\n     * Refresh loop, volume and speed based on changes to parent\n     * @method PIXI.sound.webaudio.WebAudioInstance#refresh\n     */\n    public refresh(): void\n    {\n        const global = this._media.context;\n        const sound = this._media.parent;\n\n        // Updating looping\n        this._source.loop = this._loop || sound.loop;\n\n        // Update the volume\n        const globalVolume = global.volume * (global.muted ? 0 : 1);\n        const soundVolume = sound.volume * (sound.muted ? 0 : 1);\n        const instanceVolume = this._volume * (this._muted ? 0 : 1);\n        WebAudioUtils.setParamValue(this._gain.gain, instanceVolume * soundVolume * globalVolume);\n\n        // Update the speed\n        WebAudioUtils.setParamValue(this._source.playbackRate, this._speed * sound.speed * global.speed);\n    }\n\n    /**\n     * Handle changes in paused state, either globally or sound or instance\n     * @method PIXI.sound.webaudio.WebAudioInstance#refreshPaused\n     */\n    public refreshPaused(): void\n    {\n        const global = this._media.context;\n        const sound = this._media.parent;\n\n        // Consider global and sound paused\n        const pausedReal = this._paused || sound.paused || global.paused;\n\n        if (pausedReal !== this._pausedReal)\n        {\n            this._pausedReal = pausedReal;\n\n            if (pausedReal)\n            {\n                // pause the sounds\n                this._internalStop();\n\n                /**\n                 * The sound is paused.\n                 * @event PIXI.sound.webaudio.WebAudioInstance#paused\n                 */\n                this.emit(\"paused\");\n            }\n            else\n            {\n                /**\n                 * The sound is unpaused.\n                 * @event PIXI.sound.webaudio.WebAudioInstance#resumed\n                 */\n                this.emit(\"resumed\");\n\n                // resume the playing with offset\n                this.play({\n                    start: this._elapsed % this._duration,\n                    end: this._end,\n                    speed: this._speed,\n                    loop: this._loop,\n                    volume: this._volume\n                });\n            }\n\n            /**\n             * The sound is paused or unpaused.\n             * @event PIXI.sound.webaudio.WebAudioInstance#pause\n             * @property {boolean} paused If the instance was paused or not.\n             */\n            this.emit(\"pause\", pausedReal);\n        }\n    }\n\n    /**\n     * Plays the sound.\n     * @method PIXI.sound.webaudio.WebAudioInstance#play\n     * @param {Object} options Play options\n     * @param {number} options.start The position to start playing, in seconds.\n     * @param {number} options.end The ending position in seconds.\n     * @param {number} options.speed Speed for the instance\n     * @param {boolean} options.loop If the instance is looping, defaults to sound loop\n     * @param {number} options.volume Volume of the instance\n     * @param {boolean} options.muted Muted state of instance\n     */\n    public play(options: PlayOptions): void\n    {\n        const {start, end, speed, loop, volume, muted} = options;\n\n        // @if DEBUG\n        if (end)\n        {\n            console.assert(end > start, \"End time is before start time\");\n        }\n        // @endif\n        this._paused = false;\n        const {source, gain} = this._media.nodes.cloneBufferSource();\n\n        this._source = source;\n        this._gain = gain;\n        this._speed = speed;\n        this._volume = volume;\n        this._loop = !!loop;\n        this._muted = muted;\n        this.refresh();\n\n        // WebAudio doesn't support looping when a duration is set\n        // we'll set this just for the heck of it\n        if (this.loop && end !== null)\n        {\n            // @if DEBUG\n            console.warn('Looping not support when specifying an \"end\" time');\n            // @endif\n            this.loop = false;\n        }\n        this._end = end;\n\n        const duration: number = this._source.buffer.duration;\n\n        this._duration = duration;\n        this._lastUpdate = this._now();\n        this._elapsed = start;\n        this._source.onended = this._onComplete.bind(this);\n        \n        if (end)\n        {\n            this._source.start(0, start, end - start);\n        }\n        else\n        {\n            this._source.start(0, start);\n        }\n\n        /**\n         * The sound is started.\n         * @event PIXI.sound.webaudio.WebAudioInstance#start\n         */\n        this.emit(\"start\");\n\n        // Do an update for the initial progress\n        this._update(true);\n\n        // Start handling internal ticks\n        this._enabled = true;\n    }\n\n    /**\n     * Utility to convert time in millseconds or seconds\n     * @method PIXI.sound.webaudio.WebAudioInstance#_toSec\n     * @private\n     * @param {number} [time] Time in either ms or sec\n     * @return {number} Time in seconds\n     */\n    private _toSec(time?: number): number\n    {\n        if (time > 10)\n        {\n            time /= 1000;\n        }\n        return time || 0;\n    }\n\n    /**\n     * Start the update progress.\n     * @name PIXI.sound.webaudio.WebAudioInstance#_enabled\n     * @type {boolean}\n     * @private\n     */\n    private set _enabled(enabled: boolean)\n    {\n        const script = this._media.nodes.script;\n\n        script.removeEventListener('audioprocess', this._updateListener);\n\n        if (enabled)\n        {\n            script.addEventListener('audioprocess', this._updateListener);\n        }\n    }\n\n    /**\n     * The current playback progress from 0 to 1.\n     * @type {number}\n     * @name PIXI.sound.webaudio.WebAudioInstance#progress\n     */\n    public get progress(): number\n    {\n        return this._progress;\n    }\n\n    /**\n     * Pauses the sound.\n     * @type {boolean}\n     * @name PIXI.sound.webaudio.WebAudioInstance#paused\n     */\n    public get paused(): boolean\n    {\n        return this._paused;\n    }\n\n    public set paused(paused: boolean)\n    {\n        this._paused = paused;\n        this.refreshPaused();\n    }\n\n    /**\n     * Don't use after this.\n     * @method PIXI.sound.webaudio.WebAudioInstance#destroy\n     */\n    public destroy(): void\n    {\n        this.removeAllListeners();\n        this._internalStop();\n        if (this._source)\n        {\n            this._source.disconnect();\n            this._source = null;\n        }\n        if (this._gain)\n        {\n            this._gain.disconnect();\n            this._gain = null;\n        }\n        if (this._media)\n        {\n            this._media.context.events.off('refresh', this.refresh, this);\n            this._media.context.events.off('refreshPaused', this.refreshPaused, this);\n            this._media = null;\n        }\n        this._end = null;\n        this._speed = 1;\n        this._volume = 1;\n        this._loop = false;\n        this._elapsed = 0;\n        this._duration = 0;\n        this._paused = false;\n        this._muted = false;\n        this._pausedReal = false;\n    }\n\n    /**\n     * To string method for instance.\n     * @method PIXI.sound.webaudio.WebAudioInstance#toString\n     * @return {string} The string representation of instance.\n     * @private\n     */\n    public toString(): string\n    {\n        return \"[WebAudioInstance id=\" + this.id + \"]\";\n    }\n\n    /**\n     * Get the current time in seconds.\n     * @method PIXI.sound.webaudio.WebAudioInstance#_now\n     * @private\n     * @return {number} Seconds since start of context\n     */\n    private _now(): number\n    {\n        return this._media.context.audioContext.currentTime;\n    }\n\n    /**\n     * Internal update the progress.\n     * @method PIXI.sound.webaudio.WebAudioInstance#_update\n     * @private\n     */\n    private _update(force: boolean = false): void\n    {\n        if (this._source)\n        {\n            const now: number = this._now();\n            const delta: number = now - this._lastUpdate;\n\n            if (delta > 0 || force)\n            {\n                const speed: number = this._source.playbackRate.value;\n                this._elapsed += delta * speed;\n                this._lastUpdate = now;\n                const duration: number = this._duration;\n                const progress: number = (this._elapsed % duration) / duration;\n\n                // Update the progress\n                this._progress = progress;\n\n                /**\n                 * The sound progress is updated.\n                 * @event PIXI.sound.webaudio.WebAudioInstance#progress\n                 * @property {number} progress Amount progressed from 0 to 1\n                 * @property {number} duration The total playback in seconds\n                 */\n                this.emit(\"progress\", this._progress, duration);\n            }\n        }\n    }\n\n    /**\n     * Initializes the instance.\n     * @method PIXI.sound.webaudio.WebAudioInstance#init\n     */\n    public init(media: WebAudioMedia): void\n    {\n        this._media = media;\n        media.context.events.on('refresh', this.refresh, this);\n        media.context.events.on('refreshPaused', this.refreshPaused, this);\n    }\n\n    /**\n     * Stops the instance.\n     * @method PIXI.sound.webaudio.WebAudioInstance#_internalStop\n     * @private\n     */\n    private _internalStop(): void\n    {\n        if (this._source)\n        {\n            this._enabled = false;\n            this._source.onended = null;\n            this._source.stop(0); // param needed for iOS 8 bug\n            this._source = null;\n        }\n    }\n\n    /**\n     * Callback when completed.\n     * @method PIXI.sound.webaudio.WebAudioInstance#_onComplete\n     * @private\n     */\n    private _onComplete(): void\n    {\n        if (this._source)\n        {\n            this._enabled = false;\n            this._source.onended = null;\n        }\n        this._source = null;\n        this._progress = 1;\n        this.emit(\"progress\", 1, this._duration);\n        /**\n         * The sound ends, don't use after this\n         * @event PIXI.sound.webaudio.WebAudioInstance#end\n         */\n        this.emit(\"end\", this);\n    }\n}\n","import Filterable from \"../Filterable\";\nimport Filter from \"../filters/Filter\";\nimport WebAudioContext from \"./WebAudioContext\";\nimport WebAudioUtils from \"./WebAudioUtils\";\n\n/**\n * Output for cloneing node\n * @interface PIXI.sound.SoundNodes~SourceClone\n * @property {AudioBufferSourceNode} source Cloned audio buffer source\n * @property {GainNode} gain Independent volume control\n */\nexport interface SourceClone {\n    source: AudioBufferSourceNode;\n    gain: GainNode;\n};\n\n/**\n * @private\n * @class WebAudioNodes\n * @extends PIXI.sound.Filterable\n * @private\n * @memberof PIXI.sound.webaudio\n * @param {PIXI.sound.webaudio.WebAudioContext} audioContext The audio context.\n */\nexport default class WebAudioNodes extends Filterable\n{\n    /**\n     * The buffer size for script processor\n     * @name PIXI.sound.SoundNodes.BUFFER_SIZE\n     * @type {number}\n     * @default 256\n     */\n    public static BUFFER_SIZE: number = 256;\n\n    /**\n     * Get the buffer source node\n     * @name PIXI.sound.SoundNodes#bufferSource\n     * @type {AudioBufferSourceNode}\n     * @readonly\n     */\n    public bufferSource: AudioBufferSourceNode;\n\n    /**\n     * Get the script processor node.\n     * @name PIXI.sound.SoundNodes#script\n     * @type {ScriptProcessorNode}\n     * @readonly\n     */\n    public script: ScriptProcessorNode;\n\n    /**\n     * Get the gain node\n     * @name PIXI.sound.SoundNodes#gain\n     * @type {GainNode}\n     * @readonly\n     */\n    public gain: GainNode;\n\n    /**\n     * Get the analyser node\n     * @name PIXI.sound.SoundNodes#analyser\n     * @type {AnalyserNode}\n     * @readonly\n     */\n    public analyser: AnalyserNode;\n\n    /**\n     * Reference to the SoundContext\n     * @name PIXI.sound.SoundNodes#context\n     * @type {PIXI.sound.webaudio.WebAudioContext}\n     * @readonly\n     */\n    public context: WebAudioContext;\n\n    constructor(context: WebAudioContext)\n    {\n        const audioContext: AudioContext = context.audioContext;\n\n        const bufferSource: AudioBufferSourceNode = audioContext.createBufferSource();\n        const script: ScriptProcessorNode = audioContext.createScriptProcessor(WebAudioNodes.BUFFER_SIZE);\n        const gain: GainNode = audioContext.createGain();\n        const analyser: AnalyserNode = audioContext.createAnalyser();\n\n        bufferSource.connect(analyser);\n        analyser.connect(gain);\n        gain.connect(context.destination);\n        script.connect(context.destination);\n\n        super(analyser, gain);\n\n        this.context = context;\n        this.bufferSource = bufferSource;\n        this.script = script;\n        this.gain = gain;\n        this.analyser = analyser;\n    }\n\n    /**\n     * Cleans up.\n     * @method PIXI.sound.SoundNodes#destroy\n     */\n    public destroy(): void\n    {\n        super.destroy();\n\n        this.bufferSource.disconnect();\n        this.script.disconnect();\n        this.gain.disconnect();\n        this.analyser.disconnect();\n\n        this.bufferSource = null;\n        this.script = null;\n        this.gain = null;\n        this.analyser = null;\n\n        this.context = null;\n    }\n\n    /**\n     * Clones the bufferSource. Used just before playing a sound.\n     * @method PIXI.sound.SoundNodes#cloneBufferSource\n     * @returns {PIXI.sound.SoundNodes~SourceClone} The clone AudioBufferSourceNode.\n     */\n    public cloneBufferSource(): SourceClone\n    {\n        const orig: AudioBufferSourceNode = this.bufferSource;\n        const source: AudioBufferSourceNode = this.context.audioContext.createBufferSource();\n        source.buffer = orig.buffer;\n        WebAudioUtils.setParamValue(source.playbackRate, orig.playbackRate.value);\n        source.loop = orig.loop;\n\n        const gain: GainNode = this.context.audioContext.createGain();\n        source.connect(gain);\n        gain.connect(this.destination);\n        return { source, gain };\n    }\n}\n","import * as path from \"path\";\nimport Filter from \"../filters/Filter\";\nimport WebAudioContext from \"./WebAudioContext\";\nimport WebAudioInstance from \"./WebAudioInstance\";\nimport WebAudioNodes from \"./WebAudioNodes\";\nimport SoundSprite from \"../sprites/SoundSprite\";\nimport {SoundSpriteData, SoundSprites} from \"../sprites/SoundSprite\";\nimport Sound from \"../Sound\";\nimport {IMedia} from \"../interfaces/IMedia\";\nimport {Options, PlayOptions, LoadedCallback, CompleteCallback} from \"../Sound\";\n\n/**\n * Represents a single sound element. Can be used to play, pause, etc. sound instances.\n * @private\n * @class WebAudioMedia\n * @memberof PIXI.sound.webaudio\n * @param {PIXI.sound.Sound} parent - Instance of parent Sound container\n */\nexport default class WebAudioMedia implements IMedia\n{\n    /**\n     * Reference to the parent Sound container.\n     * @name PIXI.sound.webaudio.WebAudioMedia#parent\n     * @type {PIXI.sound.Sound}\n     * @readonly\n     */\n    public parent: Sound;\n\n    /**\n     * The file buffer to load.\n     * @name PIXI.sound.webaudio.WebAudioMedia#source\n     * @type {ArrayBuffer}\n     * @readonly\n     */\n    public source: ArrayBuffer;\n\n    /**\n     * Instance of the chain builder.\n     * @name PIXI.sound.webaudio.WebAudioMedia#_nodes\n     * @type {PIXI.sound.webaudio.WebAudioNodes}\n     * @private\n     */\n    private _nodes: WebAudioNodes;\n\n    /**\n     * Instance of the source node.\n     * @name PIXI.sound.webaudio.WebAudioMedia#_source\n     * @type {AudioBufferSourceNode}\n     * @private\n     */\n    private _source: AudioBufferSourceNode;\n\n    init(parent:Sound): void\n    {\n        this.parent = parent;\n        this._nodes = new WebAudioNodes(this.context);\n        this._source = this._nodes.bufferSource;\n        this.source = parent.options.source as ArrayBuffer;\n    }\n\n    /**\n     * Destructor, safer to use `SoundLibrary.remove(alias)` to remove this sound.\n     * @private\n     * @method PIXI.sound.webaudio.WebAudioMedia#destroy\n     */\n    public destroy(): void\n    {\n        this.parent = null;\n        this._nodes.destroy();\n        this._nodes = null;\n        this._source = null;\n        this.source = null;\n    }\n\n    // Implement create\n    public create(): WebAudioInstance\n    {\n        return new WebAudioInstance(this);\n    }\n\n    // Implement context\n    public get context(): WebAudioContext\n    {\n        return this.parent.context as WebAudioContext;\n    }\n    \n    // Implement isPlayable\n    public get isPlayable(): boolean\n    {\n        return !!this._source && !!this._source.buffer;\n    }\n    \n    // Implement filters\n    public get filters(): Filter[]\n    {\n        return this._nodes.filters;\n    }\n    public set filters(filters: Filter[])\n    {\n        this._nodes.filters = filters;\n    }\n\n    // Implements duration\n    public get duration(): number\n    {\n        // @if DEBUG\n        console.assert(this.isPlayable, \"Sound not yet playable, no duration\");\n        // @endif\n        return this._source.buffer.duration;\n    }\n\n    /**\n     * Gets and sets the buffer.\n     * @name PIXI.sound.webaudio.WebAudioMedia#buffer\n     * @type {AudioBuffer}\n     */\n    public get buffer(): AudioBuffer\n    {\n        return this._source.buffer;\n    }\n    public set buffer(buffer: AudioBuffer)\n    {\n        this._source.buffer = buffer;\n    }\n\n    /**\n     * Get the current chained nodes object\n     * @private\n     * @name PIXI.sound.webaudio.WebAudioMedia#nodes\n     * @type {PIXI.sound.webaudio.WebAudioNodes}\n     */\n    public get nodes(): WebAudioNodes\n    {\n        return this._nodes;\n    }\n\n    // Implements load\n    public load(callback?: LoadedCallback): void\n    {\n        // Load from the arraybuffer, incase it was loaded outside\n        if (this.source)\n        {\n            this._decode(this.source, callback);\n        }\n        // Load from the file path\n        else if (this.parent.url)\n        {\n            this._loadUrl(callback);\n        }\n        else if (callback)\n        {\n            callback(new Error(\"sound.url or sound.source must be set\"));\n        }\n        else\n        {\n            console.error(\"sound.url or sound.source must be set\");\n        }\n    }\n\n    /**\n     * Loads a sound using XHMLHttpRequest object.\n     * @method PIXI.sound.webaudio.WebAudioMedia#_loadUrl\n     * @private\n     */\n    private _loadUrl(callback?: LoadedCallback): void\n    {\n        const request = new XMLHttpRequest();\n        const url: string = this.parent.url;\n        request.open(\"GET\", url, true);\n        request.responseType = \"arraybuffer\";\n\n        // Decode asynchronously\n        request.onload = () => {\n            this.source = request.response as ArrayBuffer;\n            this._decode(request.response, callback);\n        };\n\n        // actually start the request\n        request.send();\n    }\n\n    /**\n     * Decodes the array buffer.\n     * @method PIXI.sound.webaudio.WebAudioMedia#decode\n     * @param {ArrayBuffer} arrayBuffer From load.\n     * @private\n     */\n    private _decode(arrayBuffer: ArrayBuffer, callback?: LoadedCallback): void\n    {\n        const context = this.parent.context as WebAudioContext;\n        context.decode(arrayBuffer, (err: Error, buffer: AudioBuffer) =>\n        {\n            if (err)\n            {\n                if (callback)\n                {\n                    callback(err);\n                }\n            }\n            else\n            {\n                this.parent.isLoaded = true;\n                this.buffer = buffer;\n                const instance = this.parent.autoPlayStart();\n                if (callback)\n                {\n                    callback(null, this.parent, instance);\n                }\n            }\n        });\n    }\n}\n","import SoundLibrary from \"../SoundLibrary\";\nimport Sound from \"../Sound\";\nimport WebAudioMedia from \"../webaudio/WebAudioMedia\";\nimport WebAudioContext from \"../webaudio/WebAudioContext\";\n\nexport interface RenderOptions {\n    width?: number;\n    height?: number;\n    fill?: string|CanvasPattern|CanvasGradient;\n}\n\nexport type ExtensionMap = {[key:string]:boolean};\n\n/**\n * Utilities that work with sounds.\n * @namespace PIXI.sound.utils\n */\nexport default class SoundUtils\n{\n    /**\n     * Increment the alias for play once\n     * @static\n     * @private\n     * @default 0\n     */\n    private static PLAY_ID = 0;\n\n    /**\n     * RegExp for looking for format patterns.\n     * @static\n     * @private\n     */\n    private static FORMAT_PATTERN = /\\.(\\{([^\\}]+)\\})(\\?.*)?$/;\n\n    /**\n     * The list of extensions that can be played.\n     * @readonly\n     * @static\n     * @member {string[]} PIXI.sound.utils.extensions\n     */\n    public static extensions:string[] = [\n        \"mp3\",\n        \"ogg\",\n        \"oga\",\n        \"opus\",\n        \"mpeg\",\n        \"wav\",\n        \"m4a\",\n        \"mp4\",\n        \"aiff\",\n        \"wma\",\n        \"mid\"\n    ];\n\n    /**\n     * The list of browser supported audio formats.\n     * @readonly\n     * @static\n     * @member {Object} PIXI.sound.utils.supported\n     * @property {boolean} mp3 - `true` if file-type is supported\n     * @property {boolean} ogg - `true` if file-type is supported\n     * @property {boolean} oga - `true` if file-type is supported\n     * @property {boolean} opus - `true` if file-type is supported\n     * @property {boolean} mpeg - `true` if file-type is supported\n     * @property {boolean} wav - `true` if file-type is supported\n     * @property {boolean} mp4 - `true` if file-type is supported\n     * @property {boolean} aiff - `true` if file-type is supported\n     * @property {boolean} wma - `true` if file-type is supported\n     * @property {boolean} mid - `true` if file-type is supported\n     */\n    public static supported:ExtensionMap = function():ExtensionMap {\n        const types:{[key:string]:string} = {\n            m4a: \"mp4\",\n            oga: \"ogg\"\n        };\n        const audio = document.createElement('audio');\n        const formats:ExtensionMap = {};\n        const no = /^no$/;\n        SoundUtils.extensions.forEach(ext => {\n            const type = types[ext] || ext;\n            const canByExt = audio.canPlayType(`audio/${ext}`).replace(no, '');\n            const canByType = audio.canPlayType(`audio/${type}`).replace(no, '');\n            formats[ext] = !!canByExt || !!canByType;\n        });\n\n        return Object.freeze(formats);\n    }();\n\n    /**\n     * Resolve a URL with different formats in glob pattern to \n     * a path based on the supported browser format. For instance:\n     * \"sounds/music.{ogg,mp3}\", would resolve to \"sounds/music.ogg\"\n     * if \"ogg\" support is found, otherwise, fallback to \"sounds.music.mp3\"\n     * @method PIXI.sound.utils.resolveUrl\n     * @static\n     * @param {string|PIXI.loaders.Resource} source - Path to resolve or Resource, if\n     *        a Resource object is provided, automatically updates the extension and url\n     *        of that object.\n     * @return {string} The format to resolve to\n     */\n    public static resolveUrl(source: string|PIXI.loaders.Resource): string\n    {\n        // search for patterns like \".{mp3,ogg}\"\"\n        const glob = SoundUtils.FORMAT_PATTERN;\n        const url:string = typeof source === 'string' ? source : source.url;\n\n        if (!glob.test(url))\n        {\n            return url;\n        }\n        else\n        {\n            const match = glob.exec(url);\n            const exts = match[2].split(',');\n            let replace = exts[exts.length - 1]; // fallback to last ext\n            for (let i = 0, len = exts.length; i < len; i++)\n            {\n                const ext = exts[i];\n                if (SoundUtils.supported[ext])\n                {\n                    replace = ext;\n                    break;\n                }\n            }\n            const resolved = url.replace(match[1], replace);\n            if (!(typeof source === 'string'))\n            {\n                source.extension = replace;\n                source.url = resolved;\n            }\n            return resolved;\n        }\n    }\n\n    /**\n     * Create a new sound for a sine wave-based tone.  **Only supported with WebAudio**\n     * @method PIXI.sound.utils.sineTone\n     * @param {number} [hertz=200] Frequency of sound.\n     * @param {number} [seconds=1] Duration of sound in seconds.\n     * @return {PIXI.sound.Sound} New sound.\n     */\n    public static sineTone(hertz: number = 200, seconds: number = 1): Sound\n    {\n        const sound = Sound.from({\n            singleInstance: true,\n        });\n\n        if (!(sound.media instanceof WebAudioMedia))\n        {\n            return sound;\n        }\n\n        const media = sound.media as WebAudioMedia;\n        const context = sound.context as WebAudioContext;\n\n        // set default value\n        const nChannels = 1;\n        const sampleRate = 48000;\n        const amplitude = 2;\n\n        // create the buffer\n        const buffer = context.audioContext.createBuffer(\n            nChannels,\n            seconds * sampleRate,\n            sampleRate,\n        );\n        const fArray = buffer.getChannelData(0);\n\n        // fill the buffer\n        for (let i = 0; i < fArray.length; i++)\n        {\n            const time  = i / buffer.sampleRate;\n            const angle = hertz * time * Math.PI;\n            fArray[i] = Math.sin(angle) * amplitude;\n        }\n\n        // set the buffer\n        media.buffer = buffer;\n        sound.isLoaded = true;\n        return sound;\n    }\n\n    /**\n     * Render image as Texture. **Only supported with WebAudio**\n     * @method PIXI.sound.utils.render\n     * @param {PIXI.sound.Sound} sound Instance of sound to render\n     * @param {Object} [options] Custom rendering options\n     * @param {number} [options.width=512] Width of the render\n     * @param {number} [options.height=128] Height of the render\n     * @param {string|CanvasPattern|CanvasGradient} [options.fill='black'] Fill style for waveform\n     * @return {PIXI.Texture} Result texture\n     */\n    public static render(sound: Sound, options?: RenderOptions): PIXI.BaseTexture\n    {\n        const canvas: HTMLCanvasElement = document.createElement(\"canvas\");\n\n        options = Object.assign({\n            width: 512,\n            height: 128,\n            fill: \"black\",\n        }, options || {});\n\n        canvas.width = options.width;\n        canvas.height = options.height;\n\n        const baseTexture = PIXI.BaseTexture.fromCanvas(canvas);\n\n        if (!(sound.media instanceof WebAudioMedia))\n        {\n            return baseTexture;\n        }\n\n        const media: WebAudioMedia = sound.media as WebAudioMedia;\n\n        console.assert(!!media.buffer, \"No buffer found, load first\");        \n\n        const context: CanvasRenderingContext2D = canvas.getContext(\"2d\");\n        context.fillStyle = options.fill;\n        const data: Float32Array = media.buffer.getChannelData(0);\n        const step: number = Math.ceil(data.length / options.width);\n        const amp: number = options.height / 2;\n\n        for (let i: number = 0; i < options.width; i++)\n        {\n            let min: number = 1.0;\n            let max: number = -1.0;\n\n            for (let j: number = 0; j < step; j++)\n            {\n                const datum: number = data[(i * step) + j];\n\n                if (datum < min)\n                {\n                    min = datum;\n                }\n                if (datum > max)\n                {\n                    max = datum;\n                }\n            }\n            context.fillRect(i, (1 + min) * amp, 1, Math.max(1, (max - min) * amp));\n        }\n        return baseTexture;\n    }\n\n    /**\n     * Create a new \"Audio\" stream based on given audio path and project uri; returns the audio object.\n     * @method PIXI.sound.utils.playOnce\n     * @static\n     * @param {String} fileName Full path of the file to play.\n     * @param {Function} callback Callback when complete.\n     * @return {string} New audio element alias.\n     */\n    public static playOnce(url: string, callback?: (err?: Error) => void): string\n    {\n        const alias = `alias${SoundUtils.PLAY_ID++}`;\n\n        SoundLibrary.instance.add(alias, {\n            url,\n            preload: true,\n            autoPlay: true,\n            loaded: (err: Error) => {\n                if (err)\n                {\n                    console.error(err);\n                    SoundLibrary.instance.remove(alias);\n                    if (callback)\n                    {\n                        callback(err);\n                    }\n                }\n            },\n            complete: () => {\n                SoundLibrary.instance.remove(alias);\n                if (callback)\n                {\n                    callback(null);\n                }\n            },\n        });\n        return alias;\n    }\n}\n","import LoaderMiddleware from './LoaderMiddleware';\n\n/**\n * Loader to replace the default PIXI Loader, this will\n * provide support for auto-install `pre`, currently only the `addPixiMiddleware`\n * method only support's **resource-loader's** `use` method.\n * @namespace PIXI.sound.loader\n * @class\n * @private\n */\nexport default class Loader extends PIXI.loaders.Loader\n{\n    /**\n     * @param {string} [baseUrl=''] - The base url for all resources loaded by this loader.\n     * @param {number} [concurrency=10] - The number of resources to load concurrently.\n     */\n    constructor(baseUrl?:string, concurrency?:number)\n    {\n        super(baseUrl, concurrency);\n\n        this.use(LoaderMiddleware.plugin);\n        this.pre(LoaderMiddleware.resolve);\n    }\n\n    /**\n     * Adds a default middleware to the PixiJS loader.\n     *\n     * @static\n     * @param {Function} fn - The middleware to add.\n     */\n    static addPixiMiddleware(fn: () => void): void\n    {\n        super.addPixiMiddleware(fn);\n    }\n}\n","import SoundLibrary from \"../SoundLibrary\";\nimport SoundUtils from \"../utils/SoundUtils\";\nimport Loader from \"./Loader\";\n\n/**\n * Sound middleware installation utilities for PIXI.loaders.Loader\n * @class\n * @private\n */\nexport default class LoaderMiddleware\n{\n    /**\n     * @name PIXI.sound.loader._sound\n     * @type {PIXI.sound}\n     * @static\n     * @private\n     */\n    static _sound: SoundLibrary;\n\n    /**\n     * Install the middleware\n     * @method PIXI.sound.loader.install\n     * @param {PIXI.sound.SoundLibrary} sound - Instance of sound library\n     */\n    static install(sound:SoundLibrary)\n    {\n        LoaderMiddleware._sound = sound;\n        LoaderMiddleware.legacy = sound.useLegacy;\n\n        // Replace the PIXI.loaders.Loader class\n        // to support using the resolve loader middleware\n        PIXI.loaders.Loader = Loader;\n\n        // Install middleware on the default loader\n        PIXI.loader.use(LoaderMiddleware.plugin);\n        PIXI.loader.pre(LoaderMiddleware.resolve);\n    }\n\n    /**\n     * Set the legacy mode\n     * @name PIXI.sound.loader.legacy\n     * @type {boolean}\n     * @private\n     */\n    static set legacy(legacy:boolean)\n    {\n        // Configure PIXI Loader to handle audio files correctly\n        const Resource = PIXI.loaders.Resource;\n        const exts = SoundUtils.extensions;\n\n        // Make sure we support webaudio\n        if (!legacy)\n        {\n            // Load all audio files as ArrayBuffers\n            exts.forEach((ext) => {\n                Resource.setExtensionXhrType(ext, Resource.XHR_RESPONSE_TYPE.BUFFER);\n                Resource.setExtensionLoadType(ext, Resource.LOAD_TYPE.XHR);\n            });\n        }\n        else\n        {\n            // Fall back to loading as <audio> elements\n            exts.forEach((ext) => {\n                Resource.setExtensionXhrType(ext, Resource.XHR_RESPONSE_TYPE.DEFAULT);\n                Resource.setExtensionLoadType(ext, Resource.LOAD_TYPE.AUDIO);\n            });\n        }\n    }\n\n    /**\n     * Handle the preprocessing of file paths\n     */\n    static resolve(resource: PIXI.loaders.Resource, next: () => void): void\n    {\n        SoundUtils.resolveUrl(resource);\n        next();\n    }\n\n    /**\n     * Actual resource-loader middleware for sound class\n     */\n    static plugin(resource: PIXI.loaders.Resource, next: () => void): void\n    {\n        if (resource.data && SoundUtils.extensions.indexOf(resource.extension) > -1)\n        {\n            (resource as any).sound = LoaderMiddleware._sound.add(resource.name, {\n                loaded: next,\n                preload: true,\n                url: resource.url,\n                source: resource.data,\n            });\n        }\n        else\n        {\n            next();\n        }\n    }\n}\n","import Sound from \"../Sound\";\nimport {CompleteCallback} from \"../Sound\";\nimport {IMediaInstance} from '../interfaces/IMediaInstance';\n\n// Sound sprite data setup\nexport interface SoundSpriteData {\n    start: number;\n    end: number;\n    speed?: number;\n}\n\n// Collection of sound sprites\nexport type SoundSprites = {[id: string]: SoundSprite};\n\n/**\n * Object that represents a single Sound's sprite.\n * @class SoundSprite\n * @memberof PIXI.sound\n * @param {PIXI.sound.Sound} parent The parent sound\n * @param {Object} options Data associated with object.\n * @param {number} options.start The start time in seconds.\n * @param {number} options.end The end time in seconds.\n * @param {number} [options.speed] The optional speed, if not speed, uses\n *        the default speed of the parent.\n */\nexport default class SoundSprite\n{\n    /**\n     * The reference sound\n     * @name PIXI.sound.SoundSprite#parent\n     * @type {PIXI.sound.Sound}\n     * @readonly\n     */\n    public parent: Sound;\n\n    /**\n     * The starting location in seconds.\n     * @name PIXI.sound.SoundSprite#start\n     * @type {number}\n     * @readonly\n     */\n    public start: number;\n\n    /**\n     * The ending location in seconds\n     * @name PIXI.sound.SoundSprite#end\n     * @type {number}\n     * @readonly\n     */\n    public end: number;\n\n    /**\n     * The speed override where 1 is 100% speed playback.\n     * @name PIXI.sound.SoundSprite#speed\n     * @type {number}\n     * @readonly\n     */\n    public speed: number;\n\n    /**\n     * The duration of the sound in seconds.\n     * @name PIXI.sound.SoundSprite#duration\n     * @type {number}\n     * @readonly\n     */\n    public duration: number;\n\n    /**\n     * Constructor\n     */\n    constructor(parent: Sound, options: SoundSpriteData)\n    {\n        this.parent = parent;\n        Object.assign(this, options);\n        this.duration = this.end - this.start;\n\n        // @if DEBUG\n        console.assert(this.duration > 0, \"End time must be after start time\");\n        // @endif\n    }\n\n    /**\n     * Play the sound sprite.\n     * @method PIXI.sound.SoundSprite#play\n     * @param {PIXI.sound.Sound~completeCallback} [complete] Function call when complete\n     * @return {PIXI.sound.IMediaInstance|Promise<PIXI.sound.IMediaInstance>} Sound instance being played.\n     */\n    public play(complete?: CompleteCallback): IMediaInstance|Promise<IMediaInstance>\n    {\n        return this.parent.play(Object.assign({\n            complete,\n            speed: this.speed || this.parent.speed,\n            end: this.end,\n            start: this.start,\n        }));\n    }\n\n    /**\n     * Destroy and don't use after this\n     * @method PIXI.sound.SoundSprite#destroy\n     */\n    public destroy(): void\n    {\n        this.parent = null;\n    }\n}\n","import Filterable from \"../Filterable\";\nimport { IMediaContext } from \"../interfaces/IMediaContext\";\n\n/**\n * Main class to handle WebAudio API. There's a simple chain\n * of AudioNode elements: analyser > compressor > context.destination.\n * any filters that are added are inserted between the analyser and compressor nodes\n * @private\n * @class WebAudioContext\n * @extends PIXI.sound.Filterable\n * @memberof PIXI.sound.webaudio\n */\nexport default class WebAudioContext extends Filterable implements IMediaContext\n{\n    /**\n     * Context Compressor node\n     * @name PIXI.sound.webaudio.WebAudioContext#compressor\n     * @type {DynamicsCompressorNode}\n     * @readonly\n     */\n    public compressor: DynamicsCompressorNode;\n\n    /**\n     * Context Analyser node\n     * @name PIXI.sound.webaudio.WebAudioContext#analyser\n     * @type {AnalyserNode}\n     * @readonly\n     */\n    public analyser: AnalyserNode;\n\n    /**\n     * Global speed of all sounds\n     * @name PIXI.sound.webaudio.WebAudioContext#speed\n     * @type {number}\n     * @readonly\n     */\n    public speed: number;\n\n    /**\n     * Sets the muted state.\n     * @type {boolean}\n     * @name PIXI.sound.webaudio.WebAudioContext#muted\n     * @default false\n     */\n    public muted: boolean;\n\n    /**\n     * Sets the volume from 0 to 1.\n     * @type {number}\n     * @name PIXI.sound.webaudio.WebAudioContext#volume\n     * @default 1\n     */\n    public volume: number;\n\n    /**\n     * Handle global events\n     * @type {PIXI.utils.EventEmitter}\n     * @name PIXI.sound.webaudio.WebAudioContext#events\n     * @default 1\n     */\n    public events: PIXI.utils.EventEmitter;\n\n    /**\n     * The instance of the AudioContext for WebAudio API.\n     * @name PIXI.sound.webaudio.WebAudioContext#_ctx\n     * @type {AudioContext}\n     * @private\n     */\n    private _ctx: AudioContext;\n\n    /**\n     * The instance of the OfflineAudioContext for fast decoding audio.\n     * @name PIXI.sound.webaudio.WebAudioContext#_offlineCtx\n     * @type {OfflineAudioContext}\n     * @private\n     */\n    private _offlineCtx: OfflineAudioContext;\n\n    /**\n     * Current paused status\n     * @name PIXI.sound.webaudio.WebAudioContext#_paused\n     * @type {boolean}\n     * @private\n     * @default false\n     */\n    private _paused: boolean;\n\n    /**\n     * Indicated whether audio on iOS has been unlocked, which requires a touchend/mousedown event that plays an\n     * empty sound.\n     * @name PIXI.sound.webaudio.WebAudioContext#_unlocked\n     * @type {boolean}\n     * @private\n     */\n    private _unlocked: boolean;\n\n    constructor()\n    {\n        const ctx = new WebAudioContext.AudioContext();\n        const compressor: DynamicsCompressorNode = ctx.createDynamicsCompressor();\n        const analyser: AnalyserNode = ctx.createAnalyser();\n\n        // setup the end of the node chain\n        analyser.connect(compressor);\n        compressor.connect(ctx.destination);\n\n        super(analyser, compressor);\n\n        this._ctx = ctx;\n        this._offlineCtx = new WebAudioContext.OfflineAudioContext(1, 2, ctx.sampleRate);\n        this._unlocked = false;\n\n        this.compressor = compressor;\n        this.analyser = analyser;\n        this.events = new PIXI.utils.EventEmitter();\n\n        // Set the defaults\n        this.volume = 1;\n        this.speed = 1;\n        this.muted = false;\n        this.paused = false;\n\n        // Listen for document level clicks to unlock WebAudio. See the _unlock method.\n        if (ctx.state !== \"running\")\n        {\n            this._unlock(); // When played inside of a touch event, this will enable audio on iOS immediately.\n            this._unlock = this._unlock.bind(this);\n            document.addEventListener(\"mousedown\", this._unlock, true);\n            document.addEventListener(\"touchstart\", this._unlock, true);\n            document.addEventListener(\"touchend\", this._unlock, true);\n        }\n    }\n\n    /**\n     * Try to unlock audio on iOS. This is triggered from either WebAudio plugin setup (which will work if inside of\n     * a `mousedown` or `touchend` event stack), or the first document touchend/mousedown event. If it fails (touchend\n     * will fail if the user presses for too long, indicating a scroll event instead of a click event.\n     *\n     * Note that earlier versions of iOS supported `touchstart` for this, but iOS9 removed this functionality. Adding\n     * a `touchstart` event to support older platforms may preclude a `mousedown` even from getting fired on iOS9, so we\n     * stick with `mousedown` and `touchend`.\n     * @method PIXI.sound.webaudio.WebAudioContext#_unlock\n     * @private\n     */\n    private _unlock(): void\n    {\n        if (this._unlocked)\n        {\n            return;\n        }\n        this.playEmptySound();\n        if (this._ctx.state === \"running\")\n        {\n            document.removeEventListener(\"mousedown\", this._unlock, true);\n            document.removeEventListener(\"touchend\", this._unlock, true);\n            document.removeEventListener(\"touchstart\", this._unlock, true);\n            this._unlocked = true;\n        }\n    }\n\n    /**\n     * Plays an empty sound in the web audio context.  This is used to enable web audio on iOS devices, as they\n     * require the first sound to be played inside of a user initiated event (touch/click).\n     * @method PIXI.sound.webaudio.WebAudioContext#playEmptySound\n     */\n    public playEmptySound(): void\n    {\n        const source = this._ctx.createBufferSource();\n        source.buffer = this._ctx.createBuffer(1, 1, 22050);\n        source.connect(this._ctx.destination);\n        source.start(0, 0, 0);\n        if (source.context.state === 'suspended')\n        {\n            source.context.resume();\n        }\n    }\n\n    /**\n     * Get AudioContext class, if not supported returns `null`\n     * @name PIXI.sound.webaudio.WebAudioContext.AudioContext\n     * @type {Function}\n     * @static\n     */\n    public static get AudioContext(): typeof AudioContext\n    {\n        const win: any = window as any;\n        return (\n            win.AudioContext ||\n            win.webkitAudioContext ||\n            null\n        );\n    }\n\n    /**\n     * Get OfflineAudioContext class, if not supported returns `null`\n     * @name PIXI.sound.webaudio.WebAudioContext.OfflineAudioContext\n     * @type {Function}\n     * @static\n     */\n    public static get OfflineAudioContext(): typeof OfflineAudioContext\n    {\n        const win: any = window as any;\n        return (\n            win.OfflineAudioContext ||\n            win.webkitOfflineAudioContext ||\n            null\n        );\n    }\n\n    /**\n     * Destroy this context.\n     * @method PIXI.sound.webaudio.WebAudioContext#destroy\n     */\n    public destroy()\n    {\n        super.destroy();\n\n        const ctx: any = this._ctx as any;\n        // check if browser supports AudioContext.close()\n        if (typeof ctx.close !== \"undefined\")\n        {\n            ctx.close();\n        }\n        this.events.removeAllListeners();\n        this.analyser.disconnect();\n        this.compressor.disconnect();\n        this.analyser = null;\n        this.compressor = null;\n        this.events = null;\n        this._offlineCtx = null;\n        this._ctx = null;\n    }\n\n    /**\n     * The WebAudio API AudioContext object.\n     * @name PIXI.sound.webaudio.WebAudioContext#audioContext\n     * @type {AudioContext}\n     * @readonly\n     */\n    public get audioContext(): AudioContext\n    {\n        return this._ctx;\n    }\n\n    /**\n     * The WebAudio API OfflineAudioContext object.\n     * @name PIXI.sound.webaudio.WebAudioContext#offlineContext\n     * @type {OfflineAudioContext}\n     * @readonly\n     */\n    public get offlineContext(): OfflineAudioContext\n    {\n        return this._offlineCtx;\n    }\n\n    /**\n     * Pauses all sounds, even though we handle this at the instance\n     * level, we'll also pause the audioContext so that the \n     * time used to compute progress isn't messed up.\n     * @type {boolean}\n     * @name PIXI.sound.webaudio.WebAudioContext#paused\n     * @default false\n     */\n    public set paused(paused: boolean)\n    {\n        if (paused && this._ctx.state === \"running\")\n        {\n            (this._ctx as any).suspend();\n        }\n        else if (!paused && this._ctx.state === \"suspended\")\n        {\n            (this._ctx as any).resume();\n        }\n        this._paused = paused;\n    }\n    public get paused(): boolean\n    {\n        return this._paused;\n    }\n\n    /**\n     * Emit event when muted, volume or speed changes\n     * @method PIXI.sound.webaudio.WebAudioContext#refresh\n     * @private\n     */\n    public refresh(): void\n    {\n        this.events.emit('refresh');\n    }\n\n    /**\n     * Emit event when muted, volume or speed changes\n     * @method PIXI.sound.webaudio.WebAudioContext#refreshPaused\n     * @private\n     */\n    public refreshPaused(): void\n    {\n        this.events.emit('refreshPaused');\n    }\n\n\n    /**\n     * Toggles the muted state.\n     * @method PIXI.sound.webaudio.WebAudioContext#toggleMute\n     * @return {boolean} The current muted state.\n     */\n    public toggleMute(): boolean\n    {\n        this.muted = !this.muted;\n        this.refresh();\n        return this.muted;\n    }\n\n    /**\n     * Toggles the paused state.\n     * @method PIXI.sound.webaudio.WebAudioContext#togglePause\n     * @return {boolean} The current muted state.\n     */\n    public togglePause(): boolean\n    {\n        this.paused = !this.paused;\n        this.refreshPaused();\n        return this._paused;\n    }\n\n    /**\n     * Decode the audio data\n     * @method PIXI.sound.webaudio.WebAudioContext#decode\n     * @param {ArrayBuffer} arrayBuffer Buffer from loader\n     * @param {Function} callback When completed, error and audioBuffer are parameters.\n     */\n    public decode(arrayBuffer: ArrayBuffer, callback: (err?: Error, buffer?: AudioBuffer) => void): void\n    {\n        this._offlineCtx.decodeAudioData(\n            arrayBuffer, (buffer: AudioBuffer) => {\n                callback(null, buffer);\n            },\n            () => {\n                callback(new Error(\"Unable to decode file\"));\n            },\n        );\n    }\n}\n","import PromisePolyfill from \"promise-polyfill\";\nimport Filterable from \"./Filterable\";\nimport * as filters from \"./filters\";\nimport Filter from \"./filters/Filter\";\nimport * as htmlaudio from \"./htmlaudio\";\nimport {HTMLAudioContext} from \"./htmlaudio\";\nimport {IMediaContext} from \"./interfaces/IMediaContext\";\nimport {IMediaInstance} from \"./interfaces/IMediaInstance\";\nimport LoaderMiddleware from \"./loader/LoaderMiddleware\";\nimport {CompleteCallback, Options, PlayOptions} from \"./Sound\";\nimport Sound from \"./Sound\";\nimport SoundSprite from \"./sprites/SoundSprite\";\nimport utils from \"./utils/SoundUtils\";\nimport {WebAudioContext} from \"./webaudio\";\nimport * as webaudio from \"./webaudio\";\n\nexport type SoundMap = {[id: string]: Options|string|ArrayBuffer|HTMLAudioElement};\n\n/**\n * Contains all of the functionality for using the **pixi-sound** library.\n * This is deisnged to play audio with WebAudio and fallback to HTML5.\n * @namespace PIXI.sound\n */\n\n/**\n * @description Manages the playback of sounds.\n * @class SoundLibrary\n * @memberof PIXI.sound\n * @private\n */\nexport default class SoundLibrary\n{\n    /**\n     * Singleton instance\n     */\n    public static instance: SoundLibrary;\n\n    /**\n     * For legacy approach for Audio. Instead of using WebAudio API\n     * for playback of sounds, it will use HTML5 `<audio>` element.\n     * @name PIXI.sound#_useLegacy\n     * @type {boolean}\n     * @default false\n     * @private\n     */\n    private _useLegacy: boolean;\n\n    /**\n     * The global context to use.\n     * @name PIXI.sound#_context\n     * @type {PIXI.sound.webaudio.WebAudioContext}\n     * @private\n     */\n    private _context: IMediaContext;\n\n    /**\n     * The WebAudio specific context\n     * @name PIXI.sound#_webAudioContext\n     * @type {PIXI.sound.webaudio.WebAudioContext}\n     * @private\n     */\n    private _webAudioContext: WebAudioContext;\n\n    /**\n     * The HTML Audio (legacy) context.\n     * @name PIXI.sound#_htmlAudioContext\n     * @type {PIXI.sound.webaudio.WebAudioContext}\n     * @private\n     */\n    private _htmlAudioContext: HTMLAudioContext;\n\n    /**\n     * The map of all sounds by alias.\n     * @name PIXI.sound#_sounds\n     * @type {Object}\n     * @private\n     */\n    private _sounds: {[id: string]: Sound};\n\n    constructor()\n    {\n        this.init();\n    }\n\n    /**\n     * Re-initialize the sound library, this will\n     * recreate the AudioContext. If there's a hardware-failure\n     * call `close` and then `init`.\n     * @method PIXI.sound#init\n     * @return {PIXI.sound} Sound instance\n     */\n    public init(): SoundLibrary\n    {\n        if (this.supported)\n        {\n            this._webAudioContext = new WebAudioContext();\n        }\n        this._htmlAudioContext = new HTMLAudioContext();\n        this._sounds = {};\n        this.useLegacy = !this.supported;\n        return this;\n    }\n\n    /**\n     * The global context to use.\n     * @name PIXI.sound#context\n     * @readonly\n     * @type {PIXI.sound.IMediaContext}\n     */\n    public get context(): IMediaContext\n    {\n        return this._context;\n    }\n\n    /**\n     * Initialize the singleton of the library\n     * @method PIXI.sound.SoundLibrary.init\n     * @return {PIXI.sound}\n     */\n    public static init(): SoundLibrary\n    {\n        if (SoundLibrary.instance)\n        {\n            throw new Error(\"SoundLibrary is already created\");\n        }\n        const instance = SoundLibrary.instance = new SoundLibrary();\n\n        if (typeof Promise === \"undefined\")\n        {\n            (window as any).Promise = PromisePolyfill;\n        }\n\n        // In some cases loaders can be not included\n        // the the bundle for PixiJS, custom builds\n        if (typeof PIXI.loaders !== \"undefined\")\n        {\n            // Install the middleware to support\n            // PIXI.loader and new PIXI.loaders.Loader\n            LoaderMiddleware.install(instance);\n        }\n\n        // Remove the global namespace created by rollup\n        // makes it possible for users to opt-in to exposing\n        // the library globally\n        if (typeof (window as any).__pixiSound === \"undefined\")\n        {\n            delete (window as any).__pixiSound;\n        }\n\n        // Expose to PIXI.sound to the window PIXI object\n        const PixiJS = PIXI as any;\n\n        // Check incase sound has already used\n        if (!PixiJS.sound)\n        {\n            Object.defineProperty(PixiJS, \"sound\",\n            {\n                get() { return instance; },\n            });\n\n            Object.defineProperties(instance,\n            {\n                filters: { get() { return filters; } },\n                htmlaudio: { get() { return htmlaudio; } },\n                webaudio: { get() { return webaudio; } },\n                utils: { get() { return utils; } },\n                Sound: { get() { return Sound; } },\n                SoundSprite: { get() { return SoundSprite; } },\n                Filterable: { get() { return Filterable; } },\n                SoundLibrary: { get() { return SoundLibrary; } },\n            });\n        }\n\n        return instance;\n    }\n\n    /**\n     * Apply filters to all sounds. Can be useful\n     * for setting global planning or global effects.\n     * **Only supported with WebAudio.**\n     * @example\n     * // Adds a filter to pan all output left\n     * PIXI.sound.filtersAll = [\n     *     new PIXI.sound.filters.StereoFilter(-1)\n     * ];\n     * @name PIXI.sound#filtersAll\n     * @type {PIXI.sound.filters.Filter[]}\n     */\n    public get filtersAll(): Filter[]\n    {\n        if (!this.useLegacy)\n        {\n            return this._context.filters;\n        }\n        return [];\n    }\n    public set filtersAll(filters: Filter[])\n    {\n        if (!this.useLegacy)\n        {\n            this._context.filters = filters;\n        }\n    }\n\n    /**\n     * `true` if WebAudio is supported on the current browser.\n     * @name PIXI.sound#supported\n     * @readonly\n     * @type {boolean}\n     */\n    public get supported(): boolean\n    {\n        return WebAudioContext.AudioContext !== null;\n    }\n\n    /**\n     * Register an existing sound with the library cache.\n     * @method PIXI.sound#add\n     * @param {String} alias The sound alias reference.\n     * @param {PIXI.sound.Sound} sound Sound reference to use.\n     * @return {PIXI.sound.Sound} Instance of the Sound object.\n     */\n\n    /**\n     * Adds a new sound by alias.\n     * @method PIXI.sound#add\n     * @param {String} alias The sound alias reference.\n     * @param {ArrayBuffer|String|Object|HTMLAudioElement} options Either the path or url to the source file.\n     *        or the object of options to use.\n     * @param {String} [options.url] If `options` is an object, the source of file.\n     * @param {ArrayBuffer|HTMLAudioElement} [options.source] If sound is already preloaded, available.\n     * @param {boolean} [options.autoPlay=false] true to play after loading.\n     * @param {boolean} [options.preload=false] true to immediately start preloading.\n     * @param {boolean} [options.singleInstance=false] `true` to disallow playing multiple layered instances at once.\n     * @param {number} [options.volume=1] The amount of volume 1 = 100%.\n     * @param {number} [options.speed=1] The playback rate where 1 is 100% speed.\n     * @param {Object} [options.sprites] The map of sprite data. Where a sprite is an object\n     *        with a `start` and `end`, which are the times in seconds. Optionally, can include\n     *        a `speed` amount where 1 is 100% speed.\n     * @param {PIXI.sound.Sound~completeCallback} [options.complete=null] Global complete callback when\n     *        play is finished.\n     * @param {PIXI.sound.Sound~loadedCallback} [options.loaded=null] Call when finished loading.\n     * @return {PIXI.sound.Sound} Instance of the Sound object.\n     */\n    public add(alias: string, options: Options|string|ArrayBuffer|HTMLAudioElement|Sound): Sound;\n\n    /**\n     * Adds multiple sounds at once.\n     * @method PIXI.sound#add\n     * @param {Object} map Map of sounds to add, the key is the alias, the value is the\n     *        `string`, `ArrayBuffer`, `HTMLAudioElement` or the list of options\n     *        (see {@link PIXI.sound.add} for options).\n     * @param {Object} globalOptions The default options for all sounds.\n     *        if a property is defined, it will use the local property instead.\n     * @return {PIXI.sound.Sound} Instance to the Sound object.\n     */\n    public add(map: SoundMap, globalOptions?: Options): {[id: string]: Sound};\n\n    // Actual method\n    public add(source: string|SoundMap, sourceOptions?: Options|string|ArrayBuffer|HTMLAudioElement|Sound):\n        {[id: string]: Sound}|Sound\n    {\n        if (typeof source === \"object\")\n        {\n            const results: {[id: string]: Sound} = {};\n\n            for (const alias in source)\n            {\n                const options: Options = this._getOptions(\n                    source[alias],\n                    sourceOptions as Options,\n                );\n                results[alias] = this.add(alias, options);\n            }\n            return results;\n        }\n        else if (typeof source === \"string\")\n        {\n            // @if DEBUG\n            console.assert(!this._sounds[source], `Sound with alias ${source} already exists.`);\n            // @endif\n\n            if (sourceOptions instanceof Sound)\n            {\n                this._sounds[source] = sourceOptions;\n                return sourceOptions;\n            }\n            else\n            {\n                const options: Options = this._getOptions(sourceOptions);\n                const sound: Sound = Sound.from(options);\n                this._sounds[source] = sound;\n                return sound;\n            }\n        }\n    }\n\n    /**\n     * Internal methods for getting the options object\n     * @method PIXI.sound#_getOptions\n     * @private\n     * @param {string|ArrayBuffer|HTMLAudioElement|Object} source The source options\n     * @param {Object} [overrides] Override default options\n     * @return {Object} The construction options\n     */\n    private _getOptions(source: string|ArrayBuffer|HTMLAudioElement|Options, overrides?: Options): Options\n    {\n        let options: Options;\n\n        if (typeof source === \"string\")\n        {\n            options = { url: source };\n        }\n        else if (source instanceof ArrayBuffer || source instanceof HTMLAudioElement)\n        {\n            options = { source };\n        }\n        else\n        {\n            options = source as Options;\n        }\n        return Object.assign(options, overrides || {}) as Options;\n    }\n\n    /**\n     * Do not use WebAudio, force the use of legacy. This **must** be called before loading any files.\n     * @name PIXI.sound#useLegacy\n     * @type {boolean}\n     */\n    public get useLegacy(): boolean\n    {\n        return this._useLegacy;\n    }\n    public set useLegacy(legacy: boolean)\n    {\n        LoaderMiddleware.legacy = legacy;\n        this._useLegacy = legacy;\n\n        // Set the context to use\n        if (!legacy && this.supported)\n        {\n            this._context = this._webAudioContext;\n        }\n        else\n        {\n            this._context = this._htmlAudioContext;\n        }\n    }\n\n    /**\n     * Removes a sound by alias.\n     * @method PIXI.sound#remove\n     * @param {String} alias The sound alias reference.\n     * @return {PIXI.sound} Instance for chaining.\n     */\n    public remove(alias: string): SoundLibrary\n    {\n        this.exists(alias, true);\n        this._sounds[alias].destroy();\n        delete this._sounds[alias];\n        return this;\n    }\n\n    /**\n     * Set the global volume for all sounds. To set per-sound volume see {@link PIXI.sound#volume}.\n     * @name PIXI.sound#volumeAll\n     * @type {number}\n     */\n    public get volumeAll(): number\n    {\n        return this._context.volume;\n    }\n    public set volumeAll(volume: number)\n    {\n        this._context.volume = volume;\n        this._context.refresh();\n    }\n\n    /**\n     * Set the global speed for all sounds. To set per-sound speed see {@link PIXI.sound#speed}.\n     * @name PIXI.sound#speedAll\n     * @type {number}\n     */\n    public get speedAll(): number\n    {\n        return this._context.speed;\n    }\n    public set speedAll(speed: number)\n    {\n        this._context.speed = speed;\n        this._context.refresh();\n    }\n\n    /**\n     * Toggle paused property for all sounds.\n     * @method PIXI.sound#togglePauseAll\n     * @return {boolean} `true` if all sounds are paused.\n     */\n    public togglePauseAll(): boolean\n    {\n        return this._context.togglePause();\n    }\n\n    /**\n     * Pauses any playing sounds.\n     * @method PIXI.sound#pauseAll\n     * @return {PIXI.sound} Instance for chaining.\n     */\n    public pauseAll(): SoundLibrary\n    {\n        this._context.paused = true;\n        this._context.refresh();\n        return this;\n    }\n\n    /**\n     * Resumes any sounds.\n     * @method PIXI.sound#resumeAll\n     * @return {PIXI.sound} Instance for chaining.\n     */\n    public resumeAll(): SoundLibrary\n    {\n        this._context.paused = false;\n        this._context.refresh();\n        return this;\n    }\n\n    /**\n     * Toggle muted property for all sounds.\n     * @method PIXI.sound#toggleMuteAll\n     * @return {boolean} `true` if all sounds are muted.\n     */\n    public toggleMuteAll(): boolean\n    {\n        return this._context.toggleMute();\n    }\n\n    /**\n     * Mutes all playing sounds.\n     * @method PIXI.sound#muteAll\n     * @return {PIXI.sound} Instance for chaining.\n     */\n    public muteAll(): SoundLibrary\n    {\n        this._context.muted = true;\n        this._context.refresh();\n        return this;\n    }\n\n    /**\n     * Unmutes all playing sounds.\n     * @method PIXI.sound#unmuteAll\n     * @return {PIXI.sound} Instance for chaining.\n     */\n    public unmuteAll(): SoundLibrary\n    {\n        this._context.muted = false;\n        this._context.refresh();\n        return this;\n    }\n\n    /**\n     * Stops and removes all sounds. They cannot be used after this.\n     * @method PIXI.sound#removeAll\n     * @return {PIXI.sound} Instance for chaining.\n     */\n    public removeAll(): SoundLibrary\n    {\n        for (const alias in this._sounds)\n        {\n            this._sounds[alias].destroy();\n            delete this._sounds[alias];\n        }\n        return this;\n    }\n\n    /**\n     * Stops all sounds.\n     * @method PIXI.sound#stopAll\n     * @return {PIXI.sound} Instance for chaining.\n     */\n    public stopAll(): SoundLibrary\n    {\n        for (const alias in this._sounds)\n        {\n            this._sounds[alias].stop();\n        }\n        return this;\n    }\n\n    /**\n     * Checks if a sound by alias exists.\n     * @method PIXI.sound#exists\n     * @param {String} alias Check for alias.\n     * @return {boolean} true if the sound exists.\n     */\n    public exists(alias: string, assert: boolean= false): boolean\n    {\n        const exists = !!this._sounds[alias];\n        if (assert)\n        {\n            console.assert(exists, `No sound matching alias '${alias}'.`);\n        }\n        return exists;\n    }\n\n    /**\n     * Find a sound by alias.\n     * @method PIXI.sound#find\n     * @param {String} alias The sound alias reference.\n     * @return {PIXI.sound.Sound} Sound object.\n     */\n    public find(alias: string): Sound\n    {\n        this.exists(alias, true);\n        return this._sounds[alias];\n    }\n\n    /**\n     * Plays a sound.\n     * @method PIXI.sound#play\n     * @param {String} alias The sound alias reference.\n     * @param {String} sprite The alias of the sprite to play.\n     * @return {PIXI.sound.IMediaInstance|null} The sound instance, this cannot be reused\n     *         after it is done playing. Returns `null` if the sound has not yet loaded.\n     */\n\n    /**\n     * Plays a sound.\n     * @method PIXI.sound#play\n     * @param {String} alias The sound alias reference.\n     * @param {Object|Function} options The options or callback when done.\n     * @param {Function} [options.complete] When completed.\n     * @param {Function} [options.loaded] If not already preloaded, callback when finishes load.\n     * @param {number} [options.start=0] Start time offset.\n     * @param {number} [options.end] End time offset.\n     * @param {number} [options.speed] Override default speed, default to the Sound's speed setting.\n     * @param {boolean} [options.loop] Override default loop, default to the Sound's loop setting.\n     * @return {PIXI.sound.IMediaInstance|Promise<PIXI.sound.IMediaInstance>} The sound instance,\n     *        this cannot be reused after it is done playing. Returns a Promise if the sound\n     *        has not yet loaded.\n     */\n    public play(alias: string, options?: PlayOptions|CompleteCallback|string): IMediaInstance|Promise<IMediaInstance>\n    {\n        return this.find(alias).play(options);\n    }\n\n    /**\n     * Stops a sound.\n     * @method PIXI.sound#stop\n     * @param {String} alias The sound alias reference.\n     * @return {PIXI.sound.Sound} Sound object.\n     */\n    public stop(alias: string): Sound\n    {\n        return this.find(alias).stop();\n    }\n\n    /**\n     * Pauses a sound.\n     * @method PIXI.sound#pause\n     * @param {String} alias The sound alias reference.\n     * @return {PIXI.sound.Sound} Sound object.\n     */\n    public pause(alias: string): Sound\n    {\n        return this.find(alias).pause();\n    }\n\n    /**\n     * Resumes a sound.\n     * @method PIXI.sound#resume\n     * @param {String} alias The sound alias reference.\n     * @return {PIXI.sound} Instance for chaining.\n     */\n    public resume(alias: string): Sound\n    {\n        return this.find(alias).resume();\n    }\n\n    /**\n     * Get or set the volume for a sound.\n     * @method PIXI.sound#volume\n     * @param {String} alias The sound alias reference.\n     * @param {number} [volume] Optional current volume to set.\n     * @return {number} The current volume.\n     */\n    public volume(alias: string, volume?: number): number\n    {\n        const sound = this.find(alias);\n        if (volume !== undefined) {\n            sound.volume = volume;\n        }\n        return sound.volume;\n    }\n\n    /**\n     * Get or set the speed for a sound.\n     * @method PIXI.sound#speed\n     * @param {String} alias The sound alias reference.\n     * @param {number} [speed] Optional current speed to set.\n     * @return {number} The current speed.\n     */\n    public speed(alias: string, speed?: number): number\n    {\n        const sound = this.find(alias);\n        if (speed !== undefined) {\n            sound.speed = speed;\n        }\n        return sound.speed;\n    }\n\n    /**\n     * Get the length of a sound in seconds.\n     * @method PIXI.sound#duration\n     * @param {String} alias The sound alias reference.\n     * @return {number} The current duration in seconds.\n     */\n    public duration(alias: string): number\n    {\n        return this.find(alias).duration;\n    }\n\n    /**\n     * Closes the sound library. This will release/destroy\n     * the AudioContext(s). Can be used safely if you want to\n     * initialize the sound library later. Use `init` method.\n     * @method PIXI.sound#close\n     * @return {PIXI.sound}\n     */\n    public close(): SoundLibrary\n    {\n        this.removeAll();\n        this._sounds = null;\n        if (this._webAudioContext)\n        {\n            this._webAudioContext.destroy();\n            this._webAudioContext = null;\n        }\n        if (this._htmlAudioContext)\n        {\n            this._htmlAudioContext.destroy();\n            this._htmlAudioContext = null;\n        }\n        this._context = null;\n        return this;\n    }\n}\n","import Filter from \"./filters/Filter\";\nimport HTMLAudioMedia from \"./htmlaudio/HTMLAudioMedia\";\nimport {IMedia} from \"./interfaces/IMedia\";\nimport {IMediaContext} from \"./interfaces/IMediaContext\";\nimport {IMediaInstance} from \"./interfaces/IMediaInstance\";\nimport SoundLibrary from \"./SoundLibrary\";\nimport SoundSprite from \"./sprites/SoundSprite\";\nimport {SoundSpriteData, SoundSprites} from \"./sprites/SoundSprite\";\nimport SoundUtils from \"./utils/SoundUtils\";\nimport WebAudioMedia from \"./webaudio/WebAudioMedia\";\n\n// Constructor options\nexport interface Options {\n    autoPlay?: boolean;\n    preaload?: boolean;\n    singleInstance?: boolean;\n    volume?: number;\n    speed?: number;\n    complete?: CompleteCallback;\n    loaded?: LoadedCallback;\n    preload?: boolean;\n    loop?: boolean;\n    url?: string;\n    source?: ArrayBuffer|HTMLAudioElement;\n    sprites?: {[id: string]: SoundSpriteData};\n}\n\n// Interface for play options\nexport interface PlayOptions {\n    start?: number;\n    end?: number;\n    speed?: number;\n    loop?: boolean;\n    volume?: number;\n    sprite?: string;\n    muted?: boolean;\n    complete?: CompleteCallback;\n    loaded?: LoadedCallback;\n}\n\n/**\n * Callback when sound is loaded.\n * @callback PIXI.sound.Sound~loadedCallback\n * @param {Error} err The callback error.\n * @param {PIXI.sound.Sound} sound The instance of new sound.\n * @param {PIXI.sound.IMediaInstance} instance The instance of auto-played sound.\n */\nexport declare type LoadedCallback = (err: Error, sound?: Sound, instance?: IMediaInstance) => void;\n\n/**\n * Callback when sound is completed.\n * @callback PIXI.sound.Sound~completeCallback\n * @param {PIXI.sound.Sound} sound The instance of sound.\n */\nexport declare type CompleteCallback = (sound: Sound) => void;\n\n/**\n * Sound represents a single piece of loaded media. When playing a sound {@link PIXI.sound.IMediaInstance} objects\n * are created. Properties such a `volume`, `pause`, `mute`, `speed`, etc will have an effect on all instances.\n * @class Sound\n * @memberof PIXI.sound\n */\nexport default class Sound\n{\n    /**\n     * Pool of instances\n     * @name PIXI.sound.Sound#_pool\n     * @type {Array<IMediaInstance>}\n     * @private\n     */\n    private static _pool: IMediaInstance[] = [];\n\n    /**\n     * `true` if the buffer is loaded.\n     * @name PIXI.sound.Sound#isLoaded\n     * @type {boolean}\n     * @default false\n     */\n    public isLoaded: boolean;\n\n    /**\n     * `true` if the sound is currently being played.\n     * @name PIXI.sound.Sound#isPlaying\n     * @type {boolean}\n     * @default false\n     * @readonly\n     */\n    public isPlaying: boolean;\n\n    /**\n     * true to start playing immediate after load.\n     * @name PIXI.sound.Sound#autoPlay\n     * @type {boolean}\n     * @default false\n     * @readonly\n     */\n    public autoPlay: boolean;\n\n    /**\n     * `true` to disallow playing multiple layered instances at once.\n     * @name PIXI.sound.Sound#singleInstance\n     * @type {boolean}\n     * @default false\n     */\n    public singleInstance: boolean;\n\n    /**\n     * `true` to immediately start preloading.\n     * @name PIXI.sound.Sound#preload\n     * @type {boolean}\n     * @default false\n     * @readonly\n     */\n    public preload: boolean;\n\n    /**\n     * The file source to load.\n     * @name PIXI.sound.Sound#url\n     * @type {String}\n     * @readonly\n     */\n    public url: string;\n\n    /**\n     * The constructor options.\n     * @name PIXI.sound.Sound#options\n     * @type {Object}\n     * @readonly\n     */\n    public options: Options;\n\n    /**\n     * The audio source\n     * @name PIXI.sound.Sound#media\n     * @type {PIXI.sound.IMedia}\n     * @private\n     */\n    public media: IMedia;\n\n    /**\n     * The collection of instances being played.\n     * @name PIXI.sound.Sound#_instances\n     * @type {Array<IMediaInstance>}\n     * @private\n     */\n    private _instances: IMediaInstance[];\n\n    /**\n     * Reference to the sound context.\n     * @name PIXI.sound.Sound#_sprites\n     * @type {SoundContext}\n     * @private\n     */\n    private _sprites: SoundSprites;\n\n    /**\n     * The options when auto-playing.\n     * @name PIXI.sound.Sound#_autoPlayOptions\n     * @type {PlayOptions}\n     * @private\n     */\n    private _autoPlayOptions: PlayOptions;\n\n    /**\n     * The internal volume.\n     * @name PIXI.sound.Sound#_volume\n     * @type {number}\n     * @private\n     */\n    private _volume: number;\n\n    /**\n     * The internal paused state.\n     * @name PIXI.sound.Sound#_paused\n     * @type {boolean}\n     * @private\n     */\n    private _paused: boolean;\n\n    /**\n     * The internal muted state.\n     * @name PIXI.sound.Sound#_muted\n     * @type {boolean}\n     * @private\n     */\n    private _muted: boolean;\n\n    /**\n     * The internal volume.\n     * @name PIXI.sound.Sound#_loop\n     * @type {boolean}\n     * @private\n     */\n    private _loop: boolean;\n\n    /**\n     * The internal playbackRate\n     * @name PIXI.sound.Sound#_speed\n     * @type {number}\n     * @private\n     */\n    private _speed: number;\n\n    /**\n     * Create a new sound instance from source.\n     * @method PIXI.sound.Sound.from\n     * @param {ArrayBuffer|String|Object|HTMLAudioElement} options Either the path or url to the source file.\n     *        or the object of options to use.\n     * @param {String} [options.url] If `options` is an object, the source of file.\n     * @param {HTMLAudioElement|ArrayBuffer} [options.source] The source, if already preloaded.\n     * @param {boolean} [options.autoPlay=false] true to play after loading.\n     * @param {boolean} [options.preload=false] true to immediately start preloading.\n     * @param {boolean} [options.singleInstance=false] `true` to disallow playing multiple layered instances at once.\n     * @param {number} [options.volume=1] The amount of volume 1 = 100%.\n     * @param {number} [options.speed=1] The playback rate where 1 is 100% speed.\n     * @param {Object} [options.sprites] The map of sprite data. Where a sprite is an object\n     *        with a `start` and `end`, which are the times in seconds. Optionally, can include\n     *        a `speed` amount where 1 is 100% speed.\n     * @param {PIXI.sound.Sound~completeCallback} [options.complete=null] Global complete callback\n     *        when play is finished.\n     * @param {PIXI.sound.Sound~loadedCallback} [options.loaded=null] Call when finished loading.\n     * @param {boolean} [options.loop=false] true to loop the audio playback.\n     * @return {PIXI.sound.Sound} Created sound instance.\n     */\n    public static from(source: string|Options|ArrayBuffer|HTMLAudioElement): Sound\n    {\n        let options: Options = {};\n\n        if (typeof source === \"string\")\n        {\n            options.url = source as string;\n        }\n        else if (source instanceof ArrayBuffer || source instanceof HTMLAudioElement)\n        {\n            options.source = source;\n        }\n        else\n        {\n            options = source;\n        }\n\n        // Default settings\n        options = Object.assign({\n            autoPlay: false,\n            singleInstance: false,\n            url: null,\n            source: null,\n            preload: false,\n            volume: 1,\n            speed: 1,\n            complete: null,\n            loaded: null,\n            loop: false,\n        }, options);\n\n        // Resolve url in-case it has a special format\n        if (options.url)\n        {\n            options.url = SoundUtils.resolveUrl(options.url);\n        }\n\n        Object.freeze(options);\n\n        const media: IMedia = SoundLibrary.instance.useLegacy ?\n            new HTMLAudioMedia() :\n            new WebAudioMedia();\n\n        return new Sound(media, options);\n    }\n\n    /**\n     * Constructor, use `PIXI.sound.Sound.from`\n     * @private\n     */\n    constructor(media: IMedia, options: Options)\n    {\n        this.media = media;\n        this.options = options;\n        this._instances = [];\n        this._sprites = {};\n\n        this.media.init(this);\n\n        const complete = options.complete;\n        this._autoPlayOptions = complete ? { complete } : null;\n        this.isLoaded = false;\n        this.isPlaying = false;\n        this.autoPlay = options.autoPlay;\n        this.singleInstance = options.singleInstance;\n        this.preload = options.preload || this.autoPlay;\n        this.url = options.url;\n        this.speed = options.speed;\n        this.volume = options.volume;\n        this.loop = options.loop;\n\n        if (options.sprites)\n        {\n            this.addSprites(options.sprites);\n        }\n\n        if (this.preload)\n        {\n            this._preload(options.loaded);\n        }\n    }\n\n    /**\n     * Instance of the media context\n     * @name PIXI.sound.Sound#context\n     * @type {PIXI.sound.IMediaContext}\n     * @readonly\n     */\n    public get context(): IMediaContext\n    {\n        return SoundLibrary.instance.context;\n    }\n\n    /**\n     * Stops all the instances of this sound from playing.\n     * @method PIXI.sound.Sound#pause\n     * @return {PIXI.sound.Sound} Instance of this sound.\n     */\n    public pause(): Sound\n    {\n        this.isPlaying = false;\n        this.paused = true;\n        return this;\n    }\n\n    /**\n     * Resuming all the instances of this sound from playing\n     * @method PIXI.sound.Sound#resume\n     * @return {PIXI.sound.Sound} Instance of this sound.\n     */\n    public resume(): Sound\n    {\n        this.isPlaying = this._instances.length > 0;\n        this.paused = false;\n        return this;\n    }\n\n    /**\n     * Stops all the instances of this sound from playing.\n     * @name PIXI.sound.Sound#paused\n     * @type {boolean}\n     * @readonly\n     */\n    public get paused(): boolean\n    {\n        return this._paused;\n    }\n    public set paused(paused: boolean)\n    {\n        this._paused = paused;\n        this.refreshPaused();\n    }\n\n    /**\n     * The playback rate\n     * @name PIXI.sound.Sound#speed\n     * @type {number}\n     */\n    public get speed(): number\n    {\n        return this._speed;\n    }\n    public set speed(speed: number)\n    {\n        this._speed = speed;\n        this.refresh();\n    }\n\n    /**\n     * Set the filters. Only supported with WebAudio.\n     * @name PIXI.sound.Sound#filters\n     * @type {Array<PIXI.sound.filters.Filter>}\n     */\n    public get filters(): Filter[]\n    {\n        return this.media.filters;\n    }\n    public set filters(filters: Filter[])\n    {\n        this.media.filters = filters;\n    }\n\n    /**\n     * Add a sound sprite, which is a saved instance of a longer sound.\n     * Similar to an image spritesheet.\n     * @method PIXI.sound.Sound#addSprites\n     * @param {String} alias The unique name of the sound sprite.\n     * @param {object} data Either completed function or play options.\n     * @param {number} data.start Time when to play the sound in seconds.\n     * @param {number} data.end Time to end playing in seconds.\n     * @param {number} [data.speed] Override default speed, default to the Sound's speed setting.\n     * @return {PIXI.sound.SoundSprite} Sound sprite result.\n     */\n    public addSprites(alias: string, data: SoundSpriteData): SoundSprite;\n\n    /**\n     * Convenience method to add more than one sprite add a time.\n     * @method PIXI.sound.Sound#addSprites\n     * @param {Object} data Map of sounds to add where the key is the alias,\n     *        and the data are configuration options, see {@PIXI.sound.Sound#addSprite} for info on data.\n     * @return {Object} The map of sound sprites added.\n     */\n    public addSprites(sprites: {[id: string]: SoundSpriteData}): SoundSprites;\n\n    // Actual implementation\n    public addSprites(source: string|{[id: string]: SoundSpriteData}, data?: SoundSpriteData): SoundSprite|SoundSprites\n    {\n        if (typeof source === \"object\")\n        {\n            const results: SoundSprites = {};\n            for (const alias in source)\n            {\n                results[alias] = this.addSprites(alias, source[alias]);\n            }\n            return results;\n        }\n        else if (typeof source === \"string\")\n        {\n            console.assert(!this._sprites[source], `Alias ${source} is already taken`);\n            const sprite = new SoundSprite(this, data);\n            this._sprites[source] = sprite;\n            return sprite;\n        }\n    }\n\n    /**\n     * Destructor, safer to use `SoundLibrary.remove(alias)` to remove this sound.\n     * @method PIXI.sound.Sound#destroy\n     */\n    public destroy(): void\n    {\n        this._removeInstances();\n        this.removeSprites();\n        this.media.destroy();\n        this.media = null;\n        this._sprites = null;\n        this._instances = null;\n    }\n\n    /**\n     * Remove all sound sprites.\n     * @method PIXI.sound.Sound#removeSprites\n     * @return {PIXI.sound.Sound} Sound instance for chaining.\n     */\n\n    /**\n     * Remove a sound sprite.\n     * @method PIXI.sound.Sound#removeSprites\n     * @param {String} alias The unique name of the sound sprite.\n     * @return {PIXI.sound.Sound} Sound instance for chaining.\n     */\n    public removeSprites(alias?: string): Sound\n    {\n        if (!alias)\n        {\n            for (const name in this._sprites)\n            {\n                this.removeSprites(name);\n            }\n        }\n        else\n        {\n            const sprite: SoundSprite = this._sprites[alias];\n\n            if (sprite !== undefined)\n            {\n                sprite.destroy();\n                delete this._sprites[alias];\n            }\n        }\n        return this;\n    }\n\n    /**\n     * If the current sound is playable (loaded).\n     * @name PIXI.sound.Sound#isPlayable\n     * @type {boolean}\n     * @readonly\n     */\n    public get isPlayable(): boolean\n    {\n        return this.isLoaded && this.media && this.media.isPlayable;\n    }\n\n    /**\n     * Stops all the instances of this sound from playing.\n     * @method PIXI.sound.Sound#stop\n     * @return {PIXI.sound.Sound} Instance of this sound.\n     */\n    public stop(): Sound\n    {\n        if (!this.isPlayable)\n        {\n            this.autoPlay = false;\n            this._autoPlayOptions = null;\n            return this;\n        }\n        this.isPlaying = false;\n\n        // Go in reverse order so we don't skip items\n        for (let i = this._instances.length - 1; i >= 0; i--)\n        {\n            this._instances[i].stop();\n        }\n        return this;\n    }\n\n    /**\n     * Play a sound sprite, which is a saved instance of a longer sound.\n     * Similar to an image spritesheet.\n     * @method PIXI.sound.Sound#play\n     * @param {String} alias The unique name of the sound sprite.\n     * @param {object} data Either completed function or play options.\n     * @param {number} data.start Time when to play the sound in seconds.\n     * @param {number} data.end Time to end playing in seconds.\n     * @param {number} [data.speed] Override default speed, default to the Sound's speed setting.\n     * @param {PIXI.sound.Sound~completeCallback} [callback] Callback when completed.\n     * @return {PIXI.sound.IMediaInstance|Promise<PIXI.sound.IMediaInstance>} The sound instance,\n     *        this cannot be reused after it is done playing. Returns a Promise if the sound\n     *        has not yet loaded.\n     */\n    public play(alias: string, callback?: CompleteCallback): IMediaInstance|Promise<IMediaInstance>;\n\n    /**\n     * Plays the sound.\n     * @method PIXI.sound.Sound#play\n     * @param {PIXI.sound.Sound~completeCallback|object} options Either completed function or play options.\n     * @param {number} [options.start=0] Time when to play the sound in seconds.\n     * @param {number} [options.end] Time to end playing in seconds.\n     * @param {String} [options.sprite] Play a named sprite. Will override end, start and speed options.\n     * @param {number} [options.speed] Override default speed, default to the Sound's speed setting.\n     * @param {number} [options.volume] Current volume amount for instance.\n     * @param {boolean} [options.muted] Override default muted, default to the Sound's muted setting.\n     * @param {boolean} [options.loop] Override default loop, default to the Sound's loop setting.\n     * @param {PIXI.sound.Sound~completeCallback} [options.complete] Callback when complete.\n     * @param {PIXI.sound.Sound~loadedCallback} [options.loaded] If the sound isn't already preloaded, callback when\n     *        the audio has completely finished loading and decoded.\n     * @return {PIXI.sound.IMediaInstance|Promise<PIXI.sound.IMediaInstance>} The sound instance,\n     *        this cannot be reused after it is done playing. Returns a Promise if the sound\n     *        has not yet loaded.\n     */\n    public play(source?: string|PlayOptions|CompleteCallback,\n                callback?: CompleteCallback): IMediaInstance|Promise<IMediaInstance>;\n\n    // Overloaded function\n    public play(source?: any, complete?: CompleteCallback): IMediaInstance|Promise<IMediaInstance>\n    {\n        let options: PlayOptions;\n\n        if (typeof source === \"string\")\n        {\n            const sprite: string = source as string;\n            options = { sprite, complete };\n        }\n        else if (typeof source === \"function\")\n        {\n            options = {};\n            options.complete = source as CompleteCallback;\n        }\n        else\n        {\n            options = source as PlayOptions;\n        }\n\n        options = Object.assign({\n            complete: null,\n            loaded: null,\n            sprite: null,\n            end: null,\n            start: 0,\n            volume: 1,\n            speed: 1,\n            muted: false,\n            loop: false,\n        }, options || {});\n\n        // A sprite is specified, add the options\n        if (options.sprite)\n        {\n            const alias: string = options.sprite;\n            // @if DEBUG\n            console.assert(!!this._sprites[alias], `Alias ${alias} is not available`);\n            // @endif\n            const sprite: SoundSprite = this._sprites[alias];\n            options.start = sprite.start;\n            options.end = sprite.end;\n            options.speed = sprite.speed || 1;\n            delete options.sprite;\n        }\n\n        // @deprecated offset option\n        if ((options as any).offset) {\n            options.start = (options as any).offset as number;\n        }\n\n        // if not yet playable, ignore\n        // - usefull when the sound download isnt yet completed\n        if (!this.isLoaded)\n        {\n            return new Promise<IMediaInstance>((resolve, reject) =>\n            {\n                this.autoPlay = true;\n                this._autoPlayOptions = options;\n                this._preload((err: Error, sound: Sound, instance: IMediaInstance) =>\n                {\n                    if (err)\n                    {\n                        reject(err);\n                    }\n                    else\n                    {\n                        if (options.loaded)\n                        {\n                            options.loaded(err, sound, instance);\n                        }\n                        resolve(instance);\n                    }\n                });\n            });\n        }\n\n        // Stop all sounds\n        if (this.singleInstance)\n        {\n            this._removeInstances();\n        }\n\n        // clone the bufferSource\n        const instance = this._createInstance();\n        this._instances.push(instance);\n        this.isPlaying = true;\n        instance.once(\"end\", () => {\n            if (options.complete)\n            {\n                options.complete(this);\n            }\n            this._onComplete(instance);\n        });\n        instance.once(\"stop\", () => {\n            this._onComplete(instance);\n        });\n\n        instance.play(options);\n\n        return instance;\n    }\n\n    /**\n     * Internal only, speed, loop, volume change occured.\n     * @method refresh\n     * @private\n     */\n    public refresh(): void\n    {\n        const len = this._instances.length;\n        for (let i = 0; i < len; i++)\n        {\n            this._instances[i].refresh();\n        }\n    }\n\n    /**\n     * Handle changes in paused state. Internal only.\n     * @method refreshPaused\n     * @private\n     */\n    public refreshPaused(): void\n    {\n        const len = this._instances.length;\n        for (let i = 0; i < len; i++)\n        {\n            this._instances[i].refreshPaused();\n        }\n    }\n\n    /**\n     * Gets and sets the volume.\n     * @name PIXI.sound.Sound#volume\n     * @type {number}\n     */\n    public get volume(): number\n    {\n        return this._volume;\n    }\n    public set volume(volume: number)\n    {\n        this._volume = volume;\n        this.refresh();\n    }\n\n    /**\n     * Gets and sets the muted flag.\n     * @name PIXI.sound.Sound#muted\n     * @type {number}\n     */\n    public get muted(): boolean\n    {\n        return this._muted;\n    }\n    public set muted(muted: boolean)\n    {\n        this._muted = muted;\n        this.refresh();\n    }\n\n    /**\n     * Gets and sets the looping.\n     * @name PIXI.sound.Sound#loop\n     * @type {boolean}\n     */\n    public get loop(): boolean\n    {\n        return this._loop;\n    }\n    public set loop(loop: boolean)\n    {\n        this._loop = loop;\n        this.refresh();\n    }\n\n    /**\n     * Starts the preloading of sound.\n     * @method PIXI.sound.Sound#_preload\n     * @private\n     */\n    private _preload(callback?: LoadedCallback): void\n    {\n        this.media.load(callback);\n    }\n\n    /**\n     * Gets the list of instances that are currently being played of this sound.\n     * @name PIXI.sound.Sound#instances\n     * @type {Array<PIXI.sound.IMediaInstance>}\n     * @readonly\n     */\n    public get instances(): IMediaInstance[]\n    {\n        return this._instances;\n    }\n\n    /**\n     * Get the map of sprites.\n     * @name PIXI.sound.Sound#sprites\n     * @type {Object}\n     * @readonly\n     */\n    public get sprites(): SoundSprites\n    {\n        return this._sprites;\n    }\n\n    /**\n     * Get the duration of the audio in seconds.\n     * @name PIXI.sound.Sound#duration\n     * @type {number}\n     */\n    public get duration(): number\n    {\n        return this.media.duration;\n    }\n\n    /**\n     * Auto play the first instance.\n     * @method PIXI.sound.Sound#autoPlayStart\n     * @private\n     */\n    public autoPlayStart(): IMediaInstance\n    {\n        let instance: IMediaInstance;\n        if (this.autoPlay)\n        {\n            instance = this.play(this._autoPlayOptions) as IMediaInstance;\n        }\n        return instance;\n    }\n\n    /**\n     * Removes all instances.\n     * @method PIXI.sound.Sound#_removeInstances\n     * @private\n     */\n    private _removeInstances(): void\n    {\n        // destroying also stops\n        for (let i = this._instances.length - 1; i >= 0; i--)\n        {\n            this._poolInstance(this._instances[i]);\n        }\n        this._instances.length = 0;\n    }\n\n    /**\n     * Sound instance completed.\n     * @method PIXI.sound.Sound#_onComplete\n     * @private\n     * @param {PIXI.sound.IMediaInstance} instance\n     */\n    private _onComplete(instance: IMediaInstance): void\n    {\n        if (this._instances)\n        {\n            const index = this._instances.indexOf(instance);\n            if (index > -1)\n            {\n                this._instances.splice(index, 1);\n            }\n            this.isPlaying = this._instances.length > 0;\n        }\n        this._poolInstance(instance);\n    }\n\n    /**\n     * Create a new instance.\n     * @method PIXI.sound.Sound#_createInstance\n     * @private\n     * @return {PIXI.sound.IMediaInstance} New instance to use\n     */\n    private _createInstance(): IMediaInstance\n    {\n        if (Sound._pool.length > 0)\n        {\n            const instance: IMediaInstance = Sound._pool.pop();\n            instance.init(this.media);\n            return instance;\n        }\n        return this.media.create();\n    }\n\n    /**\n     * Destroy/recycling the instance object.\n     * @method PIXI.sound.Sound#_poolInstance\n     * @private\n     * @param {PIXI.sound.IMediaInstance} instance - Instance to recycle\n     */\n    private _poolInstance(instance: IMediaInstance): void\n    {\n        instance.destroy();\n        // Add it if it isn't already added\n        if (Sound._pool.indexOf(instance) < 0)\n        {\n            Sound._pool.push(instance);\n        }\n    }\n}\n","/**\n * Global namespace provided by the PixiJS project.\n * @namespace PIXI\n * @see https://github.com/pixijs/pixi.js\n */\nexport { default as Filterable } from \"./Filterable\";\nexport { default as Sound } from \"./Sound\";\nexport { default as SoundLibrary } from \"./SoundLibrary\";\nexport { default as SoundSprite } from \"./sprites/SoundSprite\";\nexport { default as utils } from \"./utils/SoundUtils\";\n\nimport SoundLibrary from \"./SoundLibrary\";\nexport const sound = SoundLibrary.init();\n\nimport * as filters from \"./filters\";\nexport { filters };\n\nimport * as htmlaudio from \"./htmlaudio\";\nexport { htmlaudio };\n\nimport * as webaudio from \"./webaudio\";\nexport { webaudio };\n"],"names":["input","output","this","_output","_input","Object","Filterable","_filters","filters","forEach","filter","disconnect","connect","length","slice","prevFilter_1","_this","destination","id","parent","_super","init","tslib_1.__extends","HTMLAudioInstance","_duration","_paused","paused","refreshPaused","_playing","media","source","duration","_source","cloneNode","src","url","onplay","_onPlay","bind","onpause","_onPause","context","on","refresh","_media","onended","pause","_internalStop","emit","_speed","speed","_volume","volume","_loop","loop","_muted","muted","global","sound","globalVolume","soundVolume","instanceVolume","playbackRate","pausedReal","_pausedReal","play","start","currentTime","end","_end","options","console","assert","warn","_start","Math","max","PADDING","min","onloadedmetadata","PIXI","ticker","shared","add","_onUpdate","_onComplete","progress","remove","removeAllListeners","off","utils","EventEmitter","HTMLAudioMedia","Audio","readyState","load","callback","isLoaded","instance_1","autoPlayStart","setTimeout","Error","removeListeners","removeEventListener","onLoad","onAbort","onError","instance","message","error","code","addEventListener","root","noop","fn","thisArg","apply","arguments","Promise","TypeError","_state","_handled","_value","undefined","_deferreds","doResolve","handle","self","deferred","push","_immediateFn","cb","onFulfilled","onRejected","resolve","reject","promise","ret","e","newValue","then","finale","_unhandledRejectionFn","i","len","Handler","done","value","reason","ex","setTimeoutFunc","prototype","prom","all","arr","res","val","call","args","remaining","Array","constructor","race","values","setImmediate","err","_setImmediateFn","_setUnhandledRejectionFn","module","exports","Filter","WebAudioUtils","param","setValueAtTime","SoundLibrary","audioContext","f32","f64","f125","f250","f500","f1k","f2k","f4k","f8k","f16k","useLegacy","bands","f","EqualizerFilter","F32","type","gain","F64","F125","F250","F500","F1K","F2K","F4K","F8K","F16K","map","band","createBiquadFilter","setParamValue","Q","frequency","bandsMap","node","getGain","setGain","amount","distortion","createWaveShaper","_distortion","DistortionFilter","_amount","x","curve","Float32Array","deg","PI","abs","oversample","destroy","pan","stereo","panner","createStereoPanner","createPanner","panningModel","_stereo","_panner","StereoFilter","_pan","setPosition","seconds","decay","reverse","convolver","createConvolver","_convolver","_seconds","_clamp","_decay","_reverse","_rebuild","ReverbFilter","n","rate","sampleRate","impulse","createBuffer","impulseL","getChannelData","impulseR","random","pow","buffer","splitter","createChannelSplitter","merger","createChannelMerger","_merger","MonoFilter","lpf1","lpf2","hpf1","hpf2","HTMLAudioContext","_elapsed","_updateListener","_update","WebAudioInstance","_gain","_a","_lastUpdate","_now","_enabled","time","enabled","script","nodes","_progress","events","force","now","delta","stop","bufferSource","createBufferSource","createScriptProcessor","WebAudioNodes","BUFFER_SIZE","createGain","analyser","createAnalyser","orig","WebAudioMedia","_nodes","isPlayable","_decode","_loadUrl","request","XMLHttpRequest","open","responseType","onload","response","send","arrayBuffer","decode","SoundUtils","glob","FORMAT_PATTERN","test","match","exec","exts","split","replace","ext","supported","resolved","extension","hertz","Sound","from","singleInstance","fArray","angle","sin","canvas","document","createElement","assign","width","height","fill","baseTexture","BaseTexture","fromCanvas","getContext","fillStyle","data","step","ceil","amp","j","datum","fillRect","alias","PLAY_ID","preload","autoPlay","loaded","complete","types","m4a","oga","audio","formats","extensions","canByExt","canPlayType","canByType","freeze","baseUrl","concurrency","use","LoaderMiddleware","plugin","pre","Loader","addPixiMiddleware","loaders","_sound","legacy","loader","Resource","setExtensionXhrType","XHR_RESPONSE_TYPE","DEFAULT","setExtensionLoadType","LOAD_TYPE","AUDIO","BUFFER","XHR","resource","next","resolveUrl","indexOf","name","SoundSprite","ctx","WebAudioContext","AudioContext","compressor","createDynamicsCompressor","_ctx","_offlineCtx","OfflineAudioContext","_unlocked","state","_unlock","playEmptySound","resume","win","window","webkitAudioContext","webkitOfflineAudioContext","close","suspend","decodeAudioData","_webAudioContext","_htmlAudioContext","_sounds","_context","PromisePolyfill","install","__pixiSound","PixiJS","defineProperty","get","defineProperties","htmlaudio","webaudio","sourceOptions","results","_getOptions","overrides","ArrayBuffer","HTMLAudioElement","_useLegacy","exists","togglePause","toggleMute","find","removeAll","_instances","_sprites","_autoPlayOptions","isPlaying","sprites","addSprites","_preload","sprite","_removeInstances","removeSprites","name_1","offset","_createInstance","once","_poolInstance","index","splice","_pool","pop","create"],"mappings":"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"}