NodeDictionary : IdentityDictionary { getDefaultOr { | key, defaultValue | if(this[\defaults][key].isNil, { ^defaultValue }, { ^this[\defaults][key] }); } processSig { | sig, gate | var releaseNode = if ( this[\sustained].asBoolean, { 2 }, { nil } ); var envDoneAction = if ( this[\sustained].asBoolean, { 0 }, { 2 } ); if(this[\useLfo].asBoolean, { var lfo = switch(this[\lfoWave]) { \sin } { SinOsc } { \saw } { Saw } { \tri } { LFTri } { \pulse } { Pulse } ? SinOsc; signal = signal * lfo.kr( \lfoFreq.kr(1) ).range( 1 - \lfoGain.kr(0.5), 1 ); }); if(this[\useSaturation].asBoolean, { this.getDefaultOr(\saturationSteps, 4).do { signal = signal.tanh; } }); if(this[\useEnv].asBoolean, { var att = this.getDefaultOr(\attack, 0.1); var rel = this.getDefaultOr(\release, 0.1); var curve = this.getDefaultOr(\curve, 1); var env = Env( [0, 0, 1, 0], [0, \attack.kr(att), \release.kr(rel)], [0, \attackCurve.kr(curve), \releaseCurve.kr(curve)], releaseNode: releaseNode, ).kr(envDoneAction, gate: gate); signal = signal * env; }); if(this[\usePan].asBoolean, { switch(this[\panning], \splay, { signal = Splay.ar(signal, \spread.kr(1), center: \pan.kr(0)); }, \splayAz, { signal = SplayAz.ar(this[\panningChannels], signal, orientation: \orientation.kr(0.5)); }, \pan, { signal = Pan2.ar(signal, \pan.kr(0)); } ); }); if(this[\postAmp].asBoolean, { signal = signal * \postAmp.kr(1); }); // if(this[\detectSilence].asBoolean, { // FreeSelf.kr( // DetectSilence.ar( // [signal[0], signal[1]] + Impulse.ar(0) // ).product) // }); if(this[\limitDuration].asBoolean, { Line.kr(0, 1, \dur.kr(1), doneAction: 2); }); signal = signal * \amp.kr(1); ^signal; } }