Hi All,
Just musing: It’s very convenient in an Ndef to do something like this
Unfortunately the NdefGui doesn’t pick up the spec from this. Not sure if NamedControl should store any specs in the global spec dictionary (probably not?) or if the NodeProxy should pick up any local specs defined in NamedControls (probably yes as this would allow for local override of defined specs, which seems rather desirable?)
That is exactly why JITLibExtensions has addSpec for adding specs to all Xdefs: Ndef(\x).addSpec(\coef, [-0.99, 0.99]);
What is the best logic for including implicitly added specs? (as in:)
NodeProxy could have its own getSpec method; if there is not an explicit spec yet, look if there is one in NodeProxy.objects ... metadata, and if yes, use that, else guess (as now).
This could become confusing when you rewrite the ndef source: should it keep the last found one (which is now in ndefs specs), or take the new one? Not sure what the best precedence order would be here,
Scott, what are your ideas for this?
I think it should follow normal scope rules, i.e. local first. So:
1 NamedControl or addSpec (I think these should be treated as equivalent in precedence, so if you supply a spec for a NamedControl that replaces a previous spec added by either method ) 2 [Maybe intermediate levels?] 3 Global Specs Dict 4 Guess
This seems least surprising to me. (At 3 we might actually improve the heuristics a bit, i.e. freq2 could reasonably be matched with \freq assuming the val is within range, though of course that’s not a JITLib issue!) 1 answers the question of what happens when source is redefined. In keeping with existing practice though, I think it shouldn’t change the value unless it’s now outside the spec range?
What do you think?
Makes sense - so for clarity, any spec given in an internal NamedControl always also gets put into addSpec (Halo)?
This only gets weird when people use both addSpec and \ param.kr(spec: ) constructions; then the latest one decides, which is fine I guess.
/// quick code sketch for trying out how this feels:
// ---------- extFindSpec.sc :
+ AbstractPlayControl { findSpec { ^nil } } + SynthDefControl { findSpec { |paramKey| var specs = synthDef.metadata[\specs]; if (specs.isNil) { ^nil }; ^specs[paramKey] } }
+ NodeProxy { findSpec { |paramKey| var spec; this.objects.do { |obj| spec = obj.findSpec(paramKey); if (spec.notNil) { ^spec } }; ^spec }
// does not put this in addSpec yet, // does not work for gui yet! getSpec { ^this.getSpec ?? { this.findSpec } } } // ----------
Ndef('a', Pbind()).play;
Ndef('a', Pbind(\degree, Pbrown(0, 14, 3), \dur, 0.25)).play;
Ndef('a').put(5, \filter -> { |in| var decay = \ decay.kr(3, spec: [1, 100, \exp]); [0.08333, 0.1667], decay ) });
Ndef('a').findSpec(\decay); // finds spec Ndef('a').findSpec(\nope); // nil
///// noticed a bug: ///// when jumping to spec arg, this works Ndef(\x, { x = \ coef.kr(0, spec: [-0.99, 0.99]); }); // specs exist Ndef('x').objects[0].synthDef.metadata
Ndef(\x, { x = \ coef.kr(0, lag: 1, spec: [-0.99, 0.99]); }); // now they don't: why? Ndef('x').objects[0].synthDef.metadata
best adc |