shaku
Version:
A simple and effective JavaScript game development framework that knows its place!
133 lines (123 loc) • 3.87 kB
JavaScript
/**
* Implement a sound mixer class.
*
* |-- copyright and license --|
* @module Shaku
* @file shaku\src\sfx\sound_mixer.js
* @author Ronen Ness (ronenness@gmail.com | http://ronenness.com)
* @copyright (c) 2021 Ronen Ness
* @license MIT
* |-- end copyright and license --|
*
*/
'use strict';
const SoundInstance = require("./sound_instance.js");
/**
* A utility class to mix between two sounds.
*/
class SoundMixer
{
/**
* Create the sound mixer.
* @param {SoundInstance} sound1 Sound to mix from. Can be null to just fade in.
* @param {SoundInstance} sound2 Sound to mix to. Can be null to just fade out.
* @param {Boolean} allowOverlapping If true (default), will mix while overlapping sounds.
* If false, will first finish first sound before begining next.
*/
constructor(sound1, sound2, allowOverlapping)
{
this._sound1 = sound1;
this._sound2 = sound2;
this.fromSoundVolume = this._sound1 ? this._sound1.volume : 0;
this.toSoundVolume = this._sound2 ? this._sound2.volume : 0;
this.allowOverlapping = allowOverlapping;
this.update(0);
}
/**
* Stop both sounds.
*/
stop()
{
if (this._sound1) { this._sound1.stop(); }
if (this._sound2) { this._sound2.stop(); }
}
/**
* Get first sound.
* @returns {SoundInstance} First sound instance.
*/
get fromSound()
{
return this._sound1;
}
/**
* Get second sound.
* @returns {SoundInstance} Second sound instance.
*/
get toSound()
{
return this._sound2;
}
/**
* Return current progress.
* @returns {Number} Mix progress from 0 to 1.
*/
get progress()
{
return this._progress;
}
/**
* Update the mixer progress with time delta instead of absolute value.
* @param {Number} delta Progress delta, in seconds.
*/
updateDelta(delta)
{
this.update(this._progress + delta);
}
/**
* Update the mixer progress.
* @param {Number} progress Transition progress from sound1 to sound2. Values must be between 0.0 to 1.0.
*/
update(progress)
{
// special case - start
if (progress <= 0) {
if (this._sound1) {
this._sound1.volume = this.fromSoundVolume;
}
if (this._sound2) {
this._sound2.volume = 0;
this._sound2.stop();
}
this._progress = 0;
}
// special case - finish
if (progress >= 1) {
if (this._sound2) {
this._sound2.volume = this.toSoundVolume;
}
if (this._sound1) {
this._sound1.volume = 0;
this._sound1.stop();
}
this._progress = 1;
}
// transition
else
{
this._progress = progress;
if (this._sound1) { this._sound1.play(); }
if (this._sound2) { this._sound2.play(); }
if (this.allowOverlapping) {
if (this._sound1) { this._sound1.volume = this.fromSoundVolume * (1 - progress); }
if (this._sound2) { this._sound2.volume = this.toSoundVolume * progress; }
}
else {
progress *= 2;
if (this._sound1) { this._sound1.volume = Math.max(this.fromSoundVolume * (1 - progress), 0); }
if (this._sound2) { this._sound2.volume = Math.max(this.toSoundVolume * (progress - 1), 0); }
}
}
}
}
// export the sound mixer
module.exports = SoundMixer;