Patterns and Arrays

Hi all,
finally got some time to do some colliding, but have been colliding my head against the wall in this particular case. Typing this up I’ve finally found a workaround but I’m still not sure why Patterns behave that way, so would be thankful for explanations.

I am trying to get a \phrase-type Pdef to pass an array (of pitches) to a subordinate Pdef, and the subordinate pattern should then play these pitches sequentially (in a Pshuf or whatever). The superordinate pdef sends it new arrays periodically; it gets these arrays from a bigger, preexisting list of pitch material; the arrays are not themselves generated by supercollider patterns. I suspect that’s where the problem is.

Trying to mock this up really quickly it should work something like this:


(
var testarray = Array.fill([5,3], {10.rand});
var a, b, c;
a = Prand(testarray); 
5.do({ b = Pshuf(a.asStream.next.postln);
    c = b.asStream; 
    3.do({ c.next.postln; })
    });
)

which works as expected, as its essentially just two nested loops.
But doing the same thing with full flegded Pbinds etc. doesn’t:

(
var testarray = Array.fill([5,3], {10.rand});
Pdef(\subord, {|wontwork| wontwork.postln; //a dimension is chewed off the array somehow
   Pbind(\note, Pshuf(wontwork),  //and Pshuf gets an int, with which it won't know what to do.
           // etc.
            }
);
Pdef(\superord, {
    Pbind(\instrument, \subord, 
    \type, \phrase,
    \wontwork, Prand(testarray),
    // etc.
)}
); 
Pdef(\superord).play //error
)

Now I’ve tried enclosing the testarray variable in another pair of brackets, but that just plays all the subord patterns at once (which is expected behavior I think). Substituting the variable with a literal array #[[1,2],[3,4]] gets the exact same problems, so that’s not it either.
What finally did help is moving the inner arrays one level deeper, i.e. from [[1,2],[3,4]] to [[[1,2],[3,4]]]. Now I guess I’ve found a solution but I still don’t understand why this is happening - why does one dimension of the array get “chewed off” as it is passed to the subordinate pattern?

If you play an event like (degree: [0, 2, 4]), it produces one synth for each pitch, and each synth receives one array element. That is, from the perspective of the synth, the array has been stripped away. (It does not play one synth that receives the whole array.)

This is the standard meaning of multichannel expansion in Events.

With \phrase, arrays in the event get similarly multichannel expanded: if wontwork consists of [0, 2, 4], then the \phrase event will spawn three simultaneous phrases, where each one receives one array element. That’s consistent with the behavior of arrays for the \note event type.

The solution is the same for both: if the event key points to a one-element array, where the one element is itself an array, then it will produce only one subordinate, and the subordinate receives the entire array. You can wrap the sequence arrays one by one:

\willwork, PThisIsMyPatternGeneratingSeqArrays(...).collect([_])

hjh

1 Like

Thanks! I came close yesterday but somehow failed to put two and two together…

I think I may have been confused by the way multichannel expansion is handled for UGens. (e.g., the help page Multichannel Expansion | SuperCollider 3.12.2 Help).

On the other hand, I do now recall running into a version of this issue before, where the arguments of a SynthDef were concerned.

What I’m still not sure I grasp is where exactly this multichannel expansion happens. I expected it to happen with the Synth argument, but if I understand you correctly, this happens with any Object (such as another Pattern) that receives an Event as argument?

It 's an Event feature (vs. UGen multichannel expansion). It’s a bit confusing that both things are called the same. Actually, with Events, it’s a multi-synth expansion. And in addition, you can have these combined …
miSCellaneous_lib contains the tutorial “Event patterns and array args” comparing some setups of that kind.

1 Like