123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- 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() {
- 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];
- if (sound.isReady()) {
- sound.play(0, this.isPaused ? undefined : startOffset);
- }
- else {
- sound.autoplay = true;
- }
- this.isPlaying = true;
- this.isPaused = false;
- }
- }
- //# sourceMappingURL=weightedsound.js.map
|