ctrlEnv merge Event \type

Hey,
i normally use an event \type for passing envelopes into Patterns with this syntax:

~utils = ();
~utils.hasEnv = {
	var durSeconds = ~sustain.value / thisThread.clock.tempo;
    var envKeys = currentEnvironment.keys.select{|k|"[eE]nv$".matchRegexp(k.asString)};
    envKeys.do{|param|
        var value = currentEnvironment[param];
        if (value.isArray.not) { value = [value] };
        value = value.collect {|v|
            if (v.isRest) { v } {
                if (v.isKindOf(Env).not) { v = Env([v, v], [1]) }
            };
            v.duration = durSeconds;
        };
        currentEnvironment[param] = value;
    };
};

Event.addParentType(\hasEnv,(
    finish: ~utils[\hasEnv]
));

Pbind(
	\type, \hasEnv,

	[...]
	
	\finish, ~utils[\hasEnv],
);

lately i was trying to use looping ctrlEnvs with passed envelopes to modulate parameters from a source synth inside Patterns like this, which is working fine (the ctrlEnv is actually more like a LFO with .range i guess. EDIT: ive seen with the Auto Map Control Approach LFO and ModEnv could both be declared in the Pattern, which is really what im searching for.

(
SynthDef(\ctrlEnv, {
	var ctrlEnv = \ctrlEnv.ar(Env.newClear(12).asArray);
	var sig;
	ctrlEnv = EnvGen.kr(ctrlEnv, \gt.kr(1), doneAction: Done.freeSelf);
	sig = ctrlEnv.range(\ctrlMin.kr(0.1), \ctrlMax.kr(1.2));
	Out.kr(\out.kr(0), sig)
}).add;
)

(
Pdef(\source,
	Pbind(
		\type, \hasEnv,
		\instrument, \source,
		
		\dur, 4,
		
		\phase, ~bus[\ctrl][0].asMap,
		
		[...]
		
		\atk, 1,
		\sus, 2,
		\rel, 1,
		
		\gainEnv, Pfunc{|e|
			Env.linen(e.atk, e.sus, e.rel, curve: \sine)
		},
		\sustain, Pfunc { |ev| ev[\gainEnv].duration },
		
		\finish, ~utils[\hasEnv],
	)
);
)

(
Pdef(\ctrlEnv,
	Pbind(
		\type, \hasEnv,
		\instrument, \ctrlEnv,

		\dur, inf,

		\ctrlMin, 0.1,
		\ctrlMax, 1.2,

		\atk, 0.5,
		\sus, 1,
		\rel, 0.5,

		\ctrlEnv, Pfunc{|e|
			Env([0, 0, 1, 0], [e.atk, e.sus, e.rel], \sin, releaseNode: 2, loopNode: 0);
		},
		\sustain, Pfunc { |ev| ev[\ctrlEnv].duration },

		\out, ~bus[\ctrl][0],
		\group, ~ctrlGrp,
		\finish, ~utils[\hasEnv],
	)
);
)

(
Pdef(\source_ctrl,
	Ptpar([0, Pdef(\source), 0.0001, Pdef(\ctrlEnv)])
).play;
)

then ive seen this thread Composite notes: Auto-mapping synth controls to events where its own Event \type \notemap, declared in TempBus is used to modulate parameters inside patterns with passed envelopes. Now my question is how do i combine / merge both of the event \types? Because for all the other Envelopes beside the Ctrl ones i would still like to use \type \hasEnv in the source. Im sorry for my probably general misunderstanding of Events.
I really like the idea of PAutomation discussed there :slight_smile:

In this case, you’re lucky – since you’re only adding a finish function, you should be able to use addParentType for just about any one of the named event types. (“Should…”)

Btw if you put your hasEnv function into the addParentType environment for a given event type, it should be available automatically. It shouldn’t be necessary to write it again into each pattern. (If you find you do have to write it again, it may be a bug – the whole point of the event type parent is to override defaults or provide new defaults.)

If you have two or more play functions, that gets tricky. An automated function composition approach may work, or not.

hjh

so if i understand correctly, with having the ~utils function in my sc bootup file its addParentType with its finish function gets already applied to any Pbind i use, even if i put another \type for example \type, \notemap from your examples in my Pbinds, it already gets merged? im sorry when im on a totally wrong path with this.

EDIT: is there a way to see in the post window if the finish function gets applied when playing a Pbind?

Check the help for addParentType: “Define an alternative parent that is chosen on the basis of ~type.”

If you addParentType for \note, then the defaults should be automatically applied to events of type \note.

If you addParentType for \notemap, then the defaults should be automatically applied to events of type \notemap.

(If an alternate parent applies to any event, regardless of its \type key, then it wouldn’t make sense for addParentType to take a type symbol that wouldn’t be used. I.e., the method interface provides some clues about the behavior.)

There’s nothing to prevent you from adding the same parent environment for multiple types:

[... types in an array...].do { |type|
    Event.addParentType(type, (... my stuff...));
};

(Also, strictly speaking, none of this is about Pbind. This has to do with how events play themselves. It doesn’t matter whether an event came from Pbind or from another means.)

hjh

thanks a lot for your explanations @jamshark70. i think i have to look at some of the fundamentals of Event in more detail and also have to look at the auto mapping approach once more.

Im not sure about the difference between declaring ModControl.kr in the SynthDef and applying \lfo and ctlEnv like in the // LFO with depth envelope example compared with using \detunedFreq, in the // sliding pitches played in the default SynthDef example.

ive now added:

[\hasEnv, \notemap].do { |type|
    Event.addParentType(type, (finish: ~utils[\hasEnv]));
};

its working fine.
Only when i use it to modulate a parameter of a source synth (with the exact same configuration) inside PbindFx its not.

In the helpfile for PbindFx Ex. 6a: Source synth reading audio modulation signals from external buses it says that you have to apply the bus to the source synth like this:

// new group and bus for the modulation signal
g = Group.new;
a = Bus.audio(s, 1);

PbindFx([
        \instrument, \source,

        \modIn, a,
        // to enable this reading the fx chain check must know
        \otherBusArgs, [\modIn],
        \group, g,

    ],[
        \fx, \effect,
	
	[...]

    ]
);

which one is it when using TempBus?

I don’t know PbindFx, so I can’t comment on that.

Do remember that TempBus was a proof of concept – not finished code – not really intended for anyone to rely on for a real project. With a new semester approaching, I might not always have time to support, or create examples for, experimental code.

Rereading the code from months ago (I already forgot how TempBus works :laughing: ), I see that the \notemap event type detects the output rate of the synth that will be created for the sub-event, and creates the bus for you, and automatically maps the bus. So there is no “you have to apply the bus.”

b = Buffer.read(s, Platform.resourceDir +/+ "sounds/a11wlk01.wav");

(
SynthDef(\pvVocoder, { |out, gate = 1, amp = 0.1|
	var eg = EnvGen.kr(Env.asr(releaseTime: 0.1), gate, doneAction: 2);
	var in = NamedControl.ar(\in, 0);
	var mod = NamedControl.ar(\mod, 0);
	var infft = FFT(LocalBuf(256), in);
	var modfft = FFT(LocalBuf(256), mod);
	var sig;
	
	infft = PV_MagMul(infft, modfft);
	sig = IFFT(infft);
	Out.ar(out, (sig * amp * eg).dup);
}).add;

SynthDef(\chord, { |out, gate = 1, amp = 0.05|
	var oscs = Saw.ar(([48, 53, 55, 58, 62, 69].midicps *.x [1, 1.008]).flat).sum;
	var eg = EnvGen.kr(Env.asr(releaseTime: 0.1), gate, doneAction: 2);
	Out.ar(out, oscs * eg * amp);
}).add;

SynthDef(\loop, { |out, gate = 1, bufnum, amp = 1|
	var loop = PlayBuf.ar(1, bufnum, loop: 1);
	var eg = EnvGen.kr(Env.asr(releaseTime: 0.1), gate, doneAction: 2);
	Out.ar(out, loop * eg * amp);
}).add;
)

(
(
type: \notemap,
instrument: \pvVocoder,
amp: -5.dbamp,
sustain: 10,
in: (instrument: \chord, sustain: 10, addAction: \addBefore),
mod: (instrument: \loop, bufnum: b, sustain: 10, addAction: \addBefore)
).play;
)

hjh

hey, thanks so much for you explanation and the always great examples of code, i learned so much already :slight_smile:

creates the bus for you, and automatically maps the bus.

that was the reason that made me thinking you cant apply the bus.
without its seems not to work inside PbindFx.
probably i then leave the auto mapping behind for now. unfortunately with the regular bus mapping its such a huge amount of code just for modulating one synth parameter, which was the reason for looking out for an alternative solution for organising control structures. Or i write everything in the SynthDef, lets see :slight_smile:

what exactly is *.x doing?

thanks :slight_smile:

I’d guess notemap is mapping the buses in one way to produce a composite audio source, and PbindFx is piping that into an effect synth, which are separate operations, so I’m not sure why they would be incompatible. But I don’t know PbindFx.

notemap is not designed for a persistent fx synth spanning multiple events, so make sure you’re not using it for that.

Help system → adverbs.

hjh