{
   "code" : "//this is code which emulates a tb303 it is not written by me but i found it on the sc-users mailing list.\r\n//it is missing some features as accent and portamento which are actually important for the 303 sound ...\r\n//the tb303 has the portamento at the end of the node, towards the next node in a fixed time.\r\n\r\n(\r\n//s =  Server .internal;\r\ns.boot;\r\n)\r\n\r\n(\r\n SynthDef ( \"sc303\" , {  arg  out=0, freq=440, wave=0, ctf=100, res=0.2,\r\n\t\tsus=0, dec=1.0, env=1000, gate=0, vol=0.2;\r\n\t var  filEnv, volEnv, waves;\r\n\r\n\t // can't use adsr with exp curve???\r\n\t //volEnv = EnvGen.ar(Env.adsr(1, 0, 1, dec, vol, 'exp'), In.kr(bus));\r\n\tvolEnv =  EnvGen .ar( Env .new([10e-10, 1, 1, 10e-10], [0.01, sus, dec],  'exp' ), gate);\r\n\tfilEnv =  EnvGen .ar( Env .new([10e-10, 1, 10e-10], [0.01, dec],  'exp' ), gate);\r\n\r\n\twaves = [ Saw .ar(freq, volEnv),  Pulse .ar(freq, 0.5, volEnv)];\r\n\r\n\t Out .ar(out,  RLPF .ar(  Select .ar(wave, waves), ctf + (filEnv * env), res).dup * vol);\r\n}).send(s);\r\n\r\n)\r\n\r\n /*\r\ns.sendMsg(\"s_new\", \"sc303\", 3000, 0, 0);\r\ns.sendMsg(\"n_set\", 3000, 'gate', 1, 'freq', 220);\r\ns.sendMsg(\"n_set\", 3000, 'gate', 0);\r\ns.sendMsg(\"n_set\", 3000, 'dec', 1);\r\n\r\ns.sendMsg(\"n_free\", ~node)\r\n*/\r\n\r\n\r\n // make GUI!\r\n(\r\n~bpm = 140;\r\n~step = 0;\r\n\t // set default note ons\r\n~defaultNoteOns =  Array .fill(16,1);\r\n\t // this is the note on array that will be used in the sequencer routine\r\n~noteOns = ~defaultNoteOns;\r\n\r\n\t // set root\r\n~root = 36;\r\n\r\n\t // set default pitches\r\n~defaultPitches = [ 0, 12, 0, 0, -12, 0, 0, 0, -12, 0, 12, 0, 3, -5, 2, 0 ];\r\n\t // this is the pitch array that will be used in the sequencer routine\r\n~pitches = ~defaultPitches;\r\n\r\n~tStepLED =  Array .new; \t // the step indicator LEDs as an array\r\n~sNoteOn =  Array .new;  \t // the note-on sliders as an array\r\n~tNoteOn =  Array .new;\t // the note-on value boxes as an array\r\n~sPitch =  Array .new;\t // the pitch sliders as an array\r\n~tPitch =  Array .new; \t // the pitch value boxes as an array\r\n\r\nw =  Window ( \"-303\" ,  Rect (128, 64, 510, 320));\r\nw.view.background =  Color .white;\r\nw.front;\r\n\r\n~layoutLeft =  CompositeView (w,  Rect (0, 0, 400, 320));\t // make the left pane of the window\r\n~layoutLeft.decorator =  FlowLayout (~layoutLeft.bounds);  // auto-arrange the elements\r\n~layoutRight =  CompositeView (w,  Rect (400, 0, 400, 120));\r\n~layoutRight.decorator =  FlowLayout (~layoutRight.bounds);\r\n\r\n // make transport controls\r\n\r\n\t // Tempo\r\n StaticText (~layoutRight,  Rect (0,0, 45, 14)).string_( \"BPM: \" );\r\n~tBpm =  NumberBox (~layoutRight,  Rect (0,0, 45, 14))\r\n\t.string_(~bpm)\r\n\t.action_({  arg  item;\r\n\t\t~bpm = item.value;\r\n\t\t~sBpm.value_((~bpm-40)/200);\r\n\t});\r\n\r\n~layoutRight.decorator.nextLine;\r\n~sBpm =  Slider (~layoutRight,  Rect (0,0, 100, 20))\r\n\t.background_( Color .new(0.8,0.8,0.8))\r\n\t.value_((~bpm-40)/200)\r\n\t.action_({  arg  sldr;\r\n\t\t~bpm = ((sldr.value)*200) + 40;\r\n\t\t~tBpm.string_(~bpm);\r\n\t});\r\n\r\n~layoutRight.decorator.nextLine;\r\n\r\n\t // Reset\r\n Button (~layoutRight,  Rect (0,0,45,20))\r\n\t.states_([[ \"|<\" ]])\r\n\t.action_({  arg  item;\r\n\t\t~tStepLED[~step].background_( Color .new(0.6,0,0));\r\n\t\t~step = 0;\r\n\t\t~tStepLED[0].background_( Color .new(1,0,0));\r\n\t});\r\n\r\n\t // Play/Pause\r\n Button (~layoutRight,  Rect (0,0,45,20))\r\n\t.states_([[ \">\" ],[ \"||\" ]])\r\n\t.action_({  arg  item;\r\n\t\tif( item.value == 0, {\r\n\t\t\t~seqr.stop;\r\n\t\t},{\r\n\t\t\t~seqr.reset;\r\n\t\t\t~seqr.play;\r\n\t\t});\r\n\t});\r\n\r\n~layoutRight.decorator.nextLine;\r\n\r\n\t // Root note\r\n StaticText (~layoutRight,  Rect (0,0, 45, 14)).string_( \"Root: \" );\r\n~tRoot =  StaticText (~layoutRight,  Rect (0,0, 45, 14)).string_(~root);\r\n~layoutRight.decorator.nextLine;\r\n Slider (~layoutRight,  Rect (0,0, 100, 20))\r\n\t.background_( Color .new(0.8,0.8,0.8))\r\n\t.value_((~root-24)/36)\r\n\t.step_(1/48)\r\n\t.action_({  arg  sldr;\r\n\t\t~root = ((sldr.value)*36) + 24;\r\n\t\t~tRoot.string_(~root);\r\n\t});\r\n\r\n\r\n // make synth control labels\r\n StaticText (~layoutLeft,  Rect (0,0, 45, 14)).string_( \"Wave\" );\r\n StaticText (~layoutLeft,  Rect (0,0, 80, 14)).string_( \"Cutoff\" );\r\n StaticText (~layoutLeft,  Rect (0,0, 80, 14)).string_( \"Resonance\" );\r\n StaticText (~layoutLeft,  Rect (0,0, 80, 14)).string_( \"Decay\" );\r\n StaticText (~layoutLeft,  Rect (0,0, 80, 14)).string_( \"Envelope\" );\r\n~layoutLeft.decorator.nextLine;\r\n\r\n // make the synth controls\r\n\t // wave-type\r\n Button (~layoutLeft,  Rect (0,0,45,20))\r\n\t.states_([[ \"Saw\" ],[ \"Square\" ]])\r\n\t.action_({  arg  item;\r\n\t\ts.sendMsg( \"n_set\" , ~node,  'wave' , item.value);\r\n\t});\r\n\t // cut-off frequency\r\n Slider (~layoutLeft,  Rect (0,0, 80, 20))\r\n\t.background_( Color .new(0.8,0.8,0.8))\r\n\t.action_({  arg  sldr;\r\n\t\ts.sendMsg( \"n_set\" , ~node,  'ctf' , ((sldr.value)*(10000-50))+50);  // modify synth param\r\n\t});\r\n\r\n\t // resonance amt\r\n Slider (~layoutLeft,  Rect (0,0, 80, 20))\r\n\t.background_( Color .new(0.8,0.8,0.8))\r\n\t.action_({  arg  sldr;\r\n\t\ts.sendMsg( \"n_set\" , ~node,  'res' , (1-sldr.value)*(0.97)+0.03);  // modify synth param\r\n\t});\r\n\r\n\t // decay amt\r\n Slider (~layoutLeft,  Rect (0,0, 80, 20))\r\n\t.background_( Color .new(0.8,0.8,0.8))\r\n\t.action_({  arg  sldr;\r\n\t\ts.sendMsg( \"n_set\" , ~node,  'dec' , (sldr.value)*2);  // modify synth param\r\n\t});\r\n\r\n\t // envelope amt\r\n Slider (~layoutLeft,  Rect (0,0, 80, 20))\r\n\t.background_( Color .new(0.8,0.8,0.8))\r\n\t.action_({  arg  sldr;\r\n\t\ts.sendMsg( \"n_set\" , ~node,  'env' , (sldr.value)*10000);  // modify synth param\r\n\t});\r\n\r\n~layoutLeft.decorator.nextLine;\r\n\r\n\t // make step LEDs\r\n16.do({  arg  i;\r\n\t~tStepLED = ~tStepLED.add(\r\n\t\t StaticText (~layoutLeft,  Rect (0,0,20,12))\r\n\t\t\t.background_( Color .new(0.6,0,0))\r\n\t\t\t.stringColor_( Color .white)\r\n\t\t\t.string_(i+1)\r\n\t);\r\n});\r\n~tStepLED[~step].background_( Color .new(1,0,0));\r\n~layoutLeft.decorator.nextLine;\r\n\r\n\t // make the note-on sliders\r\n16.do({  arg  i;\r\n\t~sNoteOn = ~sNoteOn.add(\r\n\t\t Slider (~layoutLeft,  Rect (0,0,20,60))\t\t\t // position doesn't matter; width, height do\r\n\t\t\t.background_( Color .new(0,0,0.7))\t\t // color the slider\r\n\t\t\t.step_(0.1)\t\t\t\t\t\t // values are stepped by 0.1\r\n\t\t\t.value_(~noteOns[i])\t\t\t\t // assign it its value from the note on array\r\n\t\t\t.action_({  arg  sldr;\t\t\t\t // when the slider is moved...\r\n\t\t\t\t~noteOns[i] = sldr.value;\t\t // ... update note-on array\r\n\t\t\t\t~tNoteOn[i].string = sldr.value;  // ... update its value box\r\n\t\t\t\t\t // ...change color of value box\r\n\t\t\t\t~tNoteOn[i].background =  Color .new((1-~noteOns[i]),1,(1-~noteOns[i]));\r\n\t\t\t})\r\n\t);\r\n});\r\n~layoutLeft.decorator.nextLine;\r\n\r\n\t // make the note-on value boxes\r\n16.do({  arg  i;\r\n\t~tNoteOn = ~tNoteOn.add(\r\n\t\t StaticText (~layoutLeft,  Rect (0,0,20,20))\r\n\t\t\t.background_( Color .new((1-~noteOns[i]),1,(1-~noteOns[i])))\r\n\t\t\t.string_(~sNoteOn[i].value)\r\n\t\t\t.align_(0)\r\n\t\t\t.action_({  arg  text;\r\n\t\t\t\ttext.string.postln;\r\n\t\t\t})\r\n\t);\r\n});\r\n~layoutLeft.decorator.nextLine;\r\n\r\n\t // make the pitch sliders\r\n16.do({  arg  i;\r\n\t~sPitch = ~sPitch.add(\r\n\t\t Slider (~layoutLeft,  Rect (0,0,20,120))\r\n\t\t\t.value_((~pitches[i]+12)/24)\r\n\t\t\t.step_(1/24)\r\n\t\t\t.background_( Color .new(0.8,0.8,0.8))\r\n\t\t\t.action_({  arg  item;\r\n\t\t\t\t~pitches[i] = ((item.value * 24)-12);\r\n\t\t\t\t~tPitch[i].string = ((item.value * 24)-12);\r\n\t\t\t})\r\n\t);\r\n});\r\n~layoutLeft.decorator.nextLine;\r\n\r\n\t // make the pitch value boxes\r\n16.do({  arg  i;\r\n\t~tPitch = ~tPitch.add(\r\n\t\t StaticText (~layoutLeft,  Rect (0,0,20,20))\r\n\t\t\t.background_( Color .white)\r\n\t\t\t.string_(~pitches[i].value)\r\n\t\t\t.align_(0)\r\n\t);\r\n});\r\n /*~tempButt = Button(w, Rect(0,0,60,60))\r\n\t\t\t.states_([\r\n\t\t\t\t[\"0\", Color.red, Color.black]\r\n\t\t\t]);*/\r\n\r\n)\r\n\r\n // do other stuff\r\n\r\n(\r\n~node = s.nextNodeID;\r\n\r\n // start the synth\r\ns.sendMsg( \"s_new\" ,  \"sc303\" , ~node, 1, 1);\r\n\r\n // make the step sequencer\r\n~seqr =  Routine .new({\r\n\tloop({\r\n\r\n\t\t\t // turn on LED\r\n\t\t{~tStepLED[~step].background_( Color .new(1,0,0));  /*(~step.asString + \"on\").postln;*/ }.defer;\r\n\r\n\t\tif(~noteOns[~step].coin, {\r\n\t\t\t // play note!\r\n\t\t\t\t // this is out of sync\r\n\r\n  //\r\n\t\t\ts.sendMsg(\"n_set\", ~node, 'gate', 1, 'freq', (~pitches[~step]+~root).midicps);\r\n\r\n\t\t\t//\r\n\t\t\t(7.5/~bpm).wait;\r\n\r\n\t\t\t//\r\n\t\t\ts.sendMsg(\"n_set\", ~node, 'gate', 0);\r\n\r\n\t\t\t//\r\n\t\t\t(7.5/~bpm).wait;\r\n\r\n\t\t\t// buffer playback on server (adds start/stop delay, but better inter-note timing)\r\n\t\t\t//s.sendBundle(s.latency, [ \"n_set\" , ~node,  'gate' , 1,  'freq' , (~pitches[~step]+~root).midicps]);\r\n\t\t\t//(7.5/~bpm).wait;\r\n\t\t\t//s.sendBundle(s.latency, [ \"n_set\" , ~node,  'gate' , 0]);\r\n\t\t\t//(7.5/~bpm).wait;\r\n\t\t},{\r\n\t\t\t\t // it's a rest\r\n\t\t\t(15/~bpm).wait;\r\n\t\t});\r\n\r\n\t\t\t // turn off LED\r\n\t\t{~tStepLED[(~step-1)%16].background_( Color .new(0.6,0,0));  /*(((~step-1)%16).asString + \"off\").postln;*/ }.defer;\r\n\r\n\t\t~step = (~step + 1)%16;\r\n\r\n\t});\r\n});\r\n)\r\n\r\n~seqr.play;\r\n~seqr.stop;\r\n~seqr.reset;\r\n~pitches",
   "id" : "1-4Wy",
   "is_private" : null,
   "labels" : [
      "gui",
      "synth",
      "tb303"
   ],
   "description" : "",
   "ancestor_list" : [],
   "author" : "olaf",
   "name" : "tb303"
}
