UNPKG

@pixi/sound

Version:

WebAudio API playback library with filters

1 lines 19.8 kB
{"version":3,"file":"HTMLAudioInstance.mjs","sources":["../../src/htmlaudio/HTMLAudioInstance.ts"],"sourcesContent":["import { EventEmitter, Ticker } from 'pixi.js';\nimport { Filter } from '../filters/Filter';\nimport { IMediaInstance } from '../interfaces/IMediaInstance';\nimport { PlayOptions } from '../Sound';\nimport { HTMLAudioMedia } from './HTMLAudioMedia';\n\nlet id = 0;\n\n/**\n * Instance which wraps the `<audio>` element playback.\n * @memberof htmlaudio\n * @extends PIXI.EventEmitter\n */\nclass HTMLAudioInstance extends EventEmitter implements IMediaInstance\n{\n /** Extra padding, in seconds, to deal with low-latecy of HTMLAudio. */\n public static readonly PADDING: number = 0.1;\n\n /** The current unique ID for this instance. */\n public readonly id: number;\n\n /** The instance of the Audio element. */\n private _source: HTMLAudioElement;\n\n /** The instance of the Audio media element. */\n private _media: HTMLAudioMedia;\n\n /** Playback rate, where 1 is 100%. */\n private _end: number;\n\n /** Current instance paused state. */\n private _paused: boolean;\n\n /** Current instance muted state. */\n private _muted: boolean;\n\n /** Current actual paused state. */\n private _pausedReal: boolean;\n\n /** Total length of the audio. */\n private _duration: number;\n\n /** Playback rate, where 1 is 100%. */\n private _start: number;\n\n /** `true` if the audio is actually playing. */\n private _playing: boolean;\n\n /** Volume for the instance. */\n private _volume: number;\n\n /** Speed for the instance. */\n private _speed: number;\n\n /** `true` for looping the playback */\n private _loop: boolean;\n\n /** @param parent - Parent element */\n constructor(parent: HTMLAudioMedia)\n {\n super();\n\n this.id = id++;\n\n this.init(parent);\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 'paused': this.paused = value as boolean; break;\n case 'loop': this.loop = value as boolean; break;\n case 'muted': this.muted = value as boolean; break;\n }\n }\n\n return this;\n }\n\n /** The current playback progress from 0 to 1. */\n public get progress(): number\n {\n const { currentTime } = this._source;\n\n return currentTime / this._duration;\n }\n\n /** Pauses the sound. */\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 * @private\n */\n private _onPlay(): void\n {\n this._playing = true;\n }\n\n /**\n * Reference: http://stackoverflow.com/a/40370077\n * @private\n */\n private _onPause(): void\n {\n this._playing = false;\n }\n\n /**\n * Initialize the instance.\n * @param {htmlaudio.HTMLAudioMedia} media - Same as constructor\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\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 * @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 /** Stop the sound playing */\n public stop(): void\n {\n this._internalStop();\n\n if (this._source)\n {\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 }\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 /** 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 /** `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 /**\n * HTML Audio does not support filters, this is non-functional API.\n */\n public get filters(): Filter[]\n {\n console.warn('HTML Audio does not support filters');\n\n return null;\n }\n public set filters(_filters: Filter[])\n {\n console.warn('HTML Audio does not support filters');\n }\n\n /** Call whenever the loop, speed or volume changes */\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\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 /** 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 // 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 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._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 pause\n * @property {boolean} paused - If the instance was paused or not.\n */\n this.emit('pause', pausedReal);\n }\n }\n\n /** Start playing the sound/ */\n public play(options: PlayOptions): void\n {\n const { start, end, speed, loop, volume, muted } = 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\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 console.warn('Looping not support when specifying an \"end\" time');\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 {\n if (this._source)\n {\n this._source.currentTime = start;\n this._source.onloadedmetadata = null;\n this.emit('progress', start / this._duration, this._duration);\n 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 start\n */\n this.emit('start');\n }\n\n /**\n * Handle time update on sound.\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 * @private\n */\n private _onComplete(): void\n {\n 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 end\n */\n this.emit('end', this);\n }\n\n /** Don't use after this. */\n public destroy(): void\n {\n 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 * @return The string representation of instance.\n */\n public toString(): string\n {\n return `[HTMLAudioInstance id=${this.id}]`;\n }\n}\n\nexport { HTMLAudioInstance };\n"],"names":[],"mappings":"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"}