It's been pointed out that blogger's formatting has mangled some of the code here. This is an attempt to rectify that.
If anyone has any trouble copy and pasting this please let me know.
(
s = Server.internal;
SynthDef("sc303", { arg out=0, freq=440, wave=0, ctf=100, res=0.2,
sus=0, dec=1.0, env=1000, gate=0, vol=0.2;
var filEnv, volEnv, waves;
// can't use adsr with exp curve???
//volEnv = EnvGen.ar(Env.adsr(1, 0, 1, dec, vol, 'exp'), In.kr(bus));
volEnv = EnvGen.ar(Env.new([10e-10, 1, 1, 10e-10], [0.01, sus, dec], 'exp'), gate);
filEnv = EnvGen.ar(Env.new([10e-10, 1, 10e-10], [0.01, dec], 'exp'), gate);
waves = [Saw.ar(freq, volEnv), Pulse.ar(freq, 0.5, volEnv)];
Out.ar(out, RLPF.ar( Select.ar(wave, waves), ctf + (filEnv * env), res).dup * vol);
}).send(s);
)
/*
s.sendMsg("s_new", "sc303", 3000, 0, 0);
s.sendMsg("n_set", 3000, 'gate', 1, 'freq', 220);
s.sendMsg("n_set", 3000, 'gate', 0);
s.sendMsg("n_set", 3000, 'dec', 1);
s.sendMsg("n_free", ~node)
*/
// make GUI!
(
~bpm = 140;
~step = 0;
// set default note ons
~defaultNoteOns = Array.fill(16,1);
// this is the note on array that will be used in the sequencer routine
~noteOns = ~defaultNoteOns;
// set root
~root = 36;
// set default pitches
~defaultPitches = [ 0, 12, 0, 0, -12, 0, 0, 0, -12, 0, 12, 0, 3, -5, 2, 0 ];
// this is the pitch array that will be used in the sequencer routine
~pitches = ~defaultPitches;
~tStepLED = Array.new; // the step indicator LEDs as an array
~sNoteOn = Array.new; // the note-on sliders as an array
~tNoteOn = Array.new; // the note-on value boxes as an array
~sPitch = Array.new; // the pitch sliders as an array
~tPitch = Array.new; // the pitch value boxes as an array
w = SCWindow("SC-303", Rect(128, 64, 510, 320));
w.view.background = Color.white;
w.front;
~layoutLeft = SCCompositeView(w, Rect(0, 0, 400, 320)); // make the left pane of the window
~layoutLeft.decorator = FlowLayout(~layoutLeft.bounds); // auto-arrange the elements
~layoutRight = SCCompositeView(w, Rect(400, 0, 400, 120));
~layoutRight.decorator = FlowLayout(~layoutRight.bounds);
// make transport controls
// Tempo
SCStaticText(~layoutRight, Rect(0,0, 45, 14)).string_("BPM: ");
~tBpm = SCNumberBox(~layoutRight, Rect(0,0, 45, 14))
.string_(~bpm)
.action_({ arg item;
~bpm = item.value;
~sBpm.value_((~bpm-40)/200);
});
~layoutRight.decorator.nextLine;
~sBpm = SCSlider(~layoutRight, Rect(0,0, 100, 20))
.background_(Color.new(0.8,0.8,0.8))
.value_((~bpm-40)/200)
.action_({ arg sldr;
~bpm = ((sldr.value)*200) + 40;
~tBpm.string_(~bpm);
});
~layoutRight.decorator.nextLine;
// Reset
SCButton(~layoutRight, Rect(0,0,45,20))
.states_([["|<"]])
.action_({ arg item;
~tStepLED[~step].background_(Color.new(0.6,0,0));
~step = 0;
~tStepLED[0].background_(Color.new(1,0,0));
});
// Play/Pause
SCButton(~layoutRight, Rect(0,0,45,20))
.states_([[">"],["||"]])
.action_({ arg item;
if( item.value == 0, {
~seqr.stop;
},{
~seqr.reset;
~seqr.play;
});
});
~layoutRight.decorator.nextLine;
// Root note
SCStaticText(~layoutRight, Rect(0,0, 45, 14)).string_("Root: ");
~tRoot = SCStaticText(~layoutRight, Rect(0,0, 45, 14)).string_(~root);
~layoutRight.decorator.nextLine;
SCSlider(~layoutRight, Rect(0,0, 100, 20))
.background_(Color.new(0.8,0.8,0.8))
.value_((~root-24)/36)
.step_(1/48)
.action_({ arg sldr;
~root = ((sldr.value)*36) + 24;
~tRoot.string_(~root);
});
// make synth control labels
SCStaticText(~layoutLeft, Rect(0,0, 45, 14)).string_("Wave");
SCStaticText(~layoutLeft, Rect(0,0, 80, 14)).string_("Cutoff");
SCStaticText(~layoutLeft, Rect(0,0, 80, 14)).string_("Resonance");
SCStaticText(~layoutLeft, Rect(0,0, 80, 14)).string_("Decay");
SCStaticText(~layoutLeft, Rect(0,0, 80, 14)).string_("Envelope");
~layoutLeft.decorator.nextLine;
// make the synth controls
// wave-type
SCButton(~layoutLeft, Rect(0,0,45,20))
.states_([["Saw"],["Square"]])
.action_({ arg item;
s.sendMsg("n_set", ~node, 'wave', item.value);
});
// cut-off frequency
SCSlider(~layoutLeft, Rect(0,0, 80, 20))
.background_(Color.new(0.8,0.8,0.8))
.action_({ arg sldr;
s.sendMsg("n_set", ~node, 'ctf', ((sldr.value)*(10000-100))+100); // modify synth param
});
// resonance amt
SCSlider(~layoutLeft, Rect(0,0, 80, 20))
.background_(Color.new(0.8,0.8,0.8))
.action_({ arg sldr;
s.sendMsg("n_set", ~node, 'res', (1-sldr.value)*(0.97)+0.03); // modify synth param
});
// decay amt
SCSlider(~layoutLeft, Rect(0,0, 80, 20))
.background_(Color.new(0.8,0.8,0.8))
.action_({ arg sldr;
s.sendMsg("n_set", ~node, 'dec', (sldr.value)*2); // modify synth param
});
// envelope amt
SCSlider(~layoutLeft, Rect(0,0, 80, 20))
.background_(Color.new(0.8,0.8,0.8))
.action_({ arg sldr;
s.sendMsg("n_set", ~node, 'env', (sldr.value)*10000); // modify synth param
});
~layoutLeft.decorator.nextLine;
// make step LEDs
16.do({ arg i;
~tStepLED = ~tStepLED.add(
SCStaticText(~layoutLeft, Rect(0,0,20,12))
.background_(Color.new(0.6,0,0))
.stringColor_(Color.white)
.string_(i+1)
);
});
~tStepLED[~step].background_(Color.new(1,0,0));
~layoutLeft.decorator.nextLine;
// make the note-on sliders
16.do({ arg i;
~sNoteOn = ~sNoteOn.add(
SCSlider(~layoutLeft, Rect(0,0,20,60)) // position doesn't matter; width, height do
.background_(Color.new(0,0,0.7)) // color the slider
.step_(0.1) // values are stepped by 0.1
.value_(~noteOns[i]) // assign it its value from the note on array
.action_({ arg sldr; // when the slider is moved...
~noteOns[i] = sldr.value; // ... update note-on array
~tNoteOn[i].string = sldr.value; // ... update its value box
// ...change color of value box
~tNoteOn[i].background = Color.new((1-~noteOns[i]),1,(1-~noteOns[i]));
})
);
});
~layoutLeft.decorator.nextLine;
// make the note-on value boxes
16.do({ arg i;
~tNoteOn = ~tNoteOn.add(
SCStaticText(~layoutLeft, Rect(0,0,20,20))
.background_(Color.new((1-~noteOns[i]),1,(1-~noteOns[i])))
.string_(~sNoteOn[i].value)
.align_(0)
.action_({ arg text;
text.string.postln;
})
);
});
~layoutLeft.decorator.nextLine;
// make the pitch sliders
16.do({ arg i;
~sPitch = ~sPitch.add(
SCSlider(~layoutLeft, Rect(0,0,20,120))
.value_((~pitches[i]+12)/24)
.step_(1/24)
.background_(Color.new(0.8,0.8,0.8))
.action_({ arg item;
~pitches[i] = ((item.value * 24)-12);
~tPitch[i].string = ((item.value * 24)-12);
})
);
});
~layoutLeft.decorator.nextLine;
// make the pitch value boxes
16.do({ arg i;
~tPitch = ~tPitch.add(
SCStaticText(~layoutLeft, Rect(0,0,20,20))
.background_(Color.white)
.string_(~pitches[i].value)
.align_(0)
);
});
/*~tempButt = SCButton(w, Rect(0,0,60,60))
.states_([
["0", Color.red, Color.black]
]);*/
)
// do other stuff
(
~node = s.nextNodeID;
// start the synth
s.sendMsg("s_new", "sc303", ~node, 1, 1);
// make the step sequencer
~seqr = Routine.new({
loop({
// turn on LED
{~tStepLED[~step].background_(Color.new(1,0,0)); /*(~step.asString + "on").postln;*/}.defer;
if(~noteOns[~step].coin, {
// play note!
// this is out of sync
// s.sendMsg("n_set", ~node, 'gate', 1, 'freq', (~pitches[~step]+~root).midicps);
// (7.5/~bpm).wait;
// s.sendMsg("n_set", ~node, 'gate', 0);
// (7.5/~bpm).wait;
// buffer playback on server (adds start/stop delay, but better inter-note timing)
s.sendBundle(s.latency, ["n_set", ~node, 'gate', 1, 'freq', (~pitches[~step]+~root).midicps]);
(7.5/~bpm).wait;
s.sendBundle(s.latency, ["n_set", ~node, 'gate', 0]);
(7.5/~bpm).wait;
},{
// it's a rest
(15/~bpm).wait;
});
// turn off LED
{~tStepLED[(~step-1)%16].background_(Color.new(0.6,0,0)); /*(((~step-1)%16).asString + "off").postln;*/}.defer;
~step = (~step + 1)%16;
});
});
)
~seqr.play;
~seqr.stop;
~seqr.reset;
~pitches
No comments:
Post a Comment