SynthDef Factory + Batch Instantiation (Analog-modeling)
(
~makeAnalogDirtSynth = { |name, waveFunc|
SynthDef(name, { |out, sustain=1, pan, accelerate, freq=440, speed=1, gain=1, decay=0,
coarse=0, fine=0, width=0.5, detune=0, harmonic=1, sync=1, phaseOffset=0, phaseRand=0|
var env, baseFreq, syncFreq, startPhase, phase, sig, trig;
env = EnvGen.ar(Env.pairs([[0,0],[0.05,1],[0.2,1-decay],[0.95,1-decay],[1,0]], -3), timeScale:sustain, doneAction: Done.freeSelf);
baseFreq = ((harmonic > 0) * (freq * DirtFreqScale.kr(speed, accelerate, sustain) - 1) + 1);
baseFreq = baseFreq * harmonic * ((coarse + (fine * 0.01)).midiratio) + detune;
baseFreq = baseFreq.clip(20, 20000);
syncFreq = baseFreq * sync.max(1);
trig = Impulse.kr(0);
startPhase = (phaseOffset + Rand(0, phaseRand)).wrap(0, 1);
phase = Phasor.ar(trig, syncFreq * SampleDur.ir, 0, 1, resetPos: startPhase);
sig = waveFunc.value(phase, width.clip(0.001, 0.999));
Out.ar(out, DirtPan.ar(sig * gain, ~dirt.numChannels, pan, env));
}).add;
};
[
\sine, { |p| (p * 2pi).sin },
\cosine, { |p| ((p * 2pi) + 0.5pi).sin },
\saw, { |p| (p * 2) - 1 },
\isaw, { |p| 1 - (p * 2) },
\sq, { |p, w| (p - w).sign },
\tri, { |p, w|
var rising = p / w;
var falling = (1 - p) / (1 - w);
(p <.ar w).if(rising, falling) * 2 - 1;
}
].pairsDo { |name, func| ~makeAnalogDirtSynth.value(name, func) };
)
Variables
-- Analog Synth Parameters
let coarse = pF "coarse"
fine = pF "fine"
width = pF "width"
sync = pF "sync"
harmonic = pF "harmonic"
phaseOffset = pF "phaseOffset"
phaseRand = pF "phaseRand"
Usage
d1 $ n "0"
# s "<sine cosine saw isaw sq tri>"
d1 $ n "0*4"
# sound "<sq tri>"
# width "0.01 0.25 0.5 0.99"
d1 $ n "0"
# sound "sq"
# phaseOffset "<0.1 0.5 0.9>"
d1 $ n "0"
# sound "sq"
# phaseRand "0.5"
d1 $ n "0"
# s "sq"
# coarse "<-12 -6 0 6 12>"
# fine "<-100 0 100>"
d1 $ n "0"
# s "sine"
# harmonic "2"
d1 $ n "0"
# s "sine"
# sync "4"
d1 $ n "0"
# s "sine"
# detune "159"