0

in brief

i have an array of buffers; those are passed to a synth at random using a Pbind ; i need to access info on the current buffer from within the Pbind but I need help doing that !


explanation of the problem

i have loaded an array of buffers containing samples. those samples must be played in a random order (and at random intervals, but that's for later). to do so, i pass those buffers to a synth inside a Pbind. i want to set the \dur key to be the length of the current buffer being played. the thing is, that i can't find a way to access info on the current buffer from within the Pbind. i have tried using Pkey, Pfset and Plambda, but to no success.

does somebody know how to do this ???


code

the sounds are played using:

SynthDef(\player, {
  /*
    play a file from a buffer
    out: the output channel
    bufnum: the buffer to play
  */
  arg out=0, bufnum;
  Out.ar(
    out,
    PlayBuf.ar(1, bufnum, BufRateScale.kr(bufnum),  doneAction: Done.freeSelf)) ! 2
  )
}).add;

the buffers are loaded in an array:

path = PathName.new("/path/to/files");
bufferArray = Array.new(100);
path.filesDo({
  arg file;
  bufferArray.add( Buffer.read(s, file.fullPath) );
});

my Pbind pattern works like this:

  • i define a \buffer value which is a single buffer from the array
  • i pass this \buffer to my synth
  • i then try to calculate its duration (\dur) by dividing the number of frames of the buffer by its sample rate. this is what i can't seem to get right
p = Pbind(
  \buffer, Prand(bufferArray, inf),
  \instrument, \player,
  \bufnum, Pkey(\buffer),
  \dur, (Pkey(\buffer.numFrames) / Pkey(\buffer.sampleRate))
)

thanks in advance for your help !!

paulhector
  • 85
  • 7

1 Answers1

1

solution to the problem: how to access buffer information inside a Pbind pattern

after hours of searching, i've found a solution to this problem on the supercollider forum, and i'm posting my own solution in case others are looking on here, like i was !


define a global array of buffers

this isn't compulsory, but it allows to only create the buffer array once; the array is created asynchronously using the action parameter of Buffer.read(), which allows to trigger a function once the buffer is loaded:

var path;
Buffer.freeAll;  // avoid using all buffers in server
path = PathName.new("/path/to/sound/files");
~bufferArray = Array.new(100);
path.filesDo({
  // add the buffer to `~bufferArray` asynchronously
  arg file;
  b = Buffer.read(s, file.fullPath, action: {
    arg buffer;
    ~bufferArray.add( buffer );
  })
});

play the synth and use Pfunc to access buffer information inside of the Pbind

this is the solution per se:

  • define a Pbind pattern which activates a synth to play the buffer.
  • inside that, define a \buffer variable to hold the current buffer.
  • then, access data on that buffer inside of a Pfunc. this generates an argument containing the last event in the Pbind. using this event, the buffer data can be accessed
p = Pbind(
  \buffer, Prand(~bufferArray, inf),  // randomly access one buffer inside of the array
  \instrument, \player,
  \bufnum, Pfunc { arg event; event[\buffer] },  // define a `Pfunc` function to access the previous event containing a `\buffer` variable
  \dur, Pfunc { arg event; event[\buffer].numFrames / event[\buffer].sampleRate }  // duration
);
p.play;

see the original answer on the supercollider forum for more details !

paulhector
  • 85
  • 7