ADSR Envelope
Node.js
npm install adsr-envelope
constructor(opts: object = {})
attackTime: number
default: 0.01 (10msec)decayTime: number
default: 0.3 (300msec)sustainLevel: number
default: 0.5releaseTime: number
default: 1 (1sec)gateTime: number
default: InfinitysustainTime: number
duration: number
peakLevel: number
default: 1epsilon: number
default: 0.001attackCurve: string
default: lin- lin or exp (linear or exponential)
decayCurve: string
default: lin- lin or exp (linear or exponential)
releaseCurve: string
default: lin- lin or exp (linear or exponential)
duration: number
attackTime: number
decayTime: number
sustainTime: number
sustainLevel: number
releaseTime: number
gateTime: number
peakLevel: number
epsilon: number
attackCurve: string
decayCurve: string
releaseCurve: string
valueAt(time: number = 0): number
applyTo(audioParam: AudioParam, playbackTime: number = 0): self
getWebAudioAPIMethods(playbackTime: number = 0): Array[]
clone(): ADSREnvelope
import ADSREnvelope from "adsr-envelope";
let audioContext = new AudioContext();
let oscillator = audioContext.createOscillator();
let gain = audioContext.createGain();
let adsr = new ADSREnvelope({
attackTime: 0.5,
decayTime: 0.25,
sustainLevel: 0.8,
releaseTime: 2.5,
gateTime: 6,
releaseCurve: "exp",
});
adsr.applyTo(gain.gain, audioContext.currentTime);
console.log(adsr.getWebAudioAPIMethods());
// [
// [ "setValueAtTime", 0, 0 ],
// [ "linearRampToValueAtTime", 1, 0.5 ],
// [ "linearRampToValueAtTime", 0.8, 0.75],
// [ "setValueAtTime", 0.8, 6 ],
// [ "exponentialRampToValueAtTime", 0.001, 8.5 ],
// ]
oscillator.start(audioContext.currentTime);
oscillator.stop(audioContext.currentTime + adsr.duration);
oscillator.connect(gain);
gain.connect(audioContext.destination);
import ADSREnvelope from "adsr-envelope";
let audioContext = new AudioContext();
let adsr = new ADSREnvelope({
attackTime: 0.5,
decayTime: 0.25,
sustainLevel: 0.8,
releaseTime: 2.5,
gateTime: 6,
releaseCurve: "exp",
});
let noteMap = {};
class Note {
constructor(audioContext, noteNumber, envelope) {
this.audioContext = audioContext;
this.noteNumber = noteNumber;
this.envelope = envelope;
this.startTime = 0;
this.oscillator = audioContext.createOscillator();
this.gain = audioContext.createGain();
this.oscillator.frequency.value = midicps(noteNumber);
this.oscillator.onended = () => {
this.oscillator.disconnect();
this.gain.disconnect();
};
this.oscillator.connect(this.gain);
this.gain.connect(audioContext.destination);
}
noteOn(playbackTime = this.audioContext.currentTime) {
this.startTime = playbackTime;
this.envelope.gateTime = Infinity;
this.envelope.applyTo(this.gain.gain, playbackTime);
this.oscillator.start(playbackTime);
}
noteOff(playbackTime = this.audioContext.currentTime) {
this.gain.gain.cancelScheduledValues(this.startTime);
this.envelope.gateTime = playbackTime - this.startTime;
this.envelope.applyTo(this.gain.gain, this.startTime);
this.oscillator.stop(this.startTime + this.envelope.duration);
}
}
midiKeyboard.on("noteOn", ({ noteNumber }) => {
if (noteMap[noteNumber]) {
noteMap[noteNumber].noteOff();
}
noteMap[noteNumber] = new Note(audioContext, noteNumber, adsr.clone());
noteMap[noteNumber].noteOn();
});
midiKeyboard.on("noteOff", ({ noteNumber }) => {
if (noteMap[noteNumber]) {
noteMap[noteNumber].noteOff();
}
noteMap[noteNumber] = null;
});
MIT