Using an array of buffers in a SynthDef

I’m interested in passing an array of multiple buffers to a Synth for use with a granulator. The idea is that the granulator randomly chooses grains from the different buffers (rather than having the buffer fixed at the time of synth creation).

I’m using NamedControl to pass the array. That works fine. But I’m having trouble with the random index choice. Here is what I’ve tried:

SynthDef(\granulator_cloud, {
	var buf_arr, env, playback_rate, sig;
    buf_arr = NamedControl.kr(\bufs, [0, 1]);
	playback_rate = \transpose.ir(1) * BufRateScale.kr(0);
    sig = GrainBuf.ar(
        2,
        Dust.ar(\density.kr(10.0)),
        WhiteNoise.ar(1).linlin(-1, 1, \dur.kr(0.01) - 0.001, \dur.kr(0.01) + 0.001),
        buf_arr[TIRand.ar(0, 1, Impulse.ar(10))],
        playback_rate,
        WhiteNoise.ar(1).linlin(-1, 1, \start.kr(0.1), \end.kr(0.9)),
        2,
        WhiteNoise.ar(1),
        -1,
        512,
        1
    );
    sig = sig.madd(\mul.kr(1), \add.kr(0));
	Out.ar(\out.kr(0), sig);
}).add;

I get an error when I try this, so clearly I’m not supposed to be choosing indices this way. I could use array.choose, but then the choice will remain fixed for the duration of the Synth, which I do not want.

Audio or control rate at is the Select UGen.

But an easier way (easier to handle in the server) is to arrange the buffer numbers to be consecutive, then just add the random index. If you’re reading them from disk, it isn’t obvious how to do it, but can be done:

~numBufs = 8;

// this gives you an available block of ~numBufs
// if it returns 0, the bufnums are 0, 1, 2, 3, 4, 5, 6, 7
~firstBufNum = s.bufferAllocator.alloc(~numBufs);

b = Array.fill(~numBufs, { |i|
    Buffer.read(s, somePaths[i], bufnum: ~firstBufNum + i)
});

Then in the synth, you’d have a firstBufNum argument and pass in b[0].bufnum (or ~firstBufNum), and do firstBufNum + TIRand.ar(...).

hjh

2 Likes

Select worked, thanks!