Using Pkey, Pswitch to get Buffer information


#1

Hi all,
I’m pretty new to SC and am struggling with how to access Buffer information (such as bufnum, numChannels, numFrames, sampleRate) within a Pbind, using either Pkey or Pswitch.
I’d like to be able to set the key \bufnum and then be able to refer to it in other key pairs to access numChannels, numFrames etc.

As a simple example, if I want to change \rate depending on the number of channels of a particular Buffer in the Array ~stuff, this does not work:

~test = Pbind(
        \instrument, \bufsynth,
	\bufnum, 107,
	\rate, ~stuff[Pkey(\bufnum)].numChannels	
).asStream;
	x= ~test.next(());

It gives me an “Index not an Integer” error. I’ve tried numerous variations (too many to list here), including Pkey(\bufnum).asInteger, but I always get the “Index not an Integer” error.

I’ve also tried to use Pswitch, as in the following:

~test = Pbind(
        \instrument, \bufsynth,
	\bufnum, 107,
	\rate, Pswitch(~stuff, Pkey(\bufnum)).numChannels	
).asStream;
	x= ~test.next(());

This does not give an error, but it does not give the right result. It always gives a value of 1, even for stereo buffers. Also, if I use .numFrames instead, then I do get an error ("‘numFrames’ not understood").

Can anyone help me understand what is going on? And how I can access Buffer information by referring back to a key like \bufnum in the examples above?


#2

Hi,

there are mainly two strategies to refer to “previous” data within an Event.
One is Pkey, convenient, but not always applicable, then there is Pfunc:

b = Buffer.alloc(s, 100, 1)

~test = Pbind(
	\instrument, \bufsynth,
	\buf, b,
	\channels, Pkey(\bufnum).numChannels	
).asStream;


x = ~test.next(());

~test = Pbind(
	\instrument, \bufsynth,
	\buf, b,
	\channels, Pfunc { |e| e[\buf].numChannels }	
).asStream;

x = ~test.next(());

Another thing: in almost all cases it’s better not to define the bufnum yourself (just in case you did). You can mostly use the Buffer object itself. For a switching situation use an array of Buffers.


#3

Many thanks, Daniel! This is very helpful!

I’m getting closer to what I want to accomplish with your second option, using Pfunc, although I still have some things to figure out and may be back with a follow up question.

Interestingly, with your Pkey example I still get a value of 1 for .numChannels regardless of the actual number of channels of the Buffer.
If you or anyone else knows why that is, I’d be curious to know. But in any case the Pfunc seems to be the way to go. Thanks again!

Sam


#4

Oops, my bad, two mistakes in one example: it should be key ‘buf’ and then this kind of short writing works with operators, but not with methods in general.

So you can use collect (or Pcollect)

b = Buffer.alloc(s, 100, 2)

~test = Pbind(
	\instrument, \bufsynth,
	\buf, b,
	\channels, Pkey(\buf).collect(_.numChannels) // "partial application" for .collect { |x| x.numChannels }
).asStream;

x = ~test.next(());

But note that you can write

~test2 = Pbind(
	\instrument, \bufsynth,
	\buf, b,
	\channels, Pkey(\buf).collect(_.numChannels),
	\channels_squared, Pkey(\channels).squared
).asStream;

x = ~test2.next(());

#5

Thanks for the correction and explanation! Extremely helpful and much appreciated.
Your two responses have helped me to achieve what I was aiming to do.
Thanks again!