Distortions are used to add harmonics to the original sound. In most cases, wave shapers are used for this, I say “most”, because harmonics can be added using, for example, ring modulation. So, the essence of
waveshaping is to convert the signal using a specially selected transfer function. Sounds hard? Not at all. In fact, squaring a signal is also a transfer function. This is the whole theory that we need to know. Let's start the patching!
Where are we going to get the functions from?
We will not reinvent the wheel and take functions from the site
musicdsp.org - this is the dsp community of programmers, where you can find many ready-made algorithms, however, most of them are given in C ++ code.
The first
Let's start with the simplest example:
z = M_PI * a;
s = 1 / sin (z)
b = 1 / a
')
if (x> b)
f (x) = 1
else
f (x) = sin (z * x) * sHere, the variable
a controls the degree of signal distortion, and the incoming signal is represented as the variable
x . Now we implement it in max:

First patch
Here the role of if is performed by the construction of objects
> ~ ,
+ ~ and
[selector ~ 2 ] . The object
> ~ compares the incoming signal (from cycle ~) with the variable
b and outputs unit if the signal value is greater than the variable
b , and zero if less. The unit and zero control the
selector ~ object, which outputs only one of the inlets. Accordingly, when the condition
x> b is satisfied, the output is
1 , otherwise, the output is calculated by the formula
cos (z * x) * s . You can see that we use the cosine function, while in the original formula the sine. The fact is that in Max there is no object for calculating the sine, so you have to replace it with a cosine, there is no difference, because they differ only in the initial phase.
Second
Code:
x = input in [-1..1]
k = 2 * amount / (1-amount);
f (x) = (1 + k) * x / (1 + k * abs (x))The author of the code notes that the
amount value should be in the range of
-1 ... 1 . Of course, it is not necessary to set the
amount equal to
1 , in this case there will be a division by zero. Here we have the input signal -
x .

There is nothing difficult here, having carefully studied the patch and comparing it with the formula, you can easily figure out how everything works.
Third
Code:
f (x, a) = x * (abs (x) + a) / (x ^ 2 + (a-1) * abs (x) + 1)He is in max:

The signal is distorted when the
amount> 1 parameter. I noticed a strange effect (at least on a sine wave) when the
amount is in the range
-1 ... 0 . Try, experiment and there will be happiness! :)
Chebyshev polynomials
Any nonlinear signal transformations create additional harmonics, in most cases an infinite number of them, which causes distortion at high frequencies due to aliasing. Therefore, it is so important to control the added harmonics, fortunately, this is very easily done using Chebyshev polynomials.
They have a very important property: when applying a harmonic signal with a unit amplitude through them (for example, sine waves), we get the same signal, only several times higher. The frequency multiplier will depend on the order of the polynomial.
All polynomials have approximately the following form:
y = f (x) = d0 + d1x + d2x ^ 2 + d3x ^ 3 + ... + dNx ^ N;That is, in fact, a polynomial. The nth element determines the order of the polynomial. In our case, each element generates a certain harmonic, after which they all add up. The form of each member is determined by the following recurrence relation:
Tk + 1 (x) = 2xTk (x) - Tk – 1 (x);In it, each term is determined based on the previous one, everything starts from zero, in our case it is equal to one, and the first one, which is equal to x:
T0 (x) = 1;
T1 (x) = x;Knowing them, you can determine the third member:
T2 (x) = 2x * x - 1 = 2x ^ 2 - 1;And the fourth:
T3 (x) = 2x (2x ^ 2 - 1) - x = 4x ^ 3 - 3x;As you might guess, the second term is the first harmonic, the third is the second and so on.
Another feature of Chebyshev polynomials: when you give a signal through them, with an amplitude less than one, the output is a sound with a lower harmonic intensity. This allows you to create a
drive parameter for the distortion.
So, let's go to practice. It is required to create distortion using Chebyshev polynomials, which will generate eight harmonics, and also allow you to set the amplitude of each component. We will not search for the transfer function for each harmonic; instead, we will create a small subpatch that will generate a new one based on the two previous harmonics.

The previous harmonics feed the previous harmonics, the second - the one before the previous one, and the third - the unmodified incoming signal. As you can see, this subpatch simply implements the recurrent relation
Tk + 1 (x) = 2xTk (x) - Tk – 1 (x) , nothing complicated.
Now, from these blocks, we will create a patch that allows adding up to the eighth harmonic (a high-frequency filter at the end of the chain removes
DC offset ):

This patch allows you to adjust the amplitude of the added harmonics, it can be used to emulate analog devices. So, many tube distortions, in general, add even harmonics, odd ones appear in them only at high amplitude of the incoming signal. Many low-quality amplifiers can create a third harmonic. Solid-state
“Fuzz-Face” distortions distort the signal asymmetrically, they clearly contain the second and third harmonics, as well as some fourth and fifth harmonics.
Electro-Harmonix Big Muff PI distorts symmetrically and produces mostly fifth and seventh harmonics.
Conclusion
Any amplitude transformations entail an unpleasant consequence - aliasing. It appears when the generated harmonics exceed the maximum signal frequency
(Niquist frequency) , which is half the sampling rate. To combat it, oversampling is used - execution of the internal algorithm at the sampling rate increased several times, followed by its decrease when the signal leaves the device. When using Chebyshev polynomials, it is precisely known how many times it is necessary to increase the sampling rate in order to completely remove aliasing - this is determined by the highest generated harmonic. When the algorithm is based on other transfer functions, it will not be possible to completely eliminate it, since usually these algorithms generate an infinite number of harmonics, but oversampling can significantly reduce the effect of aliasing.
The majority of waveform
vst in the work do not use formulas to convert the signal, their role is performed by the table of values, in which the values of the formulas in the range
-1 ... 1 are entered. This allows you to not carry out resource-intensive calculations in real time, and also allows you to "draw" the transfer function.
I think in one of the following articles I will write about how to do oversampling and tabular wave mapping in max, so stay tuned.
PS The archive with patches also contains the patch
all_in_one.maxpat , in which all algorithms are presented with the possibility of choosing the algorithm and the original sound.
The archive itself can be downloaded from the
link .