Skip to content

Instantly share code, notes, and snippets.

@loopier
Last active November 26, 2019 14:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save loopier/228a718c87eed5aa9f0f27007edde18a to your computer and use it in GitHub Desktop.
Save loopier/228a718c87eed5aa9f0f27007edde18a to your computer and use it in GitHub Desktop.
Supercollider FM7 synth for TidalCycles
-- modulators
mod11 = pF "mod11"
mod12 = pF "mod12"
mod13 = pF "mod13"
mod14 = pF "mod14"
mod15 = pF "mod15"
mod16 = pF "mod16"
mod21 = pF "mod21"
mod22 = pF "mod22"
mod23 = pF "mod23"
mod24 = pF "mod24"
mod25 = pF "mod25"
mod26 = pF "mod26"
mod31 = pF "mod31"
mod32 = pF "mod32"
mod33 = pF "mod33"
mod34 = pF "mod34"
mod35 = pF "mod35"
mod36 = pF "mod36"
mod41 = pF "mod41"
mod42 = pF "mod42"
mod43 = pF "mod43"
mod44 = pF "mod44"
mod45 = pF "mod45"
mod46 = pF "mod46"
mod51 = pF "mod51"
mod52 = pF "mod52"
mod53 = pF "mod53"
mod54 = pF "mod54"
mod55 = pF "mod55"
mod56 = pF "mod56"
mod61 = pF "mod61"
mod62 = pF "mod62"
mod63 = pF "mod63"
mod64 = pF "mod64"
mod65 = pF "mod65"
mod66 = pF "mod66"
-- operator envelope generator levels
eglevel11 = pF "eglevel11"
eglevel12 = pF "eglevel12"
eglevel13 = pF "eglevel13"
eglevel14 = pF "eglevel14"
eglevel21 = pF "eglevel21"
eglevel22 = pF "eglevel22"
eglevel23 = pF "eglevel23"
eglevel24 = pF "eglevel24"
eglevel31 = pF "eglevel31"
eglevel32 = pF "eglevel32"
eglevel33 = pF "eglevel33"
eglevel34 = pF "eglevel34"
eglevel41 = pF "eglevel41"
eglevel42 = pF "eglevel42"
eglevel43 = pF "eglevel43"
eglevel44 = pF "eglevel44"
eglevel51 = pF "eglevel51"
eglevel52 = pF "eglevel52"
eglevel53 = pF "eglevel53"
eglevel54 = pF "eglevel54"
eglevel61 = pF "eglevel61"
eglevel62 = pF "eglevel62"
eglevel63 = pF "eglevel63"
eglevel64 = pF "eglevel64"
-- operator envelope generator rates
egrate11 = pF "egrate11"
egrate12 = pF "egrate12"
egrate13 = pF "egrate13"
egrate14 = pF "egrate14"
egrate21 = pF "egrate21"
egrate22 = pF "egrate22"
egrate23 = pF "egrate23"
egrate24 = pF "egrate24"
egrate31 = pF "egrate31"
egrate32 = pF "egrate32"
egrate33 = pF "egrate33"
egrate34 = pF "egrate34"
egrate41 = pF "egrate41"
egrate42 = pF "egrate42"
egrate43 = pF "egrate43"
egrate44 = pF "egrate44"
egrate51 = pF "egrate51"
egrate52 = pF "egrate52"
egrate53 = pF "egrate53"
egrate54 = pF "egrate54"
egrate61 = pF "egrate61"
egrate62 = pF "egrate62"
egrate63 = pF "egrate63"
egrate64 = pF "egrate64"
-- operator output levels
amp1 = pF "amp1"
amp2 = pF "amp2"
amp3 = pF "amp3"
amp4 = pF "amp4"
amp5 = pF "amp5"
amp6 = pF "amp6"
-- operator frequency ratios
ratio1 = pF "ratio1"
ratio2 = pF "ratio2"
ratio3 = pF "ratio3"
ratio4 = pF "ratio4"
ratio5 = pF "ratio5"
ratio6 = pF "ratio6"
-- operator frequency detuners
detune1 = pF "detune1"
detune2 = pF "detune2"
detune3 = pF "detune3"
detune4 = pF "detune4"
detune5 = pF "detune5"
detune6 = pF "detune6"
d1 $ slow 8 $ n (scale "harmonicMinor" (segment 4 $ irand 7))
# s "dxt"
-- operator output levels
# amp1 1
# amp2 0
# amp3 0
# amp4 0
# amp5 1
# amp6 2
-- operator frequency ratios
# ratio2 (rand * 2)
# ratio3 (rand + 3)
# ratio4 (rand + 4)
# ratio5 0.5
# ratio6 0.25
-- operator frequency detuners
# detune2 rand * 2
# detune6 rand
-- operator modulators
-- syntax: mod[carrierIndex][modulatorIndex]
-- for feedback, carrier and modulator indices are the same, e.g. mod11
-- range [0.0-1.0] (may be more for really nasty and distorted noise)
# mod11 rand
# mod16 sine
# mod23 ((rand / 2) + 0.2)
# mod34 ((rand / 2) + 0.2)
# mod54 ((rand / 2) + 0.2)
# mod66 (rand + 0.5)
-- operator envelope generators
-- each operator has 4 levels and 4 rates, just like DX7
-- operator envelope generator levels syntax: eglevel[opIndex][levelIndex]
-- the following set op3 EG levels 1, 2 and 3
# eglevel31 0.1
# eglevel32 0.5
# eglevel33 1
-- operator envelope generator rates syntax: egrate[opIndex][levelIndex]
-- the following set op3 EG rates 1, 2 and 3
# egrate31 0.3
# egrate32 0.1
# egrate33 0.1
-- EG settings for op6
# eglevel61 1
# eglevel62 0.1
# eglevel63 2
# egrate61 0.3
# egrate62 1
-- # room 1
d1 silence
(
// 6-op FM synth for TidalCycles (DX7-like)
SynthDef(\dxt, {
var sustain = \sustain.kr(1);
var freq = \freq.kr(440);
// var amp = \amp.kr(1);
var out = \out.kr(0);
var pan = \pan.kr(0);
// overall envelope
var env = EnvGen.ar(Env.linen(0.01, 0.98, 0.01, 1,-3), timeScale:sustain, doneAction:2);
// operator output levels
var amps = Array.fill(6, { |i| (\amp++(i+1)).asSymbol.kr(1)});
// operator frequency ratios
var ratios = Array.fill(6, {|i| (\ratio++(i+1)).asSymbol.kr(i+1)});
// operator frequency detuners
var detunes = Array.fill(6, {|i| (\detune++(i+1)).asSymbol.kr(rand2(0.1))});
// operator envelopes
var envs = Array.fill(6, { |i|
EnvGen.kr(
Env.new(
[0]++Array.fill(3, { |n| (\eglevel++(i+1)++(n+1)).asSymbol.kr(1) })++[0],
[
((\egrate++(i+1)++1).asSymbol).kr(0.01),
((\egrate++(i+1)++2).asSymbol).kr(0.3),
((\egrate++(i+1)++3).asSymbol).kr(1),
((\egrate++(i+1)++4).asSymbol).kr(1),
]
),
timeScale:sustain,
doneAction:2
);
});
var ctls = Array.fill(6, { |i| [freq * ratios[i] + detunes[i], 0, envs[i]]});
// modulation matrix
var mods = Array.fill(6, { |i|
Array.fill(6, { |n| (\mod++(i+1)++(n+1)).asSymbol.kr(0)});
});
var sound = FM7.ar(ctls, mods) * amps;
// FM7 outputs 6 channels. Splay.ar() maps them to stereo.
sound = Splay.ar(sound);
OffsetOut.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env));
}).store;
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment