SynthDef("oscillator", {| out = 0, in = 16, amp = 0, freq = 440, form = 0, mix = 1, pre = 1| var input, frq_interp, amp_interp, osc, forms; input = InFeedback.ar(in)*Lag.kr(pre, 1/8); frq_interp = Lag.kr(freq, 1/8); frq_interp = frq_interp*(input+1); amp_interp = Lag.kr(amp, 1/8); forms = [ SinOsc.ar(frq_interp, 0, amp), Pulse.ar(frq_interp.clip(0.001, 22050), 0.5, amp), Saw.ar(frq_interp.clip(0.001, 22050), amp) ]; osc = Select.ar(Silent.ar + form, forms); XOut.ar(out, mix, osc) }).store; SynthDef("output", {|vol = 1| var input; input = InFeedback.ar(16); Out.ar(0, Limiter.ar(input, 0.9)!2); }).store; ~panel = Conductor.make{|con| var amps, forms, mixes, outs, pres, freqs; con.valueKeys_(#[]); //===========amps================== ~amps = amps = (0..15).collect{CV.new.sp(0,0,1);}; con.gui.keys = con.gui.keys.add(\amps); con.gui.guis.put(\amps, [\vslider]++amps); // con.valueKeys = con.valueKeys ++ \amps; con.gui.guis.put(\namps, [\numerical]++amps); con.gui.keys = con.gui.keys.add(\namps); //===========forms================= ~forms = forms = ~amps.collect{CV.new.sp(0,0,2,1);}; con.gui.keys = con.gui.keys.add(\forms); con.gui.guis.put(\forms, [\hslider]++forms); // con.valueKeys = con.valueKeys ++ \forms; //===========mixes================= ~mixes = mixes = ~amps.collect{CV.new.sp(0.0625,0,1);}; // con.valueKeys = con.valueKeys ++ \mixes; //===========outs================== ~outs = outs = ~amps.collect{CV.new.sp(0, 0, 16, 1);}; con.gui.keys = con.gui.keys.add(\outs); con.gui.guis.put(\outs, [\numerical]++outs); // con.valueKeys = con.valueKeys ++ \outs; outs.do{|x, i| x.action_({ var mix, sub, ind; sub = outs.select({|y| x.value == y.value}); mix = sub.size; if(mix!=0, { mix = 1/mix; ind = sub.collect{|z| outs.indexOf(z); }; ind.do{|z| mixes[z].value_(mix); }; }); }); }; //===========pres================== ~pres = pres = ~amps.collect{CV.new.sp(1,0,1024)}; con.gui.keys = con.gui.keys.add(\pres); con.gui.guis.put(\pres, [\numerical]++pres); // con.valueKeys = con.valueKeys ++ \pres; //===========freqs================= ~freqs = freqs = ~amps.collect{CV(\freq)}; con.gui.keys = con.gui.keys.add(\freqs); con.gui.guis.put(\freqs, [\vslider]++freqs); // con.valueKeys = con.valueKeys ++ \freqs; con.gui.guis.put(\nfreqs, [\numerical]++freqs); con.gui.keys = con.gui.keys.add(\nfreqs); //===========gui=================== con.gui.use { ~numericalRect = Rect(0, 0, 40, 16); ~vsliderRect = Rect(0, 0, 40, 120); ~popupRect = Rect(0, 0, 40, 16); ~sliderRect = Rect(0, 0, 40, 16); }; //===========synths================= ~synths = amps.collect({|x, i| con.synth_( ( instrument:\oscillator ), [amp: amps[i], freq: freqs[i], form:forms[i], out:[outs[i], (outs[i]+16)], mix:1/16, in:17+i, pre:pres[i], freq:freqs[i]] ) }); con.synth_( ( instrument:\output, addAction:\addToTail ) ); con.name_("ON"); con.preset.items = amps ++ forms ++ outs ++ freqs ++ pres; }.show("keith's drone engine", 128, 64, 900); ~labels = (0..17).collect{|x| SCStaticText(~panel, Rect(0, 0, 40, 16)); }; ~labels.do{|x, i| if(i<2, { x.string_(""); }, { x.string_("ch"+(i-1)) }; ); };