Why is NodeProxy outputting on the wrong bus if In.kr(\out.ir) is used inside its function?

Ahhhh… a valid use case that is currently not handled.

I suppose the best solution would be to search for out’s OutputProxy. If the user didn’t create an out control, then the search would fail and ProxySynthDef would be free to create a new control for it. If the OutputProxy is found, then ProxySynthDef could Out.ar(existingOutControl, signal).

The logic looks something like this. It’s kind of a deep dive, which is probably why ProxySynthDef doesn’t bother. It should probably be wrapped into a method, maybe controlChannelForName in SynthDef.

(
f = { |userFunc|
	SynthDef(\test, { |abc = 1, def = 2|
		var sig = SynthDef.wrap(userFunc);
		// this ControlName contains the index
		var outCtl = UGen.buildSynthDef.allControlNames.detect { |cname|
			cname.name == \out
		};
		var outIndex, outUGen, outChannel;
		var trig;
		if(outCtl.notNil) {
			outIndex = outCtl.index;
			outUGen = block { |break|
				UGen.buildSynthDef.children.do { |child|
					if(child.isKindOf(Control) and: {
						outIndex >= child.specialIndex and: {
							outIndex < (child.specialIndex + child.channels.size)
						}
					}) {
						break.(child);
					};
				};
				nil
			};
			outChannel = outUGen.channels[outIndex - outUGen.specialIndex];
		} {
			outChannel = NamedControl.kr(\out, 0);
		};
		trig = Impulse.kr(0);
		Poll.kr(trig, outChannel);
		FreeSelf.kr(trig <= 0);
	}).play;
};
)

f.({ |out = 300| "defined out arg as 300".postln });
defined out arg as 300
-> Synth('test' : 1003)
UGen(OutputProxy): 300  // OK!

f.({ var out = NamedControl.kr(\out, 400); "defined out as NamedControl = 400".postln });
defined out as NamedControl = 400
-> Synth('test' : 1004)
UGen(OutputProxy): 400  // OK!

f.({ "didn't declare out".postln });
didn't declare out
-> Synth('test' : 1007)
UGen(OutputProxy): 0  // OK!

The NodeProxy would still assign its own value to out but then it would be accessible in the user function.

I think the above will not handle arrayed controls though. Out of time for now. Actually it does! Because a Control’s array of OutputProxies doesn’t reflect the structure of arrayed controls – it’s flat – so the + works as desired.

f.({ |a = #[1, 2, 3], out = 500| "out arg = 500, after array".postln });
out arg = 500, after array
-> Synth('test' : 1001)
UGen(OutputProxy): 500

So the above logic should be generally OK.

hjh

1 Like