Good piano sound?

Pianoteq is great, too.

1 Like

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

3 Likes

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

1 Like

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!

1 Like

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 :smiling_imp:

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 :slight_smile:

1 Like

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

1 Like

Another plug for Pianoteq - automating the model parameters in SC is pretty amazing…

2 Likes

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.

2 Likes

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

8 Likes

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? :slight_smile: 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!

1 Like

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…

1 Like

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.