Access each element from a multichannel expansion Env

Hi!

Is it possible to access each element of a multichannel expanded Env and still get an array of Env classes?

I am being able to access the elements but converting them to a Signal:

Env([1e-9,1,1e-9],[0,1], [[\lin, \exp, \sin, \wel, \sqr, \cub]]).asMultichannelSignal

I would like to retain the Env class to use them in a GUI:

(
var w;
w = Window("Bank of envelopes", Rect(500, 200, 630, 430));

w.view.decorator = FlowLayout(w.view.bounds);

([Env([1e-9,1,1e-9],[0,1], \lin), Env([1e-2,1,1e-2],[0,1], \exp), Env([1e-9,1,1e-9],[0,1], \sin), Env([1e-9,1,1e-9],[0,1], \wel)]).do({ arg i;
	i.postln;
	b = EnvelopeView(w, Rect(0, 0, 100, 100))
    .drawLines_(true)
    .selectionColor_(Color.red)
    .drawRects_(true)
    .resize_(5)
    .step_(0.01)
	.mouseDownAction_({arg b; [b.index, b.value].postln; Ndef(\test, { SinOsc.ar([350, 351.3, 700, 703,4], 0, 0.2) + WhiteNoise.ar(0.1)* EnvGen.ar(i,doneAction: 2)}).play;})
    .thumbSize_(10)
	.setEnv(i)
	.grid_(Point(0.1, 0.1))
	.gridOn_(true);
});

w.front;
)

Thanks!

You can use .asArray or .asMultichannelArray, and then back with Env

Env(Env.asr.asMultichannelArray)

[ [ 0, 2, 1, -99, 1.0, 0.01, 5, -4.0, 0, 1.0, 5, -4.0 ] ]

-> an Env

.asMultichannelArray is returning some strange format… .asMultichannelSignal is working as expected, although for filling an Env you need to have an Array.

After the .asMultichannelSignal I can cast the Signal into an Array but it is giving me an Env with tons of points, and not the “analytic” three point envelope specified before. Here Is the working “hack”:

(
var w;
w = Window("Bank of envelopes", Rect(0, 0, 630*2, 430*1.6));

w.view.decorator = FlowLayout(w.view.bounds);

(Env([1e-2,1,1e-2],[0,1], [[\lin, \exp, \sin, \wel, \sqr, \cub]]).asMultichannelSignal).do({ arg item, i;
	i.postln;
	item.postln;
	b = EnvelopeView(w, Rect(0, 0, 200, 200))
    .drawLines_(true)
    .selectionColor_(Color.red)
    .drawRects_(true)
    .resize_(5)
    .step_(0.01)
	.mouseDownAction_({arg b; [b.index, b.value].postln; Ndef(\test, { SinOsc.ar([350, 351.3, 700, 703,4], 0, 0.2) + RLPF.ar(WhiteNoise.ar(0.1),350,0.0625)* EnvGen.ar(Env(item.as(Array)),doneAction: 2)}).play;}) /* for tweaking the behavior of action_() of a GUI check View help for more options */
    .thumbSize_(10)
	.setEnv(Env(item.as(Array)))
	.grid_(Point(0.1, 0.1))
	.gridOn_(true);
});

w.front;
)

And here is how I would like it to be:

(
var w;
w = Window("Bank of envelopes", Rect(0, 0, 630*2, 430*1.6));

w.view.decorator = FlowLayout(w.view.bounds);

([
	Env([1e-9,1,1e-9],[0,1], \lin), Env([1e-2,1,1e-2],[1e-9,1.0], \exp), Env([1e-9,1,1e-9],[0,1], \sin), Env([1e-9,1,1e-9],[0,1], \wel), Env([1e-9,1,1e-9],[0,1], \sqr), Env([1e-9,1,1e-9],[0,1], \cub),

]).do({ arg i;
	i.postln;
	b = EnvelopeView(w, Rect(0, 0, 200, 200))
    .drawLines_(true)
    .selectionColor_(Color.red)
    .drawRects_(true)
    .resize_(5)
    .step_(0.01)
	.mouseDownAction_({arg b; [b.index, b.value].postln; Ndef(\test, { SinOsc.ar([350, 351.3, 700, 703,4], 0, 0.2) + RLPF.ar(WhiteNoise.ar(0.1),350,0.0625)* EnvGen.ar(i,doneAction: 2)}).play;}) /* for tweaking the behavior of action_() of a GUI check View help for more options */
    .thumbSize_(10)
	.setEnv(i)
	.grid_(Point(0.1, 0.1))
	.gridOn_(true);
});

w.front;
)

BTW: I’ve just find out that this is working properly:

Env([1e-9,1,1e-9],[0,1], \exp).plot;

However when inserted into EnvelopeView I need to use something like Env([1e-2,1,1e-2],[0,1], \exp).plot; in order to get a plot of an exponential curve. I am missing something with the way of plotting envelopes?

That’s certainly a possible data manipulation – I guess the questions are two-fold: 1/ Is there a built-in method for this? 2/ If not, how to do it?

1/ It seems that the answer is no…?

2/ This appears to be tricky. Normally, multichannel expansion is related to “flop,” but the array geometry is different for Env:

// this array geometry will give you the right "flop"
[
	[ [1e-9, 1, 1e-9] ],
	[ [0, 1] ],
	[ \lin, \exp, \sin, \wel, \sqr, \cub ]
].flop

// but we have...
[
	[1e-9, 1, 1e-9],
	[0, 1],
	[ [ \lin, \exp, \sin, \wel, \sqr, \cub ] ]
]

… so flop won’t work correctly. This is probably why there’s only asMultichannelArray.

I can’t think of a really good way, but at least it would be reliable to unpack the multichannel array.

e = Env([1e-9, 1, 1e-9], [0, 1], [[\lin, \exp, \sin, \wel, \sqr, \cub]]);

f = e.asMultichannelArray.collect { |array|
	var curves = Array.new;
	var i = 6;
	while { i < array.size } {
		if(array[i] == 5) {
			curves = curves.add(array[i+1])
		} {
			curves = curves.add(Env.shapeNames.findKeyForValue(array[i]))
		};
		i = i + 4;
	};
	Env(array[0, 4..], array[5, 9..], curves, array[2], array[3])
};

hjh

1 Like

Generally, I use the following trick for this phenomenon:

// { Env([0,1,0],[0,1], \exp).kr }.plot(1);
{ Env([1,2,1],[0,1], \exp).kr - 1 }.plot(1);

// { SinOsc.ar * (Env([0, 1, 0], [0.01, 0.99], \exp).kr)}.play
{ SinOsc.ar * (Env([1, 2, 1], [0.01, 0.99], \exp).kr - 1) }.play

However, I could not configure this into your code block. I am very sorry.

Anyway, the following code is the last version I worked on further based on @jamshark70’s instructions. I tried to resolve the exponential curve, including 0, differently than mentioned above but could not fix it. You may see the sketch in the comments, which is not working.

(
var win, e, f;
w = Window("Bank of envelopes", Rect(0, 0, 205*6, 205));

w.view.decorator = FlowLayout(w.view.bounds);

e = Env([0.01, 1, 0.01], [0, 1], [[\lin, \exp, \sin, \wel, \sqr, \cub]]);

/*
e = Env([1, 2, 1], [0, 1], [[\lin, \exp, \sin, \wel, \sqr, \cub]]);
e = e.range(0, 1)
*/

f = e.asMultichannelArray.collect { |array|
	var curves = Array.new;
	var i = 6;
	while { i < array.size } {
		if(array[i] == 5) {
			curves = curves.add(array[i+1])
		} {
			curves = curves.add(Env.shapeNames.findKeyForValue(array[i]))
		};
		i = i + 4;
	};
	Env(array[0, 4..], array[5, 9..], curves, array[2], array[3])
};

f.collect{ |i, index|
	i.postln;
	EnvelopeView(w, Rect(0, 0, 200, 200))
	.drawLines_(true)
	.drawRects_(false)
	.mouseDownAction_{
		[index, i.totalDuration, i.levels, i.times, i.curves].postln; 
		{ 
			(
				SinOsc.ar([350, 351.3, 700, 703,4], 0, 0.2).sum
				+ 
				RLPF.ar(WhiteNoise.ar(0.1),350,0.0625)
			)
			* (EnvGen.ar(i, doneAction: 2) - 0.01)
		}.play;
	}
	.setEnv(i)
	//.value_([i.times, i.levels])
	.grid_(Point(0.1, 0.1))
	.gridOn_(true)
};

w.front;
)
1 Like

@jamshark70 and @prko thanks a lot!

After more problems with this multichannel expansion I’ve decided that the safer option is to do traditional iteration:

a = [\lin, \exp, \sin, \wel, \sqr, \cub].collect({|x|[Env([0.01, 1, 0.01], [0, 1],x),Env([0.01, 1, 0.01], [1, 0],x)]});

BTW, is there any quark with more options for Env ?

Here is the final version:

a = [\lin, \exp, \sin, \wel, \sqr, \cub].collect({|x|[Env([0.01, 1, 0.01], [0, 1],x),Env([0.01, 1, 0.01], [1, 0],x)]});

(
var w;
~dur=2.0;
w = Window("Bank of envelopes", Rect(0, 0, 105*6, 105*2));

w.view.decorator = FlowLayout(w.view.bounds);

a.flop.flat.do({ arg i;
	i.postln;
	b = EnvelopeView(w, Rect(0, 0, 100, 100))
	.drawLines_(true)
	.selectionColor_(Color.red)
	.drawRects_(true)
	.step_(0.01)
	.mouseDownAction_({arg b; [b.index, b.value].postln; Ndef(\test, { SinOsc.ar([350, 351.3, 700, 703,4], 0, 0.2) + RLPF.ar(WhiteNoise.ar(0.1),350,0.0625)* EnvGen.ar(i,doneAction: 2)}).play;}) /* for tweaking the behavior of action_() of a GUI check View help for more options */
	.thumbSize_(10)
	.setEnv(i)
	.grid_(Point(0.1, 0.1))
	.gridOn_(true);
});

w.front;
)
1 Like