{"version":3,"file":"WebAudioInstance.mjs","sources":["../../src/webaudio/WebAudioInstance.ts"],"sourcesContent":["import { EventEmitter, Ticker } from 'pixi.js';\nimport { Filter } from '../filters/Filter';\nimport { IMediaInstance } from '../interfaces';\nimport { PlayOptions } from '../Sound';\nimport { WebAudioMedia } from './WebAudioMedia';\nimport { WebAudioUtils } from './WebAudioUtils';\n\nlet id = 0;\n\n/**\n * A single play instance that handles the AudioBufferSourceNode.\n * @memberof webaudio\n * @extends PIXI.EventEmitter\n */\nclass WebAudioInstance extends EventEmitter implements IMediaInstance\n{\n    /**\n     * The current unique ID for this instance.\n     * @readonly\n     */\n    public readonly id: number;\n\n    /** The source Sound. */\n    private _media: WebAudioMedia;\n\n    /** true if paused. */\n    private _paused: boolean;\n\n    /** true if muted. */\n    private _muted: boolean;\n\n    /** true if paused. */\n    private _pausedReal: boolean;\n\n    /** The instance volume */\n    private _volume: number;\n\n    /** Last update frame number. */\n    private _lastUpdate: number;\n\n    /** The total number of seconds elapsed in playback. */\n    private _elapsed: number;\n\n    /** Playback rate, where 1 is 100%. */\n    private _speed: number;\n\n    /** Playback rate, where 1 is 100%. */\n    private _end: number;\n\n    /** `true` if should be looping. */\n    private _loop: boolean;\n\n    /** Gain node for controlling volume of instance */\n    private _gain: GainNode;\n\n    /** Length of the sound in seconds. */\n    private _duration: number;\n\n    /** The progress of the sound from 0 to 1. */\n    private _progress: number;\n\n    /** Audio buffer source clone from Sound object. */\n    private _source: AudioBufferSourceNode;\n\n    /** The filters */\n    private _filters: Filter[];\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\n        // Initialize\n        this.init(media);\n    }\n\n    /**\n     * Set a property by name, this makes it easy to chain values\n     * @param name - Name of the property to set.\n     * @param value - Value to set property to.\n     */\n    public set(name: 'speed' | 'volume' | 'muted' | 'loop' | 'paused', value: number | boolean): this\n    {\n        if (this[name] === undefined)\n        {\n            throw new Error(`Property with name ${name} does not exist.`);\n        }\n        else\n        {\n            switch (name)\n            {\n                case 'speed': this.speed = value as number; break;\n                case 'volume': this.volume = value as number; break;\n                case 'muted': this.muted = value as boolean; break;\n                case 'loop': this.loop = value as boolean; break;\n                case 'paused': this.paused = value as boolean; break;\n            }\n        }\n\n        return this;\n    }\n\n    /** Stops the instance, don't use after this. */\n    public stop(): void\n    {\n        if (this._source)\n        {\n            this._internalStop();\n            this.emit('stop');\n        }\n    }\n\n    /** Set the instance speed from 0 to 1 */\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    /** Get the set the volume for this instance from 0 to 1 */\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    /** `true` if the sound is muted */\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    /** If the sound instance should loop playback */\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    /** The collection of filters. */\n    public get filters(): Filter[]\n    {\n        return this._filters;\n    }\n    public set filters(filters: Filter[])\n    {\n        if (this._filters)\n        {\n            this._filters?.filter((filter) => filter).forEach((filter) => filter.disconnect());\n            this._filters = null;\n            // Reconnect direct path\n            this._source.connect(this._gain);\n        }\n        this._filters = filters?.length ? filters.slice(0) : null;\n        this.refresh();\n    }\n\n    /** Refresh loop, volume and speed based on changes to parent */\n    public refresh(): void\n    {\n        // Sound could be paused\n        if (!this._source)\n        {\n            return;\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\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        this.applyFilters();\n    }\n\n    /** Connect filters nodes to audio context */\n    private applyFilters(): void\n    {\n        if (this._filters?.length)\n        {\n            // Disconnect direct path before inserting filters\n            this._source.disconnect();\n\n            // Connect each filter\n            let source: { connect: (node: AudioNode) => void } = this._source;\n\n            this._filters.forEach((filter: Filter) =>\n            {\n                source.connect(filter.destination);\n                source = filter;\n            });\n            source.connect(this._gain);\n        }\n    }\n\n    /** Handle changes in paused state, either globally or sound or instance */\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 paused\n                 */\n                this.emit('paused');\n            }\n            else\n            {\n                /**\n                 * The sound is unpaused.\n                 * @event 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 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     * @param options - Play options.\n     */\n    public play(options: PlayOptions): void\n    {\n        const { start, end, speed, loop, volume, muted, filters } = options;\n\n        if (end)\n        {\n            // eslint-disable-next-line no-console\n            console.assert(end > start, 'End time is before start time');\n        }\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._filters = filters;\n        this.refresh();\n\n        const duration: number = this._source.buffer.duration;\n\n        this._duration = duration;\n        this._end = end;\n        this._lastUpdate = this._now();\n        this._elapsed = start;\n        this._source.onended = this._onComplete.bind(this);\n\n        if (this._loop)\n        {\n            this._source.loopEnd = end;\n            this._source.loopStart = start;\n            this._source.start(0, start);\n        }\n        else 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 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.enableTicker(true);\n    }\n\n    /** Start the update progress. */\n    private enableTicker(enabled: boolean): void\n    {\n        Ticker.shared.remove(this._updateListener, this);\n        if (enabled)\n        {\n            Ticker.shared.add(this._updateListener, this);\n        }\n    }\n\n    /** The current playback progress from 0 to 1. */\n    public get progress(): number\n    {\n        return this._progress;\n    }\n\n    /** Pauses the sound. */\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    /** Don't use after this. */\n    public destroy(): void\n    {\n        this.removeAllListeners();\n        this._internalStop();\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._filters?.forEach((filter) => filter.disconnect());\n        this._filters = null;\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     * @return The string representation of instance.\n     */\n    public toString(): string\n    {\n        return `[WebAudioInstance id=${this.id}]`;\n    }\n\n    /**\n     * Get the current time in seconds.\n     * @return Seconds since start of context\n     */\n    private _now(): number\n    {\n        return this._media.context.audioContext.currentTime;\n    }\n\n    /** Callback for update listener */\n    private _updateListener()\n    {\n        this._update();\n    }\n\n    /** Internal update the progress. */\n    private _update(force = 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\n                this._elapsed += delta * speed;\n                this._lastUpdate = now;\n                const duration: number = this._duration;\n                let progress: number;\n\n                if (this._source.loopStart)\n                {\n                    const soundLength = this._source.loopEnd - this._source.loopStart;\n\n                    progress = (this._source.loopStart + (this._elapsed % soundLength)) / duration;\n                }\n                else\n                {\n                    progress = (this._elapsed % duration) / duration;\n                }\n\n                // Update the progress\n                this._progress = progress;\n\n                /**\n                 * The sound progress is updated.\n                 * @event 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    /** Initializes the instance. */\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    /** Stops the instance. */\n    private _internalStop(): void\n    {\n        if (this._source)\n        {\n            this.enableTicker(false);\n            this._source.onended = null;\n            this._source.stop(0); // param needed for iOS 8 bug\n            this._source.disconnect();\n            try\n            {\n                this._source.buffer = null;\n            }\n            catch (err)\n            {\n                // try/catch workaround for bug in older Chrome versions\n                console.warn('Failed to set AudioBufferSourceNode.buffer to null:', err);\n            }\n            this._source = null;\n        }\n    }\n\n    /** Callback when completed. */\n    private _onComplete(): void\n    {\n        if (this._source)\n        {\n            this.enableTicker(false);\n            this._source.onended = null;\n            this._source.disconnect();\n            try\n            {\n                this._source.buffer = null;\n            }\n            catch (err)\n            {\n                // try/catch workaround for bug in older Chrome versions\n                console.warn('Failed to set AudioBufferSourceNode.buffer to null:', err);\n            }\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 end\n         */\n        this.emit('end', this);\n    }\n}\n\nexport { WebAudioInstance };\n"],"names":[],"mappings":"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"}