Classic subtractive synth
This commit is contained in:
parent
9db4d2f2b4
commit
19a18c33db
1 changed files with 228 additions and 0 deletions
228
thesynth.scd
Normal file
228
thesynth.scd
Normal file
|
@ -0,0 +1,228 @@
|
||||||
|
(
|
||||||
|
s.meter;
|
||||||
|
s.freqscope;
|
||||||
|
s.plotTree;
|
||||||
|
)
|
||||||
|
|
||||||
|
(
|
||||||
|
var g0 = Group.new(s); // g0 = main synth group
|
||||||
|
var g1 = Group.after(g0); // g1 = effect group
|
||||||
|
|
||||||
|
var b0 = Bus.audio(s);
|
||||||
|
var b1 = Bus.audio(s);
|
||||||
|
|
||||||
|
var makeSlider, makeChoice, makeButton;
|
||||||
|
var busses = Dictionary.new(0);
|
||||||
|
|
||||||
|
var notes = Array.newClear(128);
|
||||||
|
|
||||||
|
var reverb = nil;
|
||||||
|
var reverbEnabled = false;
|
||||||
|
|
||||||
|
Window.closeAll;
|
||||||
|
w = Window("gui", Rect(750, 50, 1200, 800)).front;
|
||||||
|
w.view.decorator_(FlowLayout(w.bounds, 15@15, 7@7));
|
||||||
|
|
||||||
|
makeButton = {
|
||||||
|
var button = Button(w, 50@50)
|
||||||
|
.states_([
|
||||||
|
["OFF", Color.black, Color.gray],
|
||||||
|
["ON", Color.black, Color.green]
|
||||||
|
])
|
||||||
|
.action_({ |obj|
|
||||||
|
reverbEnabled = (obj.value == 1);
|
||||||
|
obj.value.postln;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
makeButton.value();
|
||||||
|
|
||||||
|
makeChoice = {
|
||||||
|
arg name, items, initValue = 0;
|
||||||
|
var view, menu, bus;
|
||||||
|
|
||||||
|
bus = Bus.control(s);
|
||||||
|
busses.put(name, bus);
|
||||||
|
|
||||||
|
view = CompositeView(w, 200@100);
|
||||||
|
|
||||||
|
menu = PopUpMenu(view, 200@50)
|
||||||
|
.items_(items)
|
||||||
|
.action_({ |obj|
|
||||||
|
obj.value.postln;
|
||||||
|
bus.set(obj.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
StaticText(view, Rect(0, 60, 80, 20)).string_(name);
|
||||||
|
|
||||||
|
menu.valueAction = initValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
makeChoice.value("osc1_type", items: [\sin, \tri, \saw, \pulse]);
|
||||||
|
makeChoice.value("osc1_octave", items: [-2, -1, 0, 1, 2], initValue: 2);
|
||||||
|
makeChoice.value("osc2_type", items: [\sin, \tri, \saw, \pulse]);
|
||||||
|
makeChoice.value("osc2_octave", items: [-2, -1, 0, 1, 2], initValue: 2);
|
||||||
|
makeChoice.value("osc3_type", items: [\sin, \tri, \saw, \pulse]);
|
||||||
|
makeChoice.value("osc3_octave", items: [-2, -1, 0, 1, 2], initValue: 2);
|
||||||
|
|
||||||
|
makeSlider = {
|
||||||
|
arg name, min = 0, max = 1, initValue = 0, exponential = false;
|
||||||
|
var view, slider, numberBox, value, onUpdate, valToSlider, sliderToVal, bus;
|
||||||
|
|
||||||
|
bus = Bus.control(s);
|
||||||
|
busses.put(name, bus);
|
||||||
|
bus.set(initValue);
|
||||||
|
|
||||||
|
onUpdate = { |val|
|
||||||
|
val.postln;
|
||||||
|
bus.set(val);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Transform a number from the range (min, max) to the range (0, 1)
|
||||||
|
valToSlider = { |val|
|
||||||
|
if(exponential, val.explin(min, max, 0, 1), val.linlin(min, max, 0, 1));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Transform a number in the range (0, 1) to the range (min, max)
|
||||||
|
sliderToVal = { |val|
|
||||||
|
if(exponential, val.linexp(0, 1, min, max), val.linlin(0, 1, min, max));
|
||||||
|
};
|
||||||
|
|
||||||
|
view = CompositeView(w, 120@200);
|
||||||
|
slider = Slider(view, Rect(0, 0, 30, 120));
|
||||||
|
numberBox = NumberBox(view, Rect(0, 125, 80, 25)).clipLo_(min).clipHi_(max).decimals_(4);
|
||||||
|
|
||||||
|
slider.action = { |obj|
|
||||||
|
var val = sliderToVal.value(obj.value);
|
||||||
|
numberBox.value_(val);
|
||||||
|
onUpdate.value(val);
|
||||||
|
};
|
||||||
|
|
||||||
|
numberBox.action = { |obj|
|
||||||
|
var sliderVal = valToSlider.value(obj.value);
|
||||||
|
slider.value_(sliderVal);
|
||||||
|
onUpdate.value(obj.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
StaticText(view, Rect(0, 150, 80, 20)).string_(name);
|
||||||
|
|
||||||
|
numberBox.valueAction_(initValue);
|
||||||
|
};
|
||||||
|
|
||||||
|
makeSlider.value("lfo1_freq", 0, 10, 1);
|
||||||
|
makeSlider.value("osc1_amp", 0, 1, 0.1);
|
||||||
|
makeSlider.value("osc2_amp", 0, 1, 0.1);
|
||||||
|
makeSlider.value("osc3_amp", 0, 1, 0.1);
|
||||||
|
makeSlider.value("osc1_detune", 0.9, 1.1, 1);
|
||||||
|
makeSlider.value("osc2_detune", 0.9, 1.1, 1);
|
||||||
|
makeSlider.value("osc3_detune", 0.9, 1.1, 1);
|
||||||
|
makeSlider.value("osc1_pw", 0, 1, 0.7);
|
||||||
|
makeSlider.value("osc2_pw", 0, 1, 0.34);
|
||||||
|
makeSlider.value("osc3_pw", 0, 1, 0.49);
|
||||||
|
makeSlider.value("attack", 0, 5, 0.1);
|
||||||
|
makeSlider.value("decay", 0, 1, 0);
|
||||||
|
makeSlider.value("sustain", 0, 1, 1);
|
||||||
|
makeSlider.value("release", 0, 5, 1);
|
||||||
|
makeSlider.value("filter_cutoff", 220, 15000, 220, exponential: true);
|
||||||
|
makeSlider.value("filter_res", 0.05, 0.95, 0.5);
|
||||||
|
makeSlider.value("filter_attack", 0, 5, 0);
|
||||||
|
makeSlider.value("filter_decay", 0, 1, 0);
|
||||||
|
makeSlider.value("filter_sustain", 0, 1, 1);
|
||||||
|
makeSlider.value("filter_release", 0, 5, 5);
|
||||||
|
makeSlider.value("gain", 0, 1, 0.2);
|
||||||
|
|
||||||
|
|
||||||
|
SynthDef.new(\synth, {
|
||||||
|
arg freq = 440, outbus = 0, gate = 1, amp = 0.5, ffreqBus = 0, rqBus = 0;
|
||||||
|
var osc1, osc2, osc3, lfo1, sig, env, ffreq, rq, pw1, pw2, pw3, fenv, getOsc, gain;
|
||||||
|
|
||||||
|
lfo1 = SinOsc.kr(In.kr(busses["lfo1_freq"])).range(0.9, 1.1);
|
||||||
|
|
||||||
|
getOsc = { |name|
|
||||||
|
var detune = In.kr(busses[name ++ "_detune"]);
|
||||||
|
var amp = In.kr(busses[name ++ "_amp"]);
|
||||||
|
var pulseWidth = In.kr(busses[name ++ "_pw"]);
|
||||||
|
var octave = pow(2, In.kr(busses[name ++ "_octave"]) - 2);
|
||||||
|
|
||||||
|
Select.ar(which: In.kr(busses[name ++ "_type"]), array: [
|
||||||
|
SinOsc.ar(freq * detune * octave, mul: amp)!2,
|
||||||
|
LFTri.ar(freq * detune * octave, mul: amp)!2,
|
||||||
|
VarSaw.ar(freq * detune * octave, width: pulseWidth * lfo1, mul: amp)!2,
|
||||||
|
Pulse.ar(freq * detune * octave, width: pulseWidth * lfo1, mul: amp)!2
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
|
osc1 = getOsc.value("osc1");
|
||||||
|
osc2 = getOsc.value("osc2");
|
||||||
|
osc3 = getOsc.value("osc3");
|
||||||
|
|
||||||
|
env = EnvGen.kr(Env.adsr(In.kr(busses["attack"]), In.kr(busses["decay"]), In.kr(busses["sustain"]), In.kr(busses["release"])), gate, doneAction: 2);
|
||||||
|
|
||||||
|
sig = Mix.ar([osc1, osc2, osc3]);
|
||||||
|
gain = In.kr(busses["gain"]);
|
||||||
|
sig = sig * env * amp * gain;
|
||||||
|
|
||||||
|
ffreq = In.kr(busses["filter_cutoff"]);
|
||||||
|
fenv = EnvGen.kr(Env.adsr(In.kr(busses["filter_attack"]), In.kr(busses["filter_decay"]), In.kr(busses["filter_sustain"]), In.kr(busses["filter_release"])), gate, doneAction: 2);
|
||||||
|
ffreq = ffreq * fenv;
|
||||||
|
rq = In.kr(busses["filter_res"]);
|
||||||
|
sig = RLPF.ar(sig, ffreq, rq);
|
||||||
|
|
||||||
|
Out.ar(outbus, sig);
|
||||||
|
|
||||||
|
}).add;
|
||||||
|
|
||||||
|
SynthDef.new(\reverb, {
|
||||||
|
arg inbus, outbus;
|
||||||
|
Out.ar(outbus, JPverb.ar(in: In.ar(inbus)));
|
||||||
|
}).add;
|
||||||
|
|
||||||
|
MIDIdef.noteOn(\noteOn, {
|
||||||
|
arg vel, nn, chan, src;
|
||||||
|
|
||||||
|
var outbus = if(reverbEnabled, { b0 }, { 0 });
|
||||||
|
|
||||||
|
[vel, nn, chan, src].postln;
|
||||||
|
notes[nn] = Synth.new(\synth, [
|
||||||
|
\freq, nn.midicps,
|
||||||
|
\gate, 1,
|
||||||
|
\outbus, outbus,
|
||||||
|
], target: g0);
|
||||||
|
|
||||||
|
if(reverbEnabled && (reverb == nil), {
|
||||||
|
reverb = Synth.new(\reverb, [
|
||||||
|
\inbus, b0,
|
||||||
|
\outbus, 0
|
||||||
|
], target: g1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
MIDIdef.noteOff(\noteOff, {
|
||||||
|
arg vel, nn;
|
||||||
|
[vel, nn].postln;
|
||||||
|
notes[nn].set(\gate, 0);
|
||||||
|
notes[nn] = nil;
|
||||||
|
});
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
(
|
||||||
|
MIDIClient.init;
|
||||||
|
MIDIIn.connectAll;
|
||||||
|
)
|
||||||
|
|
||||||
|
(
|
||||||
|
~notes = [30, 34, 37, 42, 46, 49];
|
||||||
|
|
||||||
|
p = Pdef(\pattern,
|
||||||
|
Pbind(
|
||||||
|
\instrument, \synth,
|
||||||
|
\midinote, Prand(~notes.collect({ |n| n + 12 }), inf),
|
||||||
|
\dur, 0.25
|
||||||
|
)
|
||||||
|
).play;
|
||||||
|
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
p.stop;
|
Loading…
Add table
Add a link
Reference in a new issue