@pixi/sound
Version:
WebAudio API playback library with filters
365 lines (362 loc) • 9.5 kB
JavaScript
import { HTMLAudioContext } from './htmlaudio/HTMLAudioContext.mjs';
import { Sound } from './Sound.mjs';
import { WebAudioContext } from './webaudio/WebAudioContext.mjs';
class SoundLibrary {
constructor() {
this.init();
}
/**
* Re-initialize the sound library, this will
* recreate the AudioContext. If there's a hardware-failure
* call `close` and then `init`.
* @return Sound instance
*/
init() {
if (this.supported) {
this._webAudioContext = new WebAudioContext();
}
this._htmlAudioContext = new HTMLAudioContext();
this._sounds = {};
this.useLegacy = !this.supported;
return this;
}
/**
* The global context to use.
* @readonly
*/
get context() {
return this._context;
}
/**
* Apply filters to all sounds. Can be useful
* for setting global planning or global effects.
* **Only supported with WebAudio.**
* @example
* import { sound, filters } from '@pixi/sound';
* // Adds a filter to pan all output left
* sound.filtersAll = [
* new filters.StereoFilter(-1)
* ];
*/
get filtersAll() {
if (!this.useLegacy) {
return this._context.filters;
}
return [];
}
set filtersAll(filtersAll) {
if (!this.useLegacy) {
this._context.filters = filtersAll;
}
}
/**
* `true` if WebAudio is supported on the current browser.
*/
get supported() {
return WebAudioContext.AudioContext !== null;
}
/**
* @ignore
*/
add(source, sourceOptions) {
if (typeof source === "object") {
const results = {};
for (const alias in source) {
const options2 = this._getOptions(
source[alias],
sourceOptions
);
results[alias] = this.add(alias, options2);
}
return results;
}
console.assert(!this._sounds[source], `Sound with alias ${source} already exists.`);
if (sourceOptions instanceof Sound) {
this._sounds[source] = sourceOptions;
return sourceOptions;
}
const options = this._getOptions(sourceOptions);
const sound = Sound.from(options);
this._sounds[source] = sound;
return sound;
}
/**
* Internal methods for getting the options object
* @private
* @param source - The source options
* @param overrides - Override default options
* @return The construction options
*/
_getOptions(source, overrides) {
let options;
if (typeof source === "string") {
options = { url: source };
} else if (Array.isArray(source)) {
options = { url: source };
} else if (source instanceof ArrayBuffer || source instanceof AudioBuffer || source instanceof HTMLAudioElement) {
options = { source };
} else {
options = source;
}
options = { ...options, ...overrides || {} };
return options;
}
/**
* Do not use WebAudio, force the use of legacy. This **must** be called before loading any files.
*/
get useLegacy() {
return this._useLegacy;
}
set useLegacy(legacy) {
this._useLegacy = legacy;
this._context = !legacy && this.supported ? this._webAudioContext : this._htmlAudioContext;
}
/**
* This disables auto-pause all playback when the window blurs (WebAudio only).
* This is helpful to keep from playing sounds when the user switches tabs.
* However, if you're running content within an iframe, this may be undesirable
* and you should disable (set to `true`) this behavior.
* @default false
*/
get disableAutoPause() {
return !this._webAudioContext.autoPause;
}
set disableAutoPause(autoPause) {
this._webAudioContext.autoPause = !autoPause;
}
/**
* Removes a sound by alias.
* @param alias - The sound alias reference.
* @return Instance for chaining.
*/
remove(alias) {
this.exists(alias, true);
this._sounds[alias].destroy();
delete this._sounds[alias];
return this;
}
/**
* Set the global volume for all sounds. To set per-sound volume see {@link SoundLibrary#volume}.
*/
get volumeAll() {
return this._context.volume;
}
set volumeAll(volume) {
this._context.volume = volume;
this._context.refresh();
}
/**
* Set the global speed for all sounds. To set per-sound speed see {@link SoundLibrary#speed}.
*/
get speedAll() {
return this._context.speed;
}
set speedAll(speed) {
this._context.speed = speed;
this._context.refresh();
}
/**
* Toggle paused property for all sounds.
* @return `true` if all sounds are paused.
*/
togglePauseAll() {
return this._context.togglePause();
}
/**
* Pauses any playing sounds.
* @return Instance for chaining.
*/
pauseAll() {
this._context.paused = true;
this._context.refreshPaused();
return this;
}
/**
* Resumes any sounds.
* @return Instance for chaining.
*/
resumeAll() {
this._context.paused = false;
this._context.refreshPaused();
return this;
}
/**
* Toggle muted property for all sounds.
* @return `true` if all sounds are muted.
*/
toggleMuteAll() {
return this._context.toggleMute();
}
/**
* Mutes all playing sounds.
* @return Instance for chaining.
*/
muteAll() {
this._context.muted = true;
this._context.refresh();
return this;
}
/**
* Unmutes all playing sounds.
* @return Instance for chaining.
*/
unmuteAll() {
this._context.muted = false;
this._context.refresh();
return this;
}
/**
* Stops and removes all sounds. They cannot be used after this.
* @return Instance for chaining.
*/
removeAll() {
for (const alias in this._sounds) {
this._sounds[alias].destroy();
delete this._sounds[alias];
}
return this;
}
/**
* Stops all sounds.
* @return Instance for chaining.
*/
stopAll() {
for (const alias in this._sounds) {
this._sounds[alias].stop();
}
return this;
}
/**
* Checks if a sound by alias exists.
* @param alias - Check for alias.
* @param assert - Whether enable console.assert.
* @return true if the sound exists.
*/
exists(alias, assert = false) {
const exists = !!this._sounds[alias];
if (assert) {
console.assert(exists, `No sound matching alias '${alias}'.`);
}
return exists;
}
/**
* Convenience function to check to see if any sound is playing.
* @returns `true` if any sound is currently playing.
*/
isPlaying() {
for (const alias in this._sounds) {
if (this._sounds[alias].isPlaying) {
return true;
}
}
return false;
}
/**
* Find a sound by alias.
* @param alias - The sound alias reference.
* @return Sound object.
*/
find(alias) {
this.exists(alias, true);
return this._sounds[alias];
}
/**
* Plays a sound.
* @method play
* @instance
* @param {string} alias - The sound alias reference.
* @param {string} sprite - The alias of the sprite to play.
* @return {IMediaInstance|null} The sound instance, this cannot be reused
* after it is done playing. Returns `null` if the sound has not yet loaded.
*/
/**
* Plays a sound.
* @param alias - The sound alias reference.
* @param {PlayOptions|Function} options - The options or callback when done.
* @return The sound instance,
* this cannot be reused after it is done playing. Returns a Promise if the sound
* has not yet loaded.
*/
play(alias, options) {
return this.find(alias).play(options);
}
/**
* Stops a sound.
* @param alias - The sound alias reference.
* @return Sound object.
*/
stop(alias) {
return this.find(alias).stop();
}
/**
* Pauses a sound.
* @param alias - The sound alias reference.
* @return Sound object.
*/
pause(alias) {
return this.find(alias).pause();
}
/**
* Resumes a sound.
* @param alias - The sound alias reference.
* @return Instance for chaining.
*/
resume(alias) {
return this.find(alias).resume();
}
/**
* Get or set the volume for a sound.
* @param alias - The sound alias reference.
* @param volume - Optional current volume to set.
* @return The current volume.
*/
volume(alias, volume) {
const sound = this.find(alias);
if (volume !== void 0) {
sound.volume = volume;
}
return sound.volume;
}
/**
* Get or set the speed for a sound.
* @param alias - The sound alias reference.
* @param speed - Optional current speed to set.
* @return The current speed.
*/
speed(alias, speed) {
const sound = this.find(alias);
if (speed !== void 0) {
sound.speed = speed;
}
return sound.speed;
}
/**
* Get the length of a sound in seconds.
* @param alias - The sound alias reference.
* @return The current duration in seconds.
*/
duration(alias) {
return this.find(alias).duration;
}
/**
* Closes the sound library. This will release/destroy
* the AudioContext(s). Can be used safely if you want to
* initialize the sound library later. Use `init` method.
*/
close() {
this.removeAll();
this._sounds = null;
if (this._webAudioContext) {
this._webAudioContext.destroy();
this._webAudioContext = null;
}
if (this._htmlAudioContext) {
this._htmlAudioContext.destroy();
this._htmlAudioContext = null;
}
this._context = null;
return this;
}
}
export { SoundLibrary };
//# sourceMappingURL=SoundLibrary.mjs.map