Duplicate/split event in Pbind

Hi there,

I’m trying to duplicate an event in Pbind. What I want to achieve is to repeat the exact same note twice without ‘moving ahead’:

(SynthDef.new(\triy,{|gate=1, freq=100|
	var a;
	a = SinOsc.ar(freq,0,0.1);

(Pbind (
		\amp, 0.1,
		\degree, Pseq([1, 2, 3],inf),
		\dur, Pswitch1([ Rest(1), 1, Pn(0.25, 2)  ],Pseq([0,1,0,2,0,2],inf)),
		\stretch, 0.2,


This is my attempt in the \dur key, which does not work. Every time Pswitch1 receives a 0, it rests. Every time Pswitch1 receives a 1, the synth plays. When Pswitch1 receives a 2, I want Pn(0.25,2) to play the exact same note two times. Is there a way to achieve this, ideally without changing the pattern in Pseq?

I have spent several hours on this but cannot find a solution.

This is a tricky one. Conditionally sample-and-holding a pattern is not something the current pattern system does very easily.

One thing I would do is to use an “inner Pbind” to link \degree and \dur – because, in your problem description, they are linked (they both follow the Pswitch ‘index’).

But Pswitch1 isn’t appropriate because it will always pull only one value from the indexed stream. This will inherently break Pn(0.25, 2) apart. It sounds like that isn’t what you want.

Pswitch does keep them together:

p = Pswitch([1, 2, Pn(3, 2)], Pseq([0, 1, 2], inf)).asStream;

-> [ 1, 2, 3, 3, 1, 2 ]

Pswitch can contain Pbinds, so there’s the linkage.

p = Pchain(
    // unfortunately I don't see a way to keep statelessness
    // but will try to isolate the mess inside a block
    // (because 'degree' needs to be one stream shared across several patterns)
    Plazy {
        var degree = Pseq([1, 2, 3], inf).trace.asStream;
            // unfortunately \dur must come first here
            Pbind(\dur, Pn(Rest(1), 1), \degree, degree),
            Pbind(\dur, Pn(1, 1), \degree, degree),
            Pbind(\dur, Pn(0.25, 2), \degree, Pdup(2, degree))
        ], Pseq([0, 1, 0, 2, 0, 2], inf))
        \amp, 0.1,
        \instrument, \triy,
        \stretch, 0.2,

This solution is quite messy. It might be better to write imperative code inside a Prout for degree and dur. (Pattern Guide Reference 01: Pattern Internals | SuperCollider 3.12.2 Help has some important tips.)

    p = Pchain(
        Prout { |inevent|
            var d, degree = Pseq([1, 2, 3], inf).asStream;
            var i, index = Pseq([0, 1, 0, 2, 0, 2], inf).asStream;
            var durStream, durs = [
                Rest(1), 1, Pn(0.25, 2)
            var event;
            loop {
                i = index.next(inevent);
                durStream = durs[i];
                if(durStream.isPattern) {
                    durStream = durStream.asStream;
                } {
                    durStream = Pfin(1, durStream).asStream;
                d = degree.next(inevent);
                durStream.do({ |dur|
                    inevent = inevent.put(\dur, dur).put(\degree, d).yield;
                }, inevent);
            \amp, 0.1,
            \instrument, \triy,
            \stretch, 0.2,

Pclutch might also help but I’m out of time right now.


1 Like

Do you want to keep the event the same, or are you using ‘note’ as a synonymy for pitch?

Here is how I’d duplicate the event.

I’ve moved to Pdef syntax because it makes managing the patterns a little easier when they are combined.

Pdef(\base, Pbind(
	\freq, Pseq((1..10), inf),
	\dur, 1

	Pdef(\base),       // looks up \base
	Prand([0, 1], inf) // hold or advance

1 Like

jamshark70, jordan, thank you so much for your time and effort. I need to experiment with your suggestions quite a bit in order to understand, what is actually happening. There is no doubt that this helps and teaches me a lot. I will also take a look at the Pattern Internals in that “Pattern Guide Reference”. Thank you again!