{
   "name" : "Frequency Modulation GUI Demo 2",
   "author" : "Bruno Ruviaro",
   "ancestor_list" : [],
   "description" : "Another interface to experiment with frequency modulation, now using Modulation Index.",
   "labels" : [
      "fm",
      "synthesis techniques",
      "frequency modulation",
      "modulation index"
   ],
   "code" : "// ************************************\r\n// Frequency Modulation (GUI)\r\n// Patch 2 - FM with Modulation Index\r\n// Bruno Ruviaro, 2013-08-03\r\n// ************************************\r\n\r\n/*\r\n\r\nAnother interface to experiment with frequency modulation, now using Modulation Index. The Modulation Index is arguably a more musical way to control FM. This index I is defined as:\r\n\r\nI = D/M\r\n\r\nModulation Index (I) is the ratio of Frequency Deviation (D) to Modulation Frequency (M).\r\nIndex is zero = no modulation.\r\nIndex is small = little audible FM.\r\nIndex gets higher = the more complex the spectrum.\r\n\r\nSelect all (ctrl + A), then evaluate (ctrl + period).\r\nWatch the spectrum on the Frequency Analyzer window.\r\n\r\n*/\r\n\r\ns.waitForBoot({\r\n\r\n\tvar win, carrFreqKnob, carrFreqNumber, carrFreqLabel, modFreqKnob, modFreqNumber, modFreqLabel, freqDevKnob, freqDevNumber, freqDevLabel, modIndexKnob, modIndexNumber, modIndexLabel, volumeSlider, defaultFont, defaultColor, defaultAlpha, defaultStringColor, carrSpec, modSpec, devSpec, indexSpec, synth;\r\n\r\n\tdefaultFont = Font(\"Verdana\", 16, bold: true);\r\n\tdefaultColor = Color.red(0.8);\r\n\tdefaultAlpha = 0.87;\r\n\tdefaultStringColor = Color.white;\r\n\r\n\t// Main window\r\n\tWindow.closeAll;\r\n\tFreqScope.new;\r\n\twin = Window.new(\"Frequency Modulation\", Rect(20, 400, 1020, 280));\r\n\twin.onClose = {s.freeAll; Window.closeAll; \"Frequency Modulation window closed.\".postln; \"\".postln};\r\n\twin.front;\r\n\twin.background = defaultColor;\r\n\twin.alpha = defaultAlpha;\r\n\r\n\t// Carrier Frequency Knob\r\n\tcarrSpec = ControlSpec(20, 20000, 'exp', 0, 440, \" Hz\");\r\n\tcarrFreqKnob = Knob.new(win, Rect(20, 20, 200, 200))\r\n\t.action = {arg v;\r\n\t\tvar freq = carrSpec.map(v.value);\r\n\t\tcarrFreqNumber.string = freq.round;\r\n\t\tsynth.set(\\carrFreq, freq)};\r\n\tcarrFreqKnob.value = carrSpec.unmap(carrSpec.default);\r\n\r\n\t// Carrier Frequency Number\r\n\tcarrFreqNumber = StaticText.new(win, Rect(80, 210, 80, 25));\r\n\tcarrFreqNumber.background = defaultColor;\r\n\tcarrFreqNumber.alpha = defaultAlpha;\r\n\tcarrFreqNumber.align = \\center;\r\n\tcarrFreqNumber.string = carrSpec.default;\r\n\tcarrFreqNumber.font = defaultFont;\r\n\tcarrFreqNumber.stringColor = defaultStringColor;\r\n\r\n\t// Carrier Frequency Label\r\n\tcarrFreqLabel = StaticText.new(win, Rect(20, 240, 200, 25));\r\n\tcarrFreqLabel.string = \"Carrier Frequency\";\r\n\tcarrFreqLabel.align = \\center;\r\n\tcarrFreqLabel.font = defaultFont;\r\n\tcarrFreqLabel.stringColor = defaultStringColor;\r\n\r\n\t// Modulator Frequency Knob\r\n\tmodSpec = ControlSpec(0.5, 5000, 'exp', 0, 5, \" Hz\");\r\n\tmodFreqKnob = Knob.new(win, Rect(250, 20, 200, 200))\r\n\t.action = {arg v;\r\n\t\t// first update modFreq gui and use it for synth\r\n\t\tvar modFreq, freqDev, modIndex;\r\n\t\tmodFreq = modSpec.map(v.value);\r\n\t\tmodFreqNumber.string = modFreq.round(0.1);\r\n\t\tsynth.set(\\modFreq, modFreq);\r\n\t\t// now update freqDev gui\r\n\t\tmodIndex = indexSpec.map(modIndexKnob.value);\r\n\t\tfreqDev = modIndex * modFreq;\r\n\t\tfreqDevNumber.string = freqDev.round;\r\n\t};\r\n\tmodFreqKnob.value = modSpec.unmap(modSpec.default);\r\n\r\n\t// Modulator Frequency Number\r\n\tmodFreqNumber = StaticText.new(win, Rect(310, 210, 80, 25));\r\n\tmodFreqNumber.background = defaultColor;\r\n\tmodFreqNumber.alpha = defaultAlpha;\r\n\tmodFreqNumber.align = \\center;\r\n\tmodFreqNumber.string = modSpec.default;\r\n\tmodFreqNumber.font = defaultFont;\r\n\tmodFreqNumber.stringColor = defaultStringColor;\r\n\r\n\t// Modulator Frequency Label\r\n\tmodFreqLabel = StaticText.new(win, Rect(250, 240, 200, 25));\r\n\tmodFreqLabel.string = \"Modulator Frequency\";\r\n\tmodFreqLabel.align = \\center;\r\n\tmodFreqLabel.font = defaultFont;\r\n\tmodFreqLabel.stringColor = defaultStringColor;\r\n\r\n\t/* Frequency Deviation Knob\r\n\tdevSpec = ControlSpec(1, 5000, 'exp', 0, 20, \" Hz\");\r\n\tfreqDevKnob = Knob.new(win, Rect(480, 20, 200, 200))\r\n\t.action = {\"do nothing\".postln;/*arg v;\r\n\t\tvar freq = devSpec.map(v.value);\r\n\t\tfreqDevNumber.string = freq.round;\r\n\t\tsynth.set(\\freqDev, freq)*/};\r\n\tfreqDevKnob.value = devSpec.unmap(devSpec.default);\r\n\t*/\r\n\r\n\t// Frequency Deviation Number\r\n\tfreqDevNumber = StaticText.new(win, Rect(510, 100, 130, 55));\r\n\tfreqDevNumber.background = defaultColor;\r\n\tfreqDevNumber.alpha = defaultAlpha;\r\n\tfreqDevNumber.align = \\center;\r\n\tfreqDevNumber.string = 0; // initial value\r\n\tfreqDevNumber.font = Font(\"Verdana\", 36, bold: true);\r\n\tfreqDevNumber.stringColor = Color.red(0.5);\r\n\r\n\t// Frequency Deviation Label\r\n\tfreqDevLabel = StaticText.new(win, Rect(480, 240, 200, 25));\r\n\tfreqDevLabel.string = \"Frequency Deviation\";\r\n\tfreqDevLabel.align = \\center;\r\n\tfreqDevLabel.font = defaultFont;\r\n\tfreqDevLabel.stringColor = Color.red(0.5);\r\n\r\n\t// Modulation Index Knob\r\n\tindexSpec = ControlSpec(0, 10, 'lin', 0, 0, \"modIndex\");\r\n\tmodIndexKnob = Knob.new(win, Rect(710, 20, 200, 200))\r\n\t.action = {arg v;\r\n\t\tvar modIndex, modFreq, freqDev;\r\n\t\t// update index gui, use it for synth\r\n\t\tmodIndex = indexSpec.map(v.value);\r\n\t\tmodIndexNumber.string = modIndex.round(0.01);\r\n\t\tsynth.set(\\modIndex, modIndex);\r\n\t\t// now update freqDev gui\r\n\t\tmodFreq = modSpec.map(modFreqKnob.value);\r\n\t\tfreqDev = modIndex * modFreq;\r\n\t\tfreqDevNumber.string = freqDev.round;\r\n\t};\r\n\tmodIndexKnob.value = indexSpec.unmap(indexSpec.default);\r\n\r\n\t// Modulation Index Number\r\n\tmodIndexNumber = StaticText.new(win, Rect(770, 210, 80, 25));\r\n\tmodIndexNumber.background = defaultColor;\r\n\tmodIndexNumber.alpha = defaultAlpha;\r\n\tmodIndexNumber.align = \\center;\r\n\tmodIndexNumber.string = indexSpec.default;\r\n\tmodIndexNumber.font = defaultFont;\r\n\tmodIndexNumber.stringColor = defaultStringColor;\r\n\r\n\t// Modulation Index Label\r\n\tmodIndexLabel = StaticText.new(win, Rect(710, 240, 200, 25));\r\n\tmodIndexLabel.string = \"Modulation Index\";\r\n\tmodIndexLabel.align = \\center;\r\n\tmodIndexLabel.font = defaultFont;\r\n\tmodIndexLabel.stringColor = defaultStringColor;\r\n\r\n\t// Volume Slider\r\n\tvolumeSlider = EZSlider(\r\n\t\tparent: win,\r\n\t\tbounds: Rect(930, 20, 70, 230),\r\n\t\tlabel: \"VOLUME\",\r\n\t\tcontrolSpec: ControlSpec(-40, 0, \\lin, 0.1, -36, \"dB\"),\r\n\t\taction: {|ez| synth.set(\\amp, ez.value.dbamp)},\r\n\t\tlabelWidth: 80,\r\n\t\tunitWidth: 30,\r\n\t\tlayout: 'vert')\r\n\t.setColors(\r\n\t\tstringColor: defaultStringColor,\r\n\t\tsliderBackground: Color.grey(0.9),\r\n\t\tnumNormalColor: Color.black)\r\n\t.font = Font(\"Verdana\", 14, bold: true);\r\n\r\n\tvolumeSlider.numberView.align = \\center;\r\n\tvolumeSlider.unitView.align = \\center;\r\n\r\n\t{\r\n\t\tSynthDef(\"freq-mod-by-index\", {\r\n\t\t\targ carrFreq = 440, modFreq = 5, modIndex = 0, amp = 0.015;\r\n\t\t\tvar carrier, modulator, freqDev;\r\n\t\t\t// from formula i = freqDev/modfreq:\r\n\t\t\tfreqDev = modIndex * modFreq;\r\n\t\t\tmodulator = SinOsc.ar(freq: modFreq, mul: freqDev);\r\n\t\t\tcarrier = SinOsc.ar(freq: carrFreq + modulator, mul: amp);\r\n\t\t\tOut.ar(0, [carrier, carrier]);\r\n\t\t}).add;\r\n\r\n\t\ts.sync;\r\n\r\n\t\tsynth = Synth(\"freq-mod-by-index\");\r\n\r\n\t}.fork;\r\n\r\n\tCmdPeriod.doOnce({win.close});\r\n\r\n}); // end of waitForBoot",
   "is_private" : null,
   "id" : "1-4UB"
}
