Stages retrigger behavior


Got Stages yesterday. What should it do when an envelope is retriggered while it hasn’t finished its run? The manual says “The first RAMP segment ramps up to 8V, starting from whatever level the output currently stays at.” but experience seems to contradict that… in weird (buggy?) ways:

I’m using two Ramps (AD), triggered by a steady clock, both times initially at minimum. I increase attack time until it exceeds the clock period; it should be retriggering from wherever it was, instead it suddenly jumps to zero and starts its ramp up again. The behavior is consistent with doc when the envelope is retriggered during decay.

Even weirder, this behavior doesn’t seem to be consistent: playing with A and D times I can get it to get stuck high while D time is zero, which contradicts the experience above. Steps to repeat:

  1. 2 Ramp segments, triggered by a clock with period T
  2. A and D times initially at zero
  3. increase D time to > T
  4. increase A time to > T
  5. decrease D time to 0 --> envelope stuck high.

Yet another weirdness: at step 4., if I increase A sufficiently slowly I sometimes get a rising sawtooth from ~5V to 8V, even though D time is >0. No way to reproduce this consistently.

Thanks for the bug report, I’ll investigate!

Do you know the pulse width of the clock?

So the first thing: when receiving a trigger changes the active segment (for example: D is the active segment, the trigger will make it go to A), the value is preserved; but when receiving a trigger does not change the active segment (A is the active segment, trigger will make it go to A), there is indeed a reset to the initial value.

I don’t understand your answer to my bug report. I was expecting either “yes it’s a bug” or “no it’s not because blah” and I get a new rule that’s nowhere to be found in the manual.

Are you saying that “retriggering an AD envelope during the A stage will reset the envelope to zero” is expected behavior?

Clock is t2 from Marbles at 50% PW, about 1Hz.

There’s a rule not specified in the manual, which is that when the envelope is retriggered while it is still at the first stage, it is reset to the initial value of this first stage.

But this doesn’t seem to explain everything you describe, so it’s just a partial answer (for now) and I need to investigate more.

Ok so IIUC you consider this to be expected behavior (letting the other parts of my problem aside for now). This sucks for me, because it makes it unusable as an envelope for 50% of my uses; from your sentence in the manual and from how 99% of the envelopes in the market work I understood before buying it would not be the case.

How hard will it be to fix it in software (disable the rule not mentioned in the manual), without breaking the rest?

Here’s a version of the firmware that disables this exception. (355.6 KB)

Update is done through the 6th channel (6th button pressed when powering the module on, signal in the 6th CV input, level adjusted by the 6th slider).

On a second look, this exception was put in place to make single segment (D envelope) retrigger, though there is another piece of code somewhere else handling this case already; so I’ll just get rid of it.

1 Like

Thanks. I’ll wait for you to check out the other oddities.

The other oddities were all side effects of the exception I mentioned.

Note that if you have A > T, it’s normal to get the envelope stuck high - since it never gets the opportunity to go into the decay phase and reset to 0. The A segment will retrigger itself and will tend to +8V.

The forced reset to zero is a convenient behavior in some case, not in others… Hard to come up with a rule! I’ve experimented a bit with a “first segment doesn’t retrigger itself” rule - it’s nice for clock division effects but it’s not benign!

Ok so this mean that the firmware version you linked above fix them, right?

I haven’t tested the patch but what should I expect:
1/ is a retrigger during the A phase “ignored” (constant slope, a la DUSG), or
2/ does it restart counting from zero to T, effectively changing the slope of the segment?

Yes, it is normal if the A segment is not supposed to reset, and in case 2/.

The firmware version I have linked above removes an exception that caused a segment retriggering itself or looping on itself to restart from its initial value – instead of restarting from the current value.

So it’s neither 1/ or 2/ - it is exactly what the manual states: restarting from its current value.

If you want a hard, unconditional reset to 0, put a HOLD segment with a null duration and a level of 0 at the front of your envelope.

1 Like

FWIW what you implemented is 2/: every time a trigger is received during attack, the time counter restarts from zero and counts to T. This means that if you trigger it with period e.g. T/2, and if the state is initially at 0, it will grow to 0.5, then to 0.75, then to 0.875 etc. getting closer and closer to 1.

This is unlike the DUSG family of envelopes, where a trigger during attack will be “ignored”: it will restart the segment with a duration that’s proportional to the remaining distance; in other words, the Attack/Release time knobs don’t actually control times but 1/(the segment slope). This is what allows Maths to act like a (crude) clock divider, but more importantly that’s what is “natural” if you take acoustic instruments for reference.

With Stages, if you want a “plucky” attack (a few milliseconds), you set the Attack slider almost all the way down; but because of what’s above, the character of the “pluck” will depend on the state of the output when it was triggered: it will sound plucky when the state was at 0, but if you retrigger it during Decay it will sound more dull.

1 Like

Agree. I just provided settings for all the permutations I could think of in the Piqued app in O&C. - see the Attack reset, Attack gt fall and DecRel reset settings in

I just picked this module up and was surprised to see this reset behavior as well because I’m coming from a Doepfer A-143-1.

Anyway, I made a little mod to make the reset behavior more like that.

 if (go_to_segment != -1) {
  //phase = 0.0f;
  const Segment& destination = segments_[go_to_segment];
	  start = *destination.start;
	  phase = 0.0f;
	  start = value;
	  phase = (go_to_segment == active_segment_) ? phase : 0.0f;
  //start = destination.start
  //    ? *destination.start
  //    : (go_to_segment == active_segment_ ? start : value);
  active_segment_ = go_to_segment;

The wav file with this tweak is attached. (353.0 KB)

1 Like

Sooo what does this change? :smiley:

It ignores triggers while you are in the attack stage.

Now I’m trying to modify the attack and decay ranges to match the very narrow, but very playable range of the A-143-1 (atk 5ms - 3sec, dcy 5ms-10sec). It’s proving to be a lot more tricky than I was expecting.

1 Like

Ah thats a nice mod! I do understand Emilies original decision to make it autoreset but i think this option is very useful in some scenarios.