// title: Little FM Synth (Second Version) // author: yl0506 // description: // I tried to increase the modularity of the code synthdef. It remains to improve the modularity and conciseness of code pattern. I find it too "heavy", too "long" ... // // I also added comments in English this time! // code: /* My simple synth with some controls, and then a small musical pattern to test it. I'm a newbie, so your help will be welcome if you learn me how improve these codes. Goal : This little exercise is to understand how the modulation of parameters of a synthesizer is possible with SuperCollider day 2 : I tried to increase the modularity of the code synthdef. It remains to improve the modularity and conciseness of code pattern. I find it too "heavy", too "long" ... */ // Execute this code first ( SynthDef( /* It is probably possible to further improve the modularity of the code. Your help is welcome. */ name:"fm3", ugenGraphFunc:{ // We declare arguments (corresponding to variables, if I understood correctly) arg f1 = 220, freqmu = 2, f2, index = 8, decay = 0.25, vol = 0.1, filterstart = 2000, filterend = 10, phasemod = 10, /* Try to declare an argument "signal" that will be used to better visualize the structure of the synth. Otherwise it's easy to be lost by different nesting, if we want to add multiple modules. Then I continue to declare variables representing each module, I guess that's the way to go !*/ signal, filter, oscillo, env1, env2, lfo1, lfo2, // ----> variable "volu" allows you to easily increase the output volume volu = 1; // Once variable declarations made​​, we can do calculations f2 = freqmu * f1; lfo1 = SinOsc.kr(55,0,1,0); lfo2 = SinOsc.kr(27.5,0,1,0); env1 = Line.kr( start: 0.5, end: 0, dur: decay, doneAction: 2); env2 = XLine.kr( start: filterstart, end: filterend, dur: decay - 0.09); oscillo = PMOsc.ar( // a simple FM oscillator carfreq:[ f1, f1 + lfo1 * 2], // with small modulation on chanel 1 modfreq:[f2 - lfo2 * 3, f2 + lfo2 * 3], // with modulation on the 2 chanels pmindex: index * (env1 * 2), modphase: phasemod + lfo1, // Is it a good idea ? mul: vol, add: 0); filter = Resonz.ar( in: oscillo * env1, freq: env2, bwr: 2 * env1, mul: (2 + volu) * env1 ); signal = Out.ar( bus: 0, channelsArray: filter ); }).add; ); /* Let's add reverb, for this we create a synth that does that. I seem to have taken a code from somewhere... help system perhaps... I don't remember... Then execute this code */ ( SynthDef(\FreeVerb2x2, {|outbus, mix = 0.25, room = 0.70, damp = 0.5, amp = 1.0| var signal; signal = In.ar(outbus, 2); ReplaceOut.ar(outbus, FreeVerb2.ar( // FreeVerb2 - true stereo UGen signal[0], // Left channel signal[1], // Right Channel mix, room, damp, amp)); // same params as FreeVerb 1 chn version }).add; ); // Finally execute next code ( /* We declare some variables to modularize the code. You can probably do better! I suppose there are other ways to easily enter notes in these patterns. But I do not yet know enough supercollider to successfully do so. The code is very long, I'd like it to be more concise. Unfortunately, I think I need help to successfully shorten it. All suggestions are welcome. */ var a, b, c, d, e, f, n1 = 45, n2, n3, o1, o2, o3, p1, p2, p3, r1 = 1, r2, r3, r4; /* a, b, c, d, e ,f : some patterns n1, n2, n3, o1, o2, o3, p1, p2, p3 : some notes in midi format n1 is the starting note, here A3 in midi format. Let's calculate other notes : */ n2 = n1 + 12; n3 = n2 + 12; o1 = n1 + 2; o2 = o1 + 12; o3 = o2 + 12; p1 = n1 + 4; p2 = p1 + 12; p3 = p2 + 12; /* r1, r2, r3, r4 : pattern repeat I think I made a mistake but where ? */ r2 = r1 * 2; r3 = r1 * 4; r4 = r1 * 8; // pattern a a = Pbind( \instrument, 'fm3', \dur, Pseq([0.2, 0.1, 0.1, 0.2, 0.2, 0.2, 0.2, 0.2], r1), //\freqmu, Pshuf([1, 2, 3, 4, 5, 6, 7, 8], 128), \freqmu, Pshuf([1, 2, 3, 4], r2), \f1, Pseq([n2,n3,n3,n2], r2).midicps, // \index, Prand([3,4,5,6],256), \vol, Prand([0.1,0.05,0.04,0.08],repeats:r4), ); // pattern b b = Pbind( \instrument, 'fm3', \dur, Pseq([0.4, 0.2, 0.2, 0.4, 0.4, 0.4, 0.4, 0.2], r1), //\freqmu, Pshuf([1, 2, 3, 4, 5, 6, 7, 8], 128), \freqmu, Pshuf([4, 5, 2, 7], r1), \f1, Pseq([n1,n2,n2,n1], r1).midicps, \index, Pseq([3,4,5,6], r1), \vol, Prand([0.2,0.15,0.1,0.2],repeats:r3), \filterend, Pseq(list:[10,100,1,500],repeats: r1), \filterstart, Pseq(list:[1000,2000,500,3000],repeats: r1), \phasemod, Pseq(list:[100,5,10,15,20],repeats: r1), \decay, Pseq(list:[0.25,0.40,0.2,0.55,0.15],repeats: r1), ); // pattern c c = Pbind( \instrument, 'fm3', \dur, Pseq([0.2, 0.1, 0.1, 0.2, 0.2, 0.2, 0.2, 0.2], r1), //\freqmu, Pshuf([1, 2, 3, 4, 5, 6, 7, 8], 128), \freqmu, Pshuf([1, 2, 3, 4], r2), \f1, Pseq([o2,o3,o3,o2], r2).midicps, // \index, Prand([3,4,5,6],256), \vol, Prand([0.1,0.05,0.04,0.08],repeats:r4), ); // pattern d d = Pbind( \instrument, 'fm3', \dur, Pseq([0.4, 0.2, 0.2, 0.4, 0.4, 0.4, 0.4, 0.2], r1), //\freqmu, Pshuf([1, 2, 3, 4, 5, 6, 7, 8], 128), \freqmu, Pshuf([4, 5, 2, 7], r1), \f1, Pseq([o1,o2,o2,o1], r1).midicps, \index, Pseq([3,4,5,6], r1), \vol, Prand([0.2,0.15,0.1,0.2],repeats:r3), \filterend, Pseq(list:[10,100,1,500],repeats: r1), \filterstart, Pseq(list:[1000,2000,500,3000],repeats: r1), \phasemod, Pseq(list:[100,5,10,15,20],repeats: r1), \decay, Pseq(list:[0.25,0.40,0.2,0.55,0.15],repeats: r1), ); // pattern e e = Pbind( \instrument, 'fm3', \dur, Pseq([0.2, 0.1, 0.1, 0.2, 0.2, 0.2, 0.2, 0.2], r1), //\freqmu, Pshuf([1, 2, 3, 4, 5, 6, 7, 8], 128), \freqmu, Pshuf([1, 2, 3, 4], r2), \f1, Pseq([p2,p3,p3,p2], r2).midicps, // \index, Prand([3,4,5,6],256), \vol, Prand([0.1,0.05,0.04,0.08],repeats:r4), ); // pattern f f = Pbind( \instrument, 'fm3', \dur, Pseq([0.4, 0.2, 0.2, 0.4, 0.4, 0.4, 0.4, 0.2], r1), //\freqmu, Pshuf([1, 2, 3, 4, 5, 6, 7, 8], 128), \freqmu, Pshuf([4, 5, 2, 7], r1), \f1, Pseq([p1,p2,p2,p1], r1).midicps, \index, Pseq([3,4,5,6], r1), \vol, Prand([0.2,0.15,0.1,0.2],repeats:r3), \filterend, Pseq(list:[10,100,1,500],repeats: r1), \filterstart, Pseq(list:[1000,2000,500,3000],repeats: r1), \phasemod, Pseq(list:[100,5,10,15,20],repeats: r1), \decay, Pseq(list:[0.25,0.40,0.2,0.55,0.15],repeats: r1), ); z = Synth(\FreeVerb2x2, [\outbus, 0], addAction:\addToTail); // It plays two patterns in parallel, ones after the others Pseq([Ppar([a, b]),Ppar([c, d]),Ppar([e, f]),Ppar([c, d]),Ppar([a, b])], 3).play; ) ‎