{
   "labels" : [
      "gui",
      "additive synthesis",
      "synthesis techniques"
   ],
   "code" : "// ************************************\r\n// Additive Synthesis Demo (GUI)\r\n// Patch 2 - Harmonic Series with Multislider\r\n// Bruno Ruviaro, 2013-07-23\r\n// ************************************\r\n\r\n/*\r\n\r\nMultislider interface to control 32 partials of a harmonic series.\r\n\r\nTwo modes of playing:\r\n\r\n\"Continuous Tone\" - it simply plays a continuous tone as you change the spectrum.\r\n\r\n\"Percussive Tone\" - you can play single percussive tones triggered with the 'perc' button, and control attack and decay values of these notes.\r\n\r\nHow to start: select all (ctrl + A), then evaluate (ctrl + enter).\r\n\r\nClick and drag on the white rectangle to draw the spectrum.\r\n\r\n*/\r\n\r\ns.waitForBoot({\r\n\r\n\tvar spectrum, numharm, fundamental, win, continuousOut, percussiveOut, multiSlider, volumeSlider, modeButton, singleNoteButton, attackSlider, releaseSlider, subwin, singleNoteRoutine, att = 0.01, rel = 2, ampBus, sndBus;\r\n\r\n\tnumharm = 32;\r\n\tfundamental = 110;\r\n\r\n\tampBus = Bus.control(s);\r\n\tampBus.value = 0.1;\r\n\tsndBus = Bus.audio(s, 2);\r\n\r\n\t// Main window\r\n\tWindow.closeAll;\r\n\twin = Window.new(\"Additive Synthesis\", Rect(400, 30, 590, 670));\r\n\twin.view.decorator = FlowLayout(win.view.bounds, 20@20, 20@20);\r\n\twin.onClose = {s.freeAll; \"Done!\".postln; \"\".postln};\r\n\tCmdPeriod.doOnce({win.close});\r\n\twin.front;\r\n\r\n\t// Multislider\r\n\tmultiSlider = MultiSliderView(win, Rect(0, 0, 550, 300));\r\n\tmultiSlider.value = Array.fill(numharm, {0.0});\r\n\tmultiSlider.isFilled = true;\r\n\tmultiSlider.indexThumbSize = 13.0;\r\n\tmultiSlider.gap = 4;\r\n\t/*multiSlider.action = {multiSlider.value.do({arg value, count;\r\n\t\tspectrum[count].set(\\amp, value); [value, count].postln})};*/\r\n\r\n\tmultiSlider.action = {arg multi;\r\n\t\tvar index = multi.index;\r\n\t\tvar value = multi.currentvalue;\r\n\t\tspectrum[index].set(\\amp, value);\r\n\t\t[index, value.round(0.01)].postln};\r\n\r\n\t// Volume slider\r\n\tvolumeSlider = EZSlider(\r\n\t\tparent: win,\r\n\t\tbounds: 560 @ 60,\r\n\t\tlabel: \"VOLUME\",\r\n\t\tcontrolSpec: ControlSpec(1, 100, \\lin, 1, 10, \"%\"),\r\n\t\taction: {|ez| ampBus.set(ez.value/100)},\r\n\t\tinitVal: 10,\r\n\t\tunitWidth: 30)\r\n\t.setColors(\r\n\t\tstringColor: Color.black,\r\n\t\tsliderBackground: Color.grey(0.9),\r\n\t\tnumNormalColor: Color.black);\r\n\r\n\t// Mode button (toggle between continuous and percussive)\r\n\tmodeButton = Button(win, 550 @110);\r\n\tmodeButton.states = [\r\n\t\t[\"CONTINUOUS TONE (click here to switch to percussive mode)\", Color.black, Color.new255(255, 255, 114)],\r\n\t\t[\"PERCUSSIVE TONE (click here to switch to continuous mode)\", Color.black, Color.new255(255, 204, 194)]\r\n\t];\r\n\tmodeButton.action = {arg state;\r\n\t\tif(state.value==0,\r\n\t\t\t{\r\n\t\t\t\tvolumeSlider.valueAction = 10;\r\n\t\t\t\tcontinuousOut.set(\\gate, 1);\r\n\t\t\t\t\"CONTINUOUS MODE ON\".postln;\r\n\t\t\t\tsingleNoteButton.states = [[\"perc\"]];\r\n\t\t\t\tsubwin.background = Color.grey(0.6, 0);\r\n\t\t\t},\r\n\t\t\t{\r\n\t\t\t\tcontinuousOut.set(\\gate, 0);\r\n\t\t\t\t\"PERCUSSIVE MODE ON - click on perc button\".postln;\r\n\t\t\t\tsingleNoteButton.states = [[\"perc\", Color.black, Color.new255(255, 204, 194)]];\r\n\t\t\t\tsubwin.background = Color.grey(0.6, 1);\r\n\t\t\t}\r\n\t)};\r\n\r\n\t// CompositeView (sub window)\r\n\tsubwin = CompositeView(win, 550@100);\r\n\tsubwin.background = Color.grey(0.6, 0);\r\n\r\n\t// Button for triggering single percussive note\r\n\tsingleNoteButton = Button(subwin, Rect(10, 10, 70, 80));\r\n\tsingleNoteButton.states = [[\"perc\"]];\r\n\tsingleNoteButton.action = {\r\n\t\tif(modeButton.value==1, {\r\n\t\t\tpercussiveOut = Synth(\"percussiveOut\", [\\inbus, sndBus, \\att, att, \\rel, rel, \\amp, ampBus.asMap], addAction: \\addToTail);\r\n\t\t\t\"bang!\".postln});\r\n\t};\r\n\r\n\t// Attack and Release controls for percussive notes\r\n\tattackSlider = EZSlider(\r\n\t\tparent: subwin,\r\n\t\tbounds: Rect(left: 80, top: 15, width: 460, height: 30),\r\n\t\tlabel: \"Attack\",\r\n\t\tcontrolSpec: ControlSpec(0.01, 4.0, \\exp, 0.001, 0.1, \"sec\"),\r\n\t\taction: {|ez| att = ez.value},\r\n\t\tinitVal: 0.01,\r\n\t\tunitWidth: 30)\r\n\t.setColors(\r\n\t\tstringColor: Color.black,\r\n\t\tsliderBackground: Color.grey(0.7),\r\n\t\tnumNormalColor: Color.black);\r\n\r\n\treleaseSlider = EZSlider(\r\n\t\tparent: subwin,\r\n\t\tbounds: Rect(80, 55, 460, 30),\r\n\t\tlabel: \"Release\",\r\n\t\tcontrolSpec: ControlSpec(0.3, 5, \\exp, 0.01, 2, \"sec\"),\r\n\t\taction: {|ez| rel = ez.value},\r\n\t\tinitVal: 2,\r\n\t\tunitWidth: 30)\r\n\t.setColors(\r\n\t\tstringColor: Color.black,\r\n\t\tsliderBackground: Color.grey(0.7),\r\n\t\tnumNormalColor: Color.black);\r\n\r\n\t// Routine to add SynthDefs, wait for Server reply, then start Synths\r\n\t{\r\n\t\tSynthDef(\"additive-multislider\", {\r\n\t\t\targ outbus, freq = 440, amp = 0.01;\r\n\t\t\tvar snd = SinOsc.ar(freq, 0, Lag.kr(amp, 3));\r\n\t\t\tOut.ar(outbus, snd!2);\r\n\t\t}).add;\r\n\r\n\t\tSynthDef(\"continuousOut\", {\r\n\t\t\targ inbus, amp = 0.1, gate = 1, att = 0.1, sus = 1, rel = 1;\r\n\t\t\tvar env = EnvGen.kr(Env.asr(att, sus, rel), gate);\r\n\t\t\tOut.ar(0, In.ar(inbus, 2) * amp * env * 0.05);\r\n\t\t}).add;\r\n\r\n\t\tSynthDef(\"percussiveOut\", {\r\n\t\t\targ inbus, amp = 0.1, att = 0.01, rel = 2;\r\n\t\t\tvar env = EnvGen.kr(Env.perc(att, rel), doneAction: 2);\r\n\t\t\tOut.ar(0, In.ar(inbus, 2) * amp * env * 0.05);\r\n\t\t}).add;\r\n\r\n\t\t// Wait for SynthDefs to be added...\r\n\t\ts.sync;\r\n\r\n\t\t// Now call the Synths:\r\n\t\tspectrum = Array.fill(numharm, {arg i; Synth(\"additive-multislider\", [\\freq, fundamental * (i+1), \\amp, 0.0, \\outbus, sndBus])});\r\n\r\n\t\tcontinuousOut = Synth(\"continuousOut\", [\\inbus, sndBus, \\amp, ampBus.asMap], addAction: \\addToTail);\r\n\r\n\t}.fork;\r\n\r\n\ts.meter;\r\n\t\"Additive Synthesis Demo 2\".postln;\r\n\t\"\".postln;\r\n\r\n}); // end of block.",
   "is_private" : null,
   "id" : "1-4Uv",
   "author" : "Bruno Ruviaro",
   "name" : "Additive Synthesis GUI Demo 2",
   "description" : "Multislider interface to control 32 partials of a harmonic series. Two modes of playing: \"Continuous Tone\" - it simply plays a continuous tone as you change the spectrum. \"Percussive Tone\" - you can play single percussive tones triggered with the 'perc' button, and control attack and decay values of these notes.",
   "ancestor_list" : []
}
