This is an example plugin using Dplug with a Faust backend. It is a stereo reverb plugin using the Freeverb demo from the Faust library.
Install the ldc2 D compiler.
Clone Dplug
git clone https://github.com/AuburnSounds/Dplug.git
Build dplug-build
# From Dplug repository
cd tools/dplug-build
dub --compiler ldc2
Add dplug-build
to your path variable.
Clone this repo.
git clone https://github.com/ctrecordings/dplug-faust-example.git
Run dplug-build
dplug-build -c LV2 --compiler ldc2
You should now see the built LV2 plugin in builds/
You can copy this plugin to the folder on you PC that holds LV2 plugins.
If you are licensed to build VST2 or VST3 plug-ins you may also target those formats. See Dplug's documentation for more info on this.
The faust DSP code is written in dsp/freeverb.dsp
. Currently only one faust module can be supported in a single project.
In dub.json
we specify a pre-build command to compile the faust code to Dplug format
"preBuildCommands": [
"faust dsp/freeverb.dsp -lang dlang -a dplug.d -cn Freeverb -vec -o src/freeverb.d"
]
The faust architecture file for Dplug creates a complete gui-less Dplug plugin which has it's own entrypoints. We need to override these entrypoints so there is a version identifier provided to do this.
In dub.json
we add the faustoverride
version.
"versions": ["futureMouseDrag", "faustoverride"],
Now we are able to import and inherit from the generated Dplug client.
final class ExampleClient : FaustClient
As well as define our own entry points
mixin(pluginEntryPoints!ExampleClient);
When we specify our params enum, it is important that they are ordered to match what faust generates.
We can look at the buildUserInterface
method of our generated freeverb.d
to see the order.
Some code removed for conciseness.
void buildUserInterface(UI* uiInterface) nothrow @nogc {
...
uiInterface.addVerticalSlider("Damp", &fVslider0, cast(FAUSTFLOAT)0.5, cast(FAUSTFLOAT)0.0, cast(FAUSTFLOAT)1.0, cast(FAUSTFLOAT)0.025);
...
uiInterface.addVerticalSlider("RoomSize", &fVslider2, cast(FAUSTFLOAT)0.5, cast(FAUSTFLOAT)0.0, cast(FAUSTFLOAT)1.0, cast(FAUSTFLOAT)0.025);
...
uiInterface.addVerticalSlider("Stereo Spread", &fVslider3, cast(FAUSTFLOAT)0.5, cast(FAUSTFLOAT)0.0, cast(FAUSTFLOAT)1.0, cast(FAUSTFLOAT)0.01);
...
uiInterface.addVerticalSlider("Wet", &fVslider1, cast(FAUSTFLOAT)0.3333, cast(FAUSTFLOAT)0.0, cast(FAUSTFLOAT)1.0, cast(FAUSTFLOAT)0.025);
...
}
Alternatively we can add metadata to our controls by naming them like [paramIndex] Control Name
. For example: [3] Wet
. Although this example does not leverage this since it's using the freeverb demo.
So to match this we need to specify our params enum as follows:
enum : int
{
paramDamp,
paramRoomSize,
paramStereoSpread,
paramWet
}
The last step is to override processAudio
so we can update our UI if needed.
override void processAudio(const(float*)[] inputs, float*[]outputs, int frames, TimeInfo info)
{
assert(frames <= 512);
super.processAudio(inputs, outputs, frames, info);
if (ExampleGUI gui = cast(ExampleGUI) graphicsAcquire())
{
// update gui here.
graphicsRelease();
}
}