Skip to content

Commit

Permalink
Implement volume() on MusicMixer
Browse files Browse the repository at this point in the history
- Implement volume changer on MusicMixer
  • Loading branch information
almic committed Mar 27, 2024
1 parent 7911d50 commit faeaa89
Showing 1 changed file with 71 additions and 2 deletions.
73 changes: 71 additions & 2 deletions src/MusicMixer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import AudioSourceNode, { AudioAdjustmentOptions } from './AudioSourceNode';
import AudioSourceNode, { AudioAdjustmentOptions, AudioRampType } from './AudioSourceNode';
import TrackSingle, { Track, TrackGroup } from './Track';
import buildOptions from './defaults';
import * as defaults from './defaults';

/**
* MusicMixer
Expand Down Expand Up @@ -89,9 +91,76 @@ class MusicMixer {
* @returns {MusicMixer} this MusicMixer
*/
public volume(volume: number, options?: AudioAdjustmentOptions): MusicMixer {
console.log(`stub volume changed to ${volume} with ${options}`);
const currentValue = this.gainNode.gain.value;
const difference = volume - currentValue;
const adjustment = options ? buildOptions(options) : defaults.automationDefault;

// Stop automations and immediately ramp.
if (Math.abs(difference) < Number.EPSILON) {
this.gainNode.gain.cancelAndHoldAtTime(this.currentTime);
this.gainNode.gain.setValueAtTime(currentValue, this.currentTime);
this.gainNode.gain.linearRampToValueAtTime(volume, adjustment.delay + this.currentTime);
return this;
}

this.gainNode.gain.cancelAndHoldAtTime(adjustment.delay + this.currentTime);
this.gainNode.gain.setValueAtTime(currentValue, adjustment.delay + this.currentTime);
if (Array.isArray(adjustment.ramp)) {
const valueCurve = [];
for (const markiplier of adjustment.ramp) {
valueCurve.push(currentValue + difference * markiplier);
}
this.gainNode.gain.setValueCurveAtTime(
valueCurve,
adjustment.delay + this.currentTime,
adjustment.duration,
);
return this;
}

switch (adjustment.ramp) {
case AudioRampType.EXPONENTIAL: {
this.gainNode.gain.exponentialRampToValueAtTime(
volume,
adjustment.delay + adjustment.duration + this.currentTime,
);
break;
}
case AudioRampType.LINEAR: {
this.gainNode.gain.linearRampToValueAtTime(
volume,
adjustment.delay + adjustment.duration + this.currentTime,
);
break;
}
case AudioRampType.NATURAL: {
// Logarithmic approach to value, it is 95% the way there after 3 timeConstant, so we linearly ramp at that point
const timeConstant = adjustment.duration / 4;
this.gainNode.gain.setTargetAtTime(volume, adjustment.delay + this.currentTime, timeConstant);
this.gainNode.gain.cancelAndHoldAtTime(
adjustment.delay + timeConstant * 3 + this.currentTime,
);
// The following event is implicitly added, per WebAudio spec.
// https://webaudio.github.io/web-audio-api/#dom-audioparam-cancelandholdattime
// this.gainNode.gain.setValueAtTime(currentValue + (difference * (1 - Math.pow(Math.E, -3))), timeConstant * 3 + this.currentTime);
this.gainNode.gain.linearRampToValueAtTime(
volume,
adjustment.delay + adjustment.duration + this.currentTime,
);
break;
}
default: {
this.gainNode.gain.setValueAtTime(volume, adjustment.delay);
break;
}
}

return this;
}

get currentTime(): number {
return this.audioContext.currentTime;
}
}

export default MusicMixer;

0 comments on commit faeaa89

Please sign in to comment.