Sunday, March 1, 2009

Another try with the 303 code.

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