Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/itsjoesullivan/envelope-generator

Simple ADSR envelope generator for web audio
https://github.com/itsjoesullivan/envelope-generator

Last synced: about 2 months ago
JSON representation

Simple ADSR envelope generator for web audio

Awesome Lists containing this project

README

        

## Envelope Generator ![Test status](https://api.travis-ci.org/itsjoesullivan/envelope-generator.svg)

Basic ADSR envelope generator for web audio. A demo is running [here](http://joesul.li/van/envelope-generator/).

- 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](https://github.com/mmckegg/adsr/blob/master/index.js#L126) idea from [mmckegg/adsr](https://github.com/mmckegg/adsr).

### Example

```bash
npm install --save envelope-generator
```

```javascript
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`, and `releaseCurve` 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 your `releaseValueCurve` 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.

```javascript
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:

```javascript
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:

```javascript
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:

```javascript
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:

```javascript
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.

```javascript
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);
```