How to trigger an enveloppe that will go from 0 to 1 and stay at 1 until next trigger


#1

Hello !

How do I make an envelope that will go from 0 to 1 in 100ms and will stay at 1 until the next trigger ?

My code is as follows :

(
{
    var trig, tempo, drone, note;
    note = 41; // fa
    tempo = 70/60;

    trig = TDuty.kr(Dseq([Dwrand([1/3, 2/3], [0.9, 0.1], 1), 1/3, 1/3, 1],inf) / tempo +Dwhite(-0.01, 0.01,inf));

    drone = Splay.ar( (1..10).collect({ |i|
        Saw.ar(
            freq: note.midicps * i,
            mul: 1/i
        )
    }));

    drone = drone * EnvGen.ar(
        envelope: Env.asr(0.1, 1.0, 0.1), // this is obviously not the right enveloppe
        gate: trig
    );

    drone
}.play
)

Any clue ?
Thanks in advance

Geoffroy


#2

Hi,

have a look at the releaseNode / loopNode examples of the Env helpfile, there are quite tricky cases

http://doc.sccode.org/Classes/Env.html#examples

(
// you need a start segment, the loop will begin at the target of the first segment
e = Env.new([0, 0, 1], [0.1, 0.1] * 0.01, 'lin', nil, 1);
e.plot;
{ EnvGen.ar(e, Impulse.ar(100)) }.plot(0.1);
)


// due to the delay of the Env at start you'd need to 
// introduce a delay with the frequency sequence (if you need one at all)

// wrap freq with Clip as Saw with 0 produces a bump

(
{
    var trig, tempo, drone, note, att = 0.1, rel = 0.1;
    tempo = 70/60;

    trig = TDuty.ar(
        Dseq([Dwrand([1/3, 2/3], [0.9, 0.1], 1), 1/3, 1/3, 1],inf) / tempo +
        Dwhite(-0.01, 0.01,inf)
    );
    note = Demand.ar(trig, 0, Dwhite(60, 90));

    drone = Splay.ar((1..10).collect({ |i|
        Saw.ar(
            freq: Clip.ar(DelayL.ar(note.midicps * i, 0.3, rel).poll, 50, 5000),
            mul: 1/i
        )
    }));

    drone = drone * EnvGen.ar(
        envelope: Env.new([0, 0, 1], [att, rel], 'lin', nil, 1),
        gate: trig
    );

    drone
}.play
)

As Delay etc. feels a bit quirky It might be worth considering PmonoArtic.

Greetings

Daniel


#3

Thanks a lot Daniel !

I could not understand the releaseNode, loopNode and offset arguments in the Env documentation.

It makes a bit more sense now.

I also found another workaround, which is to use 1 - a perc enveloppe, like

(
{
    var trig, tempo, drone, note;
    note = 41; // fa
    tempo = 70/60;

    trig = TDuty.kr(Dseq([Dwrand([1/3, 2/3], [0.9, 0.1], 1), 1/3, 1/3, 1],inf) / tempo +Dwhite(-0.01, 0.01,inf));

    drone = Splay.ar( (1..10).collect({ |i|
        Saw.ar(
            freq: note.midicps * i,
            mul: 1/i
        )
    }));

	drone = drone * (1 - EnvGen.kr(
		envelope: Env.perc(0.01, 0.3),
		gate: trig
	));

}.play
)

But that was a hack and I am happy to better understand looping enveloppes now.

Thanks again !


#4

Re-reading your solution Daniel, I’m trying to understand loop envelopes a bit more and I’m a bit confused.

Using SC 3.10.0

(
e = Env.new(levels: [0, 0, 1, 2], times: [0.1, 0.2, 0.3]);
{
	EnvGen.kr(envelope: e, gate: Impulse.kr(1));
}.plot(duration: 2, minval: -0.1, maxval: 2.1);
)

gives :
38

and specifying another loopNode does change anything.

(
e = Env.new(levels: [0, 0, 1, 2], times: [0.1, 0.2, 0.3], loopNode: 2);
{
	EnvGen.kr(envelope: e, gate: Impulse.kr(1));
}.plot(duration: 2, minval: -0.1, maxval: 2.1);
)

brings

38

Does it mean loopNode only works with a set releaseNode ?

Thanks !


#5

You’re right.
Although my example works as it is it doesn’t use the loopNode feature.
When using the loopNode it also needs a different kind of trigger definition,
in this case looping is done without trigger, only release is triggered, but in
the opposite way, by setting gate to 0.

(
e = Env.new(levels: [0, 1, 2, 0], times: [0.1, 0.2, 0.5], loopNode: 0, releaseNode: 2);
e.plot;
{
    EnvGen.ar(envelope: e, gate: Trig.ar(1, 1.2), doneAction: 2);
}.plot(duration: 2.5, minval: -0.1, maxval: 2.1);
)

#6

Thanks a lot Daniel !

It’s a bit weird that the releaseNode is actually the node at levels[2] (value = 2) where the loopNode is the node at levels[0+1] (value = 1).

I tried another example and this is the case

(
e = Env.new(levels: [0, 1, 2, 3, 4, 0], times: [0.1, 0.2, 0.1, 0.1, 0.5], loopNode: 1, releaseNode: 4);
e.plot;
{
    EnvGen.ar(envelope: e, gate: Trig.ar(1, 2.05), doneAction: 2);
}.plot(duration: 3, minval: -0.1, maxval: 4.1);
) 

It’s definitely looping back at node levels[loopNode+1] (value = 2)

Not a big deal, it works :slight_smile: