Pbind: adding a new key based on the value of two other keys

Hi,

I would like to extend the behavior of the \note event that Pbind uses by default: the idea would be to generate the \buf key based on the value of the \n (sample number) and \sp (sample folder) keys, with \buf yielding the result of the following function: { Bank(~sp)[~n] }. It would be nice if I could abstract that behavior and hide it among the other calculations made by Event.

I am aware of the parent / proto architecture but I found nothing that I could use so far to do what I would like to do. I have received some suggestions on Discord but after searching for quite a while, I see no obvious way of adding this functionality to my setup.

Note: I could create another event type but if possible, I prefer extending the default one.

An approximation of the desired behavior is:

// CPU usage is insanely high while doing this /!\
~a = Pbind(
  \instrument, \sampler,
  \sp, Pseq(["kick", "clap"], inf),
  \n, Pseq([0, 1, 2, 3], inf),
  \buf, Pfunc({|ev| Bank(ev.sp)[ev.n]}),
).play;

You can extend the default event type quite easily

Event.addEventType(\sampleNote, { 
   |server|
   ~buf = Bank(~sample_dir)[~sample_index];

    // set back to note
    ~type = \note; 
    currentEnvironment.play; 
});

Then you’d just have to set the \type key to \sampleNote.

Or you could do something with chaining…

~bufPat = Pbind(\buf, Pfunc({|ev| Bank(ev.sp)[ev.n]}));

~pat = ~bufPat <> Pbind(\sp, 1, \n, 1);

~pat.play

You could overwrite the \note function in the default parent event. Event types are defined as functions, making it harder to compose them.

Or, a trick: You could add an item \buf, { Bank(~sp)[~n] } into the default parent event. This function will propagate into the synth argument list when needed, and will “magically” resolve into a concrete value at the moment of building the OSC message to the server. I haven’t tested this so it might not work, but it should (I guess?).

Modifications to the default event could be done in your startup file.

But tbh I’m skeptical of adding something globally. This is a key that you’ll need for some patterns using certain SynthDefs, but not all of them, all the time. Replacing the \note function would add weight to every use case, for the sake of a subset of those usages (and be harder to override). The “magic function” approach carries less weight and is easy to override, but having it always lurking in the background will pop up and bite you sometime when you’re not expecting it.

My approach is to model not in terms of free-standing patterns, but rather in terms of “musical processes,” which encapsulate a pattern, an event prototype, and any resources that are needed. The key advantage here is: I suspect the reason why you’re chafing against the default event prototype is that usage of non-default options needs to be specified in every pattern, or every play. In my usage, the event prototype, event type etc are properties of the musical process. So you would set the “buf” property in processes that need it, and not set it in processes that don’t. The impact of the change is local to where it’s needed. You just .play the process – no need to override protoEvent, and the event type can be stashed in the process’s ~event – and these will be used automatically.

This hasn’t caught on, probably because preparing a process for production use is heavier than “just writing a pattern.” But it models relationships that patterns don’t, and those relationships are useful, and it’s really nice to be able to write a process prototype once, and reuse it again and again, and not have to worry about the plumbing after the prototype is tested.

hjh

I just tried this approach and it works well! Can I add other modifications to the same event as well? Thinking about the future and probably some other tweaks I would like to bring to this event type. I suppose that I just need to modify other keys inside that prototype function?

This behavior will only be available and installed through a special Boot() function that prepares my coding environment for algorave-like performances with heavy usage of audio samples and some synthdefs played in a ProxySpace. I’m making sure that I don’t modify the global SuperCollider behavior for other coding projects.

I am intrigued, do you have a repo where I could see the technique you are using? I find reading other people code very helpful to tame the quirks and advanced usage of the language instead of solely relying on the documentation.

Yes, it is the last two lines of the new event functionthat set the type back to note and then recall play, you can access the rest of the keys here. The issue is that these are not composable, so you will need to create all of these event types at the beginning.

The PChain <> approach is composable and far more flexible. That is what I’d use, but I like composing patterns together.

Ancient tutorials:

hjh