Pattern keeping track of updated Pairs, similar to Pfunc{}

Hello!
I have multiple patterns sharing arguments which are stored in a dictionary. and to minimize code and for usability reasons, i used to give those arguments simple in the “Pairs” argument of the Patterns. However now I realized, that i want to change those arguments and keep those patterns adapt to this. Typically, I would use Pfunc{} for keeping track of argument changes, but it doesn’t work for Pairs. Is there a way to make it work or is there another workaround for this?

I provide some example code to clarify what i mean:

~a = Dictionary.with(\amp->0.3);
//this works for changing the amp in ~a, that the pattern picks it up
(
p = Pbind(
	\amp, Pfunc{~a[\amp]}
).play
)
~a[\amp] = 0.1;
~a[\amp] = 0.3;
p.stop;
//this doesnt work to track the amp of ~a when not in a Pfunc
(
p = Pbind(
	*~a.asPairs
).play
)
~a[\amp] = 0.1;
~a[\amp] = 0.3;
p.stop;

Thank you very much!!

Hi,

there are numerous ways to manipulate the contents of a Pattern. A Pbind by itself isn’t really laid out to be manipulated but e.g. Pbindf or PatternProxy might be useful? You possibly would have to adapt your strategy a bit but I think that could make a flexible framework for your purposes.

Pchain(Pbind(... new stuff...), Pfunc { ~a }) I think.

hjh

mhm, this doesn’t work Pchain chains patterns and not dictionaries or pairs. Maybe somehow differently it might work?

thanks for the response.
Not entirely sure how exaclty, u mean like this?
Pbindf(Pbind(),*~a.asPairs).play
I mean im still not able to set ~a as a function or somehow.

Not true. Try it. It won’t work for pairs but it’s fine for events. (Though, the Pfunc solution that I proposed [99% sure it will work] does use a pattern to preset the event values, so the objection doesn’t apply to that.)

hjh

But I mean, I’ve tried:

~a = Dictionary.with(\amp->0.1);
Pchain(Pbind(), Pfunc { ~a }).play;

but It doesnt work, post window tells me:

[…]
^^ ERROR: Message ‘playAndDelta’ not understood.
RECEIVER: Dictionary[ (amp → 0.1) ]

Or how exactly did you mean that i implement it? Also ~a.asPairs didn’t work.

Oh, I just found out, I was not quite right about Pbindf - rather than just replace key/value pairs in the Pbind it creates a new EventStreamPlayer. My bad. Anyway, I don’t really understand what you mean by “I mean im still not able to set ~a as a function” - ~a is some kind of Dictionary. It wouldn’t make sense to redfine it as function. I think using a Pfunc like you did isn’t a bad idea. However, the Dictionary should not just hold numbers as values but Pfuncs:

~a = 0.3;
~pairs[\amp] = Pfunc { ~a };

(
~pbind = Pbind(
    *(~pairs.asPairs)
)

// 'playing' a Pbind returns an EventStreamPlayer, not the Pbind
p = ~pbind.play;

// should update amplitude
~a = 0.7

Would this be a way to go?

1 Like

Yeah this would be a way to go. it makes the code a bit uglier but i can live with that. thank you very much!!!

Or actually, with this helper function ive just build, I can just implement everything as before, without making anything ugly:

(
~pbind_pairs = {|dict|
	var dict_new = Dictionary.new();
	dict.keys.do{|key|
		dict_new[key]= Pfunc{dict[key]}
	};
	dict_new.asPairs;
};
)

~a = Dictionary.with(\amp->0.3);
(
p = Pbind(
	*~pbind_pairs.value(~a);
).play
)
~a[\amp] = 0.1;
~a[\amp] = 0.3;
p.stop;

Thanks once again!

Use an Event instead of a Dictionary.

I’ve been doing this for years. Now I can see what you mean that Dictionary isn’t interchangeable with Event here. But it definitely works with events, and has done for a long time.

hjh

A quick example, without the function. IMO reduced ugliness:

~a = (amp: 0.3);

(
p = Pchain(
	Pbind(
		\degree, Pwhite(0, 7, inf),
		\dur, 0.25
	),
	Pfunc { ~a }
).trace.play;
)

// prints this: amp = 0.3 is there
( 'degree': 1, 'dur': 0.25, 'amp': 0.3 )

p.stop;

But, to be really formally correct, it should be:

~a = (amp: 0.3);  // or Dictionary[\amp -> 0.3] or Dictionary.with(...)

(
p = Pchain(
	Pbind(
		\degree, Pwhite(0, 7, inf),
		\dur, 0.25
	),
	Pfunc { |ev| ev.putAll(~a) }
).trace.play;
)

… because Pfunc in this context replaces any previous work with the ~a event. (This is why the result was Dictionary, causing the error, before.) putAll merges the incoming event ev and ~a.

If it’s written that way, then it also works with ~a being a Dictionary.

hjh