@babylonjs/core
Version:
Getting started? Play directly with the Babylon.js API using our [playground](https://playground.babylonjs.com/). It also contains a lot of samples to learn how to use it.
111 lines • 4.3 kB
JavaScript
import { AbstractSound } from "./abstractSound.js";
/**
* Abstract class representing a streaming sound.
*
* A streaming sound has a sound buffer that is loaded into memory in chunks as it is played. This allows it to be played
* more quickly than a static sound, but it also means that it cannot have loop points or playback rate changes.
*
* Due to the way streaming sounds are typically implemented, there can be a significant delay when attempting to play
* a streaming sound for the first time. To prevent this delay, it is recommended to preload instances of the sound
* using the {@link IStreamingSoundStoredOptions.preloadCount} options, or the {@link preloadInstanceAsync} and
* {@link preloadInstancesAsync} methods before calling the `play` method.
*
* Streaming sounds are created by the {@link CreateStreamingSoundAsync} function.
*/
export class StreamingSound extends AbstractSound {
constructor(name, engine) {
super(name, engine);
this._preloadedInstances = new Array();
}
/**
* The number of instances to preload. Defaults to `1`.
*/
get preloadCount() {
return this._options.preloadCount ?? 1;
}
/**
* Returns the number of instances that have been preloaded.
*/
get preloadCompletedCount() {
return this._preloadedInstances.length;
}
/**
* Preloads an instance of the sound.
* @returns A promise that resolves when the instance is preloaded.
*/
// eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax
preloadInstanceAsync() {
const instance = this._createInstance();
this._addPreloadedInstance(instance);
return instance.preloadedPromise;
}
/**
* Preloads the given number of instances of the sound.
* @param count - The number of instances to preload.
* @returns A promise that resolves when all instances are preloaded.
*/
async preloadInstancesAsync(count) {
for (let i = 0; i < count; i++) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
this.preloadInstanceAsync();
}
await Promise.all(this._preloadedInstances.map(async (instance) => await instance.preloadedPromise));
}
/**
* Plays the sound.
* - Triggers `onEndedObservable` if played for the full duration and the `loop` option is not set.
* @param options The options to use when playing the sound. Options set here override the sound's options.
*/
play(options = {}) {
if (this.state === 5 /* SoundState.Paused */) {
this.resume();
return;
}
let instance;
if (this.preloadCompletedCount > 0) {
instance = this._preloadedInstances[0];
instance.startOffset = this.startOffset;
this._removePreloadedInstance(instance);
}
else {
instance = this._createInstance();
}
const onInstanceStateChanged = () => {
if (instance.state === 3 /* SoundState.Started */) {
this._stopExcessInstances();
instance.onStateChangedObservable.removeCallback(onInstanceStateChanged);
}
};
instance.onStateChangedObservable.add(onInstanceStateChanged);
options.startOffset ?? (options.startOffset = this.startOffset);
options.loop ?? (options.loop = this.loop);
options.volume ?? (options.volume = 1);
this._beforePlay(instance);
instance.play(options);
this._afterPlay(instance);
}
/**
* Stops the sound.
*/
stop() {
this._setState(1 /* SoundState.Stopped */);
if (!this._instances) {
return;
}
for (const instance of Array.from(this._instances)) {
instance.stop();
}
}
_addPreloadedInstance(instance) {
if (!this._preloadedInstances.includes(instance)) {
this._preloadedInstances.push(instance);
}
}
_removePreloadedInstance(instance) {
const index = this._preloadedInstances.indexOf(instance);
if (index !== -1) {
this._preloadedInstances.splice(index, 1);
}
}
}
//# sourceMappingURL=streamingSound.js.map