«An FM Matrix Synth with 1to1 feedback.» by LFSaw
on 25 Mar'13 16:02 inFM Matrix Synth, now with 1to1 feedback!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
/////////////////////////////////////////// // a basic FM Matrix Synth, now with 1to1 feedback. s.boot; q = q ? (); q.numOscs = 10; ( Ndef(\fmMatrix, { var numOscs = q.numOscs; var oscs; var freqs = \freqs.kr({|i| 500}!numOscs); var modIndex = \modIndex.kr({|i| 0}!(numOscs**2)).clump(numOscs).postln; var amps = \amps .kr(0!numOscs); var tmpOsc; var feedbacks = LocalIn.ar(numOscs); oscs = freqs.inject([], {|oscArray, freq, i| tmpOsc = SinOsc.ar( freq + oscArray.inject(0, {|sum, osc, j| sum // modulators from already instantiated oscs //+ (osc * modIndex[i][j] * freq) + (feedbacks[j] * modIndex[i][j] * freq) }) + (numOscs - 1 - Array.iota(numOscs - (i))).postln.inject(0, {|sum, g| sum // modulators from to be instantiated oscs + (feedbacks[g] * modIndex[i][g] * freq) }) // self modulation //modIndex[i][i] ); oscArray ++ tmpOsc; }); // end inject LocalOut.ar(oscs); //SplayAz.ar(8, oscs * amps, center: LFSaw.kr(0.01)); Splay.ar(oscs * amps); }) ) // the standard Ndef gui. to hear something, press play. Ndef(\fmMatrix).gui; Ndef(\fmMatrix).setn(\modIndex, 0!(q.numOscs**2)); // ( var specs = ( freqs: [0, 10000, \lin, 0.1].asSpec, modIndex: [0, 4, \lin, 0].asSpec; ); var modIndex = Ndef(\fmMatrix).get(\modIndex).clump(q.numOscs); var freqState = Ndef(\fmMatrix).get(\freqs); var ampState = Ndef(\fmMatrix).get(\amps); var colWidth = 40; var knobHeight = 50; var idxKnobColors = [ // upper right area [Color.gray(0.8), Color.blue, blend(Color.white, Color.blue, 0.5)], [Color.gray(0.8), Color.blue, blend(Color.white, Color.blue, 0.2)], // lower left area [Color.gray(0.8), Color.red, blend(Color.white, Color.red, 0.5)], [Color.gray(0.8), Color.red, blend(Color.white, Color.red, 0.2)] ]; var bgColors = [ Color.gray(0.8), Color.gray(1), Color.gray(0.6), Color.gray(0.8), ]; q.win = Window.new("FM Matrix", Rect(100, 100, (q.numOscs+5) * colWidth, 800)).front; q.win.addFlowLayout; /////////// INDEXES StaticText(q.win, Rect(10, 10, q.numOscs * (colWidth + 5) + 150, 20)).string_("-- modulation index "); q.win.view.decorator.nextLine; q.higherAmpSliders = q.numOscs.collect{|i| var slider; //(i+1).do{|j| q.numOscs.do{|j| var ez; ez = EZKnob(q.win, Rect(25, 25, colWidth, knobHeight), controlSpec: specs[\modIndex], initAction: true, initVal: modIndex[i][j] ) .action_{|knob| modIndex[i][j] = knob.value; Ndef(\fmMatrix).setn(\modIndex, modIndex.flat); }; ez.knobView.mode_(\vert); ((j) > i).if({ ez.setColors(knobColors: idxKnobColors[j%2]); ez.setColors(background: bgColors [j%2]); }, { ez.setColors(knobColors: idxKnobColors[j%2 + 2]); ez.setColors(background: bgColors [j%2 + 2]); }); (i == j).if{ ez.knobView.color_([Color.gray, Color.blue, Color.green]); }; }; slider = EZSlider(q.win, Rect(0, 0, 150, knobHeight * 0.5), label: i, layout: 'horz', numberWidth: 0, labelWidth: 10, initVal: ampState[i] ) .action_{|slider| ampState[i] = slider.value; q.lowerAmpSliders[i].value = slider.value; Ndef(\fmMatrix).setn(\amps, ampState); }; slider.setColors(background: bgColors[i%2 + 2]); q.win.view.decorator.nextLine; // return slider }; q.win.view.decorator.nextLine; /////////// FREQS StaticText(q.win, Rect(10, 10, q.numOscs * (colWidth + 5), 20)).string_("-- freqs ----------"); q.win.view.decorator.nextLine; q.numOscs.do{|i| var ez; ez = EZKnob(q.win, Rect(0, 0, colWidth, knobHeight), controlSpec: specs[\freqs], initAction: true, initVal: freqState[i] ) .action_{|knob| freqState[i] = knob.value; Ndef(\fmMatrix).setn(\freqs, freqState); }; ez.knobView.mode_(\vert); ez.setColors(background: bgColors[i%2 + 2]); }; /////////// AMPS q.win.view.decorator.nextLine; StaticText(q.win, Rect(10, 10, q.numOscs * (colWidth + 5), 20)).string_("-- amps ----------"); q.win.view.decorator.nextLine; q.lowerAmpSliders = q.numOscs.collect{|i| var ez; ez = EZSlider(q.win, Rect(0, 0, colWidth, 150), label: i, layout: 'vert', initVal: ampState[i] ) .action_{|slider| ampState[i] = slider.value; Ndef(\fmMatrix).setn(\amps, ampState); q.higherAmpSliders[i].value = slider.value; }; ez.setColors(background: bgColors[i%2 + 2]); } )
descendants
full graph
reception
This is really awesome
really amazing and very useful!
The code above in 3.7 should be equivalent to (
Ndef(\fmMatrix, { var numOscs = q.numOscs;
}) )
Brillant ! Another way to write the NDef
``` ( Ndef(\fmMatrix, { var numOscs = q.numOscs;
}) ) ```