Review – Crafter’s Pack from Blue Cat Audio – Part 2
Blue Cat’s Plug’n’Script can jump start your capabilities to write plug-in software without first undertaking an intensive apprenticeship in plug-in development. Let the fun begin!
by David Baer, Sept. 2016
This is the second of three reviews of the components in Blue Cat Audio’s Crafter Pack bundle. It’s also the one I’ve most been looking forward to writing. Plug’n’Script is a plug-in development tool that allows mere mortals to produce significant audio-processing software. More impressive still is that it embraces all the latest technological requirements: it is both 32-bit and 64-bit compatible and supports a great many formats, including VST 3.
To use Plug’n’Script (hereafter PnS for sake of brevity) one must know a bit about writing computer code. But the skill set is nowhere near that required for doing the normal kind of plug-in development requiring using C++ and also requiring a fair amount of other related skills, such as UI management, generation of software compatible with multiple environments, and so on. You need not even have a C++ compiler at your disposal (although you might want to eventually go in that direction if you achieve notable success with PnS).
There are actually two versions of PnS, the regular one and a synth PnS tool, the latter being used when MIDI is involved. To keep things simple, I am going to ignore the MIDI aspect altogether in this review. There’s enough to talk about when we limit the discussion to just audio.
PnS supports a scheme such that a user interface is generated automatically. One need do nothing special other than write Angel Script code for a working plug-in to be achieved. However, for anything sophisticated, the developer will also probably want to provide a custom skin, and this is done with Blue Cat’s standard skinning technology called KUIML. More on the skin aspects later.
A First Plug-in
PnS comes with a substantial number of mostly rather simple working plug-ins. The easiest way to describe the development process is to just analyze one of them, in this case a gain plug-in.
In the UI above, we see a plug-in with one gain knob. There are numerous small buttons at the top that either manage the run-time aspects (there’s a bypass switch on the far left, for example) or the development aspects (the pencil tool invokes an editor for the script). I will let the curious reader learn more about these controls by reading the manual (freely downloadable) rather than devote time to this subject. Here, I want to jump right into the code.
Above is the complete program that results in the Gain plug-in pictured above. There are three significant parts. First a series of array declarations establish the input parameters. In this case, there is just one input parameter, the gain level knob. We also have one other variable, the factor by which the audio samples are multiplied to effect that gain change.
Next we have the processSample function. This function, if present in the script code, gets called once for each sample. Or more accurately, it gets called with the current sample values of all the channels in the signal. For stereo, this would be two. The internal processing could not be simpler in this case. We multiple each channel’s sample value by the gain factor.
Lastly, we have the updateInputParameters function. If present in the script code, this also gets called once per sample, but only if there have been changes to an input parameter. The gain factor is computed using a dB to numeric gain formula. Since there is only one input parameter, we don’t have to worry about wasting cycles with unnecessary calculations. But if there were more than one, we might wish to selectively do only those computations necessary for changed parameters.
On to Something Robust – Swiss Army Stereo Tool
One of the most convenient tools I’ve ever used comes bundled with Cakewalk SONAR. It’s called Channel Tools, and it does a number of really useful things for managing stereo channels. This served as the inspiration for my first project using PnS. I called my plug-in “Swiss Army Stereo Tool”, or SAST for short.
Channel Tools provides delay which is not intended for use as a typical delay effect but rather mostly to accommodate fixing stereo with L and R signals slightly out of sync. It also does L/R (left/right) to M/S (mid/side) and back. It can flip the phase of either or both channels, or swap channels themselves. It offers a flexible panning system for individual L and R channels. In this last case, it actually offers more than reality allows. Each panning knob in Channel Tools has associated width adjustments. I’d like to have some of whatever the Channel Tools designers were smoking when they thought this one up – you cannot impart width to a mono signal, and individual L and R channels are the equivalent of mono signals. So, my version does not attempt to deliver the impossible.
SAST will first operate on the incoming stereo signal, applying a delay to one of the two channels if requested. Unlike Channel Tools, I saw no need to offer independent delays for both channels.
This is followed by an optional conversion between L/R and M/S. I use a formula for conversion that doesn’t care which kind of signal enters the conversion. What comes out will be the other form – more on this a bit later.
Next, the two channels (either L/R or M/S) go through two parallel and independent processing chains: bypass, phase flip, gain adjustment, pan adjustment.
Finally the two channels are rejoined for a final possible conversion between L/R and M/S and a shared output gain adjustment.
In real life, one would never need to use all these functions at once. Panning adjustments to an M/S pair of channels would normally make no sense, just for one example. No, you use SAST to just do the things needed. If you want to collapse a stereo signal to mono, you could invoke both front and back-end L/R <-> M/S conversions and bypass the Side channel. That’s it – mission accomplished. Of course, you could instead skip the M/S conversion business and just adjust the two panners to center – same result.
OK, so let’s start with the input parameters. There are quite a few for SAST and the listing below does not show all the arrays such as minimum, maximum and default values. The entire source can be downloaded for those wishing further study from a URL at the end of this article.
You will note that the parameters do not come in the order described. This is because I decided to add the delay function only after all the rest was finished and working. I knew I had to supply a custom skin, so this was not a problem, since I could place them on the UI as necessary as specified in the skin definition. But anyone relying on automatic creation of the UI will need to order parameters accordingly. The order in the code is the order you’ll see on the UI unless you supply your own skin.
I wanted to make the delay processing a bit more user-friendly. The input parameter unit for delay amount is samples. I wanted to also display milliseconds. To do that, I added an output parameter for this purpose. If you need to display some kind of results, be it a level meter or whatever, PnS requires you to use output parameters, which are declared in a fashion similar to input parameters.
OK, so now we have the parameters defined. What the UI looks like at this point (there’s no skin yet) is not very user friendly.
Clearly we will need to do something about this. But first let’s just worry about getting the plug-in to run correctly. Next in the program are a fair number of local variables (a sampling of them shown to the right). These will be used to control run-time operation and/or to optimize the processing.
Crunching the Numbers …
Here we now depart from the simplicity of the earlier gain control example. PnS will call processing functions for every sample if those per-sample functions are in the script, as was the case for the gain control. Otherwise, it expects functions to be defined for processing entire blocks. This is more efficient since fewer calls are involved, but can lead to audio discontinuities if parameters change while the current block of samples is being processed. I went with the block call for both reasons of efficiency and because I needed access to transport information, which cannot be had in the every-sample-call scenario. SAST is a set-it-and-leave-it tool. Its parameters should not have changing values during playback. So, per-block calls are acceptable.
Above is the outer skeleton of the processBlock function. It shows the loop we set up to go through the individual processing stages. Much code is not shown for clarity – what is there is only the outer loop statements and extraction/restoration of the sample values. But below is an extract of code in that loop, annotated with comments that should be sufficient explanation. Note the L/R<->M/S conversion formula. There are a number of ways to do this, but the beauty of this choice is that the same formula is applicable no matter which way the conversion is going. The minus3dB variable is a global variable initialized to 0.707…, which is the multiplication factor equivalent to a 3 dB reduction.
Lastly, let’s look at setting up the processing factors based upon parameter settings. We have a function called before every call to processBlock, but again that only happens if any input parameter values have changed since the last call. Below is the function showing representative sections of the processing, but with much code not shown. Several things are worth noting. First is the testing of the input parameter values. Since these are double (high precision floating point), tests like “myparam == 1” are likely to fail since myparam might contain the value 0.9999999999999 (give or take a few “9”s on the right) – close but the test returns false. So, we use other sure-fire tests conditions to determine “is close to” rather than “is exactly equal”.
Another thing of note is the panorama calculations. In SAST, for panorama adjustments, we treat L and R as independent mono signals. As such, we want to enact a pan law so that the signal doesn’t sound louder when panned to center compared to when panned to either extreme. The code you see accomplishes this.
Lastly, note that we optimize the processing in some cases. We don’t want to go through a bunch of trigonometry calculations if the panorama settings have not changed, for example. So, for some of the more complicated (processor intensive) operations, we only perform that processing if there’s a reason to do so.
The Final Frontier
So, all the code is tested and working. It runs efficiently and this plug-in could be used in a real mix under realistic processing loads. But the default UI is a mess and no user would want to puzzle out the illogical placement of controls. So, it’s time for a skin. A number of files and directories that ship with PnS have the wherewithal for users to create their own skins, but at the moment, this is a rather murky business. I managed to get something that’s 99% of the way there. But I did not understand everything I was doing – some of it was guesswork that fortunately had a happy ending.
The resultant skin does look pretty nice overall, I think.
There are a few nits. The delay type drop-down is missing its down arrow and I’m at a loss as to how to fix it. The delay sample count has a digit to the right of the decimal point, which is just plain wrong. But on the whole I think the layout is quite intuitive. I also wrote a user manual in PDF form that can be accessed with the help button is clicked. All very slick – almost like a professionally produced plug-in!
The bad news is the skin definition itself. Below is just a short extract of that code.
To make this work, I had to copy many of the factory skin files to my project area. This is a problem for several reasons. For one thing, this is Blue Cat’s code. If Blue Cat makes changes to its skin code, which it has every right to do, it could break my plug-in. This actually happened on one occasion. The other problem is that it represents a considerable burden on someone who wanted to distribute their creations to a wider community. Actually, there’s also some very good news on this front as well, which we’ll get to next.
But in the meantime, I think PnS definitely needs to be improved on the skinning front. Blue Cat should (in my opinion, of course) create a simplified set of support files for skins and properly document them. Creating the skin should just have been a matter of declaring rows and columns and plopping the visual elements for parameters inside them. It required far more work than that (a good deal of that being guesswork). With a little thought and effort on the part of Blue Cat, I believe this whole issue of skin complexity could be eliminated entirely.
Things to Come
As I am writing this review, Blue Cat has a beta version of PnS that will be able to create native VSTs (and possibly other formats) by simply exporting the code into a natively-runnable, self-contained module like a DLL (or at least that’s my understanding at the moment). This means that PnS users should be able to create plug-ins that can be distributed to anyone, not just to other PnS owners. This, I think, is huge. We now have a development tool for the latest technologies (64-bit and VST 3 included) that dedicated amateurs can use to build consequential audio software for use in pretty much anyone’s DAW – very exciting indeed!
But the one thing that needs improvement is the support for skins. We are close … so very close to having a tool I could only have dreamed of a year ago.
Anyone interested in looking at the full source of SAST can download it here:
When the export tool is ready, I will also make SAST freely available, provided I can put a stable UI in place skin-wise.
PnS is included in the Blue Cat Crafters Pack bundle which lists for €329 EUR or $399 USD. It can be had individually for €79 EUR or $99 USD. Sales have been known to happen. For more information or to purchase, go here: