'hold' envelope segments...not holding when looking up with IEnvGen?

Hi – I’m trying to use IEnvGen to lookup flat/constant Envelope values, but it seems the \hold segment type is not working as I’d expect.

What I want is, for an envelope such as…

Env.pairs([[0, 1], [0.25, 2], [0.5, 3], [0.75, 4], [1, 4]], \hold).plot(minval:0, maxval: 5)

…whose plot looks like this…
HoldEnvelopePlot

…when looking up between (0 < index < 0.25), I’d like IEnvGen to return the first value (1). And so on – at index 0.4 the envelope would return 2, and at 0.6 it would return 3.

Instead, I get the lookup always getting “one index later” than I’d expect, as if I’d specified the \step interpolation type instead. So, for example, a lookup at index 0.2 actually returns 2 rather than 1.

From the docs:

type description
\step flat segments (immediately jumps to final value)
\hold flat segments (holds initial value, jump to final value at the end of the segment)

Here’s some example code with corresponding output, showing the problem:

(
var env = Env.pairs([[0, 1], [0.25, 2], [0.5, 3], [0.75, 4], [1, 4]], \hold);
"env.at(0.2) returned %".format(env.at(0.2)).postln;
Ndef(\holdEnv, {
	var c = [0, 0.2, 0.4, 0.6, 0.8];
	[c, IEnvGen.kr(env, c)].flop.poll(0);
	Silence.kr;
});
)

Outputs:

// env.at(0.2) returned 1     (as expected)
// -> Ndef('holdEnv')
// UGen Array [0]: 0
// UGen Array [0]: 1
// UGen Array [1]: 0.2
// UGen Array [1]: 2     (expected 1)
// UGen Array [2]: 0.4
// UGen Array [2]: 3     (expected 2)
// UGen Array [3]: 0.6
// UGen Array [3]: 4     (expected 3)
// UGen Array [4]: 0.8
// UGen Array [4]: 4

Doing the same thing, but with a \step-interpolated envelope segments gives the exact same result:

(
var env = Env.pairs([[0, 1], [0.25, 2], [0.5, 3], [0.75, 4], [1, 4]], \step);
"env.at(0.2) returned %".format(env.at(0.2)).postln;
Ndef(\stepEnv, {
	var c = [0, 0.2, 0.4, 0.6, 0.8];
	[c, IEnvGen.kr(env, c)].flop.poll(0);
	Silence.kr;
});
)

IEnvGen outputs the same thing (however, in this case, based on the definition of \step vs \hold, this is what I’d expect, and agrees with Env.at()!):

// env.at(0.2) returned 2
// -> Ndef('stepEnv')
// UGen Array [0]: 0
// UGen Array [0]: 1
// UGen Array [1]: 0.2
// UGen Array [1]: 2
// UGen Array [2]: 0.4
// UGen Array [2]: 3
// UGen Array [3]: 0.6
// UGen Array [3]: 4
// UGen Array [4]: 0.8
// UGen Array [4]: 4

I have a vague feeling I saw a question like this a while ago on the mailing list, but I’m having trouble finding it.

Any suggestions to get the result I want with IEnvGen and \hold envelope segments? Is this a bug, or a lack of understanding on my part?

Thanks,
Glen.

P.S. Using SC 3.9.1 on macOS.

(…and just upgraded to 3.9.3 [macOS] and problem is still there)

And with EnvGen, the envelope is correctly interpreted in all segments (as with sclang’s Env.at() method).

(
var env = Env.pairs([[0, 1], [0.25, 2], [0.5, 3], [0.75, 4], [1, 4]], \hold);
env.plot(minval: 0, maxval: 5);
{
	var t = Sweep.kr;
	[t, EnvGen.kr(env, doneAction: 2), IEnvGen.kr(env, t)].poll(label: ['t', 'EnvGen', 'IEnvGen']);
	Silence.kr;
}.play
)

Output:

t: 0.00145125
EnvGen: 1
IEnvGen: 1
t: 0.101587
EnvGen: 1
IEnvGen: 2
t: 0.201723
EnvGen: 1
IEnvGen: 2
t: 0.301859
EnvGen: 2
IEnvGen: 3
t: 0.401995
EnvGen: 2
IEnvGen: 3
t: 0.502132
EnvGen: 3
IEnvGen: 4
t: 0.602268
EnvGen: 3
IEnvGen: 4
t: 0.702404
EnvGen: 3
IEnvGen: 4
t: 0.80254
EnvGen: 4
IEnvGen: 4
t: 0.902676
EnvGen: 4
IEnvGen: 4

BTW I opened an issue in GitHub for this:

IEnvGen lookup: envelope ‘hold’ segment shapes handled the same as ‘step’

Thanks.

1 Like

I’m working on it this week. Hope to have a fix in by 3.10 (though it won’t be by the first beta)

1 Like