Noobie question here:
Is there a method that will allow me to replicate an array a variable number of times?
I am thinking of an operator similar to python’s * , which you can apply to arrays:
[ 1 , 2, 3] * 3 ==> [1,2,3 ,1,2,3 ,1,2,3,]
My use case is that I have an array of arrays representing melodic cells and I want to to construct a sequence of pitches by repeating each subarray a random number of times and combining the result. Something like the following, let’s say (I’m omitting durations for simplicity):
~cells = [ [ 1, 3, 5, 7], [1, 3, 2]];
~minMax = [2,5] ;
~pitches = PSeq[~cells.collect({
|item i|
var reps;
reps = rrand(minMax[0],minMax[1]);
item * reps); // <== does not work...
}) ;
// Then PBind etc.
I may be getting at this from a wrong angle, perhaps. Suggestions on better approaches gladly welcome.
kesey
February 7, 2022, 11:34pm
2
Hello Cleinias,
surely there are better ways but you can do it like this:
(
~cells = [ [ 1, 3, 5, 7], [1, 3, 2]];
~minMax = [2,5] ;
~pitches = Pseq(
~cells.collect({
|item i|
var reps;
reps = rrand(~minMax[0], ~minMax[1]);
item ! reps;
}).flat.postln;
);
)
Thanks Kesey,
I had looked carefully at the docs before posting but could not find any mention of the ! operator. Wold you mind sharing how I could have found out?
Also, please do not keep me on edge on the better ways of doing this
http://doc.sccode.org/Overviews/SymbolicNotations.html#Miscellaneous%20operators
FWIW I (almost) rigorously avoid !
in my own code because it’s hard to find in the help – readability over concision.
In any case: Since the end goal is streaming, here are a couple of pattern-idiomatic ways:
~cells = [[1, 3, 5, 7], [1, 3, 2]];
(
Pswitch(
~cells.collect { |cell| Pseq(cell, 1) },
Pdup(
Pwhite(2, 5, inf),
Pn(Pseries(0, 1, ~cells.size), inf)
)
)
.asStream.nextN(50)
)
(
Pflatten(1, Pdup(Pwhite(2, 5, inf), Pseq(~cells, inf)))
.asStream.nextN(50)
)
hjh
jamshark70:
~cells = [[1, 3, 5, 7], [1, 3, 2]];
(
Pswitch(
~cells.collect { |cell| Pseq(cell, 1) },
Pdup(
Pwhite(2, 5, inf),
Pn(Pseries(0, 1, ~cells.size), inf)
)
)
.asStream.nextN(50)
)
(
Pflatten(1, Pdup(Pwhite(2, 5, inf), Pseq(~cells, inf)))
.asStream.nextN(50)
)
Thanks, your examples look much better indeed. Will delve into patterns further.
rdd
February 8, 2022, 12:17am
6
In SuperCollider:
[1, 2, 3] * 3 == [3, 6, 9]
and:
([1, 2, 3] ! 3).flatten == [1, 2, 3, 1, 2, 3, 1, 2, 3]
or longer:
[1, 2, 3].dup(3).flatten == [1, 2, 3, 1, 2, 3, 1, 2, 3]
You can give this a name if you like, including an operator name:
+ Array { !- { arg count; ^ (this ! count).flatten } }
After which:
[1, 2, 3] !- 3 == [1, 2, 3, 1, 2, 3, 1, 2, 3]
You can also give it a local name.
var df = {arg array, count; array.dup(count).flatten }; df.value([1, 2, 3], 3) == [1, 2, 3, 1, 2, 3, 1, 2, 3]
It depends how much you’re using it.
C.f. https://doc.sccode.org/Guides/WritingClasses.html#External%20method%20files
Ps. https://doc.sccode.org/Classes/Object.html#-dup
rdd
February 8, 2022, 12:18am
7
Oh, overlap, sorry. More characters to be long enough to send.
Rainer
February 8, 2022, 8:38am
8
[1, 2, 3] ! 3
[1, 2, 3] dup: 3
[1, 2, 3].dup(3)
The !
operator is a shortcut for .dup
[1, 2, 3].dup(3).flat.sum
-> 18
It’s only documented for class Function
, though it’s also included as an instance method for class Object
… so it applies to everything.
It’s often used for Multichannel Expansion… the !
operator will always return it’s results in a single collection.