ambisonictoolkit / atk-sc3

An extension library for the SuperCollider programming language
GNU General Public License v3.0
74 stars 12 forks source link

Passing kerenels and matrices as arguments for Synthdefs #108

Closed thibaudk closed 2 years ago

thibaudk commented 2 years ago

Hi, I Wanted to ask if it was even possible to compile a SynthDef where the specific encoder would be provided at runtime. This is what I attempted here https://github.com/escuta/mosca/blob/wip/v0.5/Classes/spatDefs/ATKDef.sc#L36 But trying to pass the encoder as argument when launching the synth simply fails or returns the following error unhandled exception while running callback: arguments exceed message size

Anny pointers would be greatly appreciated ! Thanks a lot, Thibaud

joslloand commented 2 years ago

Hello @thibaudk,

The short answer is no (actually).

The longer answer revolves around the fact that when a graph is built we need to know how many channels there are.

Though Mosca is using a switch to catch channels when SpatDef is called, FoaEncode doesn't actually know anything until it receives an actual decoder. Then FoaEncode checks -numInputs and -numOutputs so as to build its part of the graph.

We're stuck with this as a result of the design of SC3. For instance, this won't work:

~synthDef = SynthDef.new(\thisWontWork, { |amp, numChannels|
    SinOsc.ar(amp).dup(numChannels)
})

But this will:

~synthDef = SynthDef.new(\thisWillWork, { |amp|
    var numChannels = 1;
    SinOsc.ar(amp).dup(numChannels)
})

Admittedly, this is potentially annoying! But, the advantage is we can (pre-)build complex graphs that are just loaded when we need them. W/ SC2, this wasn't the case.


Also.. so the message you're seeing:

unhandled exception while running callback: arguments exceed message size

Is actually about attempting to pass a kernel decoder as an argument.

I'm not looking at your actual use pattern, but I would think that you should be able to design a synthDef with a class like this, given an encoder has already been instanced. That is, encoder doesn't appear as an argument to the final, resulting synthDef. For instance, a resulting synthDef returned by the nChannels == 1 would have these args:

| lrevRef, p, rad, radRoot, azimuth, elevation, contract |

Make sense?

[BTW, I'm going to close this... but feel free to continue the conversation here.]

thibaudk commented 2 years ago

Thanks a lot @joslloand for the quick and thorough response !

The Idea was to be able to write SynthDefs to disc only once, without having to explicitly reload them every time. But it's is not a major issue at all.

joslloand commented 2 years ago

Hello @thibaudk,

Yep, this should be doable. I think all you'd need to do is to have an encoder instanced, then pass this to a function (or class method) that then designs the UGen graph.

thibaudk commented 2 years ago

Hi @joslloand

I have pushed these changes to the ATKDef classes and it works very well, only requiring the specific Ugens Using ATK kernels to be recompiled. This is still a significant boot time improvement !

Thanks again !