Use of Pattern in Proxy

Hello everyone !

I’m a begginer in supercollider and I was searching for something that let me “plug” a Pattern in an other module and edit it after
someting like :

a = [1, 2, 3, 4, 5];
~pattern = Pseq(a, inf);
~signal = {SinOsc.ar(400, 0, 1)!2};
~signal.map(\freq, ~pattern);
a.reverse;

The closest I could find was in the documentation of proxySpace and was using a SynthDef with a Pbind

maybe I thinking in the wrong direction
It seems to often be
Pattern(play synth)
rather than
Pattern - play - > synth
(if it makes sense)
which is a strange way of thinking coming from modular

sorry if this is a trivial question, I can’t seem to find a similar workflow in the book and helpfiles I’m reading

have a nice day !

Fundamentally, the thing you want is PatternProxy - you can place a pattern in it’s .source property, and then swap that pattern around while it’s playing. So, your previous example would look like:

~pattern1 = Pseq([1, 2, 3, 4, 5], inf);
~pattern2 = Pseq([1, 2, 3, 4, 5].reverse, inf);
~proxy = PatternProxy().source_(~pattern1);
(
{
    var stream = ~proxy.asStream;
    inf.do {
        stream.next.postln;
        1.wait;
    }
}.play
)

~proxy.source = ~pattern2;

But you’re probably much better off using Pdef and Pdefn, which are wrappers around PatternProxy that give them names and a few convenience behaviors. Pdef is for Event streams (usually used to play / modify Synths) and Pdefn is for streams of values (e.g. numbers). So my above example again:

Pdefn(\pattern1, Pseq([1, 2, 3, 4, 5], inf));
Pdefn(\pattern2, Pseq([1, 2, 3, 4, 5].reverse, inf));
Pdefn(\proxy, Pdefn(\pattern1)); // set proxy to pattern1
(
{
    var stream = Pdefn(\proxy).asStream;
    inf.do {
        stream.next.postln;
        1.wait;
    }
}.play
)

But if you’re using these things to trigger Synths or set values on running Synths, you can skip straight to using Pdef - with Pbind (for multi-voice synths - every event is a new voice), Pmono (for strictly monophonic synths, played once and then every subsequent event just updates the parameters), or PmonoArtic (a combination of the two, more in the documentation for this).

(
Pdefn(\freq, Pseq([100, 200, 300], inf));
Pdef(\synth, Pbind(
    \instrument, SynthDef(\synth, {
        var env, sig;
        
        // A proper \gate control and freeSelf ensure the synth can be stopped
        // and is cleaned up when it's done
        env = Env.adsr.kr(gate:\gate.kr(1), doneAction: Done.freeSelf);
        sig = \amp.kr(1) * env * Saw.ar(\freq.kr(100) + SinOsc.ar(16).range(-2, 2));
        
        Out.ar(\out.kr(0), sig * [1, 1]);
    }).add,
    \freq, Pdefn(\freq);
)).play;
)

Note how you can change the value of Pdefn(\freq) and it will be hot-swapped into your playing Pdef(\synth)… Definitely read through the documentation of Event and Pbind if this is appealing, because there is some bookkeeping and automatic stuff being done for you here and it’s good to know what it is, else you might get some unexpected results.

And, if the Event system is daunting to learn and you want to keep it simple, you can use the pattern things from above but simply play things yourself. Everything being played by a Pbind ultimately calls it’s \play function - this has access to all the Pbind keys as ~environmentVariables. You can override this to do whatever you want. So the above example again, but a more “manual” approach with no magic :slight_smile:

(
Pdefn(\freq, Pseq([100, 200, 300], inf));
Pdef(\synth, Pbind(
    \instrument, SynthDef(\synth, {
        var env, sig;        
        env = Env.adsr.kr(gate:\gate.kr(1), doneAction: Done.freeSelf);
        sig = \amp.kr(1) * env * Saw.ar(\freq.kr(100) + SinOsc.ar(16).range(-2, 2));
        Out.ar(\out.kr(0), sig * [1, 1]);
    }).add,
    \freq, Pdefn(\freq),
    \play, {
        var synth = Synth(~instrument.asDefName, args:[\freq, ~freq]);
        { synth.release }.defer(0.4); // make sure to free it
    }
)).play;
)

Thank you so much !

I’ll go try all of this