All posts series:
Part 1. Introduction and setupPart 2. Learning CodePart 3. VST and AUPart 4. Digital DistortionPart 5. Presets and GUIPart 6. Signal synthesisPart 7. Receive MIDI MessagesPart 8. Virtual KeyboardPart 9. EnvelopesPart 10. Refinement GUIPart 11. FilterPart 12. Low-frequency oscillatorPart 13. RedesignPart 14. Polyphony 1Part 15. Polyphony 2Part 16. Antialiasing
It's time to start writing our first plugin. This will be a dirty digital distortion. More precisely, the plugin will simply
cut off the peaks of the amplitude of the audio signal.
Digital distortion
The signal values ​​exceeding a certain threshold, we limit so that they do not go beyond it:
')

By saying “exceeding”, I mean “exceeding a certain positive threshold or falling below a certain negative threshold”.
With the help of the good old script
duplicate
you can copy any project by giving it a new name. And for each new project we don’t have to make all the changes that I described before.
Open a terminal, go to the
IPlugExamples directory in
it and enter this:
./duplicate.py MyFirstPlugin/ DigitalDistortion YourName
If you have not read the previous posts, the results of them can be downloaded
from here . If you do this on a Mac, make sure that no other project is open in Xcode. In the newly created
DigitalDistortion folder there is a
DigitalDistortion.xcodeproj file. Open it, check that the APP targt build runs without errors. Edit the schemas as I described earlier so that REAPER runs for VST and AU. Don't forget that
Arguments Passed On Launch should point to the correct
.rpp file.
Now when REAPER starts, it loads not
DigitalDistortion , but
MyFirstPlugin . Miracles. This is because the project files in REAPER are simply structured text files in which the
duplicate
script replaces all “MyFirstPlugin” with “DigitalDistortion”.
Let's first rename the
mGain
parameter to
mThreshold
. Open
DigitalDistortion.h and rename the
private
variable:
private: double mThreshold;
Now in
DigitalDistortion.cpp replace (Cmd + Alt + F) all occurring
Gain
with
Threshold
. No errors should pop up during assembly. In the constructor, in the parameter initialization string, specify
0.01
as the minimum value, and
100.0
as the default value:
GetParam(kThreshold)->InitDouble("Threshold", 100.0, 0.01, 100.0, 0.01, "%");
Now let's write the digital signal processing directly:
void DigitalDistortion::ProcessDoubleReplacing( double** inputs, double** outputs, int nFrames) {
If you get an error saying that
fmin
and
fmax
not defined, try renaming them simply to
min
and
max
. If this did not help, add the following to the
DigitalDistortion.cpp header :
#include <math.h>
If this does not solve the problem, add this instead of the previous line:
#include <algorithm>
And replace
fmin
with
std::min
, and
fmax
with
std::max
.
Despite the fact that
channelCount
hard-coded, we removed some redundancy by using an external for loop to iterate over the channels. That is, at first the plugin processes several samples from one channel, and then does the same with the samples of the second one.
An interesting point with the conditional
if
. For positive amplitude values, we choose the smaller of the two: either the input value or the threshold value. For negative ones, on the contrary, choose a larger one: either
*input
or a negative threshold value. In short, we always choose the value that is closer to zero.
Run the plugin in REAPER and drive it on the test sound. When the knob is turned all the way to the right, a clear sound will be heard. The more counterclockwise the knob is turned, the more distorted the signal becomes.
As the signal is distorted, it becomes quieter - this is because we lower the threshold value closer and closer to zero, and, accordingly, we cut off the amplitude to more and more silent values. To compensate for this, divide the input value by the threshold:
if(*input >= 0) { *output = fmin(*input, mThreshold); } else { *output = fmax(*input, -mThreshold); } *output /= mThreshold;
Slightly above, we set the minimum value for the parameter to
0.01
. Thus, we will never divide by zero, even if we turn the knob all the way to the left.
Now, if you run the plugin again, the amplitude will remain at the same level. But the volume will seem higher: clipping the amplitude brings our sine wave closer in shape closer to the
meander , which has a larger
rms value .
So far, I deliberately try not to climb into the wilds of digital signal processing. In my opinion, a good plugin is not just a signal processing algorithm. It is a mixture that includes
- reliable host compatibility (settings, stable operation)
- good sound (here is pure digital processing)
- clear user interface
- beautiful appearance
So before diving into the sound processing algorithms in the following posts, we will add presets and a more pleasant interface.
Original article:
martin-finke.de/blog/articles/audio-plugins-005-digital-distortion