@pixi/sound
Version:
WebAudio API playback library with filters
1 lines • 24.6 kB
Source Map (JSON)
{"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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"}