OFX_ChainPreset can store presets for OFX_Chain objects: A setting includes which functions are active (by name), and separate parameter settings for each active function.
First code examples:
s.boot;
// first, prepare for making a proxy chain:
(
// some sound functions - first a test source,
(
// add a sound source
OFX_Chain.add3(
\dust,
\mix -> { |dens=20, dustdec=0.02, dustfreq= 600|
Ringz.ar(Dust2.ar(dens).lag(0.0001), dustfreq, dustdec)
},
0.2,
[
\dens, [0.1, 1000, \exp],
\dustdec, [0.0001, 0.1, \exp],
\dustfreq, \freq
]
);
// ... and then some effects to use in the chain
OFX_Chain.add3(
\ringmod,
\filter -> { |in, randrate=5|
in.asArray[0] // force mono inputs
* SinOsc.ar(LFNoise0.kr([randrate, randrate]).exprange(300, 3000)).sum
},
0.5, // wet/dry mix of 50/50
[ \randrate, [0.5, 50, \exp] ]
);
OFX_Chain.add3(
\dist, \filter -> { |in, drive=10, amp=0.2| (in.asArray[0] * drive).tanh * amp },
1, // all wet, just the dito
[ \drive, [1, 100, \exp] ],
);
OFX_Chain.add3(
\comb5, \filterIn -> { |in, drive=10, amp=0.2| (in.asArray[0] * drive).clip2(0.5) * amp },
0.2,
[ \drive, [1, 100, \exp] ],
);
OFX_Chain.add(
\ampFin,
\filter -> { |in, drive=1, limit=1| Limiter.ar(in * drive, limit) },
1,
[
\drive, [1, 100, \exp],
\limit, [0.1, 1.0, \exp]
]
);
);
// now make a proxy chain and gui for it
c = OFX_Chain(\alpha, [\dust, \ringmod, \dist, \ampFin]);
c.play; // play the proxy
g = c.gui(12).moveTo(0, 800);
// 2. make a OFX_ChainPreset for c
b = OFX_ChainPreset(c);
// declare ampFin as always untouched / not to be stored
b.exceptedSlots = [\ampFin];
)
b.slotsToStore; // these slots and their values will be stored when active
c.activeSlotNames; // these are currently active
c.add(\dust, 0.5);
c.add(\ringmod, 1);
c.activeSlotNames; // these are currently active
b.addSet(\test1);
b.settings.list;
// repeat unil you find one you like
c.proxy.setUni( *c.proxy.controlKeys.collect ( [_, 1.0.rand] ).flat );
b.addSet(\test2);
b.settings.prettyList; // two entries
// add a slot and add a setting
c.add(\dist, 1);
b.addSet(\test3);
// remove another and addSet
c.remove(\ringmod);
b.addSet(\test4);
c.remove(\dist);
c.proxy.set(\dustfreq, 3000, \dens, 7, \dustdec, 0.01);
b.addSet(\test5);
// now you have 5 different settings - switch between them:
b.settings.prettyList;
b.settings.names
b.setCurr(\test1);
b.setCurr(\test2);
b.setCurr(\test3);
b.setCurr(\test4);
b.setCurr(\test5);
// now write them to disk
b.settings.write;
b.settingNames;
dict where all OFX_ChainPreset objects are stored by name
make a OFX_ChainPreset for a key or a OFX_Chain
keyOrObj |
the proxychain
the proxy of the proxychain
the key by which this OFX_ChainPreset is stored.
which slot names will be stored if active
get and set which slots are not to be stored
the settings object that does storage
add and remove a setting by name
get current setting from proxy/chain
set current setting
setName |
name of setting |
absolute |
if true turns off slots not present in setting |
except |
write settings to disk
read settings from disk
setName |
get names of all settings
Here is a quick and dirty gui sketch for a OFX_ChainPresetGui, assuming you still have b and c preset from above around:
xxxxxxxxxx
// assumes OFX_ChainPreset b is still around
// writing alpha to disk will store here:
b.settings.storePath;
b.settings.filename;
// set the dirpath to something else:
b.settings.dirpath;
(
w = Window("PCPre", Rect(0,600,500,500)).front;
w.addFlowLayout;
e = EZPopUpMenu(w, Rect(0,0,150, 20), \pcPre, b.settingNames,
{ |ez| b.setCurr(ez.item) },
labelWidth: 50);
[
\sto, { |but|
b.settings.storeDialog('???',
b.getCurr,
but.absoluteBounds.center,
// store settings to disk?
{ b.settings.write }
)
},
\del, { |but|
b.settings.deleteDialog(
but.absoluteBounds.center,
// store settings to disk?
{ b.settings.write }
)
}
].keysValuesDo { |key, fun|
Button(w, Rect(0,0,60,20)).states_([[key]])
.action_(fun)
};
g = OFX_ChainGui(c, 20, w);
// update e when stored names change:
q.pcpSkip = q.pcpSkip ?? {
SkipJack({
var newnames = b.settings.names;
if ( (newnames == q.pcpNames).not) {
e.items = newnames;
}
}, 0.5, w.isClosed);
};
)
An example of a OFX_OutputFX / OFX_ChainPreset combination, using the same sound functions as above:
xxxxxxxxxx
m = OFX_OutputFX(s, 2, [\dust, \ringmod, \dist, \ampFin]);
n = OFX_ChainPreset(m);
n.exceptedSlots = [\ampFin];
// quick and dirty copy of the settings
n.settings.list.addAll(b.settings.list);
n.settings.names;
n.setCurr(n.settings.names.choose.postcs);
n.setCurr(\test2);
n.setCurr(\test3);