Pianoteq is great, too.
BTW VSTPlugin’s setup is not that complicated in the end, but if you haven’t used it before, sorting out the commands you need can take some effort.
So here’s a quick example for sfizz.
s.boot;
// only once, before first use
// the search will be cached,
// don't need to repeat it unless you install more plug-ins
VSTPlugin.search;
// ... wait for scan (can take awhile...)
(
SynthDef(\vstInst, { |out = 0|
Out.ar(0, VSTPlugin.ar(numOut: 2));
}).add;
)
a = Synth(\vstInst);
c = VSTPluginController(a);
c.open("sfizz.vst3", editor: true);
c.editor;
// GUI opens -- choose the sfz file for your piano
// save a preset so you can recover without GUI next time
c.writeProgram("~/piano.vstpreset".standardizePath);
c.close;
a.free;
// now, when you need to just play it
(
a = Synth(\vstInst);
c = VSTPluginController(a);
c.open("sfizz.vst3", action: { |vstctl, success|
if(success) {
c.readProgram("~/piano.vstpreset".standardizePath, { |vstctl, success|
if(success) {
"OK, ready!".postln
} {
"Couldn't read preset".warn;
};
})
} {
"Couldn't open VST plugin".warn;
};
});
)
m = c.midi;
// fake Milton Babbitt
(
p = Pbind(
\type, \midi,
\midiout, m,
\midinote, Pwhite(36, 84, inf),
\dur, Pexprand(0.1, 0.4, inf),
\legato, Pexprand(0.2, 6, inf),
\amp, Pwhite(0.2, 0.8, inf)
).play;
)
p.stop;
a.free;
For the quick example, I just saved the preset file in the home directory. In practice, I would save it in the same location as the scd file, and specify the path as thisProcess.nowExecutingPath.dirname +/+ "piano.vstpreset"
. (Keeping all the resources together is simpler for project maintenance.)
hjh
Ha! I’ve just been looking for good free piano samples. “Salamander Grand Piano” sounds quite decent!
On subject of free piano samples, I had a lot of fun with this one, Chapters Piano – pianobook
The event type should rather be vst_midi
to ensure proper timing! Note that vst_midi
has a \vst
key (= the VSTPluginController
instance) instead of \midiout
. In your case the pattern would look like this:
(
p = Pbind(
\type, \vst_midi,
\vst, c,
\midinote, Pwhite(36, 84, inf),
\dur, Pexprand(0.1, 0.4, inf),
\legato, Pexprand(0.2, 6, inf),
\amp, Pwhite(0.2, 0.8, inf)
).play;
)
Fun fact: VSTPlugin
+sfizz
also allows for microtonal MIDI playback i.e. the \midinote
parameter can be floating point number with a fractional part!
Ah, I hadn’t realized that latency wasn’t implemented.
But, looking at the classes, it looks to me like it could be done:
// MIDI / Sysex
sendMidi { arg status, data1=0, data2=0, detune, latency;
// LATER we might actually omit detune if nil
this.sendBundle(latency, ['/midi_msg', Int8Array.with(status, data1, data2), detune ?? 0.0]);
}
// later...
sendBundle { arg latency ... cmds;
synth.server.listSendBundle(latency, cmds)
}
… then VSTPluginMIDIProxy could have a latency
member variable, and pass it to sendMidi.
There would be some benefit to this. For instance, my live coding framework plays pitched material through my Voicer
class. Voicer
can play synths, or can accept a MIDIOut-compatible object as the target. To support VSTPlugin, it would be nice if VSTPluginMIDIProxy could be that MIDIOut-compatible object. Otherwise, I would have to engineer my own Adapter layer (but that seems rather silly, since there already is one that does everything except handle latency).
I would not have predicted this … hm, next live set with microtonally f…ouled up harp
hjh
I think the OteyPiano supercollider extension sounds great. It’s a physical model.
https://doc.sccode.org/Classes/OteyPiano.html
I had considered this before. First off, I don’t really like the idea that the user would have to manually set a latency
member. After all, it is just a hack for MIDIOut
to (somewhat) synchronize a MIDI device with the Server. VSTPlugin
does not need it.
Also, I don’t think that a method called sendMidi
should ever schedule a bundle under the hood. My idea was that the VSTPluginMIDIProxy
methods would behave the same way as other (synchronous) Server commands, such as VSTPluginController.set
or Node.set
.
Finally, there are some more subtle issues with the \midi
Event type: when you have an array of MIDI events, it would send each Event individually. Now, if \strum
is used, it would delay events accordingly on the SystemClock, but what you really want is to schedule all events as bundles with appropriate timetags (latency + offset).
Long story short: the \midi
Event type is just not suitable for controlling Server objects. That’s why I have added the \vst_midi
Event type, which behaves more like other Server events.
Otherwise, I would have to engineer my own Adapter layer (but that seems rather silly, since there already is one that does everything except handle latency).
I mean, the only thing you have to do is replace \midi
with \vst_midi
and \midiout
with \vst
. And since we’re talking about a framework, you would only have to do it once and be done. I think it’s a reasonable tradeoff
Yeah! I’ve just finished a piece that features a detuned virtual piano and vstplugin~
+ sfizz + “Salamander Grand Piano” works really nicely for my purposes.
Voicer doesn’t use events to send its messages, so this will not work in my case.
I guess documentation should be changed, then, to make it clear that VSTPluginMIDIProxy is not a drop-in replacement for MIDIOut, and never will be. With that, I’d understand that I need to write a new adapter for it anyway.
IMO, frankly, it would be more useful for VSTPluginMIDIProxy to be a drop-in replacement for MIDIOut (I’m willing to bet that most users won’t care about conceptual purity here if it gets in the way – or maybe it’s just me), but you disagree and it’s your codebase, so I have to live with that.
hjh
I guess documentation should be changed, then, to make it clear that VSTPluginMIDIProxy is not a drop-in replacement for MIDIOut, and never will be. With that, I’d understand that I need to write a new adapter for it anyway.
In the documentation for \vst_midi
it says:
NOTE: Always prefer \vst_midi over \midi because the latter doesn’t schedule OSC bundles!
But I should probably also make it clear in the VSTPluginMIDIProxy
help file. Noted! clarify VSTPluginMIDIProxy documentation (#146) · Issues · Pure Data libraries / vstplugin · GitLab
@jamshark70 Bad news: it seems like sfizz does not support MIDI note detuning (yet). Turns out I’ve been only using sforzando by Plogue and somehow thought it would also work with sfizz… Unfortunately, sforzando is only available for Windows and macOS (but you should be able to run it on Linux with the built-in Wine bridge, or external wine bridges, such as yabridge).
Anyway, I’ve made a feature request on GitHub: Feature request: support MIDI detune parameter · Issue #1085 · sfztools/sfizz · GitHub
Another plug for Pianoteq - automating the model parameters in SC is pretty amazing…
Uhhh, I haven’t tried that yet.
BTW, the VST3 version of “Pianoteq 6” - but not “Pianoteq 6 STAGE” - also supports MIDI note detuning, i.e. fractional MIDI notes with VSTPlugin
.
I probably should have mentioned that I am a total noob…
I managed to install the VSTPlugin and I’ve downloaded a sfizz-1.2.0.tar.gz file - so could you please explain how to install sfizz and where to put the Salamander file?
I am running Debian testing, the VSTPlugin is at ~/.local/share/SuperCollider/Extensions/VSTPlugin.
Many thanks!
Apropos this topic I actually messed around with exactly this today. I’ve used sfizz/salamander for a bit but recently switched to the mind blowing pianoteq instead. Made a little pattern test today
On Linux, VST2 plugins usually go to ~/.vst
and VST3 plugins go to ~/.vst3
. Then you just have to boot the Server and call VSTPlugin.search
to scan for new plugins.
The Salamander piano samples can be anywhere. Maybe create a ~/sfz
folder where you keep all your SFZ instruments. Then you only have to drag the SalamanderGrandPianoV3.sfz
file into the sfizz
plugin editor window.
One could build a workaround for this, right? Can I combine \bend midicmds with \noteOn cmds for non-equal temperament tunings? I’m using Pianoteq 7 STAGE as an VST2, sadly the VST3 Plugin won’t load…
Mac OS 10.14.6 Error message for the Pianoteq 7 STAGE VST3
Pianoteq STAGE 7.4.2/20210719/x86_64 fatal error [f52b081c]
Internal Error [com/plug/animation_timer.cc:56].
But this is probably more of a problem on Modartt’s side, right?
Thank you for your work on VSTPlugin!
One could build a workaround for this, right? Can I combine \bend midicmds with \noteOn cmds for non-equal temperament tunings?
The problem is that pitch bend only works on the whole channel, while MIDI note detuning works per note. But if your tuning is fixed (i.e. doesn’t change dynamically), Pianoteq supports Scala files (Scala Home Page)
I’m using Pianoteq 7 STAGE as an VST2, sadly the VST3 Plugin won’t load…
Ah yes, I forgot that there is currently a bug that prevents the VST3 version from loading. I managed to get it working, but I need to make a proper fix…
That’s very nice, thanks for them demo! I’d love to hear what happens when you move some of the sliders under “voicing” and “design” as well.