Ndefs do "Point deduction"

Setting a Ndef to a scalar value and using it as a Bus results in “Point deduction”.

n = Ndef(\1, 800);
n.asBus.get // -> Bus control index: 0 value: 759.189453125.

If you-re stubborn you get the original value. But no fadeout in the end.

Ndef.clear;
Ndef(\testMap, { |freq1=440| SinOsc.ar(freq1) * 0.1 ! 2 }).play;
Ndef(\ctlBus1, 880);
Ndef(\testMap).set(\freq1, Ndef(\ctlBus1)); // hm, does not sound like an octave...
Ndef(\ctlBus1).asBus.get // value: 835.1083984375. oh!
Ndef(\ctlBus1, 880); // try again; now it sounds more like 880hz.
Ndef(\ctlBus1).asBus.get // but not quite there, value: 877.7099609375.
Ndef(\ctlBus1, 880);
Ndef(\ctlBus1).asBus.get // 879.88317871094
Ndef(\ctlBus1, 880);
Ndef(\ctlBus1).asBus.get // 879.99401855469
Ndef(\ctlBus1, 880);
Ndef(\ctlBus1).asBus.get // 879.99969482422
Ndef(\ctlBus1, 880);
Ndef(\ctlBus1).asBus.get // 880.0 finally! Do we stay there?
Ndef(\ctlBus1, 880);
Ndef(\ctlBus1).asBus.get // 880.0.
Ndef(\ctlBus1, 880);
Ndef(\ctlBus1).asBus.get // 880.0. yes, i think so.
Ndef.clear(1) // no fadeout?

Internally, setting a control rate NodeProxy to a number uses an envelope to crossfade from the bus’s old value to the desired new value, over fadeTime seconds.

In SystemSynthDefs.sc:

	SynthDef("system_setbus_control_" ++ i, { arg out = 0, fadeTime = 0, curve = 0;
		var values = NamedControl.ir(\values, 0 ! i);
		var holdTime = ControlDur.ir; // we need this to make sure value isn't overridded accidentally
		var env = Env([In.kr(out, i), values, values], [fadeTime, holdTime], curve);
		var sig = EnvGen.kr(env, doneAction: 2);
		ReplaceOut.kr(out, sig);
	}, [\ir, \kr, \ir])

This assumes that the envelope’s output after the fadeTime segment duration will equal the target value. In fact, it doesn’t quite make it all the way. The standard fadeTime of 0.02 seconds, at 44.1 kHz / 64 samples per block, = 13.78125 control blocks. At kr, the calculation must be quantized to whole blocks… but unfortunately, setting the fade time to a multiple of a full control block also doesn’t resolve the problem.

The error is reduced, but not eliminated, by increasing fadeTime (which you probably wouldn’t want to do anyway).

EnvGen will stabilize on the actual final value, but this particular usage of it is not safe (at the moment). Probably this could be considered an EnvGen bug, but I expect it would be very difficult to fix in EnvGen.

In any case, system_setbus_control should probably take a different xfade approach.

hjh

Thank you for the explanation!
Setting fadeTime to 0.1 is a solution. Still no fadeout at the end though, but thats not a problem to me right now, as i-m just playing around with this.

(
Ndef(\testMap).proxyspace.fadeTime = 0.1;
Ndef(\testMap, { |freq1=440| SinOsc.ar(freq1) * 0.1 ! 2 }).play;
Ndef(\ctlBus1, 880);
)

(
Ndef(\testMap).set(\freq1, Ndef(\ctlBus1));
Ndef(\ctlBus1).asBus.get // -> Bus control index: 0 value: 880.0.
)

Ndef(\ctlBus1).proxyspace.release(1);

Ndef.clear

Btw I put in a bug report for this.

hjh

1 Like