I think shiihs’s suggestion is the best.
Concatenating the arrays would play the two scores concurrently.
If the scores were generated independently, each one using its own dedicated Server object for ID allocators, then there’s some chance of ID conflicts – score A uses buffer 0 for one purpose, and score B uses it for a different purpose. If the scores are being played in sequence, maybe it’s not a big deal, but I think it’s not hard to imagine problem cases that would be hard to detect just by reading OSC messages. (For instance, you could be playing a droney texture with slow-envelope synths. Score A releases a synth toward the end but it will take another 10 seconds to fade out. Meanwhile, score B introduces a new sound that should be mixed on a separate channel – but they are both using buses 4-5 because the two scores were produced with separate allocators.)
The next part of this post is about a bug. The summary so far is: be careful when trying to blend OSC scores (and it’s probably better to avoid that). If you’re not interested in the bug, no need to read on.
Bug:
I had thought that problem could also be handled by initializing the servers with different clientIDs, so that the allocators would operate in different ranges.
First problem: pattern.asScore
provides no way to set server options or manipulate the server (the ScoreStreamPlayer
) before producing the score.
Second problem: Score initializes with the default group, completely ignoring any sort of clientID. This is not configurable grrrr
(
var scoreA, scoreB;
var p = Pbind(
\instrument, \helpscore,
\dur, Prand([0.3, 0.5], inf),
\freq, Prand([200, 300, 500],inf)
);
SynthDef("helpscore", { |out, freq = 440|
Out.ar(out,
SinOsc.ar(freq, 0, 0.2) * Line.kr(1, 0, 0.5, doneAction: Done.freeSelf)
)
}).add;
scoreA = ScoreStreamPlayer.new // no creation arguments here...?
.options_(ServerOptions.new.maxLogins_(2))
.clientID_(0)
.newAllocators
.makeScore(p.asStream, 2, Event.default);
scoreB = ScoreStreamPlayer.new // no creation arguments here...?
.options_(ServerOptions.new.maxLogins_(2))
.clientID_(1)
.newAllocators
// timeOffset should be how much later B starts
.makeScore(p.asStream, 2, Event.default, 2);
x = Score(scoreA.score ++ scoreB.score);
x.score.do(_.postln); ""
)
-->
[ 0.0, [ /g_new, 1, 0, 0 ] ]
// oops! should be 67108865
[ 0.0, [ /g_new, 1, 0, 0 ] ]
[ 0.0, [ 9, helpscore, 1000, 0, 1, out, 0, freq, 300.0 ] ] // this is OK
// oh, this comes from Score...
// 3 score objects, 3 default groups (= "duplicate node ID" errors),
// no accounting for server settings *grrrrr*
[ 0.0, [ /g_new, 1, 0, 0 ] ]
// ok
[ 0.3, [ 9, helpscore, 1001, 0, 1, out, 0, freq, 300.0 ] ]
[ 2, [ c_set, 0, 0 ] ]
// ok except that the group was never created
[ 2.0, [ 9, helpscore, 67109864, 0, 67108865, out, 0, freq, 500.0 ] ]
[ 2.3, [ 9, helpscore, 67109865, 0, 67108865, out, 0, freq, 500.0 ] ]
sigh … NRT has really not been carefully spec’ed enough…
hjh