![](http://habrastorage.org/getpro/habr/avatars/562/a41/01f/562a4101ff8cd82afb56388cfed1596d.png)
Creating Audio Plugins, Part 4
- Tutorial
All posts in the series:
Part 1. Introduction and configuration
Part 2. Learning the code
Part 3. VST and AU
Part 4. Digital distortion
Part 5. Presets and GUI
Part 6. Signal synthesis
Part 7. Receiving MIDI messages
Part 8. Virtual keyboard
Part 9 Envelopes
Part 10. Refinement of the GUI
Part 11. Filter
Part 12. Low-frequency oscillator
Part 13. Redesign
Part 14. Polyphony 1
Part 15. Polyphony 2
Part 16. Antialiasing
It's time to start writing our first plugin. It will be a dirty digital distortion. More specifically, the plugin will simply trim the peaks in the amplitude of the audio signal.
We will limit the signal values that exceed a certain threshold so that they do not go beyond it:
![](https://habrastorage.org/getpro/habr/post_images/e04/5ea/3e1/e045ea3e1b726f147dfc0e0c856ebb5d.jpg)
By saying “exceeding” I mean “exceeding a certain positive threshold or falling below a certain negative threshold”.
Using the good old script,
Open the terminal, in it go to the IPlugExamples directory and enter this:
If you have not read the previous posts, the results from them can be downloaded from here . If you are doing this on a Mac, make sure that no other projects are open in Xcode. In the freshly created DigitalDistortion folderlies the DigitalDistortion.xcodeproj file . Open it, check that the APP target assembly starts without errors. Edit the schemas as I described earlier so that REAPER runs for VST and AU. Do not forget that Arguments Passed On Launch should point to the desired .rpp file.
Now, when starting REAPER, it does not load MyFirstPlugin , but DigitalDistortion . Wonders. This is because project files in REAPER are simply structured text files in which the script
Let's first rename the parameter
Now, in DigitalDistortion.cpp, replace (Cmd + Alt + F) all that you find
Now let's write the digital signal processing directly:
If the error gets out about what is
If this does not solve the problem, add this instead of the previous line:
And replace
Despite the fact that the value is
An interesting point with the conditional operator
Launch the plugin in REAPER and drive it to the test sound. When the knob is turned all the way to the right, a clear sound will be heard. The more the knob is turned counterclockwise, the more distorted the signal becomes.
As the distortion increases, the signal becomes quieter - this is because we lower the threshold value closer and closer to zero, and, accordingly, cut off the amplitude to increasingly quieter values. To compensate for this, we divide the input value by a threshold:
A little higher, we set the minimum value for the parameter equal
Now, if you run the plugin again, the amplitude will remain at the same level. But the volume will seem higher: the cutoff of the amplitude brings our sine wave closer in shape closer to the meander , which has a larger rms value .
So far, I intentionally try not to get into the jungle of digital signal processing. In my opinion, a good plugin is not just signal processing algorithms. This is a mixture that includes
So before diving into the sound processing algorithms in the next posts we add presets and a more pleasant interface.
Original article:
martin-finke.de/blog/articles/audio-plugins-005-digital-distortion
Part 1. Introduction and configuration
Part 2. Learning the code
Part 3. VST and AU
Part 4. Digital distortion
Part 5. Presets and GUI
Part 6. Signal synthesis
Part 7. Receiving MIDI messages
Part 8. Virtual keyboard
Part 9 Envelopes
Part 10. Refinement of the GUI
Part 11. Filter
Part 12. Low-frequency oscillator
Part 13. Redesign
Part 14. Polyphony 1
Part 15. Polyphony 2
Part 16. Antialiasing
It's time to start writing our first plugin. It will be a dirty digital distortion. More specifically, the plugin will simply trim the peaks in the amplitude of the audio signal.
Digital distortion
We will limit the signal values that exceed a certain threshold so that they do not go beyond it:
![](https://habrastorage.org/getpro/habr/post_images/e04/5ea/3e1/e045ea3e1b726f147dfc0e0c856ebb5d.jpg)
By saying “exceeding” I mean “exceeding a certain positive threshold or falling below a certain negative threshold”.
Using the good old script,
duplicate
you can copy any project, giving it a new name. And we do not have to make all the changes that I described earlier for each new project. Open the terminal, in it go to the IPlugExamples directory and enter this:
./duplicate.py MyFirstPlugin/ DigitalDistortion YourName
If you have not read the previous posts, the results from them can be downloaded from here . If you are doing this on a Mac, make sure that no other projects are open in Xcode. In the freshly created DigitalDistortion folderlies the DigitalDistortion.xcodeproj file . Open it, check that the APP target assembly starts without errors. Edit the schemas as I described earlier so that REAPER runs for VST and AU. Do not forget that Arguments Passed On Launch should point to the desired .rpp file.
Now, when starting REAPER, it does not load MyFirstPlugin , but DigitalDistortion . Wonders. This is because project files in REAPER are simply structured text files in which the script
duplicate
replaced all “MyFirstPlugin” with “DigitalDistortion”. Let's first rename the parameter
mGain
to mThreshold
. Open DigitalDistortion.h and renameprivate
variable:private:
double mThreshold;
Now, in DigitalDistortion.cpp, replace (Cmd + Alt + F) all that you find
Gain
with Threshold
. When assembling, no errors should pop up. In the constructor, in the parameter initialization line, specify 0.01
both the minimum value and the 100.0
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)
{
// Mutex is already locked for us.
int const channelCount = 2;
for (int i = 0; i < channelCount; i++) {
double* input = inputs[i];
double* output = outputs[i];
for (int s = 0; s < nFrames; ++s, ++input, ++output) {
if(*input >= 0) {
// Make sure positive values can't go above the threshold:
*output = fmin(*input, mThreshold);
} else {
// Make sure negative values can't go below the threshold:
*output = fmax(*input, -mThreshold);
}
}
}
}
If the error gets out about what is
fmin
and fmax
is not identified, try to rename them simply min
and max
. If this doesn’t help, add the following to the DigitalDistortion.cpp header :#include
If this does not solve the problem, add this instead of the previous line:
#include
And replace
fmin
with std::min
, and fmax
with std::max
. Despite the fact that the value is
channelCount
hard-coded, we removed some redundancy by using an external loop for
to iterate over the channels. That is, first the plugin processes several samples from one channel, and then does the same with the samples of the second. An interesting point with the conditional operator
if
. For positive values of the amplitude, we choose the smaller of the two: either the input value or the threshold. For negative ones, on the contrary, we choose the larger one: either *input
, or a negative threshold value. In short, we always choose the value that is closer to zero.Launch the plugin in REAPER and drive it to the test sound. When the knob is turned all the way to the right, a clear sound will be heard. The more the knob is turned counterclockwise, the more distorted the signal becomes.
As the distortion increases, the signal becomes quieter - this is because we lower the threshold value closer and closer to zero, and, accordingly, cut off the amplitude to increasingly quieter values. To compensate for this, we divide the input value by a threshold:
if(*input >= 0) {
*output = fmin(*input, mThreshold);
} else {
*output = fmax(*input, -mThreshold);
}
*output /= mThreshold;
A little higher, we set the minimum value for the parameter equal
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: the cutoff of the amplitude brings our sine wave closer in shape closer to the meander , which has a larger rms value .
So far, I intentionally try not to get into the jungle of digital signal processing. In my opinion, a good plugin is not just signal processing algorithms. This is a mixture that includes
- reliable host compatibility (settings, stable operation)
- good sound (here is pure digital processing)
- intuitive user interface
- beautiful appearance
So before diving into the sound processing algorithms in the next posts we add presets and a more pleasant interface.
Original article:
martin-finke.de/blog/articles/audio-plugins-005-digital-distortion