npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

fastidious-envelope-generator

v2.0.0

Published

Envelope generator (aka ADSR) for the Web Audio API that tries to be well-behaved and artifact-free

Downloads

16

Readme

Fastidious-envelope-generator

Overview

Fastidious is an envelope generator (aka ADSR) for the Web Audio API that aims to be free of artifacts and handle edge cases well. Most notably, if a new envelope begins when an old one is still in progress, it picks up from where the old one left off so that there are no discontinuities.

Check out the demo.

Installation

$ npm install fastidious-envelope-generator`

Example

var EnvGen = require('fastidious-envelope-generator');

var audioContext = new (window.AudioContext || window.webkitAudioContext)();

// Create nodes
var oscNode = audioContext.createOscillator();
oscNode.start();

var vcaNode = audioContext.createGain();

// Connect up node graph
oscNode.connect(vcaNode);
vcaNode.connect(audioContext.destination);

// Instantiate envelope generator, leaving some settings as defaults
var eg = new EnvGen(audioContext, vcaNode.gain);
eg.mode = 'ASR';
eg.attackTime = 0.01;
eg.releaseTime = 0.02;

// Every second, schedule a gate cycle a little bit in the future
setInterval(function() {
  var t = audioContext.currentTime;
  eg.gateOn(t + 0.1);
  eg.gateOff(t + 0.4);
}, 1000);

Background

The Web Audio API is a fantastic new-ish API that lets you do sophisticated audio processing in the browser. One particularly important building block for audio synthesis is called an envelope generator (aka ADSR), and the API helpfully includes "automation" methods (AudioParam.linearRampToValueAtTime(), etc.) to make it easy to build those.

And if you build an envelope generator using those handy methods, it will sound good, being free of any weird pops or other sonic artifacts. ... Right?

Sadly, no. It turns out that it is rather tricky to build a well-behaved envelope generator given the API at the time of this writing (April 2017). For example, there are several other envelope generators on GitHub, but as far as I know they all have the issue that if a new envelope (gate-on) is started when a previous one is still playing, there will be a discontinuity that may result in a very audible click. (please hit me up if you know of any that avoid this issue!)

The authors of the API seem to be aware of this problem, and have spec'd an important new method called cancelAndHoldAtTime that will improve the situation, but that method is not yet implemented by most browsers. And even with that method, it's still somewhat tricky to build an envelope generator that handles edge cases properly and has a consistent sound.

So long story short, I really wanted a Web Audio envelope generator that worked correctly and handled all the various edge cases and so I tried to make one and it was not fun to make but I did it anyways and without further ado I humbly present to you (snare rush, please): Fastidious Envelope Generator.

Continuity, Shapes, Times

The most important feature of Fastidious is that if a new envelope is started when an old one is still in progress, there will be no unwanted discontinuity. The new envelope will start from where the old one is interrupted. This is how almost all analog synthesizer envelopes work, and usually sounds better than the alternative of restarting the new attack from zero. Abruptly transitioning an envelope to zero will likely cause an audible click if the envelope is not already at a low value.

As with most synthesizers, Fastidious lets you specify a time for each envelope phase. But per the previous paragraph, when a new phase starts, the value proceeds from where it last left off. So if a new attack starts when the value is already quite high, it has less distance to go before reaching 1. It turns out that it sounds more natural for the attack to always proceed at the same rate (taking less time perhaps) vs. always taking its nominal time to reach 1 (at a lower rate). So if you're the type who pays attention to minutiae, be aware that time parameters really equate to rates.

Fastidious generates envelopes with a (near-)linear attack shapes and exponential decay and release shapes. If a new attack starts from 0, it will reach 1 in attackTime seconds. Decay and release on the other hand are exponential decays that only asymptotically approach their target values. The decayTime and releaseTime parameters therefore don't represent the full time to reach their targets (sustainLevel or 0, respectively), but rather time constants, which is the time it takes for the values to get 1-1/e (about 63%) closer to their targets. To put it another way, the log of the distance from the values to their targets is a straight line, with slope of 1/time-constant.

API

new EnvGen(audioContext, targetParam)

Instantiate a new envelope generator

  • audioContext: Web Audio AudioContext object
  • targetParam: AudioParam to which envelope automation should be applied. There should be no other callers applying automation to the same AudioParam or all hell will break loose.

.gate(on, time)

Notify the envelope generator that its input gate is going on or off (aka high or low).

  • on: true for gate on/high, false for gate off/low
  • time: Optional indication of time when gate change is to take effect. If omitted, the gate change happens "now". If supplied, the time should be in the same coordinates as AudioContext.currentTime and >= that currentTime. Supplied gate times must be monotonically increasing, i.e. it's not allowed to schedule gates at times earlier than other gates that have already been scheduled.

Note: It is OK to send an 'on' followed by another 'on', or an 'off' followed by another 'off'. If an 'on' is sent when the last gate already 'on', then the envelope will behave as if there was an 'off' an infinitesimal time before the new 'on' (and vice verse for 'off' followed by 'off'). In some cases this will have no effect. But it can be useful e.g. in AD mode to only send gate-on notifications to trigger successive notes, without needing to ever send gate-offs.

.gateOn(time)

Convenience method that is equivalent to .gate(true, time).

.gateOff(time)

Convenience method that is equivalent to .gate(false, time).

.mode

The current mode or style of envelope being generated. Changes to this property will not take effect until after any current scheduled gate changes. Valid values are:

  • 'AD': Attack-decay envelope. The envelope will attack from 0 to 1, and then immediately decay back to 0. It has no sustain, and will always complete its full attack phase even if a gate-off arrives during it. This means that it ignores gate-off changes completely, and the width of incoming gates is irrelevant. This behavior is sometimes referred to as a "trigger" style envelope, and is useful for percussive sounds.
  • 'ASR': Attack-sustain-release envelope, also known as an AR envelope. This envelope will attack from 0 to 1, sustain at 1 for as long as the gate is held on, and then when the gate goes off will release back to 0. If the gate goes off during the attack, it will immediately transition to the release phase. Because the sustain will always be at full 1, the sustainLevel setting is irrelevant for this mode.
  • 'ADSR': Attack-decay-sustain-release envelope. This envelope will attack from 0 to 1, and then immediately decay to the sustainLevel for as long as the gate is held on. When the gate goes off it will release back to 0. If the gate goes off during the attack or decay phases, it will immediately transition to the release phase.

The default mode is 'ADSR'.

.attackTime

The time it takes for the attack phase to (almost-linearly) transition from 0 to 1, in seconds. Must be > 0. The default time is 0.5.

.decayTime

The time constant for the decay phase as it exponentially transitions to the sustain level (in ADSR mode) or 0 (in AD mode). Must be > 0. The default time is 1.

.sustainLevel

In ADSR mode, the level to which the envelope transitions after the attack phase completes. Must be >= 0 and <= 1. The default value is 0.5.

.releaseTime

The time constant for the release phase as it exponentially falls to 0. Must be > 0. The default time is 1.

.MODES

Array of valid .mode settings.