{
   "ancestor_list" : [],
   "description" : "A basic FM matrix synth (Ndef) with GUI",
   "name" : "Basic FM Matrix Synth",
   "author" : "LFSaw",
   "code" : "// still have to work out the right modulation index calculation\r\n\r\nq = q ? ();\r\nq.numOscs = 5;\r\n\r\n(\r\n\r\nNdef(\\fmMatrix, {\r\n\tvar numOscs = q.numOscs;\r\n\t\r\n\tvar oscs;\r\n\tvar modFreqs = \\modFreqs.kr({|i| 1000}!numOscs);\r\n\tvar modIndex = \\modIndex.kr({|i|   0}!(2**numOscs)).clump(numOscs);\r\n\tvar amps     = \\amps    .kr({|i|\r\n\t\t(i == (numOscs-1)).if({1}, {0}) }!numOscs);\r\n\tvar tmpOsc;\r\n\t\r\n\toscs = modFreqs.inject([], {|oscArray, freq, i|\r\n\t\ttmpOsc = SinOscFB.ar(\r\n\t\t\tfreq\r\n\t\t\t+ oscArray.inject(0, {|sum, osc, j| \r\n\t\t\t\tsum + (osc * modIndex[i][j].linlin(0, 3, 0, 10000))\r\n\t\t\t}),\r\n\t\t\tmodIndex[i][i]\r\n\t\t);\r\n\t\t\r\n\t\toscArray ++ tmpOsc;\r\n\t}); // end inject\r\n\t\r\n\t(oscs * amps).sum;\r\n})\r\n)\r\n\r\nNdef(\\fmMatrix).gui\r\n\r\n(\r\nvar specs = (\r\n\tmodFreqs: [0.1, 10000, \\exp, 0].asSpec,\r\n\tmodIndex: [0, 3, \\lin, 0].asSpec;\r\n);\r\nvar modIndex     = {0!q.numOscs}!q.numOscs;\r\nvar modFreqState = 1000!q.numOscs;\r\nvar ampState     = 0!q.numOscs;\r\n\r\nq.win = Window.new(\"FM Matrix\", Rect(100, 100, q.numOscs * 30, 800)).decorate.front;\r\n\r\n\r\nStaticText(q.win, Rect(10, 10, 200, 20)).string_(\"modIndex\");\r\nq.win.view.decorator.nextLine;\r\nq.numOscs.do{|i|\r\n\t(i+1).do{|j|\r\n\t\tvar ez;\r\n\t\t\r\n\t\tez = EZKnob(q.win, Rect(25, 25, 25, 50), \r\n\t\t\tcontrolSpec: specs[\\modIndex],\r\n\t\t\tinitAction: true\r\n\t\t)\r\n\t\t.action_{|knob| \r\n\t\t\t// state[i][j] = specs[key].map(knob.value);\r\n\t\t\tmodIndex[i][j] = knob.value;\r\n\t\t\tNdef(\\fmMatrix).setn(\\modIndex, modIndex.flat);\r\n\t\t};\r\n\t\tez.knobView.mode_(\\vert);\r\n\t};\r\n\tq.win.view.decorator.nextLine;\r\n};\r\nq.win.view.decorator.nextLine;\r\n\r\nStaticText(q.win, Rect(10, 10, 200, 20)).string_(\"modFreqs\");\r\nq.win.view.decorator.nextLine;\r\nq.numOscs.do{|i|\r\n\tvar ez;\r\n\tez = EZKnob(q.win, Rect(0, 0, 25, 50), \r\n\t\tcontrolSpec: specs[\\modFreqs],\r\n\t\tinitAction: true\r\n\t)\r\n\t.action_{|knob|\r\n\t\tmodFreqState[i] = knob.value;\r\n\t\tNdef(\\fmMatrix).setn(\\modFreqs, modFreqState);\r\n\t};\r\n\tez.knobView.mode_(\\vert);\r\n};\r\n\r\nq.win.view.decorator.nextLine;\r\nStaticText(q.win, Rect(10, 10, 200, 20)).string_(\"amps\");\r\nq.win.view.decorator.nextLine;\r\nq.numOscs.do{|i|\r\n\tEZSlider(q.win, Rect(0, 0, 25, 100), label: i, layout: 'vert').action_{|slider|\r\n\t\tampState[i] = slider.value;\r\n\t\tNdef(\\fmMatrix).setn(\\amps, ampState);\r\n\t}\r\n}\r\n)",
   "id" : "1-4SI",
   "is_private" : null,
   "labels" : [
      "fm",
      "synth",
      "matrix"
   ]
}
