Kod:
// TODO:
// * Randomize-buttons, randomizing parameters in some fun way
// * Reverb-control
// * Add some sort of LPG and envelopes
// * Midi control
s.boot;
s.volume.gui;
// How to run the synth:
// 1. Run the synth definition and startup block
// 2. Run the GUI block
(
// Define the synth and filter
SynthDef(\complexOscillator, {
var sig;
var primaryOsc, primaryFreq;
var modFreq, modOsc;
var fold, foldIndex;
var freqOsc;
primaryFreq = \freq.kr(100);
// Modulating Oscillator
modFreq = primaryFreq * (2 ** \modFreq.kr(0));
modOsc = LFTri.ar(modFreq);
// FM
freqOsc = modOsc.bipolar(\fmIndex.kr(0)).midiratio * primaryFreq;
// Primary Oscillator
fold = \fold.ar(1).lag(0.2) + (modOsc.unipolar() * \foldIndex.kr(0));
primaryOsc = SinOsc.ar(freqOsc, 0, fold);
sig = SmoothFoldS.ar(primaryOsc, smoothAmount: \smooth.kr(0).lag(0.1));
sig = sig ! 2;
Out.ar(\out.kr(0), sig);
}).add;
SynthDef(\barkFilter, {
var sig, bands, filters, rq, filtered;
rq = \rq.kr(0.5);
sig = In.ar(\in.kr(0), 2);
filters = [
RLPF.ar(sig, 100, rq) * \amp0.kr(0.5),
BPF.ar(sig, 150, rq) * \amp1.kr(0.5),
BPF.ar(sig, 250, rq) * \amp2.kr(0.5),
BPF.ar(sig, 350, rq) * \amp3.kr(0.5),
BPF.ar(sig, 500, rq) * \amp4.kr(0.5),
BPF.ar(sig, 630, rq) * \amp5.kr(0.5),
BPF.ar(sig, 800, rq) * \amp6.kr(0.5),
BPF.ar(sig, 1000, rq) * \amp7.kr(0.5),
BPF.ar(sig, 1300, rq) * \amp8.kr(0.5),
BPF.ar(sig, 1600, rq) * \amp9.kr(0.5),
BPF.ar(sig, 2000, rq) * \amp10.kr(0.5),
BPF.ar(sig, 2600, rq) * \amp11.kr(0.5),
BPF.ar(sig, 3500, rq) * \amp12.kr(0.5),
BPF.ar(sig, 5000, rq) * \amp13.kr(0.5),
BPF.ar(sig, 8000, rq) * \amp14.kr(0.5),
RHPF.ar(sig, 10000, rq) * \amp15.kr(0.5),
];
filtered = Mix(filters);
sig = sig.blend(filtered, \mix.kr(1));
Out.ar(\out.kr(0), sig);
}).add;
SynthDef(\rev, {
var sig;
sig = In.ar(bus: \in.kr(0), numChannels: 2);
sig = FreeVerb.ar(sig, \mix.kr(0.15), \room.kr(0.5), \damp.kr(0.5));
Out.ar(\out.ir(0), sig)
}).add;
// Start up the synth and filter
s.newBusAllocators;
~bus = ();
~bus.src = Bus.audio(s, 2);
~bus.barkFilter = Bus.audio(s, 2);
~bus.rev = Bus.audio(s, 2);
~rev = Synth(\rev, [in: ~bus.barkFilter, out: 0]);
~filter = Synth(\barkFilter, [in: ~bus.src, out: ~bus.barkFilter]);
~osc = Synth(\complexOscillator, [out: ~bus.src]);
)
// Build the GUI
(
var win, primaryOscCtrl, modOscCtrl, sliders, foldCtrl, filterCtrl;
win = Window.new("Complex oscillator", Rect(600, 700, 900, 250)).front.alwaysOnTop_(true);
win.view.decorator_(FlowLayout(win.bounds, 20@20, 20@20));
sliders = ();
sliders.fmIndex = Slider.new().action_({
arg v;
~osc.set(\fmIndex, v.value);
});
primaryOscCtrl = CompositeView(win, 200@200).background_(Color.rand);
primaryOscCtrl.layout_(GridLayout.columns(
[
Knob().action_({
arg v;
~osc.set(\freq, v.value.linexp(0, 1, 20, 2000));
}).valueAction_(0.2),
StaticText().string_('Primary Osc'),
],
[
Slider().action_({
arg v;
~osc.set(\fmIndex, v.value.linlin(0, 1, 0, 72));
}).valueAction_(0.1),
StaticText().string_('FM Index'),
]
));
modOscCtrl = CompositeView(win, 100@200).background_(Color.rand);
modOscCtrl.layout_(GridLayout.columns(
[
Knob().action_({
arg v;
~osc.set(\modFreq, v.value.linlin(0, 1, -4, 4));
}).valueAction_(0.5),
StaticText().string_('Mod Osc, rel to primary'),
],
));
foldCtrl = CompositeView(win, 200@200).background_(Color.rand);
foldCtrl.layout_(GridLayout.columns(
[
Slider().action_({
arg v;
~osc.set(\fold, v.value.linlin(0, 1, 1, 10));
}).valueAction_(0.1),
StaticText().string_('Fold'),
],
[
Slider().action_({
arg v;
~osc.set(\smooth, v.value);
}).valueAction_(0),
StaticText().string_('Smooth'),
],
[
Slider().action_({
arg v;
~osc.set(\foldIndex, v.value * 7);
}).valueAction_(0.2),
StaticText().string_('Mod'),
],
));
filterCtrl = CompositeView(win, 300@200).background_(Color.rand);
filterCtrl.layout_(GridLayout.columns([
MultiSliderView(w,Rect(0,0,300,200)).size_(16).isFilled_(true).elasticMode_(true).action_({
arg q;
q.value.collect({
arg v, index;
~filter.set("amp" ++ index, v.value);
})
}).valueAction_(16.collect({rrand(0.3, 0.7)})),
StaticText().string_('Spectral Filter'),
], [
Slider().action_({
arg v;
~filter.set(\rq, v.value.linlin(0, 1, 0.01, 0.5));
}).valueAction_(0.3),
StaticText().string_('Q'),
]));
)