@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.
164 lines • 5.39 kB
JavaScript
import { Logger } from "../Misc/logger.js";
/**
* Wraps one or more Sound objects and selects one with random weight for playback.
*/
export class WeightedSound {
/**
* Creates a new WeightedSound from the list of sounds given.
* @param loop When true a Sound will be selected and played when the current playing Sound completes.
* @param sounds Array of Sounds that will be selected from.
* @param weights Array of number values for selection weights; length must equal sounds, values will be normalized to 1
*/
constructor(loop, sounds, weights) {
/** When true a Sound will be selected and played when the current playing Sound completes. */
this.loop = false;
this._coneInnerAngle = 360;
this._coneOuterAngle = 360;
this._volume = 1;
/** A Sound is currently playing. */
this.isPlaying = false;
/** A Sound is currently paused. */
this.isPaused = false;
this._sounds = [];
this._weights = [];
if (sounds.length !== weights.length) {
throw new Error("Sounds length does not equal weights length");
}
this.loop = loop;
this._weights = weights;
// Normalize the weights
let weightSum = 0;
for (const weight of weights) {
weightSum += weight;
}
const invWeightSum = weightSum > 0 ? 1 / weightSum : 0;
for (let i = 0; i < this._weights.length; i++) {
this._weights[i] *= invWeightSum;
}
this._sounds = sounds;
for (const sound of this._sounds) {
sound.onEndedObservable.add(() => {
this._onended();
});
}
}
/**
* The size of cone in degrees for a directional sound in which there will be no attenuation.
*/
get directionalConeInnerAngle() {
return this._coneInnerAngle;
}
/**
* The size of cone in degrees for a directional sound in which there will be no attenuation.
*/
set directionalConeInnerAngle(value) {
if (value !== this._coneInnerAngle) {
if (this._coneOuterAngle < value) {
Logger.Error("directionalConeInnerAngle: outer angle of the cone must be superior or equal to the inner angle.");
return;
}
this._coneInnerAngle = value;
for (const sound of this._sounds) {
sound.directionalConeInnerAngle = value;
}
}
}
/**
* Size of cone in degrees for a directional sound outside of which there will be no sound.
* Listener angles between innerAngle and outerAngle will falloff linearly.
*/
get directionalConeOuterAngle() {
return this._coneOuterAngle;
}
/**
* Size of cone in degrees for a directional sound outside of which there will be no sound.
* Listener angles between innerAngle and outerAngle will falloff linearly.
*/
set directionalConeOuterAngle(value) {
if (value !== this._coneOuterAngle) {
if (value < this._coneInnerAngle) {
Logger.Error("directionalConeOuterAngle: outer angle of the cone must be superior or equal to the inner angle.");
return;
}
this._coneOuterAngle = value;
for (const sound of this._sounds) {
sound.directionalConeOuterAngle = value;
}
}
}
/**
* Playback volume.
*/
get volume() {
return this._volume;
}
/**
* Playback volume.
*/
set volume(value) {
if (value !== this._volume) {
for (const sound of this._sounds) {
sound.setVolume(value);
}
}
}
_onended() {
if (this._currentIndex !== undefined) {
this._sounds[this._currentIndex].autoplay = false;
}
if (this.loop && this.isPlaying) {
this.play();
}
else {
this.isPlaying = false;
}
}
/**
* Suspend playback
*/
pause() {
if (this.isPlaying) {
this.isPaused = true;
if (this._currentIndex !== undefined) {
this._sounds[this._currentIndex].pause();
}
}
}
/**
* Stop playback
*/
stop() {
this.isPlaying = false;
if (this._currentIndex !== undefined) {
this._sounds[this._currentIndex].stop();
}
}
/**
* Start playback.
* @param startOffset Position the clip head at a specific time in seconds.
*/
play(startOffset) {
if (!this.isPaused) {
this.stop();
const randomValue = Math.random();
let total = 0;
for (let i = 0; i < this._weights.length; i++) {
total += this._weights[i];
if (randomValue <= total) {
this._currentIndex = i;
break;
}
}
}
const sound = this._sounds[this._currentIndex ?? 0];
if (sound.isReady()) {
sound.play(0, this.isPaused ? undefined : startOffset);
}
else {
sound.autoplay = true;
}
this.isPlaying = true;
this.isPaused = false;
}
}
//# sourceMappingURL=weightedsound.js.map