Any way to query Synth IO?

given a Synth is there any way to find out what bus(es) it is writing to?
something like

a = Synth(\foo);
a.outputs

TIA!

If you have your Out.ar bus mono and defined internally in the SynthDef you could use the method .get to get the value of SynthDef’s args:

(
SynthDef(\ciao,{arg out = 0;
	Out.ar(out, SinOsc.ar());
}).add;
)

x = Synth(\ciao);
x.get(\out, {arg out; ("bus is now:" + out).postln});

This one also work:

~buss = Bus.alloc();

(
SynthDef(\ciao,{arg out = 0;
	Out.ar(out, SinOsc.ar());
}).add;
)

x = Synth(\ciao, [\out, ~buss]);
x.get(\out, {arg out; ("bus is now:" + out).postln});

The NodeSnapshot quark also supports this - see SynthSnapshot:outputs.

thx all! @scztt TreeSnapshot.get is working well - is there a way to get a single SynthSnapshot? SynthSnapshot().server_(s).nodeId_(1000) doesn’t seem to do it!

@brokencode thanks! I forgot about needing to put the function in the argument to get … aaaarg

Whoa TreeSnapshotView is so cool!

Well… the original question was about finding the bus number to which an Out unit was writing. If the bus number is given to Out as a synth control (which is an extremely common usage), then it’s definitely possible to query the control’s value to get the bus number.

You’re correct that you can’t query the value on the audio bus itself, but that’s a separate question. Bus number (if given as a synth control), yes; audio bus data, no.

hjh

Indeed, I misunderstood this question, it was asking something else. But @BROKENCODE 's answer is only useful if the bus is actually given as a i_ or k-rate parameter to the synth. I doesn’t work if that’s hardcoded in the SynthDef function.

The way that does it, by the way is by parsing “/g_queryTree” response. Alas there doesn’t seem to be a built-in SC facility for that parsing, unless I’m missing something.

There’s actually a queryTree in AbstractGroup in base SC, but it just prints stuff to the post window, rather than build some structure you can navigate programmatically. I suppose you can adapt that code for your own purposes.

NodeSnapshot might be cool, but it comes with dependencies to some other non-standard GUI classes, which strictly speaking are almost certainly not needed just for the parsing part.


Actually the query tree is a bit o a red herring as that only gets the SynthDef name as useful info in this case. That name is then lookedup as in

d = SynthDef(\foo) { Out.ar(5, [0, 0]) }
d.add

q = SynthDescLib.match(\foo)

// Controls:
//   O audio Out 5.0 2

So that looks easy enough, but consider that the actual output chan can be a result of computation!

(
d = SynthDef(\foo, { Out.ar(
	Demand.kr(Dust.kr(1), 0, Drand([5, 6, 7])),
	DC.ar(0.1))
}).add)

q = SynthDescLib.match(\foo)

//.. Controls:
//   O audio Out an OutputProxy 1

I’m a bit doubtful that NodeSnapshot handles this well but I cannot test it because of its obscure GUI dependencies.

Yes, in that case there’s no way to introspect it (short of the synthdef sending the bus number by OSC to the client)… but oddly enough, in the 19 years I’ve been using SuperCollider, this hasn’t proven to be a fatal weakness for anybody.

hjh

In contrast to plain SynthDefs, Ndefs force a more functional-programming approach as they normally just capture the output of one function for each of its sources slots. One can use SynthDefs as Ndef sources, but for non-surprising results, one has to use an out arg as bus to write to as Ndefs capture these.

So Ndefs can easily have Ndef(\x).bus that makes it easy to determine & access the output bus.

By the way, in hardware definition languages, like Verilog or VHDL, one can have multiple named outputs as that’s a more natural thing in that context.

It won’t be possible to get the actual output channel when it’s driven by a UGen, apart from adding a poll in the SynthDef itself. It is possible to dump the state of all UGens in a Synth, but IIRC the server simply println's this, so it isn’t parse-able (and anyway, isn’t efficient at all, making it not a good candidate for using in anything other than debugging situations).

For dynamic outputs, the information the TreeSnapshot parser gives you:


The IODesc has the rate, number of channels, and at least enough information to determine that it’s driven by dynamic input. TreeSnapshot CAN infer the output if the output is purely given by an input parameter, e.g. in normal cases like Out.kr(\out, sig).

I agree that it would be useful to extract the parsing part of TreeSnapshot from the UI, since this may be useful on it’s own for some folks. I would gladly accept a PR splitting these into e.g. NodeSnapshot and NodeSnapshotView quarks.

1 Like