Something fun I was playing with yesterday, and a peek at my working method.
I just made a small change to Voicer (ddwVoicer quark) to allow it to work with VSTPlugin. readProgram
is using a file I had prepared before with writeProgram
.
s.boot;
(
SynthDef(\vstplugin2, { |out, gate = 1|
var sig = VSTPlugin.ar(numOut: 2);
var eg = EnvGen.kr(Env.asr(0.01, 1, 0.1), gate, doneAction: 2);
Out.ar(out, sig * eg);
}).add;
)
a = Synth(\vstplugin2);
c = VSTPluginController(a);
c.open("sfizz.vst3");
c.readProgram("/home/dlm/share/SC/scd/misc/headroom-piano.vstpreset");
v = Voicer(15, c.midi);
v.gate([60, 64, 67].midicps, 2, 0.5);
v.free;
c.close;
a.release;
With the ddwChucklib quark, I can package that into an instrument:
(
(1..2).do { |numCh|
SynthDef(("vstplugin" ++ numCh).asSymbol, { |out, gate = 1|
var sig = VSTPlugin.ar(numOut: numCh);
var eg = EnvGen.kr(Env.asr(0.01, 1, 0.1), gate, doneAction: 2);
Out.ar(out, sig * eg);
}).add;
};
(
vst: "sfizz.vst3",
program: "headroom-piano.vstpreset",
numCh: 2,
make: { |name|
var out;
~vstSynth = Synth(("vstplugin" ++ ~numCh).asSymbol);
~target = MixerChannel(name, s, 2, 2, ~initLevel, outbus: ~master, completionFunc: { |chan|
~vstSynth.moveToHead(chan.synthgroup).set(\out, chan.inbus.index);
});
~vstCtl = VSTPluginController(~vstSynth);
fork {
var cond = CondVar.new;
var path, loaded;
fork { // yes, we really need to double-fork
~vstCtl.open(~vst, action: { |controller, didLoad|
loaded = didLoad;
cond.signalOne;
});
};
cond.wait;
if(loaded) {
path = ~program;
if(PathName(path).isAbsolutePath.not and: {
thisProcess.nowExecutingPath.isString
}) {
path = thisProcess.nowExecutingPath.dirname +/+ path
};
~vstCtl.readProgram(path, inEnvir { |controller, didLoad|
if(didLoad.not) {
"VC(%) failed to load preset '%'".format(
name.asCompileString, ~program
).warn;
};
});
} {
"VC(%) failed to load plugin '%'".format(name.asCompileString, ~vst).warn;
};
};
~midi = ~vstCtl.midi;
out = Voicer(15, ~midi, target: ~target);
// out.mapGlobal();
out
},
free: { ~vstCtl.close; ~target.free; },
type: \vc) => Fact(\vstVC);
)
Then I can do things like play Piano Phase on a VST, in my live coding system (ddwChucklib-livecode and ddwLivecodeInstruments quarks):
\loadAllCl.eval;
/changeKey.(\bdor);
/changeMeter.(3);
TempoClock.tempo = 126/60;
/make(vstVC:piano/melBP:piano(octave:4));
/piano = "\ins(\seq("*@"), 12, 0.25)::\seq("157", "*")::\seq("26", "@")";
/piano+
/piano- // stop
hjh