Pbindf not doing what I expected

Here’s a reduced example of something I tried:

(
var p = Pbind(
	\instrument, \default,
	\dur, Pseq([0.25], inf),
	\freq, Pseq([100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200], 5)
);

var pf = Pbindf(
	p,
	\freq, Pseq([Pkey(\freq), Rest(0)]).trace,
	\dur, Pseq([Pkey(\dur)*0.5, Pkey(\dur)*0.5]).trace
);

var player = pf.play;
)

I would expect this to result in “staccato” notes, however, this is not what happens. When I play this Pbindf, the original pattern (but with half duration) seems to be generated instead, as visible from the output generated by the .trace invocations. Documentation for Pbindf.new mentions: “The arguments to Pbindf is the initial pattern followed by an alternating sequence of keys and patterns.” As far as I understand, this is what I have provided.

Did I do something wrong or is there some subtlety involved?

Thanks for the reply. Yes I’m aware of “legato”, I was more curious about the behavior.

hmmm no I was wrong - the problem is with Pkey - let me look further…

the problem is that Pkey defaults to nil for the repeats field. Here you need to specify the repeat as 1

otherwise your Pseq first embeds an unending stream of Pkey(\freq) and never gets to the Rest!

(I’m deleting my previous comment so as not to mislead anyone)

this works:

(
var p = Pbind(
	\instrument, \default,
	\dur, Pseq([0.25], inf),
	\freq, Pseq([100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200], 5)
);

var pf = Pbindf(
	p,
	\freq, Pseq([Pkey(\freq,1), Rest(0)], inf).trace,
	\dur, Pseq([Pkey(\dur, 1)*0.5, Pkey(\dur, 1)*0.5]).trace
);

var player = pf.play;
)

Actually, it’s still not doing what I expected.
After adding a , inf in the \dur part as well, only half of the frequencies in the list are generated and the other ones are replaced by the Rest.

Ah yes that is the problem I had mentioned earlier where filtering is done per event so there is no way to interpose events using Pbindf sadly

Yes, “pattern filtering” is generally defined in SC as, one event in, one event out. You’re looking for one in, two out.

You could try Pbindf with Pdup(2, p).

Failing that, you could write the logic into Prout:

(
var p = Pbind(
	\instrument, \default,
	\dur, Pseq([0.25], inf),
	\freq, Pseq([100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200], 5)
);

var pf = Prout { |event|
	var stream = p.asStream;
	var originalEvent;
	
	loop {
		// one in...
		originalEvent = stream.next(event);

		// two out...		
		event = originalEvent.copy.dur_(originalEvent.dur * 0.5);
		event = event.debug("yield 1").yield;
		
		event = originalEvent.copy
		.dur_(Rest(originalEvent.dur * 0.5))
		.debug("yield 2")
		.yield;
	}
};

~player = pf.play;
)

yield 1: ( 'instrument': default, 'dur': 0.125, 'freq': 100 )
yield 2: ( 'instrument': default, 'dur': Rest(0.125), 'freq': 100 )  -- same freq, correct
yield 1: ( 'instrument': default, 'dur': 0.125, 'freq': 200 )
yield 2: ( 'instrument': default, 'dur': Rest(0.125), 'freq': 200 )  -- same freq, correct

hjh

I never would have thought of using Prout in this context (even though I have used it in the past…). Thanks for the suggestion!