Attack Decay Sustain Release Attack Curve Decay/Release Curve Plot:linearlog

This is the widget I used in making the ADSR video. It’s a JavaScript recreation of my C++ source code.

This entry was posted in Envelope Generators, Synthesizers, Widgets. Bookmark the permalink.

### 11 Responses to Envelope generators—ADSR widget

1. Jon Wolski says:

Does this connect to the Web Audio API?

• Nigel Redmon says:

No…just a widget to see the ADSR in action…

2. Tom Maisey says:

This is really great, but it would be better if you could see the values that the sliders correspond to. That way you can get a feel for the ranges of useful targetRatios.

• Nigel Redmon says:

Hi Tom—You’d be surprised how little help it would be. If you want it linear, then pretty much any large value will do (something like 15 will look pretty straight here—go ahead and pick 200). If you want an exponential segment, you’ll have to switch to log view to have a clue as to how it will sound. For the Decay and Release segments, the smaller the value, the more exponential—0.0001 decays to -80 dB, so you’re probably not going to hear the difference with anything smaller. See the ADSR Part 2 article for more details (“More math”).

So, that leaves the Attack Curve adjustment. It’s really unlikely you’d want anything close to exponential shape for the Attack segment—the range I’m giving it here are for illustrative purposes, mainly to show how wrong it would be to use that shape. Most likely, you would either want it to be linear, or simulate classic analog ADSRs by targeting something around 1.3 as the asymptote of the curve. We don’t care about dB here, just the ratio of the overshoot to the envelope peak. The peak is always 1.0, so the ratio is always just the amount over 1.0, in this case 0.3. For instance, in a 10v peak ADSR running on a 15v supply, that corresponds to a 13v target (asymptote), a typical design choice. So, in practical applications, the ratio will be either 0.3 or something pretty close to that, or a large number (200).

I concede that the values would be a little useful for decay when switched to log display. You can see that on the log display, the decay appears pretty linear, then drops off abruptly at a certain dB down. But the controls are pretty rough, and it’s easy enough to calculate. If you want it to drop off abruptly at -40 dB, then 10 raised to the power of -40/20, which equals 0.01 (0.001 for -60 dB, 0.0001 for -80 dB…).

An aside: Just like the attack target, the decay target is the asymptote of the curve on the other side of the target. So in a real world analog ADSR, it’s not practical to shoot for the precision we have with the -80 dB setting (or at least that would be the far reaches of practical analog). The ADSR might be biased slightly negative to avoid the VCA leaking (the VCA might be biased too for the same reason). But even if everything is designed with precision, -80 dB might be a little much to ask, since it would require no more than 0.001v (a millivolt) offset for a 10v peak envelope, better precision than the analog components have without precision trimming.

As far as going for even more precision (because we can, in software), it makes little sense. For instance, you could shoot for -120 dB on the curve for a more perfect exponential, but it would just sound like the envelope time is shortened (because we set the rate by number of samples—setting 4 seconds worth of decay to -80 dB will sound a lot longer than 4 seconds to -120 dB, since we’re not going to hear much more when it gets below -80 dB). So, I figure something in the -60 to -80 dB range is going to simulate an analog ADSR pretty well. And again, a big number if you want linear, and probably little use for anything in between.

So, that’s the long story of why the slider numbers aren’t very useful. In the case of either attack or decay/release, there a relatively small range of useful values that make sense for a curved segment, plus a single large number suitable for simulating linear.

Nigel

• Tom Maisey says:

Nigel,

Thanks for your extensive reply! That actually cleared up quite a few points for me. I’m building a synthesiser, and I’ve found envelopes, which I thought would be the easiest component to nail, more tricky than I thought to get sounding ‘right’. You have helped immensely.

Your site is by far and away the best that I’ve found on the internet that explains the murky secrets of audio DSP. Many thanks.

3. nefelia says:

Hey Nigel,

thanks for the great tutorials. Which language do you use to write the widgets? Is it possible for you to share the ADSR Widget source code?

cheers,
nefelia

• Nigel Redmon says:

Hi Nefelia,

They are written in javascript, so if you use a debugger in your browser, you can see and retrieve the source code easily. For instance, ADSR.js is a javascript translation of the C++ code, and drawADSR.js handles the drawing via the charting utility flotr.js (which uses jquery.js and prototype.js—flotr2 doesn’t have those dependences).

Nigel

4. Ben says:

Hello,

Thank you for all the good information on your site. I just discovered it 2 weeks ago, I’m trying to catch all and there’s a lot.
Selecting the Plot=”log” options seems to prevent any action of the sliders.

• Nigel Redmon says:

Thanks! Fixed now—I made changes when updating the plot engine from flotr to flotr2 recently, and didn’t update the log case.

5. Victor says:

Hi Nigel,

First of all, thanks for writing this blog, I am learning so much from it! And with all the exelent examples it is a pleasure to read as well.

I had a look at the JavaScript code and in particular the following line:

return Math.exp(-Math.log((1.0 + targetRatio) / targetRatio) / rate);

You mentioned in the ADSR articles leading to this widget that “… the constant 1 is because we are moving a distance of 1 (0.0 to 1.0, or 1.0 to 0.0) …”. Am I correct that the widget does not take into account that for decay we move from 1.0 to sustainlevel and for release we move from sustainlevel to 0?

• Nigel Redmon says:

Right. The easiest way to see how it behaves is with the ADSR widget—move sustain up and down, and you’ll see that it takes the same amount of time to decay to sustain, and to release to zero. That way, it maintains the useful property of being able to set the decay and release time, unaffected by the sustain level (a big advantage for things like auto-retriggered envelopes). It also means that the ADSR doesn’t need to recalculate decay and release times as the sustain level is moved.