{
   "id" : "1-4Rg",
   "is_private" : null,
   "code" : "(\r\nb = Bus.audio(s, 1);\r\n\r\nSynthDef(\\muse, {|freq, dur, vol|\r\n\tvar env = EnvGen.kr(Env.linen(sustainTime: dur*0.925, attackTime: 0.075*dur, releaseTime: 0.01*dur), doneAction: 2);\r\n\tOut.ar(b, LPF.ar(Pulse.ar(freq, width: 0.5, mul: vol*env), 11000));\r\n}).send(s);\r\n\r\nSynthDef(\\museverb, {\r\n\tOut.ar(0, Pan2.ar(FreeVerb.ar(In.ar(b), 0.45, 0.5)));\r\n}).send(s);\r\n\r\n)\r\n\r\n(\r\n\tvar counter0=0, counter1=0, shiftreg=rrand(0, pow(2,30).asInteger), handler, interval, theme, makeanote, tempo=320, basefreq=220, finefreq=0, rest=false, vol, slider, major, mminor, hminor, acc, lastmnote, mminorlook;\r\n\tvar lookup;\r\n\tvar mv = Synth(\\museverb, [], s);\r\n\tvar note = nil;\r\n\tinterval = Array.with(2,8,10,20);\r\n\ttheme = Array.with(5,7,25,20);\r\n\tslider = {\r\n\t\t|sliderval, i|\r\n\t\tvar choice = 0;\r\n\t\t(sliderval == 0).if { choice = 0 }; // off\r\n\t\t(sliderval == 1).if { choice = 1 }; // on\r\n\t\t(sliderval == 2).if { choice = counter0 & 1 }; // c1/2\r\n\t\t(sliderval == 3).if { choice = counter0 & 2 >> 1 }; // c1\r\n\t\t(sliderval == 4).if { choice = counter0 & 4 >> 2 }; // c2\r\n\t\t(sliderval == 5).if { choice = counter0 & 8 >> 3 }; // c4\r\n\t\t(sliderval == 6).if { choice = counter0 & 16 >> 4 }; // c8\r\n\t\t(sliderval == 7).if { choice = (counter1 / 3).asInteger % 2 }; // c3\r\n\t\t(sliderval == 8).if { choice = (counter1 >= 6).asInteger }; // c6\r\n\t\t(sliderval >= 9 && (sliderval <= 39)).if { choice = (shiftreg >> (sliderval.asInteger - 9)) & 1 };\r\n\t\tchoice;\r\n\t};\t\t\r\n\t\t\r\n\tmakeanote = { |freq|\r\n\t\tvar dur;\r\n\t\t\"makenote\".postln;\r\n\t\tif (t == nil, { dur = 1 }, { dur = 2/t.tempo });\r\n\t\t\r\n\t\tif ((counter0 & 1) == 1 && (note != nil), \r\n\t\t\t{note.set(\\freq, freq, \\vol, vol);},\r\n\t\t\t{note = Synth(\\muse, [\\freq, freq, \\dur, dur, \\vol, vol], mv, \\addBefore);}\r\n\t\t);\r\n\t};\r\n\t\r\n\thandler = { \r\n\t\tvar notes, freq, parity, mnote;\r\n\t\tparity = theme.sum(slider).asInteger & 1;\r\n\t\t(\"shiftreg\" + (shiftreg&0x7fffffff).asHexString).postln;\r\n\t\tnotes = interval.collect(slider);\r\n\t\tmnote = notes[0] + (2 * notes[1]) + (4 * notes[2]);\r\n\t\tfreq = (basefreq.cpsmidi + lookup[mnote]);\r\n\t\t(\"A\"+freq).postln;\r\n\t\tif ((mminorlook == 1) &&\r\n\t\t\t((mnote == 5) || (mnote == 6)) &&\r\n\t\t\t(lastmnote != nil)\r\n\t\t, {\r\n\t\t\tif (lastmnote > mnote, {\r\n\t\t\t\tfreq = freq - 1;\r\n\t\t\t\tfreq.postln;\r\n\t\t\t});\r\n\t\t});\r\n\t\tlastmnote = mnote;\r\n\t\tfreq = freq.midicps * (1 + notes[3]);\r\n\t\t(\"B\"+freq).postln;\r\n\t\t(\"R\"+rest).postln;\r\n\t\t(\"N\"+notes.sum).postln;\r\n\t\tif (rest == false || (notes.sum != 0)) {\r\n\t\t\tmakeanote.value(freq * finefreq);\r\n\t\t};\r\n\t\t(\"counter0\" + counter0).postln;\r\n\t\t(\"counter1\" + counter1).postln;\r\n\t\tif (counter0&1 == 1, {\r\n\t\t\tcounter1 = (counter1+1) % 12;\r\n\t\t\tshiftreg = shiftreg << 1 | parity;\r\n\t\t});\r\n\t\tcounter0 = (counter0+1) % 32;\r\n\t};\r\n\t\r\n\tWindow.allWindows.do { |w| if (w.name == \"The Muse\") { w.close } };\r\n\tw = Window.new(\"The Muse\", Rect(200,200,800,710));\r\n\tc = ControlSpec.new(0, 39, step: 1);\r\n\tt = TempoClock.new;\r\n\t\r\n\tEZSlider.new(w, Rect(0,0,800,75), \"Interval A\", c, { |ez| interval[0] = ez.value}, initAction:true);\r\n\tEZSlider.new(w, Rect(0,75,800,75), \"Interval B\", c, { |ez| interval[1] = ez.value}, initAction:true);\r\n\tEZSlider.new(w, Rect(0,150,800,75), \"Interval C\", c, { |ez| interval[2] = ez.value}, initAction:true);\r\n\tEZSlider.new(w, Rect(0,225,800,75), \"Interval D\", c, { |ez| interval[3] = ez.value}, initAction:true);\r\n\tEZSlider.new(w, Rect(0,300,800,75), \"Theme W\", c, { |ez| theme[0] = ez.value}, initAction:true);\r\n\tEZSlider.new(w, Rect(0,375,800,75), \"Theme X\", c, { |ez| theme[1] = ez.value}, initAction:true);\r\n\tEZSlider.new(w, Rect(0,450,800,75), \"Theme Y\", c, { |ez| theme[2] = ez.value}, initAction:true);\r\n\tEZSlider.new(w, Rect(0,525,800,75), \"Theme Z\", c, { |ez| theme[3] = ez.value}, initAction:true);\r\n\t\r\n\tEZSlider.new(w, Rect(0,600,400,40), \"Volume\", action: {|ez| vol = ez.value;}, initVal: 0.75, initAction:true);\r\n\tEZSlider.new(w, Rect(400,600,400,40), \"Pitch\", ControlSpec(0,127, step:1),action: {|ez| basefreq = ez.value.midicps;}, initVal: 32, initAction:true);\r\n\tEZSlider.new(w, Rect(0,640,400,40), \"Fine Pitch\", ControlSpec(1/1.0595465, 1.0595465), action: {|ez| finefreq = ez.value}, initVal: 1, initAction: true);\r\n\t~tempobutton = EZSlider.new(w, Rect(400,640,400,40), \"Tempo\", ControlSpec(12, 600), action: {|ez| if (t != nil) {t.tempo = ez.value / 60}}, initVal: 160, initAction: true);\r\n\tButton.new(w,Rect(0,680,80,30)).states_([[\"Start\"],[\"Stop\"]]).action_({\r\n\t\t|button|\r\n\t\tif ((button.value == 0), {\r\n\t\t\t\"hold\".postln;\r\n\t\t\tt.stop;\r\n\t\t\tt = nil;\r\n\t\t}, {\r\n\t\t\t\"foof\".postln;\r\n\t\t\tt = TempoClock.new(~tempobutton.value/60);\r\n\t\t\tmv.free;\r\n\t\t\tmv = Synth(\\museverb, [], s);\r\n\t\t\tt.sched(0, { handler.value(lookup, basefreq); 1})\r\n\t\t});\r\n\t});\r\n\tButton.new(w,Rect(80,680,80,30)).states_([[\"Step\"]]).action_({|button| handler.value(lookup, basefreq);});\r\n\tButton.new(w,Rect(160,680,80,30)).states_([[\"Reset\"]]).action_({counter0 = counter1 = shiftreg = 0;});\r\n\tCheckBox.new(w, Rect(240,680,80,30), \"Rest\").action = { |state| rest = state.value };\r\n\tmajor = CheckBox.new(w, Rect(320,680,80,30), \"Major\").action = {\r\n\t\t\"majorclick\".postln;\r\n\t\tmajor.value.postln;\r\n\t\tif (major.value, {\r\n\t\t\t\"majoron\".postln;\r\n\t\t\thminor.value = 0;\r\n\t\t\tmminor.value = 0;\r\n\t\t\tlookup = [0,2,4,5,7,9,11,12];\r\n\t\t});\r\n\t\tmminorlook = false;\r\n\t};\r\n\t\r\n\thminor = CheckBox.new(w, Rect(400,680,80,30), \"Harmonic\").action = {\r\n\t\t\"hminorclick\".postln;\r\n\t\tif (hminor.value, {\r\n\t\t\t\"hminoron\".postln;\r\n\t\t\tmajor.value = 0;\r\n\t\t\tmminor.value = 0;\r\n\t\t\tlookup = [0,2,3,5,7,8,11,12]\r\n\t\t});\r\n\t\tmminorlook = false;\r\n\t};\r\n\t\r\n\tmminor = CheckBox.new(w, Rect(480,680,80,30), \"Melodic\").action = {\r\n\t\t\"mminorclick\".postln;\r\n\t\tif (mminor.value, {\r\n\t\t\t\"mminor\".postln;\r\n\t\t\thminor.value = 0;\r\n\t\t\tmajor.value = 0;\r\n\t\t\tlookup = [0,2,3,5,7,9,11,12]\r\n\t\t});\r\n\t\tmminorlook = true;\r\n\t};\r\n\t\r\n\tmajor.valueAction = true;\r\n\t~display = StaticText(w,Rect(0,800,40,710)).font_(\"Monaco\").stringColor_(Color.gray(0,1));\r\n\tw.onClose = { t.stop };\r\n\tw.front;\r\n)",
   "labels" : [
      "reverse engineering",
      "sequencer",
      "the muse"
   ],
   "ancestor_list" : [],
   "description" : "emulator of Triadex's The Muse. Comments welcome; I've never used one of these things directly.",
   "name" : "The Muse",
   "author" : "mkb"
}
