I'm happy to announce the first stable release of vstplugin~, a cross-platform Pd external for using VST plugins in Pd.
Binaries are already available on Deken.
The repository also includes a version for Supercollider called VSTPlugin (which works very differently but achieves the same thing).
The overall design and functionality of vstplugin~ v0.1.0 is the same as in vstplugin~ v0.1-alpha, but there are some breaking changes and new features! Have a look at the change log in https://git.iem.at/pd/vstplugin/releases
Source code: https://git.iem.at/pd/vstplugin/tree/master
- use any VST plugin (audio effect, MIDI effect, soft synth etc.)
- search and probe plugins in the standard VST directories or in user defined paths
- automate plugin parameters programmatically
- use either the native VST GUI (WIN32, Cocoa, X11) or a generic editor
(NOTE: the VST GUI doesn't work [yet] for SuperCollider on macOS)
- preset management: read/write standard .fxp and .fxb files or
set/get the plugin state as raw data to build your own preset management
- MIDI input/output
- basic sequencing support (for arpeggiators, sequencers etc.)
NOTE: currently only VST2.x plugins are supported but VST3 support will come soon!
64bit VST plugins can only be loaded with the 64bit version of [vstplugin~] / VSTPlugin.scx and vice versa.
See the help files (vstplugin~-help.pd and VSTPlugin.schelp) for detailed instructions.
If possible, please report any issues or feature requests to https://git.iem.at/pd/vstplugin/issues
Generally, the "blocksize" in the audio setting really is the hardware buffer size and not Pd's global blocksize (which is always 64 samples).
Modern ASIO drivers are multiclient which means that the device can be used by more than one app at the same time. When you set the buffer size in your device app (e.g. Focusrite MixControl) this will set the internal blocksize and consequently the minimum latency possible for all clients. Usually you would want to set the internal buffer size as low as possible (without getting audio glitches).
Individiual clients (e.g. a Pd instance) can request a buffer size from the device. This can't be smaller than the above mentioned internal buffer size, but it can be larger (if you need extra latency). Most DAWs control the latency via the buffer size while Pd has it's own buffering mechanism ("delay").
Note that for Pd the hardware buffer size affects the overall timing resolution (when DSP is on). Pd will calculate several blocks of 64 samples as fast as possible until it has enough samples to send to the device. If the hardware buffer size is 256, Pd will calculate 4 blocks in a row (4 * 64 = 256) and then wait until the device asks for another 256 samples. This causes jitter! (Try [bang~] with [realtime] and [print] to see it yourself). The lower the hardware buffer size, the less jitter you get, so generally it's better to keep "blocksize" as low as possible and rather increase "delay" if you need more latency.
BTW, in case of old single client ASIO drivers, "blocksize" would directly set the hardware buffer size of the device. This is still the case e.g. with ASIO4ALL.
Put in a formal way, it means that computation time equals O(n).
I give you a simple example regarding [list-split]: Let's suppose dripping 100 elements would take 0.01 ms, then dripping 1000 elements will take 0.1 ms; 10.000 elements will take 1 ms etc.
I think the algorithm of [list-drip] itself should be actually O(log(n)) but in Pd you'll end up with O(n). At least this is what I've measured... Please anyone correct me if I'm wrong
BTW: As you might have seen in the mailling list, you shouldn't use the iterative approach either:
It gets reeeeally slow for longer lists, but at least it won't give you a stack overflow.
Ironically enough, it was Miller who was suggesting it, but then it turned out that it won't work as expected because of the copying. Miller somehow gave a hint that he might change the behaviour of [list] in a way that it won't make a copy if the left inlet only receives a bang. Then the iterative approach would work fine.
Finally I'd like to point out that list-abs' [list-drip] actually does two tricks: protecting against stack overflow by halfing the lists AND keeping computation time linear by avoiding all the [list objects] that do unnessecary copying. Pretty clever
Beware that you're 'normal' version of [list-drip] ist not linear, but rather exponential in computation time! This is because Pd will make a lot of copies of the list and you may end up with a stack overflow. Try, for example, sending a long list with a few hundred alements - Pd will most likely crash!
The main reason why list-abs' [list-drip] abstraction makes use of this special algorithm is to keep the computation time linear.
Coincidently, this has been discussed on the Pd mailing list just a couple of days ago, so you may want to have a look: http://lists.puredata.info/pipermail/pd-list/2015-10/111681.html
(Matt speaks about an abstraction that works basically the same way as your 'normal' one)
PS: A good (and faster) alternative to list-abs' [list-split] is zexy's [drip].
I made two phase vocoder abstractions, [cphasevoc~] and [cpitchshift~], based on Miller Puckette's example patch. The first is meant to be used on tables and to my ears it produces less artifacts than [pvoc~]. The second one is used on incoming audio signals.
You can use both for a freeze effect, depending on if you work on tables or live audio.
In the first case, you simply have the reading index of [cphasevoc~] at a constant value or vary it by a small amount to get some variations in sound.
In the second case, [cpitchshift~] has a dedicated 'freeze' method to capture live input. Of course you can also pitchshift the captured sound.
In both cases I'd go for rather large window sizes and set phase locking to zero or slightly above. Together with pitchshifting you can get quite interesting results. Try it on different kinds of source material!
Here are the patches:
Note: [cpitchshift~] requires the object [z~] from zexy.
BTW, here's the "correct" 1 pole 1 zero highpass filter:
#N canvas 0 50 450 300 10;
#X obj 40 63 inlet~;
#X obj 49 238 outlet~;
#X obj 139 31 inlet~;
#X obj 50 209 rpole~;
#X obj 48 140 *~;
#X obj 141 69 /~;
#X obj 206 69 samplerate~;
#X obj 205 31 loadbang;
#X obj 143 166 +~ 1;
#X obj 149 189 *~ 0.5;
#X obj 49 177 rzero~ 1;
#X obj 138 132 expr~ (1-sin($v1))/cos($v1);
#X obj 134 102 *~ 6.28319;
#X connect 0 0 4 0;
#X connect 2 0 5 0;
#X connect 3 0 1 0;
#X connect 4 0 10 0;
#X connect 5 0 12 0;
#X connect 6 0 5 1;
#X connect 7 0 6 0;
#X connect 8 0 9 0;
#X connect 9 0 4 1;
#X connect 10 0 3 0;
#X connect 11 0 3 1;
#X connect 11 0 8 0;
#X connect 12 0 11 0;
I 'm not really an expert on filter mathematics at all, but I tested the impulse response of the mentioned filters. [bp~] is actually quite shocking as it doubles the gain at high frequencies! [vcf~] is also not so impressive. The IEM-filters work as expected, though, and I guess I'll use them more in the future . For comparison I build a 1 pole 1 zero high pass using pd's raw filters and I got the exact same result as with [hp1] from iemlib.
I actually have a possible explanation for the "weird" frequency response of pd's [hip~]: The overall behaviour is that of a 1 pole 1 zero high pass filter, but it looks like Miller used another formular to calculate the filter coefficient from the cutoff frequency. The frequency response gets more and more "behind" for higher cutoff frequencies and eventually the pole stops at 0 at 7000 Hz (which is weird!). What is left is the zero at 1 , thus the filter freezes at the frequency response of a 1 pole 1 zero high pass at 1/2 nyquist (11025).
The "real" formula for the filter coefficient based on the cutoff frequency, however, is: p = (1 - sin(x))/cos(x) (where x is the frequency in radians). Here p goes all the way from 1 to -1 over course of 0 - nyquist. At the nyqist the output of the filter is 0 as you would expect.
As Miller writes in the help file, [hip~] is primarily meant to be used for DC removal and it does its job fine. But there should be warnings in the helpfiles of [hip~], [bp~] and [vcf~]