// title: Simple FM template with additive mixing of modulators // author: LFSaw // description: // Template to create a 2x3 FM Synth. There are two independent FM synths, of type `car(mod1(mod2))`. // all carriers and modulators are collected together and are mixed to the output according to `adLevels`. // This is intended to be a starting point for further exploration. // code: ( Ndef(\a, { var fundFreqs, ratios, fmLevels, adLevels, partials, snd; fundFreqs = [730, 150]; ratios = [ [1, 3, 5], // three vals [2, 3, 9] ]; fmLevels = [ [0.5, 0.3], // interrelation between two modulators, hence 2 vals [0.7, 0.3] ]; adLevels = [ [1, 0.2, 0.6], [0.9, 0.3, 0.3] ]; snd = [fundFreqs, ratios, fmLevels, adLevels].flop.collect{|v| var fundFreq, ratios, fmLevels, adLevels, partials, prevFMLevels; #fundFreq, ratios, fmLevels, adLevels = v; // create stacked modulators // start with innermost modulator ratios = ratios.reverse; prevFMLevels = (fmLevels ++ [1]).reverse; partials = [ratios, prevFMLevels, adLevels].flop.inject([0], {|prev, vals| var ratio, prevFMLevel; #ratio, prevFMLevel = vals; // "r: % \t l: % \t %".format(ratio, fmLevel, prev).postln; [SinOsc.ar((fundFreq * ratio) + (prev.first * fundFreq * prevFMLevel))] ++ prev }); partials = partials[0..(partials.size-2)]; // now should have [car, mod1, mod2, ...] partials = partials * adLevels; }; snd = Mix(snd.flat); snd!2 }) ) Ndef(\a).edit