Author: | Christopher Arndt |
---|---|
Date: | 2018-08-09 |
In this project we are going to build a simple audio effect plug-in without having to write a single line of code! This is possible by using the cookiecutter tool to generate our project from a template. This template provides the code for an effect plug-in based on the DISTRHO Plugin Framework (DPF). The effect is a simple audio level gain (or rather attenuation) control. From a single code base we can compile the plug-in in LV2, VST, and LADSPA format. In a later stage we can adapt the code generated by the template to different kinds of plug-ins.
This guide assumes that you are working on a common Linux distribution of your choice. Unless otherwise noted, install the requirements below from the package repository of your distribution.
Software build tools (GCC, make, etc.)
debian / Ubuntu users install the
build-essential
package.pkg-config
Python 3
debian / Ubuntu users install the
python3-dev
andpython-pip
packages.JACK server, library and development files
debian / Ubuntu users install the
jackd
orjackd2
andlibjack-dev
orlibjack-jackd2-dev
package.cookiecutter
Do not install the debian / Ubuntu package (it is outdated), install with:
pip install --user cookiecutter
and then add
$HOME/.local/bin
to thePATH
environment variable in~/.bashrc
(you need to log out and in again to make the change effective in your whole desktop session).git
jalv
lilv
resp.lilv-utils
or the appropriate package to install thelv2ls
andlv2info
programsAn LV2 host of your choice, e.g. Carla, Ardour, Ingen, etc.
An internet connection
There are a few things we need to take care of, before we can generate our
project. The commands given below are shell command lines, which you type or
copy & paste into a terminal window (without the leading $
prompt). So
open a new terminal window now and use that same window for all subsequent
commands (unless told otherwise).
If you haven't done so already in the past, configure your Git client (you may of course substitute your real name and email address):
$ git config --global user.name "John Doe" $ git config --global user.email [email protected]
This is needed because when you generate the project, it will initialize a Git repository and make an initial commit, for which Git needs to know what to use as the author of the commit. If you don't want to, you don't need to use Git after that and neither do you need to have a GitHub account, but the project will be ready be pushed to GitHub, if you so desire.
Make or choose a directory where the project will be generated, e.g.:
$ mkdir -p ~/projects; cd ~/projects
(Optional) This step is not needed but makes things easier if you want to start over and run cookiecutter again to re-generate the project or use it to make other projects.
Create a file named
~/.cookiecutterrc
in your home directory and put the following in it:default_context: full_name: "Joe Doe" domain: "mydomain.com" email: "[email protected]" github_username: "JoeDoe"
Again, substitute your real personal data, or something you made up.
Still in the same terminal window, in your project directory, run cookiecutter to generate the new project:
$ cookiecutter https://github.com/SpotlightKid/cookiecutter-dpf-effect
For this step you will need an internet connection, at least for the first time you run this, since this will download the project template from the given URL and then prompt you for some values, which are used when generating the project. If you just press the return key at any question, the default value in square brackets will be used. Here's an example run:
project_name [Simple Gain]: plugin_description [A simple audio volume gain plugin]: full_name [Joe Doe]: domain [example.com]: mydomain.com github_username [joe.doe]: JoeDoe email [[email protected]]: [email protected] plugin_brand [mydomain.com]: plugin_name [SimpleGain]: repo_name [simplegain]: plugin_uri [http://mydomain.com/plugins/simplegain]: project_license [MIT]: version [0.1.0]: year [2018]: Running post-project-generation hook... Initializing new Git repository: Initialized empty Git repository in /home/joe/projects/simplegain/.git/ Adding Git submodule for DPF library: Checking out submodules: Cloning into '/home/joe/projects/simplegain/dpf'... remote: Counting objects: 7168, done. remote: Total 7168 (delta 0), reused 0 (delta 0), pack-reused 7167 Receiving objects: 100% (7168/7168), 12.13 MiB | 1.30 MiB/s, done. Resolving deltas: 100% (6078/6078), done. Making initial Git commit: [master (root-commit) dbdfbb6] Initial commit 12 files changed, 699 insertions(+) create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 Makefile.mk create mode 100644 README.md create mode 160000 dpf create mode 100644 plugins/Makefile.mk create mode 100644 plugins/SimpleGain/DistrhoPluginInfo.h create mode 100644 plugins/SimpleGain/Makefile create mode 100644 plugins/SimpleGain/PluginSimpleGain.cpp create mode 100644 plugins/SimpleGain/PluginSimpleGain.hpp Your DPF audio effect plugin project is now ready! To compile it, change into the 'simplegain' directory and type 'make'. The plugin binaries and LV2 bundle will be placed in the 'bin' subdirectory. Have fun!
Just follow the instructions, which were printed to the console at the end of the previous step:
$ cd simplegain $ make
If you have all the required software development tools and libraries, this will compile the
plug-in in LV2, LADSPA, DSSI and VST2 format. The first time you run make
, compilation will
take a couple of seconds, because the DPF library sources have to be compiled. The next time you
run make
(without running make clean
in between), these will not have to be compiled again,
and compilation should be much faster.
The plug-in binaries will be placed in a bin
sub-directory of your project's repository root.
For each the LADSPA, DSSI and VST2 format this will produce a shared library file (i.e. with
.so
extension) and the filename will consists of the plug-in's name in lower case and the
format, e.g. simplegain-vst.so
. For the LV2 format a bundle directory will be created
(simplegain.lv2
), which also contains a shared library, a manifest.ttl
file and further
.ttl
file.
If you get any compiler warnings during the compilation, don't worry, these are probably due to some occurences of deprecated C++ syntax in the DPF library sources.
If you get any errors, please double-check that you have all the development tools and libraries
installed, are in the correct directory, and that you haven't accidentally entered any weird
data when creating the project. When trying to compile again, it's best to issue a make clean
first, to make sure everything is compiled again anew.
After the compilation, check that the bin
directory contains three .so
files and an LV2
bundle directory with current timestamps:
$ ls -l bin total 92 drwxr-xr-x 2 joe users 4096 09.08.2018 18:26 simplegain.lv2/ -rwxr-xr-x 1 joe users 27056 09.08.2018 18:26 simplegain-dssi.so* -rwxr-xr-x 1 joe users 26960 09.08.2018 18:26 simplegain-ladspa.so* -rwxr-xr-x 1 joe users 30904 09.08.2018 18:26 simplegain-vst.so*
To make the LV2 plug-in known to host programs, we need to put it into either /usr/lib/lv2
or a
.lv2
directory in our home directory. Since we don't want to mess with the system-installed
files, we will install the bundle into the latter, creating it first, if it doesn't exist yet.
Instead of simply copying the bundle directory, we will create a symbolic link to it, so when we
compile the plug-in again, we don't have to copy it again (or scratch our head when the changes we
did do not seem to take effect):
$ mkdir -p ~/.lv2 # Notice the leading dot in the directory name! $ ln -s "$(pwd)/bin/simplegain.lv2" ~/.lv2
Let's check whether our plug-in can be found with lv2ls
(make sure that the LV2_PATH
environment variable is unset or includes $HOME/.lv2
):
$ lv2ls | grep simplegain http://mydomain.com/plugins/simplegain
This should print out the LV2 URI (i.e. its unique name) of the plug-in. With this URI we can get
some more information about the plug-in with lv2info
:
$ lv2info http://example.com/plugins/simplegain http://mydomain.com/plugins/simplegain Name: SimpleGain Class: Plugin Author: mydomain.com Author Homepage: http://mydomain.com/plugins/simplegain Has latency: no Bundle: file:///home/chris/.lv2/simplegain.lv2/ Binary: file:///home/chris/.lv2/simplegain.lv2/simplegain_dsp.so Data URIs: file:///home/chris/.lv2/simplegain.lv2/manifest.ttl file:///home/chris/.lv2/simplegain.lv2/simplegain_dsp.ttl Required Features: http://lv2plug.in/ns/ext/urid#map http://lv2plug.in/ns/ext/options#options Optional Features: http://lv2plug.in/ns/ext/buf-size#boundedBlockLength http://lv2plug.in/ns/lv2core#hardRTCapable Extension Data: http://lv2plug.in/ns/ext/state#interface http://kxstudio.sf.net/ns/lv2ext/programs#Interface Presets: Default Port 0: Type: http://lv2plug.in/ns/lv2core#AudioPort http://lv2plug.in/ns/lv2core#InputPort Symbol: lv2_audio_in_1 Name: Audio Input 1 Port 1: Type: http://lv2plug.in/ns/lv2core#AudioPort http://lv2plug.in/ns/lv2core#InputPort Symbol: lv2_audio_in_2 Name: Audio Input 2 Port 2: Type: http://lv2plug.in/ns/lv2core#AudioPort http://lv2plug.in/ns/lv2core#OutputPort Symbol: lv2_audio_out_1 Name: Audio Output 1 Port 3: Type: http://lv2plug.in/ns/lv2core#AudioPort http://lv2plug.in/ns/lv2core#OutputPort Symbol: lv2_audio_out_2 Name: Audio Output 2 Port 4: Type: http://lv2plug.in/ns/lv2core#ControlPort http://lv2plug.in/ns/lv2core#InputPort Symbol: volume Name: Volume Minimum: 0.000000 Maximum: 1.000000 Default: 0.100000 Properties: http://lv2plug.in/ns/ext/port-props#logarithmic
Let's try to load the plug-in with the jalv
LV2 host. Make sure you have started the JACK
audio server (e.g. with qjackctl
) and run:
$ jalv.gtk http://mydomain.com/plugins/simplegain
This should open a small window with a menu bar and a numeric spin box and a slider for the volume control of our plug-in.
Open a JACK patchbay program (e.g. qjackctl
, patchage
or Catia
) to see the JACK client
for the plug-in created by jalv
. It should have two audio inputs and outputs and one event
(MIDI) input.
Now route some audio into the audio inputs of the plug-in and connect its audio outputs to the
system:playback_1
and system:playback_2
inputs of your soundcard. Then change the volume
parameter via the slider. The audio level of the signal should change accordingly.
That's all for now. You can test your plugin in different hosts, e.g. Carla or Ardour and try
automating the volume parameter via OSC, MIDI or a DAW track automation. Then have a look at the
source code of your plug-in in the plugins/SimpleGain
directory. We will discuss the plug-ins
C++ classes and its various methods next time.