{"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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"}