VCV Fundamental ADSR Timing does not match settings

I’ve never worked with hardware modular, and I’ve only been using VCV for less than 1 year.

I decided to time the various stages of the VCV Fundamental. Not the easiest thing to do precisely, as there are no gates or triggers indicating when each stage transitions to the next. But I was shocked by how off my timings are compared to the settings on the various parameters.

It does not seem to make a difference between V1 and V2 - qualitatively they seem the same. Also it does not seem to make much difference for very short, medium, or long stage lengths. They all seem equally “wrong”.

I’ll just give some numbers for the ADSR in V1:

I used the Submarine LA-108 and HS-101 to take measurements.

I set Attack, Decay, and Release all to 1000ms (1 sec), and the Sustain to 50%. I held the gate open until the Decay light went out, and then released as quickly as my reflexes would allow. Here are the measurements I gathered

Attack stage - 1.7 sec, reached 10V

Decay stage - 4.3 sec, reached 5.08V. That is 80mV higher than I expected

Release stage - ~5 sec to reach 0.08V (I assume the tolerance should be consistent)

The Attack timing is the only one that seems close to reasonable, but it is still off much more than I expected. The others are waaaaayyyy off. And the results are repeatable.

Also, I was a bit surprised the decay/release voltage tolerances were as high as ~ 80 mV as best as I could tell. My guess is it might be as high as 0.1V.

Are timings typically off that much in the modular world? Should I expect envelope timings to be very rough estimates. To my eyes those numbers are even worse than rough estimates.

Also, what voltage tolerances should I expect?

I did a quick check of the Bogaudio DADSR(H)+, which is much easier with the stage gates. I did the same basic test, and everything was spot on - both timings and voltages.

So which is more representative of a “typical” envelope generator?

Nothing is typical. Different people care about different things.

Be very careful measuring things and publishing the results - it’s gotten me several threats of banishment. But you seem a lot nicer than me. :wink:

Hopefully measurements in and of themselves are not controversial. I definitely went out of my way to not pass judgement on quality, especially since I am so inexperienced. I honestly don’t know if my results are typical or expected in the modular world.

When I watch videos of hardware synths, especially analog, people seem to dial in settings by ear, and/or with a scope or tuner. Graduations on knobs don’t seem to be as important. So maybe the difference between the digital parameter setting and the actual result doesn’t surprise a lot of people. But for me it was totally unexpected.

I tend to tune envelopes by ear and VCV envelopes work really well. I’m enough of a nerd to appreciate your measurements, but they would only matter if you cared down to the millesecond about timing.

Well, I agree that we often tune these things by ear, and that’s a very easy and normal way to deal with this stuff. But why put numbers in the UI if they are wrong?

I often put in arbitrary numbers when I don’t’ think it matters, like in the ADSRs in Kitchen Sink - they go from 0 to 100 and I never say/claim that those numbers mean anything. That works for me.

[ btw, the ADSR code in Kitchen Sink? I took it from Fundamental ADSR - I like that module. I don’t actually remember if the times in that are “correct”, I just tuned my module so the knobs felt right to me. ]

Other times I do put numbers in the UI. Then I usually try to make sure the numbers are correct. Look at this:

ADSR in Kitchen Sink? I’m not going to tell what the values really are. But Comp? I put 4:1 in there

How do I know it’s 4:1? I have unit tests that measure it, and fail if they are wrong. It I didn’t, I can tell you from past experience that my number would be all over the place, and usually wrong. Here’s part of a test for the compression ratios:

static void testLookupAboveThesh(const CompCurves::Recipe& r, std::function<float(float)> lookup, double acceptedError) {

    //SQINFO("in test ratio=%f knee=%f", r.ratio, r.kneeWidth);

    const float topOfKneeDb = r.kneeWidth / 2;
    const float topOfKneeVin = float(AudioMath::gainFromDb(topOfKneeDb));
    const float dbChangeInInput = 20;  // arbitrary, let's pick 20 db
    const float voltChangeInInput = (float)AudioMath::gainFromDb(dbChangeInInput);
    const float vIn1 = 2;  //gain of 2 and we are over threshold, just barely
    const float vIn2 = vIn1 * voltChangeInInput;
    const float gain1 = lookup(vIn1);
    const float gain2 = lookup(vIn2);
    const float vOut1 = vIn1 * gain1;
    const float vOut2 = vIn2 * gain2;
    const double inputDbChange = AudioMath::db(vIn2) - AudioMath::db(vIn1);
    const double gainDbChange = AudioMath::db(gain2) - AudioMath::db(gain1);
    const double outputDbChange = AudioMath::db(vOut2) - AudioMath::db(vOut1);
    const double x = outputDbChange * r.ratio;
    assertClose(x, inputDbChange, acceptedError);
} 
2 Likes

If things were only off by a few milliseconds, then I never would have posted this topic. But for Decay and Release phases we are talking about being off by 400 to 500%. That is hardly milliseconds for a 10 second stage. Tuning by ear, no problem. But I would like to be able to at least get close based on calculations, and then fine tune by ear. The parameter values and documentation imply I can do that, but it simply doesn’t work.

For example, I am in the midst of building a bunch of basic constructs using only VCV Fundamental modules. One of the projects is to build an Attack, Decay, Hold, Release envelope generator using the ADSR as the core. One of the goals is to be able to put the EG in loop mode, effectively turning it into a complex LFO. I’ve got it working better than I ever expected. But I would like to be able to dial in the stage lengths to achieve a specific LFO frequency (within reason). It is pretty difficult. If the ADSR parameter values were fairly accurate, then it would be easy.

I’m deriving gate outputs for each stage, so it is not hard to measure. But it is tedious.

Side note - the gates make it easy to apply various LFO modulations independently to each stage, with the ability to sync the phase of the modulating LFO to the stage start for consistent results. Pretty cool! Very easy to dial in some wild envelopes. (as long as I don’t care about absolute lengths!)

I know there are existing plugins that do all this with a single module. But I enjoy the challenge of getting the desired result with only Fundamental modules.

1 Like

I ended up submitting a bug report to support after reading a response from mosphaere about a similar issue with the RANDOM module’s rate parameter question of understanding s&h rate - #9 by mosphaere

btw: I notice there is still a github issues database for Fundamental. I’ve been entering bugs there. Is that no long the right way to log bugs in Fundamental?

According to the official https://vcvrack.com/support page

For assistance with your VCV account, feature requests and bug reports for VCV products, the VCV Library, and business/private requests, email support@vcvrack.com or use the contact form on this page.

I think I remember reading about that when I first starting using VCV ~9 months ago. But then I vaguely remember reading an announcement there was a change to how bugs should be reported. The web site seems pretty clear though.

It was just confusing because the github issues page for VCV went away, so ii was obvious there. The fact that VCV issues went away, but Fundamental issues stayed was confusing to me.

Yes, that support page, which is new, is fairly clear. I guess we can assume that when @Vortico removed/hit the issues from VCV he forgot to do it for the Fundamental plugins.

if you use BZ-envelope or b208 envelope, you’ll see declared times are respected… :smiley:

I have some skewing in the others but when you turn the linear to exp mode knob