Basic ADSR envelope generator for web audio. A demo is running here.
- The release stage exists as a separate
GainNode
, so the envelope doesn't need to keep track of its output gain internally. - Uses the voltage idea from mmckegg/adsr.
###Example
npm install --save envelope-generator
import Envelope from 'envelope-generator';
let context = new AudioContext();
let osc = context.createOscillator();
let gain = context.createGain();
let env = new Envelope(context, {
attackTime: 0.1,
decayTime: 3,
sustainLevel: 0.4,
releaseTime: 0.1
});
env.connect(gain.gain);
var startAt = context.currentTime;
var releaseAt = startAt + 0.5;
osc.start(startAt);
env.start(startAt);
env.release(releaseAt);
let stopAt = env.getReleaseCompleteTime();
osc.stop(stopAt);
env.stop(stopAt);
###Usage
####Constructor
The constructor accepts two arguments: an AudioContext and a settings object. All settings are optional, but you will probably want to set at least attackTime
, decayTime
, sustainLevel
, and releaseTime
.
- All
...Time
properties are in seconds - All
curve
,attackCurve
,decayCurve
, andreleaseCurve
properties default to"linear"
, with"exponential"
the alternative. - attackCurve, decayCurve, and releaseCurve override their respective curves
- Passing an
initialValueCurve
will determine the shape of the curve usually covered by the attack and decay sections of an envelope, overriding any other curve values. - Passing a
releaseValueCurve
will determine the shape of the release, overriding any other release curve value. - Both initialValueCurve and releaseValueCurve are expected to be normalized, i.e. not extending outside of the bounds [0, 1]. This is relatively intuitive for the
initialValueCurve
, but ensure that yourreleaseValueCurve
also starts at a value of 1 to avoid any jumps in the sound. The reason for this is that these two curves are applied in series. - The sampleRate property applies to initialValueCurve and releaseValueCurve, allowing them to be expressed in a sampleRate different from that of the context.
let context = new AudioContext();
let settings = {
curve: "linear",
attackCurve: "linear",
decayCurve: "linear",
releaseCurve: "linear",
initialValueCurve: Float32Array,
releaseValueCurve: Float32Array,
sampleRate: 44100,
delayTime: 0,
startLevel: 0,
maxLevel: 1,
attackTime: 0.1,
holdTime: 0,
decayTime: 0,
sustainLevel: 0.5,
releaseTime: 1
};
let env = new Envelope(context, settings)
####connect
The connect
method should be attached directly to AudioParam
s:
let osc = context.createOscillator();
let gainNode = context.createGain();
let env = new Envelope(context, settings);
env.connect(gainNode.gain);
####start
The start
method triggers the attack and decay stages of the envelope:
let osc = context.createOscillator();
let gainNode = context.createGain();
let env = new Envelope(context, settings);
env.connect(gainNode.gain);
osc.start(context.currentTime);
env.start(context.currentTime);
####release
The release
method triggers the release stage of the envelope:
let osc = context.createOscillator();
let gainNode = context.createGain();
let env = new Envelope(context, settings);
env.connect(gainNode.gain);
osc.start(context.currentTime);
env.start(context.currentTime);
// Release the envelope after 1 second
env.release(context.currentTime + 1);
####getReleaseCompleteTime
Releasing the envelope isn't the same as stopping the sound source. Once release has been called, getReleaseCompleteTime()
will return the time that the envelope finishes its release stage. If this is an amp envelope, and the startLevel (i.e., where the envelope will release to) is 0, getReleaseCompleteTime()
is when your sound source is guaranteed to be silent and can be stopped:
let osc = context.createOscillator();
let gainNode = context.createGain();
let env = new Envelope(context, settings);
env.connect(gainNode.gain);
osc.start(context.currentTime);
env.start(context.currentTime);
env.release(context.currentTime + 1);
// Stop the oscillator once the envelope has completed.
osc.stop(env.getReleaseCompleteTime());
####stop
Because they are generating a signal, envelopes need to be stopped as well as released. This should coincide with when the actual sound source is stopped.
let osc = context.createOscillator();
let gainNode = context.createGain();
let env = new Envelope(context, settings);
env.connect(gainNode.gain);
osc.start(context.currentTime);
env.start(context.currentTime);
env.release(context.currentTime + 1);
// Stop the oscillator once the envelope has completed.
let stopAt = env.getReleaseCompleteTime();
osc.stop(stopAt);
env.stop(stopAt);